diff --git a/.gitattributes b/.gitattributes
index 412eeda..c98f97b 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -10,13 +10,13 @@
*.dbproj merge=union
# Standard to msysgit
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot diff=astextplain
-*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
-*.rtf diff=astextplain
-*.RTF diff=astextplain
+*.doc diff=astextplain
+*.DOC diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot diff=astextplain
+*.DOT diff=astextplain
+*.pdf diff=astextplain
+*.PDF diff=astextplain
+*.rtf diff=astextplain
+*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
index b49a76e..c3f3424 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,34 +1,80 @@
-# Eclipse
-/.classpath
-/.project
-/.settings
+# Subversion
+.svn
-# Netbeans
-/nbproject
+## IDEs ##
+
+# Android Studio
+*.apk
+*.ap_
+*.dex
+bin/
+gen/
+out/
+.navigation/
+proguard/
+/local.properties
+/captures
+
+# IntelliJ
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# Netbeans IDE
+nbproject/
+nbactions.xml
+
+# Eclipse stuff
+.classpath
+.project
+.settings/
+
+# vim
+.*.sw[a-p]
+
+## Build systems ##
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
# We use maven!
-/build.xml
+build.xml
# Maven
-/target
dependency-reduced-pom.xml
+target/
-# Vim
-.*.sw[a-p]
+# Gradle
+!gradle-wrapper.jar
+.gradle
+build/
+gradle-app.setting
+.gradletasknamecache
+
+# Package Files
+*.jar
+*.war
+*.ear
# Various other potential build files
-/build
-/bin
-/dist
-/manifest.mf
+*.class
+build/
+bin/
+dist/
+manifest.mf
-/world
+## Other files ##
# Mac filesystem dust
-.DS_Store
+.DS_Store/
-# IntelliJ
-*.iml
-*.ipr
-*.iws
-.idea/
\ No newline at end of file
+# Logs
+*.log*
+hs_err_pid*
+
+# Keystore files
+*.jks
+
+# delombok
+*/src/main/lombok
diff --git a/README.md b/README.md
index a965bdf..913ca70 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
Fe, the simple economy plugin
=============
-Welcome to the GitHub repository for Fe! If you'd like to contribute code, you can make a pull request.
\ No newline at end of file
+Welcome to the GitHub repository for Fe! If you'd like to contribute code, you can make a pull request.
+
+Currently, build server for this fork is based here: https://ci.methuselah.ru/job/Fe-economy
diff --git a/config.yml b/config.yml
deleted file mode 100644
index d81fd4d..0000000
--- a/config.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-holdings: 10.00
-
-maxholdings: -1
-
-prefix: Fe
-
-topsize: 5
-
-currency:
- negative: false
- major:
- single: Fe
- multiple: Fe
- minor:
- enabled: false
- single: Fe
- multiple: Fe
- prefix: ""
-
-type: sqlite
-
-updatecheck: true
-
-cacheaccounts: true
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 38f3e79..e8e2944 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,90 +1,107 @@
- 4.0.0
- com.niccholaspage.Fe
- Fe
- 0.8-SNAPSHOT
- Fe
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+ com.niccholaspage
+ Fe
+ 0.9.3
+ Fe
+
+
+ UTF-8
+ Fe
+
-
-
- bukkit-repo
- http://repo.bukkit.org/content/groups/public/
-
-
- vault-repo
- http://nexus.theyeticave.net/content/repositories/pub_releases
-
-
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/groups/public/
+
+
+ vault-repo
+ http://nexus.theyeticave.net/content/repositories/pub_releases/
+
+
+ metrics-repo
+ http://repo.mcstats.org/content/repositories/public/
+
+
-
-
- org.bukkit
- bukkit
- 1.7.9-R0.1-SNAPSHOT
-
-
- net.milkbowl.vault
- VaultAPI
- 1.4
- jar
- compile
-
-
- org.mongodb
- mongo-java-driver
- 2.10.1
-
-
-
- clean package install
- ${project.name}
- ${basedir}/src
-
-
- .
- true
- ${basedir}
-
- *.yml
-
-
-
-
-
- maven-compiler-plugin
- 2.3.2
-
- 1.6
- 1.6
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.1
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.1
-
-
- package
-
- shade
-
-
- true
-
-
- org.mongodb:mongo-java-driver
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+ org.spigotmc
+ spigot-api
+ 1.10-R0.1-SNAPSHOT
+ provided
+
+
+ net.milkbowl.vault
+ VaultAPI
+ 1.6
+ jar
+ provided
+
+
+ org.mcstats.bukkit
+ metrics
+ R8-SNAPSHOT
+
+
+
+
+ ${project.name}_v${project.version}
+
+
+ maven-compiler-plugin
+ 3.3
+
+ 1.7
+ 1.7
+ ${project.build.sourceEncoding}
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.6
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.3
+
+
+ package
+
+ shade
+
+
+ true
+
+
+ org.mcstats.bukkit:metrics
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 2.7
+
+ ${project.build.sourceEncoding}
+
+
+
+
+
+ src/main/resources
+ true
+
+ *.yml
+
+
+
+
+
diff --git a/src/main/java/com/niccholaspage/Fe/API/Account.java b/src/main/java/com/niccholaspage/Fe/API/Account.java
new file mode 100644
index 0000000..2db50a4
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/API/Account.java
@@ -0,0 +1,16 @@
+package com.niccholaspage.Fe.API;
+
+import java.util.UUID;
+
+public interface Account extends Comparable
+{
+ public UUID getUUID();
+ public String getName();
+ public void setName(String name);
+ public double getMoney();
+ public void setMoney(double money);
+ public boolean has(double amount);
+ public boolean canReceive(double amount);
+ public void deposit(double amount);
+ public void withdraw(double amount);
+}
diff --git a/src/main/java/com/niccholaspage/Fe/API/CommandType.java b/src/main/java/com/niccholaspage/Fe/API/CommandType.java
new file mode 100644
index 0000000..de58c02
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/API/CommandType.java
@@ -0,0 +1,8 @@
+package com.niccholaspage.Fe.API;
+
+public enum CommandType
+{
+ CONSOLE,
+ PLAYER,
+ CONSOLE_WITH_ARGUMENTS
+}
diff --git a/src/main/java/com/niccholaspage/Fe/API/Database.java b/src/main/java/com/niccholaspage/Fe/API/Database.java
new file mode 100644
index 0000000..2b0a928
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/API/Database.java
@@ -0,0 +1,30 @@
+package com.niccholaspage.Fe.API;
+
+import java.util.List;
+import java.util.UUID;
+import org.bukkit.configuration.ConfigurationSection;
+
+public interface Database
+{
+ public String getName();
+ public boolean isAsync();
+ public boolean initialize();
+ public void close();
+ public String getConfigName();
+ public ConfigurationSection getConfigSection();
+ public void getConfigDefaults(ConfigurationSection section);
+ public void onRenameAccount(Account account, String oldName, String newName);
+ public List loadAccounts();
+ public List getAccounts();
+ public List getTopAccounts(int size);
+ public boolean accountExists(UUID uuid);
+ public boolean accountExists(String name);
+ public Account createAccount(UUID uuid, String name);
+ public Account getAccount(UUID uuid);
+ public Account getAccount(String name);
+ public void saveAccount(Account account);
+ public void reloadAccount(Account account);
+ public void removeAccount(Account account);
+ public void cleanAccountsWithDefaultHoldings();
+ public void removeAllAccounts();
+}
diff --git a/src/main/java/com/niccholaspage/Fe/API/FeAPI.java b/src/main/java/com/niccholaspage/Fe/API/FeAPI.java
new file mode 100644
index 0000000..ce805fe
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/API/FeAPI.java
@@ -0,0 +1,168 @@
+package com.niccholaspage.Fe.API;
+
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.List;
+import java.util.Locale;
+import java.util.UUID;
+import org.bukkit.ChatColor;
+
+public class FeAPI
+{
+ private final Fe plugin;
+ public FeAPI(Fe plugin)
+ {
+ this.plugin = plugin;
+ }
+ public double getDefaultHoldings()
+ {
+ return plugin.settings.getDefaultHoldings();
+ }
+ public double getMaxHoldings()
+ {
+ return plugin.settings.getMaximumHoldings();
+ }
+ public boolean isAutoClean()
+ {
+ return plugin.settings.isAutoClean();
+ }
+ public String getCurrencyPrefix()
+ {
+ return plugin.settings.getCurrencyPrefix();
+ }
+ public boolean isCurrencyNegative()
+ {
+ return plugin.settings.isCurrencyNegative();
+ }
+ public String getCurrencyMajorSingle()
+ {
+ return plugin.settings.getCurrencyMajorSingle();
+ }
+ public String getCurrencyMajorMultiple()
+ {
+ return plugin.settings.getCurrencyMajorMultiple();
+ }
+ public boolean isMinorCurrencyEnabled()
+ {
+ return plugin.settings.isMinorCurrencyEnabled();
+ }
+ public String getCurrencyMinorSingle()
+ {
+ return plugin.settings.getCurrencyMinorSingle();
+ }
+ public String getCurrencyMinorMultiple()
+ {
+ return plugin.settings.getCurrencyMinorMultiple();
+ }
+ public List getAccounts()
+ {
+ return plugin.getDB().loadAccounts();
+ }
+ public List getTopAccounts()
+ {
+ return plugin.getDB().getTopAccounts(plugin.settings.getShowTop());
+ }
+ public List getTopAccounts(int size)
+ {
+ return plugin.getDB().getTopAccounts(size);
+ }
+ public boolean accountExists(UUID uuid)
+ {
+ return plugin.getDB().accountExists(uuid);
+ }
+ public boolean accountExists(String name)
+ {
+ return plugin.getDB().accountExists(name);
+ }
+ public Account createAccount(UUID uuid, String name)
+ {
+ return plugin.getDB().createAccount(uuid, name);
+ }
+ public Account getAccount(UUID uuid)
+ {
+ return plugin.getDB().getAccount(uuid);
+ }
+ public Account getAccount(String name)
+ {
+ return plugin.getDB().getAccount(name);
+ }
+ public void removeAccount(Account account)
+ {
+ plugin.getDB().removeAccount(account);
+ }
+ public void clean()
+ {
+ plugin.getDB().cleanAccountsWithDefaultHoldings();
+ }
+ public String formatNoColor(double amount)
+ {
+ return ChatColor.stripColor(format(amount));
+ }
+ private String formatValue(double value)
+ {
+ boolean isWholeNumber = value == Math.round(value);
+ DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(Locale.ENGLISH);
+ formatSymbols.setDecimalSeparator('.');
+ String pattern = isWholeNumber ? "###,###.###" : "###,##0.00";
+ DecimalFormat df = new DecimalFormat(pattern, formatSymbols);
+ return df.format(value);
+ }
+ public String format(double amount)
+ {
+ amount = getMoneyRounded(amount);
+ String suffix = " ";
+ if(isMinorCurrencyEnabled() && amount > 0.00 && amount < 1.0)
+ {
+ if(amount == 0.01)
+ suffix += getCurrencyMinorSingle();
+ else if(amount < 1.0)
+ suffix += getCurrencyMinorMultiple();
+ amount *= 100;
+ } else
+ if(amount == 1.0)
+ suffix += getCurrencyMajorSingle();
+ else
+ suffix += getCurrencyMajorMultiple();
+ if(suffix.equalsIgnoreCase(" "))
+ suffix = "";
+ return Phrases.SECONDARY_COLOR.parse() + getCurrencyPrefix() + Phrases.PRIMARY_COLOR.parse() + formatValue(amount) + Phrases.SECONDARY_COLOR.parse() + suffix;
+ }
+ public double getMoneyRounded(double amount)
+ {
+ DecimalFormat twoDForm = new DecimalFormat("#.##");
+ String formattedAmount = twoDForm.format(amount);
+ formattedAmount = formattedAmount.replace(",", ".");
+ return Double.valueOf(formattedAmount);
+ }
+ public String formatNoColor(Account account)
+ {
+ return ChatColor.stripColor(format(account));
+ }
+ public String format(Account account)
+ {
+ return format(account.getMoney());
+ }
+ public void printDebugStackTrace()
+ {
+ if(plugin.settings.debug())
+ {
+ final String prefix = "[" + plugin.getName() + "]";
+ final StringBuilder sb = new StringBuilder(prefix);
+ sb.append("[DEBUG] An API method was invoked from the path:").append(System.lineSeparator());
+ for(StackTraceElement ste : Thread.currentThread().getStackTrace())
+ {
+ final String className = ste.getClassName();
+ if(!className.equals(FeAPI.class.getName())
+ && !className.equals(Thread.class.getName())
+ )
+ sb.append(prefix).append("[DEBUG] ")
+ .append(className.startsWith(Fe.class.getPackage().getName()) ? ChatColor.GREEN : ChatColor.GRAY)
+ .append(ste.toString())
+ .append(System.lineSeparator());
+ }
+ plugin.getServer().getConsoleSender().sendMessage(sb.toString());
+ }
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/API/SubCommand.java b/src/main/java/com/niccholaspage/Fe/API/SubCommand.java
new file mode 100644
index 0000000..5c6e28e
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/API/SubCommand.java
@@ -0,0 +1,50 @@
+package com.niccholaspage.Fe.API;
+
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+public abstract class SubCommand
+{
+ protected final Fe plugin;
+ private final String name;
+ private final String permission;
+ private final String usage;
+ private final Phrases description;
+ private final CommandType commandType;
+ public abstract boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args);
+ public SubCommand(Fe plugin, String name, String permission, String usage, Phrases description, CommandType commandType)
+ {
+ this.plugin = plugin;
+ this.name = name;
+ this.permission = permission;
+ this.usage = usage;
+ this.description = description;
+ this.commandType = commandType;
+ }
+ public String getFirstName()
+ {
+ return name.split(",")[0];
+ }
+ public String getName()
+ {
+ return name;
+ }
+ public String getPermission()
+ {
+ return permission;
+ }
+ public String getUsage()
+ {
+ return usage;
+ }
+ public Phrases getDescription()
+ {
+ return description;
+ }
+ public CommandType getCommandType()
+ {
+ return commandType;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/BalanceCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/BalanceCommand.java
new file mode 100644
index 0000000..c7bdc4a
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/BalanceCommand.java
@@ -0,0 +1,44 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class BalanceCommand extends SubCommand
+{
+ public BalanceCommand(Fe plugin)
+ {
+ super(plugin, "balance,bal", "fe.balance", "(name)", Phrases.COMMAND_BALANCE, CommandType.CONSOLE_WITH_ARGUMENTS);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ if(args.length > 0 && sender.hasPermission("fe.balance.other"))
+ {
+ Account account = plugin.getShortenedAccount(args[0]);
+ if(account == null)
+ {
+ Phrases.ACCOUNT_DOES_NOT_EXIST.sendWithPrefix(sender);
+ return true;
+ }
+ Phrases.ACCOUNT_HAS.sendWithPrefix(sender, account.getName(), plugin.api.format(account));
+ } else {
+ Player player = plugin.getServer().getPlayer(sender.getName());
+ Account account = player != null
+ ? plugin.api.getAccount(player.getUniqueId())
+ : plugin.api.getAccount(sender.getName());
+ if(account == null)
+ {
+ Phrases.YOUR_ACCOUNT_DOES_NOT_EXIST.sendWithPrefix(sender);
+ return true;
+ }
+ Phrases.YOU_HAVE.sendWithPrefix(sender, plugin.api.format(account));
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/CleanCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/CleanCommand.java
new file mode 100644
index 0000000..a67ae6c
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/CleanCommand.java
@@ -0,0 +1,23 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+public class CleanCommand extends SubCommand
+{
+ public CleanCommand(Fe plugin)
+ {
+ super(plugin, "clean", "fe.clean", "clean", Phrases.COMMAND_CLEAN, CommandType.CONSOLE);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ plugin.api.clean();
+ Phrases.ACCOUNT_CLEANED.sendWithPrefix(sender);
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/DebugCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/DebugCommand.java
new file mode 100644
index 0000000..8742b4f
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/DebugCommand.java
@@ -0,0 +1,24 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+public class DebugCommand extends SubCommand
+{
+ public DebugCommand(Fe plugin)
+ {
+ super(plugin, "debug", "fe.debug", "debug", Phrases.COMMAND_DEBUG, CommandType.CONSOLE);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ final boolean enable = !plugin.settings.debug();
+ plugin.settings.debug(enable);
+ Phrases.DEBUG_STATUS.sendWithPrefix(sender, enable ? "enabled" : "disabled");
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/DeductCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/DeductCommand.java
new file mode 100644
index 0000000..1b51447
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/DeductCommand.java
@@ -0,0 +1,44 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class DeductCommand extends SubCommand
+{
+ public DeductCommand(Fe plugin)
+ {
+ super(plugin, "deduct", "fe.deduct", "deduct [name] [amount]", Phrases.COMMAND_DEDUCT, CommandType.CONSOLE);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ if(args.length < 2)
+ return false;
+ double money;
+ try
+ {
+ money = Double.parseDouble(args[1]);
+ } catch(NumberFormatException e) {
+ return false;
+ }
+ Account victim = plugin.getShortenedAccount(args[0]);
+ if(victim == null)
+ {
+ Phrases.ACCOUNT_DOES_NOT_EXIST.sendWithPrefix(sender);
+ return true;
+ }
+ String formattedMoney = plugin.api.format(money);
+ victim.withdraw(money);
+ Phrases.PLAYER_DEDUCT_MONEY.sendWithPrefix(sender, formattedMoney, victim.getName());
+ Player receiverPlayer = plugin.getServer().getPlayerExact(victim.getName());
+ if(receiverPlayer != null)
+ Phrases.PLAYER_DEDUCTED_MONEY.sendWithPrefix(receiverPlayer, formattedMoney, sender.getName());
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/GrantCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/GrantCommand.java
new file mode 100644
index 0000000..970af40
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/GrantCommand.java
@@ -0,0 +1,49 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class GrantCommand extends SubCommand
+{
+ public GrantCommand(Fe plugin)
+ {
+ super(plugin, "grant", "fe.grant", "grant [name] [amount]", Phrases.COMMAND_GRANT, CommandType.CONSOLE);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ if(args.length < 2)
+ return false;
+ double money;
+ try
+ {
+ money = Double.parseDouble(args[1]);
+ } catch(NumberFormatException e) {
+ return false;
+ }
+ Account victim = plugin.getShortenedAccount(args[0]);
+ if(victim == null)
+ {
+ Phrases.ACCOUNT_DOES_NOT_EXIST.sendWithPrefix(sender);
+ return true;
+ }
+ if(!victim.canReceive(money))
+ {
+ Phrases.MAX_BALANCE_REACHED.sendWithPrefix(sender, victim.getName());
+ return true;
+ }
+ String formattedMoney = plugin.api.format(money);
+ victim.deposit(money);
+ Phrases.PLAYER_GRANT_MONEY.sendWithPrefix(sender, formattedMoney, victim.getName());
+ Player receiverPlayer = plugin.getServer().getPlayerExact(victim.getName());
+ if(receiverPlayer != null)
+ Phrases.PLAYER_GRANTED_MONEY.sendWithPrefix(receiverPlayer, formattedMoney, sender.getName());
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/HelpCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/HelpCommand.java
new file mode 100644
index 0000000..6b2e670
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/HelpCommand.java
@@ -0,0 +1,40 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.FeCommands;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class HelpCommand extends SubCommand
+{
+ private final FeCommands command;
+ public HelpCommand(Fe plugin, FeCommands command)
+ {
+ super(plugin, "help,?", "fe.?", "help", Phrases.COMMAND_HELP, CommandType.CONSOLE);
+ this.command = command;
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ sender.sendMessage(plugin.getEqualMessage(Phrases.HELP.parse(), 10));
+ String operatorColor = Phrases.TERTIARY_COLOR.parse();
+ String textColor = Phrases.SECONDARY_COLOR.parse();
+ sender.sendMessage(textColor + Phrases.HELP_ARGUMENTS.parse(operatorColor + "[]" + textColor, operatorColor + "()" + textColor));
+ for(SubCommand subcmd : this.command.getCommands())
+ {
+ if(subcmd.getName().equalsIgnoreCase(getName()))
+ continue;
+ if(!sender.hasPermission(subcmd.getPermission()))
+ continue;
+ if(!(sender instanceof Player) && subcmd.getCommandType() == CommandType.PLAYER)
+ continue;
+ sender.sendMessage(this.command.parse(commandLabel, subcmd) + textColor + " - " + subcmd.getDescription().parse());
+ }
+ sender.sendMessage(plugin.getEndEqualMessage(27));
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/MigrateCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/MigrateCommand.java
new file mode 100644
index 0000000..4d959a2
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/MigrateCommand.java
@@ -0,0 +1,42 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.Database;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+public class MigrateCommand extends SubCommand
+{
+ public MigrateCommand(Fe plugin)
+ {
+ super(plugin, "migrate", "fe.migrate", "migrate", Phrases.COMMAND_MIGRATE, CommandType.CONSOLE);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ if(args != null && args.length > 0 && args[0] != null && !"".equals(args[0]))
+ {
+ final String targetName = args[0].replace(" ", "").toLowerCase();
+ final Database source = plugin.getDB();
+ final Database target = plugin.findDB(targetName);
+ if(target != null)
+ {
+ if(target != source && target.initialize())
+ {
+ target.removeAllAccounts();
+ for(Account account : source.getAccounts())
+ target.saveAccount(account);
+ target.close();
+ Phrases.DATABASE_MIGRATED.sendWithPrefix(sender);
+ } else
+ Phrases.DATABASE_THE_SAME.sendWithPrefix(sender);
+ } else
+ Phrases.DATABASE_NOT_FOUND.sendWithPrefix(sender);
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/ReloadCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/ReloadCommand.java
new file mode 100644
index 0000000..cee1611
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/ReloadCommand.java
@@ -0,0 +1,26 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.plugin.PluginManager;
+
+public class ReloadCommand extends SubCommand
+{
+ public ReloadCommand(Fe plugin)
+ {
+ super(plugin, "reload", "fe.reload", "reload", Phrases.COMMAND_RELOAD, CommandType.CONSOLE);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ final PluginManager pluginManager = plugin.getServer().getPluginManager();
+ pluginManager.disablePlugin(plugin);
+ pluginManager.enablePlugin(plugin);
+ Phrases.CONFIG_RELOADED.sendWithPrefix(sender);
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/SendCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/SendCommand.java
new file mode 100644
index 0000000..6c06888
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/SendCommand.java
@@ -0,0 +1,63 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SendCommand extends SubCommand
+{
+ public SendCommand(Fe plugin)
+ {
+ super(plugin, "send,pay,give", "fe.send", "send [name] [amount]", Phrases.COMMAND_SEND, CommandType.PLAYER);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ if(args.length < 2)
+ return false;
+ double money;
+ try
+ {
+ money = Double.parseDouble(args[1]);
+ } catch(NumberFormatException e) {
+ return false;
+ }
+ if(money <= 0.0)
+ return false;
+ Account receiver = plugin.getShortenedAccount(args[0]);
+ if(receiver == null)
+ {
+ Phrases.ACCOUNT_DOES_NOT_EXIST.sendWithPrefix(sender);
+ return true;
+ }
+ Account account = plugin.api.getAccount(sender.getName());
+ if(!account.has(money))
+ {
+ Phrases.NOT_ENOUGH_MONEY.sendWithPrefix(sender);
+ return true;
+ }
+ if(!receiver.canReceive(money))
+ {
+ Phrases.MAX_BALANCE_REACHED.sendWithPrefix(sender, receiver.getName());
+ return true;
+ }
+ if(account.equals(receiver))
+ {
+ Phrases.YOU_HAVE.sendWithPrefix(sender, plugin.api.format(account));
+ return true;
+ }
+ account.withdraw(money);
+ receiver.deposit(money);
+ String formattedMoney = plugin.api.format(money);
+ Phrases.MONEY_SENT.sendWithPrefix(sender, formattedMoney, receiver.getName());
+ Player receiverPlayer = plugin.getServer().getPlayerExact(receiver.getName());
+ if(receiverPlayer != null)
+ Phrases.MONEY_RECEIVE.sendWithPrefix(receiverPlayer, formattedMoney, sender.getName());
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/SetCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/SetCommand.java
new file mode 100644
index 0000000..3787225
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/SetCommand.java
@@ -0,0 +1,45 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+public class SetCommand extends SubCommand
+{
+ public SetCommand(Fe plugin)
+ {
+ super(plugin, "set", "fe.set", "set [name] [amount]", Phrases.COMMAND_SET, CommandType.CONSOLE);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ if(args.length < 2)
+ return false;
+ double money;
+ try
+ {
+ money = Double.parseDouble(args[1]);
+ } catch(NumberFormatException e) {
+ return false;
+ }
+ Account victim = plugin.getShortenedAccount(args[0]);
+ if(victim == null)
+ {
+ Phrases.ACCOUNT_DOES_NOT_EXIST.sendWithPrefix(sender);
+ return true;
+ }
+ if(!victim.canReceive(money))
+ {
+ Phrases.MAX_BALANCE_REACHED.sendWithPrefix(sender, victim.getName());
+ return true;
+ }
+ String formattedMoney = plugin.api.format(money);
+ victim.setMoney(money);
+ Phrases.PLAYER_SET_MONEY.sendWithPrefix(sender, victim.getName(), formattedMoney);
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Commands/TopCommand.java b/src/main/java/com/niccholaspage/Fe/Commands/TopCommand.java
new file mode 100644
index 0000000..2854ac7
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Commands/TopCommand.java
@@ -0,0 +1,48 @@
+package com.niccholaspage.Fe.Commands;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Fe;
+import com.niccholaspage.Fe.Phrases;
+import java.util.List;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+public class TopCommand extends SubCommand
+{
+ public TopCommand(Fe plugin)
+ {
+ super(plugin, "top", "fe.top", "top", Phrases.COMMAND_TOP, CommandType.CONSOLE);
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ int topSize = plugin.settings.getShowTop();
+ try
+ {
+ if(args.length > 0 && args[0] != null && !"".equals(args[0]))
+ {
+ int enteredTop = Integer.parseInt(args[0]);
+ if(enteredTop > 0)
+ topSize = enteredTop;
+ }
+ } catch(NumberFormatException e) {
+ }
+ List topAccounts = plugin.api.getTopAccounts(topSize);
+ if(topAccounts.size() < 1)
+ {
+ Phrases.NO_ACCOUNTS_EXIST.sendWithPrefix(sender);
+ return true;
+ }
+ sender.sendMessage(plugin.getEqualMessage(Phrases.RICH.parse(), 10));
+ for(int i = 0; i < topAccounts.size(); i++)
+ {
+ Account account = topAccounts.get(i);
+ String two = Phrases.SECONDARY_COLOR.parse();
+ sender.sendMessage(two + (i + 1) + ". " + Phrases.PRIMARY_COLOR.parse() + account.getName() + two + " - " + plugin.api.format(account));
+ }
+ sender.sendMessage(plugin.getEndEqualMessage(28));
+ return true;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Databases/AccountInt.java b/src/main/java/com/niccholaspage/Fe/Databases/AccountInt.java
new file mode 100644
index 0000000..0ad690f
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Databases/AccountInt.java
@@ -0,0 +1,101 @@
+package com.niccholaspage.Fe.Databases;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.Database;
+import com.niccholaspage.Fe.Fe;
+import java.util.UUID;
+import org.bukkit.entity.Player;
+
+public class AccountInt implements Account
+{
+ private final Fe plugin;
+ private final Database database;
+ protected UUID uuid;
+ protected String name;
+ protected double money;
+ private Player player;
+ public AccountInt(Fe plugin, DatabaseGeneric database, String name, UUID uuid, double money)
+ {
+ this.plugin = plugin;
+ this.database = database;
+ this.name = name;
+ this.uuid = uuid;
+ this.money = money;
+ }
+ @Override
+ public UUID getUUID()
+ {
+ return uuid;
+ }
+ @Override
+ public String getName()
+ {
+ return this.name;
+ }
+ @Override
+ public void setName(String name)
+ {
+ database.onRenameAccount(this, this.name, name);
+ this.name = name;
+ database.saveAccount(this);
+ }
+ @Override
+ public double getMoney()
+ {
+ return money;
+ }
+ @Override
+ public void setMoney(double money)
+ {
+ if(money < 0 && !plugin.api.isCurrencyNegative())
+ money = 0;
+ money = plugin.api.getMoneyRounded(money);
+ final double maxHoldings = plugin.api.getMaxHoldings();
+ if(plugin.api.getMaxHoldings() > 0.0 && money > maxHoldings)
+ money = plugin.api.getMoneyRounded(maxHoldings);
+ this.money = money;
+ database.saveAccount(this);
+ }
+ @Override
+ public void withdraw(double amount)
+ {
+ setMoney(money - amount);
+ }
+ @Override
+ public void deposit(double amount)
+ {
+ setMoney(money + amount);
+ }
+ @Override
+ public boolean has(double amount)
+ {
+ return getMoney() >= amount;
+ }
+ @Override
+ public boolean canReceive(double amount)
+ {
+ final double maxHoldings = plugin.api.getMaxHoldings();
+ return maxHoldings < 0.0 || getMoney() + amount <= maxHoldings;
+ }
+ @Override
+ public int compareTo(Account other)
+ {
+ return (int)(other.getMoney() - getMoney());
+ }
+ public boolean isConnected()
+ {
+ return player != null;
+ }
+ public Player getPlayer()
+ {
+ return player;
+ }
+ public void connected(Player player)
+ {
+ this.player = player;
+ }
+ public void disconnected()
+ {
+ this.player = null;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Databases/DatabaseGeneric.java b/src/main/java/com/niccholaspage/Fe/Databases/DatabaseGeneric.java
new file mode 100644
index 0000000..01eb717
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Databases/DatabaseGeneric.java
@@ -0,0 +1,105 @@
+package com.niccholaspage.Fe.Databases;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.Database;
+import com.niccholaspage.Fe.Fe;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.bukkit.configuration.ConfigurationSection;
+
+public abstract class DatabaseGeneric implements Database
+{
+ protected final Fe plugin;
+ protected final Map accounts = new HashMap<>();
+ public DatabaseGeneric(Fe plugin)
+ {
+ this.plugin = plugin;
+ }
+ @Override
+ public String getConfigName()
+ {
+ return getName().replace(" ", "").toLowerCase();
+ }
+ @Override
+ public ConfigurationSection getConfigSection()
+ {
+ return plugin.settings.getDatabaseSection(getConfigName());
+ }
+ @Override
+ public void onRenameAccount(Account account, String oldName, String newName)
+ {
+ accounts.remove(oldName);
+ if(newName != null && !"".equals(newName))
+ accounts.put(newName, account);
+ }
+ @Override
+ public abstract List loadAccounts();
+ @Override
+ public List getAccounts()
+ {
+ return new ArrayList<>(accounts.values());
+ }
+ @Override
+ public List getTopAccounts(int size)
+ {
+ final LinkedList topList = new LinkedList<>(new LinkedHashSet<>(accounts.values()));
+ Collections.sort(topList);
+ return topList.subList(0, Math.min(size, topList.size()));
+ }
+ @Override
+ public boolean accountExists(UUID uuid)
+ {
+ return accounts.containsKey(uuid.toString());
+ }
+ @Override
+ public boolean accountExists(String name)
+ {
+ return accounts.containsKey(name);
+ }
+ @Override
+ public Account createAccount(UUID uuid, String name)
+ {
+ final Account existByUUID = accounts.get(uuid.toString());
+ if(existByUUID != null)
+ return existByUUID;
+ final Account existByName = accounts.get(name);
+ if(existByName != null)
+ return existByName;
+ final Account account = new AccountInt(plugin, this, name, uuid, plugin.api.getDefaultHoldings());
+ accounts.put(uuid.toString(), account);
+ if(name != null && !"".equals(name))
+ accounts.put(name, account);
+ saveAccount(account);
+ return account;
+ }
+ @Override
+ public Account getAccount(UUID uuid)
+ {
+ return accounts.get(uuid.toString());
+ }
+ @Override
+ public Account getAccount(String name)
+ {
+ return accounts.get(name);
+ }
+ @Override
+ public abstract void saveAccount(Account account);
+ @Override
+ public void removeAccount(Account account)
+ {
+ accounts.remove(account.getName());
+ UUID uuid = account.getUUID();
+ if(uuid != null)
+ accounts.remove(uuid.toString());
+ }
+ @Override
+ public abstract void cleanAccountsWithDefaultHoldings();
+ @Override
+ public abstract void removeAllAccounts();
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Databases/DatabaseSQL.java b/src/main/java/com/niccholaspage/Fe/Databases/DatabaseSQL.java
new file mode 100644
index 0000000..f747165
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Databases/DatabaseSQL.java
@@ -0,0 +1,283 @@
+package com.niccholaspage.Fe.Databases;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.Fe;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public abstract class DatabaseSQL extends DatabaseGeneric
+{
+ private final boolean supportsModification;
+ private final long pingDelay = 20 * 60;
+ protected String tableAccounts = "fe_accounts";
+ protected String tableVersion = "fe_version";
+ protected String columnAccountsUser = "name";
+ protected String columnAccountsUUID = "uuid";
+ protected String columnAccountsMoney = "money";
+ private Connection connection;
+ protected abstract Connection getNewConnection();
+ public DatabaseSQL(Fe plugin, boolean supportsModification)
+ {
+ super(plugin);
+ this.supportsModification = supportsModification;
+ plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ if(connection != null && !connection.isClosed())
+ connection.createStatement().execute("/* ping */ SELECT 1;");
+ } catch(SQLException e) {
+ connection = getNewConnection();
+ }
+ }
+ }, pingDelay, pingDelay);
+ }
+ @Override
+ public boolean initialize()
+ {
+ return checkConnection();
+ }
+ @Override
+ public void close()
+ {
+ try
+ {
+ if(connection != null)
+ connection.close();
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ }
+ @Override
+ public List loadAccounts()
+ {
+ checkConnection();
+ try(ResultSet set = connection.createStatement().executeQuery("SELECT * FROM `" + tableAccounts + "`;"))
+ {
+ while(set.next())
+ fromResultSet(set);
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ return new ArrayList(accounts.values());
+ }
+ private Account fromResultSet(ResultSet set) throws SQLException
+ {
+ final String name = set.getString(columnAccountsUser);
+ final String uuid = set.getString(columnAccountsUUID);
+ final AccountInt account = new AccountInt(plugin, this,
+ name, uuid != null ? UUID.fromString(uuid) : null,
+ set.getDouble(columnAccountsMoney));
+ if(name != null && !"".equals(name))
+ accounts.put(name, account);
+ if(uuid != null && !"".equals(uuid))
+ accounts.put(uuid, account);
+ return account;
+ }
+ protected abstract String getSaveAccountQuery(Account account);
+ @Override
+ public void saveAccount(Account account)
+ {
+ checkConnection();
+ try
+ {
+ if(plugin.settings.debug()) System.out.println("MySQL task - Player: " + account.getName());
+ if(plugin.settings.debug()) System.out.println("MySQL query: " + getSaveAccountQuery(account));
+ query(getSaveAccountQuery(account));
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ }
+ @Override
+ public void reloadAccount(Account account)
+ {
+ checkConnection();
+ final UUID uuid = account.getUUID();
+ final String query = uuid != null
+ ? "SELECT * FROM `" + tableAccounts + "` WHERE `" + columnAccountsUUID + "` = '" + uuid.toString() + "';"
+ : "SELECT * FROM `" + tableAccounts + "` WHERE `" + columnAccountsUser + "` = '" + account.getName() + "';";
+ try(ResultSet set = connection.createStatement().executeQuery(query))
+ {
+ if(set.next())
+ {
+ final AccountInt internal = (AccountInt)account;
+ final String dbuuid = set.getString(columnAccountsUUID);
+ final String dbname = set.getString(columnAccountsUser);
+ internal.uuid = dbuuid != null ? UUID.fromString(dbuuid) : internal.uuid;
+ internal.name = dbname != null ? dbname : internal.name;
+ internal.money = set.getDouble(columnAccountsMoney);
+ if(internal.name != null && !"".equals(internal.name))
+ accounts.put(dbname, account);
+ if(internal.uuid != null)
+ accounts.put(internal.uuid.toString(), account);
+ }
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ }
+ @Override
+ public void removeAccount(Account account)
+ {
+ super.removeAccount(account);
+ checkConnection();
+ try
+ {
+ query(account.getUUID() != null
+ ? "DELETE FROM `" + tableAccounts + "` WHERE `" + columnAccountsUUID + "` = '" + account.getUUID().toString() + "';"
+ : "DELETE FROM `" + tableAccounts + "` WHERE `" + columnAccountsUser + "` = '" + account.getName() + "';");
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ }
+ @Override
+ public void cleanAccountsWithDefaultHoldings()
+ {
+ checkConnection();
+ try
+ {
+ query("DELETE FROM `" + tableAccounts + "` WHERE `" + columnAccountsMoney + "` = '" + plugin.api.getDefaultHoldings() + "';");
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ }
+ @Override
+ public void removeAllAccounts()
+ {
+ checkConnection();
+ try
+ {
+ query("DELETE FROM `" + tableAccounts + "`;");
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ }
+ protected void setAccountTable(String accountsName)
+ {
+ this.tableAccounts = accountsName;
+ }
+ protected void setVersionTable(String versionName)
+ {
+ this.tableVersion = versionName;
+ }
+ protected void setAccountsColumnUser(String accountsColumnUser)
+ {
+ this.columnAccountsUser = accountsColumnUser;
+ }
+ protected void setAccountsColumnUUID(String accountsColumnUUID)
+ {
+ this.columnAccountsUUID = accountsColumnUUID;
+ }
+ protected void setAccountsColumnMoney(String accountsColumnMoney)
+ {
+ this.columnAccountsMoney = accountsColumnMoney;
+ }
+ private synchronized boolean checkConnection()
+ {
+ try
+ {
+ if(connection == null || connection.isClosed())
+ {
+ connection = getNewConnection();
+ if(connection == null || connection.isClosed())
+ return false;
+ boolean newDatabase;
+ try(ResultSet set = connection.prepareStatement(supportsModification
+ ? "SHOW TABLES LIKE '" + tableAccounts + "';"
+ : "SELECT `name` FROM `sqlite_master` WHERE `type` = 'table' AND `name` = '" + tableAccounts + "';")
+ .executeQuery())
+ {
+ newDatabase = set.next();
+ }
+ query("CREATE TABLE IF NOT EXISTS `" + tableAccounts + "` (`" + columnAccountsUser + "` VARCHAR(16) NOT NULL, `" + columnAccountsUUID + "` CHAR(36), `" + columnAccountsMoney + "` DOUBLE NOT NULL);");
+ query("CREATE TABLE IF NOT EXISTS `" + tableVersion + "` (`version` INT NOT NULL);");
+ // Add `id` column
+ try
+ {
+ query("ALTER TABLE `" + tableAccounts + "` ADD COLUMN `id` INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`), ADD UNIQUE INDEX `id_UNIQUE` (`id` ASC);");
+ } catch(SQLException ex) {
+ // `id` already exists?
+ if(!ex.getMessage().contains("already exists"))
+ System.err.println(ex);
+ }
+ // Add UNIQUE KEY for UUID
+ try
+ {
+ query("ALTER TABLE `" + tableAccounts + "` ADD UNIQUE INDEX `uuid_UNIQUE` (`" + columnAccountsUUID + "` ASC);");
+ } catch(SQLException ex) {
+ // `uuid_UNIQUE` already exists?
+ if(!ex.getMessage().contains("already exists"))
+ System.err.println(ex);
+ }
+ // Add UNIQUE KEY for nickname
+ try
+ {
+ query("ALTER TABLE `" + tableAccounts + "` ADD UNIQUE INDEX `name_UNIQUE` (`" + columnAccountsUser + "` ASC);");
+ } catch(SQLException ex) {
+ // `name_UNIQUE` already exists?
+ if(!ex.getMessage().contains("already exists"))
+ System.err.println(ex);
+ }
+ if(newDatabase)
+ {
+ int version = getVersion();
+ if(version == 0)
+ {
+ if(supportsModification)
+ {
+ query("ALTER TABLE `" + tableAccounts + "` MODIFY `" + columnAccountsUser + "` VARCHAR(16) NOT NULL");
+ query("ALTER TABLE `" + tableAccounts + "` MODIFY `" + columnAccountsMoney + "` DOUBLE NOT NULL");
+ }
+ try
+ {
+ query("ALTER TABLE `" + tableAccounts + "` ADD `" + columnAccountsUUID + "` CHAR(36);");
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ setVersion(1);
+ }
+ } else
+ setVersion(1);
+ }
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ return false;
+ }
+ return true;
+ }
+ private synchronized boolean query(String sql) throws SQLException
+ {
+ return connection.createStatement().execute(sql);
+ }
+ private int getVersion()
+ {
+ checkConnection();
+ int version = 0;
+ try(ResultSet set = connection.prepareStatement("SELECT * from " + tableVersion).executeQuery())
+ {
+ if(set.next())
+ version = set.getInt("version");
+ return version;
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ return version;
+ }
+ }
+ private void setVersion(int version)
+ {
+ checkConnection();
+ try
+ {
+ query("DELETE FROM `" + tableVersion + "`;");
+ query("INSERT INTO `" + tableVersion + "` (`version`) VALUES ('" + version + "');");
+ } catch(SQLException ex) {
+ System.err.println(ex);
+ }
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Databases/DefferedTask.java b/src/main/java/com/niccholaspage/Fe/Databases/DefferedTask.java
new file mode 100644
index 0000000..dc0ddc9
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Databases/DefferedTask.java
@@ -0,0 +1,15 @@
+package com.niccholaspage.Fe.Databases;
+import com.niccholaspage.Fe.API.Account;
+
+public abstract class DefferedTask implements Runnable
+{
+ private final Account account;
+ public DefferedTask(Account account)
+ {
+ this.account = account;
+ }
+ public Account getAccount()
+ {
+ return account;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Databases/MySQLDB.java b/src/main/java/com/niccholaspage/Fe/Databases/MySQLDB.java
new file mode 100644
index 0000000..f08dff4
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Databases/MySQLDB.java
@@ -0,0 +1,195 @@
+package com.niccholaspage.Fe.Databases;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.Fe;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.UUID;
+import java.util.concurrent.LinkedBlockingQueue;
+import org.bukkit.configuration.ConfigurationSection;
+
+public class MySQLDB extends DatabaseSQL implements Runnable
+{
+ private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>();
+ private Thread dispatcher;
+ private boolean maximumConsistency = true;
+ public MySQLDB(Fe plugin)
+ {
+ super(plugin, true);
+ }
+ @Override
+ public String getName()
+ {
+ return "MySQL";
+ }
+ @Override
+ public boolean isAsync()
+ {
+ return true;
+ }
+ @Override
+ public boolean initialize()
+ {
+ maximumConsistency = getConfigSection().getBoolean("maximum-consistency", true);
+ if(super.initialize())
+ {
+ dispatcher = new Thread(this);
+ dispatcher.start();
+ return true;
+ }
+ return false;
+ }
+ @Override
+ public void close()
+ {
+ if(dispatcher != null)
+ {
+ try
+ {
+ dispatcher.interrupt();
+ dispatcher.join();
+ dispatcher = null;
+ } catch(InterruptedException e) {
+ }
+ }
+ processActiveTasks();
+ super.close();
+ }
+ @Override
+ public void run()
+ {
+ try
+ {
+ for(DefferedTask task = queue.take(); task != null; task = queue.take())
+ task.run();
+ } catch(InterruptedException e) {
+ }
+ }
+ @Override
+ public void saveAccount(Account account)
+ {
+ queue.offer(new DefferedTask(account)
+ {
+ @Override
+ public void run()
+ {
+ MySQLDB.super.saveAccount(getAccount());
+ }
+ });
+ }
+ @Override
+ public Account getAccount(UUID uuid)
+ {
+ final Account account = super.getAccount(uuid);
+ if(maximumConsistency && account != null)
+ super.reloadAccount(account);
+ return account;
+ }
+ @Override
+ public Account getAccount(String name)
+ {
+ final Account account = super.getAccount(name);
+ if(maximumConsistency && account != null)
+ super.reloadAccount(account);
+ return account;
+ }
+ @Override
+ public void reloadAccount(Account account)
+ {
+ processActiveTasks();
+ queue.offer(new DefferedTask(account)
+ {
+ @Override
+ public void run()
+ {
+ MySQLDB.super.reloadAccount(getAccount());
+ }
+ });
+ }
+ @Override
+ public void removeAccount(Account account)
+ {
+ processActiveTasks();
+ queue.offer(new DefferedTask(account)
+ {
+ @Override
+ public void run()
+ {
+ MySQLDB.super.removeAccount(getAccount());
+ }
+ });
+ }
+ private synchronized int processActiveTasks()
+ {
+ int result = 0;
+ for(DefferedTask task = queue.poll(); task != null; task = queue.poll())
+ {
+ task.run();
+ result += 1;
+ }
+ return result;
+ }
+ @Override
+ protected Connection getNewConnection()
+ {
+ final ConfigurationSection config = getConfigSection();
+ setAccountTable (config.getString("tables.accounts"));
+ setAccountsColumnUser (config.getString("columns.accounts.username"));
+ setAccountsColumnMoney(config.getString("columns.accounts.money"));
+ setAccountsColumnUUID (config.getString("columns.accounts.uuid"));
+ try
+ {
+ Class.forName("com.mysql.jdbc.Driver");
+ return DriverManager.getConnection(
+ "jdbc:mysql://" + config.getString("connection.database"),
+ config.getString("connection.username"),
+ config.getString("connection.password"));
+ } catch(ClassNotFoundException | SQLException ex) {
+ System.err.println(ex);
+ return null;
+ }
+ }
+ @Override
+ public void getConfigDefaults(ConfigurationSection section)
+ {
+ final ConfigurationSection tables = getSection(section, "tables");
+ tables.addDefault("accounts", "fe_accounts");
+ final ConfigurationSection columns = getSection(section, "columns");
+ final ConfigurationSection columnsAccounts = getSection(columns, "accounts");
+ columnsAccounts.addDefault("username", "name");
+ columnsAccounts.addDefault("money", "money");
+ columnsAccounts.addDefault("uuid", "uuid");
+ final ConfigurationSection connection = getSection(section, "connection");
+ connection.addDefault("database", "localhost:3306/minecraft");
+ connection.addDefault("username", "user");
+ connection.addDefault("password", "pass");
+ section.addDefault("maximum-consistency", true);
+ }
+ private ConfigurationSection getSection(ConfigurationSection parent, String childName)
+ {
+ ConfigurationSection child = parent.getConfigurationSection(childName);
+ if(child == null)
+ child = parent.createSection(childName);
+ return child;
+ }
+ @Override
+ protected String getSaveAccountQuery(Account account)
+ {
+ final String strName = account.getName();
+ final String strBlnc = String.valueOf(account.getMoney());
+ if(account.getUUID() != null)
+ {
+ final String struuid = account.getUUID().toString();
+ return "INSERT INTO `" + tableAccounts + "` (`" + columnAccountsUser + "`, `" + columnAccountsUUID + "`, `" + columnAccountsMoney + "`) "
+ + "VALUES ('" + strName + "', '" + struuid + "', '" + strBlnc + "') ON DUPLICATE KEY UPDATE "
+ + "`" + columnAccountsUser + "` = VALUES(`" + columnAccountsUser + "`), "
+ + "`" + columnAccountsUUID + "` = VALUES(`" + columnAccountsUUID + "`), "
+ + "`" + columnAccountsMoney + "` = VALUES(`" + columnAccountsMoney + "`);";
+ }
+ return "INSERT INTO `" + tableAccounts + "` (`" + columnAccountsUser + "`, `" + columnAccountsMoney + "`) "
+ + "VALUES (" + strName + ", '" + strBlnc + "') ON DUPLICATE KEY UPDATE "
+ + "`" + columnAccountsUser + "` = VALUES(`" + columnAccountsUser + "`), "
+ + "`" + columnAccountsMoney + "` = VALUES(`" + columnAccountsMoney + "`);";
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Databases/SQLiteDB.java b/src/main/java/com/niccholaspage/Fe/Databases/SQLiteDB.java
new file mode 100644
index 0000000..3cc8433
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Databases/SQLiteDB.java
@@ -0,0 +1,57 @@
+package com.niccholaspage.Fe.Databases;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.Fe;
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import org.bukkit.configuration.ConfigurationSection;
+
+public class SQLiteDB extends DatabaseSQL
+{
+ public SQLiteDB(Fe plugin)
+ {
+ super(plugin, false);
+ }
+ @Override
+ public String getName()
+ {
+ return "SQLite";
+ }
+ @Override
+ public boolean isAsync()
+ {
+ return false;
+ }
+ @Override
+ public Connection getNewConnection()
+ {
+ try
+ {
+ Class.forName("org.sqlite.JDBC");
+ return DriverManager.getConnection(
+ "jdbc:sqlite:" + new File(plugin.getDataFolder(), "database.db").getAbsolutePath());
+ } catch(ClassNotFoundException | SQLException e) {
+ return null;
+ }
+ }
+ @Override
+ public void getConfigDefaults(ConfigurationSection section)
+ {
+ }
+ @Override
+ protected String getSaveAccountQuery(Account account)
+ {
+ final String strName = account.getName();
+ final String strBlnc = String.valueOf(account.getMoney());
+ if(account.getUUID() != null)
+ {
+ final String struuid = account.getUUID().toString();
+ return "INSERT OR REPLACE INTO `" + tableAccounts + "` (`" + columnAccountsUser + "`, `" + columnAccountsUUID + "`, `" + columnAccountsMoney + "`) "
+ + "VALUES ('" + strName + "', '" + struuid + "', '" + strBlnc + "');";
+ }
+ return "INSERT OR REPLACE INTO `" + tableAccounts + "` (`" + columnAccountsUser + "`, `" + columnAccountsMoney + "`) "
+ + "VALUES ('" + strName + "', '" + strBlnc + "');";
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Fe.java b/src/main/java/com/niccholaspage/Fe/Fe.java
new file mode 100644
index 0000000..41709f4
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Fe.java
@@ -0,0 +1,200 @@
+package com.niccholaspage.Fe;
+
+import com.niccholaspage.Fe.API.Account;
+import com.niccholaspage.Fe.API.Database;
+import com.niccholaspage.Fe.API.FeAPI;
+import com.niccholaspage.Fe.Databases.MySQLDB;
+import com.niccholaspage.Fe.Databases.SQLiteDB;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import net.milkbowl.vault.economy.Economy;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.ServicePriority;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.mcstats.Metrics;
+import org.mcstats.Metrics.Graph;
+import org.mcstats.Metrics.Plotter;
+
+public class Fe extends JavaPlugin
+{
+ public final FeAPI api = new FeAPI(this);
+ public final FeSettings settings = new FeSettings(this);
+ private final FeListener listener = new FeListener(this);
+ private final FeCommands commands = new FeCommands(this);
+ private final Set databases = new HashSet<>();
+ private Database database;
+ @Override
+ public void onLoad()
+ {
+ settings.onLoad();
+ Phrases.initialize(this);
+ }
+ @Override
+ public void onEnable()
+ {
+ settings.onEnable();
+ log("Language File location:" + new File(getDataFolder(), "phrases.yml").getAbsolutePath());
+ Phrases.setupPhrases(new File(getDataFolder(), "phrases.yml"));
+ databases.add(new MySQLDB(this));
+ databases.add(new SQLiteDB(this));
+ for(Database db : databases)
+ db.getConfigDefaults(db.getConfigSection());
+ getConfig().options().copyDefaults(true);
+ saveConfig();
+ if(!setupDatabase())
+ {
+ getServer().getPluginManager().disablePlugin(this);
+ return;
+ }
+ getCommand("fe").setExecutor(commands);
+ getServer().getPluginManager().registerEvents(listener, this);
+ setupVault();
+ loadMetrics();
+ // Load all accounts
+ database.loadAccounts();
+ // Autoclean on startup
+ if(api.isAutoClean())
+ {
+ api.clean();
+ log(Phrases.ACCOUNT_CLEANED);
+ }
+ }
+ private boolean setupDatabase()
+ {
+ String type = settings.getDatabase();
+ database = null;
+ for(Database db : databases)
+ if(type.equalsIgnoreCase(db.getConfigName()))
+ {
+ this.database = db;
+ break;
+ }
+ if(database == null)
+ {
+ log(Phrases.DATABASE_TYPE_DOES_NOT_EXIST);
+ return false;
+ }
+ log("Using " + database.getName());
+ if(!database.initialize())
+ {
+ log(Phrases.DATABASE_FAILURE_DISABLE);
+ setEnabled(false);
+ return false;
+ }
+ return true;
+ }
+ private void setupVault()
+ {
+ if(getServer().getPluginManager().getPlugin("Vault") != null)
+ getServer().getServicesManager().register(Economy.class, new VaultHandler(this), this, ServicePriority.Highest);
+ }
+ @Override
+ public void onDisable()
+ {
+ getServer().getScheduler().cancelTasks(this);
+ getDB().close();
+ getServer().getServicesManager().unregisterAll(this);
+ }
+ public FeAPI getAPI()
+ {
+ return api;
+ }
+ public Database getDB()
+ {
+ return database;
+ }
+ public Database findDB(String targetName)
+ {
+ for(Database db : databases)
+ if(db.getConfigName().equals(targetName))
+ return db;
+ return null;
+ }
+ public void log(String message)
+ {
+ getLogger().info(message);
+ }
+ public void log(Phrases phrase, String... args)
+ {
+ log(phrase.parse(args));
+ }
+ public Account getShortenedAccount(String name)
+ {
+ Account account = api.getAccount(name);
+ if(account == null)
+ {
+ final Player player = getServer().getPlayer(name);
+ if(player != null)
+ {
+ account = api.getAccount(player.getUniqueId().toString());
+ if(account == null)
+ account = api.getAccount(player.getName());
+ }
+ }
+ return account;
+ }
+ public String getMessagePrefix()
+ {
+ String third = Phrases.TERTIARY_COLOR.parse();
+ return third + "[" + Phrases.PRIMARY_COLOR.parse() + "$1" + third + "] " + Phrases.SECONDARY_COLOR.parse();
+ }
+ public String getEqualMessage(String inBetween, int length)
+ {
+ return getEqualMessage(inBetween, length, length);
+ }
+ public String getEqualMessage(String inBetween, int length, int length2)
+ {
+ String equals = getEndEqualMessage(length);
+ String end = getEndEqualMessage(length2);
+ String third = Phrases.TERTIARY_COLOR.parse();
+ return equals + third + "[" + Phrases.PRIMARY_COLOR.parse() + inBetween + third + "]" + end;
+ }
+ public String getEndEqualMessage(int length)
+ {
+ String message = Phrases.SECONDARY_COLOR.parse() + "";
+ for(int i = 0; i < length; i ++)
+ message += "=";
+ return message;
+ }
+ private void loadMetrics()
+ {
+ try
+ {
+ Metrics metrics = new Metrics(this);
+ final Graph databaseGraph = metrics.createGraph("Database Engine");
+ databaseGraph.addPlotter(new Plotter(getDB().getName())
+ {
+ @Override
+ public int getValue()
+ {
+ return 1;
+ }
+ });
+ final Graph defaultHoldings = metrics.createGraph("Default Holdings");
+ defaultHoldings.addPlotter(new Plotter(Double.toString(api.getDefaultHoldings()))
+ {
+ @Override
+ public int getValue()
+ {
+ return 1;
+ }
+ });
+ final Graph maxHoldings = metrics.createGraph("Max Holdings");
+ String maxHolding = Double.toString(api.getMaxHoldings());
+ if(api.getMaxHoldings() == -1)
+ maxHolding = "Unlimited";
+ maxHoldings.addPlotter(new Plotter(maxHolding)
+ {
+ @Override
+ public int getValue()
+ {
+ return 1;
+ }
+ });
+ metrics.start();
+ } catch(IOException e) {
+ }
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/FeCommands.java b/src/main/java/com/niccholaspage/Fe/FeCommands.java
new file mode 100644
index 0000000..0584186
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/FeCommands.java
@@ -0,0 +1,140 @@
+package com.niccholaspage.Fe;
+
+import com.niccholaspage.Fe.API.CommandType;
+import com.niccholaspage.Fe.API.SubCommand;
+import com.niccholaspage.Fe.Commands.BalanceCommand;
+import com.niccholaspage.Fe.Commands.CleanCommand;
+import com.niccholaspage.Fe.Commands.DebugCommand;
+import com.niccholaspage.Fe.Commands.DeductCommand;
+import com.niccholaspage.Fe.Commands.GrantCommand;
+import com.niccholaspage.Fe.Commands.HelpCommand;
+import com.niccholaspage.Fe.Commands.MigrateCommand;
+import com.niccholaspage.Fe.Commands.ReloadCommand;
+import com.niccholaspage.Fe.Commands.SendCommand;
+import com.niccholaspage.Fe.Commands.SetCommand;
+import com.niccholaspage.Fe.Commands.TopCommand;
+import java.util.ArrayList;
+import java.util.List;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class FeCommands implements CommandExecutor
+{
+ private final List commands = new ArrayList<>();
+ public FeCommands(Fe plugin)
+ {
+ commands.add(new BalanceCommand(plugin));
+ commands.add(new SendCommand(plugin));
+ commands.add(new TopCommand(plugin));
+ commands.add(new HelpCommand(plugin, this));
+ commands.add(new SetCommand(plugin));
+ commands.add(new GrantCommand(plugin));
+ commands.add(new DeductCommand(plugin));
+ commands.add(new CleanCommand(plugin));
+ commands.add(new DebugCommand(plugin));
+ commands.add(new MigrateCommand(plugin));
+ commands.add(new ReloadCommand(plugin));
+ }
+ public List getCommands()
+ {
+ return commands;
+ }
+ private SubCommand getCommand(String name)
+ {
+ for(SubCommand command : commands)
+ {
+ String[] aliases = command.getName().split(",");
+ for(String alias : aliases)
+ if(alias.equalsIgnoreCase(name))
+ return command;
+ }
+ return null;
+ }
+ private String[] merge(String[]... arrays)
+ {
+ int arraySize = 0;
+ for(String[] array : arrays)
+ arraySize += array.length;
+ String[] result = new String[arraySize];
+ int j = 0;
+ for(String[] array : arrays)
+ for(String string : array)
+ result[j ++] = string;
+ return result;
+ }
+ private void sendDefaultCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ String command = "balance";
+ if(!(sender instanceof Player) && args.length < 1)
+ command = "help";
+ onCommand(sender, cmd, commandLabel, merge(new String[] { command }, args));
+ }
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
+ {
+ if(args.length < 1)
+ {
+ sendDefaultCommand(sender, cmd, commandLabel, args);
+ return true;
+ }
+ SubCommand command = getCommand(args[0]);
+ if(command == null)
+ {
+ sendDefaultCommand(sender, cmd, commandLabel, args);
+ return true;
+ }
+ boolean console = !(sender instanceof Player);
+ if(console && args.length < 2 && command.getCommandType() == CommandType.CONSOLE_WITH_ARGUMENTS)
+ {
+ Phrases.COMMAND_NEEDS_ARGUMENTS.sendWithPrefix(sender);
+ return true;
+ }
+ if(console && command.getCommandType() == CommandType.PLAYER)
+ {
+ Phrases.COMMAND_NOT_CONSOLE.sendWithPrefix(sender, commandLabel);
+ return true;
+ }
+ if(!sender.hasPermission(command.getPermission()))
+ {
+ Phrases.NO_PERMISSION_FOR_COMMAND.sendWithPrefix(sender);
+ return true;
+ }
+ String[] realArgs = new String[args.length - 1];
+ for(int i = 1; i < args.length; i ++)
+ realArgs[i - 1] = args[i];
+ if(!command.onCommand(sender, cmd, commandLabel, realArgs))
+ Phrases.TRY_COMMAND.sendWithPrefix(sender, parse(commandLabel, command));
+ return true;
+ }
+ public String parse(String label, SubCommand command)
+ {
+ String commandColor = Phrases.PRIMARY_COLOR.parse();
+ String operatorsColor = Phrases.PRIMARY_COLOR.parse();
+ String argumentColor = Phrases.ARGUMENT_COLOR.parse();
+ StringBuilder builder = new StringBuilder(commandColor).append("/").append(label);
+ if(!command.getFirstName().equalsIgnoreCase("balance"))
+ builder.append(" ").append(command.getFirstName()).append(" ");
+ String[] split = command.getUsage().split(" ");
+ if(split[0].equalsIgnoreCase(command.getFirstName()))
+ {
+ for(int i = 1; i < split.length; i ++)
+ builder.append(parseArg(split[i], operatorsColor, argumentColor)).append(" ");
+ builder.deleteCharAt(builder.length() - 1);
+ } else {
+ builder.append(" ").append(parseArg(split[0], operatorsColor, argumentColor)).append(" ");
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ return builder.toString();
+ }
+ private String parseArg(String argument, String operatorsColor, String argumentColor)
+ {
+ String operator = argument.substring(0, 1);
+ argument = argument.substring(1, argument.length());
+ String reverse = operator.equals("[") ? "]" : ")";
+ argument = argument.substring(0, argument.length() - 1);
+ argument = operatorsColor + operator + argumentColor + argument + operatorsColor + reverse;
+ return argument;
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/FeListener.java b/src/main/java/com/niccholaspage/Fe/FeListener.java
new file mode 100644
index 0000000..004abec
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/FeListener.java
@@ -0,0 +1,42 @@
+package com.niccholaspage.Fe;
+
+import com.niccholaspage.Fe.Databases.AccountInt;
+import com.niccholaspage.Fe.API.Database;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerKickEvent;
+import org.bukkit.event.player.PlayerLoginEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+public class FeListener implements Listener
+{
+ private final Fe plugin;
+ public FeListener(Fe plugin)
+ {
+ this.plugin = plugin;
+ }
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onPlayerLogin(PlayerLoginEvent event)
+ {
+ final Player player = event.getPlayer();
+ final Database database = plugin.getDB();
+ final AccountInt account = (AccountInt)database.createAccount(player.getUniqueId(), player.getName());
+ database.reloadAccount(account);
+ account.setName(player.getName());
+ account.connected(player);
+ }
+ @EventHandler
+ public void onPlayerKick(PlayerKickEvent event)
+ {
+ final AccountInt account = (AccountInt)plugin.getDB().getAccount(event.getPlayer().getUniqueId());
+ account.disconnected();
+ }
+ @EventHandler
+ public void onPlayerQuit(PlayerQuitEvent event)
+ {
+ final AccountInt account = (AccountInt)plugin.getDB().getAccount(event.getPlayer().getUniqueId());
+ account.disconnected();
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/FeSettings.java b/src/main/java/com/niccholaspage/Fe/FeSettings.java
new file mode 100644
index 0000000..56a1291
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/FeSettings.java
@@ -0,0 +1,177 @@
+package com.niccholaspage.Fe;
+
+import com.google.common.io.Files;
+import java.io.File;
+import java.io.IOException;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.plugin.java.JavaPlugin;
+
+public class FeSettings
+{
+ private final JavaPlugin fe;
+ public FeSettings(JavaPlugin plugin)
+ {
+ this.fe = plugin;
+ }
+ public void onLoad()
+ {
+ fe.getDataFolder().mkdirs();
+ fe.saveDefaultConfig();
+ }
+ public void onEnable()
+ {
+ fe.reloadConfig();
+ final FileConfiguration config = fe.getConfig();
+ int version = config.getInt("internal.version", 0);
+ switch(version)
+ {
+ case 0:
+ fe.getLogger().info("[Fe] I will migrate config.yml to the newest format now.");
+ try
+ {
+ final File source = new File(fe.getDataFolder(), "config.yml");
+ final File target = new File(fe.getDataFolder(), "config.yml.v0-saved");
+ if(!target.isFile())
+ {
+ Files.copy(source, target);
+ fe.getLogger().info("[Fe] Backup of config.yml saved into config.yml.v0-saved.");
+ }
+ } catch(IOException ex) {
+ }
+ config.options().header(null);
+ migrate_v0_to_v1(config);
+ config.set("internal.version", 1);
+ fe.getLogger().info("[Fe] Configuration has been migrated successfully.");
+ // Insert new version updaters RIGHT HERE (using new "case #:" statements)
+ fe.saveConfig();
+ fe.reloadConfig();
+ default:
+ // Configuration is up-to-date
+ break;
+ }
+ }
+ public boolean debug()
+ {
+ return fe.getConfig().getBoolean("settings.debug", false);
+ }
+ public void debug(boolean enable)
+ {
+ fe.getConfig().set("settings.debug", enable);
+ fe.saveConfig();
+ }
+ public double getDefaultHoldings()
+ {
+ return fe.getConfig().getDouble("settings.new-player-holdings", 10.00);
+ }
+ public double getMaximumHoldings()
+ {
+ return fe.getConfig().getDouble("settings.maximum-holdings", -1.0);
+ }
+ public String getPrefix()
+ {
+ return fe.getConfig().getString("settings.prefix", "Fe");
+ }
+ public int getShowTop()
+ {
+ return fe.getConfig().getInt("settings.show-top", 10);
+ }
+ public boolean isAutoClean()
+ {
+ return fe.getConfig().getBoolean("settings.autoclean", true);
+ }
+ public String getCurrencyPrefix()
+ {
+ return fe.getConfig().getString("settings.currency.prefix");
+ }
+ public boolean isCurrencyNegative()
+ {
+ return fe.getConfig().getBoolean("settings.currency.negative");
+ }
+ public String getCurrencyMajorSingle()
+ {
+ return fe.getConfig().getString("settings.currency.major.single");
+ }
+ public String getCurrencyMajorMultiple()
+ {
+ return fe.getConfig().getString("settings.currency.major.multiple");
+ }
+ public boolean isMinorCurrencyEnabled()
+ {
+ return fe.getConfig().getBoolean("settings.currency.minor.enabled");
+ }
+ public String getCurrencyMinorSingle()
+ {
+ return fe.getConfig().getString("settings.currency.minor.single");
+ }
+ public String getCurrencyMinorMultiple()
+ {
+ return fe.getConfig().getString("settings.currency.minor.multiple");
+ }
+ public String getDatabase()
+ {
+ return fe.getConfig().getString("settings.database-type", "sqlite");
+ }
+ public ConfigurationSection getDatabaseSection(String name)
+ {
+ ConfigurationSection result = fe.getConfig().getConfigurationSection("settings." + name);
+ if(result == null)
+ result = fe.getConfig().createSection("settings." + name);
+ return result;
+ }
+ private void migrate_v0_to_v1(FileConfiguration config)
+ {
+ config.set("internal.do-not-touch", null);
+ final double new_player_holdings = config.getDouble("holdings", 10.00);
+ config.set("holdings", null);
+ config.set("settings.new-player-holdings", new_player_holdings);
+ final double maximum_holdings = config.getDouble("maxholdings", -1.0);
+ config.set("maxholdings", null);
+ config.set("settings.maximum-holdings", maximum_holdings);
+ final String prefix = config.getString("prefix", "Fe");
+ config.set("prefix", null);
+ config.set("settings.prefix", prefix);
+ final int show_top = config.getInt("topsize", 10);
+ config.set("topsize", null);
+ config.set("settings.show-top", show_top);
+ final ConfigurationSection currency = config.getConfigurationSection("currency");
+ config.set("currency", null);
+ config.set("settings.currency", currency);
+ final String database_type = config.getString("type", "sqlite");
+ config.set("type", null);
+ config.set("settings.database-type", database_type);
+ final boolean autoclean = config.getBoolean("autoclean", true);
+ config.set("autoclean", null);
+ config.set("settings.autoclean", autoclean);
+ ConfigurationSection mysql = config.getConfigurationSection("mysql");
+ if(mysql == null)
+ mysql = config.createSection("mysql");
+ mysql_v0_to_v1(mysql);
+ config.set("mysql", null);
+ config.set("settings.mysql", mysql);
+ config.set("sqlite", null);
+ // Remove old unused config nodes
+ config.set("cacheaccounts", null);
+ config.set("updatecheck", null);
+ }
+ private void mysql_v0_to_v1(ConfigurationSection mysql)
+ {
+ final String url = new StringBuilder()
+ .append(mysql.getString("host", "localhost"))
+ .append(":")
+ .append(mysql.getInt("port", 3306))
+ .append("/")
+ .append(mysql.getString("database", "minecraft"))
+ .toString();
+ mysql.set("host", null);
+ mysql.set("port", null);
+ mysql.set("database", null);
+ mysql.set("connection.database", url);
+ final String username = mysql.getString("user", "user1");
+ mysql.set("user", null);
+ mysql.set("connection.username", username);
+ final String password = mysql.getString("password", "pass1");
+ mysql.set("password", null);
+ mysql.set("connection.password", password);
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/Phrases.java b/src/main/java/com/niccholaspage/Fe/Phrases.java
new file mode 100644
index 0000000..2c3b132
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/Phrases.java
@@ -0,0 +1,142 @@
+package com.niccholaspage.Fe;
+
+import java.io.File;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+public enum Phrases
+{
+ DATABASE_TYPE_DOES_NOT_EXIST("That database type doesn't exist."),
+ DATABASE_FAILURE_DISABLE ("Database initialization has failed, disabling Fe."),
+ COMMAND_NEEDS_ARGUMENTS ("That command needs arguments."),
+ COMMAND_NOT_CONSOLE ("The command '$1' cannot be used in the console."),
+ NO_PERMISSION_FOR_COMMAND ("Sorry, you do not have permission to use that command."),
+ ACCOUNT_HAS ("$1 has $2"),
+ YOU_HAVE ("You have $1"),
+ HELP ("Fe Help"),
+ HELP_ARGUMENTS ("$1 Required, $2 Optional"),
+ RICH ("Rich List"),
+ STARTING_UUID_CONVERSION ("Starting UUID conversion."),
+ UUID_CONVERSION_FAILED ("UUID conversion failed, disabling Fe!"),
+ UUID_CONVERSION_SUCCEEDED ("UUID conversion has succeeded!"),
+ CONFIG_RELOADED ("The config has been reloaded."),
+ DATABASE_MIGRATED ("Database has been migrated."),
+ DATABASE_THE_SAME ("Please specify other target database type."),
+ DATABASE_NOT_FOUND ("Please specify one of existing dababase targets."),
+ NOT_ENOUGH_MONEY ("You don't have enough money."),
+ ACCOUNT_DOES_NOT_EXIST ("Sorry, that account does not exist."),
+ YOUR_ACCOUNT_DOES_NOT_EXIST ("You don't have an account."),
+ ACCOUNT_EXISTS ("That account already exists."),
+ ACCOUNT_CREATED ("An account for $1 has been created."),
+ ACCOUNT_REMOVED ("An account for $1 has been removed."),
+ MONEY_RECEIVE ("You've received $1 from $2."),
+ MONEY_SENT ("You've sent $1 to $2"),
+ MAX_BALANCE_REACHED ("$1 has reached the maximum balance."),
+ PLAYER_SET_MONEY ("You've set $1's balance to $2."),
+ PLAYER_GRANT_MONEY ("You've granted $1 to $2."),
+ PLAYER_GRANTED_MONEY ("$2 granted you $1."),
+ PLAYER_DEDUCT_MONEY ("You've deducted $1 from $2."),
+ PLAYER_DEDUCTED_MONEY ("$2 deducted $1 from your account."),
+ ACCOUNT_CREATED_GRANT ("Created an account for $1 and granted it $2"),
+ NO_ACCOUNTS_EXIST ("No accounts exist."),
+ NAME_TOO_LONG ("Sorry that name is too long."),
+ ACCOUNT_CLEANED ("All accounts with the default balance have been removed."),
+ TRY_COMMAND ("Try $1"),
+ PRIMARY_COLOR (ChatColor.GOLD.toString()),
+ SECONDARY_COLOR (ChatColor.GRAY.toString()),
+ TERTIARY_COLOR (ChatColor.DARK_GRAY.toString()),
+ ARGUMENT_COLOR (ChatColor.YELLOW.toString()),
+ DEBUG_STATUS ("Debugging is $1 now."),
+ COMMAND_BALANCE ("Checks your balance", true),
+ COMMAND_SEND ("Sends another player money", true),
+ COMMAND_TOP ("Checks the top 5 richest players", true),
+ COMMAND_HELP ("Gives you help", true),
+ COMMAND_CREATE ("Creates an account", true),
+ COMMAND_REMOVE ("Removes an account", true),
+ COMMAND_SET ("Set a player's balance", true),
+ COMMAND_GRANT ("Grants a player money", true),
+ COMMAND_DEDUCT ("Deducts money from a player", true),
+ COMMAND_CLEAN ("Cleans the accounts with default balance", true),
+ COMMAND_DEBUG ("Toggles console debug info", true),
+ COMMAND_RELOAD ("Reloads the config", true),
+ COMMAND_MIGRATE ("Migrates from default database into specified one", true),
+ ;
+ private static Fe plugin;
+ private final String defaultMessage;
+ private final boolean categorized;
+ private String message;
+ private Phrases(String defaultMessage)
+ {
+ this(defaultMessage, false);
+ }
+ private Phrases(String defaultMessage, boolean categorized)
+ {
+ this.defaultMessage = defaultMessage;
+ this.categorized = categorized;
+ message = defaultMessage + "";
+ }
+ public static void initialize(Fe instance)
+ {
+ plugin = instance;
+ }
+ private String getMessage()
+ {
+ return message;
+ }
+ public void setMessage(String message)
+ {
+ this.message = message;
+ }
+ public void reset()
+ {
+ message = defaultMessage + "";
+ }
+ public String getConfigName()
+ {
+ String name = name();
+ if(categorized)
+ name = name.replaceFirst("_", ".");
+ return name.toLowerCase();
+ }
+ public String parse(String... params)
+ {
+ String parsedMessage = getMessage();
+ if(params != null)
+ for(int i = 0; i < params.length; i ++)
+ parsedMessage = parsedMessage.replace("$" + (i + 1), params[i]);
+ return parsedMessage;
+ }
+ public String parseWithoutSpaces(String... params)
+ {
+ return parse(params).replace(" ", "");
+ }
+ private String parseWithPrefix(String... params)
+ {
+ return plugin.getMessagePrefix().replace("$1", plugin.settings.getPrefix()) + parse(params);
+ }
+ public void send(CommandSender sender, String... params)
+ {
+ sender.sendMessage(parse(params));
+ }
+ public void sendWithPrefix(CommandSender sender, String... params)
+ {
+ sender.sendMessage(parseWithPrefix(params));
+ }
+ public static void setupPhrases(File phrasesFile)
+ {
+ for(Phrases phrase : Phrases.values())
+ phrase.reset();
+ if(!phrasesFile.exists())
+ return;
+ YamlConfiguration phrasesConfig = YamlConfiguration.loadConfiguration(phrasesFile);
+ for(Phrases phrase : Phrases.values())
+ {
+ String phraseConfigName = phrase.getConfigName();
+ String phraseMessage = phrasesConfig.getString(phraseConfigName);
+ if(phraseMessage == null)
+ phraseMessage = phrase.parse();
+ phrase.setMessage(phraseMessage);
+ }
+ }
+}
diff --git a/src/main/java/com/niccholaspage/Fe/VaultHandler.java b/src/main/java/com/niccholaspage/Fe/VaultHandler.java
new file mode 100644
index 0000000..830b0df
--- /dev/null
+++ b/src/main/java/com/niccholaspage/Fe/VaultHandler.java
@@ -0,0 +1,325 @@
+package com.niccholaspage.Fe;
+
+import com.niccholaspage.Fe.API.Account;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import net.milkbowl.vault.economy.Economy;
+import net.milkbowl.vault.economy.EconomyResponse;
+import net.milkbowl.vault.economy.EconomyResponse.ResponseType;
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.server.PluginDisableEvent;
+import org.bukkit.event.server.PluginEnableEvent;
+import org.bukkit.plugin.Plugin;
+
+public class VaultHandler implements Economy, Listener
+{
+ private final String name = "Fe";
+ private Fe plugin;
+ public VaultHandler(Fe plugin)
+ {
+ this.plugin = plugin;
+ plugin.getServer().getPluginManager().registerEvents((Listener)this, plugin);
+ plugin.log("Vault support enabled.");
+ }
+ @Override
+ public boolean isEnabled()
+ {
+ return plugin != null;
+ }
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+ @Override
+ public String format(double amount)
+ {
+ return plugin.api.formatNoColor(amount);
+ }
+ @Override
+ public String currencyNameSingular()
+ {
+ return plugin.api.getCurrencyMajorSingle();
+ }
+ @Override
+ public String currencyNamePlural()
+ {
+ return plugin.api.getCurrencyMajorMultiple();
+ }
+ @Deprecated
+ @Override
+ public double getBalance(String playerName)
+ {
+ plugin.api.printDebugStackTrace();
+ final Account account = plugin.getDB().getAccount(playerName);
+ return account != null
+ ? account.getMoney()
+ : plugin.api.getDefaultHoldings();
+ }
+ @Override
+ public double getBalance(OfflinePlayer offlinePlayer)
+ {
+ plugin.api.printDebugStackTrace();
+ final Account account = plugin.getDB().getAccount(offlinePlayer.getUniqueId());
+ return account != null
+ ? account.getMoney()
+ : plugin.api.getDefaultHoldings();
+ }
+ @Deprecated
+ @Override
+ public EconomyResponse withdrawPlayer(String playerName, double amount)
+ {
+ final Account account = plugin.getDB().getAccount(playerName);
+ return withdraw(account, amount);
+ }
+ @Override
+ public EconomyResponse withdrawPlayer(OfflinePlayer offlinePlayer, double amount)
+ {
+ final Account account = plugin.getDB().getAccount(offlinePlayer.getUniqueId());
+ return withdraw(account, amount);
+ }
+ private EconomyResponse withdraw(Account account, double amount)
+ {
+ plugin.api.printDebugStackTrace();
+ if(amount < 0.0)
+ return new EconomyResponse(0.0, 0.0, ResponseType.FAILURE, "Cannot withdraw negative funds");
+ if(account == null)
+ return new EconomyResponse(0.0, 0.0, ResponseType.FAILURE, "Account doesn't exist");
+ if(account.has(amount))
+ {
+ account.withdraw(amount);
+ return new EconomyResponse(amount, account.getMoney(), ResponseType.SUCCESS, "");
+ } else
+ return new EconomyResponse(0, account.getMoney(), ResponseType.FAILURE, "Insufficient funds");
+ }
+ @Deprecated
+ @Override
+ public EconomyResponse depositPlayer(String playerName, double amount)
+ {
+ final Account account = plugin.getDB().getAccount(playerName);
+ return deposit(account, amount);
+ }
+ @Override
+ public EconomyResponse depositPlayer(OfflinePlayer offlinePlayer, double amount)
+ {
+ final Account account = plugin.getDB().getAccount(offlinePlayer.getUniqueId());
+ return deposit(account, amount);
+ }
+ private EconomyResponse deposit(Account account, double amount)
+ {
+ plugin.api.printDebugStackTrace();
+ if(amount < 0.0)
+ return new EconomyResponse(0.0, 0.0, ResponseType.FAILURE, "Cannot deposit negative funds");
+ if(account == null)
+ return new EconomyResponse(0.0, 0.0, ResponseType.FAILURE, "Account doesn't exist");
+ account.deposit(amount);
+ return new EconomyResponse(amount, account.getMoney(), ResponseType.SUCCESS, "");
+ }
+ @Deprecated
+ @Override
+ public boolean has(String playerName, double amount)
+ {
+ return getBalance(playerName) >= amount;
+ }
+ @Override
+ public boolean has(OfflinePlayer offlinePlayer, double amount)
+ {
+ return getBalance(offlinePlayer) >= amount;
+ }
+ @Deprecated
+ @Override
+ public EconomyResponse createBank(String name, String player)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public EconomyResponse createBank(String name, OfflinePlayer offlinePlayer)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public EconomyResponse deleteBank(String name)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public EconomyResponse bankHas(String name, double amount)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public EconomyResponse bankWithdraw(String name, double amount)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public EconomyResponse bankDeposit(String name, double amount)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Deprecated
+ @Override
+ public EconomyResponse isBankOwner(String name, String playerName)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public EconomyResponse isBankOwner(String name, OfflinePlayer offlinePlayer)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Deprecated
+ @Override
+ public EconomyResponse isBankMember(String name, String playerName)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public EconomyResponse isBankMember(String name, OfflinePlayer offlinePlayer)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public EconomyResponse bankBalance(String name)
+ {
+ return new EconomyResponse(0.0, 0.0, ResponseType.NOT_IMPLEMENTED, "Fe does not support bank accounts!");
+ }
+ @Override
+ public List getBanks()
+ {
+ return new ArrayList<>();
+ }
+ @Override
+ public boolean hasBankSupport()
+ {
+ return false;
+ }
+ @Deprecated
+ @Override
+ public boolean hasAccount(String playerName)
+ {
+ plugin.api.printDebugStackTrace();
+ return plugin.api.accountExists(playerName);
+ }
+ @Override
+ public boolean hasAccount(OfflinePlayer offlinePlayer)
+ {
+ plugin.api.printDebugStackTrace();
+ return plugin.api.accountExists(offlinePlayer.getUniqueId());
+ }
+ @Deprecated
+ @Override
+ public boolean createPlayerAccount(String playerName)
+ {
+ plugin.api.printDebugStackTrace();
+ return plugin.getDB().createAccount(UUID.randomUUID(), playerName) != null;
+ }
+ @Override
+ public boolean createPlayerAccount(OfflinePlayer offlinePlayer)
+ {
+ plugin.api.printDebugStackTrace();
+ Account account = plugin.getDB().createAccount(offlinePlayer.getUniqueId(), offlinePlayer.getName());
+ account.setName(offlinePlayer.getName());
+ plugin.getDB().saveAccount(account);
+ return true;
+ }
+ @Override
+ public int fractionalDigits()
+ {
+ return -1;
+ }
+ @Deprecated
+ @Override
+ public boolean hasAccount(String playerName, String worldName)
+ {
+ return hasAccount(playerName);
+ }
+ @Override
+ public boolean hasAccount(OfflinePlayer offlinePlayer, String worldName)
+ {
+ return hasAccount(offlinePlayer);
+ }
+ @Deprecated
+ @Override
+ public double getBalance(String playerName, String worldName)
+ {
+ return getBalance(playerName);
+ }
+ @Override
+ public double getBalance(OfflinePlayer offlinePlayer, String worldName)
+ {
+ return getBalance(offlinePlayer);
+ }
+ @Deprecated
+ @Override
+ public boolean has(String playerName, String worldName, double amount)
+ {
+ return has(playerName, amount);
+ }
+ @Override
+ public boolean has(OfflinePlayer offlinePlayer, String worldName, double amount)
+ {
+ return has(offlinePlayer, amount);
+ }
+ @Deprecated
+ @Override
+ public EconomyResponse withdrawPlayer(String playerName, String worldName, double amount)
+ {
+ return withdrawPlayer(playerName, amount);
+ }
+ @Override
+ public EconomyResponse withdrawPlayer(OfflinePlayer offlinePlayer, String worldName, double amount)
+ {
+ return withdrawPlayer(offlinePlayer, amount);
+ }
+ @Deprecated
+ @Override
+ public EconomyResponse depositPlayer(String playerName, String worldName, double amount)
+ {
+ return depositPlayer(playerName, amount);
+ }
+ @Override
+ public EconomyResponse depositPlayer(OfflinePlayer offlinePlayer, String worldName, double amount)
+ {
+ return depositPlayer(offlinePlayer, amount);
+ }
+ @Deprecated
+ @Override
+ public boolean createPlayerAccount(String playerName, String worldName)
+ {
+ return createPlayerAccount(playerName);
+ }
+ @Override
+ public boolean createPlayerAccount(OfflinePlayer offlinePlayer, String worldName)
+ {
+ return createPlayerAccount(offlinePlayer);
+ }
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onPluginEnable(PluginEnableEvent event)
+ {
+ if(plugin == null)
+ {
+ final Plugin fe = Bukkit.getServer().getPluginManager().getPlugin("Fe");
+ if(fe != null && fe.isEnabled())
+ {
+ plugin = (Fe)fe;
+ plugin.log("Vault support enabled.");
+ }
+ }
+ }
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onPluginDisable(PluginDisableEvent event)
+ {
+ if(plugin != null && event.getPlugin().getDescription().getName().equals(name))
+ {
+ plugin = null;
+ Bukkit.getLogger().info("[Fe] Vault support disabled.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..5e42d2d
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1,33 @@
+settings:
+ new-player-holdings: 10.00
+ maximum-holdings: -1.0
+ show-top: 10
+ prefix: Fe
+ currency:
+ prefix: ''
+ negative: false
+ major:
+ single: Fes
+ multiple: Fe
+ minor:
+ enabled: false
+ single: Fe
+ multiple: Fe
+ database-type: sqlite
+ sqlite: {}
+ mysql:
+ maximum-consistency: true
+ connection:
+ database: localhost:3306/minecraft
+ username: user
+ password: pass
+ tables:
+ accounts: fe_accounts
+ columns:
+ accounts:
+ uuid: uuid
+ username: name
+ money: money
+ autoclean: true
+internal:
+ version: 1
diff --git a/plugin.yml b/src/main/resources/plugin.yml
similarity index 89%
rename from plugin.yml
rename to src/main/resources/plugin.yml
index a3e29ce..a825087 100644
--- a/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,10 +1,7 @@
-name: Fe
-
-main: org.melonbrew.fe.Fe
-
-version: ${project.version}-b${BUILD_NUMBER}
-
-load: startup
+name: ${project.bukkitpluginname}
+main: ${project.groupId}.${project.artifactId}.${project.name}
+version: ${project.version}
+load: startup
commands:
fe:
@@ -54,6 +51,7 @@ permissions:
fe.balance.other: true
fe.send: true
fe.top: true
+ fe.help: true
fe.?: true
fe.admin:
children:
@@ -63,7 +61,9 @@ permissions:
fe.grant: true
fe.deduct: true
fe.clean: true
+ fe.debug: true
fe.reload: true
+ fe.migrate: true
fe.notify: true
fe.*:
children:
diff --git a/src/org/melonbrew/fe/API.java b/src/org/melonbrew/fe/API.java
deleted file mode 100644
index 51b79f4..0000000
--- a/src/org/melonbrew/fe/API.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.melonbrew.fe;
-
-import org.bukkit.ChatColor;
-import org.melonbrew.fe.database.Account;
-
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.util.List;
-import java.util.Locale;
-
-public class API {
- private final Fe plugin;
-
- public API(Fe plugin) {
- this.plugin = plugin;
- }
-
- public List getTopAccounts() {
- return plugin.getFeDatabase().getTopAccounts(plugin.getConfig().getInt("topsize"));
- }
-
- public List getTopAccounts(int size) {
- return plugin.getFeDatabase().getTopAccounts(size);
- }
-
- public List getAccounts() {
- return plugin.getFeDatabase().getAccounts();
- }
-
- public double getDefaultHoldings() {
- return plugin.getConfig().getDouble("holdings");
- }
-
- public double getMaxHoldings() {
- return plugin.getConfig().getDouble("maxholdings");
- }
-
- public String getCurrencyPrefix() {
- return plugin.getConfig().getString("currency.prefix");
- }
-
- public boolean isCurrencyNegative() {
- return plugin.getConfig().getBoolean("currency.negative");
- }
-
- public String getCurrencyMajorSingle() {
- return plugin.getConfig().getString("currency.major.single");
- }
-
- public String getCurrencyMajorMultiple() {
- return plugin.getConfig().getString("currency.major.multiple");
- }
-
- public boolean isMinorCurrencyEnabled() {
- return plugin.getConfig().getBoolean("currency.minor.enabled");
- }
-
- public String getCurrencyMinorSingle() {
- return plugin.getConfig().getString("currency.minor.single");
- }
-
- public String getCurrencyMinorMultiple() {
- return plugin.getConfig().getString("currency.minor.multiple");
- }
-
- public boolean getCacheAccounts() {
- return plugin.getConfig().getBoolean("cacheaccounts");
- }
-
- public Account createAccount(String name, String uuid) {
- return plugin.getFeDatabase().createAccount(name, uuid);
- }
-
- public void removeAccount(String name, String uuid) {
- plugin.getFeDatabase().removeAccount(name, uuid);
- }
-
- public Account getAccount(String name, String uuid) {
- return plugin.getFeDatabase().getAccount(name, uuid);
- }
-
- public boolean accountExists(String name, String uuid) {
- return plugin.getFeDatabase().accountExists(name, uuid);
- }
-
- public String formatNoColor(double amount) {
- return ChatColor.stripColor(format(amount));
- }
-
- private String formatValue(double value) {
- boolean isWholeNumber = value == Math.round(value);
-
- DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(Locale.ENGLISH);
-
- formatSymbols.setDecimalSeparator('.');
-
- String pattern = isWholeNumber ? "###,###.###" : "###,##0.00";
-
- DecimalFormat df = new DecimalFormat(pattern, formatSymbols);
-
- return df.format(value);
- }
-
- public String format(double amount) {
- amount = getMoneyRounded(amount);
-
- String suffix = " ";
-
- if (isMinorCurrencyEnabled() && amount > 0.00 && amount < 1.0) {
- if (amount == 0.01) {
- suffix += getCurrencyMinorSingle();
- } else if (amount < 1.0) {
- suffix += getCurrencyMinorMultiple();
- }
-
- amount *= 100;
- } else if (amount == 1.0) {
- suffix += getCurrencyMajorSingle();
- } else {
- suffix += getCurrencyMajorMultiple();
- }
-
- if (suffix.equalsIgnoreCase(" ")) {
- suffix = "";
- }
-
- return Phrase.SECONDARY_COLOR.parse() + getCurrencyPrefix() + Phrase.PRIMARY_COLOR.parse() + formatValue(amount) + Phrase.SECONDARY_COLOR.parse() + suffix;
- }
-
- public double getMoneyRounded(double amount) {
- DecimalFormat twoDForm = new DecimalFormat("#.##");
-
- String formattedAmount = twoDForm.format(amount);
-
- formattedAmount = formattedAmount.replace(",", ".");
-
- return Double.valueOf(formattedAmount);
- }
-
- public String formatNoColor(Account account) {
- return ChatColor.stripColor(format(account));
- }
-
- public String format(Account account) {
- return format(account.getMoney());
- }
-
- public void clean() {
- plugin.getFeDatabase().clean();
- }
-}
diff --git a/src/org/melonbrew/fe/Fe.java b/src/org/melonbrew/fe/Fe.java
deleted file mode 100644
index 48858c7..0000000
--- a/src/org/melonbrew/fe/Fe.java
+++ /dev/null
@@ -1,362 +0,0 @@
-package org.melonbrew.fe;
-
-import net.milkbowl.vault.economy.Economy;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.plugin.ServicePriority;
-import org.bukkit.plugin.java.JavaPlugin;
-import org.melonbrew.fe.Metrics.Graph;
-import org.melonbrew.fe.Metrics.Plotter;
-import org.melonbrew.fe.database.Account;
-import org.melonbrew.fe.database.Database;
-import org.melonbrew.fe.database.databases.MongoDB;
-import org.melonbrew.fe.database.databases.MySQLDB;
-import org.melonbrew.fe.database.databases.SQLiteDB;
-import org.melonbrew.fe.listeners.FePlayerListener;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-
-public class Fe extends JavaPlugin {
- private final Set databases;
- private API api;
- private Database database;
- private double currentVersion;
-
- private double latestVersion;
-
- private String latestVersionString;
-
- public Fe() {
- databases = new HashSet();
- }
-
- public void onEnable() {
- getDataFolder().mkdirs();
-
- Phrase.init(this);
-
- databases.add(new MySQLDB(this));
- databases.add(new SQLiteDB(this));
- databases.add(new MongoDB(this));
-
- for (Database database : databases) {
- String name = database.getConfigName();
-
- ConfigurationSection section = getConfig().getConfigurationSection(name);
-
- if (section == null) {
- section = getConfig().createSection(name);
- }
-
- database.getConfigDefaults(section);
-
- if (section.getKeys(false).isEmpty()) {
- getConfig().set(name, null);
- }
- }
-
- getConfig().options().copyDefaults(true);
-
- getConfig().options().header("Fe Config - okicore.com\n" +
- "holdings - The amount of money that players will start out with\n" +
- "prefix - The message prefix\n" +
- "currency - The single and multiple names for the currency\n" +
- "type - The type of database used (sqlite, mysql, or mongo)\n" +
- "updatecheck - Checks if there is an update to Fe" +
- "cacheaccounts - Caches players' balances when logged on to the server");
-
- saveConfig();
-
- api = new API(this);
-
- if (!setupDatabase()) {
- return;
- }
-
- String currentVersionString = getDescription().getVersion();
-
- currentVersion = versionToDouble(currentVersionString);
-
- setLatestVersion(currentVersion);
-
- setLatestVersionString(currentVersionString);
-
- getCommand("fe").setExecutor(new FeCommand(this));
-
- new FePlayerListener(this);
-
- setupVault();
-
- loadMetrics();
-
- if (getConfig().getBoolean("updatecheck")) {
- getServer().getScheduler().runTaskAsynchronously(this, new UpdateCheck(this));
- }
- }
-
- public void log(String message) {
- getLogger().info("[Fe] " + message);
- }
-
- public double versionToDouble(String version) {
- boolean isSnapshot = version.contains("-SNAPSHOT");
-
- version = version.substring(0, version.indexOf("-SNAPSHOT"));
-
- String fixed = "";
-
- boolean doneFirst = false;
-
- for (int i = 0; i < version.length(); i++) {
- char c = version.charAt(i);
-
- if (c == '.') {
- if (doneFirst) {
- continue;
- } else {
- doneFirst = true;
- }
- }
-
- fixed += c;
- }
-
- try {
- double ret = Double.parseDouble(fixed);
-
- if (isSnapshot) {
- ret -= 0.001;
- }
-
- return ret;
- } catch (NumberFormatException e) {
- return -1;
- }
- }
-
- public double getLatestVersion() {
- return latestVersion;
- }
-
- protected void setLatestVersion(double latestVersion) {
- this.latestVersion = latestVersion;
- }
-
- public String getLatestVersionString() {
- return latestVersionString;
- }
-
- protected void setLatestVersionString(String latestVersionString) {
- this.latestVersionString = latestVersionString;
- }
-
- public boolean isUpdated() {
- return currentVersion >= latestVersion;
- }
-
- public void onDisable() {
- getServer().getScheduler().cancelTasks(this);
-
- getFeDatabase().close();
- }
-
- public void log(Phrase phrase, String... args) {
- log(phrase.parse(args));
- }
-
- public Database getFeDatabase() {
- return database;
- }
-
- public boolean addDatabase(Database database) {
- return databases.add(database);
- }
-
- public Set getDatabases() {
- return new HashSet(databases);
- }
-
- public API getAPI() {
- return api;
- }
-
- private boolean setupDatabase() {
- String type = getConfig().getString("type");
-
- database = null;
-
- for (Database database : databases) {
- if (type.equalsIgnoreCase(database.getConfigName())) {
- this.database = database;
-
- break;
- }
- }
-
- if (database == null) {
- log(Phrase.DATABASE_TYPE_DOES_NOT_EXIST);
-
- return false;
- }
-
- if (!database.init()) {
- log(Phrase.DATABASE_FAILURE_DISABLE);
-
- setEnabled(false);
-
- return false;
- }
-
- return true;
- }
-
- private void setupPhrases() {
- File phrasesFile = new File(getDataFolder(), "phrases.yml");
-
- for (Phrase phrase : Phrase.values()) {
- phrase.reset();
- }
-
- if (!phrasesFile.exists()) {
- return;
- }
-
- YamlConfiguration phrasesConfig = YamlConfiguration.loadConfiguration(phrasesFile);
-
- for (Phrase phrase : Phrase.values()) {
- String phraseConfigName = phrase.getConfigName();
-
- String phraseMessage = phrasesConfig.getString(phraseConfigName);
-
- if (phraseMessage == null) {
- phraseMessage = phrase.parse();
- }
-
- phrase.setMessage(phraseMessage);
- }
- }
-
- public void reloadConfig() {
- super.reloadConfig();
-
- String oldCurrencySingle = getConfig().getString("currency.single");
-
- String oldCurrencyMultiple = getConfig().getString("currency.multiple");
-
- if (oldCurrencySingle != null) {
- getConfig().set("currency.major.single", oldCurrencySingle);
-
- getConfig().set("currency.single", null);
- }
-
- if (oldCurrencyMultiple != null) {
- getConfig().set("currency.major.multiple", oldCurrencyMultiple);
-
- getConfig().set("currency.multiple", null);
- }
-
- setupPhrases();
-
- saveConfig();
- }
-
- @SuppressWarnings("deprecation")
- public Account getShortenedAccount(String name) {
- Account account = getAPI().getAccount(name, null);
-
- if (account == null) {
- Player player = getServer().getPlayer(name);
-
- if (player != null) {
- account = getAPI().getAccount(player.getName(), null);
- }
- }
-
- return account;
- }
-
- public String getMessagePrefix() {
- String third = Phrase.TERTIARY_COLOR.parse();
-
- return third + "[" + Phrase.PRIMARY_COLOR.parse() + "$1" + third + "] " + Phrase.SECONDARY_COLOR.parse();
- }
-
- public String getEqualMessage(String inBetween, int length) {
- return getEqualMessage(inBetween, length, length);
- }
-
- public String getEqualMessage(String inBetween, int length, int length2) {
- String equals = getEndEqualMessage(length);
-
- String end = getEndEqualMessage(length2);
-
- String third = Phrase.TERTIARY_COLOR.parse();
-
- return equals + third + "[" + Phrase.PRIMARY_COLOR.parse() + inBetween + third + "]" + end;
- }
-
- public String getEndEqualMessage(int length) {
- String message = Phrase.SECONDARY_COLOR.parse() + "";
-
- for (int i = 0; i < length; i++) {
- message += "=";
- }
-
- return message;
- }
-
- private void loadMetrics() {
- try {
- Metrics metrics = new Metrics(this);
-
- Graph databaseGraph = metrics.createGraph("Database Engine");
-
- databaseGraph.addPlotter(new Plotter(getFeDatabase().getName()) {
- public int getValue() {
- return 1;
- }
- });
-
- Graph defaultHoldings = metrics.createGraph("Default Holdings");
-
- defaultHoldings.addPlotter(new Plotter(getAPI().getDefaultHoldings() + "") {
- public int getValue() {
- return 1;
- }
- });
-
- Graph maxHoldings = metrics.createGraph("Max Holdings");
-
- String maxHolding = getAPI().getMaxHoldings() + "";
-
- if (getAPI().getMaxHoldings() == -1) {
- maxHolding = "Unlimited";
- }
-
- maxHoldings.addPlotter(new Plotter(maxHolding) {
- public int getValue() {
- return 1;
- }
- });
-
- metrics.start();
- } catch (IOException e) {
-
- }
- }
-
- private void setupVault() {
- Plugin vault = getServer().getPluginManager().getPlugin("Vault");
-
- if (vault == null) {
- return;
- }
-
- getServer().getServicesManager().register(Economy.class, new VaultHandler(this), this, ServicePriority.Highest);
- }
-}
diff --git a/src/org/melonbrew/fe/FeCommand.java b/src/org/melonbrew/fe/FeCommand.java
deleted file mode 100644
index 3bd15e6..0000000
--- a/src/org/melonbrew/fe/FeCommand.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.melonbrew.fe;
-
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.melonbrew.fe.command.CommandType;
-import org.melonbrew.fe.command.SubCommand;
-import org.melonbrew.fe.command.commands.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class FeCommand implements CommandExecutor {
- private final List commands;
-
- public FeCommand(Fe plugin) {
- commands = new ArrayList();
-
- commands.add(new BalanceCommand(plugin));
- commands.add(new SendCommand(plugin));
- commands.add(new TopCommand(plugin));
- commands.add(new HelpCommand(plugin, this));
- commands.add(new CreateCommand(plugin));
- commands.add(new RemoveCommand(plugin));
- commands.add(new SetCommand(plugin));
- commands.add(new GrantCommand(plugin));
- commands.add(new DeductCommand(plugin));
- commands.add(new CleanCommand(plugin));
- commands.add(new ReloadCommand(plugin));
- }
-
- public List getCommands() {
- return commands;
- }
-
- private SubCommand getCommand(String name) {
- for (SubCommand command : commands) {
- String[] aliases = command.getName().split(",");
-
- for (String alias : aliases) {
- if (alias.equalsIgnoreCase(name)) {
- return command;
- }
- }
- }
-
- return null;
- }
-
- private String[] merge(String[]... arrays) {
- int arraySize = 0;
-
- for (String[] array : arrays) {
- arraySize += array.length;
- }
-
- String[] result = new String[arraySize];
-
- int j = 0;
-
- for (String[] array : arrays) {
- for (String string : array) {
- result[j++] = string;
- }
- }
-
- return result;
- }
-
- private void sendDefaultCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
- String command = "balance";
-
- if (!(sender instanceof Player) && args.length < 1) {
- command = "help";
- }
-
- onCommand(sender, cmd, commandLabel, merge(new String[]{command}, args));
- }
-
- public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
- if (args.length < 1) {
- sendDefaultCommand(sender, cmd, commandLabel, args);
-
- return true;
- }
-
- SubCommand command = getCommand(args[0]);
-
- if (command == null) {
- sendDefaultCommand(sender, cmd, commandLabel, args);
-
- return true;
- }
-
- boolean console = !(sender instanceof Player);
-
- if (console && args.length < 2 && command.getCommandType() == CommandType.CONSOLE_WITH_ARGUMENTS) {
- Phrase.COMMAND_NEEDS_ARGUMENTS.sendWithPrefix(sender);
-
- return true;
- }
-
- if (console && command.getCommandType() == CommandType.PLAYER) {
- Phrase.COMMAND_NOT_CONSOLE.sendWithPrefix(sender, commandLabel);
-
- return true;
- }
-
- if (!sender.hasPermission(command.getPermission())) {
- Phrase.NO_PERMISSION_FOR_COMMAND.sendWithPrefix(sender);
-
- return true;
- }
-
- String[] realArgs = new String[args.length - 1];
-
- for (int i = 1; i < args.length; i++) {
- realArgs[i - 1] = args[i];
- }
-
- if (!command.onCommand(sender, cmd, commandLabel, realArgs)) {
- Phrase.TRY_COMMAND.sendWithPrefix(sender, parse(commandLabel, command));
- }
-
- return true;
- }
-
- public String parse(String label, SubCommand command) {
- String commandColor = Phrase.PRIMARY_COLOR.parse();
-
- String operatorsColor = Phrase.PRIMARY_COLOR.parse();
-
- String argumentColor = Phrase.ARGUMENT_COLOR.parse();
-
- StringBuilder builder = new StringBuilder(commandColor).append("/").append(label);
-
- if (!command.getFirstName().equalsIgnoreCase("balance")) {
- builder.append(" ").append(command.getFirstName()).append(" ");
- }
-
- String[] split = command.getUsage().split(" ");
-
- if (split[0].equalsIgnoreCase(command.getFirstName())) {
- for (int i = 1; i < split.length; i++) {
- builder.append(parseArg(split[i], operatorsColor, argumentColor)).append(" ");
- }
-
- builder.deleteCharAt(builder.length() - 1);
- } else {
- builder.append(" ").append(parseArg(split[0], operatorsColor, argumentColor)).append(" ");
-
- builder.deleteCharAt(builder.length() - 1);
- }
-
- return builder.toString();
- }
-
- private String parseArg(String argument, String operatorsColor, String argumentColor) {
- String operator = argument.substring(0, 1);
-
- argument = argument.substring(1, argument.length());
-
- String reverse;
-
- if (operator.equals("[")) {
- reverse = "]";
- } else {
- reverse = ")";
- }
-
- argument = argument.substring(0, argument.length() - 1);
-
- argument = operatorsColor + operator + argumentColor + argument + operatorsColor + reverse;
-
- return argument;
- }
-}
diff --git a/src/org/melonbrew/fe/Metrics.java b/src/org/melonbrew/fe/Metrics.java
deleted file mode 100644
index 3d3a72d..0000000
--- a/src/org/melonbrew/fe/Metrics.java
+++ /dev/null
@@ -1,748 +0,0 @@
-/*
- * Copyright 2011-2013 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 org.melonbrew.fe;
-
-import org.bukkit.Bukkit;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.plugin.PluginDescriptionFile;
-import org.bukkit.scheduler.BukkitTask;
-
-import java.io.*;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLEncoder;
-import java.util.*;
-import java.util.logging.Level;
-import java.util.zip.GZIPOutputStream;
-
-public class Metrics {
-
- /**
- * The current revision number
- */
- private final static int REVISION = 7;
-
- /**
- * The base url of the metrics domain
- */
- private static final String BASE_URL = "http://report.mcstats.org";
-
- /**
- * The url used to report a server's status
- */
- private static final String REPORT_URL = "/plugin/%s";
-
- /**
- * Interval of time to ping (in minutes)
- */
- private static final int PING_INTERVAL = 15;
-
- /**
- * The plugin this metrics submits for
- */
- private final Plugin plugin;
-
- /**
- * All of the custom graphs to submit to metrics
- */
- private final Set graphs = Collections.synchronizedSet(new HashSet());
-
- /**
- * The plugin configuration file
- */
- private final YamlConfiguration configuration;
-
- /**
- * The plugin configuration file
- */
- private final File configurationFile;
-
- /**
- * Unique server id
- */
- private final String guid;
-
- /**
- * Debug mode
- */
- private final boolean debug;
-
- /**
- * Lock for synchronization
- */
- private final Object optOutLock = new Object();
-
- /**
- * The scheduled task
- */
- private volatile BukkitTask task = null;
-
- public Metrics(final Plugin plugin) throws IOException {
- if (plugin == null) {
- throw new IllegalArgumentException("Plugin cannot be null");
- }
-
- this.plugin = plugin;
-
- // load the config
- configurationFile = getConfigFile();
- configuration = YamlConfiguration.loadConfiguration(configurationFile);
-
- // add some defaults
- configuration.addDefault("opt-out", false);
- configuration.addDefault("guid", UUID.randomUUID().toString());
- configuration.addDefault("debug", false);
-
- // Do we need to create the file?
- if (configuration.get("guid", null) == null) {
- configuration.options().header("http://mcstats.org").copyDefaults(true);
- configuration.save(configurationFile);
- }
-
- // Load the guid then
- guid = configuration.getString("guid");
- debug = configuration.getBoolean("debug", false);
- }
-
- /**
- * GZip compress a string of bytes
- *
- * @param input
- * @return
- */
- public static byte[] gzip(String input) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- GZIPOutputStream gzos = null;
-
- try {
- gzos = new GZIPOutputStream(baos);
- gzos.write(input.getBytes("UTF-8"));
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (gzos != null) try {
- gzos.close();
- } catch (IOException ignore) {
- }
- }
-
- return baos.toByteArray();
- }
-
- /**
- * Appends a json encoded key/value pair to the given string builder.
- *
- * @param json
- * @param key
- * @param value
- * @throws UnsupportedEncodingException
- */
- private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
- boolean isValueNumeric = false;
-
- try {
- if (value.equals("0") || !value.endsWith("0")) {
- Double.parseDouble(value);
- isValueNumeric = true;
- }
- } catch (NumberFormatException e) {
- isValueNumeric = false;
- }
-
- if (json.charAt(json.length() - 1) != '{') {
- json.append(',');
- }
-
- json.append(escapeJSON(key));
- json.append(':');
-
- if (isValueNumeric) {
- json.append(value);
- } else {
- json.append(escapeJSON(value));
- }
- }
-
- /**
- * Escape a string to create a valid JSON string
- *
- * @param text
- * @return
- */
- private static String escapeJSON(String text) {
- StringBuilder builder = new StringBuilder();
-
- builder.append('"');
- for (int index = 0; index < text.length(); index++) {
- char chr = text.charAt(index);
-
- switch (chr) {
- case '"':
- case '\\':
- builder.append('\\');
- builder.append(chr);
- break;
- case '\b':
- builder.append("\\b");
- break;
- case '\t':
- builder.append("\\t");
- break;
- case '\n':
- builder.append("\\n");
- break;
- case '\r':
- builder.append("\\r");
- break;
- default:
- if (chr < ' ') {
- String t = "000" + Integer.toHexString(chr);
- builder.append("\\u" + t.substring(t.length() - 4));
- } else {
- builder.append(chr);
- }
- break;
- }
- }
- builder.append('"');
-
- return builder.toString();
- }
-
- /**
- * Encode text as UTF-8
- *
- * @param text the text to encode
- * @return the encoded text, as UTF-8
- */
- private static String urlEncode(final String text) throws UnsupportedEncodingException {
- return URLEncoder.encode(text, "UTF-8");
- }
-
- /**
- * Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics
- * website. Plotters can be added to the graph object returned.
- *
- * @param name The name of the graph
- * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
- */
- public Graph createGraph(final String name) {
- if (name == null) {
- throw new IllegalArgumentException("Graph name cannot be null");
- }
-
- // Construct the graph object
- final Graph graph = new Graph(name);
-
- // Now we can add our graph
- graphs.add(graph);
-
- // and return back
- return graph;
- }
-
- /**
- * Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend
- *
- * @param graph The name of the graph
- */
- public void addGraph(final Graph graph) {
- if (graph == null) {
- throw new IllegalArgumentException("Graph cannot be null");
- }
-
- graphs.add(graph);
- }
-
- /**
- * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the
- * initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200
- * ticks.
- *
- * @return True if statistics measuring is running, otherwise false.
- */
- public boolean start() {
- synchronized (optOutLock) {
- // Did we opt out?
- if (isOptOut()) {
- return false;
- }
-
- // Is metrics already running?
- if (task != null) {
- return true;
- }
-
- // Begin hitting the server with glorious data
- task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
-
- private boolean firstPost = true;
-
- public void run() {
- try {
- // This has to be synchronized or it can collide with the disable method.
- synchronized (optOutLock) {
- // Disable Task, if it is running and the server owner decided to opt-out
- if (isOptOut() && task != null) {
- task.cancel();
- task = null;
- // Tell all plotters to stop gathering information.
- for (Graph graph : graphs) {
- graph.onOptOut();
- }
- }
- }
-
- // We use the inverse of firstPost because if it is the first time we are posting,
- // it is not a interval ping, so it evaluates to FALSE
- // Each time thereafter it will evaluate to TRUE, i.e PING!
- postPlugin(!firstPost);
-
- // After the first post we set firstPost to false
- // Each post thereafter will be a ping
- firstPost = false;
- } catch (IOException e) {
- if (debug) {
- Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
- }
- }
- }
- }, 0, PING_INTERVAL * 1200);
-
- return true;
- }
- }
-
- /**
- * Has the server owner denied plugin metrics?
- *
- * @return true if metrics should be opted out of it
- */
- public boolean isOptOut() {
- synchronized (optOutLock) {
- try {
- // Reload the metrics file
- configuration.load(getConfigFile());
- } catch (IOException ex) {
- if (debug) {
- Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
- }
- return true;
- } catch (InvalidConfigurationException ex) {
- if (debug) {
- Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
- }
- return true;
- }
- return configuration.getBoolean("opt-out", false);
- }
- }
-
- /**
- * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
- *
- * @throws java.io.IOException
- */
- public void enable() throws IOException {
- // This has to be synchronized or it can collide with the check in the task.
- synchronized (optOutLock) {
- // Check if the server owner has already set opt-out, if not, set it.
- if (isOptOut()) {
- configuration.set("opt-out", false);
- configuration.save(configurationFile);
- }
-
- // Enable Task, if it is not running
- if (task == null) {
- start();
- }
- }
- }
-
- /**
- * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
- *
- * @throws java.io.IOException
- */
- public void disable() throws IOException {
- // This has to be synchronized or it can collide with the check in the task.
- synchronized (optOutLock) {
- // Check if the server owner has already set opt-out, if not, set it.
- if (!isOptOut()) {
- configuration.set("opt-out", true);
- configuration.save(configurationFile);
- }
-
- // Disable Task, if it is running
- if (task != null) {
- task.cancel();
- task = null;
- }
- }
- }
-
- /**
- * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status
- *
- * @return the File object for the config file
- */
- public File getConfigFile() {
- // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
- // is to abuse the plugin object we already have
- // plugin.getDataFolder() => base/plugins/PluginA/
- // pluginsFolder => base/plugins/
- // The base is not necessarily relative to the startup directory.
- File pluginsFolder = plugin.getDataFolder().getParentFile();
-
- // return => base/plugins/PluginMetrics/config.yml
- return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
- }
-
- /**
- * Generic method that posts a plugin to the metrics website
- */
- private void postPlugin(final boolean isPing) throws IOException {
- // Server software specific section
- PluginDescriptionFile description = plugin.getDescription();
- String pluginName = description.getName();
- boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
- String pluginVersion = description.getVersion();
- String serverVersion = Bukkit.getVersion();
- int playersOnline = Bukkit.getServer().getOnlinePlayers().length;
-
- // END server software specific section -- all code below does not use any code outside of this class / Java
-
- // Construct the post data
- StringBuilder json = new StringBuilder(1024);
- json.append('{');
-
- // The plugin's description file containg all of the plugin data such as name, version, author, etc
- appendJSONPair(json, "guid", guid);
- appendJSONPair(json, "plugin_version", pluginVersion);
- appendJSONPair(json, "server_version", serverVersion);
- appendJSONPair(json, "players_online", Integer.toString(playersOnline));
-
- // New data as of R6
- String osname = System.getProperty("os.name");
- String osarch = System.getProperty("os.arch");
- String osversion = System.getProperty("os.version");
- String java_version = System.getProperty("java.version");
- int coreCount = Runtime.getRuntime().availableProcessors();
-
- // normalize os arch .. amd64 -> x86_64
- if (osarch.equals("amd64")) {
- osarch = "x86_64";
- }
-
- appendJSONPair(json, "osname", osname);
- appendJSONPair(json, "osarch", osarch);
- appendJSONPair(json, "osversion", osversion);
- appendJSONPair(json, "cores", Integer.toString(coreCount));
- appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
- appendJSONPair(json, "java_version", java_version);
-
- // If we're pinging, append it
- if (isPing) {
- appendJSONPair(json, "ping", "1");
- }
-
- if (graphs.size() > 0) {
- synchronized (graphs) {
- json.append(',');
- json.append('"');
- json.append("graphs");
- json.append('"');
- json.append(':');
- json.append('{');
-
- boolean firstGraph = true;
-
- final Iterator iter = graphs.iterator();
-
- while (iter.hasNext()) {
- Graph graph = iter.next();
-
- StringBuilder graphJson = new StringBuilder();
- graphJson.append('{');
-
- for (Plotter plotter : graph.getPlotters()) {
- appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue()));
- }
-
- graphJson.append('}');
-
- if (!firstGraph) {
- json.append(',');
- }
-
- json.append(escapeJSON(graph.getName()));
- json.append(':');
- json.append(graphJson);
-
- firstGraph = false;
- }
-
- json.append('}');
- }
- }
-
- // close json
- json.append('}');
-
- // Create the url
- URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
-
- // Connect to the website
- URLConnection connection;
-
- // Mineshafter creates a socks proxy, so we can safely bypass it
- // It does not reroute POST requests so we need to go around it
- if (isMineshafterPresent()) {
- connection = url.openConnection(Proxy.NO_PROXY);
- } else {
- connection = url.openConnection();
- }
-
-
- byte[] uncompressed = json.toString().getBytes();
- byte[] compressed = gzip(json.toString());
-
- // Headers
- connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
- connection.addRequestProperty("Content-Type", "application/json");
- connection.addRequestProperty("Content-Encoding", "gzip");
- connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
- connection.addRequestProperty("Accept", "application/json");
- connection.addRequestProperty("Connection", "close");
-
- connection.setDoOutput(true);
-
- if (debug) {
- System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length);
- }
-
- // Write the data
- OutputStream os = connection.getOutputStream();
- os.write(compressed);
- os.flush();
-
- // Now read the response
- final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- String response = reader.readLine();
-
- // close resources
- os.close();
- reader.close();
-
- if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
- if (response == null) {
- response = "null";
- } else if (response.startsWith("7")) {
- response = response.substring(response.startsWith("7,") ? 2 : 1);
- }
-
- throw new IOException(response);
- } else {
- // Is this the first update this hour?
- if (response.equals("1") || response.contains("This is your first update this hour")) {
- synchronized (graphs) {
- final Iterator iter = graphs.iterator();
-
- while (iter.hasNext()) {
- final Graph graph = iter.next();
-
- for (Plotter plotter : graph.getPlotters()) {
- plotter.reset();
- }
- }
- }
- }
- }
- }
-
- /**
- * Check if mineshafter is present. If it is, we need to bypass it to send POST requests
- *
- * @return true if mineshafter is installed on the server
- */
- private boolean isMineshafterPresent() {
- try {
- Class.forName("mineshafter.MineServer");
- return true;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * Represents a custom graph on the website
- */
- public static class Graph {
-
- /**
- * The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
- * rejected
- */
- private final String name;
-
- /**
- * The set of plotters that are contained within this graph
- */
- private final Set plotters = new LinkedHashSet();
-
- private Graph(final String name) {
- this.name = name;
- }
-
- /**
- * Gets the graph's name
- *
- * @return the Graph's name
- */
- public String getName() {
- return name;
- }
-
- /**
- * Add a plotter to the graph, which will be used to plot entries
- *
- * @param plotter the plotter to add to the graph
- */
- public void addPlotter(final Plotter plotter) {
- plotters.add(plotter);
- }
-
- /**
- * Remove a plotter from the graph
- *
- * @param plotter the plotter to remove from the graph
- */
- public void removePlotter(final Plotter plotter) {
- plotters.remove(plotter);
- }
-
- /**
- * Gets an unmodifiable set of the plotter objects in the graph
- *
- * @return an unmodifiable {@link java.util.Set} of the plotter objects
- */
- public Set getPlotters() {
- return Collections.unmodifiableSet(plotters);
- }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
-
- @Override
- public boolean equals(final Object object) {
- if (!(object instanceof Graph)) {
- return false;
- }
-
- final Graph graph = (Graph) object;
- return graph.name.equals(name);
- }
-
- /**
- * Called when the server owner decides to opt-out of BukkitMetrics while the server is running.
- */
- protected void onOptOut() {
- }
- }
-
- /**
- * Interface used to collect custom data for a plugin
- */
- public static abstract class Plotter {
-
- /**
- * The plot's name
- */
- private final String name;
-
- /**
- * Construct a plotter with the default plot name
- */
- public Plotter() {
- this("Default");
- }
-
- /**
- * Construct a plotter with a specific plot name
- *
- * @param name the name of the plotter to use, which will show up on the website
- */
- public Plotter(final String name) {
- this.name = name;
- }
-
- /**
- * Get the current value for the plotted point. Since this function defers to an external function it may or may
- * not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called
- * from any thread so care should be taken when accessing resources that need to be synchronized.
- *
- * @return the current value for the point to be plotted.
- */
- public abstract int getValue();
-
- /**
- * Get the column name for the plotted point
- *
- * @return the plotted point's column name
- */
- public String getColumnName() {
- return name;
- }
-
- /**
- * Called after the website graphs have been updated
- */
- public void reset() {
- }
-
- @Override
- public int hashCode() {
- return getColumnName().hashCode();
- }
-
- @Override
- public boolean equals(final Object object) {
- if (!(object instanceof Plotter)) {
- return false;
- }
-
- final Plotter plotter = (Plotter) object;
- return plotter.name.equals(name) && plotter.getValue() == getValue();
- }
- }
-}
\ No newline at end of file
diff --git a/src/org/melonbrew/fe/Phrase.java b/src/org/melonbrew/fe/Phrase.java
deleted file mode 100644
index 8de9137..0000000
--- a/src/org/melonbrew/fe/Phrase.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package org.melonbrew.fe;
-
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-
-public enum Phrase {
- DATABASE_TYPE_DOES_NOT_EXIST("That database type doesn't exist."),
- DATABASE_FAILURE_DISABLE("Database initialization has failed, disabling Fe."),
- COMMAND_NEEDS_ARGUMENTS("That command needs arguments."),
- COMMAND_NOT_CONSOLE("The command '$1' cannot be used in the console."),
- NO_PERMISSION_FOR_COMMAND("Sorry, you do not have permission to use that command."),
- ACCOUNT_HAS("$1 has $2"),
- YOU_HAVE("You have $1"),
- HELP("Fe Help"),
- HELP_ARGUMENTS("$1 Required, $2 Optional"),
- RICH("Rich List"),
- STARTING_UUID_CONVERSION("Starting UUID conversion."),
- UUID_CONVERSION_FAILED("UUID conversion failed, disabling Fe!"),
- UUID_CONVERSION_SUCCEEDED("UUID conversion has succeeded!"),
- CONFIG_RELOADED("The config has been reloaded."),
- NOT_ENOUGH_MONEY("You don't have enough money."),
- ACCOUNT_DOES_NOT_EXIST("Sorry, that account does not exist."),
- YOUR_ACCOUNT_DOES_NOT_EXIST("You don't have an account."),
- ACCOUNT_EXISTS("That account already exists."),
- ACCOUNT_CREATED("An account for $1 has been created."),
- ACCOUNT_REMOVED("An account for $1 has been removed."),
- MONEY_RECEIVE("You've received $1 from $2."),
- MONEY_SENT("You've sent $1 to $2"),
- MAX_BALANCE_REACHED("$1 has reached the maximum balance."),
- PLAYER_SET_MONEY("You've set $1's balance to $2."),
- PLAYER_GRANT_MONEY("You've granted $1 to $2."),
- PLAYER_GRANTED_MONEY("$2 granted you $1."),
- PLAYER_DEDUCT_MONEY("You've deducted $1 from $2."),
- PLAYER_DEDUCTED_MONEY("$2 deducted $1 from your account."),
- ACCOUNT_CREATED_GRANT("Created an account for $1 and granted it $2"),
- NO_ACCOUNTS_EXIST("No accounts exist."),
- NAME_TOO_LONG("Sorry that name is too long."),
- ACCOUNT_CLEANED("All accounts with the default balance have been removed."),
- TRY_COMMAND("Try $1"),
- FE_OUTDATED("Fe is outdated! The latest version is $1."),
- PRIMARY_COLOR(ChatColor.GOLD.toString()),
- SECONDARY_COLOR(ChatColor.GRAY.toString()),
- TERTIARY_COLOR(ChatColor.DARK_GRAY.toString()),
- ARGUMENT_COLOR(ChatColor.YELLOW.toString()),
- COMMAND_BALANCE("Checks your balance", true),
- COMMAND_SEND("Sends another player money", true),
- COMMAND_TOP("Checks the top 5 richest players", true),
- COMMAND_HELP("Gives you help", true),
- COMMAND_CREATE("Creates an account", true),
- COMMAND_REMOVE("Removes an account", true),
- COMMAND_SET("Set a player's balance", true),
- COMMAND_GRANT("Grants a player money", true),
- COMMAND_DEDUCT("Deducts money from a player", true),
- COMMAND_CLEAN("Cleans the accounts with default balance", true),
- COMMAND_RELOAD("Reloads the config", true);
-
- private static Fe plugin;
-
- private final String defaultMessage;
-
- private final boolean categorized;
-
- private String message;
-
- private Phrase(String defaultMessage) {
- this(defaultMessage, false);
- }
-
- private Phrase(String defaultMessage, boolean categorized) {
- this.defaultMessage = defaultMessage;
-
- this.categorized = categorized;
-
- message = defaultMessage + "";
- }
-
- public static void init(Fe instance) {
- plugin = instance;
- }
-
- private String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public void reset() {
- message = defaultMessage + "";
- }
-
- public String getConfigName() {
- String name = name();
-
- if (categorized) {
- name = name.replaceFirst("_", ".");
- }
-
- return name.toLowerCase();
- }
-
- public String parse(String... params) {
- String parsedMessage = getMessage();
-
- if (params != null) {
- for (int i = 0; i < params.length; i++) {
- parsedMessage = parsedMessage.replace("$" + (i + 1), params[i]);
- }
- }
-
- return parsedMessage;
- }
-
- public String parseWithoutSpaces(String... params) {
- return parse(params).replace(" ", "");
- }
-
- private String parseWithPrefix(String... params) {
- return plugin.getMessagePrefix().replace("$1", plugin.getConfig().getString("prefix")) + parse(params);
- }
-
- public void send(CommandSender sender, String... params) {
- sender.sendMessage(parse(params));
- }
-
- public void sendWithPrefix(CommandSender sender, String... params) {
- sender.sendMessage(parseWithPrefix(params));
- }
-}
\ No newline at end of file
diff --git a/src/org/melonbrew/fe/UUIDFetcher.java b/src/org/melonbrew/fe/UUIDFetcher.java
deleted file mode 100644
index 0b78769..0000000
--- a/src/org/melonbrew/fe/UUIDFetcher.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.melonbrew.fe;
-
-import com.google.common.collect.ImmutableList;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.json.simple.parser.JSONParser;
-
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.nio.ByteBuffer;
-import java.util.*;
-import java.util.concurrent.Callable;
-
-public class UUIDFetcher implements Callable