Implement complete Augmentation & Item Leveling System

Major Features Added:
- Complete Augmentation System with 17 augmentation types
- Item Leveling System with XP progression
- Player Level System with XP tracking
- Auto-Enhancement for all items (Level 1, no augmentations)
- Demo system with 10 pre-configured items
- Beautiful lore display with slot visualization
- Level-based slot unlocking system
- Legacy system cleanup and deactivation

New Commands:
- /augment (create, add, remove, info, levelup)
- /demo (1-10, all, random, list)
- /playerlevel (info, add, set)
- /convert (hand, all)

Technical Implementation:
- EnhancedItem class with NBT persistence
- AugmentationType enum with 17 types
- ItemLevelingSystem with XP curves
- PlayerLevelManager with progression
- Auto-enhancement listeners for all item sources
- Item leveling through usage (mining, combat, crafting)
- Rarity-based max levels and slot limits
This commit is contained in:
SimolZimol
2025-10-12 00:17:55 +02:00
parent 43b4ab60e4
commit 6517913eeb
23 changed files with 2517 additions and 37 deletions

View File

@@ -9,6 +9,22 @@ commands:
testsmithchest:
description: Spawns a weaponsmith chest for testing
usage: /testsmithchest
augment:
description: Manage item augmentations
usage: /augment <create|add|remove|info|levelup>
aliases: [aug, enhance]
playerlevel:
description: View and manage player levels
usage: /playerlevel [player] [info|add|set] [amount]
aliases: [plevel, level]
demo:
description: Get demo items with pre-configured augmentations
usage: /demo [1-10|all|random|list]
aliases: [demoitems, examples]
convert:
description: Convert regular items to Enhanced Items
usage: /convert [hand|all|help]
aliases: [enhance, upgrade]
permissions:
levelcraft.admin:

View File

@@ -13,16 +13,35 @@ public class LevelCraft extends JavaPlugin {
public void onEnable() {
instance = this;
getLogger().info("LevelCraft enabled!");
com.simolzimol.levelcraft.item.ItemUtil.init(this);
// Initialize core systems
// com.simolzimol.levelcraft.item.ItemUtil.init(this); // DISABLED: Legacy system replaced by augmentations
com.simolzimol.levelcraft.augmentation.EnhancedItem.init(this);
com.simolzimol.levelcraft.player.PlayerLevelManager.init(this);
// Register event listeners
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.CraftListener(), this);
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.LootListener(this), this);
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.VillagerTradeListener(), this);
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.MobDropListener(), this);
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.MobSpawnListener(), this);
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.CustomStatsListener(), this);
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.PlayerLevelListener(), this);
// NEW: Auto-Enhancement System - converts all items to Enhanced Items
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.AutoEnhancementListener(), this);
// NEW: Item Leveling System - items gain XP from usage
getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.ItemLevelingListener(), this);
// Register commands
getCommand("testsmithchest").setExecutor(new com.simolzimol.levelcraft.command.TestSmithChestCommand());
getCommand("augment").setExecutor(new com.simolzimol.levelcraft.command.AugmentCommand());
getCommand("playerlevel").setExecutor(new com.simolzimol.levelcraft.command.PlayerLevelCommand());
getCommand("demo").setExecutor(new com.simolzimol.levelcraft.command.DemoCommand());
getCommand("convert").setExecutor(new com.simolzimol.levelcraft.command.ConvertCommand());
// Start ActionBar task for all players
// Start background tasks
com.simolzimol.levelcraft.system.PlayerStatsManager.startActionBarTask(this);
com.simolzimol.levelcraft.system.PlayerStatsManager.startRegenTask(this);
}

View File

@@ -0,0 +1,127 @@
package com.simolzimol.levelcraft.augmentation;
import java.util.Map;
import java.util.HashMap;
public class Augmentation {
private final AugmentationType type;
private final int level;
private final Map<String, Double> statModifiers;
public Augmentation(AugmentationType type, int level) {
this.type = type;
this.level = Math.min(level, type.getMaxLevel());
this.statModifiers = calculateStatModifiers();
}
private Map<String, Double> calculateStatModifiers() {
Map<String, Double> modifiers = new HashMap<>();
switch (type) {
case SHARPNESS -> modifiers.put("attack_damage", (double) level);
case PROTECTION -> modifiers.put("damage_reduction", level * 2.0); // 2% per level
case FIRE_ASPECT -> modifiers.put("fire_duration", (double) level);
case KNOCKBACK -> modifiers.put("knockback", level * 0.5);
case FORTUNE -> modifiers.put("drop_multiplier", 1.0 + (level * 0.2)); // 20% per level
case EFFICIENCY -> modifiers.put("mining_speed", level * 10.0); // 10% per level
case UNBREAKING -> modifiers.put("durability_save", level * 20.0); // 20% per level
case MENDING -> modifiers.put("xp_repair", 1.0);
case VAMPIRIC -> modifiers.put("lifesteal", level * 5.0); // 5% per level
case CRITICAL_STRIKE -> modifiers.put("crit_chance", level * 2.0); // 2% per level
case CHAIN_LIGHTNING -> modifiers.put("chain_range", level * 3.0); // 3 block range per level
case THORNS -> modifiers.put("reflect_damage", level * 15.0); // 15% damage reflection per level
case RESISTANCE -> modifiers.put("all_damage_reduction", level * 3.0); // 3% per level
case REGENERATION -> modifiers.put("health_regen", level * 0.1); // 0.1 HP/sec per level
case SPEED -> modifiers.put("movement_speed", level * 10.0); // 10% per level
case SILK_TOUCH -> modifiers.put("silk_touch", 1.0);
case SMITE -> modifiers.put("undead_damage", level * 2.0); // +2 damage vs undead per level
case BANE_OF_ARTHROPODS -> modifiers.put("arthropod_damage", level * 2.0); // +2 damage vs arthropods per level
}
return modifiers;
}
public AugmentationType getType() {
return type;
}
public int getLevel() {
return level;
}
public Map<String, Double> getStatModifiers() {
return new HashMap<>(statModifiers);
}
public String getDisplayName() {
return type.getFormattedName(level);
}
public String getDescription() {
StringBuilder desc = new StringBuilder(type.getDescription());
// Add specific values to description
switch (type) {
case SHARPNESS -> desc.append(" (+").append(level).append(" damage)");
case PROTECTION -> desc.append(" (-").append(level * 2).append("% damage)");
case FIRE_ASPECT -> desc.append(" (").append(level).append("s burn)");
case KNOCKBACK -> desc.append(" (+").append(level * 50).append("% knockback)");
case FORTUNE -> desc.append(" (+").append((int)(level * 20)).append("% drops)");
case EFFICIENCY -> desc.append(" (+").append(level * 10).append("% speed)");
case UNBREAKING -> desc.append(" (+").append(level * 20).append("% durability)");
case MENDING -> desc.append(" (XP repairs item)");
case VAMPIRIC -> desc.append(" (").append(level * 5).append("% lifesteal)");
case CRITICAL_STRIKE -> desc.append(" (").append(level * 2).append("% chance)");
case CHAIN_LIGHTNING -> desc.append(" (").append(level * 3).append(" block range)");
case THORNS -> desc.append(" (").append(level * 15).append("% reflect)");
case RESISTANCE -> desc.append(" (-").append(level * 3).append("% all damage)");
case REGENERATION -> desc.append(" (+").append(level * 0.1).append(" HP/sec)");
case SPEED -> desc.append(" (+").append(level * 10).append("% speed)");
case SILK_TOUCH -> desc.append(" (Harvests blocks intact)");
case SMITE -> desc.append(" (+").append(level * 2).append(" vs undead)");
case BANE_OF_ARTHROPODS -> desc.append(" (+").append(level * 2).append(" vs arthropods)");
}
return desc.toString();
}
// Serialization for NBT storage
public String serialize() {
return type.name() + ":" + level;
}
public static Augmentation deserialize(String data) {
String[] parts = data.split(":");
if (parts.length != 2) return null;
try {
AugmentationType type = AugmentationType.valueOf(parts[0]);
int level = Integer.parseInt(parts[1]);
return new Augmentation(type, level);
} catch (Exception e) {
return null;
}
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Augmentation that = (Augmentation) obj;
return level == that.level && type == that.type;
}
@Override
public int hashCode() {
return type.hashCode() * 31 + level;
}
@Override
public String toString() {
return getDisplayName();
}
}

View File

@@ -0,0 +1,104 @@
package com.simolzimol.levelcraft.augmentation;
public class AugmentationSlot {
private final int slotId;
private Augmentation augmentation;
private boolean locked;
public AugmentationSlot(int slotId) {
this.slotId = slotId;
this.augmentation = null;
this.locked = false;
}
public AugmentationSlot(int slotId, boolean locked) {
this.slotId = slotId;
this.augmentation = null;
this.locked = locked;
}
public int getSlotId() {
return slotId;
}
public Augmentation getAugmentation() {
return augmentation;
}
public void setAugmentation(Augmentation augmentation) {
if (!locked) {
this.augmentation = augmentation;
}
}
public void removeAugmentation() {
if (!locked) {
this.augmentation = null;
}
}
public boolean isEmpty() {
return augmentation == null;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public void unlock() {
this.locked = false;
}
public String getDisplayName() {
if (locked) {
return "§8[LOCKED]";
}
if (isEmpty()) {
return "§7[EMPTY]";
}
return augmentation.getDisplayName();
}
// Serialization for NBT storage
public String serialize() {
StringBuilder sb = new StringBuilder();
sb.append(slotId).append(";");
sb.append(locked).append(";");
if (augmentation != null) {
sb.append(augmentation.serialize());
} else {
sb.append("EMPTY");
}
return sb.toString();
}
public static AugmentationSlot deserialize(String data) {
String[] parts = data.split(";");
if (parts.length != 3) return null;
try {
int slotId = Integer.parseInt(parts[0]);
boolean locked = Boolean.parseBoolean(parts[1]);
AugmentationSlot slot = new AugmentationSlot(slotId, locked);
if (!parts[2].equals("EMPTY")) {
Augmentation aug = Augmentation.deserialize(parts[2]);
slot.setAugmentation(aug);
}
return slot;
} catch (Exception e) {
return null;
}
}
@Override
public String toString() {
return "Slot " + slotId + ": " + getDisplayName();
}
}

View File

@@ -0,0 +1,100 @@
package com.simolzimol.levelcraft.augmentation;
public enum AugmentationType {
// Combat Augmentations
SHARPNESS("Sharpness", "§c", "Increases attack damage", 10),
PROTECTION("Protection", "§9", "Reduces incoming damage", 5),
FIRE_ASPECT("Fire Aspect", "§6", "Sets enemies on fire", 3),
KNOCKBACK("Knockback", "§7", "Increases knockback", 2),
// Utility Augmentations
FORTUNE("Fortune", "§e", "Increases drop rates", 5),
EFFICIENCY("Efficiency", "§a", "Increases mining speed", 10),
UNBREAKING("Unbreaking", "§b", "Reduces durability loss", 5),
MENDING("Mending", "§d", "Repairs item with XP", 1),
// Special Augmentations
VAMPIRIC("Vampiric", "§4", "Heals on damage dealt", 3),
CRITICAL_STRIKE("Critical Strike", "§c", "Chance for critical hits", 5),
CHAIN_LIGHTNING("Chain Lightning", "§e", "Damages nearby enemies", 2),
THORNS("Thorns", "§8", "Reflects damage to attackers", 3),
// Defensive Augmentations
RESISTANCE("Resistance", "§5", "Reduces all damage types", 3),
REGENERATION("Regeneration", "§c", "Slowly regenerates health", 3),
SPEED("Speed", "§f", "Increases movement speed", 2),
// Tool Augmentations
SILK_TOUCH("Silk Touch", "§f", "Harvests blocks intact", 1),
SMITE("Smite", "§e", "Extra damage vs undead", 5),
BANE_OF_ARTHROPODS("Bane of Arthropods", "§2", "Extra damage vs arthropods", 5);
private final String displayName;
private final String colorCode;
private final String description;
private final int maxLevel;
AugmentationType(String displayName, String colorCode, String description, int maxLevel) {
this.displayName = displayName;
this.colorCode = colorCode;
this.description = description;
this.maxLevel = maxLevel;
}
public String getDisplayName() {
return displayName;
}
public String getColorCode() {
return colorCode;
}
public String getDescription() {
return description;
}
public int getMaxLevel() {
return maxLevel;
}
public String getFormattedName(int level) {
return colorCode + displayName + " " + toRoman(level);
}
private String toRoman(int number) {
if (number <= 0) return "";
String[] romanNumerals = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"};
return number <= 10 ? romanNumerals[number] : String.valueOf(number);
}
// Check if augmentation is applicable to item type
public boolean isApplicableTo(org.bukkit.Material material) {
return switch (this) {
case SHARPNESS, FIRE_ASPECT, KNOCKBACK, SMITE, BANE_OF_ARTHROPODS -> isWeapon(material);
case PROTECTION, THORNS, RESISTANCE -> isArmor(material);
case FORTUNE, EFFICIENCY, SILK_TOUCH -> isTool(material);
case UNBREAKING, MENDING -> material.getMaxDurability() > 0;
case VAMPIRIC, CRITICAL_STRIKE, CHAIN_LIGHTNING -> isWeapon(material);
case REGENERATION, SPEED -> isArmor(material);
default -> true; // Universal augmentations
};
}
private boolean isWeapon(org.bukkit.Material material) {
String name = material.name();
return name.endsWith("_SWORD") || name.endsWith("_AXE") ||
name.equals("TRIDENT") || name.equals("BOW") || name.equals("CROSSBOW");
}
private boolean isArmor(org.bukkit.Material material) {
String name = material.name();
return name.endsWith("_HELMET") || name.endsWith("_CHESTPLATE") ||
name.endsWith("_LEGGINGS") || name.endsWith("_BOOTS") || name.equals("SHIELD");
}
private boolean isTool(org.bukkit.Material material) {
String name = material.name();
return name.endsWith("_PICKAXE") || name.endsWith("_SHOVEL") ||
name.endsWith("_HOE") || name.endsWith("_AXE");
}
}

View File

@@ -0,0 +1,393 @@
package com.simolzimol.levelcraft.augmentation;
import com.simolzimol.levelcraft.item.Rarity;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.*;
public class EnhancedItem {
private static NamespacedKey enhancedKey;
private static NamespacedKey levelKey;
private static NamespacedKey slotsKey;
private static NamespacedKey rarityKey;
private static NamespacedKey xpKey;
private ItemStack itemStack;
private Rarity rarity;
private int itemLevel;
private long itemXP;
private List<AugmentationSlot> slots;
private Map<String, Double> calculatedStats;
public EnhancedItem(ItemStack itemStack, Rarity rarity) {
this(itemStack, rarity, 1);
}
public EnhancedItem(ItemStack itemStack, Rarity rarity, int level) {
this.itemStack = itemStack.clone();
this.rarity = rarity;
this.itemLevel = Math.max(1, level);
this.itemXP = 0; // Start with 0 XP
this.slots = new ArrayList<>();
this.calculatedStats = new HashMap<>();
initializeSlots();
updateItemMeta();
}
// Create from existing ItemStack (load from NBT)
public static EnhancedItem fromItemStack(ItemStack itemStack) {
ItemMeta meta = itemStack.getItemMeta();
if (meta == null || !isEnhanced(itemStack)) {
return null;
}
// Load rarity
Integer rarityValue = meta.getPersistentDataContainer().get(rarityKey, PersistentDataType.INTEGER);
Rarity rarity = rarityValue != null ? Rarity.fromValue(rarityValue) : Rarity.COMMON;
EnhancedItem enhanced = new EnhancedItem(itemStack, rarity);
// Load level
Integer level = meta.getPersistentDataContainer().get(levelKey, PersistentDataType.INTEGER);
enhanced.itemLevel = level != null ? level : 1;
// Load XP
Long xp = meta.getPersistentDataContainer().get(xpKey, PersistentDataType.LONG);
enhanced.itemXP = xp != null ? xp : 0;
// Load slots
String slotsData = meta.getPersistentDataContainer().get(slotsKey, PersistentDataType.STRING);
if (slotsData != null && !slotsData.isEmpty()) {
enhanced.loadSlotsFromData(slotsData);
}
enhanced.recalculateStats();
return enhanced;
}
public static void init(org.bukkit.plugin.Plugin plugin) {
enhancedKey = new NamespacedKey(plugin, "enhanced");
slotsKey = new NamespacedKey(plugin, "augmentation_slots");
levelKey = new NamespacedKey(plugin, "item_level");
rarityKey = new NamespacedKey(plugin, "rarity");
xpKey = new NamespacedKey(plugin, "item_xp");
}
public static boolean isEnhanced(ItemStack itemStack) {
if (itemStack == null || !itemStack.hasItemMeta()) return false;
ItemMeta meta = itemStack.getItemMeta();
return meta.getPersistentDataContainer().has(enhancedKey, PersistentDataType.BYTE);
}
private void initializeSlots() {
int maxSlots = getMaxSlotsForRarity(rarity);
int unlockedSlots = com.simolzimol.levelcraft.system.ItemLevelingSystem.calculateSlotsForLevel(itemLevel);
// Ensure we don't exceed the rarity maximum
unlockedSlots = Math.min(unlockedSlots, maxSlots);
slots.clear();
// Add unlocked slots
for (int i = 0; i < unlockedSlots; i++) {
slots.add(new AugmentationSlot(i));
}
// Add locked slots (locked by level or rarity)
for (int i = unlockedSlots; i < maxSlots; i++) {
slots.add(new AugmentationSlot(i, true));
}
}
private int getMaxSlotsForRarity(Rarity rarity) {
return switch (rarity) {
case CURSED -> 1;
case COMMON -> 1;
case UNCOMMON -> 2;
case RARE -> 3;
case EPIC -> 4;
case LEGENDARY -> 5;
case MYTHIC -> 6;
case ANCIENT -> 7;
case DIVINE -> 8;
};
}
private int getAvailableSlotsForRarity(Rarity rarity) {
return switch (rarity) {
case CURSED -> 0; // Cursed items have no available slots initially
case COMMON -> 1;
case UNCOMMON -> 1;
case RARE -> 2;
case EPIC -> 2;
case LEGENDARY -> 3;
case MYTHIC -> 4;
case ANCIENT -> 5;
case DIVINE -> 6;
};
}
public boolean addAugmentation(Augmentation augmentation, org.bukkit.entity.Player player) {
// Check if augmentation is applicable to this item type
if (!augmentation.getType().isApplicableTo(itemStack.getType())) {
return false;
}
// Check if player/item level allows this augmentation level
int maxAllowedLevel = com.simolzimol.levelcraft.player.PlayerLevelManager.getMaxAugmentationLevel(
player, itemLevel, augmentation.getType().getMaxLevel());
if (augmentation.getLevel() > maxAllowedLevel) {
return false;
}
// Find first empty, unlocked slot
for (AugmentationSlot slot : slots) {
if (slot.isEmpty() && !slot.isLocked()) {
slot.setAugmentation(augmentation);
recalculateStats();
updateItemMeta();
return true;
}
}
return false;
}
// Backward compatibility method (assumes max allowed level)
public boolean addAugmentation(Augmentation augmentation) {
// Find first empty, unlocked slot
for (AugmentationSlot slot : slots) {
if (slot.isEmpty() && !slot.isLocked()) {
slot.setAugmentation(augmentation);
recalculateStats();
updateItemMeta();
return true;
}
}
return false;
}
public boolean removeAugmentation(int slotId) {
if (slotId >= 0 && slotId < slots.size()) {
AugmentationSlot slot = slots.get(slotId);
if (!slot.isEmpty() && !slot.isLocked()) {
slot.removeAugmentation();
recalculateStats();
updateItemMeta();
return true;
}
}
return false;
}
public void levelUp() {
itemLevel++;
// Every 5 levels, unlock a random locked slot
if (itemLevel % 5 == 0) {
unlockRandomSlot();
}
updateItemMeta();
}
private void unlockRandomSlot() {
List<AugmentationSlot> lockedSlots = slots.stream()
.filter(AugmentationSlot::isLocked)
.toList();
if (!lockedSlots.isEmpty()) {
Random random = new Random();
AugmentationSlot slotToUnlock = lockedSlots.get(random.nextInt(lockedSlots.size()));
slotToUnlock.unlock();
}
}
private void recalculateStats() {
calculatedStats.clear();
for (AugmentationSlot slot : slots) {
if (!slot.isEmpty()) {
Augmentation aug = slot.getAugmentation();
for (Map.Entry<String, Double> entry : aug.getStatModifiers().entrySet()) {
calculatedStats.merge(entry.getKey(), entry.getValue(), Double::sum);
}
}
}
}
private void updateItemMeta() {
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) return;
// Mark as enhanced
meta.getPersistentDataContainer().set(enhancedKey, PersistentDataType.BYTE, (byte) 1);
meta.getPersistentDataContainer().set(rarityKey, PersistentDataType.INTEGER, rarity.getValue());
meta.getPersistentDataContainer().set(levelKey, PersistentDataType.INTEGER, itemLevel);
meta.getPersistentDataContainer().set(xpKey, PersistentDataType.LONG, itemXP);
meta.getPersistentDataContainer().set(slotsKey, PersistentDataType.STRING, serializeSlots());
// Update display name and lore
updateDisplayNameAndLore(meta);
itemStack.setItemMeta(meta);
}
private void updateDisplayNameAndLore(ItemMeta meta) {
// Update display name with level and rarity
String baseName = itemStack.getType().name().replace("_", " ").toLowerCase();
baseName = Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
String displayName = rarity.getDisplayName() + " " + baseName + " §7[Lv." + itemLevel + "]";
meta.displayName(net.kyori.adventure.text.Component.text(displayName));
// Create lore
List<net.kyori.adventure.text.Component> lore = new ArrayList<>();
// Rarity line
lore.add(net.kyori.adventure.text.Component.text(rarity.getDisplayName() + " §7Item"));
lore.add(net.kyori.adventure.text.Component.text("§7Level: §f" + itemLevel));
// XP Progress line
if (itemLevel < com.simolzimol.levelcraft.system.ItemLevelingSystem.getMaxItemLevel(rarity)) {
long xpForNext = com.simolzimol.levelcraft.system.ItemLevelingSystem.getXPRequiredForLevel(itemLevel + 1);
long xpForCurrent = itemLevel > 1 ? com.simolzimol.levelcraft.system.ItemLevelingSystem.getXPRequiredForLevel(itemLevel) : 0;
long xpInLevel = itemXP - xpForCurrent;
long xpNeeded = xpForNext - xpForCurrent;
double progress = (double) xpInLevel / xpNeeded;
int bars = 10;
int filledBars = (int) (progress * bars);
StringBuilder progressBar = new StringBuilder("§a");
for (int i = 0; i < bars; i++) {
if (i < filledBars) {
progressBar.append("");
} else {
progressBar.append("§7█");
}
}
lore.add(net.kyori.adventure.text.Component.text("§7XP: " + progressBar + " §e" + xpInLevel + "§7/§e" + xpNeeded));
} else {
lore.add(net.kyori.adventure.text.Component.text("§7XP: §6MAX LEVEL"));
}
lore.add(net.kyori.adventure.text.Component.text(""));
// Augmentation slots
lore.add(net.kyori.adventure.text.Component.text("§6⬟ Augmentation Slots:"));
for (AugmentationSlot slot : slots) {
String slotDisplay;
if (slot.isEmpty()) {
if (slot.isLocked()) {
slotDisplay = "§8▣ §7[" + (slot.getSlotId() + 1) + "] §8Locked Slot";
} else {
slotDisplay = "§7▢ §7[" + (slot.getSlotId() + 1) + "] §7Empty Slot";
}
} else {
Augmentation aug = slot.getAugmentation();
String typeColor = getAugmentationTypeColor(aug.getType());
slotDisplay = "§a▣ §7[" + (slot.getSlotId() + 1) + "] " + typeColor + aug.getDisplayName();
lore.add(net.kyori.adventure.text.Component.text(" " + slotDisplay));
lore.add(net.kyori.adventure.text.Component.text(" §8↳ " + aug.getDescription()));
continue;
}
lore.add(net.kyori.adventure.text.Component.text(" " + slotDisplay));
}
// Stats summary if any augmentations
if (!calculatedStats.isEmpty()) {
lore.add(net.kyori.adventure.text.Component.text(""));
lore.add(net.kyori.adventure.text.Component.text("§aTotal Bonuses:"));
for (Map.Entry<String, Double> entry : calculatedStats.entrySet()) {
String statName = entry.getKey().replace("_", " ");
statName = Character.toUpperCase(statName.charAt(0)) + statName.substring(1);
lore.add(net.kyori.adventure.text.Component.text("§7+ " + entry.getValue() + " " + statName));
}
}
meta.lore(lore);
}
private String serializeSlots() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < slots.size(); i++) {
if (i > 0) sb.append("|");
sb.append(slots.get(i).serialize());
}
return sb.toString();
}
private void loadSlotsFromData(String data) {
slots.clear();
String[] slotData = data.split("\\|");
for (String slotString : slotData) {
AugmentationSlot slot = AugmentationSlot.deserialize(slotString);
if (slot != null) {
slots.add(slot);
}
}
}
// Getters
public ItemStack getItemStack() {
return itemStack.clone();
}
public Rarity getRarity() {
return rarity;
}
public int getItemLevel() {
return itemLevel;
}
public long getItemXP() {
return itemXP;
}
public void setItemLevel(int level) {
this.itemLevel = Math.max(1, level);
// Reinitialize slots when level changes (may unlock new slots)
initializeSlots();
updateItemMeta();
}
public void setItemXP(long xp) {
this.itemXP = Math.max(0, xp);
updateItemMeta();
}
public List<AugmentationSlot> getSlots() {
return new ArrayList<>(slots);
}
public Map<String, Double> getCalculatedStats() {
return new HashMap<>(calculatedStats);
}
public int getUsedSlots() {
return (int) slots.stream().filter(slot -> !slot.isEmpty()).count();
}
public int getAvailableSlots() {
return (int) slots.stream().filter(slot -> slot.isEmpty() && !slot.isLocked()).count();
}
public int getTotalSlots() {
return slots.size();
}
private String getAugmentationTypeColor(AugmentationType type) {
return switch (type) {
case SHARPNESS, SMITE, BANE_OF_ARTHROPODS, CRITICAL_STRIKE -> "§c"; // Red for damage
case PROTECTION, RESISTANCE, THORNS -> "§9"; // Blue for protection
case EFFICIENCY, UNBREAKING, MENDING, SILK_TOUCH -> "§e"; // Yellow for utility
case FORTUNE, VAMPIRIC, REGENERATION -> "§a"; // Green for beneficial
case FIRE_ASPECT, CHAIN_LIGHTNING, SPEED -> "§d"; // Magenta for special
case KNOCKBACK -> "§7"; // Gray for knockback
default -> "§f"; // White fallback
};
}
}

View File

@@ -0,0 +1,226 @@
package com.simolzimol.levelcraft.command;
import com.simolzimol.levelcraft.augmentation.*;
import com.simolzimol.levelcraft.item.Rarity;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Random;
public class AugmentCommand implements CommandExecutor {
private final Random random = new Random();
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage("Only players can use this command.");
return true;
}
if (args.length == 0) {
player.sendMessage("§6=== LevelCraft Augmentation Commands ===");
player.sendMessage("§e/augment create [rarity] §7- Create enhanced item");
player.sendMessage("§e/augment add <type> [level] §7- Add augmentation to held item");
player.sendMessage("§e/augment remove <slot> §7- Remove augmentation from slot");
player.sendMessage("§e/augment info §7- Show item information");
player.sendMessage("§e/augment levelup §7- Level up held item");
return true;
}
String subCommand = args[0].toLowerCase();
switch (subCommand) {
case "create" -> handleCreate(player, args);
case "add" -> handleAdd(player, args);
case "remove" -> handleRemove(player, args);
case "info" -> handleInfo(player);
case "levelup" -> handleLevelUp(player);
default -> player.sendMessage("§cUnknown subcommand. Use /augment for help.");
}
return true;
}
private void handleCreate(Player player, String[] args) {
Rarity rarity = Rarity.COMMON;
if (args.length > 1) {
try {
rarity = Rarity.valueOf(args[1].toUpperCase());
} catch (IllegalArgumentException e) {
player.sendMessage("§cInvalid rarity. Available: " + java.util.Arrays.toString(Rarity.values()));
return;
}
}
// Create a random weapon/tool/armor
Material[] testMaterials = {
Material.DIAMOND_SWORD, Material.DIAMOND_PICKAXE, Material.DIAMOND_HELMET,
Material.IRON_SWORD, Material.IRON_AXE, Material.IRON_CHESTPLATE,
Material.NETHERITE_SWORD, Material.NETHERITE_BOOTS
};
Material material = testMaterials[random.nextInt(testMaterials.length)];
ItemStack item = new ItemStack(material);
EnhancedItem enhanced = new EnhancedItem(item, rarity);
player.getInventory().addItem(enhanced.getItemStack());
player.sendMessage("§aCreated " + rarity.getDisplayName() + " §aitem with " +
enhanced.getAvailableSlots() + "/" + enhanced.getTotalSlots() + " slots available!");
}
private void handleAdd(Player player, String[] args) {
if (args.length < 2) {
player.sendMessage("§cUsage: /augment add <type> [level]");
player.sendMessage("§cAvailable types: " + java.util.Arrays.toString(AugmentationType.values()));
return;
}
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (heldItem.getType() == Material.AIR) {
player.sendMessage("§cYou must hold an item!");
return;
}
// Convert to enhanced item if not already
EnhancedItem enhanced;
if (EnhancedItem.isEnhanced(heldItem)) {
enhanced = EnhancedItem.fromItemStack(heldItem);
} else {
enhanced = new EnhancedItem(heldItem, Rarity.COMMON);
}
if (enhanced == null) {
player.sendMessage("§cFailed to create enhanced item!");
return;
}
try {
AugmentationType type = AugmentationType.valueOf(args[1].toUpperCase());
int level = args.length > 2 ? Integer.parseInt(args[2]) : 1;
level = Math.min(level, type.getMaxLevel());
level = Math.max(level, 1);
// Check level restrictions
int maxAllowedLevel = com.simolzimol.levelcraft.player.PlayerLevelManager.getMaxAugmentationLevel(
player, enhanced.getItemLevel(), type.getMaxLevel());
if (level > maxAllowedLevel) {
level = maxAllowedLevel;
player.sendMessage("§eLevel reduced to " + level + " (max allowed for your player/item level)");
}
if (level < 1) {
player.sendMessage("§cYour player level is too low for this augmentation!");
return;
}
Augmentation augmentation = new Augmentation(type, level);
if (enhanced.addAugmentation(augmentation, player)) {
player.getInventory().setItemInMainHand(enhanced.getItemStack());
player.sendMessage("§aAdded " + augmentation.getDisplayName() + " §ato your item!");
} else {
player.sendMessage("§cCould not add augmentation! (No free slots, incompatible type, or level too high)");
}
} catch (IllegalArgumentException e) {
player.sendMessage("§cInvalid augmentation type or level!");
}
}
private void handleRemove(Player player, String[] args) {
if (args.length < 2) {
player.sendMessage("§cUsage: /augment remove <slot_number>");
return;
}
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (!EnhancedItem.isEnhanced(heldItem)) {
player.sendMessage("§cYou must hold an enhanced item!");
return;
}
EnhancedItem enhanced = EnhancedItem.fromItemStack(heldItem);
if (enhanced == null) {
player.sendMessage("§cFailed to load enhanced item!");
return;
}
try {
int slotId = Integer.parseInt(args[1]) - 1; // Convert to 0-based
if (enhanced.removeAugmentation(slotId)) {
player.getInventory().setItemInMainHand(enhanced.getItemStack());
player.sendMessage("§aRemoved augmentation from slot " + (slotId + 1) + "!");
} else {
player.sendMessage("§cCould not remove augmentation from slot " + (slotId + 1) + "!");
}
} catch (NumberFormatException e) {
player.sendMessage("§cInvalid slot number!");
}
}
private void handleInfo(Player player) {
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (!EnhancedItem.isEnhanced(heldItem)) {
player.sendMessage("§cYou must hold an enhanced item!");
return;
}
EnhancedItem enhanced = EnhancedItem.fromItemStack(heldItem);
if (enhanced == null) {
player.sendMessage("§cFailed to load enhanced item!");
return;
}
player.sendMessage("§6=== Enhanced Item Info ===");
player.sendMessage("§eRarity: " + enhanced.getRarity().getDisplayName());
player.sendMessage("§eLevel: §f" + enhanced.getItemLevel());
player.sendMessage("§eSlots: §f" + enhanced.getUsedSlots() + "/" + enhanced.getAvailableSlots() +
" available, " + enhanced.getTotalSlots() + " total");
player.sendMessage("§6Augmentations:");
for (AugmentationSlot slot : enhanced.getSlots()) {
player.sendMessage("§7[" + (slot.getSlotId() + 1) + "] " + slot.getDisplayName());
}
if (!enhanced.getCalculatedStats().isEmpty()) {
player.sendMessage("§6Total Stats:");
for (var entry : enhanced.getCalculatedStats().entrySet()) {
player.sendMessage("§a+ " + entry.getValue() + " " + entry.getKey());
}
}
}
private void handleLevelUp(Player player) {
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (!EnhancedItem.isEnhanced(heldItem)) {
player.sendMessage("§cYou must hold an enhanced item!");
return;
}
EnhancedItem enhanced = EnhancedItem.fromItemStack(heldItem);
if (enhanced == null) {
player.sendMessage("§cFailed to load enhanced item!");
return;
}
int oldLevel = enhanced.getItemLevel();
enhanced.levelUp();
int newLevel = enhanced.getItemLevel();
player.getInventory().setItemInMainHand(enhanced.getItemStack());
player.sendMessage("§aItem leveled up! §7(" + oldLevel + "" + newLevel + ")");
if (newLevel % 5 == 0) {
player.sendMessage("§6Milestone reached! A slot may have been unlocked!");
}
}
}

View File

@@ -0,0 +1,164 @@
package com.simolzimol.levelcraft.command;
import com.simolzimol.levelcraft.augmentation.EnhancedItem;
import com.simolzimol.levelcraft.item.Rarity;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Random;
/**
* Command to convert regular items to Enhanced Items
* Usage: /convert [hand|all]
*/
public class ConvertCommand implements CommandExecutor {
private final Random random = new Random();
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("§cThis command can only be used by players!");
return true;
}
Player player = (Player) sender;
if (args.length == 0) {
// Default: convert item in hand
convertItemInHand(player);
return true;
}
String subcommand = args[0].toLowerCase();
switch (subcommand) {
case "hand":
convertItemInHand(player);
break;
case "all":
convertAllItems(player);
break;
case "help":
showHelp(player);
break;
default:
player.sendMessage("§cInvalid argument! Use: /convert [hand|all|help]");
break;
}
return true;
}
private void convertItemInHand(Player player) {
ItemStack item = player.getInventory().getItemInMainHand();
if (item == null || item.getType() == Material.AIR) {
player.sendMessage("§cYou must hold an item!");
return;
}
if (EnhancedItem.isEnhanced(item)) {
player.sendMessage("§eThis item is already enhanced!");
return;
}
if (!isEnhanceable(item)) {
player.sendMessage("§cThis item cannot be enhanced! (Only tools, weapons, and armor)");
return;
}
// Convert to Enhanced Item
Rarity rarity = getRandomRarity();
EnhancedItem enhanced = new EnhancedItem(item, rarity, 1);
player.getInventory().setItemInMainHand(enhanced.getItemStack());
player.sendMessage("§a✦ Item converted to Enhanced Item!");
player.sendMessage("§7Rarity: " + rarity.getDisplayName());
player.sendMessage("§7Level: §f1 §8(no augmentations yet)");
}
private void convertAllItems(Player player) {
if (!player.hasPermission("levelcraft.admin")) {
player.sendMessage("§cYou don't have permission to convert all items!");
return;
}
int converted = 0;
for (int slot = 0; slot < player.getInventory().getSize(); slot++) {
ItemStack item = player.getInventory().getItem(slot);
if (item == null || item.getType() == Material.AIR) continue;
if (EnhancedItem.isEnhanced(item)) continue;
if (!isEnhanceable(item)) continue;
// Convert to Enhanced Item
Rarity rarity = getRandomRarity();
EnhancedItem enhanced = new EnhancedItem(item, rarity, 1);
player.getInventory().setItem(slot, enhanced.getItemStack());
converted++;
}
if (converted > 0) {
player.sendMessage("§a§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("§a§l BULK CONVERSION COMPLETE!");
player.sendMessage("§a§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("§eConverted " + converted + " items to Enhanced Items!");
player.sendMessage("§7All items are now Level 1 with random rarities.");
player.sendMessage("§7Use /augment add to add augmentations to them!");
} else {
player.sendMessage("§eNo items to convert found!");
}
}
private void showHelp(Player player) {
player.sendMessage("§6§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("§6§l CONVERT COMMAND HELP");
player.sendMessage("§6§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("");
player.sendMessage("§e/convert §7- Convert item in hand to Enhanced Item");
player.sendMessage("§e/convert hand §7- Convert item in hand to Enhanced Item");
player.sendMessage("§e/convert all §7- Convert all items in inventory §c(Admin)");
player.sendMessage("§e/convert help §7- Show this help");
player.sendMessage("");
player.sendMessage("§7Enhanced Items start at Level 1 with random rarity");
player.sendMessage("§7but no augmentations. Use §e/augment add §7to enhance them!");
player.sendMessage("§6▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
}
/**
* Determines if an item can be enhanced
*/
private boolean isEnhanceable(ItemStack item) {
if (item == null || item.getType().isAir()) return false;
// Only enhance items with durability (tools, weapons, armor)
return item.getType().getMaxDurability() > 0;
}
/**
* Gets a random rarity with weighted distribution
*/
private Rarity getRandomRarity() {
int roll = random.nextInt(1000);
// Weighted rarity distribution using correct Rarity enum values
if (roll < 3) return Rarity.DIVINE; // 0.3%
if (roll < 15) return Rarity.ANCIENT; // 1.2%
if (roll < 40) return Rarity.MYTHIC; // 2.5%
if (roll < 90) return Rarity.LEGENDARY; // 5.0%
if (roll < 170) return Rarity.EPIC; // 8.0%
if (roll < 290) return Rarity.RARE; // 12.0%
if (roll < 490) return Rarity.UNCOMMON; // 20.0%
if (roll < 980) return Rarity.COMMON; // 49.0%
return Rarity.CURSED; // 2.0%
}
}

View File

@@ -0,0 +1,162 @@
package com.simolzimol.levelcraft.command;
import com.simolzimol.levelcraft.demo.DemoAugmentationSystem;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
/**
* Command for creating demo items with augmentations
* Usage: /demo [item_number] [all] [random]
*/
public class DemoCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("§cThis command can only be used by players!");
return true;
}
Player player = (Player) sender;
if (args.length == 0) {
showHelp(player);
return true;
}
String subcommand = args[0].toLowerCase();
switch (subcommand) {
case "all":
giveAllDemoItems(player);
break;
case "random":
giveRandomDemoItem(player);
break;
case "list":
listDemoItems(player);
break;
default:
try {
int itemIndex = Integer.parseInt(subcommand) - 1; // Convert to 0-based index
if (itemIndex >= 0 && itemIndex <= 9) {
giveSpecificDemoItem(player, itemIndex);
} else {
player.sendMessage("§cInvalid item number! Use 1-10.");
}
} catch (NumberFormatException e) {
player.sendMessage("§cInvalid argument! Use: /demo [1-10|all|random|list]");
}
break;
}
return true;
}
private void showHelp(Player player) {
player.sendMessage("§6§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("§6§l DEMO AUGMENTATION SYSTEM");
player.sendMessage("§6§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("");
player.sendMessage("§e/demo [1-10] §7- Get a specific demo item");
player.sendMessage("§e/demo all §7- Get all 10 demo items");
player.sendMessage("§e/demo random §7- Get a random demo item");
player.sendMessage("§e/demo list §7- List all available demo items");
player.sendMessage("");
player.sendMessage("§7These items showcase the augmentation system with");
player.sendMessage("§7pre-configured augmentations for different playstyles!");
player.sendMessage("§6▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
}
private void giveAllDemoItems(Player player) {
try {
for (int i = 0; i < 10; i++) {
ItemStack demoItem = DemoAugmentationSystem.getDemoItem(i);
player.getInventory().addItem(demoItem);
}
player.sendMessage("§a§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("§a§l ALL DEMO ITEMS RECEIVED!");
player.sendMessage("§a§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("§eYou received all 10 demo items with pre-configured augmentations!");
player.sendMessage("§7Use these items to explore the augmentation system capabilities.");
} catch (Exception e) {
player.sendMessage("§cError creating demo items: " + e.getMessage());
}
}
private void giveRandomDemoItem(Player player) {
try {
ItemStack randomItem = DemoAugmentationSystem.createRandomDemoItem();
player.getInventory().addItem(randomItem);
player.sendMessage("§a✦ §eYou received a random demo item!");
player.sendMessage("§7Check your inventory to see what you got!");
} catch (Exception e) {
player.sendMessage("§cError creating random demo item: " + e.getMessage());
}
}
private void giveSpecificDemoItem(Player player, int index) {
try {
ItemStack demoItem = DemoAugmentationSystem.getDemoItem(index);
String itemName = DemoAugmentationSystem.getDemoItemName(index);
player.getInventory().addItem(demoItem);
player.sendMessage("§a▣ §eYou received: §6" + itemName);
player.sendMessage("§7This item showcases specific augmentation combinations!");
} catch (Exception e) {
player.sendMessage("§cError creating demo item: " + e.getMessage());
}
}
private void listDemoItems(Player player) {
player.sendMessage("§6§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("§6§l AVAILABLE DEMO ITEMS");
player.sendMessage("§6§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("");
for (int i = 0; i < 10; i++) {
String itemName = DemoAugmentationSystem.getDemoItemName(i);
String themeColor = getDemoItemThemeColor(i);
player.sendMessage("§e" + (i + 1) + ". " + themeColor + itemName + " §8- " + getDemoItemDescription(i));
}
player.sendMessage("");
player.sendMessage("§7Use §e/demo [number] §7to get a specific item!");
player.sendMessage("§6▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
}
private String getDemoItemThemeColor(int index) {
String[] colors = {
"§c", "§9", "§e", "§8", "§6", "§a", "§d", "§7", "§2", "§5"
};
return colors[index % colors.length];
}
private String getDemoItemDescription(int index) {
String[] descriptions = {
"High damage combat sword",
"Ultimate protection armor",
"Efficient mining tool",
"Fast critical strikes",
"Balanced combat/defense",
"Ranged combat bow",
"Magical lightning staff",
"Basic survival gear",
"Treasure finding tool",
"Ultimate legendary item"
};
return descriptions[index % descriptions.length];
}
}

View File

@@ -0,0 +1,160 @@
package com.simolzimol.levelcraft.command;
import com.simolzimol.levelcraft.player.PlayerLevelManager;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
/**
* Command for managing player levels and XP
* Usage: /playerlevel [player] [add/set/info] [amount]
*/
public class PlayerLevelCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
// Show own level if player
if (sender instanceof Player) {
showPlayerInfo((Player) sender, (Player) sender);
} else {
sender.sendMessage("§cUsage: /playerlevel <player> [add/set/info] [amount]");
}
return true;
}
if (args.length == 1) {
// Show target player's level
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
sender.sendMessage("§cPlayer not found!");
return true;
}
if (sender instanceof Player) {
showPlayerInfo((Player) sender, target);
} else {
showPlayerInfoConsole(sender, target);
}
return true;
}
if (args.length >= 2) {
if (!sender.hasPermission("levelcraft.admin")) {
sender.sendMessage("§cYou don't have permission to modify player levels!");
return true;
}
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
sender.sendMessage("§cPlayer not found!");
return true;
}
String action = args[1].toLowerCase();
switch (action) {
case "info":
if (sender instanceof Player) {
showPlayerInfo((Player) sender, target);
} else {
showPlayerInfoConsole(sender, target);
}
break;
case "add":
if (args.length < 3) {
sender.sendMessage("§cUsage: /playerlevel <player> add <amount>");
return true;
}
try {
int amount = Integer.parseInt(args[2]);
PlayerLevelManager.addXP(target, amount, "Admin Command");
sender.sendMessage("§aAdded " + amount + " XP to " + target.getName());
} catch (NumberFormatException e) {
sender.sendMessage("§cInvalid amount!");
}
break;
case "set":
if (args.length < 3) {
sender.sendMessage("§cUsage: /playerlevel <player> set <level>");
return true;
}
try {
int level = Integer.parseInt(args[2]);
if (level < 1) {
sender.sendMessage("§cLevel must be at least 1!");
return true;
}
PlayerLevelManager.setPlayerLevel(target, level);
sender.sendMessage("§aSet " + target.getName() + "'s level to " + level);
target.sendMessage("§eYour level has been set to " + level + " by an admin!");
} catch (NumberFormatException e) {
sender.sendMessage("§cInvalid level!");
}
break;
default:
sender.sendMessage("§cInvalid action! Use: info, add, set");
break;
}
}
return true;
}
private void showPlayerInfo(Player viewer, Player target) {
int level = PlayerLevelManager.getPlayerLevel(target);
long xp = PlayerLevelManager.getPlayerXP(target);
long xpForNext = PlayerLevelManager.getXPRequiredForLevel(level + 1);
long xpForCurrent = level > 1 ? PlayerLevelManager.getXPRequiredForLevel(level) : 0;
long xpInLevel = xp - xpForCurrent;
long xpNeededForNext = xpForNext - xpForCurrent;
String targetName = target.equals(viewer) ? "Your" : target.getName() + "'s";
viewer.sendMessage("§6▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
viewer.sendMessage("§6§l " + targetName.toUpperCase() + " LEVEL STATUS");
viewer.sendMessage("");
viewer.sendMessage("§e Current Level: §6§l" + level);
viewer.sendMessage("§e Total XP: §6" + xp);
viewer.sendMessage("§e XP in Level: §6" + xpInLevel + "§7/§6" + xpNeededForNext);
viewer.sendMessage("§e XP to Next: §6" + (xpNeededForNext - xpInLevel));
viewer.sendMessage("");
// Show progress bar
double progress = (double) xpInLevel / xpNeededForNext;
int barLength = 30;
int filledBars = (int) (progress * barLength);
StringBuilder progressBar = new StringBuilder("§a");
for (int i = 0; i < barLength; i++) {
if (i < filledBars) {
progressBar.append("");
} else if (i == filledBars && progress > 0) {
progressBar.append("§e▌§7");
} else {
progressBar.append("§7█");
}
}
viewer.sendMessage(" Progress: " + progressBar + " §e" + String.format("%.1f%%", progress * 100));
viewer.sendMessage("§6▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
}
private void showPlayerInfoConsole(CommandSender sender, Player target) {
int level = PlayerLevelManager.getPlayerLevel(target);
long xp = PlayerLevelManager.getPlayerXP(target);
long xpForNext = PlayerLevelManager.getXPRequiredForLevel(level + 1);
sender.sendMessage("§6" + target.getName() + "'s Level Status:");
sender.sendMessage("§e Level: " + level);
sender.sendMessage("§e XP: " + xp + "/" + xpForNext);
}
}

View File

@@ -0,0 +1,213 @@
package com.simolzimol.levelcraft.demo;
import com.simolzimol.levelcraft.augmentation.*;
import com.simolzimol.levelcraft.item.Rarity;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* Demo system for creating items with pre-configured augmentations
* This showcases the augmentation system with 10 different demo setups
*/
public class DemoAugmentationSystem {
private static final Random random = new Random();
/**
* Creates a list of 10 demo items with different augmentation setups
*/
public static List<ItemStack> createDemoItems() {
List<ItemStack> demoItems = new ArrayList<>();
// 1. Warrior's Sword - Combat focused
demoItems.add(createWarriorSword());
// 2. Guardian's Shield - Protection focused
demoItems.add(createGuardianShield());
// 3. Miner's Pickaxe - Utility focused
demoItems.add(createMinerPickaxe());
// 4. Assassin's Dagger - Critical strike focused
demoItems.add(createAssassinDagger());
// 5. Paladin's Hammer - Balanced combat/defense
demoItems.add(createPaladinHammer());
// 6. Hunter's Bow - Ranged combat
demoItems.add(createHunterBow());
// 7. Wizard's Staff - Magic focused
demoItems.add(createWizardStaff());
// 8. Survivor's Armor - Survival focused
demoItems.add(createSurvivorArmor());
// 9. Treasure Hunter's Tool - Luck focused
demoItems.add(createTreasureHunterTool());
// 10. Legendary All-Purpose Item - Mixed augmentations
demoItems.add(createLegendaryItem());
return demoItems;
}
private static ItemStack createWarriorSword() {
ItemStack sword = new ItemStack(Material.NETHERITE_SWORD);
EnhancedItem enhanced = new EnhancedItem(sword, Rarity.EPIC, 15);
enhanced.addAugmentation(new Augmentation(AugmentationType.SHARPNESS, 8));
enhanced.addAugmentation(new Augmentation(AugmentationType.CRITICAL_STRIKE, 4));
enhanced.addAugmentation(new Augmentation(AugmentationType.FIRE_ASPECT, 2));
return enhanced.getItemStack();
}
private static ItemStack createGuardianShield() {
ItemStack chestplate = new ItemStack(Material.DIAMOND_CHESTPLATE);
EnhancedItem enhanced = new EnhancedItem(chestplate, Rarity.RARE, 12);
enhanced.addAugmentation(new Augmentation(AugmentationType.PROTECTION, 5));
enhanced.addAugmentation(new Augmentation(AugmentationType.RESISTANCE, 3));
enhanced.addAugmentation(new Augmentation(AugmentationType.THORNS, 2));
return enhanced.getItemStack();
}
private static ItemStack createMinerPickaxe() {
ItemStack pickaxe = new ItemStack(Material.DIAMOND_PICKAXE);
EnhancedItem enhanced = new EnhancedItem(pickaxe, Rarity.RARE, 10);
enhanced.addAugmentation(new Augmentation(AugmentationType.EFFICIENCY, 7));
enhanced.addAugmentation(new Augmentation(AugmentationType.FORTUNE, 4));
enhanced.addAugmentation(new Augmentation(AugmentationType.UNBREAKING, 4));
return enhanced.getItemStack();
}
private static ItemStack createAssassinDagger() {
ItemStack dagger = new ItemStack(Material.IRON_SWORD);
EnhancedItem enhanced = new EnhancedItem(dagger, Rarity.UNCOMMON, 8);
enhanced.addAugmentation(new Augmentation(AugmentationType.CRITICAL_STRIKE, 5));
enhanced.addAugmentation(new Augmentation(AugmentationType.VAMPIRIC, 2));
enhanced.addAugmentation(new Augmentation(AugmentationType.SPEED, 1));
return enhanced.getItemStack();
}
private static ItemStack createPaladinHammer() {
ItemStack hammer = new ItemStack(Material.NETHERITE_AXE);
EnhancedItem enhanced = new EnhancedItem(hammer, Rarity.EPIC, 16);
enhanced.addAugmentation(new Augmentation(AugmentationType.SMITE, 6));
enhanced.addAugmentation(new Augmentation(AugmentationType.PROTECTION, 3));
enhanced.addAugmentation(new Augmentation(AugmentationType.REGENERATION, 2));
enhanced.addAugmentation(new Augmentation(AugmentationType.UNBREAKING, 3));
return enhanced.getItemStack();
}
private static ItemStack createHunterBow() {
ItemStack bow = new ItemStack(Material.BOW);
EnhancedItem enhanced = new EnhancedItem(bow, Rarity.RARE, 11);
enhanced.addAugmentation(new Augmentation(AugmentationType.SHARPNESS, 5)); // Represents Power
enhanced.addAugmentation(new Augmentation(AugmentationType.CRITICAL_STRIKE, 3));
enhanced.addAugmentation(new Augmentation(AugmentationType.MENDING, 1));
return enhanced.getItemStack();
}
private static ItemStack createWizardStaff() {
ItemStack staff = new ItemStack(Material.BLAZE_ROD);
EnhancedItem enhanced = new EnhancedItem(staff, Rarity.LEGENDARY, 18);
enhanced.addAugmentation(new Augmentation(AugmentationType.CHAIN_LIGHTNING, 2));
enhanced.addAugmentation(new Augmentation(AugmentationType.FIRE_ASPECT, 3));
enhanced.addAugmentation(new Augmentation(AugmentationType.REGENERATION, 2));
enhanced.addAugmentation(new Augmentation(AugmentationType.MENDING, 1));
return enhanced.getItemStack();
}
private static ItemStack createSurvivorArmor() {
ItemStack armor = new ItemStack(Material.CHAINMAIL_HELMET);
EnhancedItem enhanced = new EnhancedItem(armor, Rarity.UNCOMMON, 7);
enhanced.addAugmentation(new Augmentation(AugmentationType.PROTECTION, 4));
enhanced.addAugmentation(new Augmentation(AugmentationType.REGENERATION, 1));
enhanced.addAugmentation(new Augmentation(AugmentationType.UNBREAKING, 3));
return enhanced.getItemStack();
}
private static ItemStack createTreasureHunterTool() {
ItemStack shovel = new ItemStack(Material.GOLDEN_SHOVEL);
EnhancedItem enhanced = new EnhancedItem(shovel, Rarity.RARE, 9);
enhanced.addAugmentation(new Augmentation(AugmentationType.FORTUNE, 5));
enhanced.addAugmentation(new Augmentation(AugmentationType.EFFICIENCY, 6));
enhanced.addAugmentation(new Augmentation(AugmentationType.SILK_TOUCH, 1));
return enhanced.getItemStack();
}
private static ItemStack createLegendaryItem() {
ItemStack item = new ItemStack(Material.NETHERITE_HELMET);
EnhancedItem enhanced = new EnhancedItem(item, Rarity.LEGENDARY, 20);
// Fill all slots with different augmentations
enhanced.addAugmentation(new Augmentation(AugmentationType.PROTECTION, 5));
enhanced.addAugmentation(new Augmentation(AugmentationType.RESISTANCE, 3));
enhanced.addAugmentation(new Augmentation(AugmentationType.REGENERATION, 3));
enhanced.addAugmentation(new Augmentation(AugmentationType.SPEED, 2));
enhanced.addAugmentation(new Augmentation(AugmentationType.UNBREAKING, 5));
enhanced.addAugmentation(new Augmentation(AugmentationType.MENDING, 1));
return enhanced.getItemStack();
}
/**
* Creates a random demo item from the available templates
*/
public static ItemStack createRandomDemoItem() {
List<ItemStack> demoItems = createDemoItems();
return demoItems.get(random.nextInt(demoItems.size())).clone();
}
/**
* Gets a specific demo item by index (0-9)
*/
public static ItemStack getDemoItem(int index) {
if (index < 0 || index >= 10) {
throw new IllegalArgumentException("Demo item index must be between 0 and 9");
}
List<ItemStack> demoItems = createDemoItems();
return demoItems.get(index).clone();
}
/**
* Gets the name of a demo item by index
*/
public static String getDemoItemName(int index) {
String[] names = {
"Warrior's Sword", "Guardian's Shield", "Miner's Pickaxe",
"Assassin's Dagger", "Paladin's Hammer", "Hunter's Bow",
"Wizard's Staff", "Survivor's Armor", "Treasure Hunter's Tool",
"Legendary All-Purpose Item"
};
if (index < 0 || index >= names.length) {
return "Unknown Demo Item";
}
return names[index];
}
}

View File

@@ -2,20 +2,38 @@ package com.simolzimol.levelcraft.item;
import java.util.List;
/**
* @deprecated This class is deprecated in favor of the new Augmentation System.
* Use com.simolzimol.levelcraft.augmentation.AugmentationType instead.
* This class is kept for backward compatibility but should not be used in new code.
*/
@Deprecated
public class ItemEffects {
// These are deprecated - use AugmentationType enum instead
@Deprecated
public static final List<String> EFFECTS = List.of(
"§bEffekt: Feuerresistenz",
"§bEffekt: Schnelligkeit",
"§bEffekt: Regeneration",
"§bEffekt: Unsichtbarkeit",
"§bEffekt: Stärke"
"§8§m§bEffekt: Feuerresistenz§r §7(Use FIRE_ASPECT augmentation)",
"§8§m§bEffekt: Schnelligkeit§r §7(Use SPEED augmentation)",
"§8§m§bEffekt: Regeneration§r §7(Use REGENERATION augmentation)",
"§8§m§bEffekt: Unsichtbarkeit§r §7(Removed - not available)",
"§8§m§bEffekt: Stärke§r §7(Use SHARPNESS augmentation)"
);
@Deprecated
public static final List<String> SKILLS = List.of(
"§dSkill: Doppelschlag",
"§dSkill: Lebensraub",
"§dSkill: Flächenschaden",
"§dSkill: Rückstoß",
"§dSkill: Kritischer Treffer"
"§8§m§dSkill: Doppelschlag§r §7(Use CRITICAL_STRIKE augmentation)",
"§8§m§dSkill: Lebensraub§r §7(Use VAMPIRIC augmentation)",
"§8§m§dSkill: Flächenschaden§r §7(Use CHAIN_LIGHTNING augmentation)",
"§8§m§dSkill: Rückstoß§r §7(Use KNOCKBACK augmentation)",
"§8§m§dSkill: Kritischer Treffer§r §7(Use CRITICAL_STRIKE augmentation)"
);
/**
* @deprecated Use the new Augmentation system instead
*/
@Deprecated
public static void printDeprecationWarning() {
System.out.println("[LevelCraft] WARNING: ItemEffects is deprecated. Use AugmentationType instead!");
}
}

View File

@@ -167,20 +167,19 @@ public class ItemUtil {
}
}
// Effekte und Skills NUR wenn NICHT CURSED
// Legacy Effects and Skills - DISABLED (Use new Augmentation System)
// NOTE: ItemEffects system has been replaced by the Augmentation System
// Use EnhancedItem with AugmentationType instead for new items
/*
if (rarity != Rarity.CURSED) {
java.util.List<String> effectsList = new java.util.ArrayList<>(ItemEffects.EFFECTS);
java.util.Collections.shuffle(effectsList, random);
int effects = 1;
for (int i = 0; i < effects && i < effectsList.size(); i++) {
lore.add(net.kyori.adventure.text.Component.text(effectsList.get(i)));
}
java.util.List<String> 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(net.kyori.adventure.text.Component.text(skillsList.get(i)));
}
// Old system disabled - use Augmentation system instead
ItemEffects.printDeprecationWarning();
}
*/
// Add note about new augmentation system
if (rarity != Rarity.CURSED) {
lore.add(net.kyori.adventure.text.Component.text("§8Use /augment add to add augmentations"));
}
meta.lore(lore);

View File

@@ -0,0 +1,111 @@
package com.simolzimol.levelcraft.listener;
import com.simolzimol.levelcraft.augmentation.EnhancedItem;
import com.simolzimol.levelcraft.item.Rarity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDropItemEvent;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.world.LootGenerateEvent;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Automatically converts all items to Enhanced Items (Level 1, no augmentations)
* This replaces the old legacy system and ensures all items use the new framework
*/
public class AutoEnhancementListener implements Listener {
private final Random random = new Random();
@EventHandler(priority = EventPriority.HIGH)
public void onItemCraft(CraftItemEvent event) {
ItemStack result = event.getCurrentItem();
if (result == null) return;
// Only enhance items that can have durability (tools, weapons, armor)
if (!isEnhanceable(result)) return;
// Skip if already enhanced
if (EnhancedItem.isEnhanced(result)) return;
// Convert to Enhanced Item with random rarity but Level 1 and no augmentations
Rarity rarity = getRandomRarity();
EnhancedItem enhanced = new EnhancedItem(result, rarity, 1);
event.setCurrentItem(enhanced.getItemStack());
}
@EventHandler(priority = EventPriority.HIGH)
public void onMobDrop(EntityDropItemEvent event) {
ItemStack item = event.getItemDrop().getItemStack();
if (item == null) return;
if (!isEnhanceable(item)) return;
if (EnhancedItem.isEnhanced(item)) return;
// Convert to Enhanced Item
Rarity rarity = getRandomRarity();
EnhancedItem enhanced = new EnhancedItem(item, rarity, 1);
event.getItemDrop().setItemStack(enhanced.getItemStack());
}
@EventHandler(priority = EventPriority.HIGH)
public void onLootGenerate(LootGenerateEvent event) {
List<ItemStack> newLoot = new ArrayList<>();
boolean changed = false;
for (ItemStack item : event.getLoot()) {
if (item == null) {
newLoot.add(item);
continue;
}
if (!isEnhanceable(item) || EnhancedItem.isEnhanced(item)) {
newLoot.add(item);
continue;
}
// Convert to Enhanced Item
Rarity rarity = getRandomRarity();
EnhancedItem enhanced = new EnhancedItem(item, rarity, 1);
newLoot.add(enhanced.getItemStack());
changed = true;
}
if (changed) {
event.setLoot(newLoot);
}
}
/**
* Determines if an item should be enhanced
*/
private boolean isEnhanceable(ItemStack item) {
if (item == null || item.getType().isAir()) return false;
// Only enhance items with durability (tools, weapons, armor)
return item.getType().getMaxDurability() > 0;
}
/**
* Gets a random rarity with weighted distribution
*/
private Rarity getRandomRarity() {
int roll = random.nextInt(1000);
// Weighted rarity distribution using correct Rarity enum values
if (roll < 3) return Rarity.DIVINE; // 0.3%
if (roll < 15) return Rarity.ANCIENT; // 1.2%
if (roll < 40) return Rarity.MYTHIC; // 2.5%
if (roll < 90) return Rarity.LEGENDARY; // 5.0%
if (roll < 170) return Rarity.EPIC; // 8.0%
if (roll < 290) return Rarity.RARE; // 12.0%
if (roll < 490) return Rarity.UNCOMMON; // 20.0%
if (roll < 980) return Rarity.COMMON; // 49.0%
return Rarity.CURSED; // 2.0%
}
}

View File

@@ -14,6 +14,11 @@ public class CraftListener implements Listener {
@EventHandler
public void onCraft(CraftItemEvent event) {
// LEGACY SYSTEM DISABLED - Use new Augmentation System instead
// This old system conflicts with the new EnhancedItem augmentation system
// Players can now use /demo or /augment commands to get enhanced items
/* OLD CODE DISABLED:
ItemStack result = event.getCurrentItem();
if (result == null) return;
if (result.getType().getMaxDurability() <= 0) return;
@@ -23,5 +28,6 @@ public class CraftListener implements Listener {
ItemUtil.assignUniqueId(result);
ItemUtil.addRandomBonuses(result, rarity, random);
event.setCurrentItem(result);
*/
}
}

View File

@@ -0,0 +1,90 @@
package com.simolzimol.levelcraft.listener;
import com.simolzimol.levelcraft.system.ItemLevelingSystem;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.enchantment.EnchantItemEvent;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
/**
* Handles item XP gain from various activities
*/
public class ItemLevelingListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockBreak(BlockBreakEvent event) {
if (event.isCancelled()) return;
Player player = event.getPlayer();
ItemStack tool = player.getInventory().getItemInMainHand();
if (tool == null || tool.getType().isAir()) return;
// Give XP to the tool used
ItemLevelingSystem.addItemXP(tool, ItemLevelingSystem.XP_PER_BLOCK_BROKEN,
player, "Mining");
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityDeath(EntityDeathEvent event) {
Player killer = event.getEntity().getKiller();
if (killer == null) return;
ItemStack weapon = killer.getInventory().getItemInMainHand();
if (weapon == null || weapon.getType().isAir()) return;
// Give XP to the weapon used for killing
ItemLevelingSystem.addItemXP(weapon, ItemLevelingSystem.XP_PER_MOB_KILL,
killer, "Combat");
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityDamage(EntityDamageByEntityEvent event) {
if (event.isCancelled()) return;
if (event.getDamager() instanceof Player player) {
ItemStack weapon = player.getInventory().getItemInMainHand();
if (weapon == null || weapon.getType().isAir()) return;
// Give XP based on damage dealt (small amounts)
double damage = event.getFinalDamage();
int xp = (int) Math.ceil(damage * ItemLevelingSystem.XP_PER_DAMAGE_DEALT);
if (xp > 0) {
ItemLevelingSystem.addItemXP(weapon, xp, player, "Combat");
}
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onCraftItem(CraftItemEvent event) {
if (event.isCancelled()) return;
if (event.getWhoClicked() instanceof Player player) {
ItemStack result = event.getCurrentItem();
if (result == null) return;
// Give XP to crafted items (if they are enhanced)
ItemLevelingSystem.addItemXP(result, ItemLevelingSystem.XP_PER_CRAFT,
player, "Crafting");
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEnchantItem(EnchantItemEvent event) {
if (event.isCancelled()) return;
Player player = event.getEnchanter();
ItemStack item = event.getItem();
// Give significant XP for enchanting
ItemLevelingSystem.addItemXP(item, ItemLevelingSystem.XP_PER_ENCHANT,
player, "Enchanting");
}
}

View File

@@ -57,7 +57,11 @@ public class LootListener implements Listener {
String type = inv.getType().name();
if (!(type.contains("CHEST") || type.contains("BARREL") || type.contains("SHULKER_BOX"))) return;
// Verzögere die Verarbeitung um 1 Tick, damit der Loot generiert wurde
// LEGACY SYSTEM DISABLED - Use new Augmentation System instead
// This old system conflicts with the new EnhancedItem augmentation system
// Use /demo commands to get enhanced items instead
/* OLD CODE DISABLED:
Bukkit.getScheduler().runTaskLater(plugin, () -> {
for (ItemStack item : inv.getContents()) {
if (item == null) continue;
@@ -67,8 +71,7 @@ public class LootListener implements Listener {
if (meta == null) continue;
if (meta.getPersistentDataContainer().has(ItemUtil.getRarityKey(), PersistentDataType.INTEGER)) continue;
// Rarity für Kisten-Loot: -1 bis 5
int rarityValue = random.nextInt(7) - 1; // -1 bis 5
int rarityValue = random.nextInt(7) - 1;
if (rarityValue > 5) rarityValue = 5;
if (rarityValue < -1) rarityValue = -1;
@@ -78,6 +81,7 @@ public class LootListener implements Listener {
ItemUtil.addRandomBonuses(item, rarity, random);
item.setItemMeta(item.getItemMeta());
}
}, 1L); // 1 Tick Verzögerung
}, 1L);
*/
}
}

View File

@@ -14,13 +14,15 @@ public class MobDropListener implements Listener {
@EventHandler
public void onMobDrop(EntityDropItemEvent event) {
// LEGACY SYSTEM DISABLED - Use new Augmentation System instead
// This old system conflicts with the new EnhancedItem augmentation system
// Use DemoAugmentationSystem or manual augmentation commands instead
/* OLD CODE DISABLED:
ItemStack item = event.getItemDrop().getItemStack();
if (item == null) return;
// Optional: Nur für bestimmte Itemtypen, z.B. Waffen, Rüstung, Tools, Bögen, Schilde
// if (!ItemUtil.isWeapon(item) && !ItemUtil.isArmor(item) && !ItemUtil.isTool(item) && !item.getType().name().equals("SHIELD") && !item.getType().name().equals("BOW") && !item.getType().name().equals("CROSSBOW")) return;
int rarityValue = random.nextInt(9) - 1; // -1 bis 7
int rarityValue = random.nextInt(9) - 1;
if (rarityValue > 7) rarityValue = 7;
if (rarityValue < -1) rarityValue = -1;
@@ -29,5 +31,6 @@ public class MobDropListener implements Listener {
ItemUtil.assignUniqueId(item);
ItemUtil.addRandomBonuses(item, rarity, random);
event.getItemDrop().setItemStack(item);
*/
}
}

View File

@@ -31,10 +31,13 @@ public class MobSpawnListener implements Listener {
eq.getLeggings(),
eq.getBoots()
};
// LEGACY SYSTEM DISABLED - Use new Augmentation System instead
// This old system conflicts with the new EnhancedItem augmentation system
/* OLD CODE DISABLED:
for (int i = 0; i < items.length; i++) {
ItemStack item = items[i];
if (item == null || item.getType().isAir()) continue;
// Optional: Filter für Waffen, Bögen, etc.
Rarity rarity = Rarity.getRandomRarity(random, true, 5);
ItemUtil.setRarity(item, rarity);
ItemUtil.assignUniqueId(item);
@@ -48,6 +51,7 @@ public class MobSpawnListener implements Listener {
case 5 -> eq.setBoots(item);
}
}
*/
}, 1L // 1 Tick Verzögerung
);
}

View File

@@ -0,0 +1,141 @@
package com.simolzimol.levelcraft.listener;
import com.simolzimol.levelcraft.player.PlayerLevelManager;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.player.PlayerJoinEvent;
/**
* Listener for player level and XP events
*/
public class PlayerLevelListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
// Initialize player data if needed
PlayerLevelManager.getPlayerLevel(player);
PlayerLevelManager.getPlayerXP(player);
}
@EventHandler(priority = EventPriority.MONITOR)
public void onCraftItem(CraftItemEvent event) {
if (event.isCancelled()) return;
if (event.getWhoClicked() instanceof Player) {
Player player = (Player) event.getWhoClicked();
// Give crafting XP based on item complexity
int xpGain = calculateCraftingXP(event);
if (xpGain > 0) {
PlayerLevelManager.addXP(player, xpGain, "Crafting");
}
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockBreak(BlockBreakEvent event) {
if (event.isCancelled()) return;
Player player = event.getPlayer();
// Give mining XP for certain blocks
int xpGain = calculateMiningXP(event);
if (xpGain > 0) {
PlayerLevelManager.addXP(player, xpGain, "Mining");
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityDeath(EntityDeathEvent event) {
Player killer = event.getEntity().getKiller();
if (killer == null) return;
// Give combat XP based on mob type
int xpGain = calculateCombatXP(event);
if (xpGain > 0) {
PlayerLevelManager.addXP(killer, xpGain, "Combat");
}
}
private int calculateCraftingXP(CraftItemEvent event) {
// Base XP for crafting
int baseXP = 5;
int amount = event.getRecipe().getResult().getAmount();
// More complex recipes give more XP
int ingredientCount = event.getRecipe().getResult().getType().toString().length() / 10; // Simple complexity metric
return Math.max(1, baseXP + ingredientCount) * amount;
}
private int calculateMiningXP(BlockBreakEvent event) {
switch (event.getBlock().getType()) {
case COAL_ORE:
case DEEPSLATE_COAL_ORE:
return 8;
case IRON_ORE:
case DEEPSLATE_IRON_ORE:
return 12;
case GOLD_ORE:
case DEEPSLATE_GOLD_ORE:
return 15;
case REDSTONE_ORE:
case DEEPSLATE_REDSTONE_ORE:
return 10;
case LAPIS_ORE:
case DEEPSLATE_LAPIS_ORE:
return 12;
case DIAMOND_ORE:
case DEEPSLATE_DIAMOND_ORE:
return 25;
case EMERALD_ORE:
case DEEPSLATE_EMERALD_ORE:
return 30;
case ANCIENT_DEBRIS:
return 50;
case STONE:
case DEEPSLATE:
return 1;
case COBBLESTONE:
case COBBLED_DEEPSLATE:
return 1;
default:
return 0;
}
}
private int calculateCombatXP(EntityDeathEvent event) {
switch (event.getEntity().getType()) {
case ZOMBIE:
case SKELETON:
case SPIDER:
return 15;
case CREEPER:
return 20;
case ENDERMAN:
return 25;
case WITCH:
return 18;
case BLAZE:
return 30;
case WITHER_SKELETON:
return 35;
case GHAST:
return 40;
case ENDER_DRAGON:
return 500;
case WITHER:
return 300;
case VILLAGER:
case IRON_GOLEM:
return 0; // No XP for killing friendly mobs
default:
return 10; // Default for other hostile mobs
}
}
}

View File

@@ -24,14 +24,18 @@ public class VillagerTradeListener implements Listener {
Inventory inv = event.getInventory();
if (!(inv instanceof MerchantInventory merchantInventory)) return;
// Neue Rezeptliste
// LEGACY SYSTEM DISABLED - Use new Augmentation System instead
// This old system conflicts with the new EnhancedItem augmentation system
// Use /demo commands or manual augmentation instead
/* OLD CODE DISABLED:
List<MerchantRecipe> newRecipes = new ArrayList<>();
for (MerchantRecipe recipe : merchantInventory.getMerchant().getRecipes()) {
ItemStack result = recipe.getResult().clone();
ItemMeta meta = result.getItemMeta();
if (meta != null && !meta.getPersistentDataContainer().has(ItemUtil.getRarityKey(), PersistentDataType.INTEGER)) {
if (result.getType().getMaxDurability() > 0) {
int rarityValue = random.nextInt(7) - 1; // -1 bis 5
int rarityValue = random.nextInt(7) - 1;
if (rarityValue > 5) rarityValue = 5;
if (rarityValue < -1) rarityValue = -1;
Rarity rarity = Rarity.fromValue(rarityValue);
@@ -40,7 +44,6 @@ public class VillagerTradeListener implements Listener {
ItemUtil.addRandomBonuses(result, rarity, random);
}
}
// Neues Rezept mit gleichem Input, aber modifiziertem Output
MerchantRecipe newRecipe = new MerchantRecipe(result, recipe.getMaxUses());
newRecipe.setIngredients(recipe.getIngredients());
newRecipe.setExperienceReward(recipe.hasExperienceReward());
@@ -49,5 +52,6 @@ public class VillagerTradeListener implements Listener {
newRecipes.add(newRecipe);
}
merchantInventory.getMerchant().setRecipes(newRecipes);
*/
}
}

View File

@@ -0,0 +1,220 @@
package com.simolzimol.levelcraft.player;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class PlayerLevelManager {
private static NamespacedKey playerLevelKey;
private static NamespacedKey playerXpKey;
private static final Map<UUID, Integer> levelCache = new HashMap<>();
private static final Map<UUID, Long> xpCache = new HashMap<>();
public static void init(org.bukkit.plugin.Plugin plugin) {
playerLevelKey = new NamespacedKey(plugin, "player_level");
playerXpKey = new NamespacedKey(plugin, "player_xp");
}
public static int getPlayerLevel(Player player) {
UUID uuid = player.getUniqueId();
// Check cache first
if (levelCache.containsKey(uuid)) {
return levelCache.get(uuid);
}
// Load from persistent data
Integer level = player.getPersistentDataContainer().get(playerLevelKey, PersistentDataType.INTEGER);
if (level == null) {
level = 1; // Starting level
setPlayerLevel(player, level);
}
levelCache.put(uuid, level);
return level;
}
public static void setPlayerLevel(Player player, int level) {
UUID uuid = player.getUniqueId();
level = Math.max(1, level); // Minimum level 1
player.getPersistentDataContainer().set(playerLevelKey, PersistentDataType.INTEGER, level);
levelCache.put(uuid, level);
// Update action bar or send message
player.sendMessage("§6Level up! You are now level " + level + "!");
}
public static long getPlayerXP(Player player) {
UUID uuid = player.getUniqueId();
// Check cache first
if (xpCache.containsKey(uuid)) {
return xpCache.get(uuid);
}
// Load from persistent data
Long xp = player.getPersistentDataContainer().get(playerXpKey, PersistentDataType.LONG);
if (xp == null) {
xp = 0L;
setPlayerXP(player, xp);
}
xpCache.put(uuid, xp);
return xp;
}
public static void setPlayerXP(Player player, long xp) {
UUID uuid = player.getUniqueId();
xp = Math.max(0, xp);
player.getPersistentDataContainer().set(playerXpKey, PersistentDataType.LONG, xp);
xpCache.put(uuid, xp);
}
public static void addPlayerXP(Player player, long xpAmount) {
long currentXp = getPlayerXP(player);
int currentLevel = getPlayerLevel(player);
long newXp = currentXp + xpAmount;
setPlayerXP(player, newXp);
// Check for level up
int newLevel = calculateLevelFromXP(newXp);
if (newLevel > currentLevel) {
setPlayerLevel(player, newLevel);
// Level up effects
player.sendMessage("§a+" + xpAmount + " XP!");
player.playSound(player.getLocation(), org.bukkit.Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.0f);
} else if (xpAmount > 0) {
player.sendMessage("§a+" + xpAmount + " XP!");
}
}
public static long getXPRequiredForLevel(int level) {
// Exponential XP curve: Level^2.5 * 100
return (long) (Math.pow(level, 2.5) * 100);
}
public static int calculateLevelFromXP(long totalXP) {
int level = 1;
while (getXPRequiredForLevel(level + 1) <= totalXP) {
level++;
if (level >= 100) break; // Max level cap
}
return level;
}
public static long getXPToNextLevel(Player player) {
int currentLevel = getPlayerLevel(player);
long currentXP = getPlayerXP(player);
long xpForNextLevel = getXPRequiredForLevel(currentLevel + 1);
return Math.max(0, xpForNextLevel - currentXP);
}
public static double getXPProgressToNextLevel(Player player) {
int currentLevel = getPlayerLevel(player);
long currentXP = getPlayerXP(player);
long xpForCurrentLevel = getXPRequiredForLevel(currentLevel);
long xpForNextLevel = getXPRequiredForLevel(currentLevel + 1);
if (currentLevel >= 100) return 1.0; // Max level
long xpInCurrentLevel = currentXP - xpForCurrentLevel;
long xpNeededForNextLevel = xpForNextLevel - xpForCurrentLevel;
return Math.min(1.0, (double) xpInCurrentLevel / xpNeededForNextLevel);
}
// Calculate max augmentation level based on player and item level
public static int getMaxAugmentationLevel(Player player, int itemLevel, int augmentationMaxLevel) {
int playerLevel = getPlayerLevel(player);
// Formula: (Player Level + Item Level) / 4, capped by augmentation's natural max
int calculatedMax = (playerLevel + itemLevel) / 4;
calculatedMax = Math.max(1, calculatedMax); // At least level 1
return Math.min(calculatedMax, augmentationMaxLevel);
}
/**
* Adds XP to a player with a custom message source
*/
public static void addXP(Player player, int xp, String source) {
if (xp <= 0) return;
long currentXP = getPlayerXP(player);
int currentLevel = getPlayerLevel(player);
// Add the XP
addPlayerXP(player, xp);
// Check if we leveled up
int newLevel = getPlayerLevel(player);
if (newLevel > currentLevel) {
// Level up notification is handled in addPlayerXP
player.sendMessage("§7Source: " + source);
} else {
// Show XP gain message
long newXP = currentXP + xp;
long xpForNext = getXPRequiredForLevel(newLevel + 1);
player.sendMessage("§a+" + xp + " XP §7(" + source + ") §8[" +
newXP + "/" + xpForNext + "]");
}
}
// Grant XP for various activities
public static void giveXPForCrafting(Player player) {
addPlayerXP(player, 10 + (getPlayerLevel(player) * 2));
}
public static void giveXPForKill(Player player, org.bukkit.entity.EntityType entityType) {
long baseXP = switch (entityType) {
case ZOMBIE, SKELETON, SPIDER -> 5;
case CREEPER, ENDERMAN -> 10;
case BLAZE, WITHER_SKELETON -> 15;
case ENDER_DRAGON -> 1000;
case WITHER -> 500;
default -> 3;
};
addPlayerXP(player, baseXP + (getPlayerLevel(player) / 2));
}
public static void giveXPForMining(Player player, org.bukkit.Material material) {
long baseXP = switch (material) {
case COAL_ORE, DEEPSLATE_COAL_ORE -> 2;
case IRON_ORE, DEEPSLATE_IRON_ORE -> 3;
case GOLD_ORE, DEEPSLATE_GOLD_ORE -> 4;
case DIAMOND_ORE, DEEPSLATE_DIAMOND_ORE -> 8;
case EMERALD_ORE, DEEPSLATE_EMERALD_ORE -> 10;
case ANCIENT_DEBRIS -> 15;
default -> 1;
};
addPlayerXP(player, baseXP);
}
// Clear cache when player leaves
public static void clearCache(Player player) {
UUID uuid = player.getUniqueId();
levelCache.remove(uuid);
xpCache.remove(uuid);
}
// Get level info for display
public static String getLevelInfo(Player player) {
int level = getPlayerLevel(player);
long xpToNext = getXPToNextLevel(player);
double progress = getXPProgressToNextLevel(player) * 100;
return String.format("§6Level %d §7(%.1f%% to next) §8- %d XP needed",
level, progress, xpToNext);
}
}

View File

@@ -0,0 +1,196 @@
package com.simolzimol.levelcraft.system;
import com.simolzimol.levelcraft.augmentation.EnhancedItem;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
/**
* System for item leveling and XP management
* Items gain XP through usage and level up to unlock more augmentation slots
*/
public class ItemLevelingSystem {
// XP constants for different activities
public static final int XP_PER_BLOCK_BROKEN = 2;
public static final int XP_PER_MOB_KILL = 5;
public static final int XP_PER_DAMAGE_DEALT = 1;
public static final int XP_PER_CRAFT = 3;
public static final int XP_PER_ENCHANT = 10;
// Level up thresholds (exponential growth)
private static final int BASE_XP_REQUIREMENT = 100;
private static final double XP_MULTIPLIER = 1.5;
/**
* Adds XP to an item and handles level ups
* @param item The item to add XP to
* @param xp Amount of XP to add
* @param player The player using the item (for notifications)
* @param activity Description of the activity
* @return True if the item leveled up
*/
public static boolean addItemXP(ItemStack item, int xp, Player player, String activity) {
if (item == null || !EnhancedItem.isEnhanced(item)) {
return false;
}
EnhancedItem enhanced = EnhancedItem.fromItemStack(item);
if (enhanced == null) return false;
// Get current XP and level
long currentXP = enhanced.getItemXP();
int currentLevel = enhanced.getItemLevel();
// Add XP
long newXP = currentXP + xp;
enhanced.setItemXP(newXP);
// Check for level up
int newLevel = calculateLevelFromXP(newXP);
boolean leveledUp = false;
if (newLevel > currentLevel) {
enhanced.setItemLevel(newLevel);
leveledUp = true;
// Notify player of level up
notifyItemLevelUp(player, enhanced, currentLevel, newLevel, activity);
// Update the item in player's inventory
updateItemInInventory(player, item, enhanced.getItemStack());
} else if (xp > 0) {
// Just show XP gain
long xpForNext = getXPRequiredForLevel(newLevel + 1);
player.sendMessage("§7+" + xp + " Item XP §8(" + activity + ") §7[" +
newXP + "/" + xpForNext + "]");
// Update the item in player's inventory
updateItemInInventory(player, item, enhanced.getItemStack());
}
return leveledUp;
}
/**
* Calculates the required XP for a specific level
*/
public static long getXPRequiredForLevel(int level) {
if (level <= 1) return 0;
return (long) (BASE_XP_REQUIREMENT * Math.pow(XP_MULTIPLIER, level - 2));
}
/**
* Calculates the level from total XP
*/
public static int calculateLevelFromXP(long totalXP) {
int level = 1;
long requiredXP = 0;
while (requiredXP <= totalXP) {
level++;
requiredXP = getXPRequiredForLevel(level);
}
return level - 1; // Return the highest level we can afford
}
/**
* Gets the maximum level an item can reach (based on rarity)
*/
public static int getMaxItemLevel(com.simolzimol.levelcraft.item.Rarity rarity) {
return switch (rarity) {
case CURSED -> 5; // Limited growth
case COMMON -> 10; // Basic cap
case UNCOMMON -> 15; // Moderate cap
case RARE -> 25; // Good cap
case EPIC -> 40; // High cap
case LEGENDARY -> 60; // Very high cap
case MYTHIC -> 80; // Extreme cap
case ANCIENT -> 100; // Maximum for Ancient
case DIVINE -> 120; // Ultimate cap for Divine
};
}
/**
* Notifies the player of an item level up
*/
private static void notifyItemLevelUp(Player player, EnhancedItem enhanced,
int oldLevel, int newLevel, String activity) {
// Title notification
player.sendTitle(
"§6§lITEM LEVEL UP!",
enhanced.getRarity().getDisplayName() + " §7→ §6Level " + newLevel,
10, 30, 10
);
// Chat notification
player.sendMessage("§a▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
player.sendMessage("§a§l ITEM LEVEL UP!");
player.sendMessage("§e " + enhanced.getRarity().getDisplayName() + " §eitem leveled up!");
player.sendMessage("§7 Level " + oldLevel + " → §6Level " + newLevel);
player.sendMessage("§7 Activity: §f" + activity);
// Check if new augmentation slots unlocked
int oldSlots = calculateSlotsForLevel(oldLevel);
int newSlots = calculateSlotsForLevel(newLevel);
if (newSlots > oldSlots) {
int unlockedSlots = newSlots - oldSlots;
player.sendMessage("§a ✦ Unlocked " + unlockedSlots + " new augmentation slot" +
(unlockedSlots > 1 ? "s" : "") + "!");
}
player.sendMessage("§a▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬");
// Sound effect
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f);
}
/**
* Calculates how many augmentation slots should be available at a given level
*/
public static int calculateSlotsForLevel(int level) {
// Start with 2 slots, gain 1 slot every 5 levels
int baseSlots = 2;
int bonusSlots = Math.max(0, (level - 1) / 5);
return Math.min(baseSlots + bonusSlots, 8); // Cap at 8 slots max
}
/**
* Updates an item in the player's inventory
*/
private static void updateItemInInventory(Player player, ItemStack oldItem, ItemStack newItem) {
// Find the item in inventory and replace it
for (int slot = 0; slot < player.getInventory().getSize(); slot++) {
ItemStack slotItem = player.getInventory().getItem(slot);
if (slotItem != null && slotItem.equals(oldItem)) {
player.getInventory().setItem(slot, newItem);
break;
}
}
// Also check main hand
if (player.getInventory().getItemInMainHand().equals(oldItem)) {
player.getInventory().setItemInMainHand(newItem);
}
// And off hand
if (player.getInventory().getItemInOffHand().equals(oldItem)) {
player.getInventory().setItemInOffHand(newItem);
}
}
/**
* Gets the XP progress towards the next level as a percentage
*/
public static double getXPProgressPercentage(long currentXP, int currentLevel) {
long xpForCurrentLevel = currentLevel > 1 ? getXPRequiredForLevel(currentLevel) : 0;
long xpForNextLevel = getXPRequiredForLevel(currentLevel + 1);
long xpInCurrentLevel = currentXP - xpForCurrentLevel;
long xpNeededForNext = xpForNextLevel - xpForCurrentLevel;
return (double) xpInCurrentLevel / xpNeededForNext;
}
}