Add WG Hooks, Change Economy to support easy static useage, Add playerutils, fix ServerVersion, simplify commandmanager registration, prep work for updater

This commit is contained in:
jascotty2 2019-08-21 21:31:53 -05:00
parent 206baa86a8
commit 6790f0680a
20 changed files with 814 additions and 166 deletions

View File

@ -7,7 +7,7 @@ import org.json.simple.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class Plugin {
public class PluginInfo {
private JavaPlugin javaPlugin;
private int songodaId;
@ -18,7 +18,7 @@ public class Plugin {
private String marketplaceLink;
private JSONObject json;
public Plugin(JavaPlugin javaPlugin, int songodaId) {
public PluginInfo(JavaPlugin javaPlugin, int songodaId) {
this.javaPlugin = javaPlugin;
this.songodaId = songodaId;
}

View File

@ -25,14 +25,19 @@ public class SongodaCore {
private static String prefix = "[SongodaCore]";
private static int version = 1;
private static int updaterVersion = 1;
private static Set<Plugin> registeredPlugins = new HashSet<>();
private static Set<PluginInfo> registeredPlugins = new HashSet<>();
private static SongodaCore INSTANCE;
private static JavaPlugin hijackedPlugin;
public static void registerPlugin(JavaPlugin plugin, int pluginID) {
}
public SongodaCore(JavaPlugin javaPlugin) {
hijackedPlugin = javaPlugin;
Bukkit.getPluginManager().registerEvents(new LoginListener(this), hijackedPlugin);
@ -40,11 +45,11 @@ public class SongodaCore {
new CommandManager(this);
}
private void update(Plugin plugin) {
private void update(PluginInfo plugin) {
try {
URL url = new URL("http://update.songoda.com/index.php?plugin=" + plugin.getSongodaId()
+ "&version=" + plugin.getJavaPlugin().getDescription().getVersion()
+ "&updaterVersion=" + version);
+ "&updaterVersion=" + updaterVersion);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(5000);
InputStream is = urlConnection.getInputStream();
@ -76,11 +81,11 @@ public class SongodaCore {
}
}
public static Plugin load(Plugin plugin) {
public static PluginInfo load(PluginInfo plugin) {
boolean found = false;
for (Class<?> clazz : Bukkit.getServicesManager().getKnownServices()) {
try {
clazz.getMethod("hook", Plugin.class).invoke(null, plugin);
clazz.getMethod("hook", PluginInfo.class).invoke(null, plugin);
found = true;
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) {
@ -94,18 +99,18 @@ public class SongodaCore {
return plugin;
}
public static void hook(Plugin plugin) {
public static void hook(PluginInfo plugin) {
System.out.println(getPrefix() + "Hooked " + plugin.getJavaPlugin().getName() + ".");
getInstance().update(plugin);
registeredPlugins.add(plugin);
}
public List<Plugin> getPlugins() {
public List<PluginInfo> getPlugins() {
return new ArrayList<>(registeredPlugins);
}
public static int getVersion() {
return version;
return updaterVersion;
}
public static String getPrefix() {

View File

@ -27,7 +27,7 @@ public class CommandManager implements CommandExecutor {
this.instance = instance;
this.tabManager = new TabManager(this);
registerCommandDynamically("songoda", this);
registerCommandDynamically("songoda", this, tabManager);
AbstractCommand commandSongoda = addCommand(new CommandSongoda());
addCommand(new CommandDiag(commandSongoda));
@ -81,7 +81,7 @@ public class CommandManager implements CommandExecutor {
return Collections.unmodifiableList(commands);
}
private void registerCommandDynamically(String command, CommandExecutor executor) {
public static void registerCommandDynamically(String command, CommandExecutor executor, TabManager tabManager) {
try {
// Retrieve the SimpleCommandMap from the server
Class<?> classCraftServer = Bukkit.getServer().getClass();

View File

@ -1,6 +1,6 @@
package com.songoda.core.command.commands;
import com.songoda.core.Plugin;
import com.songoda.core.PluginInfo;
import com.songoda.core.SongodaCore;
import com.songoda.core.command.AbstractCommand;
import org.bukkit.Bukkit;
@ -42,7 +42,7 @@ public class CommandDiag extends AbstractCommand {
sender.sendMessage("Songoda Diagnostics Information");
sender.sendMessage("");
sender.sendMessage("Plugins:");
for (Plugin plugin : instance.getPlugins()) {
for (PluginInfo plugin : instance.getPlugins()) {
sender.sendMessage(plugin.getJavaPlugin().getName()
+ " (" + plugin.getJavaPlugin().getDescription().getVersion() + ")");
}

View File

@ -1,6 +1,6 @@
package com.songoda.core.gui;
import com.songoda.core.Plugin;
import com.songoda.core.PluginInfo;
import com.songoda.core.SongodaCore;
import com.songoda.core.utils.gui.AbstractGUI;
import org.bukkit.Material;
@ -21,9 +21,9 @@ public class GUIOverview extends AbstractGUI {
@Override
protected void constructGUI() {
List<Plugin> plugins = update.getPlugins();
List<PluginInfo> plugins = update.getPlugins();
for (int i = 0; i < plugins.size(); i++) {
Plugin plugin = plugins.get(i);
PluginInfo plugin = plugins.get(i);
createButton(i + 9, Material.STONE, "&6" + plugin.getJavaPlugin().getName(),
"&7Latest Version: " + plugin.getLatestVersion(),

View File

@ -1,51 +1,36 @@
package com.songoda.core.library.commands;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public abstract class AbstractCommand {
private final boolean noConsole;
private AbstractCommand parent = null;
private boolean hasArgs = false;
private String command;
private List<String> subCommand = new ArrayList<>();
private final List<String> subCommand = new ArrayList<>();
protected AbstractCommand(AbstractCommand parent, boolean noConsole, String... command) {
if (parent != null) {
this.subCommand = Arrays.asList(command);
} else {
this.command = Arrays.asList(command).get(0);
}
this.parent = parent;
protected AbstractCommand(boolean noConsole, String... command) {
this.subCommand.addAll(Arrays.asList(command));
this.noConsole = noConsole;
}
protected AbstractCommand(boolean noConsole, boolean hasArgs, String... command) {
this.command = Arrays.asList(command).get(0);
this.subCommand.addAll(Arrays.asList(command));
this.hasArgs = hasArgs;
this.noConsole = noConsole;
}
public AbstractCommand getParent() {
return parent;
public final List<String> getCommands() {
return Collections.unmodifiableList(subCommand);
}
public String getCommand() {
return command;
}
public List<String> getSubCommand() {
return subCommand;
}
public void addSubCommand(String command) {
public final void addSubCommand(String command) {
subCommand.add(command);
}
@ -67,6 +52,6 @@ public abstract class AbstractCommand {
return noConsole;
}
public enum ReturnType {SUCCESS, FAILURE, SYNTAX_ERROR}
public static enum ReturnType {SUCCESS, FAILURE, SYNTAX_ERROR}
}

View File

@ -4,34 +4,64 @@ import com.songoda.core.utils.Methods;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class CommandManager implements CommandExecutor {
public class CommandManager implements CommandExecutor, TabCompleter {
private JavaPlugin plugin;
private TabManager tabManager;
private final JavaPlugin plugin;
private List<AbstractCommand> commands = new ArrayList<>();
private final HashMap<String, SimpleNestedCommand> commands = new HashMap<>();
private boolean allowLooseCommands = false;
public void load(JavaPlugin plugin) {
public CommandManager(JavaPlugin plugin) {
this.plugin = plugin;
this.tabManager = new TabManager(this);
for (AbstractCommand abstractCommand : commands) {
if (abstractCommand.getParent() != null) continue;
plugin.getCommand(abstractCommand.getCommand()).setTabCompleter(tabManager);
}
}
public AbstractCommand addCommand(AbstractCommand abstractCommand) {
commands.add(abstractCommand);
return abstractCommand;
public Set<String> getCommands() {
return Collections.unmodifiableSet(commands.keySet());
}
public List<String> getSubCommands(String command) {
SimpleNestedCommand nested = command == null ? null : commands.get(command.toLowerCase());
return nested == null ? Collections.EMPTY_LIST : nested.children.keySet().stream().collect(Collectors.toList());
}
public Set<AbstractCommand> getAllCommands() {
HashSet<AbstractCommand> all = new HashSet();
commands.values().stream()
.filter(c -> c.parent != null && !all.contains(c.parent))
.forEach(c -> {
all.add(c.parent);
c.children.values().stream()
.filter(s -> !all.contains(s))
.forEach(s -> all.add(s));
});
return all;
}
public SimpleNestedCommand addCommand(AbstractCommand abstractCommand) {
SimpleNestedCommand nested = new SimpleNestedCommand(abstractCommand);
abstractCommand.getCommands().stream().forEach(cmd -> {
commands.put(cmd.toLowerCase(), nested);
PluginCommand pcmd = plugin.getCommand(cmd);
if(pcmd != null) {
pcmd.setExecutor(this);
pcmd.setTabCompleter(this);
} else {
plugin.getLogger().warning("Failed to register command: /" + cmd);
}
});
return nested;
}
public CommandManager addCommands(AbstractCommand... abstractCommands) {
@ -45,36 +75,77 @@ public class CommandManager implements CommandExecutor {
return this;
}
public CommandManager setUseClosestCommand(boolean bool) {
allowLooseCommands = bool;
return this;
}
@Override
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) {
for (AbstractCommand abstractCommand : commands) {
if (abstractCommand.getCommand() != null && abstractCommand.getCommand().equalsIgnoreCase(command.getName().toLowerCase())) {
if (strings.length == 0 || abstractCommand.hasArgs()) {
processRequirements(abstractCommand, commandSender, strings);
public boolean onCommand(CommandSender commandSender, Command command, String label, String[] args) {
// grab the specific command that's being called
SimpleNestedCommand nested = commands.get(command.getName().toLowerCase());
if(nested != null) {
// check to see if we're trying to call a sub-command
if(args.length != 0 && !nested.children.isEmpty()) {
String subCmd = getSubCommand(nested, args);
if(subCmd != null) {
// we have a subcommand to use!
AbstractCommand sub = nested.children.get(subCmd);
// adjust the arguments to match - BREAKING!!
int i = subCmd.indexOf(' ') == -1 ? 1 : 2;
String[] newArgs = new String[args.length - i];
System.arraycopy(args, i, newArgs, 0, newArgs.length);
// now process the command
processRequirements(sub, commandSender, newArgs);
return true;
}
} else if (strings.length != 0 && abstractCommand.getParent() != null && abstractCommand.getParent().getCommand().equalsIgnoreCase(command.getName())) {
String cmd = strings[0];
String cmd2 = strings.length >= 2 ? String.join(" ", strings[0], strings[1]) : null;
for (String cmds : abstractCommand.getSubCommand()) {
if (cmd.equalsIgnoreCase(cmds) || (cmd2 != null && cmd2.equalsIgnoreCase(cmds))) {
processRequirements(abstractCommand, commandSender, strings);
return true;
}
}
}
// if we've gotten this far, then just use the command we have
if(nested.parent != null) {
processRequirements(nested.parent, commandSender, args);
return true;
}
}
commandSender.sendMessage(Methods.formatText("&7The command you entered does not exist or is spelt incorrectly."));
return true;
}
private void processRequirements(AbstractCommand command, CommandSender sender, String[] strings) {
private String getSubCommand(SimpleNestedCommand nested, String[] args) {
String cmd = args[0].toLowerCase();
if(nested.children.containsKey(cmd))
return cmd;
String match = null;
// support for two-argument subcommands
if(args.length >= 2 && nested.children.keySet().stream().anyMatch(k -> k.indexOf(' ') != -1)) {
cmd = String.join(" ", args[0], args[1]);
if(nested.children.containsKey(cmd))
return cmd;
}
// if we don't have a subcommand, should we search for one?
if (allowLooseCommands) {
// do a "closest match"
int count = 0;
for (String c : nested.children.keySet()) {
if (c.startsWith(cmd)) {
match = c;
if (++count > 1) {
// there can only be one!
match = null;
break;
}
}
}
}
return match;
}
private void processRequirements(AbstractCommand command, CommandSender sender, String[] args) {
if (!(sender instanceof Player) && command.isNoConsole()) {
sender.sendMessage("&cYou must be a player to use this command...");
return;
}
if (command.getPermissionNode() == null || sender.hasPermission(command.getPermissionNode())) {
AbstractCommand.ReturnType returnType = command.runCommand(sender, strings);
AbstractCommand.ReturnType returnType = command.runCommand(sender, args);
if (returnType == AbstractCommand.ReturnType.SYNTAX_ERROR) {
sender.sendMessage(Methods.formatText("&cInvalid Syntax!"));
sender.sendMessage(Methods.formatText("&7The valid syntax is: &6" + command.getSyntax() + "&7."));
@ -84,8 +155,54 @@ public class CommandManager implements CommandExecutor {
sender.sendMessage(Methods.formatText("&cYou do not have permission to do that."));
}
public List<AbstractCommand> getCommands() {
return Collections.unmodifiableList(commands);
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
// grab the specific command that's being called
SimpleNestedCommand nested = commands.get(command.getName().toLowerCase());
if(nested != null) {
if(args.length == 0) {
return nested.parent != null ? nested.parent.onTab(sender, args) : null;
}
// check for each sub-command that they have access to
final boolean op = sender.isOp();
final boolean console = !(sender instanceof Player);
if(args.length == 1) {
// suggest sub-commands that this user has access to
final String arg = args[0].toLowerCase();
return nested.children.entrySet().stream()
.filter(e -> !console || !e.getValue().isNoConsole())
.filter(e -> e.getKey().startsWith(arg))
.filter(e -> op || e.getValue().getPermissionNode() == null || sender.hasPermission(e.getValue().getPermissionNode()))
.map(e -> e.getKey())
.collect(Collectors.toList());
} else {
// more than one arg, let's check to see if we have a command here
String subCmd = getSubCommand(nested, args);
AbstractCommand sub;
if(subCmd != null && (sub = nested.children.get(subCmd)) != null
&& (!console || !sub.isNoConsole())
&& (op || sub.getPermissionNode() == null || sender.hasPermission(sub.getPermissionNode()))) {
// adjust the arguments to match - BREAKING!!
int i = subCmd.indexOf(' ') == -1 ? 1 : 2;
String[] newArgs = new String[args.length - i];
System.arraycopy(args, i, newArgs, 0, newArgs.length);
// we're good to go!
return fetchList(sub, newArgs, sender);
}
}
}
return Collections.EMPTY_LIST;
}
private List<String> fetchList(AbstractCommand abstractCommand, String[] args, CommandSender sender) {
List<String> list = abstractCommand.onTab(sender, args);
String str = args[args.length - 1];
if (list != null && str != null && str.length() >= 1) {
try {
list.removeIf(s -> !s.toLowerCase().startsWith(str.toLowerCase()));
} catch (UnsupportedOperationException ignored) {
}
}
return list;
}
}

View File

@ -0,0 +1,25 @@
package com.songoda.core.library.commands;
import java.util.HashMap;
import java.util.stream.Stream;
public class SimpleNestedCommand {
final AbstractCommand parent;
final HashMap<String, AbstractCommand> children = new HashMap();
protected SimpleNestedCommand(AbstractCommand parent) {
this.parent = parent;
}
public SimpleNestedCommand addSubCommand(AbstractCommand command) {
command.getCommands().stream().forEach(cmd -> children.put(cmd.toLowerCase(), command));
return this;
}
public SimpleNestedCommand addSubCommands(AbstractCommand... commands) {
Stream.of(commands).forEach(command -> command.getCommands().stream().forEach(cmd -> children.put(cmd.toLowerCase(), command)));
return this;
}
}

View File

@ -1,62 +0,0 @@
package com.songoda.core.library.commands;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import java.util.ArrayList;
import java.util.List;
public class TabManager implements TabCompleter {
private final CommandManager commandManager;
TabManager(CommandManager commandManager) {
this.commandManager = commandManager;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] strings) {
for (AbstractCommand abstractCommand : commandManager.getCommands()) {
if (command.getPermission() != null && !sender.hasPermission(command.getPermission())) continue;
if (abstractCommand.getCommand() != null && abstractCommand.getCommand().equalsIgnoreCase(command.getName()) && !abstractCommand.hasArgs()) {
if (strings.length != 1) continue;
List<String> subs = new ArrayList<>();
for (AbstractCommand ac : commandManager.getCommands()) {
if (ac.getSubCommand() == null) continue;
subs.addAll(ac.getSubCommand());
}
subs.removeIf(s -> !s.toLowerCase().startsWith(strings[0].toLowerCase()));
return subs;
} else if (strings.length != 0 && abstractCommand.getParent() != null && abstractCommand.getParent().getCommand().equalsIgnoreCase(command.getName())
|| abstractCommand.hasArgs() && abstractCommand.getCommand().equalsIgnoreCase(command.getName())) {
String[] args = abstractCommand.hasArgs() ? (String[]) ArrayUtils.add(strings, 0, command.getName()) : strings;
String cmd = abstractCommand.hasArgs() ? command.getName() : args[0];
String cmd2 = args.length >= 2 ? String.join(" ", args[0], args[1]) : null;
if (!abstractCommand.hasArgs()) {
for (String cmds : abstractCommand.getSubCommand()) {
if (cmd.equalsIgnoreCase(cmds) || (cmd2 != null && cmd2.equalsIgnoreCase(cmds))) {
return fetchList(abstractCommand, args, sender);
}
}
} else {
return fetchList(abstractCommand, args, sender);
}
}
}
return new ArrayList<>();
}
private List<String> fetchList(AbstractCommand abstractCommand, String[] args, CommandSender sender) {
List<String> list = abstractCommand.onTab(sender, args);
String str = args[args.length - 1];
if (list != null && str != null && str.length() >= 1) {
try {
list.removeIf(s -> !s.toLowerCase().startsWith(str.toLowerCase()));
} catch (UnsupportedOperationException ignored) {
}
}
return list;
}
}

View File

@ -0,0 +1,13 @@
package com.songoda.core.library.compatibility;
import org.bukkit.Bukkit;
/**
* TODO
*/
public enum ServerProject {
CRAFTBUKKIT, SPIGOT, PAPER;
private final static String serverPackage = Bukkit.getServer().getClass().getPackage().getName();
}

View File

@ -1,4 +1,4 @@
package com.songoda.core.library;
package com.songoda.core.library.compatibility;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.Bukkit;
@ -7,14 +7,18 @@ public enum ServerVersion {
UNKNOWN, V1_7, V1_8, V1_9, V1_10, V1_11, V1_12, V1_13, V1_14, V1_15, V1_16, V1_17, V1_18, V1_19, V1_20;
private final static String serverPackage = Bukkit.getServer().getClass().getPackage().getName().toUpperCase();
private static ServerVersion serverVersion = UNKNOWN;
static {
for (ServerVersion version : values())
if (Bukkit.getServer().getClass().getPackage().getName().toUpperCase().endsWith(version.name()))
if (serverPackage.startsWith(version.name()))
serverVersion = version;
}
public static String getServerVersionString() {
return serverPackage;
}
public static ServerVersion getServerVersion() {
return serverVersion;
}
@ -30,4 +34,8 @@ public enum ServerVersion {
public static boolean isServerVersionAtLeast(ServerVersion version) {
return serverVersion.ordinal() >= version.ordinal();
}
public static boolean isServerVersionBelow(ServerVersion version) {
return serverVersion.ordinal() < version.ordinal();
}
}

View File

@ -1,47 +1,172 @@
package com.songoda.core.library.economy;
import com.songoda.core.library.economy.economies.Economy;
import com.songoda.core.library.economy.economies.PlayerPointsEconomy;
import com.songoda.core.library.economy.economies.ReserveEconomy;
import com.songoda.core.library.economy.economies.VaultEconomy;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.PluginManager;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
public class EconomyManager {
private static Set<Economy> registeredEconomies = new HashSet<>();
private final static Map<EconomyType, Economy> registeredEconomies = new HashMap<>();
private static Economy defaultEcon = null;
/**
* Load all supported economy plugins. <br />
* Note: This method should be called in your plugin's onEnable() section
*/
public static void load() {
if (!registeredEconomies.isEmpty()) return;
PluginManager pluginManager = Bukkit.getPluginManager();
if (pluginManager.isPluginEnabled("Vault"))
registeredEconomies.add(new VaultEconomy());
if (pluginManager.isPluginEnabled("Reserve"))
registeredEconomies.add(new ReserveEconomy());
if (pluginManager.isPluginEnabled("PlayerPoints"))
registeredEconomies.add(new PlayerPointsEconomy());
for(EconomyType type : EconomyType.values()) {
if (pluginManager.isPluginEnabled(type.plugin)) {
Economy econ = type.getInstance();
registeredEconomies.put(type, econ);
if(defaultEcon == null)
defaultEcon = econ;
}
}
}
/**
* Set the default economy to a different plugin, if that plugin exists.
* If the plugin is not loaded or supported, the previously defined default will be used. <br />
* NOTE: using a default economy assumes that this library is shaded
* @param name name of the plugin to use
*/
public static void setPreferredEconomy(String name) {
Economy econ = getEconomy(name);
if(econ != null)
defaultEcon = econ;
}
/**
* Set the default economy to a different plugin, if that plugin exists.
* If the plugin is not loaded or supported, the previously defined default will be used. <br />
* NOTE: using a default economy assumes that this library is shaded
* @param economy plugin to use
*/
public static void setPreferredEconomy(EconomyType economy) {
Economy econ = getEconomy(economy);
if(econ != null)
defaultEcon = econ;
}
/**
* Try to grab the handler for this specific economy plugin.
* @param name plugin to use
* @return returns null if plugin is not enabled
*/
public static Economy getEconomy(String name) {
return registeredEconomies.stream().filter(economy -> economy.getName().equalsIgnoreCase(name.trim()))
.findFirst().orElse(null);
if(name == null) return null;
final String plugin = name.trim();
return registeredEconomies.get(registeredEconomies.keySet().stream()
.filter(type -> type.plugin.equalsIgnoreCase(plugin))
.findFirst().orElse(null));
}
/**
* Try to grab the handler for this specific economy plugin.
* @param economy plugin to use
* @return returns null if plugin is not enabled
*/
public static Economy getEconomy(EconomyType economy) {
return registeredEconomies.get(economy);
}
/**
* Grab the default economy plugin. <br />
* NOTE: using a default economy assumes that this library is shaded
* @return returns null if no plugin enabled
*/
public static Economy getEconomy() {
return defaultEcon;
}
/**
* Grab a list of all supported economy plugins.
* @return an immutable collection of the loaded economy handler instances
*/
public static Collection<Economy> getRegisteredEconomies() {
return Collections.unmodifiableCollection(registeredEconomies.values());
}
/**
* Check to see if a specific economy plugin is enabled.
* @param name plugin to check
* @return true if this economy plugin is supported and loaded
*/
public static boolean isEnabled(String name) {
return getEconomy(name) != null;
}
public static boolean isEnabled() {
return !registeredEconomies.isEmpty();
/**
* Check to see if a specific economy plugin is enabled.
* @param economy plugin to check
* @return true if this economy plugin is supported and loaded
*/
public static boolean isEnabled(EconomyType economy) {
return registeredEconomies.containsKey(economy);
}
public static Set<Economy> getRegisteredEconomies() {
return Collections.unmodifiableSet(registeredEconomies);
/**
* Check to see if there is a default economy loaded. <br />
* NOTE: using a default economy assumes that this library is shaded
* @return returns false if there are no supported economy plugins
*/
public static boolean isEnabled() {
return defaultEcon != null;
}
/**
* Get the name of the economy plugin being used. <br />
* NOTE: using a default economy assumes that this library is shaded
*
* @return
*/
public static String getName() {
return defaultEcon != null ? defaultEcon.getName() : null;
}
/**
* Check to see if a player has at least some balance available. <br />
* NOTE: using a default economy assumes that this library is shaded
*
* @param player player to check
* @param cost minimum amount this player should have
* @return true if this player can have this amount withdrawn
*/
public static boolean hasBalance(OfflinePlayer player, double cost) {
return defaultEcon != null ? defaultEcon.hasBalance(player, cost) : false;
}
/**
* Try to withdraw an amount from a player's balance. <br />
* NOTE: using a default economy assumes that this library is shaded
*
* @param player player to check
* @param cost amount to remove from this player
* @return true if the total amount was withdrawn successfully
*/
public static boolean withdrawBalance(OfflinePlayer player, double cost) {
return defaultEcon != null ? defaultEcon.withdrawBalance(player, cost) : false;
}
/**
* Try to add an amount to a player's balance. <br />
* NOTE: using a default economy assumes that this library is shaded
*
* @param player player to check
* @param amount amount to add to this player
* @return true if the total amount was added successfully
*/
public static boolean deposit(OfflinePlayer player, double amount) {
return defaultEcon != null ? defaultEcon.deposit(player, amount) : false;
}
}

View File

@ -0,0 +1,29 @@
package com.songoda.core.library.economy;
import com.songoda.core.library.economy.economies.*;
import java.util.logging.Level;
import org.bukkit.Bukkit;
public enum EconomyType {
VAULT("Vault", VaultEconomy.class),
PLAYER_POINTS("Reserve", ReserveEconomy.class),
RESERVE("PlayerPoints", PlayerPointsEconomy.class);
public final String plugin;
protected final Class managerClass;
private EconomyType(String plugin, Class managerClass) {
this.plugin = plugin;
this.managerClass = managerClass;
}
protected Economy getInstance() {
try {
return (Economy) managerClass.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
Bukkit.getLogger().log(Level.SEVERE, "Unexpected Error while creating a new Economy Manager for " + name(), ex);
}
return null;
}
}

View File

@ -4,11 +4,37 @@ import org.bukkit.OfflinePlayer;
public interface Economy {
/**
* Get the name of the economy plugin being used
*
* @return
*/
String getName();
/**
* Check to see if a player has at least some balance available
*
* @param player player to check
* @param cost minimum amount this player should have
* @return true if this player can have this amount withdrawn
*/
boolean hasBalance(OfflinePlayer player, double cost);
/**
* Try to withdraw an amount from a player's balance
*
* @param player player to check
* @param cost amount to remove from this player
* @return true if the total amount was withdrawn successfully
*/
boolean withdrawBalance(OfflinePlayer player, double cost);
/**
* Try to add an amount to a player's balance
*
* @param player player to check
* @param amount amount to add to this player
* @return true if the total amount was added successfully
*/
boolean deposit(OfflinePlayer player, double amount);
}

View File

@ -0,0 +1,289 @@
/**
* Hooks for adding a custom WorldGuard flag
*
* Note: Hooks must be added before WG loads!
*/
package com.songoda.core.library.hooks;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.stream.Stream;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
public class WorldGuardHook {
static Boolean wgPlugin = null;
static Object worldGuardPlugin;
static boolean legacy = false;
static boolean hooksInstalled = false;
static Map<String, Object> flags = new HashMap();
/**
* Attempt to register a worldGuard flag (ALLOW/DENY)
* @param flag
* @param state
*/
public static void addHook(String flag, boolean state) {
if (wgPlugin == null && (wgPlugin = (worldGuardPlugin = Bukkit.getPluginManager().getPlugin("WorldGuard")) != null)) {
try {
// if this class exists, we're on an older version
Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
legacy = true;
} catch (ClassNotFoundException ex) {
}
}
if (!wgPlugin) return;
if (legacy) {
addLegacyHook(flag, state);
return;
}
StateFlag addFlag = new StateFlag(flag, state);
try {
WorldGuard.getInstance().getFlagRegistry().register(addFlag);
flags.put(flag, addFlag);
} catch (Exception ex) {
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add flag {0} to WorldGuard", addFlag.getName());
Flag wgFlag = (StateFlag) WorldGuard.getInstance().getFlagRegistry().get(addFlag.getName());
if (wgFlag == null) {
wgPlugin = false;
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not hook WorldGuard");
} else {
flags.put(flag, wgFlag);
Bukkit.getServer().getLogger().log(Level.WARNING, "Loaded existing {1} {0}", new Object[] {wgFlag.getName(), wgFlag.getClass().getSimpleName()});
}
}
}
// reflection to add hooks
private static void addLegacyHook(String flag, boolean state) {
try {
// 6.0 has the same classpath for StateFlag as the current version does
// does this flag exist already?
Class defaultFlagClazz = Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
Field flagField = defaultFlagClazz.getField("flagsList");
Flag<?>[] flagsOld = (Flag<?>[]) flagField.get(null);
Flag wgFlag = Stream.of(flagsOld)
.filter(f -> ((Flag<?>)f).getName().equalsIgnoreCase(flag))
.findFirst().orElse(null);
if (wgFlag != null) {
// we already have one
flags.put(flag, wgFlag);
Bukkit.getServer().getLogger().log(Level.WARNING, "Loaded existing {1} {0}", new Object[] {wgFlag.getName(), wgFlag.getClass().getSimpleName()});
return;
}
// if not, we need to add one
wgFlag = new StateFlag(flag, state);
// we need to sneak our flag into the array
// make a copy first
Flag<?>[] flagsNew = new Flag<?>[flagsOld.length + 1];
System.arraycopy(flagsOld, 0, flagsNew, 0, flagsOld.length);
// add ours
flagsNew[flagsNew.length - 1] = wgFlag;
// and put the new list into place
setStaticField(flagField, flagsNew);
// register this flag in the registry
Object flagRegistry = getPrivateField(worldGuardPlugin.getClass(), worldGuardPlugin, "flagRegistry");
Class simpleFlagRegistryClazz = Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
Method registerSimpleFlagRegistry = simpleFlagRegistryClazz.getDeclaredMethod("register", Flag.class);
registerSimpleFlagRegistry.invoke(flagRegistry, wgFlag);
// all good!
flags.put(flag, wgFlag);
} catch (Exception ex) {
//Bukkit.getServer().getLogger().log(Level.WARNING, "Failed to set legacy WorldGuard Flags", ex);
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add flag {0} to WorldGuard", flag);
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not hook WorldGuard");
}
}
private static Object getPrivateField(Class<?> c, Object handle, String fieldName) throws Exception {
Field field = c.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(handle);
}
private static void setStaticField(Field field, Object value) throws Exception {
field.setAccessible(true);
Field modifier = Field.class.getDeclaredField("modifiers");
modifier.setAccessible(true);
modifier.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, value);
}
public static boolean isEnabled() {
return wgPlugin != null && wgPlugin;
}
/**
* Checks this location to see what this flag is set to
* @param l location to check
* @param flag ALLOW/DENY flag to check
* @return flag state, or null if undefined
*/
public static Boolean getBooleanFlag(Location l, String flag) {
if (wgPlugin == null || !wgPlugin) return null;
Object flagObj = flags.get(flag);
// There's a different way to get this in the old version
if (legacy)
return flagObj == null ? null : getBooleanFlagLegacy(l, flagObj);
// for convinience, we can load a flag if we don't know it
if (flagObj == null && !legacy)
flags.put(flag, flagObj = WorldGuard.getInstance().getFlagRegistry().get(flag));
// so, what's up?
if (flagObj instanceof StateFlag) {
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery query = container.createQuery();
com.sk89q.worldedit.util.Location loc = BukkitAdapter.adapt(l);
return query.testState(loc, (RegionAssociable) null, (StateFlag) flagObj);
}
return null;
}
/**
* Query all regions that are in or intersect this chunk
* @param c chunk to check for regions in
* @param flag ALLOW/DENY flag to check
* @return flag state, or null if undefined
*/
public static Boolean getBooleanFlag(Chunk c, String flag) {
if (wgPlugin == null || !wgPlugin) return null;
Object flagObj = flags.get(flag);
// There's a different way to get this in the old version
if (legacy)
return flagObj == null ? null : getBooleanFlagLegacy(c, flagObj);
// for convinience, we can load a flag if we don't know it
if (flagObj == null)
flags.put(flag, flagObj = WorldGuard.getInstance().getFlagRegistry().get(flag));
// so, what's up?
if (flagObj instanceof StateFlag) {
RegionManager worldManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(c.getWorld()));
if (worldManager == null)
return null;
ProtectedCuboidRegion chunkRegion = new ProtectedCuboidRegion("__TEST__",
BlockVector3.at(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
BlockVector3.at((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
ApplicableRegionSet set = worldManager.getApplicableRegions(chunkRegion);
State result = set.queryState((RegionAssociable) null, (StateFlag) flagObj);
if (result == null && set.size() == 0)
return null;
return result == State.ALLOW;
}
return null;
}
static Method legacy_getRegionManager = null;
static Method legacy_getApplicableRegions_Region = null;
static Method legacy_getApplicableRegions_Location = null;
static Constructor legacy_newProtectedCuboidRegion;
static Class legacy_blockVectorClazz;
static Constructor legacy_newblockVector;
private static Boolean getBooleanFlagLegacy(Location l, Object flag) {
try {
// cache reflection methods
if (legacy_getRegionManager == null) {
legacy_getRegionManager = worldGuardPlugin.getClass()
.getDeclaredMethod("getRegionManager", org.bukkit.World.class);
legacy_getApplicableRegions_Region = RegionManager.class.getDeclaredMethod("getApplicableRegions",
Class.forName("com.sk89q.worldguard.protection.regions.ProtectedRegion"));
legacy_getApplicableRegions_Location = RegionManager.class.getDeclaredMethod("getApplicableRegions",
Location.class);
legacy_blockVectorClazz = Class.forName("com.sk89q.worldedit.BlockVector");
legacy_newblockVector = legacy_blockVectorClazz.getConstructor(int.class, int.class, int.class);
legacy_newProtectedCuboidRegion = Class.forName("com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion")
.getConstructor(String.class, legacy_blockVectorClazz, legacy_blockVectorClazz);
}
// grab the applicable manager for this world
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, l.getWorld());
if (worldManager == null)
return null;
// now look for any intersecting regions
ApplicableRegionSet set = (ApplicableRegionSet) legacy_getApplicableRegions_Region.invoke(worldManager, l);
// so what's the verdict?
State result = set.queryState((RegionAssociable) null, (StateFlag) flag);
if (result == null && set.size() == 0)
return null;
return result == State.ALLOW;
} catch (Exception ex) {
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
}
return null;
}
private static Boolean getBooleanFlagLegacy(Chunk c, Object flag) {
// ApplicableRegionSet and RegionManager have the same classpath as the current version
// ProtectedCuboidRegion uses a different constructor, though
try {
// cache reflection methods
if (legacy_getRegionManager == null) {
legacy_getRegionManager = worldGuardPlugin.getClass()
.getDeclaredMethod("getRegionManager", org.bukkit.World.class);
legacy_getApplicableRegions_Region = RegionManager.class.getDeclaredMethod("getApplicableRegions",
Class.forName("com.sk89q.worldguard.protection.regions.ProtectedRegion"));
legacy_getApplicableRegions_Location = RegionManager.class.getDeclaredMethod("getApplicableRegions",
Location.class);
legacy_blockVectorClazz = Class.forName("com.sk89q.worldedit.BlockVector");
legacy_newblockVector = legacy_blockVectorClazz.getConstructor(int.class, int.class, int.class);
legacy_newProtectedCuboidRegion = Class.forName("com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion")
.getConstructor(String.class, legacy_blockVectorClazz, legacy_blockVectorClazz);
}
// grab the applicable manager for this world
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, c.getWorld());
if (worldManager == null)
return null;
// Create a legacy ProtectedCuboidRegion
Object chunkRegion = legacy_newProtectedCuboidRegion.newInstance("__TEST__",
legacy_newblockVector.newInstance(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
legacy_newblockVector.newInstance((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
// now look for any intersecting regions
ApplicableRegionSet set = (ApplicableRegionSet) legacy_getApplicableRegions_Region.invoke(worldManager, chunkRegion);
// so what's the verdict?
State result = set.queryState((RegionAssociable) null, (StateFlag) flag);
if (result == null && set.size() == 0)
return null;
return result == State.ALLOW;
} catch (Exception ex) {
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
}
return null;
}
}

View File

@ -1,6 +1,6 @@
package com.songoda.core.listeners;
import com.songoda.core.Plugin;
import com.songoda.core.PluginInfo;
import com.songoda.core.SongodaCore;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
@ -18,7 +18,7 @@ public class LoginListener implements Listener {
@EventHandler
public void onLogin(PlayerLoginEvent event) {
if (!event.getPlayer().isOp()) return;
for (Plugin plugin : instance.getPlugins()) {
for (PluginInfo plugin : instance.getPlugins()) {
if (plugin.getNotification() != null)
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin.getJavaPlugin(), () ->
event.getPlayer().sendMessage("[" + plugin.getJavaPlugin().getName() + "] " + plugin.getNotification()), 10L);

View File

@ -1,9 +1,9 @@
package com.songoda.core.modules;
import com.songoda.core.Plugin;
import com.songoda.core.PluginInfo;
public interface Module {
void run(Plugin plugin);
void run(PluginInfo plugin);
}

View File

@ -2,7 +2,7 @@ package com.songoda.core.modules.common;
import com.songoda.core.library.locale.Locale;
import com.songoda.core.modules.Module;
import com.songoda.core.Plugin;
import com.songoda.core.PluginInfo;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
@ -13,7 +13,7 @@ import java.net.URL;
public class LocaleModule implements Module {
@Override
public void run(Plugin plugin) {
public void run(PluginInfo plugin) {
JSONObject json = plugin.getJson();
try {
JSONArray files = (JSONArray) json.get("neededFiles");

View File

@ -0,0 +1,88 @@
package com.songoda.core.utils;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class PlayerUtils {
static Random random = new Random();
/**
* Get a list of all of the players that this player can "see"
*
* @param player player to check against, or null for all players
* @param startingWith optional query to test: only players whose game names
* start with this
* @return list of player names that are "visible" to the player
*/
public static List<String> getVisiblePlayerNames(Player player, String startingWith) {
final String startsWith = startingWith == null || startingWith.isEmpty() ? null : startingWith.toLowerCase();
return Bukkit.getOnlinePlayers().stream()
.filter(p -> p != player)
.filter(p -> startsWith == null || p.getName().toLowerCase().startsWith(startsWith))
.filter(p -> player == null || (player.canSee(p) && p.getMetadata("vanished").isEmpty()))
.map(Player::getName)
.collect(Collectors.toList());
}
/**
* Get a list of all of the players that this player can "see"
*
* @param player player to check against, or null for all players
* @param startingWith optional query to test: only players whose game names
* start with this
* @return list of players that are "visible" to the player
*/
public static List<Player> getVisiblePlayers(Player player, String startingWith) {
final String startsWith = startingWith == null || startingWith.isEmpty() ? null : startingWith.toLowerCase();
return Bukkit.getOnlinePlayers().stream()
.filter(p -> p != player)
.filter(p -> startsWith == null || p.getName().toLowerCase().startsWith(startsWith))
.filter(p -> player == null || (player.canSee(p) && p.getMetadata("vanished").isEmpty()))
.map(p -> (Player) p)
.collect(Collectors.toList());
}
/**
* Search for and grab the closest match for a provided player name. <br />
* Uses player display names if there is not an exact match.
*
* @param player player to search for
* @return Player that closest matches the input name, or null if none found
*/
public static Player findPlayer(String player) {
Player found = Bukkit.getServer().getPlayer(player);
if (found == null) {
final String searchName = player.replaceAll("[^a-zA-Z]", "").toLowerCase();
int d = 999;
for (Player p2 : Bukkit.getOnlinePlayers()) {
final String test = p2.getDisplayName().replaceAll("[^a-zA-Z]", "");
if (test.toLowerCase().startsWith(searchName)) {
int d2 = test.length() - searchName.length();
if (d2 < d) {
found = p2;
d = d2;
} else if (d2 == d) {
found = null;
}
}
}
}
return found;
}
public static Player getRandomPlayer() {
final Collection<? extends Player> all = Bukkit.getOnlinePlayers();
final Iterator<? extends Player> alli = all.iterator();
int pick = random.nextInt(all.size());
for (; pick > 0; --pick) {
alli.next();
}
return alli.hasNext() ? alli.next() : null;
}
}

View File

@ -1,7 +1,7 @@
package com.songoda.core.utils.gui;
import com.songoda.core.SongodaCore;
import com.songoda.core.library.ServerVersion;
import com.songoda.core.library.compatibility.ServerVersion;
import org.bukkit.Sound;
import org.bukkit.event.inventory.ClickType;