package com.volmit.iris.object; import java.awt.Color; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.material.Colorable; import com.volmit.iris.Iris; import com.volmit.iris.gen.atomics.AtomicCache; import com.volmit.iris.noise.CNG; import com.volmit.iris.util.ArrayType; import com.volmit.iris.util.B; import com.volmit.iris.util.C; import com.volmit.iris.util.Desc; import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.Form; import com.volmit.iris.util.KList; import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.RNG; import com.volmit.iris.util.RegistryListItemType; import com.volmit.iris.util.Required; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; @Accessors(chain = true) @NoArgsConstructor @AllArgsConstructor @Desc("Represents a loot entry") @Data public class IrisLoot { @DontObfuscate @Desc("The target inventory slot types to fill this loot with") private InventorySlotType slotTypes = InventorySlotType.STORAGE; @MinNumber(1) @DontObfuscate @Desc("The sub rarity of this loot. Calculated after this loot table has been picked.") private int rarity = 1; @MinNumber(1) @DontObfuscate @Desc("Minimum amount of this loot") private int minAmount = 1; @MinNumber(1) @DontObfuscate @Desc("Maximum amount of this loot") private int maxAmount = 1; @MinNumber(1) @DontObfuscate @Desc("The display name of this item") private String displayName = null; @MinNumber(0) @MaxNumber(1) @DontObfuscate @Desc("Minimum durability percent") private double minDurability = 0; @MinNumber(0) @MaxNumber(1) @DontObfuscate @Desc("Maximum durability percent") private double maxDurability = 1; @DontObfuscate @Desc("Define a custom model identifier 1.14+ only") private Integer customModel = null; @DontObfuscate @Desc("Set this to true to prevent it from being broken") private boolean unbreakable = false; @ArrayType(min = 1, type = ItemFlag.class) @DontObfuscate @Desc("The item flags to add") private KList itemFlags = new KList<>(); @DontObfuscate @Desc("Apply enchantments to this item") @ArrayType(min = 1, type = IrisEnchantment.class) private KList enchantments = new KList<>(); @DontObfuscate @Desc("Apply attribute modifiers to this item") @ArrayType(min = 1, type = IrisAttributeModifier.class) private KList attributes = new KList<>(); @ArrayType(min = 1, type = String.class) @DontObfuscate @Desc("Add lore to this item") private KList lore = new KList<>(); @RegistryListItemType @Required @DontObfuscate @Desc("This is the item or block type. Does not accept minecraft:*. Only materials such as DIAMOND_SWORD or DIRT.") private String type = ""; @DontObfuscate @Desc("The dye color") private DyeColor dyeColor = null; @DontObfuscate @Desc("The leather armor color") private String leatherColor = null; private final transient AtomicCache chance = new AtomicCache<>(); public Material getType() { return B.getMaterial(type); } public ItemStack get(boolean debug, RNG rng) { try { ItemStack is = new ItemStack(getType(), Math.max(1, rng.i(getMinAmount(), getMaxAmount()))); ItemMeta m = is.getItemMeta(); if(getType().getMaxDurability() > 0 && m instanceof Damageable) { Damageable d = (Damageable) m; int max = getType().getMaxDurability(); d.setDamage((int) Math.round(Math.max(0, Math.min(max, (1D - rng.d(getMinDurability(), getMaxDurability())) * max)))); } for(IrisEnchantment i : getEnchantments()) { i.apply(rng, m); } for(IrisAttributeModifier i : getAttributes()) { i.apply(rng, m); } if(Iris.customModels) { m.setCustomModelData(getCustomModel()); } m.setLocalizedName(C.translateAlternateColorCodes('&', displayName)); m.setDisplayName(C.translateAlternateColorCodes('&', displayName)); m.setUnbreakable(isUnbreakable()); for(ItemFlag i : getItemFlags()) { m.addItemFlags(i); } KList lore = new KList<>(); getLore().forEach((i) -> { String mf = C.translateAlternateColorCodes('&', i); if(mf.length() > 24) { for(String g : Form.wrapWords(mf, 24).split("\\Q\n\\E")) { lore.add(g.trim()); } } else { lore.add(mf); } }); if(debug) { if(lore.isNotEmpty()) { lore.add(C.GRAY + "--------------------"); } lore.add(C.GRAY + "1 in " + (getRarity()) + " Chance (" + Form.pc(1D / (getRarity()), 5) + ")"); } m.setLore(lore); if(getLeatherColor() != null && m instanceof LeatherArmorMeta) { Color c = Color.decode(getLeatherColor()); ((LeatherArmorMeta) m).setColor(org.bukkit.Color.fromRGB(c.getRed(), c.getGreen(), c.getBlue())); } if(getDyeColor() != null && m instanceof Colorable) { ((Colorable) m).setColor(getDyeColor()); } is.setItemMeta(m); return is; } catch(Throwable e) { } return new ItemStack(Material.AIR); } public ItemStack get(boolean debug, boolean giveSomething, IrisLootTable table, RNG rng, int x, int y, int z) { if(debug) { chance.reset(); } if(giveSomething || chance.aquire(() -> NoiseStyle.STATIC.create(rng)).fit(1, rarity * table.getRarity(), x, y, z) == 1) { if(getType() == null) { Iris.warn("Cant find item type " + type); return null; } try { ItemStack is = new ItemStack(getType(), Math.max(1, rng.i(getMinAmount(), getMaxAmount()))); ItemMeta m = is.getItemMeta(); if(getType().getMaxDurability() > 0 && m instanceof Damageable) { Damageable d = (Damageable) m; int max = getType().getMaxDurability(); d.setDamage((int) Math.round(Math.max(0, Math.min(max, (1D - rng.d(getMinDurability(), getMaxDurability())) * max)))); } for(IrisEnchantment i : getEnchantments()) { i.apply(rng, m); } for(IrisAttributeModifier i : getAttributes()) { i.apply(rng, m); } if(Iris.customModels) { m.setCustomModelData(getCustomModel()); } m.setLocalizedName(C.translateAlternateColorCodes('&', displayName)); m.setDisplayName(C.translateAlternateColorCodes('&', displayName)); m.setUnbreakable(isUnbreakable()); for(ItemFlag i : getItemFlags()) { m.addItemFlags(i); } KList lore = new KList<>(); getLore().forEach((i) -> { String mf = C.translateAlternateColorCodes('&', i); if(mf.length() > 24) { for(String g : Form.wrapWords(mf, 24).split("\\Q\n\\E")) { lore.add(g.trim()); } } else { lore.add(mf); } }); if(debug) { if(lore.isNotEmpty()) { lore.add(C.GRAY + "--------------------"); } lore.add(C.GRAY + "From: " + table.getName() + " (" + Form.pc(1D / table.getRarity(), 5) + ")"); lore.add(C.GRAY + "1 in " + (table.getRarity() * getRarity()) + " Chance (" + Form.pc(1D / (table.getRarity() * getRarity()), 5) + ")"); } m.setLore(lore); is.setItemMeta(m); return is; } catch(Throwable e) { } } return null; } }