summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsnowleo <schneeleo@gmail.com>2011-11-23 02:43:38 +0100
committersnowleo <schneeleo@gmail.com>2011-11-23 02:43:38 +0100
commit8aaaed2ef8aa09597f76f8aec6f7b2e5b89d111b (patch)
tree1dd70fe9603ab5eccb3e638ea1a4f8a29caacd0c
parente683ce575120334ccc7de6285d12fa9f518b414f (diff)
downloadEssentials-8aaaed2ef8aa09597f76f8aec6f7b2e5b89d111b.tar
Essentials-8aaaed2ef8aa09597f76f8aec6f7b2e5b89d111b.tar.gz
Essentials-8aaaed2ef8aa09597f76f8aec6f7b2e5b89d111b.tar.lz
Essentials-8aaaed2ef8aa09597f76f8aec6f7b2e5b89d111b.tar.xz
Essentials-8aaaed2ef8aa09597f76f8aec6f7b2e5b89d111b.zip
More work on the config code
-rw-r--r--Essentials/src/com/earth2me/essentials/UserData.java5
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Backup.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Chat.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Commands.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Economy.java7
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/General.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/GroupOptions.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Groups.java6
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Location.java28
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Locations.java22
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Settings.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Worth.java29
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/commands/Afk.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/commands/God.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/commands/Help.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/commands/Home.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/commands/Kit.java13
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/commands/KitObject.java7
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/commands/Lightning.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/commands/Spawnmob.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java182
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/IStorageReader.java7
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/IStorageWriter.java7
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/MapKeyType.java (renamed from Essentials/src/com/earth2me/essentials/storage/MapType.java)2
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/MapValueType.java14
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/StorageObject.java239
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/YamlStorageReader.java126
-rw-r--r--Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java295
-rw-r--r--Essentials/src/com/earth2me/essentials/userdata/Ban.java14
-rw-r--r--Essentials/src/com/earth2me/essentials/userdata/Inventory.java27
-rw-r--r--Essentials/src/com/earth2me/essentials/userdata/User.java65
-rw-r--r--Essentials/src/com/earth2me/essentials/userdata/UserData.java61
-rw-r--r--Essentials/test/com/earth2me/essentials/FakeServer.java12
-rw-r--r--Essentials/test/com/earth2me/essentials/StorageTest.java122
34 files changed, 1016 insertions, 298 deletions
diff --git a/Essentials/src/com/earth2me/essentials/UserData.java b/Essentials/src/com/earth2me/essentials/UserData.java
index 777ea981d..d9dad769d 100644
--- a/Essentials/src/com/earth2me/essentials/UserData.java
+++ b/Essentials/src/com/earth2me/essentials/UserData.java
@@ -862,4 +862,9 @@ public abstract class UserData extends PlayerExtension implements IConf
config.setProperty("timestamps.kits", kitTimestamps);
config.save();
}
+
+ public void save()
+ {
+ config.save();
+ }
}
diff --git a/Essentials/src/com/earth2me/essentials/settings/Backup.java b/Essentials/src/com/earth2me/essentials/settings/Backup.java
index 1b59260db..f43af47c0 100644
--- a/Essentials/src/com/earth2me/essentials/settings/Backup.java
+++ b/Essentials/src/com/earth2me/essentials/settings/Backup.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Backup extends StorageObject
+public class Backup implements StorageObject
{
@Comment("Interval in minutes")
private long interval = 60;
diff --git a/Essentials/src/com/earth2me/essentials/settings/Chat.java b/Essentials/src/com/earth2me/essentials/settings/Chat.java
index d20d1dc68..623228c4e 100644
--- a/Essentials/src/com/earth2me/essentials/settings/Chat.java
+++ b/Essentials/src/com/earth2me/essentials/settings/Chat.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Chat extends StorageObject
+public class Chat implements StorageObject
{
@Comment("The character(s) to prefix all nicknames, so that you know they are not true usernames.")
private String nicknamePrefix = "~";
diff --git a/Essentials/src/com/earth2me/essentials/settings/Commands.java b/Essentials/src/com/earth2me/essentials/settings/Commands.java
index ed4c3595b..08efc881c 100644
--- a/Essentials/src/com/earth2me/essentials/settings/Commands.java
+++ b/Essentials/src/com/earth2me/essentials/settings/Commands.java
@@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Commands extends StorageObject
+public class Commands implements StorageObject
{
private Afk afk = new Afk();
private God god = new God();
diff --git a/Essentials/src/com/earth2me/essentials/settings/Economy.java b/Essentials/src/com/earth2me/essentials/settings/Economy.java
index b18f05b96..5872dada9 100644
--- a/Essentials/src/com/earth2me/essentials/settings/Economy.java
+++ b/Essentials/src/com/earth2me/essentials/settings/Economy.java
@@ -1,7 +1,7 @@
package com.earth2me.essentials.settings;
import com.earth2me.essentials.storage.Comment;
-import com.earth2me.essentials.storage.MapType;
+import com.earth2me.essentials.storage.MapValueType;
import com.earth2me.essentials.storage.StorageObject;
import java.util.HashMap;
import java.util.Map;
@@ -11,11 +11,11 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Economy extends StorageObject
+public class Economy implements StorageObject
{
@Comment("Defines the balance with which new players begin. Defaults to 0.")
private double startingBalance = 0.0;
- @MapType(Double.class)
+ @MapValueType(Double.class)
@Comment("Defines the cost to use the given commands PER USE")
private Map<String, Double> commandCosts = new HashMap<String, Double>();
@Comment("Set this to a currency symbol you want to use.")
@@ -39,4 +39,5 @@ public class Economy extends StorageObject
}
@Comment("Enable this to log all interactions with trade/buy/sell signs and sell command")
private boolean logEnabled = false;
+ private Worth worth = new Worth();
}
diff --git a/Essentials/src/com/earth2me/essentials/settings/General.java b/Essentials/src/com/earth2me/essentials/settings/General.java
index 77143eb1a..a7cf537bb 100644
--- a/Essentials/src/com/earth2me/essentials/settings/General.java
+++ b/Essentials/src/com/earth2me/essentials/settings/General.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class General extends StorageObject
+public class General implements StorageObject
{
@Comment("Backup runs a command while saving is disabled")
private Backup backup = new Backup();
diff --git a/Essentials/src/com/earth2me/essentials/settings/GroupOptions.java b/Essentials/src/com/earth2me/essentials/settings/GroupOptions.java
index 1e0137302..7b16a471b 100644
--- a/Essentials/src/com/earth2me/essentials/settings/GroupOptions.java
+++ b/Essentials/src/com/earth2me/essentials/settings/GroupOptions.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class GroupOptions extends StorageObject
+public class GroupOptions implements StorageObject
{
@Comment("Message format of chat messages")
private String messageFormat;
diff --git a/Essentials/src/com/earth2me/essentials/settings/Groups.java b/Essentials/src/com/earth2me/essentials/settings/Groups.java
index 64b391300..5e67db890 100644
--- a/Essentials/src/com/earth2me/essentials/settings/Groups.java
+++ b/Essentials/src/com/earth2me/essentials/settings/Groups.java
@@ -1,7 +1,7 @@
package com.earth2me.essentials.settings;
import com.earth2me.essentials.storage.Comment;
-import com.earth2me.essentials.storage.MapType;
+import com.earth2me.essentials.storage.MapValueType;
import com.earth2me.essentials.storage.StorageObject;
import java.util.LinkedHashMap;
import lombok.Data;
@@ -10,7 +10,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Groups extends StorageObject
+public class Groups implements StorageObject
{
public Groups()
{
@@ -23,6 +23,6 @@ public class Groups extends StorageObject
"All group names have to be lower case.",
"The groups can be connected to users using the permission essentials.groups.groupname"
})
- @MapType(GroupOptions.class)
+ @MapValueType(GroupOptions.class)
private LinkedHashMap<String, GroupOptions> groups = new LinkedHashMap<String, GroupOptions>();
}
diff --git a/Essentials/src/com/earth2me/essentials/settings/Location.java b/Essentials/src/com/earth2me/essentials/settings/Location.java
deleted file mode 100644
index 0535fdf52..000000000
--- a/Essentials/src/com/earth2me/essentials/settings/Location.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.earth2me.essentials.settings;
-
-import com.earth2me.essentials.storage.StorageObject;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import org.bukkit.Server;
-
-
-@Data
-@EqualsAndHashCode(callSuper = false)
-public class Location extends StorageObject
-{
- private String worldName = "Test";
- private double x;
- private double y;
- private double z;
- private Float yaw;
- private Float pitch;
-
- public org.bukkit.Location getBukkit(Server server)
- {
- if (yaw == null || pitch == null)
- {
- return new org.bukkit.Location(server.getWorld(worldName), x, y, z);
- }
- return new org.bukkit.Location(server.getWorld(worldName), x, y, z, yaw, pitch);
- }
-}
diff --git a/Essentials/src/com/earth2me/essentials/settings/Locations.java b/Essentials/src/com/earth2me/essentials/settings/Locations.java
new file mode 100644
index 000000000..7e7f1a63d
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/settings/Locations.java
@@ -0,0 +1,22 @@
+package com.earth2me.essentials.settings;
+
+import com.earth2me.essentials.storage.MapValueType;
+import com.earth2me.essentials.storage.StorageObject;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.bukkit.Location;
+
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class Locations implements StorageObject
+{
+ @MapValueType(Location.class)
+ Map<String, Location> jails = new HashMap<String, Location>();
+ @MapValueType(Location.class)
+ Map<String, Location> warps = new HashMap<String, Location>();
+ @MapValueType(Location.class)
+ Map<String, Location> spawns = new HashMap<String, Location>();
+}
diff --git a/Essentials/src/com/earth2me/essentials/settings/Settings.java b/Essentials/src/com/earth2me/essentials/settings/Settings.java
index 890bfef4e..4c2ff2dd9 100644
--- a/Essentials/src/com/earth2me/essentials/settings/Settings.java
+++ b/Essentials/src/com/earth2me/essentials/settings/Settings.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Settings extends StorageObject
+public class Settings implements StorageObject
{
@Comment(
{
diff --git a/Essentials/src/com/earth2me/essentials/settings/Worth.java b/Essentials/src/com/earth2me/essentials/settings/Worth.java
new file mode 100644
index 000000000..939cdd883
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/settings/Worth.java
@@ -0,0 +1,29 @@
+package com.earth2me.essentials.settings;
+
+import com.earth2me.essentials.storage.MapKeyType;
+import com.earth2me.essentials.storage.MapValueType;
+import com.earth2me.essentials.storage.StorageObject;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.bukkit.Material;
+import org.bukkit.material.MaterialData;
+
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class Worth implements StorageObject
+{
+ @MapKeyType(MaterialData.class)
+ @MapValueType(Double.class)
+ private Map<MaterialData, Double> sell = new HashMap<MaterialData, Double>();
+ @MapKeyType(MaterialData.class)
+ @MapValueType(Double.class)
+ private Map<MaterialData, Double> buy = new HashMap<MaterialData, Double>();
+
+ public Worth()
+ {
+ sell.put(new MaterialData(Material.APPLE, (byte)0), 1.0);
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/Afk.java b/Essentials/src/com/earth2me/essentials/settings/commands/Afk.java
index 20076c273..80cae7e8a 100644
--- a/Essentials/src/com/earth2me/essentials/settings/commands/Afk.java
+++ b/Essentials/src/com/earth2me/essentials/settings/commands/Afk.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Afk extends StorageObject
+public class Afk implements StorageObject
{
@Comment(
{
diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/God.java b/Essentials/src/com/earth2me/essentials/settings/commands/God.java
index 3b38b70b0..a6f5dbfc3 100644
--- a/Essentials/src/com/earth2me/essentials/settings/commands/God.java
+++ b/Essentials/src/com/earth2me/essentials/settings/commands/God.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class God extends StorageObject
+public class God implements StorageObject
{
@Comment("Turn off god mode when people exit")
private boolean removeOnDisconnect = false;
diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/Help.java b/Essentials/src/com/earth2me/essentials/settings/commands/Help.java
index 03a9d5958..0b4787471 100644
--- a/Essentials/src/com/earth2me/essentials/settings/commands/Help.java
+++ b/Essentials/src/com/earth2me/essentials/settings/commands/Help.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Help extends StorageObject
+public class Help implements StorageObject
{
@Comment("Show other plugins commands in help")
private boolean showNonEssCommandsInHelp = true;
diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/Home.java b/Essentials/src/com/earth2me/essentials/settings/commands/Home.java
index 6ec2f1339..8b3a0ca82 100644
--- a/Essentials/src/com/earth2me/essentials/settings/commands/Home.java
+++ b/Essentials/src/com/earth2me/essentials/settings/commands/Home.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Home extends StorageObject
+public class Home implements StorageObject
{
@Comment("When players die, should they respawn at their homes, instead of the spawnpoint?")
private boolean respawnAtHome = false;
diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/Kit.java b/Essentials/src/com/earth2me/essentials/settings/commands/Kit.java
index bd7c15eab..87aa42d3c 100644
--- a/Essentials/src/com/earth2me/essentials/settings/commands/Kit.java
+++ b/Essentials/src/com/earth2me/essentials/settings/commands/Kit.java
@@ -1,25 +1,28 @@
package com.earth2me.essentials.settings.commands;
-import com.earth2me.essentials.storage.MapType;
+import com.earth2me.essentials.storage.MapValueType;
import com.earth2me.essentials.storage.StorageObject;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Kit extends StorageObject
+public class Kit implements StorageObject
{
public Kit()
{
final KitObject kit = new KitObject();
kit.setDelay(10.0);
- kit.setItems(Arrays.asList("277 1,278 1,279 1".split(",")));
+ kit.getItems().add(new ItemStack(Material.DIAMOND_SPADE, 1));
+ kit.getItems().add(new ItemStack(Material.DIAMOND_PICKAXE, 1));
+ kit.getItems().add(new ItemStack(Material.DIAMOND_AXE, 1));
kits.put("tools", kit);
}
- @MapType(KitObject.class)
+ @MapValueType(KitObject.class)
private Map<String, KitObject> kits = new HashMap<String, KitObject>();
}
diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/KitObject.java b/Essentials/src/com/earth2me/essentials/settings/commands/KitObject.java
index 93f6c6ade..fe0353be9 100644
--- a/Essentials/src/com/earth2me/essentials/settings/commands/KitObject.java
+++ b/Essentials/src/com/earth2me/essentials/settings/commands/KitObject.java
@@ -6,13 +6,14 @@ import java.util.ArrayList;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import org.bukkit.inventory.ItemStack;
@Data
@EqualsAndHashCode(callSuper = false)
-public class KitObject extends StorageObject
+public class KitObject implements StorageObject
{
- @ListType
- private List<String> items = new ArrayList<String>();
+ @ListType(ItemStack.class)
+ private List<ItemStack> items = new ArrayList<ItemStack>();
private Double delay;
}
diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/Lightning.java b/Essentials/src/com/earth2me/essentials/settings/commands/Lightning.java
index b70bd0abf..e40e645da 100644
--- a/Essentials/src/com/earth2me/essentials/settings/commands/Lightning.java
+++ b/Essentials/src/com/earth2me/essentials/settings/commands/Lightning.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Lightning extends StorageObject
+public class Lightning implements StorageObject
{
@Comment("Shall we notify users when using /lightning")
private boolean warnPlayer = true;
diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/Spawnmob.java b/Essentials/src/com/earth2me/essentials/settings/commands/Spawnmob.java
index 3c338b443..37d41c296 100644
--- a/Essentials/src/com/earth2me/essentials/settings/commands/Spawnmob.java
+++ b/Essentials/src/com/earth2me/essentials/settings/commands/Spawnmob.java
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
-public class Spawnmob extends StorageObject
+public class Spawnmob implements StorageObject
{
@Comment("The maximum amount of monsters, a player can spawn with a call of /spawnmob.")
private int limit = 10;
diff --git a/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java b/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java
new file mode 100644
index 000000000..2656d183d
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java
@@ -0,0 +1,182 @@
+package com.earth2me.essentials.storage;
+
+import java.util.regex.Pattern;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.material.MaterialData;
+import org.yaml.snakeyaml.constructor.Constructor;
+import org.yaml.snakeyaml.nodes.MappingNode;
+import org.yaml.snakeyaml.nodes.Node;
+import org.yaml.snakeyaml.nodes.NodeId;
+import org.yaml.snakeyaml.nodes.NodeTuple;
+import org.yaml.snakeyaml.nodes.ScalarNode;
+
+
+public class BukkitConstructor extends Constructor
+{
+ private final transient Pattern NUMPATTERN = Pattern.compile("\\d+");
+
+ public BukkitConstructor(Class clazz)
+ {
+ super(clazz);
+ yamlClassConstructors.put(NodeId.scalar, new ConstructBukkitScalar());
+ yamlClassConstructors.put(NodeId.mapping, new ConstructBukkitMapping());
+ }
+
+
+ private class ConstructBukkitScalar extends ConstructScalar
+ {
+ @Override
+ public Object construct(final Node node)
+ {
+ if (node.getType().equals(Material.class))
+ {
+ final String val = (String)constructScalar((ScalarNode)node);
+ Material mat;
+ if (NUMPATTERN.matcher(val).matches())
+ {
+ final int typeId = Integer.parseInt(val);
+ mat = Material.getMaterial(typeId);
+ }
+ else
+ {
+ mat = Material.matchMaterial(val);
+ }
+ return mat;
+ }
+ if (node.getType().equals(MaterialData.class))
+ {
+ final String val = (String)constructScalar((ScalarNode)node);
+ if (val.isEmpty())
+ {
+ return null;
+ }
+ final String[] split = val.split("[:+',;.]", 2);
+ if (split.length == 0)
+ {
+ return null;
+ }
+ Material mat;
+ if (NUMPATTERN.matcher(split[0]).matches())
+ {
+ final int typeId = Integer.parseInt(split[0]);
+ mat = Material.getMaterial(typeId);
+ }
+ else
+ {
+ mat = Material.matchMaterial(split[0]);
+ }
+ byte data = 0;
+ if (split.length == 2 && NUMPATTERN.matcher(split[1]).matches())
+ {
+ data = Byte.parseByte(split[1]);
+ }
+ return new MaterialData(mat, data);
+ }
+ if (node.getType().equals(ItemStack.class))
+ {
+ final String val = (String)constructScalar((ScalarNode)node);
+ if (val.isEmpty())
+ {
+ return null;
+ }
+ final String[] split1 = val.split("\\W", 2);
+ if (split1.length == 0)
+ {
+ return null;
+ }
+ final String[] split2 = split1[0].split("[:+',;.]", 2);
+ if (split2.length == 0)
+ {
+ return null;
+ }
+ Material mat;
+ if (NUMPATTERN.matcher(split2[0]).matches())
+ {
+ final int typeId = Integer.parseInt(split2[0]);
+ mat = Material.getMaterial(typeId);
+ }
+ else
+ {
+ mat = Material.matchMaterial(split2[0]);
+ }
+ short data = 0;
+ if (split2.length == 2 && NUMPATTERN.matcher(split2[1]).matches())
+ {
+ data = Short.parseShort(split2[1]);
+ }
+ int size = mat.getMaxStackSize();
+ if (split1.length == 2 && NUMPATTERN.matcher(split1[1]).matches())
+ {
+ size = Integer.parseInt(split1[1]);
+ }
+ return new ItemStack(mat, size, data);
+ }
+ return super.construct(node);
+ }
+ }
+
+
+ private class ConstructBukkitMapping extends ConstructMapping
+ {
+ @Override
+ public Object construct(final Node node)
+ {
+ if (node.getType().equals(Location.class))
+ {
+ //TODO: NPE checks
+ final MappingNode mnode = (MappingNode)node;
+ String worldName = "";
+ double x = 0, y = 0, z = 0;
+ float yaw = 0, pitch = 0;
+ if (mnode.getValue().size() < 4)
+ {
+ return null;
+ }
+ for (NodeTuple nodeTuple : mnode.getValue())
+ {
+ final String key = (String)constructScalar((ScalarNode)nodeTuple.getKeyNode());
+ final ScalarNode snode = (ScalarNode)nodeTuple.getValueNode();
+ if (key.equalsIgnoreCase("world"))
+ {
+ worldName = (String)constructScalar(snode);
+ }
+ if (key.equalsIgnoreCase("x"))
+ {
+ x = Double.parseDouble((String)constructScalar(snode));
+ }
+ if (key.equalsIgnoreCase("y"))
+ {
+ y = Double.parseDouble((String)constructScalar(snode));
+ }
+ if (key.equalsIgnoreCase("z"))
+ {
+ z = Double.parseDouble((String)constructScalar(snode));
+ }
+ if (key.equalsIgnoreCase("yaw"))
+ {
+ yaw = Float.parseFloat((String)constructScalar(snode));
+ }
+ if (key.equalsIgnoreCase("pitch"))
+ {
+ pitch = Float.parseFloat((String)constructScalar(snode));
+ }
+ }
+ if (worldName == null || worldName.isEmpty())
+ {
+ return null;
+ }
+ final World world = Bukkit.getWorld(worldName);
+ if (world == null)
+ {
+ return null;
+ }
+ return new Location(world, x, y, z, yaw, pitch);
+ }
+ return super.construct(node);
+ }
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/storage/IStorageReader.java b/Essentials/src/com/earth2me/essentials/storage/IStorageReader.java
new file mode 100644
index 000000000..5e259a322
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/storage/IStorageReader.java
@@ -0,0 +1,7 @@
+package com.earth2me.essentials.storage;
+
+
+public interface IStorageReader
+{
+ <T extends StorageObject> T load(final Class<? extends T> clazz);
+}
diff --git a/Essentials/src/com/earth2me/essentials/storage/IStorageWriter.java b/Essentials/src/com/earth2me/essentials/storage/IStorageWriter.java
new file mode 100644
index 000000000..5b8498869
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/storage/IStorageWriter.java
@@ -0,0 +1,7 @@
+package com.earth2me.essentials.storage;
+
+
+public interface IStorageWriter
+{
+ void save(final StorageObject object);
+}
diff --git a/Essentials/src/com/earth2me/essentials/storage/MapType.java b/Essentials/src/com/earth2me/essentials/storage/MapKeyType.java
index dc5636315..aa162e51c 100644
--- a/Essentials/src/com/earth2me/essentials/storage/MapType.java
+++ b/Essentials/src/com/earth2me/essentials/storage/MapKeyType.java
@@ -8,7 +8,7 @@ import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
-public @interface MapType
+public @interface MapKeyType
{
Class value() default String.class;
} \ No newline at end of file
diff --git a/Essentials/src/com/earth2me/essentials/storage/MapValueType.java b/Essentials/src/com/earth2me/essentials/storage/MapValueType.java
new file mode 100644
index 000000000..1b5fff978
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/storage/MapValueType.java
@@ -0,0 +1,14 @@
+package com.earth2me.essentials.storage;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MapValueType
+{
+ Class value() default String.class;
+} \ No newline at end of file
diff --git a/Essentials/src/com/earth2me/essentials/storage/StorageObject.java b/Essentials/src/com/earth2me/essentials/storage/StorageObject.java
index cd144f424..0c66fefcf 100644
--- a/Essentials/src/com/earth2me/essentials/storage/StorageObject.java
+++ b/Essentials/src/com/earth2me/essentials/storage/StorageObject.java
@@ -1,243 +1,6 @@
package com.earth2me.essentials.storage;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.Map.Entry;
-import java.util.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import org.yaml.snakeyaml.DumperOptions;
-import org.yaml.snakeyaml.TypeDescription;
-import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.constructor.Constructor;
-
-public class StorageObject
+public interface StorageObject
{
- protected Class<? extends StorageObject> clazz;
-
- protected StorageObject()
- {
- }
- private static Map<Class, Constructor> constructors = new HashMap<Class, Constructor>();
-
- public static <T extends StorageObject> T load(Class<? extends T> clazz, Reader reader)
- {
- Constructor constructor;
- if (constructors.containsKey(clazz))
- {
- constructor = constructors.get(clazz);
- }
- else
- {
- constructor = prepareConstructor(clazz);
- constructors.put(clazz, constructor);
- }
-
- final Yaml yaml = new Yaml(constructor);
- T ret = (T)yaml.load(reader);
- if (ret == null)
- {
- try
- {
- ret = (T)clazz.newInstance();
- }
- catch (InstantiationException ex)
- {
- Logger.getLogger(StorageObject.class.getName()).log(Level.SEVERE, null, ex);
- }
- catch (IllegalAccessException ex)
- {
- Logger.getLogger(StorageObject.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
- ret.clazz = clazz;
- return ret;
- }
-
- private static Constructor prepareConstructor(final Class<?> clazz)
- {
- final Constructor constructor = new Constructor(clazz);
- final Set<Class> classes = new HashSet<Class>();
-
- prepareConstructor(constructor, classes, clazz);
- return constructor;
- }
-
- private static void prepareConstructor(final Constructor constructor, final Set<Class> classes, final Class clazz)
- {
- classes.add(clazz);
- final TypeDescription description = new TypeDescription(clazz);
- for (Field field : clazz.getDeclaredFields())
- {
- final ListType listType = field.getAnnotation(ListType.class);
- if (listType != null)
- {
- description.putListPropertyType(field.getName(), listType.value());
- if (StorageObject.class.isAssignableFrom(listType.value())
- && !classes.contains(listType.value()))
- {
- prepareConstructor(constructor, classes, listType.value());
- }
- }
- final MapType mapType = field.getAnnotation(MapType.class);
- if (mapType != null)
- {
- description.putMapPropertyType(field.getName(), String.class, mapType.value());
- if (StorageObject.class.isAssignableFrom(mapType.value())
- && !classes.contains(mapType.value()))
- {
- prepareConstructor(constructor, classes, mapType.value());
- }
- }
- if (StorageObject.class.isAssignableFrom(field.getType())
- && !classes.contains(field.getType()))
- {
- prepareConstructor(constructor, classes, field.getType());
- }
- }
- constructor.addTypeDescription(description);
- }
- private transient Yaml yaml;
-
- public void save(final PrintWriter writer)
- {
- final DumperOptions ops = new DumperOptions();
- yaml = new Yaml(ops);
- try
- {
- writeToFile(this, writer, 0, clazz);
- }
- catch (IllegalArgumentException ex)
- {
- Logger.getLogger(StorageObject.class.getName()).log(Level.SEVERE, null, ex);
- }
- catch (IllegalAccessException ex)
- {
- Logger.getLogger(StorageObject.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- private void writeToFile(final Object object, final PrintWriter writer, final int depth, final Class clazz) throws IllegalArgumentException, IllegalAccessException
- {
- for (Field field : clazz.getDeclaredFields())
- {
- final int modifier = field.getModifiers();
- if (Modifier.isPrivate(modifier) && !Modifier.isTransient(modifier) && !Modifier.isStatic(modifier))
- {
- field.setAccessible(true);
- final boolean commentPresent = field.isAnnotationPresent(Comment.class);
- final String name = field.getName();
- if (commentPresent)
- {
- final Comment comments = field.getAnnotation(Comment.class);
- for (String comment : comments.value())
- {
- final String trimmed = comment.trim();
- if (trimmed.isEmpty())
- {
- continue;
- }
- writeIndention(writer, depth);
- writer.print("# ");
- writer.print(trimmed);
- writer.println();
- }
- }
-
- final Object data = field.get(object);
- if (data == null && !commentPresent)
- {
- continue;
- }
- writeIndention(writer, depth);
- if (data == null && commentPresent)
- {
- writer.print('#');
- }
- writer.print(name);
- writer.print(": ");
- if (data == null && commentPresent)
- {
- writer.println();
- writer.println();
- continue;
- }
- if (data instanceof StorageObject)
- {
- writer.println();
- writeToFile(data, writer, depth + 1, data.getClass());
- }
- else if (data instanceof Map)
- {
- writer.println();
- for (Entry<String, Object> entry : ((Map<String, Object>)data).entrySet())
- {
- final Object value = entry.getValue();
- if (value != null)
- {
- writeIndention(writer, depth + 1);
- writer.print(entry.getKey());
- writer.print(": ");
- if (value instanceof StorageObject)
- {
- writer.println();
- writeToFile(value, writer, depth + 2, value.getClass());
- }
- else if (value instanceof String || value instanceof Boolean || value instanceof Number)
- {
- yaml.dumpAll(Collections.singletonList(value).iterator(), writer);
- writer.println();
- }
- else
- {
- throw new UnsupportedOperationException();
- }
-
- }
- }
- }
- else if (data instanceof Collection)
- {
- writer.println();
- for (Object entry : (Collection<Object>)data)
- {
- if (entry != null)
- {
- writeIndention(writer, depth + 1);
- writer.print("- ");
- if (entry instanceof String || entry instanceof Boolean || entry instanceof Number)
- {
- yaml.dumpAll(Collections.singletonList(entry).iterator(), writer);
- }
- else
- {
- throw new UnsupportedOperationException();
- }
- }
- }
- writer.println();
- }
- else if (data instanceof String || data instanceof Boolean || data instanceof Number)
- {
- yaml.dumpAll(Collections.singletonList(data).iterator(), writer);
- writer.println();
- }
- else
- {
- throw new UnsupportedOperationException();
- }
- }
- }
- }
-
- private void writeIndention(final PrintWriter writer, final int depth)
- {
- for (int i = 0; i < depth; i++)
- {
- writer.print(" ");
- }
- }
}
diff --git a/Essentials/src/com/earth2me/essentials/storage/YamlStorageReader.java b/Essentials/src/com/earth2me/essentials/storage/YamlStorageReader.java
new file mode 100644
index 000000000..2881c1f18
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/storage/YamlStorageReader.java
@@ -0,0 +1,126 @@
+package com.earth2me.essentials.storage;
+
+import java.io.Reader;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.yaml.snakeyaml.TypeDescription;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+
+public class YamlStorageReader implements IStorageReader
+{
+ private transient static Map<Class, Yaml> preparedYamls = Collections.synchronizedMap(new HashMap<Class, Yaml>());
+ private transient static Map<Class, ReentrantLock> locks = new HashMap<Class, ReentrantLock>();
+ private transient final Reader reader;
+
+ public YamlStorageReader(final Reader reader)
+ {
+ this.reader = reader;
+ }
+
+ public <T extends StorageObject> T load(final Class<? extends T> clazz)
+ {
+ Yaml yaml = preparedYamls.get(clazz);
+ if (yaml == null)
+ {
+ yaml = new Yaml(prepareConstructor(clazz));
+ preparedYamls.put(clazz, yaml);
+ }
+ ReentrantLock lock;
+ synchronized (locks)
+ {
+ lock = locks.get(clazz);
+ if (lock == null)
+ {
+ lock = new ReentrantLock();
+ }
+ }
+ T ret;
+ lock.lock();
+ try
+ {
+ ret = (T)yaml.load(reader);
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ if (ret == null)
+ {
+ try
+ {
+ ret = (T)clazz.newInstance();
+ }
+ catch (InstantiationException ex)
+ {
+ Logger.getLogger(StorageObject.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ catch (IllegalAccessException ex)
+ {
+ Logger.getLogger(StorageObject.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ return ret;
+ }
+
+ private static Constructor prepareConstructor(final Class<?> clazz)
+ {
+ final Constructor constructor = new BukkitConstructor(clazz);
+ final Set<Class> classes = new HashSet<Class>();
+
+ prepareConstructor(constructor, classes, clazz);
+ return constructor;
+ }
+
+ private static void prepareConstructor(final Constructor constructor, final Set<Class> classes, final Class clazz)
+ {
+ classes.add(clazz);
+ final TypeDescription description = new TypeDescription(clazz);
+ for (Field field : clazz.getDeclaredFields())
+ {
+ prepareList(field, description, classes, constructor);
+ prepareMap(field, description, classes, constructor);
+ if (StorageObject.class.isAssignableFrom(field.getType())
+ && !classes.contains(field.getType()))
+ {
+ prepareConstructor(constructor, classes, field.getType());
+ }
+ }
+ constructor.addTypeDescription(description);
+ }
+
+ private static void prepareList(final Field field, final TypeDescription description, final Set<Class> classes, final Constructor constructor)
+ {
+ final ListType listType = field.getAnnotation(ListType.class);
+ if (listType != null)
+ {
+ description.putListPropertyType(field.getName(), listType.value());
+ if (StorageObject.class.isAssignableFrom(listType.value())
+ && !classes.contains(listType.value()))
+ {
+ prepareConstructor(constructor, classes, listType.value());
+ }
+ }
+ }
+
+ private static void prepareMap(final Field field, final TypeDescription description, final Set<Class> classes, final Constructor constructor)
+ {
+ final MapValueType mapType = field.getAnnotation(MapValueType.class);
+ if (mapType != null)
+ {
+ final MapKeyType mapKeyType = field.getAnnotation(MapKeyType.class);
+ description.putMapPropertyType(field.getName(),
+ mapKeyType == null ? String.class : mapKeyType.value(),
+ mapType.value());
+ if (StorageObject.class.isAssignableFrom(mapType.value())
+ && !classes.contains(mapType.value()))
+ {
+ prepareConstructor(constructor, classes, mapType.value());
+ }
+ }
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java b/Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java
new file mode 100644
index 000000000..209de1ed7
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java
@@ -0,0 +1,295 @@
+package com.earth2me.essentials.storage;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.material.MaterialData;
+import org.yaml.snakeyaml.Yaml;
+
+
+public class YamlStorageWriter implements IStorageWriter
+{
+ private transient static Pattern pattern = Pattern.compile("\\w");
+ private transient final PrintWriter writer;
+ private transient static final Yaml YAML = new Yaml();
+
+ public YamlStorageWriter(final PrintWriter writer)
+ {
+ this.writer = writer;
+ }
+
+ public void save(final StorageObject object)
+ {
+ try
+ {
+ writeToFile(object, 0, object.getClass());
+ }
+ catch (IllegalArgumentException ex)
+ {
+ Logger.getLogger(YamlStorageWriter.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ catch (IllegalAccessException ex)
+ {
+ Logger.getLogger(YamlStorageWriter.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ private void writeToFile(final Object object, final int depth, final Class clazz) throws IllegalAccessException
+ {
+ for (Field field : clazz.getDeclaredFields())
+ {
+ final int modifier = field.getModifiers();
+ if (Modifier.isPrivate(modifier) && !Modifier.isTransient(modifier) && !Modifier.isStatic(modifier))
+ {
+ field.setAccessible(true);
+
+ final Object data = field.get(object);
+ if (writeKey(field, depth, data))
+ {
+ continue;
+ }
+ if (data instanceof StorageObject)
+ {
+ writer.println();
+ writeToFile(data, depth + 1, data.getClass());
+ }
+ else if (data instanceof Map)
+ {
+ writeMap((Map<Object, Object>)data, depth + 1);
+ }
+ else if (data instanceof Collection)
+ {
+ writeCollection((Collection<Object>)data, depth + 1);
+ }
+ else if (data instanceof Location)
+ {
+ writeLocation((Location)data, depth + 1);
+ }
+ else
+ {
+ writeScalar(data);
+ writer.println();
+ }
+ }
+ }
+ }
+
+ private boolean writeKey(final Field field, final int depth, final Object data)
+ {
+ final boolean commentPresent = writeComment(field, depth);
+ if (data == null && !commentPresent)
+ {
+ return true;
+ }
+ writeIndention(depth);
+ if (data == null && commentPresent)
+ {
+ writer.print('#');
+ }
+ final String name = field.getName();
+ writer.print(name);
+ writer.print(": ");
+ if (data == null && commentPresent)
+ {
+ writer.println();
+ writer.println();
+ return true;
+ }
+ return false;
+ }
+
+ private boolean writeComment(final Field field, final int depth)
+ {
+ final boolean commentPresent = field.isAnnotationPresent(Comment.class);
+ if (commentPresent)
+ {
+ final Comment comments = field.getAnnotation(Comment.class);
+ for (String comment : comments.value())
+ {
+ final String trimmed = comment.trim();
+ if (trimmed.isEmpty())
+ {
+ continue;
+ }
+ writeIndention(depth);
+ writer.print("# ");
+ writer.print(trimmed);
+ writer.println();
+ }
+ }
+ return commentPresent;
+ }
+
+ private void writeCollection(final Collection<Object> data, final int depth) throws IllegalAccessException
+ {
+ writer.println();
+ if (data.isEmpty())
+ {
+ writer.println();
+ }
+ for (Object entry : data)
+ {
+ if (entry != null)
+ {
+ writeIndention(depth);
+ writer.print("- ");
+ if (entry instanceof StorageObject)
+ {
+ writer.println();
+ writeToFile(entry, depth + 1, entry.getClass());
+ }
+ else if (entry instanceof Location)
+ {
+ writeLocation((Location)entry, depth + 1);
+ }
+ else
+ {
+ writeScalar(entry);
+ }
+ }
+ }
+ writer.println();
+ }
+
+ private void writeMap(final Map<Object, Object> data, final int depth) throws IllegalArgumentException, IllegalAccessException
+ {
+ writer.println();
+ if (data.isEmpty())
+ {
+ writer.println();
+ }
+ for (Entry<Object, Object> entry : data.entrySet())
+ {
+ final Object value = entry.getValue();
+ if (value != null)
+ {
+ writeIndention(depth);
+ writeKey(entry.getKey());
+ writer.print(": ");
+ if (value instanceof StorageObject)
+ {
+ writer.println();
+ writeToFile(value, depth + 1, value.getClass());
+ }
+ else if (value instanceof Collection)
+ {
+ writeCollection((Collection<Object>)value, depth + 1);
+ }
+ else if (value instanceof Location)
+ {
+ writeLocation((Location)value, depth + 1);
+ }
+ else
+ {
+ writeScalar(value);
+ writer.println();
+ }
+ }
+ }
+ }
+
+ private void writeIndention(final int depth)
+ {
+ for (int i = 0; i < depth; i++)
+ {
+ writer.print(" ");
+ }
+ }
+
+ private void writeScalar(final Object data)
+ {
+ if (data instanceof String || data instanceof Boolean || data instanceof Number)
+ {
+ synchronized (YAML)
+ {
+ YAML.dumpAll(Collections.singletonList(data).iterator(), writer);
+ }
+ }
+ else if (data instanceof Material)
+ {
+ writer.println(data.toString().toLowerCase());
+ }
+ else if (data instanceof MaterialData)
+ {
+ final MaterialData matData = (MaterialData)data;
+ writer.println(matData.getItemType().toString().toLowerCase()
+ + (matData.getData() > 0 ? ":" + matData.getData() : ""));
+ }
+ else if (data instanceof ItemStack)
+ {
+ final ItemStack itemStack = (ItemStack)data;
+ writer.println(itemStack.getType().toString().toLowerCase()
+ + (itemStack.getDurability() > 0 ? ":" + itemStack.getDurability() : "")
+ + " " + itemStack.getAmount());
+ }
+ else
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private void writeKey(final Object data)
+ {
+ if (data instanceof String || data instanceof Boolean || data instanceof Number)
+ {
+ String output = data.toString();
+ if (pattern.matcher(output).find())
+ {
+ writer.print('"');
+ writer.print(output.replace("\"", "\\\""));
+ writer.print('"');
+ }
+ else
+ {
+ writer.print(output);
+ }
+ }
+ else if (data instanceof Material)
+ {
+ writer.print(data.toString().toLowerCase());
+ }
+ else if (data instanceof MaterialData)
+ {
+ final MaterialData matData = (MaterialData)data;
+ writer.print(matData.getItemType().toString().toLowerCase()
+ + (matData.getData() > 0 ? ":" + matData.getData() : ""));
+ }
+ else
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private void writeLocation(final Location entry, final int depth)
+ {
+ writer.println();
+ writeIndention(depth);
+ writer.print("world: ");
+ writeScalar(entry.getWorld().getName());
+ writeIndention(depth);
+ writer.print("x: ");
+ writeScalar(entry.getX());
+ writeIndention(depth);
+ writer.print("y: ");
+ writeScalar(entry.getY());
+ writeIndention(depth);
+ writer.print("z: ");
+ writeScalar(entry.getZ());
+ writeIndention(depth);
+ writer.print("yaw: ");
+ writeScalar(entry.getYaw());
+ writeIndention(depth);
+ writer.print("pitch: ");
+ writeScalar(entry.getPitch());
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/userdata/Ban.java b/Essentials/src/com/earth2me/essentials/userdata/Ban.java
new file mode 100644
index 000000000..6e86780cf
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/userdata/Ban.java
@@ -0,0 +1,14 @@
+package com.earth2me.essentials.userdata;
+
+import com.earth2me.essentials.storage.StorageObject;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class Ban implements StorageObject
+{
+ private String reason;
+ private long timeout;
+}
diff --git a/Essentials/src/com/earth2me/essentials/userdata/Inventory.java b/Essentials/src/com/earth2me/essentials/userdata/Inventory.java
new file mode 100644
index 000000000..91a19e2d1
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/userdata/Inventory.java
@@ -0,0 +1,27 @@
+package com.earth2me.essentials.userdata;
+
+import com.earth2me.essentials.storage.MapKeyType;
+import com.earth2me.essentials.storage.MapValueType;
+import com.earth2me.essentials.storage.StorageObject;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class Inventory implements StorageObject
+{
+ private int size;
+ @MapKeyType(Integer.class)
+ @MapValueType(ItemStack.class)
+ private Map<Integer, ItemStack> items = new HashMap<Integer, ItemStack>();
+
+ public Inventory()
+ {
+ items.put(1, new ItemStack(Material.APPLE, 64));
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/userdata/User.java b/Essentials/src/com/earth2me/essentials/userdata/User.java
new file mode 100644
index 000000000..232e0b95e
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/userdata/User.java
@@ -0,0 +1,65 @@
+package com.earth2me.essentials.userdata;
+
+import com.earth2me.essentials.storage.YamlStorageReader;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import lombok.Cleanup;
+
+// this is a prototype for locking userdata
+public class User
+{
+ UserData data = new UserData();
+ ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+
+ public void loadUserData()
+ {
+ data = new YamlStorageReader(null).load(UserData.class);
+ }
+
+ public void aquireReadLock()
+ {
+ rwl.readLock().lock();
+ }
+
+ public void aquireWriteLock()
+ {
+ while (rwl.getReadHoldCount() > 0)
+ {
+ rwl.readLock().unlock();
+ }
+ rwl.writeLock().lock();
+ rwl.readLock().lock();
+ }
+
+ public void close()
+ {
+ if (rwl.isWriteLockedByCurrentThread())
+ {
+ scheduleSaving();
+ rwl.writeLock().unlock();
+ }
+ while (rwl.getReadHoldCount() > 0)
+ {
+ rwl.readLock().unlock();
+ }
+ }
+
+ public void example()
+ {
+ // Cleanup will call close at the end of the function
+ @Cleanup
+ final User user = this;
+
+ // read lock allows to read data from the user
+ user.aquireReadLock();
+ double i = user.data.getMoney();
+
+ // write lock allows only one thread to modify the data
+ user.aquireWriteLock();
+ user.data.setMoney(10 + user.data.getMoney());
+ }
+
+ private void scheduleSaving()
+ {
+ System.out.println("Schedule saving...");
+ }
+}
diff --git a/Essentials/src/com/earth2me/essentials/userdata/UserData.java b/Essentials/src/com/earth2me/essentials/userdata/UserData.java
new file mode 100644
index 000000000..bce62f5fa
--- /dev/null
+++ b/Essentials/src/com/earth2me/essentials/userdata/UserData.java
@@ -0,0 +1,61 @@
+package com.earth2me.essentials.userdata;
+
+import com.earth2me.essentials.storage.ListType;
+import com.earth2me.essentials.storage.MapKeyType;
+import com.earth2me.essentials.storage.MapValueType;
+import com.earth2me.essentials.storage.StorageObject;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.bukkit.Location;
+import org.bukkit.Material;
+
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class UserData implements StorageObject
+{
+ private String nickname;
+ private double money;
+ @MapValueType(Location.class)
+ private Map<String, Location> homes = new HashMap<String, Location>();
+ @ListType(Material.class)
+ private Set<Material> unlimited = new HashSet<Material>();
+ @MapValueType(List.class)
+ @MapKeyType(Material.class)
+ private Map<Material, List<String>> powerTools = new HashMap<Material, List<String>>();
+ private Location lastLocation;
+ @MapValueType(Long.class)
+ private Map<String, Long> timestamps;
+ private String jail;
+ @ListType
+ private List<String> mails;
+ private Inventory inventory;
+ private boolean teleportEnabled;
+ @ListType
+ private Set<String> ignore;
+ private boolean godmode;
+ private boolean muted;
+ private boolean jailed;
+ private Ban ban;
+ private String ipAddress;
+ private boolean afk;
+ private boolean newplayer = true;
+ private String geolocation;
+ private boolean socialspy;
+ private boolean npc;
+ private boolean powertoolsenabled;
+
+ public UserData()
+ {
+ unlimited.add(Material.AIR);
+ unlimited.add(Material.ARROW);
+ unlimited.add(Material.APPLE);
+ powerTools.put(Material.DEAD_BUSH, Collections.singletonList("test"));
+ }
+}
diff --git a/Essentials/test/com/earth2me/essentials/FakeServer.java b/Essentials/test/com/earth2me/essentials/FakeServer.java
index 0cea89bdc..78b5380a6 100644
--- a/Essentials/test/com/earth2me/essentials/FakeServer.java
+++ b/Essentials/test/com/earth2me/essentials/FakeServer.java
@@ -28,9 +28,17 @@ public class FakeServer implements Server
private List<Player> players = new ArrayList<Player>();
private final List<World> worlds = new ArrayList<World>();
+ public FakeServer()
+ {
+ if (Bukkit.getServer() == null)
+ {
+ Bukkit.setServer(this);
+ }
+ }
+
public String getName()
{
- return "Test Server";
+ return "Essentials Fake Server";
}
public String getVersion()
@@ -576,6 +584,6 @@ public class FakeServer implements Server
@Override
public String getBukkitVersion()
{
- throw new UnsupportedOperationException("Not supported yet.");
+ return "Essentials Fake-Server";
}
}
diff --git a/Essentials/test/com/earth2me/essentials/StorageTest.java b/Essentials/test/com/earth2me/essentials/StorageTest.java
index ada3d703a..e6850ce91 100644
--- a/Essentials/test/com/earth2me/essentials/StorageTest.java
+++ b/Essentials/test/com/earth2me/essentials/StorageTest.java
@@ -2,32 +2,148 @@ package com.earth2me.essentials;
import com.earth2me.essentials.settings.Settings;
import com.earth2me.essentials.storage.StorageObject;
+import com.earth2me.essentials.storage.YamlStorageReader;
+import com.earth2me.essentials.storage.YamlStorageWriter;
import java.io.*;
import junit.framework.TestCase;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.World.Environment;
+import org.bukkit.plugin.InvalidDescriptionException;
import org.junit.Test;
+import org.yaml.snakeyaml.Yaml;
public class StorageTest extends TestCase
{
+ Essentials ess;
+ FakeServer server;
+ World world;
+
+ public StorageTest()
+ {
+ ess = new Essentials();
+ server = new FakeServer();
+ world = server.createWorld("testWorld", Environment.NORMAL);
+ try
+ {
+ ess.setupForTesting(server);
+ }
+ catch (InvalidDescriptionException ex)
+ {
+ fail("InvalidDescriptionException");
+ }
+ catch (IOException ex)
+ {
+ fail("IOException");
+ }
+ }
+
@Test
public void testSettings()
{
assertTrue(StorageObject.class.isAssignableFrom(Settings.class));
+ ExecuteTimer ext = new ExecuteTimer();
+ ext.start();
final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
final Reader reader = new InputStreamReader(bais);
- final Settings settings = StorageObject.load(Settings.class, reader);
+ final Settings settings = new YamlStorageReader(reader).load(Settings.class);
+ ext.mark("load empty settings");
+ final ByteArrayInputStream bais3 = new ByteArrayInputStream(new byte[0]);
+ final Reader reader3 = new InputStreamReader(bais3);
+ final Settings settings3 = new YamlStorageReader(reader3).load(Settings.class);
+ ext.mark("load empty settings (class cached)");
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintWriter writer = new PrintWriter(baos);
- settings.save(writer);
+ new YamlStorageWriter(writer).save(settings);
writer.close();
+ ext.mark("write settings");
byte[] written = baos.toByteArray();
System.out.println(new String(written));
final ByteArrayInputStream bais2 = new ByteArrayInputStream(written);
final Reader reader2 = new InputStreamReader(bais2);
- final Settings settings2 = StorageObject.load(Settings.class, reader2);
+ final Settings settings2 = new YamlStorageReader(reader2).load(Settings.class);
System.out.println(settings.toString());
System.out.println(settings2.toString());
+ ext.mark("reload settings");
+ System.out.println(ext.end());
//assertEquals("Default and rewritten config should be equal", settings, settings2);
//that assertion fails, because empty list and maps return as null
}
+
+ @Test
+ public void testUserdata()
+ {
+ FakeServer server = new FakeServer();
+ World world = server.createWorld("testWorld", Environment.NORMAL);
+ ExecuteTimer ext = new ExecuteTimer();
+ ext.start();
+ final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
+ final Reader reader = new InputStreamReader(bais);
+ final com.earth2me.essentials.userdata.UserData userdata = new YamlStorageReader(reader).load(com.earth2me.essentials.userdata.UserData.class);
+ ext.mark("load empty user");
+ final ByteArrayInputStream bais3 = new ByteArrayInputStream(new byte[0]);
+ final Reader reader3 = new InputStreamReader(bais3);
+ final com.earth2me.essentials.userdata.UserData userdata3 = new YamlStorageReader(reader3).load(com.earth2me.essentials.userdata.UserData.class);
+ ext.mark("load empty user (class cached)");
+
+ for (int j = 0; j < 10000; j++)
+ {
+ userdata.getHomes().put("home", new Location(world, j, j, j));
+ }
+ ext.mark("change home 10000 times");
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintWriter writer = new PrintWriter(baos);
+ new YamlStorageWriter(writer).save(userdata);
+ writer.close();
+ ext.mark("write user");
+ final ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
+ final PrintWriter writer2 = new PrintWriter(baos2);
+ new YamlStorageWriter(writer2).save(userdata);
+ writer2.close();
+ ext.mark("write user (cached)");
+ byte[] written = baos.toByteArray();
+ System.out.println(new String(written));
+ ext.mark("debug output");
+ final ByteArrayInputStream bais2 = new ByteArrayInputStream(written);
+ final Reader reader2 = new InputStreamReader(bais2);
+ final com.earth2me.essentials.userdata.UserData userdata2 = new YamlStorageReader(reader2).load(com.earth2me.essentials.userdata.UserData.class);
+ ext.mark("reload file");
+ final ByteArrayInputStream bais4 = new ByteArrayInputStream(written);
+ final Reader reader4 = new InputStreamReader(bais4);
+ final com.earth2me.essentials.userdata.UserData userdata4 = new YamlStorageReader(reader4).load(com.earth2me.essentials.userdata.UserData.class);
+ ext.mark("reload file (cached)");
+ System.out.println(userdata.toString());
+ System.out.println(userdata2.toString());
+ System.out.println(ext.end());
+ com.earth2me.essentials.userdata.User test = new com.earth2me.essentials.userdata.User();
+ test.example();
+
+ }
+
+ @Test
+ public void testOldUserdata()
+ {
+ ExecuteTimer ext = new ExecuteTimer();
+ ext.start();
+ OfflinePlayer base1 = server.createPlayer("testPlayer1", ess);
+ server.addPlayer(base1);
+ ext.mark("fake user created");
+ UserData user = (UserData)ess.getUser(base1);
+ ext.mark("load empty user");
+ for (int j = 0; j < 1; j++)
+ {
+ user.setHome("home", new Location(world, j, j, j));
+ }
+ ext.mark("change home 1 times");
+ user.save();
+ ext.mark("write user");
+ user.save();
+ ext.mark("write user (cached)");
+ user.reloadConfig();
+ ext.mark("reloaded file");
+ user.reloadConfig();
+ ext.mark("reloaded file (cached)");
+ System.out.println(ext.end());
+ }
}