package org.shininet.bukkit.itemrenamer;
import java.util.List;
import net.milkbowl.vault.chat.Chat;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.shininet.bukkit.itemrenamer.SerializeItemStack.StackField;
import org.shininet.bukkit.itemrenamer.api.ItemsListener;
import org.shininet.bukkit.itemrenamer.api.RenamerSnapshot;
import org.shininet.bukkit.itemrenamer.configuration.DamageLookup;
import org.shininet.bukkit.itemrenamer.configuration.ItemRenamerConfiguration;
import org.shininet.bukkit.itemrenamer.configuration.RenameConfiguration;
import org.shininet.bukkit.itemrenamer.configuration.RenameRule;
import org.shininet.bukkit.itemrenamer.meta.NiceBookMeta;
import org.shininet.bukkit.itemrenamer.meta.NiceItemMeta;
import org.shininet.bukkit.itemrenamer.wrappers.LeveledEnchantment;
import com.google.common.collect.Lists;
public class RenameProcessor extends AbstractRenameProcessor {
/**
* Storage of the original ItemMeta.
*/
private static final String KEY_ORIGINAL = "com.comphenix.original";
// Configuration
private final ItemRenamerConfiguration config;
// Vault
private final Chat chat;
// Listeners
private RenameListenerManager listenerMananger;
/**
* Construct a new rename processor.
* <p>
* The Vault chat layer is used to retrieve per-player configuration.
* @param listenerManager - the listener manager.
* @param config - the current configuration.
* @param chat - the current Vault chat abstraction layer.
*/
RenameProcessor(RenameListenerManager listenerMananger, ItemRenamerConfiguration config, Chat chat) {
super(KEY_ORIGINAL);
this.listenerMananger = listenerMananger;
this.config = config;
this.chat = chat;
}
/**
* Create a item stack serializer that doesn't preserve the count field.
* @return The serializer.
*/
public static SerializeItemStack createSerializer() {
SerializeItemStack serializer = new SerializeItemStack();
serializer.removeField(StackField.COUNT);
return serializer;
}
/**
* Retrieve the current listener manager.
* @return The listener manager.
*/
public RenameListenerManager getListenerMananger() {
return listenerMananger;
}
/**
* Process the name on the given item meta.
* @param itemMeta - the item meta.
* @param rule - the name rule to apply.
*/
private void packName(NiceItemMeta itemMeta, RenameRule rule) {
if (rule.getName() != null) {
itemMeta.setDisplayName(ChatColor.RESET +
ChatColor.translateAlternateColorCodes('&', rule.getName()) + ChatColor.RESET);
}
}
/**
* Process lore on the given item meta.
* @param itemMeta - the item meta.
* @param rule - the lore rule to apply.
*/
private void packLore(NiceItemMeta itemMeta, RenameRule rule) {
// Don't process empty rules
if (rule.getLoreSections().size() == 0)
return;
List<String> output = Lists.newArrayList(rule.getLoreSections());
// Translate color codes as well
for (int i = 0; i < output.size(); i++) {
output.set(i, ChatColor.translateAlternateColorCodes('&', output.get(i)) + ChatColor.RESET);
}
itemMeta.setLore(output);
}
/**
* Retrieve the associated rule for the given pack and item stack.
* <p>
* This will first look for exact rules, then damage lookup rules.
* @param pack - the rename pack.
* @param input - the item stack.
* @return The associated rule, or NULL if not found.
*/
public RenameRule getRule(String pack, ItemStack input) {
// They have no rule
if (pack == null || input == null)
return null;
RenameConfiguration renameConfig = config.getRenameConfig();
// Make sure there is an associated pack
if (renameConfig.hasPack(pack)) {
RenameRule exactRule = renameConfig.getExact(pack).getRule(input);
// Exact item stacks has priority
if (exactRule != null) {
return exactRule;
}
// Next look at ranged rename rules
DamageLookup lookup = renameConfig.getLookup(pack, input.getTypeId());
if (lookup != null) {
return lookup.getRule(input.getDurability());
}
}
return null;
}
/**
* Rename or append lore to the given item stack.
* @param input - the item stack.
* @param rule - the rename rule to apply.
* @return The renamed item stacks.
*/
public ItemStack processRule(ItemStack stack, RenameRule rule) {
NiceItemMeta niceMeta = NiceItemMeta.fromStack(stack);
// Fix a client bug
if (niceMeta instanceof NiceBookMeta) {
NiceBookMeta bookMeta = (NiceBookMeta) niceMeta;
// Create the pages NBT tag
if (bookMeta.getPageCount() == 0) {
bookMeta.setPages("");
}
}
// No need to rename these types
if (rule == null)
return stack;
if (rule.isSkippingCustomNamed() && (niceMeta.hasDisplayName()) || (niceMeta.hasLore()))
return stack;
// Don't overwrite custom NBT tags if we can help it
packName(niceMeta, rule);
packLore(niceMeta, rule);
stack = niceMeta.getStack();
// Remove or add enchantments
for (LeveledEnchantment removed : rule.getDechantments()) {
stack = removed.getEnchanter().disenchant(stack);
}
for (LeveledEnchantment added : rule.getEnchantments()) {
stack = added.getEnchanter().enchant(stack);
}
return stack;
}
@Override
protected void processSnapshot(Player player, RenamerSnapshot snapshot) {
final RenameRule[] rules = new RenameRule[snapshot.size()];
final String pack = getPack(player);
// Retrieve the rename rule for each item stack
for (int i = 0; i < rules.length; i++) {
rules[i] = getRule(pack, snapshot.getSlot(i));
}
listenerMananger.setRenamerListener(new ItemsListener() {
@Override
public void onItemsSending(Player player, RenamerSnapshot snapshot) {
for (int i = 0; i < rules.length; i++) {
ItemStack input = snapshot.getSlot(i);
RenameRule rule = rules[i];
if (input != null) {
snapshot.setSlot(i, processRule(input, rule));
}
}
}
});
// Invoke other plugins
listenerMananger.invokeListeners(player, snapshot);
}
/**
* Retrieve the associated rename pack for a given player.
* <p>
* This may depend on the current world the player is located in.
* @param player - the player to look up.
* @return The name of the rename pack.
*/
public String getPack(Player player) {
if (chat != null) {
String pack = chat.getPlayerInfoString(player, "itempack", null);
// Use this pack instead
if (pack != null && pack.length() > 0)
return pack;
}
return config.getEffectiveWorldPack(player.getWorld().getName());
}
}