mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-11-25 20:25:19 +01:00
Metrics
This commit is contained in:
parent
6529364397
commit
c609030ff7
@ -1,11 +1,13 @@
|
||||
package net.citizensnpcs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.citizensnpcs.Settings.Setting;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
import net.citizensnpcs.api.exception.NPCException;
|
||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
@ -16,10 +18,6 @@ import net.citizensnpcs.api.npc.trait.trait.Inventory;
|
||||
import net.citizensnpcs.api.npc.trait.trait.Owner;
|
||||
import net.citizensnpcs.api.npc.trait.trait.SpawnLocation;
|
||||
import net.citizensnpcs.api.npc.trait.trait.Spawned;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.api.util.DatabaseStorage;
|
||||
import net.citizensnpcs.api.util.Storage;
|
||||
import net.citizensnpcs.api.util.YamlStorage;
|
||||
import net.citizensnpcs.command.CommandManager;
|
||||
import net.citizensnpcs.command.Injector;
|
||||
import net.citizensnpcs.command.command.AdminCommands;
|
||||
@ -32,9 +30,13 @@ import net.citizensnpcs.command.exception.ServerCommandException;
|
||||
import net.citizensnpcs.command.exception.UnhandledCommandException;
|
||||
import net.citizensnpcs.command.exception.WrappedCommandException;
|
||||
import net.citizensnpcs.npc.CitizensNPCManager;
|
||||
import net.citizensnpcs.storage.DatabaseStorage;
|
||||
import net.citizensnpcs.storage.Storage;
|
||||
import net.citizensnpcs.storage.YamlStorage;
|
||||
import net.citizensnpcs.trait.LookClose;
|
||||
import net.citizensnpcs.trait.Sneak;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
import net.citizensnpcs.util.Metrics;
|
||||
import net.citizensnpcs.util.StringHelper;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@ -46,6 +48,7 @@ import org.bukkit.entity.CreatureType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class Citizens extends JavaPlugin {
|
||||
@ -58,16 +61,16 @@ public class Citizens extends JavaPlugin {
|
||||
private volatile CitizensNPCManager npcManager;
|
||||
private final DefaultInstanceFactory<Character> characterManager = new DefaultInstanceFactory<Character>();
|
||||
private final DefaultInstanceFactory<Trait> traitManager = new DefaultInstanceFactory<Trait>();
|
||||
private final CommandManager cmdManager = new CommandManager();
|
||||
private final CommandManager commands = new CommandManager();
|
||||
private Settings config;
|
||||
private Storage saves;
|
||||
private Storage templates;
|
||||
private boolean compatible;
|
||||
|
||||
private boolean handleMistake(CommandSender sender, String command, String modifier) {
|
||||
private boolean suggestClosestModifier(CommandSender sender, String command, String modifier) {
|
||||
int minDist = Integer.MAX_VALUE;
|
||||
String closest = "";
|
||||
for (String string : cmdManager.getAllCommandModifiers(command)) {
|
||||
for (String string : commands.getAllCommandModifiers(command)) {
|
||||
int distance = StringHelper.getLevenshteinDistance(modifier, string);
|
||||
if (minDist > distance) {
|
||||
minDist = distance;
|
||||
@ -94,16 +97,10 @@ public class Citizens extends JavaPlugin {
|
||||
System.arraycopy(args, 0, split, 1, args.length);
|
||||
split[0] = cmd.getName().toLowerCase();
|
||||
|
||||
String modifier = "";
|
||||
if (args.length > 0)
|
||||
modifier = args[0];
|
||||
String modifier = args.length > 0 ? args[0] : "";
|
||||
|
||||
// No command found!
|
||||
if (!cmdManager.hasCommand(split[0], modifier)) {
|
||||
if (!modifier.isEmpty()) {
|
||||
boolean value = handleMistake(sender, split[0], modifier);
|
||||
return value;
|
||||
}
|
||||
if (!commands.hasCommand(split[0], modifier) && !modifier.isEmpty()) {
|
||||
return suggestClosestModifier(sender, split[0], modifier);
|
||||
}
|
||||
|
||||
NPC npc = null;
|
||||
@ -111,7 +108,7 @@ public class Citizens extends JavaPlugin {
|
||||
npc = npcManager.getSelectedNPC(player);
|
||||
|
||||
try {
|
||||
cmdManager.execute(split, player, player == null ? sender : player, npc);
|
||||
commands.execute(split, player, player == null ? sender : player, npc);
|
||||
} catch (ServerCommandException ex) {
|
||||
sender.sendMessage("You must be in-game to execute that command.");
|
||||
} catch (NoPermissionsException ex) {
|
||||
@ -167,10 +164,34 @@ public class Citizens extends JavaPlugin {
|
||||
config.load();
|
||||
|
||||
// NPC storage
|
||||
if (Setting.USE_DATABASE.asBoolean())
|
||||
if (Setting.USE_DATABASE.asBoolean()) {
|
||||
saves = new DatabaseStorage();
|
||||
else
|
||||
} else {
|
||||
saves = new YamlStorage(getDataFolder() + File.separator + "saves.yml", "Citizens NPC Storage");
|
||||
}
|
||||
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Metrics metrics = new Metrics();
|
||||
metrics.addCustomData(Citizens.this, new Metrics.Plotter() {
|
||||
@Override
|
||||
public int getValue() {
|
||||
return Iterators.size(npcManager.iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
return "Total NPCs";
|
||||
}
|
||||
});
|
||||
metrics.beginMeasuringPlugin(Citizens.this);
|
||||
} catch (IOException ex) {
|
||||
Messaging.log("Unable to load metrics");
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
// Templates
|
||||
templates = new YamlStorage(getDataFolder() + File.separator + "templates.yml", "NPC Templates");
|
||||
@ -221,7 +242,7 @@ public class Citizens extends JavaPlugin {
|
||||
}
|
||||
|
||||
public CommandManager getCommandManager() {
|
||||
return cmdManager;
|
||||
return commands;
|
||||
}
|
||||
|
||||
public Storage getStorage() {
|
||||
@ -233,12 +254,12 @@ public class Citizens extends JavaPlugin {
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
cmdManager.setInjector(new Injector(this));
|
||||
commands.setInjector(new Injector(this));
|
||||
|
||||
// Register command classes
|
||||
cmdManager.register(AdminCommands.class);
|
||||
cmdManager.register(NPCCommands.class);
|
||||
cmdManager.register(HelpCommands.class);
|
||||
commands.register(AdminCommands.class);
|
||||
commands.register(NPCCommands.class);
|
||||
commands.register(HelpCommands.class);
|
||||
}
|
||||
|
||||
private void saveNPCs() {
|
||||
@ -254,15 +275,16 @@ public class Citizens extends JavaPlugin {
|
||||
if (!key.keyExists("name"))
|
||||
throw new NPCLoadException("Could not find a name for the NPC with ID '" + id + "'.");
|
||||
|
||||
String type = key.getString("traits.type");
|
||||
String type = key.getString("traits.type").toUpperCase();
|
||||
NPC npc = npcManager.createNPC(
|
||||
type.equalsIgnoreCase("DEFAULT") ? null : CreatureType.valueOf(key.getString("traits.type")
|
||||
.toUpperCase()), id, key.getString("name"), null);
|
||||
type.equalsIgnoreCase("DEFAULT") ? CreatureType.MONSTER : CreatureType.valueOf(type), id,
|
||||
key.getString("name"), null);
|
||||
try {
|
||||
npc.load(key);
|
||||
} catch (NPCException ex) {
|
||||
Messaging.log(ex.getMessage());
|
||||
}
|
||||
|
||||
++created;
|
||||
if (npc.isSpawned())
|
||||
++spawned;
|
||||
|
@ -2,8 +2,8 @@ package net.citizensnpcs;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.api.util.YamlStorage;
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
import net.citizensnpcs.storage.YamlStorage;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
|
||||
public class Settings {
|
||||
@ -30,9 +30,11 @@ public class Settings {
|
||||
}
|
||||
|
||||
public enum Setting {
|
||||
DEBUG_MODE("general.debug-mode", false), USE_DATABASE("use-database", false), SELECTION_ITEM(
|
||||
"npc.selection.item", 280), SELECTION_MESSAGE("npc.selection.message", "<b>You selected <a><npc><b>!"), QUICK_SELECT(
|
||||
"npc.selection.quick-select", false);
|
||||
DEBUG_MODE("general.debug-mode", false),
|
||||
USE_DATABASE("use-database", false),
|
||||
SELECTION_ITEM("npc.selection.item", 280),
|
||||
SELECTION_MESSAGE("npc.selection.message", "<b>You selected <a><npc><b>!"),
|
||||
QUICK_SELECT("npc.selection.quick-select", false);
|
||||
|
||||
private String path;
|
||||
private Object value;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package net.citizensnpcs;
|
||||
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
|
||||
public class Template {
|
||||
private final DataKey template;
|
||||
|
@ -51,7 +51,7 @@ public class NPCCommands {
|
||||
Messaging.sendError(player, "NPC names cannot be longer than 16 characters. The name has been shortened.");
|
||||
name = name.substring(0, 15);
|
||||
}
|
||||
CreatureType type = null;
|
||||
CreatureType type = CreatureType.MONSTER; // Default NPC type
|
||||
if (args.hasValueFlag("type"))
|
||||
try {
|
||||
type = CreatureType.valueOf(args.getFlag("type").toUpperCase().replace('-', '_'));
|
||||
@ -89,7 +89,7 @@ public class NPCCommands {
|
||||
create.addTrait(new Owner(player.getName()));
|
||||
|
||||
// Set the mob type
|
||||
create.addTrait(new MobType(type == null ? "DEFAULT" : type.toString()));
|
||||
create.addTrait(new MobType(type == CreatureType.MONSTER ? "DEFAULT" : type.toString()));
|
||||
|
||||
create.spawn(player.getLocation());
|
||||
npcManager.selectNPC(player, create);
|
||||
|
@ -9,7 +9,7 @@ import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPCManager;
|
||||
import net.citizensnpcs.api.npc.trait.Character;
|
||||
import net.citizensnpcs.api.npc.trait.trait.SpawnLocation;
|
||||
import net.citizensnpcs.api.util.Storage;
|
||||
import net.citizensnpcs.storage.Storage;
|
||||
import net.citizensnpcs.util.ByIdArray;
|
||||
import net.citizensnpcs.util.NPCBuilder;
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package net.citizensnpcs.npc.entity;
|
||||
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||
import net.citizensnpcs.npc.CitizensNPC;
|
||||
import net.citizensnpcs.npc.CitizensNPCManager;
|
||||
import net.citizensnpcs.resource.lib.EntityHumanNPC;
|
||||
@ -53,4 +55,9 @@ public class CitizensHumanNPC extends CitizensNPC {
|
||||
handle.setPositionRotation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
|
||||
return handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(DataKey key) throws NPCLoadException {
|
||||
super.load(key);
|
||||
}
|
||||
}
|
143
src/net/citizensnpcs/storage/DatabaseStorage.java
Normal file
143
src/net/citizensnpcs/storage/DatabaseStorage.java
Normal file
@ -0,0 +1,143 @@
|
||||
package net.citizensnpcs.storage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
|
||||
public class DatabaseStorage implements Storage {
|
||||
|
||||
@Override
|
||||
public DataKey getKey(String root) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public class DatabaseKey extends DataKey {
|
||||
|
||||
@Override
|
||||
public void copy(String to) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataKey> getIntegerSubKeys() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRaw(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataKey getRelative(String relative) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<DataKey> getSubKeys() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyExists(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeKey(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(String key, boolean value) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(String key, double value) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInt(String key, int value) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLong(String key, long value) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRaw(String path, Object value) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setString(String key, String value) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
}
|
12
src/net/citizensnpcs/storage/Storage.java
Normal file
12
src/net/citizensnpcs/storage/Storage.java
Normal file
@ -0,0 +1,12 @@
|
||||
package net.citizensnpcs.storage;
|
||||
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
|
||||
public interface Storage {
|
||||
|
||||
public DataKey getKey(String root);
|
||||
|
||||
public void load();
|
||||
|
||||
public void save();
|
||||
}
|
261
src/net/citizensnpcs/storage/YamlStorage.java
Normal file
261
src/net/citizensnpcs/storage/YamlStorage.java
Normal file
@ -0,0 +1,261 @@
|
||||
package net.citizensnpcs.storage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class YamlStorage implements Storage {
|
||||
private final FileConfiguration config;
|
||||
private final File file;
|
||||
|
||||
public YamlStorage(String fileName, String header) {
|
||||
config = new YamlConfiguration();
|
||||
file = new File(fileName);
|
||||
if (!file.exists()) {
|
||||
create();
|
||||
config.options().header(header);
|
||||
save();
|
||||
} else
|
||||
load();
|
||||
}
|
||||
|
||||
private void create() {
|
||||
try {
|
||||
Messaging.log("Creating file: " + file.getName());
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
} catch (IOException ex) {
|
||||
Messaging.log(Level.SEVERE, "Could not create file: " + file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataKey getKey(String root) {
|
||||
return new YamlKey(root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
try {
|
||||
config.load(file);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean pathExists(String key) {
|
||||
return config.get(key) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
try {
|
||||
config.save(file);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public class YamlKey extends DataKey {
|
||||
private final String current;
|
||||
|
||||
public YamlKey(String root) {
|
||||
current = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copy(String to) {
|
||||
ConfigurationSection root = config.getConfigurationSection(current);
|
||||
if (root == null)
|
||||
return;
|
||||
config.createSection(to, root.getValues(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key) {
|
||||
String path = getKeyExt(key);
|
||||
if (pathExists(path)) {
|
||||
if (config.getString(path) == null)
|
||||
return config.getBoolean(path);
|
||||
return Boolean.parseBoolean(config.getString(path));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean def) {
|
||||
return config.getBoolean(getKeyExt(key), def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(String key) {
|
||||
String path = getKeyExt(key);
|
||||
if (pathExists(path)) {
|
||||
if (config.getString(path) == null) {
|
||||
if (config.get(path) instanceof Integer)
|
||||
return config.getInt(path);
|
||||
return config.getDouble(path);
|
||||
}
|
||||
return Double.parseDouble(config.getString(path));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(String key, double def) {
|
||||
return config.getDouble(getKeyExt(key), def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String key) {
|
||||
String path = getKeyExt(key);
|
||||
if (pathExists(path)) {
|
||||
if (config.getString(path) == null)
|
||||
return config.getInt(path);
|
||||
return Integer.parseInt(config.getString(path));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String key, int def) {
|
||||
return config.getInt(getKeyExt(key), def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataKey> getIntegerSubKeys() {
|
||||
List<DataKey> res = new ArrayList<DataKey>();
|
||||
ConfigurationSection section = config.getConfigurationSection(current);
|
||||
if (section == null)
|
||||
return res;
|
||||
List<Integer> keys = new ArrayList<Integer>();
|
||||
for (String key : section.getKeys(false)) {
|
||||
try {
|
||||
keys.add(Integer.parseInt(key));
|
||||
} catch (NumberFormatException ex) {
|
||||
}
|
||||
}
|
||||
Collections.sort(keys);
|
||||
for (int key : keys)
|
||||
res.add(getRelative(Integer.toString(key)));
|
||||
return res;
|
||||
}
|
||||
|
||||
private String getKeyExt(String from) {
|
||||
if (from.isEmpty())
|
||||
return current;
|
||||
if (from.charAt(0) == '.')
|
||||
return current.isEmpty() ? from.substring(1, from.length()) : current + from;
|
||||
return current.isEmpty() ? from : current + "." + from;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String key) {
|
||||
String path = getKeyExt(key);
|
||||
if (pathExists(path)) {
|
||||
if (config.getString(path) == null) {
|
||||
if (config.get(path) instanceof Integer)
|
||||
return config.getInt(path);
|
||||
return config.getLong(path);
|
||||
}
|
||||
return Long.parseLong(config.getString(path));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String key, long def) {
|
||||
return config.getLong(getKeyExt(key), def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRaw(String key) {
|
||||
return config.get(getKeyExt(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataKey getRelative(String relative) {
|
||||
if (relative == null || relative.isEmpty())
|
||||
return this;
|
||||
return new YamlKey(getKeyExt(relative));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String key) {
|
||||
String path = getKeyExt(key);
|
||||
if (pathExists(path)) {
|
||||
return config.get(path).toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<DataKey> getSubKeys() {
|
||||
List<DataKey> res = new ArrayList<DataKey>();
|
||||
ConfigurationSection section = config.getConfigurationSection(current);
|
||||
if (section == null)
|
||||
return res;
|
||||
for (String key : section.getKeys(false)) {
|
||||
res.add(getRelative(key));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyExists(String key) {
|
||||
return config.get(getKeyExt(key)) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
int last = current.lastIndexOf('.');
|
||||
return current.substring(last == 0 ? 0 : last + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeKey(String key) {
|
||||
config.set(getKeyExt(key), null);
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(String key, boolean value) {
|
||||
config.set(getKeyExt(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(String key, double value) {
|
||||
config.set(getKeyExt(key), String.valueOf(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInt(String key, int value) {
|
||||
config.set(getKeyExt(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLong(String key, long value) {
|
||||
config.set(getKeyExt(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRaw(String key, Object value) {
|
||||
config.set(getKeyExt(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setString(String key, String value) {
|
||||
config.set(getKeyExt(key), value);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,11 +3,11 @@ package net.citizensnpcs.trait;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.trait.SaveId;
|
||||
import net.citizensnpcs.api.npc.trait.Trait;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.npc.CitizensNPC;
|
||||
import net.minecraft.server.EntityLiving;
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
package net.citizensnpcs.trait;
|
||||
|
||||
import net.citizensnpcs.api.DataKey;
|
||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.trait.SaveId;
|
||||
import net.citizensnpcs.api.npc.trait.Trait;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.npc.entity.CitizensHumanNPC;
|
||||
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
|
300
src/net/citizensnpcs/util/Metrics.java
Normal file
300
src/net/citizensnpcs/util/Metrics.java
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright 2011 Tyler Blair. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and contributors and should not be interpreted as representing official policies,
|
||||
* either expressed or implied, of anybody else.
|
||||
*/
|
||||
package net.citizensnpcs.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Tooling to post to metrics.griefcraft.com
|
||||
*/
|
||||
public class Metrics {
|
||||
|
||||
/**
|
||||
* Interface used to collect custom data for a plugin
|
||||
*/
|
||||
public static abstract class Plotter {
|
||||
|
||||
/**
|
||||
* Get the column name for the plotted point
|
||||
*
|
||||
* @return the plotted point's column name
|
||||
*/
|
||||
public abstract String getColumnName();
|
||||
|
||||
/**
|
||||
* Get the current value for the plotted point
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract int getValue();
|
||||
|
||||
/**
|
||||
* Called after the website graphs have been updated
|
||||
*/
|
||||
public void reset() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getColumnName().hashCode() + getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (!(object instanceof Plotter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Plotter plotter = (Plotter) object;
|
||||
return plotter.getColumnName().equals(getColumnName()) && plotter.getValue() == getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The metrics revision number
|
||||
*/
|
||||
private final static int REVISION = 4;
|
||||
|
||||
/**
|
||||
* The base url of the metrics domain
|
||||
*/
|
||||
private static final String BASE_URL = "http://metrics.griefcraft.com";
|
||||
|
||||
/**
|
||||
* The url used to report a server's status
|
||||
*/
|
||||
private static final String REPORT_URL = "/report/%s";
|
||||
|
||||
/**
|
||||
* The file where guid and opt out is stored in
|
||||
*/
|
||||
private static final String CONFIG_FILE = "plugins/PluginMetrics/config.yml";
|
||||
|
||||
/**
|
||||
* Interval of time to ping in minutes
|
||||
*/
|
||||
private final static int PING_INTERVAL = 10;
|
||||
|
||||
/**
|
||||
* A map of the custom data plotters for plugins
|
||||
*/
|
||||
private final Map<Plugin, Set<Plotter>> customData = Collections
|
||||
.synchronizedMap(new HashMap<Plugin, Set<Plotter>>());
|
||||
|
||||
/**
|
||||
* The plugin configuration file
|
||||
*/
|
||||
private final YamlConfiguration configuration;
|
||||
|
||||
/**
|
||||
* Unique server id
|
||||
*/
|
||||
private final String guid;
|
||||
|
||||
public Metrics() throws IOException {
|
||||
// load the config
|
||||
File file = new File(CONFIG_FILE);
|
||||
configuration = YamlConfiguration.loadConfiguration(file);
|
||||
|
||||
// add some defaults
|
||||
configuration.addDefault("opt-out", false);
|
||||
configuration.addDefault("guid", UUID.randomUUID().toString());
|
||||
|
||||
// Do we need to create the file?
|
||||
if (configuration.get("guid", null) == null) {
|
||||
configuration.options().header("http://metrics.griefcraft.com").copyDefaults(true);
|
||||
configuration.save(file);
|
||||
}
|
||||
|
||||
// Load the guid then
|
||||
guid = configuration.getString("guid");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom data plotter for a given plugin
|
||||
*
|
||||
* @param plugin
|
||||
* @param plotter
|
||||
*/
|
||||
public void addCustomData(Plugin plugin, Plotter plotter) {
|
||||
Set<Plotter> plotters = customData.get(plugin);
|
||||
|
||||
if (plotters == null) {
|
||||
plotters = Collections.synchronizedSet(new LinkedHashSet<Plotter>());
|
||||
customData.put(plugin, plotters);
|
||||
}
|
||||
|
||||
plotters.add(plotter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin measuring a plugin
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
public void beginMeasuringPlugin(final Plugin plugin) throws IOException {
|
||||
// Did we opt out?
|
||||
if (configuration.getBoolean("opt-out", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First tell the server about us
|
||||
postPlugin(plugin, false);
|
||||
|
||||
// Ping the server in intervals
|
||||
plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
postPlugin(plugin, true);
|
||||
} catch (IOException e) {
|
||||
System.out.println("[Metrics] " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}, PING_INTERVAL * 1200, PING_INTERVAL * 1200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method that posts a plugin to the metrics website
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
private void postPlugin(Plugin plugin, boolean isPing) throws IOException {
|
||||
// Construct the post data
|
||||
String response = "ERR No response";
|
||||
String data = encode("guid") + '=' + encode(guid) + '&' + encode("version") + '='
|
||||
+ encode(plugin.getDescription().getVersion()) + '&' + encode("server") + '='
|
||||
+ encode(Bukkit.getVersion()) + '&' + encode("players") + '='
|
||||
+ encode(String.valueOf(Bukkit.getServer().getOnlinePlayers().length)) + '&' + encode("revision") + '='
|
||||
+ encode(REVISION + "");
|
||||
|
||||
// If we're pinging, append it
|
||||
if (isPing) {
|
||||
data += '&' + encode("ping") + '=' + encode("true");
|
||||
}
|
||||
|
||||
// Add any custom data (if applicable)
|
||||
Set<Plotter> plotters = customData.get(plugin);
|
||||
|
||||
if (plotters != null) {
|
||||
for (Plotter plotter : plotters) {
|
||||
data += "&" + encode("Custom" + plotter.getColumnName()) + "="
|
||||
+ encode(Integer.toString(plotter.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
// Create the url
|
||||
URL url = new URL(BASE_URL + String.format(REPORT_URL, plugin.getDescription().getName()));
|
||||
|
||||
// Connect to the website
|
||||
URLConnection connection;
|
||||
|
||||
// Mineshafter creates a socks proxy, so we can safely bypass it
|
||||
if (isMineshafterPresent()) {
|
||||
connection = url.openConnection(Proxy.NO_PROXY);
|
||||
} else {
|
||||
connection = url.openConnection();
|
||||
}
|
||||
|
||||
connection.setDoOutput(true);
|
||||
|
||||
// Write the data
|
||||
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
|
||||
writer.write(data);
|
||||
writer.flush();
|
||||
|
||||
// Now read the response
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
response = reader.readLine();
|
||||
|
||||
// close resources
|
||||
writer.close();
|
||||
reader.close();
|
||||
|
||||
if (response.startsWith("ERR")) {
|
||||
throw new IOException(response); // Throw the exception
|
||||
} else {
|
||||
// Is this the first update this hour?
|
||||
if (response.contains("OK This is your first update this hour")) {
|
||||
if (plotters != null) {
|
||||
for (Plotter plotter : plotters) {
|
||||
plotter.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (response.startsWith("OK")) - We should get "OK" followed by an
|
||||
// optional description if everything goes right
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if mineshafter is present. If it is, we need to bypass it to send
|
||||
* POST requests
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean isMineshafterPresent() {
|
||||
try {
|
||||
Class.forName("mineshafter.MineServer");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode text as UTF-8
|
||||
*
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
private static String encode(String text) throws UnsupportedEncodingException {
|
||||
return URLEncoder.encode(text, "UTF-8");
|
||||
}
|
||||
|
||||
}
|
@ -46,6 +46,7 @@ public class NPCBuilder {
|
||||
types.put(CreatureType.GHAST, CitizensGhastNPC.class);
|
||||
types.put(CreatureType.GIANT, CitizensGiantNPC.class);
|
||||
types.put(CreatureType.MAGMA_CUBE, CitizensMagmaCubeNPC.class);
|
||||
types.put(CreatureType.MONSTER, CitizensHumanNPC.class);
|
||||
types.put(CreatureType.MUSHROOM_COW, CitizensMushroomCowNPC.class);
|
||||
types.put(CreatureType.PIG, CitizensPigNPC.class);
|
||||
types.put(CreatureType.PIG_ZOMBIE, CitizensPigZombieNPC.class);
|
||||
@ -63,9 +64,6 @@ public class NPCBuilder {
|
||||
|
||||
public CitizensNPC getByType(CreatureType type, CitizensNPCManager npcManager, int id, String name) {
|
||||
Class<? extends CitizensNPC> npcClass = types.get(type);
|
||||
if (npcClass == null)
|
||||
npcClass = CitizensHumanNPC.class;
|
||||
|
||||
try {
|
||||
return npcClass.getConstructor(CitizensNPCManager.class, int.class, String.class).newInstance(npcManager,
|
||||
id, name);
|
||||
|
Loading…
Reference in New Issue
Block a user