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 }