From 787fc3d82ebf9c1824e48e5db6019fe176f1b460 Mon Sep 17 00:00:00 2001 From: Olof Larsson Date: Wed, 27 Apr 2016 15:36:48 +0200 Subject: [PATCH] Working on Item stuff. Not done yet. --- .../command/type/TypeDataItemStack.java | 60 ++++++++ .../command/type/TypeTransformer.java | 8 +- .../command/type/primitive/TypeObject.java | 56 +++++++ .../massivecore/item/DataItemStack.java | 99 +++++++++++- .../massivecore/util/InventoryUtil.java | 142 ++++++++++++++++-- 5 files changed, 349 insertions(+), 16 deletions(-) create mode 100644 src/com/massivecraft/massivecore/command/type/TypeDataItemStack.java create mode 100644 src/com/massivecraft/massivecore/command/type/primitive/TypeObject.java diff --git a/src/com/massivecraft/massivecore/command/type/TypeDataItemStack.java b/src/com/massivecraft/massivecore/command/type/TypeDataItemStack.java new file mode 100644 index 00000000..6f53169f --- /dev/null +++ b/src/com/massivecraft/massivecore/command/type/TypeDataItemStack.java @@ -0,0 +1,60 @@ +package com.massivecraft.massivecore.command.type; + +import org.bukkit.inventory.ItemStack; + +import com.massivecraft.massivecore.MassiveCore; +import com.massivecraft.massivecore.command.type.primitive.TypeObject; +import com.massivecraft.massivecore.item.DataItemStack; + +public class TypeDataItemStack extends TypeTransformer +{ + // -------------------------------------------- // + // INSTANCE + // -------------------------------------------- // + + private static final TypeDataItemStack i = new TypeDataItemStack(); + public static TypeDataItemStack get() { return i; } + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public TypeDataItemStack(Type typeInner) + { + super(typeInner, TypeObject.get(DataItemStack.class)); + } + + public TypeDataItemStack() + { + this(TypeItemStack.get()); + } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public DataItemStack innerToOuter(ItemStack inner) + { + // TODO: Why on earth doesn't this line work. + DataItemStack outer = DataItemStack.fromBukkit(inner); + + System.out.println("1 from inner: " + inner); + System.out.println("2 to outer: " + outer.getId()); + System.out.println("3 to outer: " + MassiveCore.get().getGson().toJson(outer, DataItemStack.class)); + + return outer; + } + + @Override + public ItemStack outerToInner(DataItemStack outer) + { + ItemStack inner = DataItemStack.toBukkit(outer); + + System.out.println("from outer: " + MassiveCore.get().getGson().toJson(outer, DataItemStack.class)); + System.out.println("to inner: " + inner); + + return inner; + } + +} diff --git a/src/com/massivecraft/massivecore/command/type/TypeTransformer.java b/src/com/massivecraft/massivecore/command/type/TypeTransformer.java index 948066e5..abf40b48 100644 --- a/src/com/massivecraft/massivecore/command/type/TypeTransformer.java +++ b/src/com/massivecraft/massivecore/command/type/TypeTransformer.java @@ -14,8 +14,12 @@ import com.massivecraft.massivecore.command.editor.EditSettings; import com.massivecraft.massivecore.command.editor.Property; import com.massivecraft.massivecore.mson.Mson; -// The "inner" controls all ways the type behaves and "seems". -// The "outer" type is how the type interfaces in source code. For example what is read. +// The INNER type controls all ways the type behaves and seems. +// It is used for visuals, names, ids and when reading from a command argument. +// +// The OUTER type is how the type interfaces in source code. +// It is used for instance creation, editor command creation, and as an optional fallback. +// It should be noted that the OUTER type is kind of optional. public abstract class TypeTransformer extends TypeAbstract { // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/command/type/primitive/TypeObject.java b/src/com/massivecraft/massivecore/command/type/primitive/TypeObject.java new file mode 100644 index 00000000..5ae14b6e --- /dev/null +++ b/src/com/massivecraft/massivecore/command/type/primitive/TypeObject.java @@ -0,0 +1,56 @@ +package com.massivecraft.massivecore.command.type.primitive; + +import java.util.Collection; +import java.util.Collections; + +import org.bukkit.command.CommandSender; + +import com.massivecraft.massivecore.command.type.TypeAbstract; + +// This type is pretty weak and dysfunctional. +// It's intended to be used as a place holder. +// You can pass it instead of null for the sake of NPE evasion. +// It was initially created for usage within TypeTransformer. +public class TypeObject extends TypeAbstract +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static TypeObject i = new TypeObject(); + + @SuppressWarnings("unchecked") + public static TypeObject get() { return (TypeObject) i; } + + @SuppressWarnings("unchecked") + public static TypeObject get(Class classOfT) { return (TypeObject) i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public String getName() + { + return "object"; + } + + @Override + public String getIdInner(T value) + { + return value.toString(); + } + + @Override + public T read(String arg, CommandSender sender) + { + return null; + } + + @Override + public Collection getTabList(CommandSender sender, String arg) + { + return Collections.emptySet(); + } + +} diff --git a/src/com/massivecraft/massivecore/item/DataItemStack.java b/src/com/massivecraft/massivecore/item/DataItemStack.java index 5153549c..a16e0b46 100644 --- a/src/com/massivecraft/massivecore/item/DataItemStack.java +++ b/src/com/massivecraft/massivecore/item/DataItemStack.java @@ -4,13 +4,16 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import org.bukkit.Bukkit; import org.bukkit.inventory.ItemStack; +import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.collections.MassiveListDef; +import com.massivecraft.massivecore.collections.MassiveMap; import com.massivecraft.massivecore.collections.MassiveTreeMapDef; import com.massivecraft.massivecore.collections.MassiveTreeSetDef; import com.massivecraft.massivecore.comparator.ComparatorSmart; @@ -226,7 +229,6 @@ public class DataItemStack implements Comparable // The order matters and is explicitly assigned. // String, Number, String, Number ... - // TODO: Make sure the special adapter for upgrading the format is implemented! @SerializedName("banner") private MassiveListDef bannerPatterns = null; public List getBannerPatterns() { return get(this.bannerPatterns, DEFAULT_BANNER_PATTERNS); } @@ -265,9 +267,15 @@ public class DataItemStack implements Comparable } // -------------------------------------------- // - // TO BUKKIT + // CONVERT ONE // -------------------------------------------- // + public static DataItemStack fromBukkit(ItemStack itemStack) + { + if (itemStack == null) return null; + return new DataItemStack(itemStack); + } + public ItemStack toBukkit() { // Create @@ -280,6 +288,93 @@ public class DataItemStack implements Comparable return ret; } + public static ItemStack toBukkit(DataItemStack dataItemStack) + { + if (dataItemStack == null) return null; + return dataItemStack.toBukkit(); + } + + // -------------------------------------------- // + // CONVERT MANY + // -------------------------------------------- // + + public static void fromBukkit(Iterable itemStacks, Collection dataItemStacks) + { + for (ItemStack itemStack : itemStacks) + { + dataItemStacks.add(fromBukkit(itemStack)); + } + } + + public static List fromBukkit(Iterable itemStacks) + { + // Create + List ret = new MassiveList<>(); + + // Fill + fromBukkit(itemStacks, ret); + + // Return + return ret; + } + + public static void fromBukkitKeys(Map itemStacks, Map dataItemStacks) + { + for (Entry entry : itemStacks.entrySet()) + { + dataItemStacks.put(fromBukkit(entry.getKey()), entry.getValue()); + } + } + + public static Map fromBukkitKeys(Map itemStacks) + { + // Create + Map ret = new MassiveMap<>(); + + // Fill + fromBukkitKeys(itemStacks, ret); + + // Return + return ret; + } + + public static void fromBukkitValues(Map itemStacks, Map dataItemStacks) + { + for (Entry entry : itemStacks.entrySet()) + { + dataItemStacks.put(entry.getKey(), fromBukkit(entry.getValue())); + } + } + + public static Map fromBukkitValues(Map itemStacks) + { + // Create + Map ret = new MassiveMap<>(); + + // Fill + fromBukkitValues(itemStacks, ret); + + // Return + return ret; + } + + // -------------------------------------------- // + // UTILITY + // -------------------------------------------- // + + public static boolean isSomething(DataItemStack dataItemStack) + { + if (dataItemStack == null) return false; + if (dataItemStack.getId() == 0) return false; + // In Minecraft 1.9 zero quantity is a thing. + return true; + } + + public static boolean isNothing(DataItemStack dataItemStack) + { + return ! isSomething(dataItemStack); + } + // -------------------------------------------- // // COMPARE & EQUALS & HASHCODE // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/util/InventoryUtil.java b/src/com/massivecraft/massivecore/util/InventoryUtil.java index f54f21ee..8ff1e8ce 100644 --- a/src/com/massivecraft/massivecore/util/InventoryUtil.java +++ b/src/com/massivecraft/massivecore/util/InventoryUtil.java @@ -2,8 +2,11 @@ package com.massivecraft.massivecore.util; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Map.Entry; +import java.util.AbstractMap.SimpleEntry; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -11,6 +14,8 @@ import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.inventory.InventoryInteractEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.inventory.Inventory; @@ -496,18 +501,6 @@ public class InventoryUtil return isBottomInventory(event.getRawSlot(), event.getInventory()); } - @Deprecated - public static boolean isGiving(InventoryClickEvent event) - { - return getAlter(event).isGiving(); - } - - @Deprecated - public static boolean isTaking(InventoryClickEvent event) - { - return getAlter(event).isTaking(); - } - public static boolean isAltering(InventoryClickEvent event) { return getAlter(event).isAltering(); @@ -642,6 +635,131 @@ public class InventoryUtil } } + // -------------------------------------------- // + // GET CHANGES + // -------------------------------------------- // + // In this section we interpret the changes made by inventory interact events. + // The very same event may cause both giving and taking of multiple different items. + // We return a list of entries: + // > KEY: The raw and unmodified ItemStack. + // > VALUE: The change in amount where positive means take. (count change measured in the "players inventory") + // By choosing this return value we can provide the rawest data possible. + // We never ever clone or modify the ItemStacks in any way. + // This means that the amount within the ItemStack key is irrelevant. + // We can also avoid all kinds of oddities related to ItemStack equals and compare in the Bukkit API. + + public static List> getChanges(InventoryInteractEvent event) + { + if (event instanceof InventoryClickEvent) + { + InventoryClickEvent clickEvent = (InventoryClickEvent)event; + return getChangesClick(clickEvent); + } + + if (event instanceof InventoryDragEvent) + { + InventoryDragEvent dragEvent = (InventoryDragEvent)event; + return getChangesDrag(dragEvent); + } + + return Collections.emptyList(); + } + + protected static List> getChangesClick(InventoryClickEvent event) + { + // Create + List> ret = new MassiveList<>(); + + // Fill + final InventoryAlter alter = InventoryUtil.getAlter(event); + final InventoryAction action = event.getAction(); + ItemStack item; + int amount; + + // Give + if (alter.isGiving()) + { + // Special > MOVE_TO_OTHER_INVENTORY + if (action == InventoryAction.MOVE_TO_OTHER_INVENTORY) + { + item = event.getCurrentItem(); + + ItemStack compare = item.clone(); + compare.setAmount(1); + amount = InventoryUtil.roomLeft(event.getInventory(), compare, item.getAmount()); + } + // Special > HOTBAR_SWAP + else if (action == InventoryAction.HOTBAR_SWAP) + { + item = event.getView().getBottomInventory().getItem(event.getHotbarButton()); + + amount = item.getAmount(); + } + // Normal + else + { + item = event.getCursor(); + + amount = item.getAmount(); + if (action == InventoryAction.PLACE_ONE) + { + amount = 1; + } + else if (action == InventoryAction.PLACE_SOME) + { + int max = event.getCurrentItem().getType().getMaxStackSize(); + amount = max - event.getCurrentItem().getAmount(); + } + } + + amount *= -1; + ret.add(new SimpleEntry(item, amount)); + } + + // Take + if (alter.isTaking()) + { + item = event.getCurrentItem(); + + amount = item.getAmount(); + if (action == InventoryAction.PICKUP_ONE) amount = 1; + if (action == InventoryAction.PICKUP_HALF) amount = (int) Math.ceil(amount / 2.0); + + ret.add(new SimpleEntry(item, amount)); + } + + // Return + return ret; + } + + // Drag events by nature only matters when they affect the top inventory. + // What you are holding in the cursor is already yours. + // If you drag it into your own inventory you are not really taking anything. + // If you drag into the top inventory however, you may both give and take. + // You "take" by dragging over an existing item (since we don't do any math). + protected static List> getChangesDrag(InventoryDragEvent event) + { + // Create + List> ret = new MassiveList<>(); + + // Fill + final Inventory inventory = event.getInventory(); + for (Entry entry : event.getNewItems().entrySet()) + { + int rawSlot = entry.getKey(); + if (InventoryUtil.isBottomInventory(rawSlot, inventory)) continue; + + ItemStack take = inventory.getItem(rawSlot); + if (isSomething(take)) ret.add(new SimpleEntry(take, -take.getAmount())); + + ItemStack give = entry.getValue(); + if (isSomething(give)) ret.add(new SimpleEntry(give, +take.getAmount())); + } + + // Return + return ret; + } + // -------------------------------------------- // // DEBUG // -------------------------------------------- //