mirror of
https://github.com/EssentialsX/Essentials.git
synced 2024-09-28 15:47:26 +02:00
More work on the config code
This commit is contained in:
parent
e683ce5751
commit
8aaaed2ef8
@ -862,4 +862,9 @@ public abstract class UserData extends PlayerExtension implements IConf
|
||||
config.setProperty("timestamps.kits", kitTimestamps);
|
||||
config.save();
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
config.save();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 = "~";
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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>();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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>();
|
||||
}
|
@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Settings extends StorageObject
|
||||
public class Settings implements StorageObject
|
||||
{
|
||||
@Comment(
|
||||
{
|
||||
|
29
Essentials/src/com/earth2me/essentials/settings/Worth.java
Normal file
29
Essentials/src/com/earth2me/essentials/settings/Worth.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Afk extends StorageObject
|
||||
public class Afk implements StorageObject
|
||||
{
|
||||
@Comment(
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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>();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.earth2me.essentials.storage;
|
||||
|
||||
|
||||
public interface IStorageReader
|
||||
{
|
||||
<T extends StorageObject> T load(final Class<? extends T> clazz);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.earth2me.essentials.storage;
|
||||
|
||||
|
||||
public interface IStorageWriter
|
||||
{
|
||||
void save(final StorageObject object);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
14
Essentials/src/com/earth2me/essentials/userdata/Ban.java
Normal file
14
Essentials/src/com/earth2me/essentials/userdata/Ban.java
Normal file
@ -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;
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
65
Essentials/src/com/earth2me/essentials/userdata/User.java
Normal file
65
Essentials/src/com/earth2me/essentials/userdata/User.java
Normal file
@ -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...");
|
||||
}
|
||||
}
|
@ -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"));
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user