- Added selling/buying of Enchanted items

- Modified /iteminfo command to show enchantments (and their id)
- Fixed LWC problem
- Added an option to ignore creative mode
- Fixed broken inventory.addItem(ItemStack) (adds up to custom Material max stack amount now) @Bukkit
This commit is contained in:
Acrobot 2011-12-16 17:20:09 +01:00
parent 353dacf1a0
commit 2e489774d8
11 changed files with 189 additions and 63 deletions

View File

@ -10,7 +10,6 @@ import com.Acrobot.ChestShop.DB.Queue;
import com.Acrobot.ChestShop.DB.Transaction;
import com.Acrobot.ChestShop.Listeners.*;
import com.Acrobot.ChestShop.Logging.FileWriterQueue;
import com.Acrobot.ChestShop.Protection.MaskChest;
import com.avaje.ebean.EbeanServer;
import com.lennardf1989.bukkitex.Database;
import org.bukkit.Server;
@ -59,7 +58,8 @@ public class ChestShop extends JavaPlugin {
if (Config.getBoolean(Property.LOG_TO_DATABASE) || Config.getBoolean(Property.GENERATE_STATISTICS_PAGE)) setupDB();
if (Config.getBoolean(Property.GENERATE_STATISTICS_PAGE)) scheduleTask(new Generator(), 300L, (long) Config.getDouble(Property.STATISTICS_PAGE_GENERATION_INTERVAL) * 20L);
if (Config.getBoolean(Property.LOG_TO_FILE)) scheduleTask(new FileWriterQueue(), 201L, 201L);
if (Config.getBoolean(Property.MASK_CHESTS_AS_OTHER_BLOCKS)) scheduleTask(new MaskChest(), 40L, 40L);
//if (Config.getBoolean(Property.MASK_CHESTS_AS_OTHER_BLOCKS)) scheduleTask(new MaskChest(), 40L, 40L); //Disabled due to bug //TODO Fix that
playerInteract.interval = Config.getInteger(Property.SHOP_INTERACTION_INTERVAL);
//Register our commands!
getCommand("iteminfo").setExecutor(new ItemInfo());

View File

@ -3,14 +3,19 @@ package com.Acrobot.ChestShop.Commands;
import com.Acrobot.ChestShop.Config.Config;
import com.Acrobot.ChestShop.Config.Language;
import com.Acrobot.ChestShop.Items.Items;
import com.Acrobot.ChestShop.Utils.uEnchantment;
import com.Acrobot.ChestShop.Utils.uSign;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
/**
* @author Acrobot
*/
@ -21,14 +26,41 @@ public class ItemInfo implements CommandExecutor {
if (!(sender instanceof Player)) return false;
item = ((Player) sender).getItemInHand();
} else {
item = Items.getItemStack(args[0]);
item = Items.getItemStack(joinArray(args));
}
if (item == null || item.getType() == Material.AIR) return false;
String durability = (item.getDurability() != 0 ? ChatColor.DARK_GREEN + ":" + item.getDurability() : "");
String ench = uEnchantment.getEnchantment(item);
String enchantment = (ench != null ? ChatColor.DARK_AQUA + "-" + ench : "");
sender.sendMessage(Config.getLocal(Language.iteminfo));
sender.sendMessage(item.getTypeId() + (item.getDurability() != 0 ? " : " + item.getDurability() : "") + " - " + ChatColor.GRAY + item.getType().name());
sender.sendMessage(ChatColor.GRAY + uSign.capitalizeFirst(item.getType().name())
+ ChatColor.WHITE + " " + item.getTypeId() + durability + enchantment + ChatColor.WHITE);
Map<Enchantment, Integer> map = item.getEnchantments();
for (Map.Entry<Enchantment, Integer> e : map.entrySet())
sender.sendMessage(ChatColor.DARK_GRAY + uSign.capitalizeFirst(e.getKey().getName()) + ' ' + intToRoman(e.getValue()));
return true;
}
private static String intToRoman(int integer){
if (integer == 1) return "I";
if (integer == 2) return "II";
if (integer == 3) return "III";
if (integer == 4) return "IV";
if (integer == 5) return "V";
return null;
}
private static String joinArray(String[] array){
StringBuilder b = new StringBuilder(array.length);
for (String s : array) b.append(s).append(' ');
return b.toString();
}
}

View File

@ -21,7 +21,8 @@ public enum Property {
USE_BUILT_IN_PROTECTION(true, "Do you want to use built-in protection against chest destruction?"),
PROTECT_CHEST_WITH_LWC(false, "Do you want to protect shop chests with LWC?"),
PROTECT_SIGN_WITH_LWC(false, "Do you want to protect shop signs with LWC?"),
MASK_CHESTS_AS_OTHER_BLOCKS(false, "Do you want to mask shop chests as other blocks? HIGHLY EXPERIMENTAL, CAN LAG!"),
//MASK_CHESTS_AS_OTHER_BLOCKS(false, "Do you want to mask shop chests as other blocks? HIGHLY EXPERIMENTAL, CAN LAG!"),
IGNORE_CREATIVE_MODE(true, "Do you want to allow using shops to people in creative mode?"),
SHOW_MESSAGE_OUT_OF_STOCK(true, "Do you want to show \"Out of stock\" messages?"),
SHOW_TRANSACTION_INFORMATION_CLIENT(true, "Do you want to show \"You bought/sold... \" messages?"),
SHOW_TRANSACTION_INFORMATION_OWNER(true, "Do you want to show \"Somebody bought/sold... \" messages?"),
@ -29,7 +30,8 @@ public enum Property {
WORLDGUARD_INTEGRATION(false, "Do you want to only let people build inside plots?"),
TAX_AMOUNT(0, "Percent of the price that should go to the server's account. (100 = 100 percent)"),
SHOP_REFUND_PRICE(0, "How much money do you get back when destroying a sign?"),
ALLOW_MULTIPLE_SHOPS_AT_ONE_BLOCK(false, "Do you want to allow other players to build a shop on a block where there's one already?");
ALLOW_MULTIPLE_SHOPS_AT_ONE_BLOCK(false, "Do you want to allow other players to build a shop on a block where there's one already?"),
SHOP_INTERACTION_INTERVAL(100, "(In 1/1000th of a second) How often can a player use a shop sign?");
private final Object value;

View File

@ -1,9 +1,13 @@
package com.Acrobot.ChestShop.Items;
import com.Acrobot.ChestShop.Utils.uEnchantment;
import com.Acrobot.ChestShop.Utils.uNumber;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
/**
* @author Acrobot
* Manages ItemStack names and ID's
@ -31,33 +35,42 @@ public class Items {
public static ItemStack getItemStack(String itemName) {
ItemStack toReturn = getFromOddItem(itemName);
if (toReturn != null) return toReturn;
String[] split = itemName.split(":|-");
Material material = getMaterial(itemName);
if (material != null) return new ItemStack(material, 1);
String[] space = split[0].split(" ");
Material material = getMaterial(split[0]);
return getItemStackWithDataValue(itemName);
for (int i = (space.length > 1 ? 1 : 0); i >= 0 && material == null; i--) material = getMaterial(space[i]);
if (material == null) return null;
toReturn = new ItemStack(material, 1);
for (int i = 1; i < split.length; i++){
split[i] = split[i].trim();
if (uNumber.isInteger(split[i])) toReturn.setDurability((short) Integer.parseInt(split[i]));
else {
try{ toReturn.addEnchantments(getEnchantment(split[i]));
} catch (Exception ignored){}
}
}
short data = getDataFromWord(space[0], material);
if (data != 0) toReturn.setDurability(data);
return toReturn;
}
private static Map<Enchantment, Integer> getEnchantment(String itemName){
return uEnchantment.decodeEnchantment(itemName);
}
private static ItemStack getFromOddItem(String itemName) {
return !Odd.isInitialized() ? null : Odd.returnItemStack(itemName.replace(":", ";"));
}
private static ItemStack getItemStackWithDataValue(String itemName) {
if (!itemName.contains(":")) return getItemStackWithDataValueFromWord(itemName);
String[] word = itemName.split(":");
if (word.length < 2 || !uNumber.isInteger(word[1])) return null;
Material item = getMaterial(word[0]);
return item == null ? null : new ItemStack(item, 1, Short.parseShort(word[1]));
}
private static ItemStack getItemStackWithDataValueFromWord(String itemName) {
int indexOfChar = itemName.indexOf(' ');
if (indexOfChar == -1) return null;
Material item = getMaterial(itemName.substring(indexOfChar));
return item == null ? null : new ItemStack(item, 1, DataValue.get(itemName.substring(0, indexOfChar), item));
private static short getDataFromWord(String name, Material material) {
return DataValue.get(name, material);
}
}

View File

@ -12,6 +12,7 @@ import com.Acrobot.ChestShop.Utils.uLongName;
import com.Acrobot.ChestShop.Utils.uSign;
import net.minecraft.server.IInventory;
import net.minecraft.server.InventoryLargeChest;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Chest;
@ -31,7 +32,7 @@ import java.util.HashMap;
public class playerInteract extends PlayerListener {
private static final HashMap<Player, Long> lastTransactionTime = new HashMap<Player, Long>(); //Last player's transaction
private static final int interval = 100;//Minimal interval between transactions
public static int interval = 100;//Minimal interval between transactions
public void onPlayerInteract(PlayerInteractEvent event) {
Action action = event.getAction();
@ -54,6 +55,11 @@ public class playerInteract extends PlayerListener {
if (!uSign.isValid(sign) || !enoughTimeHasPassed(player) || player.isSneaking()) return;
if (Config.getBoolean(Property.IGNORE_CREATIVE_MODE) && player.getGameMode() == GameMode.CREATIVE){
event.setCancelled(true);
return;
}
lastTransactionTime.put(player, System.currentTimeMillis());
if (action == Action.RIGHT_CLICK_BLOCK) event.setCancelled(true);

View File

@ -94,7 +94,6 @@ public class signChange extends BlockListener {
dropSign(event);
return;
}
boolean canAccess = !Security.isProtected(chestBlock) || Security.canAccess(player, chestBlock);
if (!canAccess) {
@ -150,18 +149,17 @@ public class signChange extends BlockListener {
}
private static String formatFourthLine(String fourthLine, Material material) {
String[] split = fourthLine.split(":");
if (uNumber.isInteger(split[0])) {
String materialLine = material.name();
if (split.length == 2) {
int maxLength = (14 - split[1].length()); //15 - length - 1
if (materialLine.length() > maxLength) materialLine = materialLine.substring(0, maxLength);
materialLine = materialLine + ':' + split[1];
}
fourthLine = materialLine;
}
fourthLine = fourthLine.replace("_", " ");
return fourthLine;
int index = (fourthLine.indexOf(':') != -1 ? fourthLine.indexOf(':') : 9999);
if (fourthLine.indexOf('-') < index && fourthLine.indexOf('-') != -1) index = fourthLine.indexOf('-');
StringBuilder toReturn = new StringBuilder(3);
String matName = uSign.capitalizeFirst(material.name());
if (index != 9999 && matName.length() > (15 - (fourthLine.length() - index))) matName = matName.substring(0, 15 - (fourthLine.length() - index));
if (Items.getMaterial(matName) == material) toReturn.append(matName);
else toReturn.append(material.getId());
if (index != -1 && index != 9999) toReturn.append(fourthLine.substring(index));
return toReturn.toString();
}
private static boolean formatFirstLine(String line1, Player player) {

View File

@ -29,7 +29,7 @@ public class Default implements Protection {
Chest neighborChest = uBlock.findNeighbor(block);
Sign neighborSign = (neighborChest != null ? uBlock.findSign2(neighborChest.getBlock()) : null);
return neighborSign != null && uLongName.stripName(playerName).equals(neighborSign.getLine(0));
return neighborSign == null || uLongName.stripName(playerName).equals(neighborSign.getLine(0));
}
public boolean protect(String name, Block block) {

View File

@ -0,0 +1,41 @@
package com.Acrobot.ChestShop.Utils;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
/**
* @author Acrobot
*/
public class uEnchantment {
public static String getEnchantment(ItemStack item){
return encodeEnchantment(item.getEnchantments());
}
public static String encodeEnchantment(Map<Enchantment, Integer> map){
int integer = 0;
for (Map.Entry<Enchantment, Integer> entry : map.entrySet()){
integer = integer * 1000 + (entry.getKey().getId()) * 10 + entry.getValue();
}
return (integer != 0 ? Integer.toString(integer, 32) : null);
}
public static Map<Enchantment, Integer> decodeEnchantment(String base32){
if (base32 == null) return new HashMap<Enchantment, Integer>();
Map<Enchantment, Integer> map = new HashMap<Enchantment, Integer>();
String integer = String.valueOf(Integer.parseInt(base32, 32));
for (int i = 0; i < (integer.length() / 3); i++){
String item = integer.substring(i * 3, i * 3 + 3);
Enchantment ench = Enchantment.getById(Integer.parseInt(item.substring(0, 2)));
if (ench == null) continue;
int level = Integer.parseInt(item.substring(2));
if (ench.getMaxLevel() < level || level < ench.getStartLevel()) continue;
map.put(ench, level);
}
return map;
}
}

View File

@ -6,8 +6,6 @@ import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
/**
* @author Acrobot
*/
@ -26,7 +24,7 @@ public class uInventory {
ItemStack currentItem = inv.getItem(slot);
if (currentItem == null || currentItem.getType() == Material.AIR) continue;
if (currentItem.getType() == itemMaterial && (durability == -1 || currentItem.getDurability() == durability)) {
if (equals(currentItem, item, durability)) {
int currentAmount = currentItem.getAmount();
if (amount == currentAmount) {
currentItem = null;
@ -41,36 +39,53 @@ public class uInventory {
inv.setItem(slot, currentItem);
}
}
return amount;
}
public static int add(Inventory inv, ItemStack item, int amount) {
amount = (amount > 0 ? amount : 1);
if (Config.getBoolean(Property.STACK_UNSTACKABLES)) return addAndStackTo64(inv, item, amount);
HashMap<Integer, ItemStack> items = inv.addItem(new ItemStack(item.getType(), amount, item.getDurability()));
/*ItemStack itemstack = new ItemStack(item.getType(), amount, item.getDurability());
itemstack.addEnchantments(item.getEnchantments());
HashMap<Integer, ItemStack> items = inv.addItem(itemstack);
amount = 0;
for (ItemStack toAdd : items.values()) amount += toAdd.getAmount();
return amount;
return amount;*/ //TODO: Fix this in CraftBukkit's code
return addManually(inv, item, amount);
}
private static int addManually(Inventory inv, ItemStack item, int amount) {
return addManually(inv, item, amount, item.getType().getMaxStackSize());
}
public static int addAndStackTo64(Inventory inv, ItemStack item, int amount) {
Material type = item.getType();
for (int slot = 0; slot < inv.getSize(); slot++) {
if (amount <= 0) return 0;
return addManually(inv, item, amount, 64);
}
public static int addManually(Inventory inv, ItemStack item, int amount, int max){
if (amount <= 0) return 0;
for (int slot = 0; slot < inv.getSize() && amount > 0; slot++){
ItemStack curItem = inv.getItem(slot);
ItemStack dupe = item.clone();
if (curItem == null || curItem.getType() == Material.AIR) {
item.setAmount((amount > 64 ? 64 : amount));
amount -= item.getAmount();
inv.setItem(slot, item);
} else if (curItem.getType() == type && curItem.getDurability() == item.getDurability() && curItem.getAmount() != 64) {
int toFill = (64 - curItem.getAmount());
item.setAmount((amount > toFill ? 64 : curItem.getAmount() + amount));
amount -= item.getAmount();
inv.setItem(slot, item);
dupe.setAmount((amount > max ? max : amount));
dupe.addEnchantments(item.getEnchantments());
amount -= dupe.getAmount();
inv.setItem(slot, dupe);
} else if (equals(item, curItem, item.getDurability()) && curItem.getAmount() != max) {
int cA = curItem.getAmount();
int amountAdded = amount > max - cA ? max - cA : amount;
dupe.setAmount(cA + amountAdded);
amount -= amountAdded;
dupe.addEnchantments(item.getEnchantments());
inv.setItem(slot, dupe);
}
}
return amount;
}
@ -79,14 +94,13 @@ public class uInventory {
int amount = 0;
for (ItemStack i : inv.getContents()) {
if (i != null && i.getType() == item.getType() && (durability == -1 || i.getDurability() == durability)) amount += i.getAmount();
if (equals(i, item, durability)) amount += i.getAmount();
}
return amount;
}
public static int fits(Inventory inv, ItemStack item, int amount, short durability) {
Material itemMaterial = item.getType();
int maxStackSize = (Config.getBoolean(Property.STACK_UNSTACKABLES) ? 64 : itemMaterial.getMaxStackSize());
int maxStackSize = (Config.getBoolean(Property.STACK_UNSTACKABLES) ? 64 : item.getType().getMaxStackSize());
int amountLeft = amount;
for (ItemStack currentItem : inv.getContents()) {
@ -99,11 +113,18 @@ public class uInventory {
int currentAmount = currentItem.getAmount();
if (currentAmount != maxStackSize && currentItem.getType() == itemMaterial && (durability == -1 || currentItem.getDurability() == durability)) {
if (currentAmount != maxStackSize && equals(currentItem, item, durability)) {
amountLeft = currentAmount + amountLeft <= maxStackSize ? 0 : amountLeft - (maxStackSize - currentAmount);
}
}
return amountLeft;
}
private static boolean equals(ItemStack i, ItemStack item, short durability){
return i != null
&& i.getType() == item.getType()
&& i.getEnchantments().equals(item.getEnchantments())
&& (durability == -1 || i.getDurability() == durability);
}
}

View File

@ -16,7 +16,7 @@ public class uSign {
Pattern.compile("^$|^\\w.+$"),
Pattern.compile("[0-9]+"),
Pattern.compile(".+"),
Pattern.compile("[\\w :]+")
Pattern.compile("[\\w : -]+")
};
public static Towny towny; //Moved this here - somehow, java fails at try/catch
@ -82,4 +82,17 @@ public class uSign {
return (amount >= 1 ? amount : 1);
} else return 1;
}
public static String capitalizeFirst(String name){
return capitalizeFirst(name, '_');
}
public static String capitalizeFirst(String name, char separator){
name = name.toLowerCase();
String[] split = name.split(Character.toString(separator));
StringBuilder total = new StringBuilder(3);
for (String s : split) total.append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).append(' ');
return total.toString().trim();
}
}

View File

@ -2,7 +2,7 @@ name: ChestShop
main: com.Acrobot.ChestShop.ChestShop
version: 3.29
version: 3.30
author: Acrobot