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:
16
plugin.yml
16
plugin.yml
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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%
|
||||
}
|
||||
}
|
||||
162
src/main/java/com/simolzimol/levelcraft/command/DemoCommand.java
Normal file
162
src/main/java/com/simolzimol/levelcraft/command/DemoCommand.java
Normal 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];
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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%
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user