From 8aaaed2ef8aa09597f76f8aec6f7b2e5b89d111b Mon Sep 17 00:00:00 2001 From: snowleo Date: Wed, 23 Nov 2011 02:43:38 +0100 Subject: More work on the config code --- .../src/com/earth2me/essentials/UserData.java | 5 + .../com/earth2me/essentials/settings/Backup.java | 2 +- .../src/com/earth2me/essentials/settings/Chat.java | 2 +- .../com/earth2me/essentials/settings/Commands.java | 2 +- .../com/earth2me/essentials/settings/Economy.java | 7 +- .../com/earth2me/essentials/settings/General.java | 2 +- .../earth2me/essentials/settings/GroupOptions.java | 2 +- .../com/earth2me/essentials/settings/Groups.java | 6 +- .../com/earth2me/essentials/settings/Location.java | 28 -- .../earth2me/essentials/settings/Locations.java | 22 ++ .../com/earth2me/essentials/settings/Settings.java | 2 +- .../com/earth2me/essentials/settings/Worth.java | 29 ++ .../earth2me/essentials/settings/commands/Afk.java | 2 +- .../earth2me/essentials/settings/commands/God.java | 2 +- .../essentials/settings/commands/Help.java | 2 +- .../essentials/settings/commands/Home.java | 2 +- .../earth2me/essentials/settings/commands/Kit.java | 13 +- .../essentials/settings/commands/KitObject.java | 7 +- .../essentials/settings/commands/Lightning.java | 2 +- .../essentials/settings/commands/Spawnmob.java | 2 +- .../essentials/storage/BukkitConstructor.java | 182 +++++++++++++ .../essentials/storage/IStorageReader.java | 7 + .../essentials/storage/IStorageWriter.java | 7 + .../earth2me/essentials/storage/MapKeyType.java | 14 + .../com/earth2me/essentials/storage/MapType.java | 14 - .../earth2me/essentials/storage/MapValueType.java | 14 + .../earth2me/essentials/storage/StorageObject.java | 239 +---------------- .../essentials/storage/YamlStorageReader.java | 126 +++++++++ .../essentials/storage/YamlStorageWriter.java | 295 +++++++++++++++++++++ .../src/com/earth2me/essentials/userdata/Ban.java | 14 + .../earth2me/essentials/userdata/Inventory.java | 27 ++ .../src/com/earth2me/essentials/userdata/User.java | 65 +++++ .../com/earth2me/essentials/userdata/UserData.java | 61 +++++ .../test/com/earth2me/essentials/FakeServer.java | 12 +- .../test/com/earth2me/essentials/StorageTest.java | 122 ++++++++- 35 files changed, 1029 insertions(+), 311 deletions(-) delete mode 100644 Essentials/src/com/earth2me/essentials/settings/Location.java create mode 100644 Essentials/src/com/earth2me/essentials/settings/Locations.java create mode 100644 Essentials/src/com/earth2me/essentials/settings/Worth.java create mode 100644 Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java create mode 100644 Essentials/src/com/earth2me/essentials/storage/IStorageReader.java create mode 100644 Essentials/src/com/earth2me/essentials/storage/IStorageWriter.java create mode 100644 Essentials/src/com/earth2me/essentials/storage/MapKeyType.java delete mode 100644 Essentials/src/com/earth2me/essentials/storage/MapType.java create mode 100644 Essentials/src/com/earth2me/essentials/storage/MapValueType.java create mode 100644 Essentials/src/com/earth2me/essentials/storage/YamlStorageReader.java create mode 100644 Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java create mode 100644 Essentials/src/com/earth2me/essentials/userdata/Ban.java create mode 100644 Essentials/src/com/earth2me/essentials/userdata/Inventory.java create mode 100644 Essentials/src/com/earth2me/essentials/userdata/User.java create mode 100644 Essentials/src/com/earth2me/essentials/userdata/UserData.java 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 commandCosts = new HashMap(); @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 groups = new LinkedHashMap(); } 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 jails = new HashMap(); + @MapValueType(Location.class) + Map warps = new HashMap(); + @MapValueType(Location.class) + Map spawns = new HashMap(); +} 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 sell = new HashMap(); + @MapKeyType(MaterialData.class) + @MapValueType(Double.class) + private Map buy = new HashMap(); + + 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 kits = new HashMap(); } 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 items = new ArrayList(); + @ListType(ItemStack.class) + private List items = new ArrayList(); 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 load(final Class 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/MapKeyType.java b/Essentials/src/com/earth2me/essentials/storage/MapKeyType.java new file mode 100644 index 000000000..aa162e51c --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/storage/MapKeyType.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 MapKeyType +{ + Class value() default String.class; +} \ No newline at end of file diff --git a/Essentials/src/com/earth2me/essentials/storage/MapType.java b/Essentials/src/com/earth2me/essentials/storage/MapType.java deleted file mode 100644 index dc5636315..000000000 --- a/Essentials/src/com/earth2me/essentials/storage/MapType.java +++ /dev/null @@ -1,14 +0,0 @@ -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 MapType -{ - 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 clazz; - - protected StorageObject() - { - } - private static Map constructors = new HashMap(); - - public static T load(Class 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 classes = new HashSet(); - - prepareConstructor(constructor, classes, clazz); - return constructor; - } - - private static void prepareConstructor(final Constructor constructor, final Set 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 entry : ((Map)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)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 preparedYamls = Collections.synchronizedMap(new HashMap()); + private transient static Map locks = new HashMap(); + private transient final Reader reader; + + public YamlStorageReader(final Reader reader) + { + this.reader = reader; + } + + public T load(final Class 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 classes = new HashSet(); + + prepareConstructor(constructor, classes, clazz); + return constructor; + } + + private static void prepareConstructor(final Constructor constructor, final Set 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 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 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)data, depth + 1); + } + else if (data instanceof Collection) + { + writeCollection((Collection)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 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 data, final int depth) throws IllegalArgumentException, IllegalAccessException + { + writer.println(); + if (data.isEmpty()) + { + writer.println(); + } + for (Entry 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)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 items = new HashMap(); + + 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 homes = new HashMap(); + @ListType(Material.class) + private Set unlimited = new HashSet(); + @MapValueType(List.class) + @MapKeyType(Material.class) + private Map> powerTools = new HashMap>(); + private Location lastLocation; + @MapValueType(Long.class) + private Map timestamps; + private String jail; + @ListType + private List mails; + private Inventory inventory; + private boolean teleportEnabled; + @ListType + private Set 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 players = new ArrayList(); private final List worlds = new ArrayList(); + 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()); + } } -- cgit v1.2.3