001    package org.bukkit.command.defaults;
002    
003    import java.util.ArrayList;
004    import java.util.Collections;
005    import java.util.List;
006    import java.util.Map;
007    
008    import org.apache.commons.lang.Validate;
009    import org.apache.commons.lang.WordUtils;
010    import com.google.common.collect.ImmutableList;
011    
012    import org.bukkit.Bukkit;
013    import org.bukkit.ChatColor;
014    import org.bukkit.Material;
015    import org.bukkit.command.Command;
016    import org.bukkit.command.CommandSender;
017    import org.bukkit.enchantments.Enchantment;
018    import org.bukkit.entity.Player;
019    import org.bukkit.inventory.ItemStack;
020    import org.bukkit.util.StringUtil;
021    
022    public class EnchantCommand extends VanillaCommand {
023        private static final List<String> ENCHANTMENT_NAMES = new ArrayList<String>();
024    
025        public EnchantCommand() {
026            super("enchant");
027            this.description = "Adds enchantments to the item the player is currently holding. Specify 0 for the level to remove an enchantment. Specify force to ignore normal enchantment restrictions";
028            this.usageMessage = "/enchant <player> <enchantment> [level|max|0] [force]";
029            this.setPermission("bukkit.command.enchant");
030        }
031    
032        @Override
033        public boolean execute(CommandSender sender, String commandLabel, String[] args) {
034            if (!testPermission(sender)) return true;
035            if (args.length < 2) {
036                sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
037                return false;
038            }
039    
040            boolean force = false;
041            if (args.length > 2) {
042                force = args[args.length > 3 ? 3 : 2].equalsIgnoreCase("force");
043            }
044    
045            Player player = Bukkit.getPlayerExact(args[0]);
046            if (player == null) {
047                sender.sendMessage("Can't find player " + args[0]);
048            } else {
049                ItemStack item = player.getItemInHand();
050                if (item.getType() == Material.AIR) {
051                    sender.sendMessage("The player isn't holding an item");
052                } else {
053                    String itemName = item.getType().toString().replaceAll("_", " ");
054                    itemName = WordUtils.capitalizeFully(itemName);
055    
056                    Enchantment enchantment = getEnchantment(args[1].toUpperCase());
057                    if (enchantment == null) {
058                        sender.sendMessage(String.format("Enchantment does not exist: %s", args[1]));
059                    }  else {
060                        String enchantmentName = enchantment.getName().replaceAll("_", " ");
061                        enchantmentName = WordUtils.capitalizeFully(enchantmentName);
062    
063                        if (!force && !enchantment.canEnchantItem(item)) {
064                            sender.sendMessage(String.format("%s cannot be applied to %s", enchantmentName, itemName));
065                        } else {
066                            int level = 1;
067                            if (args.length > 2) {
068                                Integer integer = getInteger(args[2]);
069                                int minLevel = enchantment.getStartLevel();
070                                int maxLevel = force ? Short.MAX_VALUE : enchantment.getMaxLevel();
071    
072                                if (integer != null) {
073                                    if (integer == 0) {
074                                        item.removeEnchantment(enchantment);
075                                        Command.broadcastCommandMessage(sender, String.format("Removed %s on %s's %s", enchantmentName, player.getName(), itemName));
076                                        return true;
077                                    }
078    
079                                    if (integer < minLevel || integer > maxLevel) {
080                                        sender.sendMessage(String.format("Level for enchantment %s must be between %d and %d", enchantmentName, minLevel, maxLevel));
081                                        sender.sendMessage("Specify 0 for level to remove an enchantment");
082                                        return true;
083                                    }
084    
085                                    level = integer;
086                                }
087    
088                                if ("max".equals(args[2])) {
089                                    level = maxLevel;
090                                }
091                            }
092    
093                            Map<Enchantment, Integer> enchantments = item.getEnchantments();
094                            boolean conflicts = false;
095    
096                            if (!force && !enchantments.isEmpty()) { // TODO: Improve this to use a "hasEnchantments" call
097                                for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
098                                    Enchantment enchant = entry.getKey();
099    
100                                    if (enchant.equals(enchantment)) continue;
101                                    if (enchant.conflictsWith(enchantment)) {
102                                        sender.sendMessage(String.format("Can't apply the enchantment %s on an item with the enchantment %s", enchantmentName, WordUtils.capitalizeFully(enchant.getName().replaceAll("_", " "))));
103                                        conflicts = true;
104                                        break;
105                                    }
106                                }
107                            }
108    
109                            if (!conflicts) {
110                                item.addUnsafeEnchantment(enchantment, level);
111    
112                                Command.broadcastCommandMessage(sender, String.format("Applied %s (Lvl %d) on %s's %s", enchantmentName, level, player.getName(), itemName), false);
113                                sender.sendMessage(String.format("Enchanting succeeded, applied %s (Lvl %d) onto your %s", enchantmentName, level, itemName));
114                            }
115                        }
116                    }
117                }
118            }
119            return true;
120        }
121    
122         @Override
123        public List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
124            Validate.notNull(sender, "Sender cannot be null");
125            Validate.notNull(args, "Arguments cannot be null");
126            Validate.notNull(alias, "Alias cannot be null");
127    
128            if (args.length == 1) {
129                return super.tabComplete(sender, alias, args);
130            }
131    
132            if (args.length == 2) {
133                return StringUtil.copyPartialMatches(args[1], ENCHANTMENT_NAMES, new ArrayList<String>(ENCHANTMENT_NAMES.size()));
134            }
135    
136            if (args.length == 3 || args.length == 4) {
137                if (!args[args.length - 2].equalsIgnoreCase("force")) {
138                    return ImmutableList.of("force");
139                }
140            }
141    
142            return ImmutableList.of();
143         }
144    
145        private Enchantment getEnchantment(String lookup) {
146            Enchantment enchantment = Enchantment.getByName(lookup);
147    
148            if (enchantment == null) {
149                Integer id = getInteger(lookup);
150                if (id != null) {
151                    enchantment = Enchantment.getById(id);
152                }
153            }
154    
155            return enchantment;
156        }
157    
158        public static void buildEnchantments() {
159            if (!ENCHANTMENT_NAMES.isEmpty()) {
160                throw new IllegalStateException("Enchantments have already been built!");
161            }
162    
163            for (Enchantment enchantment : Enchantment.values()) {
164                ENCHANTMENT_NAMES.add(enchantment.getName());
165            }
166    
167            Collections.sort(ENCHANTMENT_NAMES);
168        }
169    }