diff --git a/src/main/java/com/massivecraft/massivecore/CaseInsensitiveComparator.java b/src/main/java/com/massivecraft/massivecore/CaseInsensitiveComparator.java new file mode 100644 index 00000000..3715dbb7 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/CaseInsensitiveComparator.java @@ -0,0 +1,24 @@ +package com.massivecraft.massivecore; + +import java.util.Comparator; + +public class CaseInsensitiveComparator implements Comparator +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static CaseInsensitiveComparator i = new CaseInsensitiveComparator(); + public static CaseInsensitiveComparator get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public int compare(String o1, String o2) + { + return String.CASE_INSENSITIVE_ORDER.compare(o1, o2); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/MassiveCore.java b/src/main/java/com/massivecraft/massivecore/MassiveCore.java index 0b28d727..962ddef9 100644 --- a/src/main/java/com/massivecraft/massivecore/MassiveCore.java +++ b/src/main/java/com/massivecraft/massivecore/MassiveCore.java @@ -15,14 +15,29 @@ import org.bukkit.inventory.PlayerInventory; import com.massivecraft.massivecore.adapter.InventoryAdapter; import com.massivecraft.massivecore.adapter.ItemStackAdapter; import com.massivecraft.massivecore.adapter.JsonElementAdapter; +import com.massivecraft.massivecore.adapter.MassiveListAdapter; +import com.massivecraft.massivecore.adapter.MassiveMapAdapter; +import com.massivecraft.massivecore.adapter.MassiveSetAdapter; +import com.massivecraft.massivecore.adapter.MassiveTreeSetAdapter; import com.massivecraft.massivecore.adapter.ModdedEnumTypeAdapter; import com.massivecraft.massivecore.adapter.PlayerInventoryAdapter; +import com.massivecraft.massivecore.adapter.MassiveTreeMapAdapter; import com.massivecraft.massivecore.adapter.UUIDAdapter; import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCore; import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCoreBuffer; import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCoreCmdurl; import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCoreStore; import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCoreUsys; +import com.massivecraft.massivecore.collections.MassiveList; +import com.massivecraft.massivecore.collections.MassiveListDef; +import com.massivecraft.massivecore.collections.MassiveMap; +import com.massivecraft.massivecore.collections.MassiveMapDef; +import com.massivecraft.massivecore.collections.MassiveSet; +import com.massivecraft.massivecore.collections.MassiveSetDef; +import com.massivecraft.massivecore.collections.MassiveTreeMap; +import com.massivecraft.massivecore.collections.MassiveTreeMapDef; +import com.massivecraft.massivecore.collections.MassiveTreeSet; +import com.massivecraft.massivecore.collections.MassiveTreeSetDef; import com.massivecraft.massivecore.event.EventMassiveCoreUuidUpdate; import com.massivecraft.massivecore.fetcher.Fetcher; import com.massivecraft.massivecore.fetcher.IdAndName; @@ -88,6 +103,18 @@ public class MassiveCore extends MassivePlugin .registerTypeAdapter(Inventory.class, InventoryAdapter.get()) .registerTypeAdapter(PlayerInventory.class, PlayerInventoryAdapter.get()) .registerTypeAdapter(PS.class, PSAdapter.get()) + + .registerTypeAdapter(MassiveList.class, MassiveListAdapter.get()) + .registerTypeAdapter(MassiveListDef.class, MassiveListAdapter.get()) + .registerTypeAdapter(MassiveMap.class, MassiveMapAdapter.get()) + .registerTypeAdapter(MassiveMapDef.class, MassiveMapAdapter.get()) + .registerTypeAdapter(MassiveSet.class, MassiveSetAdapter.get()) + .registerTypeAdapter(MassiveSetDef.class, MassiveSetAdapter.get()) + .registerTypeAdapter(MassiveTreeMap.class, MassiveTreeMapAdapter.get()) + .registerTypeAdapter(MassiveTreeMapDef.class, MassiveTreeMapAdapter.get()) + .registerTypeAdapter(MassiveTreeSet.class, MassiveTreeSetAdapter.get()) + .registerTypeAdapter(MassiveTreeSetDef.class, MassiveTreeSetAdapter.get()) + .registerTypeAdapterFactory(ModdedEnumTypeAdapter.ENUM_FACTORY); } diff --git a/src/main/java/com/massivecraft/massivecore/adapter/MassiveListAdapter.java b/src/main/java/com/massivecraft/massivecore/adapter/MassiveListAdapter.java new file mode 100644 index 00000000..1a4a097d --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/adapter/MassiveListAdapter.java @@ -0,0 +1,38 @@ +package com.massivecraft.massivecore.adapter; + +import java.lang.reflect.Type; +import java.util.Collection; + +import com.massivecraft.massivecore.collections.MassiveList; +import com.massivecraft.massivecore.collections.MassiveListDef; +import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext; +import com.massivecraft.massivecore.xlib.gson.JsonElement; + +public class MassiveListAdapter extends MassiveXAdapter> +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static MassiveListAdapter i = new MassiveListAdapter(); + public static MassiveListAdapter get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public MassiveList create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) + { + if (def) + { + return new MassiveListDef((Collection)parent); + } + else + { + return new MassiveList((Collection)parent); + } + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/adapter/MassiveMapAdapter.java b/src/main/java/com/massivecraft/massivecore/adapter/MassiveMapAdapter.java new file mode 100644 index 00000000..cc62ba52 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/adapter/MassiveMapAdapter.java @@ -0,0 +1,38 @@ +package com.massivecraft.massivecore.adapter; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.massivecraft.massivecore.collections.MassiveMap; +import com.massivecraft.massivecore.collections.MassiveMapDef; +import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext; +import com.massivecraft.massivecore.xlib.gson.JsonElement; + +public class MassiveMapAdapter extends MassiveXAdapter> +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static MassiveMapAdapter i = new MassiveMapAdapter(); + public static MassiveMapAdapter get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public MassiveMap create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) + { + if (def) + { + return new MassiveMapDef((Map)parent); + } + else + { + return new MassiveMap((Map)parent); + } + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/adapter/MassiveSetAdapter.java b/src/main/java/com/massivecraft/massivecore/adapter/MassiveSetAdapter.java new file mode 100644 index 00000000..b41a38ae --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/adapter/MassiveSetAdapter.java @@ -0,0 +1,38 @@ +package com.massivecraft.massivecore.adapter; + +import java.lang.reflect.Type; +import java.util.Collection; + +import com.massivecraft.massivecore.collections.MassiveSet; +import com.massivecraft.massivecore.collections.MassiveSetDef; +import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext; +import com.massivecraft.massivecore.xlib.gson.JsonElement; + +public class MassiveSetAdapter extends MassiveXAdapter> +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static MassiveSetAdapter i = new MassiveSetAdapter(); + public static MassiveSetAdapter get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public MassiveSet create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) + { + if (def) + { + return new MassiveSetDef((Collection)parent); + } + else + { + return new MassiveSet((Collection)parent); + } + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/adapter/MassiveTreeMapAdapter.java b/src/main/java/com/massivecraft/massivecore/adapter/MassiveTreeMapAdapter.java new file mode 100644 index 00000000..38391915 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/adapter/MassiveTreeMapAdapter.java @@ -0,0 +1,48 @@ +package com.massivecraft.massivecore.adapter; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.massivecraft.massivecore.collections.MassiveTreeMap; +import com.massivecraft.massivecore.collections.MassiveTreeMapDef; +import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext; +import com.massivecraft.massivecore.xlib.gson.JsonElement; + +public class MassiveTreeMapAdapter extends MassiveXAdapter> +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static MassiveTreeMapAdapter i = new MassiveTreeMapAdapter(); + public static MassiveTreeMapAdapter get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public MassiveTreeMap create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) + { + Object comparator = getComparator(typeOfT); + if (def) + { + return new MassiveTreeMapDef(comparator, (Map)parent); + } + else + { + return new MassiveTreeMap(comparator, (Map)parent); + } + } + + // -------------------------------------------- // + // GET COMPARATOR + // -------------------------------------------- // + + public static Object getComparator(Type typeOfT) + { + return getNewArgumentInstance(typeOfT, 2); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/adapter/MassiveTreeSetAdapter.java b/src/main/java/com/massivecraft/massivecore/adapter/MassiveTreeSetAdapter.java new file mode 100644 index 00000000..492c1d53 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/adapter/MassiveTreeSetAdapter.java @@ -0,0 +1,48 @@ +package com.massivecraft.massivecore.adapter; + +import java.lang.reflect.Type; +import java.util.Collection; + +import com.massivecraft.massivecore.collections.MassiveTreeSet; +import com.massivecraft.massivecore.collections.MassiveTreeSetDef; +import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext; +import com.massivecraft.massivecore.xlib.gson.JsonElement; + +public class MassiveTreeSetAdapter extends MassiveXAdapter> +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static MassiveTreeSetAdapter i = new MassiveTreeSetAdapter(); + public static MassiveTreeSetAdapter get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public MassiveTreeSet create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context) + { + Object comparator = getComparator(typeOfT); + if (def) + { + return new MassiveTreeSetDef(comparator, (Collection)parent); + } + else + { + return new MassiveTreeSet(comparator, (Collection)parent); + } + } + + // -------------------------------------------- // + // GET COMPARATOR + // -------------------------------------------- // + + public static Object getComparator(Type typeOfT) + { + return getNewArgumentInstance(typeOfT, 1); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/adapter/MassiveXAdapter.java b/src/main/java/com/massivecraft/massivecore/adapter/MassiveXAdapter.java new file mode 100644 index 00000000..280c37b2 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/adapter/MassiveXAdapter.java @@ -0,0 +1,146 @@ +package com.massivecraft.massivecore.adapter; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Map; + +import com.massivecraft.massivecore.collections.Def; +import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext; +import com.massivecraft.massivecore.xlib.gson.JsonDeserializer; +import com.massivecraft.massivecore.xlib.gson.JsonElement; +import com.massivecraft.massivecore.xlib.gson.JsonNull; +import com.massivecraft.massivecore.xlib.gson.JsonParseException; +import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext; +import com.massivecraft.massivecore.xlib.gson.JsonSerializer; + +/** + * This is the abstract adapter for all "Massive structures". + * It makes sure Def instances "handle empty as null". + * It makes sure we avoid infinite GSON recurse loops by recursing with supertype. + */ +public abstract class MassiveXAdapter implements JsonDeserializer, JsonSerializer +{ + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public JsonElement serialize(T src, Type type, JsonSerializationContext context) + { + // Calculate def + Class clazz = getClazz(type); + boolean def = Def.class.isAssignableFrom(clazz); + + // If this is a Def ... + if (def) + { + // ... and the instance is null or contains no elements ... + if (isEmpty(src)) + { + // ... then serialize as a JsonNull! + return JsonNull.INSTANCE; + } + // ... and it's non null and contains something ... + else + { + // ... then serialize it as if it were the regular Java collection! + // SUPER TYPE x2 EXAMPLE: MassiveListDef --> MassiveList --> ArrayList + return context.serialize(src, getSuperType(getSuperType(type))); + } + } + // If this a regular Massive structure and not a Def ... + else + { + // ... then serialize it as if it were the regular java collection! + // SUPER TYPE x1 EXAMPLE: MassiveList --> ArrayList + return context.serialize(src, getSuperType(type)); + } + } + + @Override + public T deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException + { + // Calculate def + Class clazz = getClazz(type); + boolean def = Def.class.isAssignableFrom(clazz); + + // If this is a Def ... + if (def) + { + // ... then deserialize it as if it were the regular Java collection! + // SUPER TYPE x2 EXAMPLE: MassiveListDef --> MassiveList --> ArrayList + Object parent = context.deserialize(json, getSuperType(getSuperType(type))); + return create(parent, def, json, type, context); + } + // If this a regular Massive structure and not a Def ... + else + { + // ... and the json is null or a JsonNull ... + if (json == null || json instanceof JsonNull) + { + // ... then deserialize as a null! + return null; + } + // ... and it's non null and contains something ... + else + { + // ... then deserialize it as if it were the regular java collection! + // SUPER TYPE x1 EXAMPLE: MassiveList --> ArrayList + Object parent = context.deserialize(json, getSuperType(type)); + return create(parent, def, json, type, context); + } + } + } + + // -------------------------------------------- // + // ABSTRACT + // -------------------------------------------- // + + public abstract T create(Object parent, boolean def, JsonElement json, Type typeOfT, JsonDeserializationContext context); + + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // + + public static Class getClazz(Type type) + { + ParameterizedType parameterizedType = (ParameterizedType) type; + Class clazz = (Class)parameterizedType.getRawType(); + return clazz; + } + + public static Type getSuperType(Type type) + { + Class clazz = getClazz(type); + Type superclazz = clazz.getGenericSuperclass(); + return superclazz; + } + + public static Object getNewArgumentInstance(Type type, int index) + { + ParameterizedType parameterizedType = (ParameterizedType) type; + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + Class clazz = (Class) actualTypeArguments[index]; + try + { + return clazz.newInstance(); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + @SuppressWarnings("rawtypes") + public static boolean isEmpty(Object object) + { + // A Map is not a Collection. + // Thus we have to use isEmpty() declared in different interfaces. + if (object == null) return true; + if (object instanceof Map) return ((Map)object).isEmpty(); + if (object instanceof Collection) return ((Collection)object).isEmpty(); + return false; + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/cmd/MassiveCommand.java b/src/main/java/com/massivecraft/massivecore/cmd/MassiveCommand.java index 1fa7c8cc..5d2f4699 100644 --- a/src/main/java/com/massivecraft/massivecore/cmd/MassiveCommand.java +++ b/src/main/java/com/massivecraft/massivecore/cmd/MassiveCommand.java @@ -49,10 +49,29 @@ public class MassiveCommand public void setSubCommands(List subCommands) { this.subCommands = subCommands; } public void addSubCommand(MassiveCommand subCommand) + { + this.addSubCommand(subCommand, this.subCommands.size()); + } + + public void addSubCommand(MassiveCommand subCommand, MassiveCommand after) + { + int index = this.subCommands.indexOf(after); + if (index == -1) + { + index = this.subCommands.size(); + } + else + { + index++; + } + this.addSubCommand(subCommand, index); + } + + public void addSubCommand(MassiveCommand subCommand, int index) { subCommand.commandChain.addAll(this.commandChain); subCommand.commandChain.add(this); - this.subCommands.add(subCommand); + this.subCommands.add(index, subCommand); } // FIELD: aliases diff --git a/src/main/java/com/massivecraft/massivecore/collections/Def.java b/src/main/java/com/massivecraft/massivecore/collections/Def.java new file mode 100644 index 00000000..64611fbc --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/Def.java @@ -0,0 +1,6 @@ +package com.massivecraft.massivecore.collections; + +public interface Def +{ + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveList.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveList.java new file mode 100644 index 00000000..0028a272 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveList.java @@ -0,0 +1,50 @@ +package com.massivecraft.massivecore.collections; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +/** + * This subclass adds better constructors. + */ +public class MassiveList extends ArrayList +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: BASE + // -------------------------------------------- // + + public MassiveList(int initialCapacity) + { + super(initialCapacity); + } + + public MassiveList() + { + super(); + } + + @SuppressWarnings("unchecked") + public MassiveList(Collection c) + { + // Support Null + super(c == null ? Collections.EMPTY_LIST : c); + } + + // -------------------------------------------- // + // CONSTRUCT: EXTRA + // -------------------------------------------- // + + @SafeVarargs + public MassiveList(E... elements) + { + this(Arrays.asList(elements)); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveListDef.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveListDef.java new file mode 100644 index 00000000..4b69c9ad --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveListDef.java @@ -0,0 +1,42 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Collection; + +/** + * This subclass does nothing new except implementing the Def interface. + * Def is short for "Default" and means GSON should handle "null" as "empty". + */ +public class MassiveListDef extends MassiveList implements Def +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: SUPER + // -------------------------------------------- // + + public MassiveListDef(int initialCapacity) + { + super(initialCapacity); + } + + public MassiveListDef() + { + super(); + } + + public MassiveListDef(Collection c) + { + super(c); + } + + @SafeVarargs + public MassiveListDef(E... elements) + { + super(elements); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveMap.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveMap.java new file mode 100644 index 00000000..957e3e83 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveMap.java @@ -0,0 +1,82 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * This subclass adds better constructors. + */ +public class MassiveMap extends LinkedHashMap +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: BASE + // -------------------------------------------- // + + public MassiveMap(int initialCapacity, float loadFactor) + { + super(initialCapacity, loadFactor); + } + + public MassiveMap(int initialCapacity) + { + super(initialCapacity); + } + + public MassiveMap() + { + super(); + } + + @SuppressWarnings("unchecked") + public MassiveMap(Map m) + { + // Support Null + super(m == null ? Collections.EMPTY_MAP : m); + } + + public MassiveMap(int initialCapacity, float loadFactor, boolean accessOrder) + { + super(initialCapacity, loadFactor, accessOrder); + } + + // -------------------------------------------- // + // CONSTRUCT: EXTRA + // -------------------------------------------- // + + public MassiveMap(K key1, V value1, Object... objects) + { + this(varargCreate(key1, value1, objects)); + } + + // -------------------------------------------- // + // UTIL + // -------------------------------------------- // + + @SuppressWarnings("unchecked") + public static MassiveMap varargCreate(K key1, V value1, Object... objects) + { + MassiveMap ret = new MassiveMap(); + + ret.put(key1, value1); + + Iterator iter = Arrays.asList(objects).iterator(); + while (iter.hasNext()) + { + K key = (K) iter.next(); + V value = (V) iter.next(); + ret.put(key, value); + } + + return ret; + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveMapDef.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveMapDef.java new file mode 100644 index 00000000..29f50286 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveMapDef.java @@ -0,0 +1,51 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Map; + +/** + * This subclass does nothing new except implementing the Def interface. + * Def is short for "Default" and means GSON should handle "null" as "empty". + */ +public class MassiveMapDef extends MassiveMap implements Def +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: SUPER + // -------------------------------------------- // + + public MassiveMapDef(int initialCapacity, float loadFactor) + { + super(initialCapacity, loadFactor); + } + + public MassiveMapDef(int initialCapacity) + { + super(initialCapacity); + } + + public MassiveMapDef() + { + super(); + } + + public MassiveMapDef(Map m) + { + super(m); + } + + public MassiveMapDef(int initialCapacity, float loadFactor, boolean accessOrder) + { + super(initialCapacity, loadFactor, accessOrder); + } + + public MassiveMapDef(K key1, V value1, Object... objects) + { + super(key1, value1, objects); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveSet.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveSet.java new file mode 100644 index 00000000..5fa3341e --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveSet.java @@ -0,0 +1,55 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashSet; + +/** + * This subclass adds better constructors. + */ +public class MassiveSet extends LinkedHashSet +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: BASE + // -------------------------------------------- // + + public MassiveSet(int initialCapacity, float loadFactor) + { + super(initialCapacity, loadFactor); + } + + public MassiveSet(int initialCapacity) + { + super(initialCapacity); + } + + public MassiveSet() + { + super(); + } + + @SuppressWarnings("unchecked") + public MassiveSet(Collection c) + { + // Support Null + super(c == null ? Collections.EMPTY_LIST : c); + } + + // -------------------------------------------- // + // CONSTRUCT: EXTRA + // -------------------------------------------- // + + @SafeVarargs + public MassiveSet(E... elements) + { + this(Arrays.asList(elements)); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveSetDef.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveSetDef.java new file mode 100644 index 00000000..c7fa0ea4 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveSetDef.java @@ -0,0 +1,47 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Collection; + +/** + * This subclass does nothing new except implementing the Def interface. + * Def is short for "Default" and means GSON should handle "null" as "empty". + */ +public class MassiveSetDef extends MassiveSet implements Def +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: SUPER + // -------------------------------------------- // + + public MassiveSetDef(int initialCapacity, float loadFactor) + { + super(initialCapacity, loadFactor); + } + + public MassiveSetDef(int initialCapacity) + { + super(initialCapacity); + } + + public MassiveSetDef() + { + super(); + } + + public MassiveSetDef(Collection c) + { + super(c); + } + + @SafeVarargs + public MassiveSetDef(E... elements) + { + super(elements); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeMap.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeMap.java new file mode 100644 index 00000000..22f0faab --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeMap.java @@ -0,0 +1,45 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Comparator; +import java.util.Map; +import java.util.TreeMap; + +/** + * This subclass adds better constructors. + * It also includes the comparator as a Generic for automatic use with GSON. + */ +public class MassiveTreeMap> extends TreeMap +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: BASE + // -------------------------------------------- // + + @SuppressWarnings("unchecked") + public MassiveTreeMap(Object comparator) + { + super((comparator instanceof Comparator) ? (C)comparator : null); + } + + public MassiveTreeMap(Object comparator, Map map) + { + // Support Null & this(comparator) + this(comparator); + if (map != null) putAll(map); + } + + // -------------------------------------------- // + // CONSTRUCT: EXTRA + // -------------------------------------------- // + + public MassiveTreeMap(Object comparator, K key1, V value1, Object... objects) + { + this(comparator, MassiveMap.varargCreate(key1, value1, objects)); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeMapDef.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeMapDef.java new file mode 100644 index 00000000..006f8a92 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeMapDef.java @@ -0,0 +1,37 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Comparator; +import java.util.Map; + +/** + * This subclass does nothing new except implementing the Def interface. + * Def is short for "Default" and means GSON should handle "null" as "empty". + */ +public class MassiveTreeMapDef> extends MassiveTreeMap implements Def +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: SUPER + // -------------------------------------------- // + + public MassiveTreeMapDef(Object comparator) + { + super(comparator); + } + + public MassiveTreeMapDef(Object comparator, Map map) + { + super(comparator, map); + } + + public MassiveTreeMapDef(Object comparator, K key1, V value1, Object... objects) + { + super(comparator, key1, value1, objects); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeSet.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeSet.java new file mode 100644 index 00000000..a4e676c5 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeSet.java @@ -0,0 +1,47 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.TreeSet; + +/** + * This subclass adds better constructors. + * It also includes the comparator as a Generic for automatic use with GSON. + */ +public class MassiveTreeSet> extends TreeSet +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: BASE + // -------------------------------------------- // + + @SuppressWarnings("unchecked") + public MassiveTreeSet(Object comparator) + { + super((comparator instanceof Comparator) ? (C)comparator : null); + } + + public MassiveTreeSet(Object comparator, Collection c) + { + // Support Null & this(comparator) + this(comparator); + if (c != null) addAll(c); + } + + // -------------------------------------------- // + // CONSTRUCT: EXTRA + // -------------------------------------------- // + + @SafeVarargs + public MassiveTreeSet(Object comparator, E... elements) + { + this(comparator, Arrays.asList(elements)); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeSetDef.java b/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeSetDef.java new file mode 100644 index 00000000..b0fbe2c7 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/MassiveTreeSetDef.java @@ -0,0 +1,38 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Collection; +import java.util.Comparator; + +/** + * This subclass does nothing new except implementing the Def interface. + * Def is short for "Default" and means GSON should handle "null" as "empty". + */ +public class MassiveTreeSetDef> extends MassiveTreeSet implements Def +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + private static final long serialVersionUID = 1L; + + // -------------------------------------------- // + // CONSTRUCT: SUPER + // -------------------------------------------- // + + public MassiveTreeSetDef(Object comparator) + { + super(comparator); + } + + public MassiveTreeSetDef(Object comparator, Collection c) + { + super(comparator, c); + } + + @SafeVarargs + public MassiveTreeSetDef(Object comparator, E... elements) + { + super(comparator, elements); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/money/Money.java b/src/main/java/com/massivecraft/massivecore/money/Money.java index 24d95b7d..9a530c3e 100644 --- a/src/main/java/com/massivecraft/massivecore/money/Money.java +++ b/src/main/java/com/massivecraft/massivecore/money/Money.java @@ -55,6 +55,12 @@ public class Money return mixin.format(amount); } + public static String format(double amount, boolean includeUnit) + { + if (disabled()) return String.valueOf(amount) + (includeUnit ? "$": ""); + return mixin.format(amount, includeUnit); + } + public static String singular() { if (disabled()) return "singular"; @@ -67,6 +73,12 @@ public class Money return mixin.plural(); } + public static int fractionalDigits() + { + if (disabled()) return 0; + return mixin.fractionalDigits(); + } + // -------------------------------------------- // // EXISTANCE // -------------------------------------------- // diff --git a/src/main/java/com/massivecraft/massivecore/money/MoneyMixin.java b/src/main/java/com/massivecraft/massivecore/money/MoneyMixin.java index ec7ad7f8..34e53869 100644 --- a/src/main/java/com/massivecraft/massivecore/money/MoneyMixin.java +++ b/src/main/java/com/massivecraft/massivecore/money/MoneyMixin.java @@ -15,8 +15,10 @@ public interface MoneyMixin // -------------------------------------------- // public String format(double amount); + public String format(double amount, boolean includeUnit); public String singular(); public String plural(); + public int fractionalDigits(); // -------------------------------------------- // // EXISTANCE diff --git a/src/main/java/com/massivecraft/massivecore/money/MoneyMixinAbstract.java b/src/main/java/com/massivecraft/massivecore/money/MoneyMixinAbstract.java index 28e8ef16..c93770af 100644 --- a/src/main/java/com/massivecraft/massivecore/money/MoneyMixinAbstract.java +++ b/src/main/java/com/massivecraft/massivecore/money/MoneyMixinAbstract.java @@ -6,6 +6,15 @@ import java.util.Collection; public abstract class MoneyMixinAbstract implements MoneyMixin { + // -------------------------------------------- // + // FORMAT AND NAME + // -------------------------------------------- // + + public String format(double amount) + { + return this.format(amount, true); + } + // -------------------------------------------- // // MOVE // -------------------------------------------- // diff --git a/src/main/java/com/massivecraft/massivecore/money/MoneyMixinVault.java b/src/main/java/com/massivecraft/massivecore/money/MoneyMixinVault.java index bb7a9cea..0eb6a762 100644 --- a/src/main/java/com/massivecraft/massivecore/money/MoneyMixinVault.java +++ b/src/main/java/com/massivecraft/massivecore/money/MoneyMixinVault.java @@ -13,6 +13,7 @@ import com.massivecraft.massivecore.util.MUtil; + import net.milkbowl.vault.economy.Economy; public class MoneyMixinVault extends MoneyMixinAbstract @@ -63,9 +64,28 @@ public class MoneyMixinVault extends MoneyMixinAbstract // -------------------------------------------- // @Override - public String format(double amount) + public String format(double amount, boolean includeUnit) { - return this.economy.format(amount); + if (includeUnit) + { + return this.economy.format(amount); + } + else + { + int fractionalDigits = this.fractionalDigits(); + if (fractionalDigits < 0) + { + return String.valueOf(amount); + } + else if (fractionalDigits == 0) + { + return String.valueOf((int)Math.round(amount)); + } + else + { + return String.format("%." + fractionalDigits + "f", amount); + } + } } @Override @@ -80,6 +100,12 @@ public class MoneyMixinVault extends MoneyMixinAbstract return this.economy.currencyNamePlural(); } + @Override + public int fractionalDigits() + { + return this.economy.fractionalDigits(); + } + // -------------------------------------------- // // EXISTS AND CREATE // -------------------------------------------- // diff --git a/src/main/java/com/massivecraft/massivecore/util/MUtil.java b/src/main/java/com/massivecraft/massivecore/util/MUtil.java index 48db16ae..c1591330 100644 --- a/src/main/java/com/massivecraft/massivecore/util/MUtil.java +++ b/src/main/java/com/massivecraft/massivecore/util/MUtil.java @@ -13,7 +13,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.UUID; @@ -49,9 +48,13 @@ import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.projectiles.ProjectileSource; +import com.massivecraft.massivecore.CaseInsensitiveComparator; import com.massivecraft.massivecore.MassiveCore; import com.massivecraft.massivecore.MassiveCoreEngineMain; import com.massivecraft.massivecore.MassiveCoreEngineWorldNameSet; +import com.massivecraft.massivecore.collections.MassiveList; +import com.massivecraft.massivecore.collections.MassiveSet; +import com.massivecraft.massivecore.collections.MassiveTreeSet; import com.massivecraft.massivecore.util.extractor.Extractor; import com.massivecraft.massivecore.util.extractor.ExtractorPlayer; import com.massivecraft.massivecore.util.extractor.ExtractorPlayerName; @@ -589,34 +592,21 @@ public class MUtil // SIMPLE CONSTRUCTORS // -------------------------------------------- // - @SafeVarargs public static List list(T... items) { - return new ArrayList(Arrays.asList(items)); + return new MassiveList(Arrays.asList(items)); } @SafeVarargs public static Set set(T... items) { - return new LinkedHashSet(Arrays.asList(items)); + return new MassiveSet(Arrays.asList(items)); } - @SuppressWarnings("unchecked") - @SafeVarargs - public static Set treeset(T... items) + public static Set treeset(String... items) { - Set ret; - if (items[0] instanceof String) - { - ret = (Set) new TreeSet(String.CASE_INSENSITIVE_ORDER); - } - else - { - ret = new TreeSet(); - } - ret.addAll(Arrays.asList(items)); - return ret; + return new MassiveTreeSet(CaseInsensitiveComparator.get(), Arrays.asList(items)); } @SuppressWarnings("unchecked") @@ -750,12 +740,29 @@ public class MUtil public static int compare(Comparable herp, T derp) { - if (herp == null && derp == null) return 0; - if (herp == null) return -1; - if (derp == null) return +1; + Integer ret = compareNulls(herp, derp); + if (ret != null) return ret; return herp.compareTo(derp); } + public static Integer compareNulls(Object one, Object two) + { + if (one == null && two == null) return 0; + if (one == null) return -1; + if (two == null) return +1; + return null; + } + + public static Integer compareWithList(Object one, Object two, List list) + { + int oneIndex = list.indexOf(one); + int twoIndex = list.indexOf(two); + if (oneIndex != -1 && twoIndex != -1) return oneIndex - twoIndex; + if (oneIndex != -1) return -1; + if (twoIndex != -1) return +1; + return null; + } + // -------------------------------------------- // // SORTING // -------------------------------------------- //