diff options
author | David <david@panic.tk> | 2018-11-07 23:50:06 +0100 |
---|---|---|
committer | David <david@panic.tk> | 2018-11-07 23:50:06 +0100 |
commit | 604cf01967ede98bf5024e4926bb0777fc4e8eee (patch) | |
tree | e2fa63d7e683769ee3bf3eddc75280648e92eb04 /src/main/java/com/redstoner/modules | |
parent | e86c52ef7c0e1e33c6af0e8674b038976bec11cc (diff) |
Converted Modules to gradle
Diffstat (limited to 'src/main/java/com/redstoner/modules')
97 files changed, 11199 insertions, 0 deletions
diff --git a/src/main/java/com/redstoner/modules/abot/Abot.cmd b/src/main/java/com/redstoner/modules/abot/Abot.cmd new file mode 100644 index 0000000..c8bb2d8 --- /dev/null +++ b/src/main/java/com/redstoner/modules/abot/Abot.cmd @@ -0,0 +1,7 @@ +command abot { + reload { + help Reloads answers from the .json file.; + run abot_reload; + perm utils.abot.reload; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/abot/Abot.java b/src/main/java/com/redstoner/modules/abot/Abot.java new file mode 100644 index 0000000..728d61c --- /dev/null +++ b/src/main/java/com/redstoner/modules/abot/Abot.java @@ -0,0 +1,68 @@ +package com.redstoner.modules.abot; + +import java.io.File; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Abot implements Module, Listener +{ + private File answerFile = new File(Main.plugin.getDataFolder(), "abot.json"); + JSONArray answers; + + @EventHandler + public void onPlayerChat(AsyncPlayerChatEvent event) + { + for (Object rawObject : answers) + { + JSONObject entry = (JSONObject) rawObject; + JSONArray regexes = (JSONArray) entry.get("regex"); + for (Object regex : regexes) + { + if (event.getMessage().toLowerCase().matches((String) regex)) + { + Object hideperm = entry.get("hide-perm"); + if (hideperm == null || !event.getPlayer().hasPermission((String) hideperm)) + { + event.setCancelled(true); + getLogger().message(event.getPlayer(), (String) entry.get("message")); + return; + } + } + } + } + } + + @Command(hook = "abot_reload") + public void loadAnswers(CommandSender sender) + { + answers = JsonManager.getArray(answerFile); + if (answers == null) + answers = new JSONArray(); + getLogger().message(sender, "Loaded the abot.json file!"); + } + + @Override + public boolean onEnable() + { + loadAnswers(Bukkit.getConsoleSender()); + return true; + } +} diff --git a/src/main/java/com/redstoner/modules/adminchat/Adminchat.cmd b/src/main/java/com/redstoner/modules/adminchat/Adminchat.cmd new file mode 100644 index 0000000..b083eb9 --- /dev/null +++ b/src/main/java/com/redstoner/modules/adminchat/Adminchat.cmd @@ -0,0 +1,42 @@ +command ac { + [string:message...] { + help Sends a message in Admin Chat; + perm utils.ac; + run ac_msg message; + } +} +command acn { + [string:name] [string:message...] { + help Sends a message in Admin Chat; + perm utils.ac; + type console; + run acn_msg name message; + } +} + +command ackey { + [string:key] { + help Sets your Admin Chat key; + perm utils.ac; + type player; + run setackey key; + } +} + +command act { + on { + help Turns on act; + perm utils.ac; + run act_on; + } + off { + help Turns off act; + perm utils.ac; + run act_off; + } + [empty] { + help toggles Admin Chat; + perm utils.ac; + run act; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/adminchat/Adminchat.java b/src/main/java/com/redstoner/modules/adminchat/Adminchat.java new file mode 100644 index 0000000..d736f8f --- /dev/null +++ b/src/main/java/com/redstoner/modules/adminchat/Adminchat.java @@ -0,0 +1,214 @@ +package com.redstoner.modules.adminchat; + +import java.io.File; +import java.util.ArrayList; +import java.util.UUID; +import java.util.regex.Pattern; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; + +import net.nemez.chatapi.ChatAPI; + +/** AdminChat module. Allows staff to chat to other staff using /ac \<message\> as well as a one char prefix or a toggle. + * + * @author Pepich */ +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Adminchat implements Module, Listener +{ + private static final char defaultKey = ','; + private static final File keysLocation = new File(Main.plugin.getDataFolder(), "adminchat_keys.json"); + private ArrayList<UUID> actoggled; + private static JSONObject keys; + + @Override + public boolean onEnable() + { + keys = JsonManager.getObject(keysLocation); + if (keys == null) + { + keys = new JSONObject(); + saveKeys(); + } + actoggled = new ArrayList<>(); + return true; + } + + @Command(hook = "ac_msg") + public boolean acSay(CommandSender sender, String message) + { + String name; + if (sender instanceof Player) + name = ((Player) sender).getDisplayName(); + else + name = sender.getName(); + Utils.broadcast("§8[§cAC§8] §9" + name + "§8: §b", ChatAPI.colorify(sender, message), new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return recipient.hasPermission("utils.ac"); + } + }); + return true; + } + + @Command(hook = "acn_msg") + public boolean acnSay(CommandSender sender, String name, String message) + { + Utils.broadcast("§8[§cAC§8] §9" + name + "§8: §b", ChatAPI.colorify(sender, message), new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return recipient.hasPermission("utils.ac"); + } + }); + return true; + } + + /** Let's a Player toggle their ac-toglge status to allow for automatically sending chat messages to adminchat. + * + * @param sender the issuer of the command. + * @param _void ignored. + * @return true. */ + @Command(hook = "act") + public boolean acToggleCommand(CommandSender sender) + { + if (actoggled.contains(((Player) sender).getUniqueId())) + { + actoggled.remove(((Player) sender).getUniqueId()); + getLogger().message(sender, "ACT now §cdisabled"); + } + else + { + actoggled.add(((Player) sender).getUniqueId()); + getLogger().message(sender, "ACT now §aenabled"); + } + return true; + } + + /** Let's a Player toggle their ac-toglge status to allow for automatically sending chat messages to adminchat. + * + * @param sender the issuer of the command. + * @return true. */ + @Command(hook = "act_on") + public boolean acToggleOnCommand(CommandSender sender) + { + if (!actoggled.contains(((Player) sender).getUniqueId())) + { + actoggled.add(((Player) sender).getUniqueId()); + getLogger().message(sender, "ACT now §aenabled"); + } + else + getLogger().message(sender, "ACT was already enabled"); + return true; + } + + /** Let's a Player toggle their ac-toglge status to allow for automatically sending chat messages to adminchat. + * + * @param sender the issuer of the command. + * @return true. */ + @Command(hook = "act_off") + public boolean acToggleOffCommand(CommandSender sender) + { + if (actoggled.contains(((Player) sender).getUniqueId())) + { + actoggled.remove(((Player) sender).getUniqueId()); + getLogger().message(sender, "ACT now §cdisabled"); + } + else + { + getLogger().message(sender, "ACT was already disabled"); + } + return true; + } + + /** Deals with chat events to allow for ackeys and actoggle. + * + * @param event the chat event containing the player and the message. */ + @EventHandler + public void onPlayerChat(AsyncPlayerChatEvent event) + { + Player player = event.getPlayer(); + if (!player.hasPermission("utils.ac")) + return; + if (event.getMessage().startsWith(getKey(player))) + { + event.setCancelled(true); + acSay(event.getPlayer(), event.getMessage().replaceFirst(Pattern.quote(getKey(player)), "")); + } + else if (actoggled.contains(event.getPlayer().getUniqueId())) + { + event.setCancelled(true); + acSay(event.getPlayer(), event.getMessage()); + } + } + + /** Sets the ackey of a Player. + * + * @param sender the issuer of the command. + * @param key the key to be set. Set to NULL or "" to get your current key. + * @return true. */ + @SuppressWarnings("unchecked") + @Command(hook = "setackey") + public boolean setAcKey(CommandSender sender, String key) + { + if (key.length() > 1) + { + getLogger().message(sender, true, + "Could not set your key to §6" + key + " §7, it can be at most one char."); + return true; + } + if (key == null || key.length() == 0) + { + getAcKey(sender); + return true; + } + getLogger().message(sender, "Set your key to §6" + key); + keys.put(((Player) sender).getUniqueId().toString(), key + ""); + saveKeys(); + return true; + } + + /** This method will find the AdminChat key of any player. + * + * @param player the player to get the key from. + * @return the key. */ + public static String getKey(Player player) + { + String key = (String) keys.get(player.getUniqueId().toString()); + return (key == null ? "" + defaultKey : key); + } + + /** Prints a Players ackey to their chat. + * + * @param sender the issuer of the command. */ + public void getAcKey(CommandSender sender) + { + getLogger().message(sender, "Your current ackey is §6" + getKey((Player) sender)); + } + + /** Saves the keys. */ + private void saveKeys() + { + JsonManager.save(keys, keysLocation); + } +} diff --git a/src/main/java/com/redstoner/modules/afk/AFK.cmd b/src/main/java/com/redstoner/modules/afk/AFK.cmd new file mode 100644 index 0000000..6f9385d --- /dev/null +++ b/src/main/java/com/redstoner/modules/afk/AFK.cmd @@ -0,0 +1,24 @@ +command afk { + alias eafk; + alias away; + alias eaway; + [empty] { + run afk; + perm utils.afk; + } + [optional:-s] { + run afks -s; + perm utils.afk; + } + [optional:-s] [string:reason...] { + run afk2 -s reason; + perm utils.afk; + } +} + +command update_afk_listeners { + [empty] { + run update_afk_listeners; + perm utils.afk.admin; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/afk/AFK.java b/src/main/java/com/redstoner/modules/afk/AFK.java new file mode 100644 index 0000000..810c0bb --- /dev/null +++ b/src/main/java/com/redstoner/modules/afk/AFK.java @@ -0,0 +1,235 @@ +package com.redstoner.modules.afk; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.EventException; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.plugin.EventExecutor; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Main; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 0, revision = 6, compatible = 5) +public class AFK implements Module, Listener +{ + private CustomListener listener; + boolean move = true, look = false; + + @Override + public void firstLoad() + { + Module.super.firstLoad(); + DataManager.setConfig("indicator", "&7[AFK]"); + String[] choices = new String[] {"listen", "ignore"}; + DataManager.setConfig("move", "listen", choices); + DataManager.setConfig("look", "ignore", choices); + DataManager.setConfig("chat", "listen", choices); + DataManager.setConfig("interact", "listen", choices); + DataManager.setConfig("command", "ignore", choices); + } + + @Override + public void migrate(Version old) + { + Module.super.migrate(old); + if ((old.major() == 4) && (old.minor() == 0) && (old.revision() == 3)) + { + String[] choices = new String[] {"listen", "ignore"}; + DataManager.setConfig("look", "ignore", choices); + } + } + + @Override + public void postEnable() + { + Module.super.postEnable(); + listener = new CustomListener(); + update_afk_listeners(Bukkit.getConsoleSender()); + } + + @Override + public void onDisable() + { + Module.super.onDisable(); + HandlerList.unregisterAll(listener); + } + + @Command(hook = "afk") + public boolean afk(CommandSender sender) + { + return afk(sender, false, ""); + } + + @Command(hook = "afks") + public boolean afk(CommandSender sender, boolean silent) + { + return afk(sender, silent, ""); + } + + @Command(hook = "afk2") + public boolean afk(CommandSender sender, boolean silent, String reason) + { + if (isafk(sender)) + { + unafk(sender, silent); + } + else + { + DataManager.setData(sender, "afk_time", System.currentTimeMillis()); + DataManager.setData(sender, "afk_reason", reason); + DataManager.setState(sender, "afk_silent", silent); + DataManager.setState(sender, "afk", true); + if (!silent) + Utils.broadcast("§7 * ", Utils.getName(sender) + "§7 is now AFK", null); + } + return true; + } + + public void unafk(CommandSender sender, boolean silent) + { + DataManager.setState(sender, "afk", false); + if (!silent) + Utils.broadcast("§7 * ", Utils.getName(sender) + "§7 is no longer AFK", null); + } + + public boolean isafk(CommandSender sender) + { + return DataManager.getState(sender, "afk"); + } + + public boolean isVanished(Player player) + { + return DataManager.getState(player, "vanished"); + } + + @Command(hook = "update_afk_listeners") + public boolean update_afk_listeners(CommandSender sender) + { + Utils.broadcast(null, "Updating afk listeners...", new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return recipient.hasPermission("utils.afk.admin"); + } + }); + move = DataManager.getConfigOrDefault("move", "listen").equals("listen"); + look = DataManager.getConfigOrDefault("look", "ignore").equals("listen"); + if (move || look) + Bukkit.getPluginManager().registerEvent(PlayerMoveEvent.class, listener, EventPriority.MONITOR, listener, + Main.plugin); + else + PlayerMoveEvent.getHandlerList().unregister(listener); + if (DataManager.getConfigOrDefault("chat", "listen").equals("listen")) + Bukkit.getPluginManager().registerEvent(PlayerInteractEvent.class, listener, EventPriority.MONITOR, + listener, Main.plugin); + else + PlayerInteractEvent.getHandlerList().unregister(listener); + if (DataManager.getConfigOrDefault("interact", "listen").equals("listen")) + Bukkit.getPluginManager().registerEvent(AsyncPlayerChatEvent.class, listener, EventPriority.MONITOR, + listener, Main.plugin); + else + AsyncPlayerChatEvent.getHandlerList().unregister(listener); + if (DataManager.getConfigOrDefault("command", "ignore").equals("listen")) + Bukkit.getPluginManager().registerEvent(PlayerCommandPreprocessEvent.class, listener, EventPriority.MONITOR, + listener, Main.plugin); + else + PlayerCommandPreprocessEvent.getHandlerList().unregister(listener); + return true; + } + + @EventHandler + public void onLeave(PlayerQuitEvent event) + { + DataManager.setState(event.getPlayer(), "afk", false); + } +} + +class CustomListener implements Listener, EventExecutor +{ + private boolean move = true, look = false; + + @Override + public void execute(Listener listener, Event event) throws EventException + { + if (event instanceof PlayerEvent) + { + if (event instanceof PlayerMoveEvent) + { + PlayerMoveEvent pevent = (PlayerMoveEvent) event; + double distance = pevent.getFrom().distance(pevent.getTo()); + boolean moved = distance > 0; + boolean looked = (pevent.getFrom().getPitch() != pevent.getTo().getPitch()) + || (pevent.getFrom().getYaw() != pevent.getTo().getYaw()); + if ((move && moved) || (look && looked)) + { + Player player = pevent.getPlayer(); + if (isafk(player)) + if (!isVanished(player)) + unafk(player); + } + } + else + { + PlayerEvent pevent = (PlayerEvent) event; + Player player = pevent.getPlayer(); + if (isafk(player)) + if (!isVanished(player)) + unafk(player); + } + } + } + + public void unafk(CommandSender sender) + { + DataManager.setState(sender, "afk", false); + if ( !isSilent(sender) ) + Utils.broadcast("§7 * ", Utils.getName(sender) + "§7 is no longer AFK", null); + } + + public boolean isafk(CommandSender sender) + { + return DataManager.getState(sender, "afk"); + } + + public boolean isSilent(CommandSender sender) + { + return DataManager.getState(sender, "afk_silent"); + } + + public boolean isVanished(Player player) + { + return DataManager.getState(player, "vanished"); + } + + public void listenMove(boolean move) + { + this.move = move; + } + + public void listenLook(boolean look) + { + this.look = look; + } +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/BlockPlaceMods.java b/src/main/java/com/redstoner/modules/blockplacemods/BlockPlaceMods.java new file mode 100644 index 0000000..6befbae --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/BlockPlaceMods.java @@ -0,0 +1,206 @@ +package com.redstoner.modules.blockplacemods; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; +import com.redstoner.modules.blockplacemods.mods.Mod; +import com.redstoner.modules.blockplacemods.mods.ModAbstract; +import com.redstoner.modules.blockplacemods.mods.ModToggledAbstract; +import com.redstoner.utils.CommandException; +import com.redstoner.utils.CommandMap; + +@Commands(CommandHolderType.None) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 1, compatible = 4) +public final class BlockPlaceMods implements Module, Listener +{ + @Override + public boolean onEnable() + { + ModAbstract.registerAll(getLogger()); + for (Mod mod : new ArrayList<>(ModAbstract.getMods().values())) + { + mod.registerListeners(); + } + try + { + Map<String, org.bukkit.command.Command> commandMap = CommandMap.getCommandMap(); + org.bukkit.command.Command command = new BlockPlaceModsCommand(); + for (String alias : getCommandAliases()) + { + commandMap.put(alias, command); + } + } + catch (ReflectiveOperationException ex) + { + ex.printStackTrace(); + return false; + } + return true; + } + + @Override + public void postEnable() + { + setPrefix("BPM"); + } + + @Override + public void onDisable() + { + for (Mod mod : ModAbstract.getMods().values()) + { + mod.unregisterListeners(); + } + try + { + Map<String, org.bukkit.command.Command> commandMap = CommandMap.getCommandMap(); + for (String alias : getCommandAliases()) + { + org.bukkit.command.Command command = commandMap.get(alias); + if (command != null && command.getClass() == BlockPlaceModsCommand.class) + { + commandMap.remove(alias); + } + } + } + catch (Exception ignored) + {} + } + + private static String[] getCommandAliases() + { + String pluginName = Main.plugin.getName().toLowerCase(); + // @noformat + return new String[]{"mod", pluginName + ":mod", + "set", pluginName + ":set", + "toggle", pluginName + ":toggle" + }; + // @format + } + + @Command(hook = "mod_empty") + public void onModEmptyCommand(CommandSender sender) + { + onModCommand(sender, ""); + } + + @Command(hook = "mod") + public void onModCommand(CommandSender sender, String input) + { + String[] args = new ArrayList<>(Arrays.asList(input.split(" "))).stream() + .filter(x -> x != null && !x.trim().isEmpty()).toArray(String[]::new); + String prefix = ""; + String message; + try + { + if (args.length > 0) + { + Mod target = ModAbstract.getMod(args[0].toLowerCase()); + if (target != null) + { + prefix += "&7[&2" + capitalize(target.getName()) + "&7]:&a "; + if (!(sender instanceof Player)) + { + message = "&cYou must be a player to use any block place mod"; + } + else + { + message = target.runCommand((Player) sender, Arrays.copyOfRange(args, 1, args.length)); + } + } + else if (args[0].equalsIgnoreCase("help")) + { + message = commandHelp(sender, args); + } + else + { + message = "&cThat argument could not be recognized"; + } + } + else + { + message = commandHelp(sender, args); + } + } + catch (CommandException ex) + { + message = " &c" + ex.getMessage(); + } + catch (Throwable t) + { + message = " &cAn unexpected error occurred while executing this command."; + t.printStackTrace(); + } + getLogger().message(sender, prefix + message); + } + + private String commandHelp(CommandSender sender, String[] args) + { + StringBuilder result = new StringBuilder("§7BlockPlaceMods adds some redstone-centric utilities"); + result.append("\n").append(ChatColor.GRAY.toString()).append("Available mods:"); + List<Mod> mods = new ArrayList<>(new HashSet<>(ModAbstract.getMods().values())); + mods.sort(Comparator.<Mod> comparingInt(m -> ModToggledAbstract.class.isInstance(m) ? 1 : -1) + .thenComparing(Mod::getName)); + for (Mod mod : mods) + { + result.append("\n").append(ChatColor.AQUA.toString()).append("/mod ").append(ChatColor.ITALIC.toString()) + .append(mod.getName()); + for (String alias : mod.getAliases()) + { + result.append('|').append(alias); + } + result.append(ChatColor.GRAY.toString()).append(" - ").append(mod.getDescription()); + } + return result.toString(); + } + + private static String capitalize(String modName) + { + if (modName.isEmpty()) + { + return modName; + } + char first = modName.charAt(0); + if (first != (first = Character.toUpperCase(first))) + { + char[] result = modName.toCharArray(); + result[0] = first; + return String.valueOf(result); + } + return modName; + } + + private class BlockPlaceModsCommand extends org.bukkit.command.Command + { + public BlockPlaceModsCommand() + { + super("mod"); + String[] aliases = getCommandAliases(); + setAliases(Arrays.asList(Arrays.copyOfRange(aliases, 1, aliases.length))); + } + + @Override + public boolean execute(CommandSender sender, String label, String[] args) + { + onModCommand(sender, String.join(" ", args)); + return true; + } + } +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/Mod.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/Mod.java new file mode 100644 index 0000000..9a2fcad --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/Mod.java @@ -0,0 +1,24 @@ +package com.redstoner.modules.blockplacemods.mods; + +import org.bukkit.entity.Player; + +import com.redstoner.utils.CommandException; + +import java.util.Set; + +public interface Mod +{ + String getName(); + + String getDescription(); + + Set<String> getAliases(); + + Object getDefault(); + + String runCommand(Player sender, String[] args) throws CommandException; + + void registerListeners(); + + void unregisterListeners(); +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModAbstract.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModAbstract.java new file mode 100644 index 0000000..5a383d8 --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModAbstract.java @@ -0,0 +1,94 @@ +package com.redstoner.modules.blockplacemods.mods; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryType; + +import com.redstoner.misc.Main; +import com.redstoner.modules.ModuleLogger; +import com.redstoner.modules.datamanager.DataManager; + +public abstract class ModAbstract implements Mod, Listener +{ + private static final Map<String, Mod> mods = new HashMap<>(); + private final String name; + private final Set<String> aliases; + private static ModuleLogger logger; + + public static Map<String, Mod> getMods() + { + return Collections.unmodifiableMap(mods); + } + + public static Mod getMod(String name) + { + return mods.get(name); + } + + public static void registerMod(Mod mod) + { + mods.put(mod.getName(), mod); + for (String alias : mod.getAliases()) + { + mods.putIfAbsent(alias, mod); + } + } + + public static void registerAll(final ModuleLogger logger) + { + ModAbstract.logger = logger; + registerMod(new ModToggledCauldron()); + registerMod(new ModToggledPiston()); + registerMod(new ModToggledObserver()); + registerMod(new ModToggledStep()); + registerMod(new ModToggledTorch()); + registerMod(new ModInventory("dropper", InventoryType.DROPPER)); + registerMod(new ModInventory("furnace", InventoryType.FURNACE)); + registerMod(new ModInventory("hopper", InventoryType.HOPPER)); + } + + public ModAbstract(String name) + { + this.name = Objects.requireNonNull(name); + this.aliases = new HashSet<>(2); + logger.info("Loaded mod " + name); + } + + @Override + public String getName() + { + return name; + } + + @Override + public Set<String> getAliases() + { + return aliases; + } + + @Override + public void registerListeners() + { + Bukkit.getPluginManager().registerEvents(this, Main.plugin); + } + + @Override + public void unregisterListeners() + { + HandlerList.unregisterAll(this); + } + + protected void reset(Player player) + { + DataManager.removeData(player.getUniqueId().toString(), "BlockPlaceMods", getName()); + } +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModInventory.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModInventory.java new file mode 100644 index 0000000..c6e483e --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModInventory.java @@ -0,0 +1,195 @@ +package com.redstoner.modules.blockplacemods.mods; + +import com.redstoner.modules.datamanager.DataManager; +import com.redstoner.utils.CommandException; +import com.redstoner.utils.ItemProperties; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.Arrays; + +public class ModInventory extends ModAbstract +{ + protected InventoryType inventoryType; + + public ModInventory(String name, InventoryType inventoryType) + { + super(name); + this.inventoryType = inventoryType; + } + + private static int highestUsedIndex(ItemStack[] items) + { + for (int i = items.length - 1; i >= 0; i--) + { + if (items[i] != null) + { + return i; + } + } + return -1; + } + + @Override + public String getDescription() + { + return "Controls " + inventoryType.name().toLowerCase() + " placement content"; + } + + @Override + public String runCommand(Player sender, String[] args) throws CommandException + { + if (args.length > 0) + { + if (args[0].equalsIgnoreCase("clear")) + { + reset(sender); + return "Reset data successfully"; + } + try + { + int slot = Integer.parseInt(args[0]); + if (slot >= inventoryType.getDefaultSize()) + { + throw new CommandException( + "Slot number " + slot + " is too high for " + inventoryType.toString().toLowerCase() + "s"); + } + if (slot < 0) + { + throw new CommandException("Slot number " + slot + " is negative"); + } + // Set the stored item to the item in the sender's hand + ItemStack item = sender.getInventory().getItemInMainHand(); + if (item == null || item.getType() == Material.AIR || item.getAmount() == 0) + { + // Remove the item. + // Set item to null to ensure correct itemName below. + item = null; + if (present(sender)) + { + set(sender, slot, null); + } + } + else + { + set(sender, slot, item);// don't need to clone because the reference isn't kept + } + String itemName = item == null ? "nothing" + : item.getAmount() + " " + item.getType().toString().toLowerCase().replace("_", ""); + return "Set the item in slot " + slot + " to " + itemName; + } + catch (NumberFormatException ex) + { + if (!args[0].equalsIgnoreCase("help")) + { + throw new CommandException("Expected a number indicating the slot that you want to set"); + } + } + } + StringBuilder message = new StringBuilder(); + message.append(" &a### &3Container Mod&a Help ###\n"); + message.append("&7").append(getDescription()).append('\n'); + message.append("&6/mod ").append(getName().toLowerCase()) + .append("&o <slot> &bsets the item in slot to your hand\n"); + message.append("&6/mod ").append(getName().toLowerCase()).append("&o clear &bclears the data\n"); + message.append("&6/mod ").append(getName().toLowerCase()).append("&o help &bshows this help page\n"); + return message.toString(); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) + { + if (present(event.getPlayer()) && event.getPlayer().getGameMode() == GameMode.CREATIVE) + { + BlockState state = event.getBlock().getState(); + if (state instanceof InventoryHolder) + { + Inventory inv = ((InventoryHolder) state).getInventory(); + if (inv.getType() == inventoryType) + { + ItemStack[] data = get(event.getPlayer()); + inv.setContents(data); + state.update(); + } + } + } + } + + protected ItemStack[] get(Player player) + { + Object obj = DataManager.getData(player.getUniqueId().toString(), "BlockPlaceMods", getName()); + if (obj == null) + return getDefault(); + JSONArray array = (JSONArray) obj; + ItemStack[] items = new ItemStack[Math.min(inventoryType.getDefaultSize(), array.size())]; + for (int i = 0, n = items.length; i < n; i++) + { + Object obj2 = array.get(i); + if (obj2 instanceof JSONObject) + { // if null, items[i] remains null + items[i] = new ItemProperties().loadFrom((JSONObject) obj2).toItemStack(); + } + } + return items; + } + + protected void set(Player player, int index, ItemStack item) + { + ItemStack[] data = get(player); + if (item == null) + { + if (index < data.length) + { + data[index] = null; + } + } + else + { + if (index >= data.length) + { + data = Arrays.copyOf(data, index + 1); + } + data[index] = item; + } + set(player, data); + } + + @SuppressWarnings("unchecked") + protected void set(Player player, ItemStack[] data) + { + if (highestUsedIndex(data) == -1) + reset(player); + else + { + JSONArray array = new JSONArray(); + for (int i = 0, n = highestUsedIndex(data); i < n; i++) + { + ItemStack item = data[i]; + array.add(item == null ? null : new ItemProperties(item).toJSONObject()); + } + DataManager.setData(player.getUniqueId().toString(), "BlockPlaceMods", getName(), array); + } + } + + protected boolean present(Player player) + { + return get(player) != null; + } + + @Override + public ItemStack[] getDefault() + { + return new ItemStack[0]; + } +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledAbstract.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledAbstract.java new file mode 100644 index 0000000..b9b2a7c --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledAbstract.java @@ -0,0 +1,80 @@ +package com.redstoner.modules.blockplacemods.mods; + +import com.redstoner.modules.datamanager.DataManager; +import com.redstoner.utils.CommandException; +import org.bukkit.entity.Player; + +public abstract class ModToggledAbstract extends ModAbstract +{ + protected boolean enabledByDefault; + + public ModToggledAbstract(String name, boolean enabledByDefault) { + super(name); + this.enabledByDefault = enabledByDefault; + } + + @Override + public Boolean getDefault() { + return enabledByDefault; + } + + protected boolean hasEnabled(Player player) + { + return (boolean) DataManager.getOrDefault(player.getUniqueId().toString(), "BlockPlaceMods", getName(), + enabledByDefault); + } + + protected boolean setEnabled(Player sender, boolean enabled) + { + if (enabled == hasEnabled(sender)) + return false; + if (enabled == enabledByDefault) + reset(sender); + else + DataManager.setData(sender.getUniqueId().toString(), "BlockPlaceMods", getName(), enabled); + return true; + } + + @Override + public String runCommand(Player sender, String[] args) throws CommandException + { + if (args.length == 0 || args[0].equalsIgnoreCase("toggle")) + { + boolean enabled = hasEnabled(sender); + setEnabled(sender, !enabled); + return !enabled ? "Enabled" : "Disabled"; + } + if (args[0].equalsIgnoreCase("help")) + { + StringBuilder message = new StringBuilder(); + message.append(" &a### &3Toggled Mod&a Help ###"); + message.append("\n&7").append(getDescription()); + message.append("\n&6/mod ").append(getName()).append("&o (toggle) &btoggles state"); + message.append("\n&6/mod ").append(getName()).append("&o on/off &bsets state"); + message.append("\n&6/mod ").append(getName()).append("&o help &bshows this help page"); + return message.toString(); + } + final boolean enable; + switch (args[0].toLowerCase()) + { + case "on": + case "enable": + case "true": + enable = true; + break; + case "off": + case "disable": + case "false": + enable = false; + break; + default: + throw new CommandException("Input '" + args[0] + "' was not understood. " + + "Use one of: \non, enable, true, off, disable, false."); + } + if (!setEnabled(sender, enable)) + { + throw new CommandException("Was already " + (enable ? "enabled" : "disabled")); + } + return enable ? "Enabled" : "Disabled"; + } +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledCauldron.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledCauldron.java new file mode 100644 index 0000000..669f093 --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledCauldron.java @@ -0,0 +1,49 @@ +package com.redstoner.modules.blockplacemods.mods; + +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +public class ModToggledCauldron extends ModToggledAbstract +{ + public ModToggledCauldron() + { + super("cauldron", false); + } + + @Override + public String getDescription() + { + return "If active, placed cauldrons are filled, and they cycle on shiftless right click with redstone or fist"; + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) + { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && !event.getPlayer().isSneaking() + && event.getClickedBlock().getType() == Material.CAULDRON && hasEnabled(event.getPlayer()) + && (event.getPlayer().getGameMode() == GameMode.CREATIVE) + && (event.getPlayer().getInventory().getItemInMainHand().getType() == Material.AIR)) + { + Block block = event.getClickedBlock(); + block.setData((byte) ((block.getData() - 1) & 0x3)); + } + } + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) + { + if (event.getBlock().getType() == Material.CAULDRON && !event.getPlayer().isSneaking() + && hasEnabled(event.getPlayer()) && (event.getPlayer().getGameMode() == GameMode.CREATIVE)) + { + event.getBlock().setData((byte) 3); + } + } +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledLogPlaceAbstract.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledLogPlaceAbstract.java new file mode 100644 index 0000000..17c414b --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledLogPlaceAbstract.java @@ -0,0 +1,40 @@ +package com.redstoner.modules.blockplacemods.mods; + +import org.bukkit.GameMode; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockPlaceEvent; + +/** + * A mod that makes placement of directional blocks act the way placement of logs does normally. + * Quartz pillar placement works like this too. + * + * Placed blocks face the block you clicked to place them. + */ +public abstract class ModToggledLogPlaceAbstract extends ModToggledAbstract { + + protected ModToggledLogPlaceAbstract(String name, boolean enabledByDefault) { + super(name, enabledByDefault); + } + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) + { + Player player = event.getPlayer(); + Block block; + if (hasEnabled(player) && !player.isSneaking() && player.getGameMode() == GameMode.CREATIVE + && isApplicableToPlacedBlock(block = event.getBlock())) + { + block.setData((byte) getBlockDataForFacing(block.getFace(event.getBlockAgainst()))); + } + } + + protected abstract int getBlockDataForFacing(BlockFace direction); + + protected abstract boolean isApplicableToPlacedBlock(Block block); + +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledObserver.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledObserver.java new file mode 100644 index 0000000..8084bf4 --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledObserver.java @@ -0,0 +1,43 @@ +package com.redstoner.modules.blockplacemods.mods; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +public class ModToggledObserver extends ModToggledLogPlaceAbstract { + + protected ModToggledObserver() { + super("observer", false); + } + + @Override + public String getDescription() { + return "If active, observers face the block you place them against"; + } + + @Override + protected boolean isApplicableToPlacedBlock(Block block) { + return block.getType() == Material.OBSERVER; + } + + @Override + protected int getBlockDataForFacing(BlockFace direction) { + switch (direction) { + case UP: + return 0; + default: + case DOWN: + return 1; + case SOUTH: + return 2; + case NORTH: + return 3; + case EAST: + return 4; + case WEST: + return 5; + } + } + + +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledPiston.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledPiston.java new file mode 100644 index 0000000..29e810c --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledPiston.java @@ -0,0 +1,46 @@ +package com.redstoner.modules.blockplacemods.mods; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +public class ModToggledPiston extends ModToggledLogPlaceAbstract +{ + public ModToggledPiston() + { + super("piston", false); + } + + @Override + public String getDescription() + { + return "If active, pistons face the block you place them against"; + } + + @Override + protected boolean isApplicableToPlacedBlock(Block block) { + Material type = block.getType(); + return type == Material.PISTON_BASE || type == Material.PISTON_STICKY_BASE; + } + + @Override + protected int getBlockDataForFacing(BlockFace direction) { + switch (direction) + { + default: + case DOWN: + return 0; + case UP: + return 1; + case NORTH: + return 2; + case SOUTH: + return 3; + case WEST: + return 4; + case EAST: + return 5; + } + } + +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledStep.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledStep.java new file mode 100644 index 0000000..fe42fa4 --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledStep.java @@ -0,0 +1,40 @@ +package com.redstoner.modules.blockplacemods.mods; + +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockPlaceEvent; + +public class ModToggledStep extends ModToggledAbstract +{ + public ModToggledStep() + { + super("step", true); + getAliases().add("slab"); + } + + @Override + public String getDescription() + { + return "If active, placed steps will always turn upside-down"; + } + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) + { + if (isStep(event.getBlock().getType()) && !event.getPlayer().isSneaking() && hasEnabled(event.getPlayer())) + { + byte data = event.getBlock().getData(); + if (data != (data |= 0x8)) + { + event.getBlock().setData(data); + } + } + } + + private boolean isStep(Material block) + { + return block == Material.STEP || block == Material.STONE_SLAB2; + } +} diff --git a/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledTorch.java b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledTorch.java new file mode 100644 index 0000000..188bce2 --- /dev/null +++ b/src/main/java/com/redstoner/modules/blockplacemods/mods/ModToggledTorch.java @@ -0,0 +1,91 @@ +package com.redstoner.modules.blockplacemods.mods; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockPlaceEvent; + +import com.redstoner.misc.Main; + +public class ModToggledTorch extends ModToggledAbstract +{ + private final Set<Block> torchesPlaced = new HashSet<>(); + + public ModToggledTorch() + { + super("torch", true); + Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.plugin, this::updateTorches, 2, 2); + } + + @Override + public String getDescription() + { + return "If active, redstone torches placed on a redstone block disappear quickly"; + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) + { + final Player player = event.getPlayer(); + if (!player.isSneaking() && player.getGameMode() == GameMode.CREATIVE && hasEnabled(player) + && event.getBlock().getType() == Material.REDSTONE_TORCH_ON) + { + if (isAttachedToRedstoneBlock(event.getBlock())) + { + torchesPlaced.add(event.getBlock()); + } + } + } + + @SuppressWarnings("deprecation") + private boolean isAttachedToRedstoneBlock(Block block) + { + BlockFace towardsAgainst = getFaceTowardsBlockAgainst(block.getData()); + return towardsAgainst != null && block.getRelative(towardsAgainst).getType() == Material.REDSTONE_BLOCK; + } + + private BlockFace getFaceTowardsBlockAgainst(byte data) + { + switch (data) + { + case 1: + return BlockFace.WEST; + case 2: + return BlockFace.EAST; + case 3: + return BlockFace.NORTH; + case 4: + return BlockFace.SOUTH; + case 5: + return BlockFace.DOWN; + default: + return null; + } + } + + private void updateTorches() + { + for (Iterator<Block> it = torchesPlaced.iterator(); it.hasNext();) + { + Block block = it.next(); + if (block.getType() == Material.REDSTONE_TORCH_OFF) + { + block.setType(Material.AIR); + it.remove(); + } + else if (block.getType() != Material.REDSTONE_TORCH_ON || !isAttachedToRedstoneBlock(block)) + { + it.remove(); + } + } + } +} diff --git a/src/main/java/com/redstoner/modules/buildchat/BuildChat.cmd b/src/main/java/com/redstoner/modules/buildchat/BuildChat.cmd new file mode 100644 index 0000000..ddd7d77 --- /dev/null +++ b/src/main/java/com/redstoner/modules/buildchat/BuildChat.cmd @@ -0,0 +1,42 @@ +command bc { + [string:message...] { + help Sends a message in BuildTeam Chat; + perm utils.bc; + run bc_msg message; + } +} +command bcn { + [string:name] [string:message...] { + help Sends a message in BuildTeam Chat; + perm utils.bc; + type console; + run bcn_msg name message; + } +} + +command bckey { + [string:key] { + help Sets your BuildTeam Chat key; + perm utils.bc; + type player; + run setbckey key; + } +} + +command bct { + on { + help Turns on bct; + perm utils.bc; + run bct_on; + } + off { + help Turns off bct; + perm utils.bc; + run bct_off; + } + [empty] { + help toggles BuildTeam Chat; + perm utils.bc; + run bct; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/buildchat/BuildChat.java b/src/main/java/com/redstoner/modules/buildchat/BuildChat.java new file mode 100644 index 0000000..4ea0779 --- /dev/null +++ b/src/main/java/com/redstoner/modules/buildchat/BuildChat.java @@ -0,0 +1,207 @@ +package com.redstoner.modules.buildchat; + +import java.io.File; +import java.util.ArrayList; +import java.util.UUID; +import java.util.regex.Pattern; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; + +/** BuildTeamChat module. Allows the build team to chat privately using /bc \<message\> as well as a one char prefix or a toggle. + * + * @author Pepich */ +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class BuildChat implements Module, Listener +{ + private static final char defaultKey = ';'; + private static final File keysLocation = new File(Main.plugin.getDataFolder(), "buildchat_keys.json"); + private ArrayList<UUID> bctoggled; + private static JSONObject keys; + + @Override + public boolean onEnable() + { + keys = JsonManager.getObject(keysLocation); + if (keys == null) + { + keys = new JSONObject(); + saveKeys(); + } + bctoggled = new ArrayList<>(); + return true; + } + + @Command(hook = "bc_msg") + public boolean bcSay(CommandSender sender, String message) + { + String name; + if (sender instanceof Player) + name = ((Player) sender).getDisplayName(); + else + name = sender.getName(); + Utils.broadcast("§8[§cBC§8] §9" + name + "§8: §b", message, new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return recipient.hasPermission("utils.bc"); + } + }); + return true; + } + + @Command(hook = "bcn_msg") + public boolean bcnSay(CommandSender sender, String name, String message) + { + Utils.broadcast("§8[§cBC§8] §9" + name + "§8: §b", message, new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return recipient.hasPermission("utils.bc"); + } + }); + return true; + } + + /** Let's a Player toggle their auto-cg status to allow for automatically sending chat messages to their chatgroup. + * + * @param sender the issuer of the command. + * @param _void ignored. + * @return true. */ + @Command(hook = "bct") + public boolean bcToggleCommand(CommandSender sender) + { + if (bctoggled.contains(((Player) sender).getUniqueId())) + { + bctoggled.remove(((Player) sender).getUniqueId()); + getLogger().message(sender, "BCT now §cdisabled"); + } + else + { + bctoggled.add(((Player) sender).getUniqueId()); + getLogger().message(sender, "BCT now §aenabled"); + } + return true; + } + + /** Let's a Player toggle their auto-cg status to allow for automatically sending chat messages to their chatgroup. + * + * @param sender the issuer of the command. + * @return true. */ + @Command(hook = "bct_on") + public boolean bcToggleOnCommand(CommandSender sender) + { + if (!bctoggled.contains(((Player) sender).getUniqueId())) + { + bctoggled.add(((Player) sender).getUniqueId()); + getLogger().message(sender, "BCT now §aenabled"); + } + else + getLogger().message(sender, "BCT was already enabled"); + return true; + } + + /** Let's a Player toggle their auto-cg status to allow for automatically sending chat messages to their chatgroup. + * + * @param sender the issuer of the command. + * @return true. */ + @Command(hook = "bct_off") + public boolean bcToggleOffCommand(CommandSender sender) + { + if (bctoggled.remove(((Player) sender).getUniqueId())) + getLogger().message(sender, "BCT now §cdisabled"); + else + getLogger().message(sender, "BCT was already disabled"); + return true; + } + + /** Deals with chat events to allow for bckeys and bctoggle. + * + * @param event the chat event containing the player and the message. */ + @EventHandler + public void onPlayerChat(AsyncPlayerChatEvent event) + { + Player player = event.getPlayer(); + if (!player.hasPermission("utils.bc")) + return; + if (event.getMessage().startsWith(getKey(player))) + { + event.setCancelled(true); + bcSay(event.getPlayer(), event.getMessage().replaceFirst(Pattern.quote(getKey(player)), "")); + } + else if (bctoggled.contains(event.getPlayer().getUniqueId())) + { + event.setCancelled(true); + bcSay(event.getPlayer(), event.getMessage()); + } + } + + /** Sets the bckey of a Player. + * + * @param sender the issuer of the command. + * @param key the key to be set. Set to NULL or "" to get your current key. + * @return true. */ + @SuppressWarnings("unchecked") + @Command(hook = "setbckey") + public boolean setBcKey(CommandSender sender, String key) + { + if (key.length() > 1) + { + getLogger().message(sender, true, + "Could not set your key to §6" + key + " §7, it can be at most one char."); + return true; + } + if (key == null || key.length() == 0) + { + getBcKey(sender); + return true; + } + getLogger().message(sender, "Set your key to §6" + key); + keys.put(((Player) sender).getUniqueId().toString(), key + ""); + saveKeys(); + return true; + } + + /** This method will find the ChatgGroup key of any player. + * + * @param player the player to get the key from. + * @return the key. */ + public static String getKey(Player player) + { + String key = (String) keys.get(player.getUniqueId().toString()); + return (key == null ? "" + defaultKey : key); + } + + /** Prints a Players bckey to their chat. + * + * @param sender the issuer of the command. */ + public void getBcKey(CommandSender sender) + { + getLogger().message(sender, "Your current bckey is §6" + getKey((Player) sender)); + } + + /** Saves the keys. */ + private void saveKeys() + { + JsonManager.save(keys, keysLocation); + } +} diff --git a/src/main/java/com/redstoner/modules/buildteam/BuildTeam.cmd b/src/main/java/com/redstoner/modules/buildteam/BuildTeam.cmd new file mode 100644 index 0000000..d4f3303 --- /dev/null +++ b/src/main/java/com/redstoner/modules/buildteam/BuildTeam.cmd @@ -0,0 +1,22 @@ +command teleport { + alias tp; + alias tele; + [string:player...] { + run teleport player; + } + type player; +} + +command team_add { + [string:player] { + run team_add player; + perm utils.buildteam.manage; + } +} + +command team_remove { + [string:player] { + run team_remove player; + perm utils.buildteam.manage; + } +} diff --git a/src/main/java/com/redstoner/modules/buildteam/BuildTeam.java b/src/main/java/com/redstoner/modules/buildteam/BuildTeam.java new file mode 100644 index 0000000..986b41c --- /dev/null +++ b/src/main/java/com/redstoner/modules/buildteam/BuildTeam.java @@ -0,0 +1,56 @@ +package com.redstoner.modules.buildteam; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 0, compatible = 4) +public class BuildTeam implements Module +{ + @Command(hook = "teleport") + public boolean teleport(CommandSender sender, String target_name) + { + final Player player = (Player) sender; + final Player target = Bukkit.getPlayer(target_name); + if (target == null || !player.hasPermission("utils.buildteam.teleport") + || !target.getLocation().getWorld().getName().equals("BuildTeam")) + { + player.performCommand("essentials:tp " + target_name); + return true; + } + player.teleport(target); + getLogger().message(sender, "Teleported you to &e" + target.getDisplayName() + "&7!"); + return true; + } + + @Command(hook = "team_add") + public boolean add(CommandSender sender, String target_name) + { + if (!target_name.matches("^\\w{2,16}$")) + { + getLogger().message(sender, true, "This doesn't look like a valid playername!"); + return true; + } + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "pex user " + target_name + " group add +buildteam"); + return true; + } + + @Command(hook = "team_remove") + public boolean remove(CommandSender sender, String target_name) + { + if (!target_name.matches("^\\w{2,16}$")) + { + getLogger().message(sender, true, "This doesn't look like a valid playername!"); + return true; + } + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "pex user " + target_name + " group remove +buildteam"); + return true; + } +} diff --git a/src/main/java/com/redstoner/modules/chat/Chat.cmd b/src/main/java/com/redstoner/modules/chat/Chat.cmd new file mode 100644 index 0000000..3091609 --- /dev/null +++ b/src/main/java/com/redstoner/modules/chat/Chat.cmd @@ -0,0 +1,81 @@ +command me { + perm utils.me; + [string:text...] { + help /me's in chat.; + run me text; + } +} +command action { + perm utils.action; + [string:text...] { + help /action's in chat.; + run action text; + } +} +command chat { + alias speak; + [string:message...] { + perm utils.chat; + run chat message; + help A way to speak in normal chat with normal formatting if you have ACT or CGT on.; + } +} +command chatn { + alias speakn; + [string:name] [string:message...] { + perm utils.chatn; + run chatn name message; + help A way to speak in normal chat with normal formatting for console users.; + } +} +command shrug { + [string:message...] { + perm utils.shrug; + run shrug message; + help Appends the shrug emoticon to the end of your message.; + } + [empty] { + perm utils.shrug; + run shrugnoarg; + help Just the shrug emoticon.; + } +} +command say { + [string:message...] { + perm utils.say; + run say message; + help A replacement for the default say command to make the format be more consistant.; + } +} +command sayn { + [string:name] [string:message...] { + perm utils.sayn; + type console; + run sayn name message; + help A replacement for the default say command to make the format be more consistant.; + } +} + +command mute { + [string:player] { + perm utils.chat.admin; + run mute player; + help Mutes a player.; + } +} + +command print { + [string:message...] { + perm utils.print; + run print message; + help A way to just print something in to chat with all the formatting things a user has.; + } +} + +command unmute { + [string:player] { + perm utils.chat.admin; + run unmute player; + help Unmutes a player.; + } +} diff --git a/src/main/java/com/redstoner/modules/chat/Chat.java b/src/main/java/com/redstoner/modules/chat/Chat.java new file mode 100644 index 0000000..1c7f8a1 --- /dev/null +++ b/src/main/java/com/redstoner/modules/chat/Chat.java @@ -0,0 +1,215 @@ +package com.redstoner.modules.chat; + +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +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.AsyncPlayerChatEvent; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; +import com.redstoner.modules.ignore.Ignore; + +import net.nemez.chatapi.ChatAPI; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 1, compatible = 4) +public class Chat implements Module, Listener +{ + private final Map<String, String> defaults = new HashMap<>(); + + public Chat() + { + defaults.put("chat", " %n §7→§r %m"); + defaults.put("me", " §7- %n §7⇦ %m"); + defaults.put("action", " §7- %n §7⇦ %m"); + defaults.put("say", " §7[§9%n§7]:§r %m"); + defaults.put("shrug", " %n §7→§r %m ¯\\_(ツ)_/¯"); + defaults.put("print", "%m"); + } + + @Override + public void firstLoad() + { + Module.super.firstLoad(); + DataManager.setConfig("chat", defaults.get("chat")); + DataManager.setConfig("me", defaults.get("me")); + DataManager.setConfig("action", defaults.get("action")); + DataManager.setConfig("say", defaults.get("say")); + DataManager.setConfig("shrug", defaults.get("shrug")); + DataManager.setConfig("print", defaults.get("print")); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerChat(AsyncPlayerChatEvent event) + { + if (event.isCancelled()) + return; + Player player = event.getPlayer(); + String message = event.getMessage(); + event.setCancelled(true); + broadcastFormatted("chat", player, message, event); + } + + @Command(hook = "me") + public boolean me(CommandSender sender, String message) + { + broadcastFormatted("me", sender, message); + return true; + } + + @Command(hook = "chat") + public boolean chat(CommandSender sender, String message) + { + broadcastFormatted("chat", sender, message); + return true; + } + + @Command(hook = "chatn") + public boolean chatn(CommandSender sender, String name, String message) + { + broadcastFormatted("chat", sender, message, name); + return true; + } + + @Command(hook = "action") + public boolean action(CommandSender sender, String message) + { + broadcastFormatted("action", sender, message); + return true; + } + + @Command(hook = "say") + public boolean say(CommandSender sender, String message) + { + String name; + if (sender instanceof Player) + name = ((Player) sender).getName(); + else + name = "§9CONSOLE"; + broadcastFormatted("say", sender, message, name); + return true; + } + + @Command(hook = "sayn") + public boolean say(CommandSender sender, String name, String message) + { + broadcastFormatted("say", sender, message, name); + return true; + } + + @Command(hook = "shrug") + public boolean shrug(CommandSender sender, String message) + { + broadcastFormatted("shrug", sender, message); + return true; + } + + @Command(hook = "shrugnoarg") + public boolean shrug(CommandSender sender) + { + broadcastFormatted("shrug", sender, ""); + return true; + } + + @Command(hook = "print") + public boolean print(CommandSender sender, String message) + { + broadcastFormatted("print", sender, message); + return true; + } + + @Command(hook = "mute") + public boolean mute(CommandSender sender, String player) + { + Player p = Bukkit.getPlayer(player); + if (p == null) + { + getLogger().message(sender, true, "That player couldn't be found!"); + return true; + } + DataManager.setData(p, "muted", true); + getLogger().message(sender, "Muted player &e" + Utils.getName(p) + "&7!"); + getLogger().message(p, "You have been &cmuted&7!"); + return true; + } + + @Command(hook = "unmute") + public boolean unmute(CommandSender sender, String player) + { + Player p = Bukkit.getPlayer(player); + if (p == null) + { + getLogger().message(sender, true, "That player couldn't be found!"); + return true; + } + DataManager.setData(p, "muted", false); + getLogger().message(sender, "Unmuted player &e" + Utils.getName(p) + "&7!"); + getLogger().message(p, "You have been &aunmuted&7!"); + return true; + } + + public boolean broadcastFormatted(String format, CommandSender sender, String message) + { + return broadcastFormatted(format, sender, message, Utils.getName(sender), null); + } + + public boolean broadcastFormatted(String format, CommandSender sender, String message, String name) + { + return broadcastFormatted(format, sender, message, name, null); + } + + public boolean broadcastFormatted(String format, CommandSender sender, String message, AsyncPlayerChatEvent event) + { + return broadcastFormatted(format, sender, message, Utils.getName(sender), event); + } + + public boolean broadcastFormatted(String format, CommandSender sender, String message, String name, + AsyncPlayerChatEvent event) + { + if ((boolean) DataManager.getOrDefault(sender, "muted", false)) + { + getLogger().message(sender, true, "You have been muted!"); + getLogger().info(" &7User &e" + Utils.getName(sender) + " &7tried to &e" + format + " &7(&e" + message + + "&7) while being &cmuted&7."); + return false; + } + String raw = (String) DataManager.getConfigOrDefault(format, defaults.get(format)); + String formatted = raw.replace("%n", name).replace("%m", message); + Utils.broadcast("", ChatAPI.colorify(sender, formatted), + wrap(ModuleLoader.exists("Ignore") ? Ignore.getIgnoredBy(sender) : null, event)); + return true; + } + + public BroadcastFilter wrap(BroadcastFilter filter, AsyncPlayerChatEvent event) + { + if (event == null) + return filter; + else + return new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + if (recipient instanceof ConsoleCommandSender) + return true; + return filter.sendTo(recipient) && event.getRecipients().contains(recipient); + } + }; + } +} diff --git a/src/main/java/com/redstoner/modules/chatalias/Chatalias.cmd b/src/main/java/com/redstoner/modules/chatalias/Chatalias.cmd new file mode 100644 index 0000000..8af4bb6 --- /dev/null +++ b/src/main/java/com/redstoner/modules/chatalias/Chatalias.cmd @@ -0,0 +1,16 @@ +command alias { + add [flag:-r] [string:keyword] [string:replacement...] { + help Adds a new alias. Set -r to make it a regex-alias.; + run addalias -r keyword replacement; + } + del [flag:-r] [string:keyword] { + help Deletes an alias. -r indicates if it was a regex-alias.; + run delalias -r keyword; + } + list { + help Lists your aliases.; + run listaliases; + } + perm utils.alias; + type player; +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/chatalias/Chatalias.java b/src/main/java/com/redstoner/modules/chatalias/Chatalias.java new file mode 100644 index 0000000..eb13b4d --- /dev/null +++ b/src/main/java/com/redstoner/modules/chatalias/Chatalias.java @@ -0,0 +1,317 @@ +package com.redstoner.modules.chatalias; + +import java.io.File; +import java.util.ArrayList; +import java.util.Set; +import java.util.UUID; +import java.util.regex.Pattern; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +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.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.permissions.PermissionAttachmentInfo; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; + +import net.nemez.chatapi.ChatAPI; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Chatalias implements Module, Listener +{ + private final String[] commands = new String[] {"e?r", "e?m .+?", "e?t", "e?w", "e?msg .+?", "e?message .+?", + "e?whisper .+?", "e?me", "cgsay", "ac", "bc", "say", "sayn .+?", "chat", "shrug", "action"}; + private JSONObject aliases = new JSONObject(); + + @Override + public boolean onEnable() + { + for (Player p : Bukkit.getOnlinePlayers()) + { + loadAliases(p.getUniqueId()); + } + return true; + } + + @Override + public void onDisable() + { + for (Object key : aliases.keySet()) + { + UUID uuid = UUID.fromString((String) key); + saveAliases(uuid); + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) + { + loadAliases(event.getPlayer().getUniqueId()); + } + + @EventHandler + public void onPlayerLeave(PlayerQuitEvent event) + { + aliases.remove(event.getPlayer().getUniqueId().toString()); + } + + @SuppressWarnings("unchecked") + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerChat(AsyncPlayerChatEvent event) + { + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + if (!aliases.containsKey(uuid.toString())) + { + loadAliases(player.getUniqueId()); + if (!aliases.containsKey(uuid.toString())) + return; + } + JSONObject playerAliases = (JSONObject) aliases.get(uuid.toString()); + boolean changed = false; + for (Object key : playerAliases.keySet()) + { + String keyword = (String) key; + String replacement = (String) playerAliases.get(key); + if (keyword.startsWith("R: ")) + { + keyword = keyword.replace("R: ", ""); + event.setMessage(event.getMessage().replaceAll(keyword, replacement)); + } + else + { + if (keyword.startsWith("N: ")) + keyword = keyword.replace("N: ", ""); + else + { + changed = true; + playerAliases.put("N: " + key, replacement); + } + event.setMessage(event.getMessage().replace(keyword, replacement)); + } + int maxLength; + try + { + maxLength = Integer.valueOf(getPermissionContent(player, "utils.alias.length.")); + } + catch (NumberFormatException e) + { + maxLength = 255; + } + if (event.getMessage().length() > maxLength) + { + getLogger().message(player, true, "The generated message is too long!"); + event.setCancelled(true); + return; + } + } + event.setMessage(ChatAPI.colorify(event.getPlayer(), event.getMessage())); + if (changed) + saveAliases(uuid); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerCommand(PlayerCommandPreprocessEvent event) + { + if (event.isCancelled()) + return; + boolean listening = false; + String command = ""; + for (String s : commands) + { + command = "^\\/(.*:)?" + s + " "; + if (event.getMessage().matches(command + ".*")) + { + listening = true; + break; + } + } + if (!listening) + return; + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + JSONObject playerAliases = (JSONObject) aliases.get(uuid.toString()); + String temp = event.getMessage().replaceAll(command, ""); + command = event.getMessage().replaceAll(Pattern.quote(temp) + "$", ""); + event.setMessage(event.getMessage().replaceFirst(Pattern.quote(command), "")); + for (Object key : playerAliases.keySet()) + { + String keyword = (String) key; + String replacement = (String) playerAliases.get(key); + if (keyword.startsWith("R: ")) + { + keyword = keyword.replace("R: ", ""); + event.setMessage(event.getMessage().replaceAll(keyword, replacement)); + } + else + { + if (keyword.startsWith("N: ")) + keyword = keyword.replace("N: ", ""); + event.setMessage(event.getMessage().replace(keyword, replacement)); + } + int maxLength; + try + { + maxLength = Integer.valueOf(getPermissionContent(player, "utils.alias.length.")); + } + catch (NumberFormatException e) + { + maxLength = 255; + } + if (event.getMessage().length() > maxLength) + { + getLogger().message(player, true, "The generated message is too long!"); + event.setCancelled(true); + return; + } + } + event.setMessage(command + event.getMessage()); + } + + @SuppressWarnings("unchecked") + @Command(hook = "addalias") + public boolean addAlias(CommandSender sender, boolean regex, String keyword, String replacement) + { + if (regex && keyword.equals(".*")) + { + getLogger().message(sender, true, "You may not define the wildcard regex as an alias."); + return true; + } + Player player = (Player) sender; + UUID uuid = player.getUniqueId(); + JSONObject data = (JSONObject) aliases.get(uuid.toString()); + keyword = (regex ? "R: " : "N: ") + keyword; + if (!data.containsKey(keyword)) + { + int maxAmount; + try + { + maxAmount = Integer.valueOf(getPermissionContent(player, "utils.alias.amount.")); + } + catch (NumberFormatException e) + { + maxAmount = 25; + } + if (data.size() == maxAmount) + { + getLogger().message(sender, true, "You already reached your maximum of aliases!"); + return true; + } + } + data.put(keyword, replacement); + if (sender.hasPermission("essentials.chat.color")) + getLogger().message(sender, + "Successfully created alias " + keyword.substring(3) + " §7-> " + replacement + " §7for you."); + else + getLogger().message(sender, + "Successfully created alias " + keyword.substring(3) + " §7-> " + replacement + " §7for you."); + saveAliases(uuid); + return true; + } + + @Command(hook = "delalias") + public boolean delAlias(CommandSender sender, boolean regex, String keyword) + { + Player player = (Player) sender; + UUID uuid = player.getUniqueId(); + JSONObject data = (JSONObject) aliases.get(uuid.toString()); + keyword = (regex ? "R: " : "N: ") + keyword; + if (data.remove(keyword) != null) + { + getLogger().message(sender, "Successfully removed the alias!"); + saveAliases(uuid); + return true; + } + else + { + getLogger().message(sender, true, "That alias doesn't exist! Hint: regex/no regex does matter for this."); + return true; + } + } + + @Command(hook = "listaliases") + public boolean listAliases(CommandSender sender) + { + ArrayList<String> message = new ArrayList<>(); + Player player = (Player) sender; + UUID uuid = player.getUniqueId(); + JSONObject data = (JSONObject) aliases.get(uuid.toString()); + for (Object key : data.keySet()) + message.add((String) key + " §7-> " + data.get(key)); + getLogger().message(sender, message.toArray(new String[] {})); + return true; + } + + private String getPermissionContent(Player player, String permnode) + { + Set<PermissionAttachmentInfo> perms = player.getEffectivePermissions(); + for (PermissionAttachmentInfo perm : perms) + if (perm.getPermission().toString().startsWith(permnode)) + return perm.getPermission().replace(permnode, ""); + return null; + } + + @SuppressWarnings("unchecked") + private void loadAliases(UUID uuid) + { + JSONObject defaults = new JSONObject(); + defaults.put("dataFormat", "v1"); + JSONObject data = new JSONObject(); + data.put("N: ./", "/"); + defaults.put("data", data); + JSONObject playerAliases = JsonManager + .getObject(new File(Main.plugin.getDataFolder(), "aliases/" + uuid.toString() + ".json")); + if (playerAliases == null) + { + playerAliases = defaults; + } + String dataFormat = (String) playerAliases.get("dataFormat"); + if (dataFormat == null) + { + JSONObject temp = new JSONObject(); + temp.put("dataFormat", "v1"); + JSONObject tempAliases = new JSONObject(); + { + for (Object key : playerAliases.keySet()) + { + tempAliases.put("N: " + key, playerAliases.get(key)); + } + } + temp.put("data", tempAliases); + aliases.put(uuid.toString(), temp.get("data")); + } + else if (dataFormat.equals("v1")) + aliases.put(uuid.toString(), playerAliases.get("data")); + else + { + getLogger().error("Unknown data format for alias set of player " + uuid.toString()); + aliases.put(uuid.toString(), ((JSONObject) defaults.get("data")).clone()); + saveAliases(uuid); + } + } + + @SuppressWarnings("unchecked") + private void saveAliases(UUID uuid) + { + JSONObject temp = new JSONObject(); + temp.put("dataFormat", "v1"); + temp.put("data", aliases.get(uuid.toString())); + JsonManager.save(temp, new File(Main.plugin.getDataFolder(), "aliases/" + uuid.toString() + ".json")); + } +} diff --git a/src/main/java/com/redstoner/modules/chatgroups/Chatgroups.cmd b/src/main/java/com/redstoner/modules/chatgroups/Chatgroups.cmd new file mode 100644 index 0000000..33fd0c5 --- /dev/null +++ b/src/main/java/com/redstoner/modules/chatgroups/Chatgroups.cmd @@ -0,0 +1,35 @@ +command cgt { + [empty] { + help Toggles your cgtoggle status.; + type player; + run cgtoggle; + } +} +command cgkey { + [string:key] { + help Sets your chatgroup key.; + run setcgkey key; + type player; + } +} +command cgsay { + [string:message...] { + help Chats in your chatgroup.; + run cgsay message; + } +} +command cg { + join [string:group] { + help Joins a chatgroup.; + run cgjoin group; + } + leave { + help Leaves your chatgroup.; + run cgleave; + } + info { + help Displays info about your chatgroup.; + run cginfo; + } + +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/chatgroups/Chatgroups.java b/src/main/java/com/redstoner/modules/chatgroups/Chatgroups.java new file mode 100644 index 0000000..457702c --- /dev/null +++ b/src/main/java/com/redstoner/modules/chatgroups/Chatgroups.java @@ -0,0 +1,400 @@ +package com.redstoner.modules.chatgroups; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.ignore.Ignore; +import com.redstoner.modules.socialspy.Socialspy; + +import net.nemez.chatapi.ChatAPI; + +/** The ChatGroups module. Allows people to have private sub-chats that can be accessed via a single char prefix or a toggle. + * + * @author Pepich */ +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Chatgroups implements Module, Listener +{ + private static final char defaultKey = ':'; + private static final File groupsLocation = new File(Main.plugin.getDataFolder(), "chatgroups.json"); + private static final File keysLocation = new File(Main.plugin.getDataFolder(), "chatgroup_keys.json"); + private ArrayList<UUID> cgtoggled; + private static JSONObject groups, keys; + + @Override + public boolean onEnable() + { + groups = JsonManager.getObject(groupsLocation); + if (groups == null) + { + groups = new JSONObject(); + saveGroups(); + } + keys = JsonManager.getObject(keysLocation); + if (keys == null) + { + keys = new JSONObject(); + saveKeys(); + } + cgtoggled = new ArrayList<>(); + return true; + } + + @Override + public void onDisable() + { + saveKeys(); + saveGroups(); + } + + /** Prints chatgroup info (like players in the group, groupname) to the sender. + * + * @param sender the issuer of the command. + * @return true. */ + @SuppressWarnings("unchecked") + @Command(hook = "cginfo") + public boolean cgInfo(CommandSender sender) + { + String group = getGroup(sender); + if (group == null) + getLogger().message(sender, true, "You are not in a chatgroup!"); + else + { + ArrayList<String> message = new ArrayList<>(); + message.add("§7Your current chatgroup is: §6" + group); + ArrayList<String> players = new ArrayList<>(); + Iterator<String> iter = groups.keySet().iterator(); + while (iter.hasNext()) + { + String id = iter.next(); + if (((String) groups.get(id)).equals(group)) + { + if (!id.equals("CONSOLE")) + { + UUID uuid = UUID.fromString(id); + Player p = Bukkit.getPlayer(uuid); + if (p != null) + players.add(p.getDisplayName()); + else + players.add(Bukkit.getOfflinePlayer(UUID.fromString(id)).getName()); + } + else + players.add(id); + } + } + StringBuilder sb = new StringBuilder("&6Other players in this group: &9"); + for (String player : players) + { + sb.append(player); + sb.append("&7, &9"); + } + sb.delete(sb.length() - 2, sb.length()); + message.add(sb.toString()); + getLogger().message(sender, message.toArray(new String[] {})); + } + return true; + } + + /** Prints a Players cgkey to their chat. + * + * @param sender the issuer of the command. */ + public void getCgKey(CommandSender sender) + { + getLogger().message(sender, "Your current cgkey is §6" + getKey((Player) sender)); + } + + /** Sets the cgkey of a Player. + * + * @param sender the issuer of the command. + * @param key the key to be set. Set to NULL or "" to get your current key. + * @return true. */ + @SuppressWarnings("unchecked") + @Command(hook = "setcgkey") + public boolean setCgKey(CommandSender sender, String key) + { + if (key.length() > 1) + { + getLogger().message(sender, true, + "Could not set your key to §6" + key + " §7, it can be at most one char."); + return true; + } + if (key == null || key.length() == 0) + { + getCgKey(sender); + return true; + } + getLogger().message(sender, "Set your key to §6" + key); + keys.put(((Player) sender).getUniqueId().toString(), key + ""); + saveKeys(); + return true; + } + + /** Let's a Player toggle their auto-cg status to allow for automatically sending chat messages to their chatgroup. + * + * @param sender the issuer of the command. + * @return true. */ + @Command(hook = "cgtoggle") + public boolean cgToggleCommand(CommandSender sender) + { + if (getGroup(sender) != null) + if (cgtoggled.contains(((Player) sender).getUniqueId())) + { + cgtoggled.remove(((Player) sender).getUniqueId()); + getLogger().message(sender, "CGT now §cdisabled"); + } + else + { + cgtoggled.add(((Player) sender).getUniqueId()); + getLogger().message(sender, "CGT now §aenabled"); + } + else + getLogger().message(sender, true, "You are not in a chatgroup!"); + return true; + } + + /** Lets a CommandSender leave their group. + * + * @param sender the command issuer. + * @return true. */ + @Command(hook = "cgleave") + public boolean cgLeave(CommandSender sender) + { + String group = removeGroup(sender); + if (group == null) + { + getLogger().message(sender, true, "You were not in a chatgroup!"); + return true; + } + String name = Utils.getName(sender); + sendToGroup(group, "&9" + name + " &7left the group!"); + getLogger().message(sender, "Successfully removed you from your group!"); + if (sender instanceof Player) + cgtoggled.remove(((Player) sender).getUniqueId()); + return true; + } + + /** Lets a CommandSender join a group. + * + * @param sender the command issuer. + * @param name the name of the group. + * @return true. */ + @Command(hook = "cgjoin") + public boolean cgJoin(CommandSender sender, String name) + { + String pname = Utils.getName(sender); + String group = getGroup(sender); + if (group != null && group.equals(name)) + getLogger().message(sender, true, "You were already in group §6" + name); + else + { + setGroup(sender, null); + if (group != null) + sendToGroup(group, "&9" + pname + " &7left the group!"); + sendToGroup(name, "&9" + pname + " &7joined the group!"); + setGroup(sender, name); + getLogger().message(sender, "Successfully joined group §6" + name); + } + return true; + } + + /** Sends a message to a group. + * + * @param sender the sender of the message - the message will be sent to the group of the sender. + * @param message the message to be sent. + * @return true. */ + @Command(hook = "cgsay") + public boolean cgSay(CommandSender sender, String message) + { + String group = getGroup(sender); + if (group != null) + sendToGroup(sender, message); + else + getLogger().message(sender, true, "You are not in a chatgroup right now!"); + return true; + } + + /** Deals with chat events to allow for cgkeys and cgtoggle. + * + * @param event the chat event containing the player and the message. */ + @EventHandler + public void onPlayerChat(AsyncPlayerChatEvent event) + { + String group = getGroup(event.getPlayer()); + Player player = event.getPlayer(); + if (group != null) + { + if (event.getMessage().startsWith(getKey(player))) + { + event.setCancelled(true); + sendToGroup(event.getPlayer(), event.getMessage().substring(1)); + } + else if (cgtoggled.contains(event.getPlayer().getUniqueId())) + { + event.setCancelled(true); + sendToGroup(event.getPlayer(), event.getMessage()); + } + } + } + + /** Finds the group of a CommandSender. + * + * @param target the CommandSender to get the group of. + * @return the group of the target or NULL if he doesn't have one. */ + public static String getGroup(CommandSender target) + { + if (target instanceof Player) + return (String) groups.get(((Player) target).getUniqueId().toString()); + else + return (String) groups.get("CONSOLE"); + } + + /** Sets the group of the CommandSender. + * + * @param target the CommandSender to set the group of. + * @param group the name of the group to join. */ + @SuppressWarnings("unchecked") + private void setGroup(CommandSender target, String group) + { + if (target instanceof Player) + groups.put(((Player) target).getUniqueId().toString(), group); + else + groups.put("CONSOLE", group); + saveGroups(); + } + + /** Removes a CommandSender from their chatgroup. Will also save the groups after finishing + * + * @param target the CommandSender to get their group removed. */ + private String removeGroup(CommandSender target) + { + String group; + if (target instanceof Player) + group = (String) groups.remove(((Player) target).getUniqueId().toString()); + else + group = (String) groups.remove("CONSOLE"); + saveGroups(); + return group; + } + + /** This method will find the ChatgGroup key of any player. + * + * @param player the player to get the key from. + * @return the key. */ + public static String getKey(Player player) + { + String key = (String) keys.get(player.getUniqueId().toString()); + return (key == null ? "" + defaultKey : key); + } + + /** This method sends a message to a chatgroup. + * + * @param sender the sender of the message. Also defines which group the message will be sent to. + * @param message the message to be sent. */ + private void sendToGroup(CommandSender sender, String message) + { + String name = Utils.getName(sender); + String group = getGroup(sender); + message = ChatAPI.colorify(null, message); + + BroadcastFilter ignore = ModuleLoader.exists("Ignore")? Ignore.getIgnoredBy(sender) : null; + Utils.broadcast("§8[§bCG§8] §9", name + "§8: §6" + message, new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + + String rgroup = getGroup(recipient); + if ( rgroup != null && (ignore == null? true : ignore.sendTo(recipient)) ) + return rgroup.equals(group); + else + return false; + } + }); + if (ModuleLoader.getModule("Socialspy") != null) + { + Socialspy.spyBroadcast(sender, "§e" + group + " §a(cg)", message, "/cg", new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return getGroup(recipient) == null || !getGroup(recipient).equals(group); + } + }); + } + if (getGroup(Bukkit.getConsoleSender()) == null || !getGroup(Bukkit.getConsoleSender()).equals(group)) + { + getLogger().info(name + " in " + group + ": " + message + " §8(hidden)"); + } + } + + /** This method sends a message to a chatgroup. + * + * @param sender the sender of the message. Also defines which group the message will be sent to. + * @param message the message to be sent. */ + private void sendToGroup(String group, String message) + { + message = ChatAPI.colorify(null, message); + Utils.broadcast(null, message, new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + String rgroup = getGroup(recipient); + if (rgroup != null) + return rgroup.equals(group); + else + return false; + } + }); + if (ModuleLoader.getModule("Socialspy") != null) + { + Socialspy.spyBroadcast(Bukkit.getConsoleSender(), "§e" + group + " §a(cg)", message, "/cg", + new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return getGroup(recipient) == null || !getGroup(recipient).equals(group); + } + }); + } + if (getGroup(Bukkit.getConsoleSender()) == null || !getGroup(Bukkit.getConsoleSender()).equals(group)) + { + getLogger().info("In " + group + ": " + message + " §8(hidden)"); + } + } + + /** Saves the groups. */ + private void saveGroups() + { + JsonManager.save(groups, groupsLocation); + } + + /** Saves the keys. */ + private void saveKeys() + { + JsonManager.save(keys, keysLocation); + } +} diff --git a/src/main/java/com/redstoner/modules/check/Check.cmd b/src/main/java/com/redstoner/modules/check/Check.cmd new file mode 100644 index 0000000..87cadbd --- /dev/null +++ b/src/main/java/com/redstoner/modules/check/Check.cmd @@ -0,0 +1,8 @@ +command check { + perm utils.check; + + [string:player] { + run checkCommand player; + help Get info on a player; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/check/Check.java b/src/main/java/com/redstoner/modules/check/Check.java new file mode 100644 index 0000000..48bf579 --- /dev/null +++ b/src/main/java/com/redstoner/modules/check/Check.java @@ -0,0 +1,247 @@ +package com.redstoner.modules.check; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.event.Listener; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.nemez.cmdmgr.CommandManager; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Main; +import com.redstoner.misc.mysql.JSONManager; +import com.redstoner.misc.mysql.MysqlHandler; +import com.redstoner.misc.mysql.elements.ConstraintOperator; +import com.redstoner.misc.mysql.elements.MysqlConstraint; +import com.redstoner.misc.mysql.elements.MysqlDatabase; +import com.redstoner.misc.mysql.elements.MysqlTable; +import com.redstoner.modules.Module; + +import net.nemez.chatapi.click.Message; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Check implements Module, Listener +{ + MysqlTable table; + + @Override + public boolean onEnable() + { + Map<Serializable, Serializable> config = JSONManager.getConfiguration("check.json"); + if (config == null || !config.containsKey("database") || !config.containsKey("table")) + { + getLogger().error("Could not load the Check config file, disabling!"); + return false; + } + try + { + MysqlDatabase database = MysqlHandler.INSTANCE + .getDatabase((String) config.get("database") + "?autoReconnect=true"); + table = database.getTable((String) config.get("table")); + } + catch (NullPointerException e) + { + getLogger().error("Could not use the Check config, disabling!"); + return false; + } + return true; + } + + @Override + public void postEnable() + { + CommandManager.registerCommand(getCommandString(), this, Main.plugin); + } + + @SuppressWarnings("deprecation") + @Command(hook = "checkCommand", async = AsyncType.ALWAYS) + public void checkCommand(final CommandSender sender, final String player) + { + getLogger().message(sender, "&7Please note that the data may not be fully accurate!"); + OfflinePlayer oPlayer; + oPlayer = Bukkit.getPlayer(player); + if (oPlayer == null) + oPlayer = Bukkit.getServer().getOfflinePlayer(player); + sendData(sender, oPlayer); + if (ModuleLoader.exists("Tag")) + Bukkit.dispatchCommand(sender, "tag check " + player); + } + + public String read(URL url) + { + String data = ""; + try + { + Scanner in = new Scanner(new InputStreamReader(url.openStream())); + while (in.hasNextLine()) + { + data += in.nextLine(); + } + in.close(); + return data; + } + catch (IOException e) + {} + return null; + } + + public JSONObject getIpInfo(OfflinePlayer player) + { + String ip = ""; + if (player.isOnline()) + { + ip = player.getPlayer().getAddress().getHostString(); + } + else + { + try + { + ip = (String) table.get("last_ip", new MysqlConstraint("uuid", ConstraintOperator.EQUAL, + player.getUniqueId().toString().replace("-", "")))[0]; + } + catch (Exception e) + { + return null; + } + } + try + { + URL ipinfo = new URL("https://ipinfo.io/" + ip + "/json"); + String rawJson = read(ipinfo); + return (JSONObject) new JSONParser().parse(rawJson); + } + catch (Exception e) + {} + return null; + } + + public String getFirstJoin(OfflinePlayer player) + { + Long firstJoin = player.getFirstPlayed(); + Date date = new Date(firstJoin); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + return format.format(date); + } + + public String getLastSeen(OfflinePlayer player) + { + Long lastSeen = player.getLastPlayed(); + Date date = new Date(lastSeen); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + return format.format(date); + } + + public Object[] getWebsiteData(OfflinePlayer player) + { + MysqlConstraint constraint = new MysqlConstraint("uuid", ConstraintOperator.EQUAL, + player.getUniqueId().toString().replace("-", "")); + try + { + int id = (int) table.get("id", constraint)[0]; + String email = (String) table.get("email", constraint)[0]; + boolean confirmed = (boolean) table.get("confirmed", constraint)[0]; + return new Object[] {"https://redstoner.com/users/" + id, email, confirmed}; + } + catch (Exception e) + { + try + { + int id = (int) table.get("id", constraint)[0]; + String email = (String) table.get("email", constraint)[0]; + boolean confirmed = (boolean) table.get("confirmed", constraint)[0]; + return new Object[] {"https://redstoner.com/users/" + id, email, confirmed}; + } + catch (Exception e2) + {} + return new Object[] {null}; + } + } + + public String getCountry(JSONObject data) + { + return (String) data.get("country"); + } + + public String getAllNames(OfflinePlayer player) + { + String uuid = player.getUniqueId().toString().replace("-", ""); + String nameString = ""; + try + { + String rawJson = read(new URL("https://api.mojang.com/user/profiles/" + uuid + "/names")); + JSONArray names = (JSONArray) new JSONParser().parse(rawJson); + for (Object obj : names) + { + nameString += "&e" + ((JSONObject) obj).get("name") + "&7, "; + } + nameString = nameString.substring(0, nameString.length() - 2); + return nameString; + } + catch (Exception e) + {} + return null; + } + + public void sendData(CommandSender sender, OfflinePlayer player) + { + try + { + JSONObject ipInfo = getIpInfo(player); + // data + String firstJoin = getFirstJoin(player); + String lastSeen = getLastSeen(player); + firstJoin = (firstJoin.equals("1970-01-01 01:00")) ? "&eNever" : "&7(yyyy-MM-dd hh:mm) &e" + firstJoin; + lastSeen = (lastSeen.equals("1970-1-1 01:00")) ? "&eNever" : "&7(yyyy-MM-dd hh:mm) &e" + lastSeen; + Object[] websiteData = getWebsiteData(player); + String websiteUrl = (websiteData[0] == null) ? "None" : (String) websiteData[0]; + String email = (websiteData[0] == null) ? "Unknown" : (String) websiteData[1]; + boolean emailNotConfirmed = (websiteData[0] == null) ? false : !((boolean) websiteData[2]); + String country = (ipInfo == null) ? "Unknown" : getCountry(ipInfo); + String namesUsed = getAllNames(player); + if (namesUsed == null) + namesUsed = "None"; + // messages + List<Message> messages = new ArrayList<>(); + messages.add(new Message(sender, null).appendText(getLogger().getHeader())); + messages.add(new Message(sender, null).appendText("&7Data provided by redstoner:")); + messages.add(new Message(sender, null).appendSuggestHover("&6> UUID: &e" + player.getUniqueId().toString(), + player.getUniqueId().toString(), "Click to copy into chatbox!")); + messages.add(new Message(sender, null).appendText("&6> First joined: &e" + firstJoin)); + messages.add(new Message(sender, null).appendText("&6> Last seen: &e" + lastSeen)); + messages.add( + new Message(sender, null).appendText("&6> Website account: &e").appendLink(websiteUrl, websiteUrl)); + messages.add(new Message(sender, null).appendText("&6> Email: &e") + .appendText((emailNotConfirmed ? "&6> &4Email NOT Confirmed!&e" : "&e") + email)); + messages.add(new Message(sender, null).appendText("&7Data provided by ipinfo:")); + messages.add(new Message(sender, null).appendText("&6> Country: &e" + country)); + messages.add(new Message(sender, null).appendText("&7Data provided by mojang:")); + messages.add(new Message(sender, null).appendText("&6> All ingame names used so far: &e" + namesUsed)); + for (Message m : messages) + m.send(); + } + catch (Exception e) + { + getLogger().message(sender, true, "Sorry, something went wrong while fetching data"); + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/redstoner/modules/clear/Clear.cmd b/src/main/java/com/redstoner/modules/clear/Clear.cmd new file mode 100644 index 0000000..117804b --- /dev/null +++ b/src/main/java/com/redstoner/modules/clear/Clear.cmd @@ -0,0 +1,13 @@ +command clear{ + [empty] { + help Clears your inventory; + type player; + perm utils.clear; + run clear; + } + [string:player] { + help Clears someone elses inventory; + perm utils.admin.clear; + run clearother player; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/clear/Clear.java b/src/main/java/com/redstoner/modules/clear/Clear.java new file mode 100644 index 0000000..a6ea86f --- /dev/null +++ b/src/main/java/com/redstoner/modules/clear/Clear.java @@ -0,0 +1,44 @@ +package com.redstoner.modules.clear; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Clear implements Module +{ + @Command(hook = "clear") + public boolean clearInventory(CommandSender sender) + { + Player player = (Player) sender; + Inventory inv = player.getInventory(); + for (int i = 0; i < 36; i++) + inv.clear(i); + getLogger().message(sender, "Cleared your inventory!"); + return true; + } + + @Command(hook = "clearother") + public boolean clearOtherInventory(CommandSender sender, String name) + { + Player player = Bukkit.getPlayer(name); + if (player == null) + getLogger().message(sender, true, "That player couldn't be found!"); + else + { + Inventory inv = player.getInventory(); + for (int i = 0; i < 36; i++) + inv.clear(i); + getLogger().message(sender, "Cleared " + player.getDisplayName() + "&7's inventory!"); + } + return true; + } +} diff --git a/src/main/java/com/redstoner/modules/cycle/Cycle.cmd b/src/main/java/com/redstoner/modules/cycle/Cycle.cmd new file mode 100644 index 0000000..dc8e10a --- /dev/null +++ b/src/main/java/com/redstoner/modules/cycle/Cycle.cmd @@ -0,0 +1,12 @@ +command cycle { + on { + help Turns on cycle; + type player; + run cycle_on; + } + off { + help Turns off cycle; + type player; + run cycle_off; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/cycle/Cycle.java b/src/main/java/com/redstoner/modules/cycle/Cycle.java new file mode 100644 index 0000000..b0a6310 --- /dev/null +++ b/src/main/java/com/redstoner/modules/cycle/Cycle.java @@ -0,0 +1,142 @@ +package com.redstoner.modules.cycle; + +import java.io.File; +import java.util.UUID; + +import org.bukkit.GameMode; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.json.simple.JSONArray; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Cycle implements Module, Listener +{ + private File cycleFile = new File(Main.plugin.getDataFolder(), "cycle.json"); + private JSONArray no_cyclers; + + @Override + public boolean onEnable() + { + no_cyclers = JsonManager.getArray(cycleFile); + if (no_cyclers == null) + no_cyclers = new JSONArray(); + return true; + } + + @Override + public void onDisable() + { + saveCyclers(); + } + + private void saveCyclers() + { + JsonManager.save(no_cyclers, cycleFile); + } + + @Command(hook = "cycle_on") + public boolean cycleOn(CommandSender sender) + { + UUID uid = ((Player) sender).getUniqueId(); + if (no_cyclers.remove(uid.toString())) + { + getLogger().message(sender, "Cycle enabled!"); + saveCyclers(); + } + else + getLogger().message(sender, "Cycle was already enabled!"); + return true; + } + + @SuppressWarnings("unchecked") + @Command(hook = "cycle_off") + public boolean cycleOff(CommandSender sender) + { + UUID uid = ((Player) sender).getUniqueId(); + if (!no_cyclers.contains(uid.toString())) + { + getLogger().message(sender, "Cycle disabled!"); + no_cyclers.add(uid.toString()); + saveCyclers(); + } + else + getLogger().message(sender, "Cycle was already disabled!"); + return true; + } + + @EventHandler + public void onInventoryCycle(PlayerItemHeldEvent event) + { + Player player = event.getPlayer(); + UUID uid = player.getUniqueId(); + if (!player.getGameMode().equals(GameMode.CREATIVE) || player.isSneaking() + || no_cyclers.contains(uid.toString())) + return; + int prev_slot = event.getPreviousSlot(); + int new_slot = event.getNewSlot(); + if (prev_slot == 0 && new_slot == 8) + shift(player, false); + else if (prev_slot == 8 && new_slot == 0) + shift(player, true); + } + + private void shift(Player player, boolean down) + { + Inventory inv = player.getInventory(); + ItemStack[] items = inv.getStorageContents(); + int shift = down ? -9 : 9; + shift = (shift + items.length) % items.length; + for (int i = 0; i < 4; i++) + { + items = join(subset(items, shift, items.length), subset(items, 0, shift)); + ItemStack[] hotbar = subset(items, 0, 9); + boolean found = false; + for (ItemStack item : hotbar) + if (item != null) + { + found = true; + break; + } + if (found) + break; + } + inv.setStorageContents(items); + } + + private ItemStack[] subset(ItemStack[] items, int start, int end) + { + ItemStack[] result = new ItemStack[end - start]; + for (int i = start; i < end; i++) + { + result[i - start] = items[i]; + } + return result; + } + + private ItemStack[] join(ItemStack[] items1, ItemStack[] items2) + { + ItemStack[] result = new ItemStack[items1.length + items2.length]; + for (int i = 0; i < items1.length; i++) + result[i] = items1[i]; + int offset = items1.length; + for (int i = 0; i < items2.length; i++) + result[i + offset] = items2[i]; + return result; + } +} diff --git a/src/main/java/com/redstoner/modules/damnspam/DamnSpam.cmd b/src/main/java/com/redstoner/modules/damnspam/DamnSpam.cmd new file mode 100644 index 0000000..404968e --- /dev/null +++ b/src/main/java/com/redstoner/modules/damnspam/DamnSpam.cmd @@ -0,0 +1,15 @@ +command damnspam { + perm utils.damnspam; + + [double:seconds] { + run damnspamSingle seconds; + help Set single input cooldown for button or lever.; + type player; + } + + [double:secondsOff] [double:secondsOn] { + run damnspamDouble secondsOff secondsOn; + help Set input cooldown after it's been turned off and turned on (for lever only).; + type player; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/damnspam/DamnSpam.java b/src/main/java/com/redstoner/modules/damnspam/DamnSpam.java new file mode 100644 index 0000000..fa5af87 --- /dev/null +++ b/src/main/java/com/redstoner/modules/damnspam/DamnSpam.java @@ -0,0 +1,350 @@ +package com.redstoner.modules.damnspam; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; + +import net.nemez.chatapi.ChatAPI; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 1, compatible = 4) +public class DamnSpam implements Module, Listener +{ + File configFile = new File(Main.plugin.getDataFolder(), "DamnSpam.json"); + Map<String, SpamInput> inputs; + boolean changingInput = false; + List<Material> acceptedInputs; + HashMap<Material, int[][]> attachedBlocks; + HashMap<Player, SpamInput> players; + int maxTimeout = 240; + String timeoutErrorString = "The timeout must be -1 or within 0 and " + maxTimeout; + + @Override + public boolean onEnable() + { + loadInputs(); + acceptedInputs = new ArrayList<Material>(); + Collections.addAll(acceptedInputs, Material.WOOD_BUTTON, Material.STONE_BUTTON, Material.LEVER); + attachedBlocks = new HashMap<Material, int[][]>(); + attachedBlocks.put(Material.LEVER, + new int[][] {{0, 7, 8, 15}, {5, 6, 13, 14}, {4, 12}, {3, 11}, {2, 10}, {1, 9}}); + attachedBlocks.put(Material.STONE_BUTTON, + new int[][] {{0, 8}, {5, 6, 7, 13, 14, 15}, {4, 12}, {3, 11}, {2, 10}, {1, 9}}); + attachedBlocks.put(Material.WOOD_BUTTON, + new int[][] {{0, 8}, {5, 6, 7, 13, 14, 15}, {4, 12}, {3, 11}, {2, 10}, {1, 9}}); + players = new HashMap<Player, SpamInput>(); + return true; + } + + public void loadInputs() + { + inputs = new HashMap<String, SpamInput>(); + try + { + FileReader reader = new FileReader(configFile); + JSONObject json = (JSONObject) new JSONParser().parse(reader); + for (Object key : json.keySet()) + { + JSONObject inputData = (JSONObject) json.get(key); + String uuid = (String) inputData.get("creator"); + Double timeoutOn = (Double) inputData.get("timeout_on"); + Double timeoutOff = (Double) inputData.get("timeout_off"); + Double lastTime = (Double) inputData.get("last_time"); + inputs.put((String) key, new SpamInput(uuid, timeoutOff, timeoutOn, lastTime)); + } + } + catch (IOException | ParseException e) + { + e.printStackTrace(); + } + } + + @SuppressWarnings("unchecked") + public void saveInputs() + { + JSONObject json = new JSONObject(); + for (String key : inputs.keySet()) + { + JSONObject jsonInput = new JSONObject(); + SpamInput input = inputs.get(key); + jsonInput.put("creator", input.player); + jsonInput.put("timeout_on", input.timeoutOn); + jsonInput.put("timeout_off", input.timeoutOff); + jsonInput.put("last_time", input.lastTime); + json.put(key, jsonInput); + } + try + { + PrintWriter writer = new PrintWriter(configFile); + writer.write(json.toJSONString()); + writer.close(); + } + catch (FileNotFoundException e) + { + e.printStackTrace(); + } + } + + public String locationString(Location loc) + { + return loc.getWorld().getName() + ";" + loc.getBlockX() + ";" + loc.getBlockY() + ";" + loc.getBlockZ(); + } + + public boolean isAcceptableTimeout(double timeout) + { + return (timeout > 0 && timeout <= maxTimeout) || timeout == -1; + } + + public boolean canBuild(Player player, Block block) + { + BlockBreakEvent event = new BlockBreakEvent(block, player); + Bukkit.getPluginManager().callEvent(event); + return !event.isCancelled(); + } + + @Command(hook = "damnspamSingle") + public void damnspam(CommandSender sender, double seconds) + { + boolean destroyingInput = false; + seconds = (double) Math.round(seconds * 100) / 100; + if (seconds == 0) + destroyingInput = true; + else if (!isAcceptableTimeout(seconds)) + { + ChatAPI.sendActionBar(sender, "&cThe timeout must be &e-1&c or within &e0&c and &e" + maxTimeout); + return; + } + ChatAPI.sendActionBar(sender, "&7Please click the input you would like to set."); + setPlayer((Player) sender, destroyingInput, seconds, seconds); + } + + @Command(hook = "damnspamDouble") + public void damnspam(CommandSender sender, double secondsOff, double secondsOn) + { + boolean destroyingInput = false; + secondsOn = (double) Math.round(secondsOn * 100) / 100; + secondsOff = (double) Math.round(secondsOff * 100) / 100; + if (secondsOn == 0 && secondsOff == 0) + { + destroyingInput = true; + } + else if (!(isAcceptableTimeout(secondsOn) && isAcceptableTimeout(secondsOff))) + { + ChatAPI.sendActionBar(sender, "&cThe timeout must be &e-1&c or within &e0&c and &e" + maxTimeout); + return; + } + ChatAPI.sendActionBar(sender, "Please click the input you would like to set."); + setPlayer((Player) sender, destroyingInput, secondsOff, secondsOn); + } + + public void setPlayer(Player player, boolean destroying, double timeoutOff, double timeoutOn) + { + SpamInput input = null; + if (!destroying) + { + input = new SpamInput(player.getUniqueId().toString(), timeoutOff, timeoutOn, 0); + } + players.put(player, input); + } + + public boolean attemptInputRegister(Player player, Block block, Cancellable event) + { + if (players.containsKey(player)) + { + if (!acceptedInputs.contains(block.getType())) + { + ChatAPI.sendActionBar(player, "&cThat block is not an acceptable input!"); + return true; + } + String typeStr = block.getType().toString().toLowerCase().replace("_", " "); + String locationStr = locationString(block.getLocation()); + changingInput = true; + boolean buildCheck = canBuild(player, block); + changingInput = false; + if (!buildCheck) + { + ChatAPI.sendActionBar(player, + "&cSomething went wrong trying to change the timeout of the " + typeStr + "!"); + event.setCancelled(true); + return true; + } + SpamInput input = players.get(player); + if (input == null) + { + if (!inputs.containsKey(locationStr)) + { + ChatAPI.sendActionBar(player, + "&cSomething went wrong trying to change the timeout of the" + typeStr + "!"); + event.setCancelled(true); + return true; + } + inputs.remove(locationStr); + ChatAPI.sendActionBar(player, "&7Successfully removed the timeout for the " + typeStr); + } + else + { + inputs.put(locationStr, players.get(player)); + ChatAPI.sendActionBar(player, "&7Successfully removed the timeout for the " + typeStr); + } + event.setCancelled(true); + players.remove(player); + saveInputs(); + return true; + } + return false; + } + + public void checkBlockBreak(BlockBreakEvent event, Block block) + { + if (!acceptedInputs.contains(block.getType())) + return; + String posStr = locationString(block.getLocation()); + if (!inputs.containsKey(posStr)) + return; + SpamInput input = inputs.get(posStr); + Player sender = event.getPlayer(); + String typeStr = block.getType().toString().toLowerCase().replace("_", " "); + String inputStr = (block.getLocation().equals(event.getBlock()) ? "this " + typeStr + : "the " + typeStr + " attached to that block"); + if (!sender.isSneaking()) + { + ChatAPI.sendActionBar(sender, "&7To destroy " + inputStr + ", hold &esneak&7 while breaking it."); + event.setCancelled(true); + return; + } + if (sender.hasPermission("damnspam.admin") || sender.getUniqueId().toString().equals(input.player)) + { + inputs.remove(posStr); + saveInputs(); + ChatAPI.sendActionBar(sender, "&7Succesfully destroyed the" + typeStr + "."); + } + else + { + ChatAPI.sendActionBar(sender, "You are not allowed to remove " + inputStr); + event.setCancelled(true); + } + } + + @SuppressWarnings("deprecation") + public List<Block> getAttachedBlocks(Block block) + { + List<Block> blocks = new ArrayList<Block>(); + BlockFace[] directions = {BlockFace.DOWN, BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.WEST, + BlockFace.EAST}; + for (int i = 0; i < directions.length; i++) + { + Block side = block.getRelative(directions[i]); + int[][] dvalues = attachedBlocks.get(side.getType()); + if (dvalues != null) + { + boolean onSide = false; + for (int val : dvalues[i]) + { + if (side.getData() == (byte) val) + { + onSide = true; + break; + } + } + if (onSide) + blocks.add(side); + } + } + return blocks; + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onBreak(BlockBreakEvent event) + { + if (changingInput || event.isCancelled()) + return; + boolean register = attemptInputRegister(event.getPlayer(), event.getBlock(), event); + if (!register) + { + Block block = event.getBlock(); + checkBlockBreak(event, block); + for (Block affected : getAttachedBlocks(block)) + { + checkBlockBreak(event, affected); + } + } + } + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.HIGHEST) + public void onInteract(PlayerInteractEvent event) + { + if (event.getClickedBlock() == null) + return; + boolean register = attemptInputRegister(event.getPlayer(), event.getClickedBlock(), event); + if (!register && event.getAction().equals(Action.RIGHT_CLICK_BLOCK) && !event.isCancelled()) + { + Player sender = event.getPlayer(); + Block block = event.getClickedBlock(); + String posStr = locationString(block.getLocation()); + SpamInput data = inputs.get(posStr); + if (data != null) + { + String btype = block.getType().toString().toLowerCase().replace("_", " "); + double checktime = 0; + if (btype.equals("lever") && block.getData() < 8) + checktime = data.timeoutOff; + else + checktime = data.timeoutOn; + double timeLeft = (data.lastTime + checktime) + - ((double) Math.round((double) System.currentTimeMillis() / 10) / 100); + timeLeft = (double) Math.round(timeLeft * 100) / 100; + if (checktime == -1) + { + event.setCancelled(true); + ChatAPI.sendActionBar(sender, "&7This " + btype + " is locked permanently by /damnspam."); + } + else if (timeLeft > 0) + { + event.setCancelled(true); + ChatAPI.sendActionBar(sender, "&7This " + btype + " has a damnspam timeout of &e" + checktime + "&7, with &e" + + timeLeft + "&7 left."); + } + else + { + data.lastTime = (double) Math.round((double) System.currentTimeMillis() / 10) / 100; + } + inputs.put(posStr, data); + } + } + } +} diff --git a/src/main/java/com/redstoner/modules/damnspam/SpamInput.java b/src/main/java/com/redstoner/modules/damnspam/SpamInput.java new file mode 100644 index 0000000..9735dd9 --- /dev/null +++ b/src/main/java/com/redstoner/modules/damnspam/SpamInput.java @@ -0,0 +1,17 @@ +package com.redstoner.modules.damnspam; + +public class SpamInput { + + protected String player; + protected double timeoutOn; + protected double timeoutOff; + protected double lastTime; + + protected SpamInput(String player, double timeoutOff, double timeoutOn, double lastTime) { + this.player = player; + this.timeoutOff = timeoutOff; + this.timeoutOn = timeoutOn; + this.lastTime = lastTime; + } + +} diff --git a/src/main/java/com/redstoner/modules/datamanager/DataManager.cmd b/src/main/java/com/redstoner/modules/datamanager/DataManager.cmd new file mode 100644 index 0000000..f7d480a --- /dev/null +++ b/src/main/java/com/redstoner/modules/datamanager/DataManager.cmd @@ -0,0 +1,34 @@ +command data { + import [string:file] as [string:module] { + run import_file file module; + type console; + } +} + +command config { + alias configs; + alias setting; + alias settings; + perm datamanager.admin; + list { + run config_list; + help Lists all modules that have at least one config setting.; + } + list [string:module] { + run config_list2 module; + help Lists all config settings of the specified module.; + } + get [string:module] [string:key] { + run config_get module key; + help Displays the value of the specified setting.; + } + set [string:module] [string:key] [string:value...] { + run config_set module key value; + help Assigns a new value to the given setting.; + } + remove_all [string:module] { + run config_remove_all module; + type console; + help Deletes all config settings of a given module.; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/datamanager/DataManager.java b/src/main/java/com/redstoner/modules/datamanager/DataManager.java new file mode 100644 index 0000000..63ce1ce --- /dev/null +++ b/src/main/java/com/redstoner/modules/datamanager/DataManager.java @@ -0,0 +1,1029 @@ +package com.redstoner.modules.datamanager; + +import java.io.File; +import java.io.FilenameFilter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.server.TabCompleteEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.CommandManager; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.misc.Utils; +import com.redstoner.modules.CoreModule; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.Stream) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 10, compatible = 4) +public final class DataManager implements CoreModule, Listener +{ + protected final File dataFolder = new File(Main.plugin.getDataFolder(), "data"); + protected JSONObject data = new JSONObject(); + protected JSONObject config_data; + protected ArrayList<String> module_index; + int old_hash = 0; + protected HashMap<String, HashMap<String, Boolean>> states = new HashMap<>(); + private static DataManager previous_instance = null; + protected ArrayList<String> subcommands; + protected List<String> scheduled_saves = new ArrayList<>(); + int task_id; + + @Override + public void postEnable() + { + if (!dataFolder.exists()) + dataFolder.mkdirs(); + for (Player p : Bukkit.getOnlinePlayers()) + { + loadData_(p.getUniqueId().toString()); + } + subcommands = new ArrayList<>(); + subcommands.add("list"); + subcommands.add("get"); + subcommands.add("set"); + subcommands.add("remove"); + if (previous_instance == null) + states.put(getID(Bukkit.getConsoleSender()), new HashMap<String, Boolean>()); + else + { + this.states = previous_instance.states; + previous_instance = null; + } + config_data = JsonManager.getObject(new File(dataFolder, "configs.json")); + if (config_data == null) + config_data = new JSONObject(); + fixJson(); + updateIndex(); + CommandManager.registerCommand(getClass().getResourceAsStream("DataManager.cmd"), this, Main.plugin); + + // Schedule save every ten seconds + task_id = Bukkit.getScheduler().runTaskTimerAsynchronously(Main.plugin, new Runnable() + { + @Override + public void run() + { + for (String id : scheduled_saves) + { + Object raw = data.get(id); + if (raw == null || ((JSONObject) raw).size() == 0) + continue; + JSONObject json = (JSONObject) raw; + JsonManager.save(json, new File(dataFolder, id + ".json")); + } + scheduled_saves.clear(); + } + }, 0, 20).getTaskId(); + } + + @Override + public void onDisable() + { + previous_instance = this; + for (Player p : Bukkit.getOnlinePlayers()) + { + saveAndUnload(p); + } + JsonManager.save(config_data, new File(dataFolder, "configs.json")); + Bukkit.getScheduler().cancelTask(task_id); + } + + @Command(hook = "import_file") + public boolean importFile(CommandSender sender, String file, String module) + { + try + { + JSONObject object = JsonManager.getObject(new File(file)); + importObject_(module, object); + } + catch (Exception e) + { + getLogger().error("Could not import data!"); + } + return true; + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) + { + loadData_(event.getPlayer().getUniqueId().toString()); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) + { + saveAndUnload(event.getPlayer()); + } + + public static void loadData(CommandSender sender) + { + loadData(getID(sender)); + } + + public static void loadData(String id) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("loadData_", String.class); + m.setAccessible(true); + m.invoke(mod, id); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + @SuppressWarnings("unchecked") + protected synchronized void loadData_(String id) + { + JSONObject playerData = JsonManager.getObject(new File(dataFolder, id + ".json")); + if (playerData == null) + playerData = new JSONObject(); + data.put(id.toString(), playerData); + states.put(id.toString(), new HashMap<String, Boolean>()); + } + + public static Object getOrDefault(CommandSender sender, String key, Object fallback) + { + return getOrDefault(getID(sender), Utils.getCaller("DataManager"), key, fallback); + } + + public static Object getOrDefault(String id, String key, Object fallback) + { + return getOrDefault(id, Utils.getCaller("DataManager"), key, fallback); + } + + public static Object getOrDefault(String id, String module, String key, Object fallback) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("getOrDefault_", String.class, String.class, String.class, + Object.class); + m.setAccessible(true); + return m.invoke(mod, id, module, key, fallback); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + return fallback; + } + + protected Object getOrDefault_(String id, String module, String key, Object fallback) + { + Object o = getData_(id, module, key); + return o == null ? fallback : o; + } + + public static Object getData(CommandSender sender, String key) + { + return getData(getID(sender), Utils.getCaller("DataManager"), key); + } + + public static Object getData(String id, String key) + { + return getData(id, Utils.getCaller("DataManager"), key); + } + + public static Object getData(String id, String module, String key) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("getData_", String.class, String.class, String.class); + m.setAccessible(true); + return m.invoke(mod, id, module, key); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + return null; + } + + protected Object getData_(String id, String module, String key) + { + if (data.containsKey(id)) + { + JSONObject moduleData = ((JSONObject) ((JSONObject) data.get(id)).get(module)); + if (moduleData == null) + return null; + if (key == null) + return moduleData; + else + return moduleData.get(key); + } + else + return loadAndGet(id, module, key); + } + + protected synchronized Object loadAndGet(String id, String module, String key) + { + JSONObject playerData = JsonManager.getObject(new File(dataFolder, id + ".json")); + if (playerData == null) + return null; + if (key == null) + return playerData.get(module); + else + return ((JSONObject) playerData.get(module)).get(key); + } + + public static void setData(CommandSender sender, String key, Object value) + { + setData(getID(sender), Utils.getCaller("DataManager"), key, value); + } + + public static void setData(String id, String key, Object value) + { + setData(id, Utils.getCaller("DataManager"), key, value); + } + + public static void setData(String id, String module, String key, Object value) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("setData_", String.class, String.class, String.class, + Object.class); + m.setAccessible(true); + m.invoke(mod, id, module, key, value); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + @SuppressWarnings("unchecked") + protected void setData_(String id, String module, String key, Object value) + { + if (data.containsKey(id)) + { + JSONObject moduleData = ((JSONObject) ((JSONObject) data.get(id)).get(module)); + if (moduleData == null) + { + moduleData = new JSONObject(); + ((JSONObject) data.get(id)).put(module, moduleData); + } + if (key == null) + setDirectly_(id, module, value); + else + moduleData.put(key, value); + save_(id); + } + else + loadAndSet(id, module, key, value); + } + + public static void setDirectly(CommandSender sender, Object value) + { + setDirectly(getID(sender), Utils.getCaller("DataManager"), value); + } + + public static void setDirectly(String id, Object value) + { + setDirectly(id, Utils.getCaller("DataManager"), value); + } + + public static void setDirectly(String id, String module, Object value) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("setDirectly_", String.class, String.class, Object.class); + m.setAccessible(true); + m.invoke(mod, id, module, value); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + @SuppressWarnings("unchecked") + protected void setDirectly_(String id, String module, Object value) + { + if (data.containsKey(id)) + { + JSONObject playerdata = (JSONObject) data.get(id); + playerdata.put(module, value); + save_(id); + } + else + loadAndSetDirectly(id, module, value); + } + + @SuppressWarnings("unchecked") + protected synchronized void loadAndSet(String id, String module, String key, Object value) + { + File dataFile = new File(dataFolder, id + ".json"); + JSONObject playerData = JsonManager.getObject(dataFile); + if (playerData == null) + playerData = new JSONObject(); + JSONObject moduleData = ((JSONObject) playerData.get(module)); + if (moduleData == null) + { + moduleData = new JSONObject(); + playerData.put(module, moduleData); + } + moduleData.put(key, value); + JsonManager.save(playerData, dataFile); + } + + @SuppressWarnings("unchecked") + protected void loadAndSetDirectly(String id, String module, Object value) + { + File dataFile = new File(dataFolder, id + ".json"); + JSONObject playerData = JsonManager.getObject(dataFile); + if (playerData == null) + playerData = new JSONObject(); + playerData.put(module, value); + JsonManager.save(playerData, dataFile); + } + + public static void removeData(CommandSender sender, String key) + { + removeData(getID(sender), Utils.getCaller("DataManager"), key); + } + + public static void removeData(String id, String key) + { + removeData(id, Utils.getCaller("DataManager"), key); + } + + public static void removeData(String id, String module, String key) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("removeData_", String.class, String.class, String.class); + m.setAccessible(true); + m.invoke(mod, id, module, key); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + @SuppressWarnings("unchecked") + protected void removeData_(String id, String module, String key) + { + if (data.containsKey(id)) + { + JSONObject moduleData = ((JSONObject) ((JSONObject) data.get(id)).get(module)); + if (moduleData == null) + return; + moduleData.remove(key); + data.put(module, data); + save_(id); + } + else + loadAndRemove(id, module, key); + } + + protected synchronized void loadAndRemove(String id, String module, String key) + { + File dataFile = new File(dataFolder, id + ".json"); + JSONObject playerData = JsonManager.getObject(dataFile); + if (playerData == null) + return; + JSONObject moduleData = ((JSONObject) playerData.get(module)); + if (moduleData == null) + return; + moduleData.remove(key); + JsonManager.save(playerData, dataFile); + } + + public static void importObject(JSONObject object) + { + importObject(object, Utils.getCaller("DataManager")); + } + + public static void importObject(JSONObject object, String module) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("importObject_", String.class, String.class, String.class); + m.setAccessible(true); + m.invoke(mod, module, object); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + protected void importObject_(String module, JSONObject object) + { + for (Object o : object.keySet()) + { + String uid = null; + if (o instanceof String) + uid = (String) o; + else if (o instanceof UUID) + uid = ((UUID) o).toString(); + if (uid == null) + continue; + setDirectly_(uid, module, object.get(o)); + } + } + + public static void migrateAll(String oldName) + { + migrateAll(oldName, Utils.getCaller("DataManager")); + } + + public static void migrateAll(String oldName, String newName) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("migrateAll_", String.class, String.class); + m.setAccessible(true); + m.invoke(mod, oldName, newName); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + protected void migrateAll_(String oldName, String newName) + { + for (String s : dataFolder.list(new FilenameFilter() + { + @Override + public boolean accept(File dir, String name) + { + return name.endsWith(".json"); + } + })) + { + migrate_(s.replace(".json", ""), oldName, newName); + } + } + + public static void migrate(String id, String oldName) + { + migrate(id, oldName, Utils.getCaller("DataManager")); + } + + public static void migrate(String id, String oldName, String newName) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("migrate_", String.class, String.class, String.class); + m.setAccessible(true); + m.invoke(mod, id, oldName, newName); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + @SuppressWarnings("unchecked") + protected void migrate_(String id, String oldName, String newName) + { + if (data.containsKey(id)) + { + data.put(newName, data.get(oldName)); + data.remove(oldName); + save_(id); + } + else + loadAndMigrate(id, oldName, newName); + } + + @SuppressWarnings("unchecked") + protected void loadAndMigrate(String id, String oldName, String newName) + { + File dataFile = new File(dataFolder, id + ".json"); + JSONObject data = JsonManager.getObject(dataFile); + data.put(newName, data.get(oldName)); + data.remove(oldName); + JsonManager.save(data, dataFile); + } + + public static void save(CommandSender sender) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("save_", CommandSender.class); + m.setAccessible(true); + m.invoke(mod, sender); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + protected void save_(CommandSender sender) + { + save_(getID(sender)); + } + + public static void save(String id) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("save_", String.class); + m.setAccessible(true); + m.invoke(mod, id); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + protected void save_(String id) + { + scheduled_saves.add(id); + } + + protected void saveAndUnload(CommandSender sender) + { + saveAndUnload(getID(sender)); + states.remove(getID(sender)); + } + + protected void saveAndUnload(String id) + { + save_(id); + data.remove(id); + } + + private static String getID(CommandSender sender) + { + String id; + if (sender instanceof Player) + id = ((Player) sender).getUniqueId().toString(); + else + id = "CONSOLE"; + return id; + } + + public static void setState(CommandSender sender, String key, boolean value) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("setState_", CommandSender.class, String.class, boolean.class); + m.setAccessible(true); + m.invoke(mod, sender, key, value); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + protected void setState_(CommandSender sender, String key, boolean value) + { + String id = getID(sender); + HashMap<String, Boolean> lstates = states.get(id); + lstates.put(key, value); + states.put(id, lstates); + } + + public static boolean getState(CommandSender sender, String key) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("getState_", CommandSender.class, String.class); + m.setAccessible(true); + return (boolean) m.invoke(mod, sender, key); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + return false; + } + + protected boolean getState_(CommandSender sender, String key) + { + String id = getID(sender); + HashMap<String, Boolean> lstates = states.get(id); + if (lstates == null) + return false; + return lstates.containsKey(key) ? lstates.get(key) : false; + } + + protected boolean hasConfigChanged() + { + return old_hash != config_data.hashCode(); + } + + protected void updateIndex() + { + if (!hasConfigChanged()) + return; + old_hash = config_data.hashCode(); + module_index = new ArrayList<>(); + if (config_data.size() > 0) + { + for (Object key : config_data.keySet()) + module_index.add(key.toString()); + } + } + + @SuppressWarnings("unchecked") + protected void fixJson() + { + for (Object key : config_data.keySet()) + { + JSONObject json = (JSONObject) config_data.get(key); + for (Object key2 : json.keySet()) + { + Object o = json.get(key2); + if (!(o instanceof ConfigEntry)) + json.put(key2, new ConfigEntry((JSONObject) o)); + } + config_data.put(key, json); + } + } + + private List<String> subsetWhereStartsWith(List<String> list, String prefix) + { + ArrayList<String> subset = new ArrayList<>(); + if (prefix == null || prefix.equals("")) + return list; + for (String s : list) + if (s.toLowerCase().startsWith(prefix.toLowerCase())) + subset.add(s); + return subset; + } + + @SuppressWarnings("unchecked") + @EventHandler + public void onTabComplete(TabCompleteEvent event) + { + if (event.getBuffer().toLowerCase().matches("^/?settings? .*") + || event.getBuffer().toLowerCase().matches("^/?configs? .*")) + { + boolean argument_complete = event.getBuffer().endsWith(" "); + String[] arguments = event.getBuffer().split(" "); + event.setCompletions(new ArrayList<String>()); + if (arguments.length == 1 || (arguments.length == 2 && !argument_complete)) + event.setCompletions(subsetWhereStartsWith(subcommands, arguments.length >= 2 ? arguments[1] : "")); + else if (arguments.length == 2 || (arguments.length == 3 && !argument_complete)) + { + switch (arguments[1].toLowerCase()) + { + case "list": + case "get": + case "set": + { + event.setCompletions( + subsetWhereStartsWith(module_index, arguments.length == 3 ? arguments[2] : "")); + break; + } + } + } + else if ((arguments.length == 3 && argument_complete) || (arguments.length == 4 && !argument_complete)) + { + switch (arguments[1].toLowerCase()) + { + case "get": + case "set": + { + Object o = config_data.get(arguments[2]); + if (o == null) + break; + event.setCompletions(subsetWhereStartsWith(new ArrayList<String>(((JSONObject) o).keySet()), + arguments.length == 4 ? arguments[3] : "")); + break; + } + } + } + else + { + if (arguments[1].toLowerCase().equals("set")) + { + Object o = config_data.get(arguments[2]); + if (o == null) + return; + Object o2 = ((JSONObject) o).get(arguments[3]); + if (o2 == null) + return; + event.setCompletions(subsetWhereStartsWith(Arrays.asList(((ConfigEntry) o2).getCompleteOptions()), + arguments.length > 4 ? String.join(" ", Arrays.copyOfRange(arguments, 4, arguments.length)) + : "")); + } + } + } + } + + @Command(hook = "config_list") + public boolean list(CommandSender sender) + { + getLogger().message(sender, Arrays.toString(module_index.toArray(new String[] {}))); + return true; + } + + @Command(hook = "config_list2") + public boolean list(CommandSender sender, String module) + { + Object o = config_data.get(module); + if (o == null) + { + getLogger().message(sender, "This module has not registered any settings."); + } + else + { + ArrayList<String> entries = new ArrayList<>(); + JSONObject json = (JSONObject) o; + for (Object key : json.keySet()) + { + String entry = key.toString(); + entries.add("§e" + entry + "§7"); + } + getLogger().message(sender, "The module §e" + module + "§7 has the following config settings: ", + Arrays.toString(entries.toArray(new String[] {}))); + } + return true; + } + + @Command(hook = "config_get") + public boolean get(CommandSender sender, String module, String key) + { + getLogger().message(sender, new String[] {"§e" + module + "." + key + "§7 currently holds the value:", + getConfigOrDefault_(module, key, "<empty>").toString()}); + return true; + } + + @Command(hook = "config_set") + public boolean set(CommandSender sender, String module, String key, String value) + { + if (setConfig_(module, key, value)) + { + getLogger().message(sender, "Successfully changed the value for §e" + module + "." + key); + } + else + { + getLogger().message(sender, true, + "§7\"§e" + value + "§7\" is not a valid value for setting §e" + module + "." + key); + } + return true; + } + + @Command(hook = "config_remove_all") + public boolean remove_all(CommandSender sender, String module) + { + if (removeAllConfig_(module)) + getLogger().message(sender, "Successfully deleted all config entries for module §e" + module + "§7!"); + else + getLogger().message(sender, true, "Could not delete all config entries for module §e" + module + "§7!"); + return true; + } + + public static Object getConfigOrDefault(String key, Object fallback) + { + return getConfigOrDefault(Utils.getCaller("DataManager"), key, fallback); + } + + public static Object getConfigOrDefault(String module, String key, Object fallback) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("getConfigOrDefault_", String.class, String.class, + Object.class); + m.setAccessible(true); + return m.invoke(mod, module, key, fallback); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + return fallback; + } + + protected Object getConfigOrDefault_(String module, String key, Object fallback) + { + Object o = getConfigData_(module, key); + return o == null ? fallback : o; + } + + protected Object getConfigData_(String module, String key) + { + module = module.toLowerCase(); + Object o = config_data.get(module); + if (o == null) + return null; + else + { + JSONObject json = (JSONObject) o; + Object o2 = json.get(key); + if (o2 == null) + return null; + return ((ConfigEntry) o2).getValue(); + } + } + + protected ConfigEntry getConfigEntry_(String module, String key) + { + module = module.toLowerCase(); + Object o = config_data.get(module); + if (o == null) + return null; + else + { + JSONObject json = (JSONObject) o; + return (ConfigEntry) json.get(key); + } + } + + public static void setConfig(String key, String value) + { + setConfig(Utils.getCaller("DataManager"), key, value, null); + } + + public static void setConfig(String key, String value, String[] complete_options) + { + setConfig(Utils.getCaller("DataManager"), key, value, complete_options); + } + + public static void setConfig(String module, String key, String value, String[] complete_options) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("setConfig_", String.class, String.class, String.class, + String[].class); + m.setAccessible(true); + m.invoke(mod, module, key, value, complete_options); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + @SuppressWarnings("unchecked") + protected boolean setConfig_(String module, String key, String value) + { + module = module.toLowerCase(); + ConfigEntry entry = getConfigEntry_(module, key); + if (entry == null) + entry = new ConfigEntry(value, null); + if (entry.attemptSet(value)) + { + Object o = config_data.get(module); + JSONObject json; + if (o == null) + json = new JSONObject(); + else + json = (JSONObject) o; + json.put(key, entry); + config_data.put(module, json); + updateIndex(); + return true; + } + else + return false; + } + + @SuppressWarnings("unchecked") + protected void setConfig_(String module, String key, String value, String[] complete_options) + { + module = module.toLowerCase(); + ConfigEntry entry = new ConfigEntry(value, complete_options); + Object o = config_data.get(module); + JSONObject json; + if (o == null) + json = new JSONObject(); + else + json = (JSONObject) o; + json.put(key, entry); + config_data.put(module, json); + updateIndex(); + } + + public static boolean removeConfig(String key) + { + return removeConfig(Utils.getCaller("DataManager"), key); + } + + public static boolean removeConfig(String module, String key) + { + try + { + Module mod = ModuleLoader.getModule("DataManager"); + Method m = mod.getClass().getDeclaredMethod("removeConfig_", String.class, String.class); + m.setAccessible(true); + return (boolean) m.invoke(mod, module, key); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + return false; + } + + @SuppressWarnings("unchecked") + protected boolean removeConfig_(String module, String key) + { + module = module.toLowerCase(); + if (key == null) + return removeAllConfig_(module); + Object o = config_data.get(module); + JSONObject json; + if (o == null) + return false; + else + json = (JSONObject) o; + json.remove(key); + if (json.size() == 0) + config_data.remove(module); + else + config_data.put(module, json); + updateIndex(); + return true; + } + + protected boolean removeAllConfig_(String module) + { + module = module.toLowerCase(); + if (config_data.remove(module) == null) + return false; + updateIndex(); + return true; + } +} + +class ConfigEntry +{ + private String value; + private String[] complete_options; + + public ConfigEntry(String value, String[] complete_options) + { + this.value = value; + this.complete_options = complete_options; + } + + @SuppressWarnings("unchecked") + public ConfigEntry(JSONObject json) + { + this(json.get("value").toString(), + (String[]) ((JSONArray) json.get("complete_options")).toArray(new String[] {})); + } + + protected boolean attemptSet(String value) + { + if (complete_options == null || complete_options.length == 0) + { + this.value = value; + return true; + } + else + { + for (String s : complete_options) + { + if (s.equals(value)) + { + this.value = value; + return true; + } + } + return false; + } + } + + protected String[] getCompleteOptions() + { + return complete_options; + } + + protected String getValue() + { + return value; + } + + @Override + public String toString() + { + return "{\"value\":\"" + value + "\",\"complete_options\":" + + (complete_options == null || complete_options.length == 0 ? "[]" + : "[\"" + String.join("\",\"", complete_options) + "\"]") + + "}"; + } +} diff --git a/src/main/java/com/redstoner/modules/discord/Discord.cmd b/src/main/java/com/redstoner/modules/discord/Discord.cmd new file mode 100644 index 0000000..a3e1af5 --- /dev/null +++ b/src/main/java/com/redstoner/modules/discord/Discord.cmd @@ -0,0 +1,8 @@ +command discord { + [empty] { + perm utils.external.discord + help Info, Register Instructions, and Token for the Discord; + run discord; + type player; + } +} diff --git a/src/main/java/com/redstoner/modules/discord/Discord.java b/src/main/java/com/redstoner/modules/discord/Discord.java new file mode 100644 index 0000000..9d87bc0 --- /dev/null +++ b/src/main/java/com/redstoner/modules/discord/Discord.java @@ -0,0 +1,118 @@ +package com.redstoner.modules.discord; + +import java.io.File; +import java.security.SecureRandom; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.json.simple.JSONObject; + +import net.nemez.chatapi.click.Message; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 0, compatible = 4) +public class Discord implements Module { + + private final String FILENAME = "discordTokens.json"; + private final String DNE_LINK = "dne://"; + + private JSONObject discordTables; + private JSONObject byToken; + private JSONObject byUUID; + + private String joinLink; + private File savefile; + + private final String tokenCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + private SecureRandom rnd = new SecureRandom(); + + @SuppressWarnings("unchecked") + @Override + public boolean onEnable() { + savefile = new File(Main.plugin.getDataFolder(), FILENAME); + + discordTables = JsonManager.getObject(savefile); + + if (discordTables == null) { + discordTables = new JSONObject(); + discordTables.put("joinLink", DNE_LINK); + save(); + } + + Object joinLinkObject = discordTables.get("joinLink"); + + if (joinLinkObject == null || ((String) joinLinkObject).equals(DNE_LINK)) { + getLogger().error("Missing Join Link. Set: \"joinLink\" to \"_joinLink_\" in the discordTokens.json file."); + return false; + } + + joinLink = (String) joinLinkObject; + + Object byTokenObject = discordTables.get("byToken"); + + if (byTokenObject == null) { + discordTables.put("byToken", new JSONObject()); + discordTables.put("byUUID", new JSONObject()); + } + + byToken = (JSONObject) discordTables.get("byToken"); + byUUID = (JSONObject) discordTables.get("byUUID"); + + return true; + + } + + @SuppressWarnings("unchecked") + @Command(hook = "discord") + public void discord(CommandSender sender) { + Player p = (Player) sender; + String pUUID = p.getUniqueId().toString(); + + Object tokenObject = byUUID.get(pUUID); + String token = tokenObject == null? null : (String) tokenObject; + + if (token == null) { + + token = randomToken(8); + Object UUIDObject = byToken.get(token); + + while (UUIDObject != null) { + token = randomToken(8); + UUIDObject = byToken.get(token); + } + byUUID.put(pUUID, token); + byToken.put(token, pUUID); + save(); + } + + new Message(sender, null).appendText("\n&cRedstoner&7 has a &2Discord&7 Now! \nClick ") + .appendLinkHover("&e" + joinLink, joinLink, "&aClick to Join") + .appendText("&7 to join. \n\nTo sync you rank, copy ") + .appendSuggestHover("&e" + token, token, "&aClick to Copy") + .appendText("&7 into &3#rank-sync&7.\n") + .send(); + } + + private String randomToken(int length){ + StringBuilder sb = new StringBuilder( length ); + for( int i = 0; i < length; i++ ) + sb.append( tokenCharacters.charAt( rnd.nextInt(tokenCharacters.length()) ) ); + return sb.toString(); + } + + @SuppressWarnings("unchecked") + private void save() { + + discordTables.put("byToken", byToken); + discordTables.put("byUUID", byUUID); + JsonManager.save(discordTables, savefile); + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/friends/Friends.cmd b/src/main/java/com/redstoner/modules/friends/Friends.cmd new file mode 100644 index 0000000..ea205c9 --- /dev/null +++ b/src/main/java/com/redstoner/modules/friends/Friends.cmd @@ -0,0 +1,38 @@ +command friends { + add [string:name] { + run add name; + help Adds a friend to your friendlist.; + perm utils.friends; + } + add [string:name] [string:group] { + run add_grouped name group; + help Adds a friend to a group of friends; + perm utils.friends.groups; + } + remove [string:name] { + run del name; + help Removes a friend from your friendlist.; + perm utils.friends; + } + remove [string:name] [string:group] { + run del_grouped name group; + help Removes a friend from a group of friends; + perm utils.friends.groups; + } + list { + run list; + help Shows a list of all your friends.; + perm utils.friends; + } + list [string:group] { + run list_group group; + help Shows a list of all friends in that group.; + perm utils.friends.groups; + } + groups { + run list_groups; + help Shows all your friend groups that have at least one person in them.; + perm utils.friends.groups; + } + type player; +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/friends/Friends.java b/src/main/java/com/redstoner/modules/friends/Friends.java new file mode 100644 index 0000000..2eb9728 --- /dev/null +++ b/src/main/java/com/redstoner/modules/friends/Friends.java @@ -0,0 +1,360 @@ +package com.redstoner.modules.friends; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.Sound; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.CoreModule; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +@AutoRegisterListener +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 0, compatible = 4) +public class Friends implements CoreModule +{ + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerJoin(PlayerJoinEvent e) + { + JSONArray friended_by = (JSONArray) DataManager.getOrDefault(e.getPlayer(), "friended_by", new JSONArray()); + for (Object obj : friended_by) + { + UUID uuid = UUID.fromString((String) obj); + Player p = Bukkit.getPlayer(uuid); + if (p != null && p.canSee(e.getPlayer())) + { + getLogger().message(p, "Your friend &e" + e.getPlayer().getDisplayName() + "&7 just joined!"); + p.playSound(p.getLocation(), Sound.ENTITY_CHICKEN_EGG, 1, 1); + } + } + JSONArray notifications = (JSONArray) DataManager.getOrDefault(e.getPlayer(), "scheduled_notifications", + new JSONArray()); + for (Object obj : notifications) + getLogger().message(e.getPlayer(), (String) obj); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerLeave(PlayerQuitEvent e) + { + JSONArray friended_by = (JSONArray) DataManager.getOrDefault(e.getPlayer(), "friended_by", new JSONArray()); + for (Object obj : friended_by) + { + UUID uuid = UUID.fromString((String) obj); + Player p = Bukkit.getPlayer(uuid); + if (p != null && p.canSee(e.getPlayer())) + { + getLogger().message(p, "Your friend &e" + e.getPlayer().getDisplayName() + "&7 just left!"); + p.playSound(p.getLocation(), Sound.ENTITY_CHICKEN_EGG, 1, 1); + } + } + } + + @SuppressWarnings({"unchecked", "deprecation"}) + @Command(hook = "add") + public boolean add(CommandSender sender, String target) + { + if (target.equalsIgnoreCase("CONSOLE")) + { + getLogger().message(sender, true, "You can't add console to your friends!"); + return true; + } + OfflinePlayer p = Bukkit.getPlayer(target); + if (p == null) + p = Bukkit.getOfflinePlayer(target); + if (p == null) + { + getLogger().message(sender, true, "That player couldn't be found!"); + return true; + } + JSONArray friends = ((JSONArray) DataManager.getOrDefault(sender, "friends", new JSONArray())); + if (friends.contains(p.getUniqueId().toString())) + { + getLogger().message(sender, true, "You are already friends with this person!"); + return true; + } + friends.add(p.getUniqueId().toString()); + DataManager.save(sender); + JSONArray friended_by = ((JSONArray) DataManager.getOrDefault(p.getUniqueId().toString(), "friended_by", + new JSONArray())); + friended_by.add(getID(sender)); + DataManager.save(p.getUniqueId().toString()); + getLogger().message(sender, "You are now friends with &e" + p.getName() + "&7!"); + if (p instanceof Player) + { + getLogger().message((Player) p, "&e" + Utils.getName(sender) + "&7 added you as a friend!"); + } + else + { + JSONArray notifications = (JSONArray) DataManager.getOrDefault(p.getUniqueId().toString(), + "scheduled_notifications", new JSONArray()); + notifications.add("&e" + Utils.getName(sender) + "&7 added you as a friend!"); + notifications.remove("&e" + Utils.getName(sender) + "&7 removed you as a friend!"); + DataManager.setData(p.getUniqueId().toString(), "scheduled_notifications", notifications); + } + return true; + } + + @SuppressWarnings({"deprecation", "unchecked"}) + @Command(hook = "add_grouped") + public boolean add_grouped(CommandSender sender, String target, String group) + { + if (target.equalsIgnoreCase("CONSOLE")) + { + getLogger().message(sender, true, "You can't add console to your friends!"); + return true; + } + OfflinePlayer p = Bukkit.getPlayer(target); + if (p == null) + p = Bukkit.getOfflinePlayer(target); + if (p == null) + { + getLogger().message(sender, true, "That player couldn't be found!"); + return true; + } + JSONArray friends = ((JSONArray) DataManager.getOrDefault(sender, "groups." + group, new JSONArray())); + if (friends.contains(p.getUniqueId().toString())) + { + getLogger().message(sender, true, "This person already is part of that friendsgroup!"); + return true; + } + friends.add(p.getUniqueId().toString()); + DataManager.save(sender); + getLogger().message(sender, "&e" + p.getName() + "&7 is now part of the group &e" + group + "&7!"); + if (p instanceof Player) + { + getLogger().message((Player) p, + "&e" + Utils.getName(sender) + " &7added you to their friendsgroup &e" + group + "&7!"); + } + else + { + JSONArray notifications = (JSONArray) DataManager.getOrDefault(p.getUniqueId().toString(), + "scheduled_notifications", new JSONArray()); + notifications.add("&e" + Utils.getName(sender) + " &7added you to their friendsgroup &e" + group + "&7!"); + notifications + .remove("&e" + Utils.getName(sender) + " &7removed you from their friendsgroup &e" + group + "&7!"); + DataManager.setData(p.getUniqueId().toString(), "scheduled_notifications", notifications); + } + return true; + } + + @SuppressWarnings({"deprecation", "unchecked"}) + @Command(hook = "del") + public boolean del(CommandSender sender, String target) + { + if (target.equalsIgnoreCase("CONSOLE")) + { + getLogger().message(sender, true, "You can't add console to your friends!"); + return true; + } + OfflinePlayer p = Bukkit.getPlayer(target); + if (p == null) + p = Bukkit.getOfflinePlayer(target); + if (p == null) + { + getLogger().message(sender, true, "That player couldn't be found!"); + return true; + } + JSONArray friends = ((JSONArray) DataManager.getOrDefault(sender, "friends", new JSONArray())); + if (friends.contains(p.getUniqueId().toString())) + { + getLogger().message(sender, true, "You are already friends with this person!"); + return true; + } + friends.remove(p.getUniqueId().toString()); + DataManager.save(sender); + JSONArray friended_by = ((JSONArray) DataManager.getOrDefault(p.getUniqueId().toString(), "friended_by", + new JSONArray())); + friended_by.remove(getID(sender)); + DataManager.save(p.getUniqueId().toString()); + getLogger().message(sender, "You are now friends with &e" + p.getName() + "&7!"); + if (p instanceof Player) + { + getLogger().message((Player) p, "&e" + Utils.getName(sender) + "&7 added you as a friend!"); + } + else + { + JSONArray notifications = (JSONArray) DataManager.getOrDefault(p.getUniqueId().toString(), + "scheduled_notifications", new JSONArray()); + notifications.add("&e" + Utils.getName(sender) + "&7 removed you as a friend!"); + notifications.remove("&e" + Utils.getName(sender) + "&7 added you as a friend!"); + DataManager.setData(p.getUniqueId().toString(), "scheduled_notifications", notifications); + } + return true; + } + + @SuppressWarnings({"deprecation", "unchecked"}) + @Command(hook = "del_grouped") + public boolean del_grouped(CommandSender sender, String target, String group) + { + if (target.equalsIgnoreCase("CONSOLE")) + { + getLogger().message(sender, true, "You can't add console to your friends!"); + return true; + } + OfflinePlayer p = Bukkit.getPlayer(target); + if (p == null) + p = Bukkit.getOfflinePlayer(target); + if (p == null) + { + getLogger().message(sender, true, "That player couldn't be found!"); + return true; + } + JSONArray friends = ((JSONArray) DataManager.getOrDefault(sender, "groups." + group, new JSONArray())); + if (friends.contains(p.getUniqueId().toString())) + { + getLogger().message(sender, true, "This person already is part of that friendsgroup!"); + return true; + } + friends.add(p.getUniqueId().toString()); + DataManager.save(sender); + getLogger().message(sender, "&e" + p.getName() + "&7 is now part of the group &e" + group + "&7!"); + if (p instanceof Player) + { + getLogger().message((Player) p, + "&e" + Utils.getName(sender) + " &7added you to their friendsgroup &e" + group + "&7!"); + } + else + { + JSONArray notifications = (JSONArray) DataManager.getOrDefault(p.getUniqueId().toString(), + "scheduled_notifications", new JSONArray()); + notifications + .add("&e" + Utils.getName(sender) + " &7removed you from their friendsgroup &e" + group + "&7!"); + notifications + .remove("&e" + Utils.getName(sender) + " &7added you to their friendsgroup &e" + group + "&7!"); + DataManager.setData(p.getUniqueId().toString(), "scheduled_notifications", notifications); + } + return true; + } + + @Command(hook = "list") + public boolean list(CommandSender sender) + { + JSONArray friends = (JSONArray) DataManager.getOrDefault(sender, "friends", new JSONArray()); + if (friends.size() == 0) + { + getLogger().message(sender, true, "You didn't add anyone to your friendslist yet."); + } + else + { + StringBuilder sb = new StringBuilder(); + for (Object o : friends.toArray()) + { + UUID id = UUID.fromString((String) o); + Player p = Bukkit.getPlayer(id); + if (p != null) + sb.append(p.getDisplayName() + "&7, "); + else + sb.append("&9" + Bukkit.getOfflinePlayer(id).getName() + "&7, "); + } + String out = sb.toString().replaceAll(", $", ""); + getLogger().message(sender, "You have a total of &e" + friends.size() + "&7 friends:", out); + } + return true; + } + + @Command(hook = "list_group") + public boolean list_group(CommandSender sender, String group) + { + JSONArray friends = (JSONArray) DataManager.getOrDefault(sender, "group." + group, new JSONArray()); + if (friends.size() == 0) + { + getLogger().message(sender, true, "You didn't add anyone to this group yet."); + } + else + { + StringBuilder sb = new StringBuilder(); + for (Object o : friends.toArray()) + { + UUID id = UUID.fromString((String) o); + Player p = Bukkit.getPlayer(id); + if (p != null) + sb.append(p.getDisplayName() + "&7, "); + else + sb.append("&9" + Bukkit.getOfflinePlayer(id).getName() + "&7, "); + } + String out = sb.toString().replaceAll(", $", ""); + getLogger().message(sender, "You have a total of &e" + friends.size() + "&7 friends added to this group:", out); + } + return true; + } + + @Command(hook = "list_groups") + public boolean list_groups(CommandSender sender) + { + JSONObject raw = (JSONObject) DataManager.getOrDefault(sender, null, new JSONObject()); + Set<?> keys = raw.keySet(); + if (keys.size() == 0 || (keys.contains("friends") && keys.size() == 1)) + { + getLogger().message(sender, true, "You don't have any custom groups made yet."); + return true; + } + else + { + StringBuilder sb = new StringBuilder(); + for (Object o : keys) + { + sb.append("&e" + (String) o + "&7, "); + } + String out = sb.toString().replaceAll(", $", ""); + getLogger().message(sender, "", out); + } + return true; + } + + public static boolean isFriend(CommandSender player, CommandSender friend) + { + return isFriend(player, friend, null); + } + + public static boolean isFriend(CommandSender player, CommandSender friend, String condition) + { + try + { + Module mod = ModuleLoader.getModule("Friends"); + Method m = mod.getClass().getDeclaredMethod("isFriend_", String.class); + return (boolean) m.invoke(mod, player, friend, condition); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + return false; + } + + protected boolean isFriend_(CommandSender player, CommandSender friend, String group) + { + if (group == null) + group = "friends"; + else if (!group.startsWith("group.")) + group = "group." + group; + JSONArray array = (JSONArray) DataManager.getOrDefault(player, group, new JSONArray()); + return array.contains(getID(friend)); + } + + private final String getID(CommandSender sender) + { + if (sender instanceof Player) + return ((Player) sender).getUniqueId().toString(); + else + return sender.getName(); + } +} diff --git a/src/main/java/com/redstoner/modules/ignore/Ignore.cmd b/src/main/java/com/redstoner/modules/ignore/Ignore.cmd new file mode 100644 index 0000000..382846b --- /dev/null +++ b/src/main/java/com/redstoner/modules/ignore/Ignore.cmd @@ -0,0 +1,22 @@ +command ignore { + [string:player] { + perm utils.ignore; + run ignore player; + type player; + help Ignores or Unignores a player.; + } + [empty] { + perm utils.ignore; + run list; + type player; + help Lists everyone you ignore.; + } +} +command unignore { + [string:player] { + perm utils.ignore; + run unignore player; + type player; + help Unignore a player.; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/ignore/Ignore.java b/src/main/java/com/redstoner/modules/ignore/Ignore.java new file mode 100644 index 0000000..c830700 --- /dev/null +++ b/src/main/java/com/redstoner/modules/ignore/Ignore.java @@ -0,0 +1,159 @@ +package com.redstoner.modules.ignore; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.json.simple.JSONArray; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +import net.nemez.chatapi.click.Message; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 0, revision = 0, compatible = 4) +public class Ignore implements Module +{ + + @Command(hook = "unignore", async = AsyncType.ALWAYS) + public boolean unignore(CommandSender sender, String player) + { + return ignore(sender, player, false); + } + + @Command(hook = "ignore", async = AsyncType.ALWAYS) + public boolean ignore(CommandSender sender, String player) + { + return ignore(sender, player, true); + } + + @Command(hook = "list", async = AsyncType.ALWAYS) + public boolean list(CommandSender sender) + { + getLogger().message(sender, "§7You are currently ignoring:"); + + JSONArray ignores = (JSONArray) DataManager.getOrDefault(sender, "ignores", new JSONArray()); + + if (ignores.isEmpty()) + { + new Message(sender, null).appendText(" §7Nobody \\o/").send(); + return true; + } + + String players; + OfflinePlayer pi = Bukkit.getOfflinePlayer(UUID.fromString((String) ignores.get(0))); + players = " §3" + pi.getName() + "§7"; + + for (int i = 1; i < ignores.size(); i++) + { + OfflinePlayer p = Bukkit.getOfflinePlayer(UUID.fromString((String) ignores.get(i))); + players += ", §3" + p.getName() + "§7"; + } + + Message m = new Message(sender, null); + m.appendText(players); + m.send(); + return true; + } + + @SuppressWarnings({"unchecked", "deprecation"}) + public boolean ignore(CommandSender sender, String player, boolean allowIgnore) + { + JSONArray ignores = (JSONArray) DataManager.getOrDefault(sender, "ignores", new JSONArray()); + + Player p = Utils.isUUID(player) ? Bukkit.getPlayer(UUID.fromString(player)) : Bukkit.getPlayer(player); + + OfflinePlayer op = Utils.isUUID(player) ? Bukkit.getOfflinePlayer(UUID.fromString(player)) + : Bukkit.getOfflinePlayer(player); + + String pName = p != null ? p.getDisplayName() : op.getName(); + String pUUID = p != null ? p.getUniqueId().toString() : op.getUniqueId().toString(); + String sUUID = ((Player) sender).getUniqueId().toString(); + + if (pUUID.equals(sUUID)) + { + getLogger().message(sender, true, "§7You can't ignore yourself :P"); + return true; + } + + if (ignores.contains(pUUID)) + { + ignores.remove(pUUID); + getLogger().message(sender, "§7You are no longer ignoring §3" + pName + "§7."); + } + else if (!allowIgnore) + { + getLogger().message(sender, "§7You weren't ignoring §3" + pName + "§7."); + } + else + { + ignores.add(pUUID); + getLogger().message(sender, "§7You are now ignoring §3" + pName + "§7."); + } + DataManager.setData(sender, "ignores", ignores); + return true; + + } + + public static BroadcastFilter getIgnoredBy(CommandSender sender) + { + try + { + Module mod = ModuleLoader.getModule("Ignore"); + Method m = mod.getClass().getDeclaredMethod("_getIgnoredBy", CommandSender.class); + m.setAccessible(true); + return (BroadcastFilter) m.invoke(mod, sender); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + return null; + } + + @SuppressWarnings("unused") + private BroadcastFilter _getIgnoredBy(CommandSender sender) + { + return new BroadcastFilter() + { + + private final String sUUID = sender instanceof Player ? ((Player) sender).getUniqueId().toString() + : "CONSOLE"; + + @Override + public boolean sendTo(CommandSender recipient) + { + if (sUUID.equals("CONSOLE")) + return true; + + if (recipient instanceof Player) + { + Player player = (Player) recipient; + + if (sender.hasPermission("utils.ignore.override")) + return true; + + JSONArray ignores = (JSONArray) DataManager.getOrDefault(recipient, "ignores", new JSONArray()); + return !ignores.contains(sUUID); + } + else + return true; + } + }; + } + +} diff --git a/src/main/java/com/redstoner/modules/lagchunks/LagChunks.cmd b/src/main/java/com/redstoner/modules/lagchunks/LagChunks.cmd new file mode 100644 index 0000000..142a437 --- /dev/null +++ b/src/main/java/com/redstoner/modules/lagchunks/LagChunks.cmd @@ -0,0 +1,19 @@ +command lc { + perm utils.lagchunks; + + list { + run list_cmd; + help re-lists already scanned chunks; + } + + [int:amount] { + run scan_cmd amount; + help scans for laggy chunks; + } + + tp [int:number] { + run tp number; + help teleports to the specified chunk; + type player; + } +} diff --git a/src/main/java/com/redstoner/modules/lagchunks/LagChunks.java b/src/main/java/com/redstoner/modules/lagchunks/LagChunks.java new file mode 100644 index 0000000..1debf12 --- /dev/null +++ b/src/main/java/com/redstoner/modules/lagchunks/LagChunks.java @@ -0,0 +1,82 @@ +package com.redstoner.modules.lagchunks; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class LagChunks implements Module +{ + private List<LaggyChunk> laggyChunks = new ArrayList<LaggyChunk>(); + + private void scan(int amount) + { + laggyChunks.clear(); + for (World world : Bukkit.getServer().getWorlds()) + { + for (Chunk chunk : world.getLoadedChunks()) + { + if (chunk.getEntities().length > amount) + { + Location entLoc = chunk.getEntities()[0].getLocation(); + laggyChunks.add(new LaggyChunk(entLoc.getBlockX(), entLoc.getBlockY(), entLoc.getBlockZ(), world, + chunk.getEntities().length)); + } + } + } + } + + @Command(hook = "list_cmd") + public void list(CommandSender sender) + { + if (laggyChunks.size() > 0) + { + ArrayList<String> message = new ArrayList<String>(); + for (LaggyChunk lc : laggyChunks) + { + message.add("§b[§a" + laggyChunks.indexOf(lc) + "§b]: §a" + lc.x + "§7, §a" + lc.y + "§7, §a" + lc.z + + " §7(" + lc.world.getName() + ") §a- §b" + lc.amount + " entities"); + } + message.add("§2-------------------"); + getLogger().message(sender, message.toArray(new String[] {})); + } + else + getLogger().message(sender, true, "Couldn't find any chunks with that many entities."); + } + + @Command(hook = "scan_cmd", async = AsyncType.ALWAYS) + public void scan_cmd(CommandSender sender, int amount) + { + scan(amount); + list(sender); + } + + @Command(hook = "tp") + public void tp(CommandSender sender, int number) + { + Player player = (Player) sender; + if (number < laggyChunks.size()) + { + player.teleport(laggyChunks.get(number).getLocation()); + getLogger().message(player, "§aTeleported to chunk " + number + "!"); + } + else + { + getLogger().message(sender, true, "§4Invalid chunk number! Use §e/lc list §4to show laggy chunks!"); + } + } +} diff --git a/src/main/java/com/redstoner/modules/lagchunks/LaggyChunk.java b/src/main/java/com/redstoner/modules/lagchunks/LaggyChunk.java new file mode 100644 index 0000000..3ff4d6f --- /dev/null +++ b/src/main/java/com/redstoner/modules/lagchunks/LaggyChunk.java @@ -0,0 +1,21 @@ +package com.redstoner.modules.lagchunks; + +import org.bukkit.Location; +import org.bukkit.World; + +public class LaggyChunk { + public final int x, y, z, amount; + public final World world; + + public LaggyChunk(int x, int y, int z, World world, int amount) { + this.x = x; + this.y = y; + this.z = z; + this.world = world; + this.amount = amount; + } + + public Location getLocation() { + return new Location(world, x, y, z); + } +} diff --git a/src/main/java/com/redstoner/modules/list/List.cmd b/src/main/java/com/redstoner/modules/list/List.cmd new file mode 100644 index 0000000..f4caf02 --- /dev/null +++ b/src/main/java/com/redstoner/modules/list/List.cmd @@ -0,0 +1,38 @@ +command list { + alias ls; + alias elist; + alias online; + alias eonline; + alias playerlist; + alias eplayerlist; + alias plist; + alias eplist; + alias who; + alias ewho; + [empty] { + run list; + help Shows all online players sorted by rank.; + } + [string:rank...] { + run list_rank rank; + help Shows all online players of the specified rank(s); + } +} +command staff { + [empty] { + help Shows all online staff.; + run staff; + } +} +command console_join { + [string:name] { + run console_join name; + type console; + } +} +command console_leave { + [string:name] { + run console_leave name; + type console; + } +} diff --git a/src/main/java/com/redstoner/modules/list/List.java b/src/main/java/com/redstoner/modules/list/List.java new file mode 100644 index 0000000..d5a0016 --- /dev/null +++ b/src/main/java/com/redstoner/modules/list/List.java @@ -0,0 +1,194 @@ +package com.redstoner.modules.list; + +import java.util.HashMap; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +import net.nemez.chatapi.click.Message; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 5, compatible = 4) +public class List implements Module +{ + private HashMap<String, Integer> onConsole; + + @Override + public void postEnable() + { + onConsole = new HashMap<>(); + } + + @Command(hook = "console_join") + public boolean console_join(CommandSender sender, String name) + { + if (onConsole.containsKey(name)) + onConsole.put(name, onConsole.get(name) + 1); + else + onConsole.put(name, 1); + return true; + } + + @Command(hook = "console_leave") + public boolean console_leave(CommandSender sender, String name) + { + if (onConsole.containsKey(name)) + if (onConsole.get(name) == 1) + onConsole.remove(name); + else + onConsole.put(name, onConsole.get(name) - 1); + return true; + } + + @Command(hook = "staff") + public boolean staff(CommandSender sender) + { + return listRank(sender, "staff"); + } + + @Command(hook = "list") + public boolean list(CommandSender sender) + { + return (listRank(sender, "all")); + } + + @Command(hook = "list_rank") + public boolean listRank(CommandSender sender, String rank) + { + int onlinePlayers = Bukkit.getOnlinePlayers().size(); + getLogger().message(sender, "", "&7There are &e" + onlinePlayers + "&7 out of maximum &e" + + Bukkit.getMaxPlayers() + "&7 players online."); + + rank = rank.toLowerCase(); + boolean all = rank.equals("all"); + + if (onlinePlayers == 0 && !rank.contains("console") && !all) + return true; + + rank = rank.replace("staff", "mit mod admin lead"); + + boolean shownAnything = false; + + if (rank.contains("visitor") || all) + shownAnything |= show(sender, "&7Visitors", getPlayers(sender, "group.visitor", "group.member"), all); + if (rank.contains("member") || all) + shownAnything |= show(sender, "&fMembers", getPlayers(sender, "group.member", "group.builder"), all); + if (rank.contains("builder") || all) + shownAnything |= show(sender, "&aBuilders", getPlayers(sender, "group.builder", "group.trusted"), all); + if (rank.contains("trusted") || all) + shownAnything |= show(sender, "&3Trusteds", getPlayers(sender, "group.trusted", "group.trainingmod"), all); + if (rank.contains("trainingmod") || rank.contains("mit") || all) + shownAnything |= show(sender, "&cTrainingmod &e•", getPlayers(sender, "group.trainingmod", "group.mod"), + all); + if (rank.contains("mod") || all) + shownAnything |= show(sender, "&cModerators", getPlayers(sender, "group.mod", "group.admin"), all); + if (rank.contains("admin") || all) + shownAnything |= show(sender, "&4Admins", getPlayers(sender, "group.admin", null), all); + if (rank.contains("lead") || all) + shownAnything |= show(sender, "&4Leads •", getPlayers(sender, "group.lead", null), all); + if (rank.contains("console") || all) + { + if (sender.hasPermission("utils.list.console")) + { + StringBuilder sb = new StringBuilder(); + for (Entry<String, Integer> entry : onConsole.entrySet()) + { + if (entry.getValue() > 0) + { + sb.append(entry.getKey()); + sb.append("&7, "); + } + } + String players = sb.toString().replaceAll(", $", ""); + shownAnything |= show(sender, "&9Console" + afk(Bukkit.getConsoleSender()), players); + } + else + { + if (!all) + { + getLogger().message(sender, true, "You do not have permissions to see who's on console!"); + shownAnything = true; + } + } + } + if (!shownAnything) + { + getLogger().message(sender, new String[] { + "Looks like I couldn't figure out what you meant. Try again with different parameters maybe?", + "Possible parameters are: &eAll&7, &eStaff&7, &eVisitor&7, &eMember&7, &eBuilder&7, &eTrusted&7, &eMit&7, &eMod&7, &eAdmin&7 and &eLead", + "You can also combine any of the parameters, like this: &eMember, Staff"}); + } + return true; + } + + public boolean show(CommandSender sender, String rank, String players) + { + return show(sender, rank, players, false); + } + + public boolean show(CommandSender sender, String rank, String players, boolean all) + { + if (players.length() == 0) + { + if (!all) + { + players = "None"; + } + else + players = null; + } + if (players != null) + { + Message m = new Message(sender, null); + m.appendText("&8[" + rank + "&8]&7: " + players); + m.send(); + return true; + } + return false; + } + + public String getPlayers(CommandSender sender, String positive, String negative) + { + Player player = null; + if (sender instanceof Player) + player = (Player) sender; + StringBuilder sb = new StringBuilder(); + for (Player p : Bukkit.getOnlinePlayers()) + { + if (p.hasPermission(positive) && (negative == null || !p.hasPermission(negative)) + && (positive.equals("group.lead") || !p.hasPermission("group.lead"))) + { + if (player == null || player.canSee(p)) + { + sb.append(Utils.getName(p) + afk(p) + vanish(p)); + sb.append(", "); + } + } + } + return sb.toString().replaceAll(", $", ""); + } + + public String afk(CommandSender sender) + { + return DataManager.getState(sender, "afk") + ? (String) DataManager.getConfigOrDefault("afk", "indicator", "&7[AFK]") + : ""; + } + + public String vanish(Player player) + { + return DataManager.getState(player, "vanished") + ? (String) DataManager.getConfigOrDefault("vanish", "indicator", "&7[V]") + : ""; + } +} diff --git a/src/main/java/com/redstoner/modules/loginsecurity/CancelledEventsHandler.java b/src/main/java/com/redstoner/modules/loginsecurity/CancelledEventsHandler.java new file mode 100644 index 0000000..e39d781 --- /dev/null +++ b/src/main/java/com/redstoner/modules/loginsecurity/CancelledEventsHandler.java @@ -0,0 +1,95 @@ +package com.redstoner.modules.loginsecurity; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerPickupArrowEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; + +public class CancelledEventsHandler implements Listener { + private LoginSecurity mainClass; + + public CancelledEventsHandler(LoginSecurity mainClass) { + this.mainClass = mainClass; + } + + @EventHandler + public void onMove(PlayerMoveEvent e) { + if (isLoggingIn(e.getPlayer())) { + e.getPlayer().teleport(LoginSecurity.loggingIn.get(e.getPlayer().getUniqueId())); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onChat(AsyncPlayerChatEvent e) { + if (isLoggingIn(e.getPlayer())) { + e.getPlayer().sendMessage(ChatColor.RED + "You must login before you can chat!"); + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onCommand(PlayerCommandPreprocessEvent e) { + String command = e.getMessage(); + + if (!command.startsWith("/login") && isLoggingIn(e.getPlayer())) { + e.getPlayer().sendMessage(ChatColor.RED + "You must login before you can execute commands!"); + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onItemHold(PlayerItemHeldEvent e) { + if (isLoggingIn(e.getPlayer())) { + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onItemPickup(PlayerPickupItemEvent e) { + if (isLoggingIn(e.getPlayer())) { + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onItemDrop(PlayerDropItemEvent e) { + if (isLoggingIn(e.getPlayer())) { + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onInteract(PlayerInteractEvent e) { + if (isLoggingIn(e.getPlayer())) { + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onArrowPickup(PlayerPickupArrowEvent e) { + if (isLoggingIn(e.getPlayer())) { + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onInvClick(InventoryClickEvent e) { + if (e.getWhoClicked() instanceof Player && isLoggingIn((Player) e.getWhoClicked())) { + e.setCancelled(true); + } + } + + private boolean isLoggingIn(Player player) { + return mainClass.isLoggingIn(player); + } +} diff --git a/src/main/java/com/redstoner/modules/loginsecurity/CryptographyHandler.java b/src/main/java/com/redstoner/modules/loginsecurity/CryptographyHandler.java new file mode 100644 index 0000000..48e81a9 --- /dev/null +++ b/src/main/java/com/redstoner/modules/loginsecurity/CryptographyHandler.java @@ -0,0 +1,53 @@ +package com.redstoner.modules.loginsecurity; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.Base64; + +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; + +public class CryptographyHandler { + public static String hash(String password, String salt) { + String algorithm = "PBKDF2WithHmacSHA256"; + int derivedKeyLength = 256; + int iterations = 200000; + byte[] decodedSalt = Base64.getDecoder().decode(salt.getBytes()); + + KeySpec spec = new PBEKeySpec(password.toCharArray(), decodedSalt, iterations, derivedKeyLength); + + byte[] hashed = null; + + try { + SecretKeyFactory f = SecretKeyFactory.getInstance(algorithm); + + hashed = f.generateSecret(spec).getEncoded(); + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { + e.printStackTrace(); + } + + return Base64.getEncoder().encodeToString(hashed).substring(0, 43); + } + + public static boolean verify(String password, String salt, String hash) { + return hash(password, salt).equals(hash); + } + + public static boolean verify(String password, String stored) { + String[] split = stored.split("\\$"); + + return verify(password, split[3], split[4]); + } + + public static String generateSalt() throws NoSuchAlgorithmException, NoSuchProviderException { + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + + byte[] salt = new byte[16]; + random.nextBytes(salt); + + return Base64.getEncoder().encodeToString(salt).substring(0, 22); + } +} diff --git a/src/main/java/com/redstoner/modules/loginsecurity/LoginSecurity.cmd b/src/main/java/com/redstoner/modules/loginsecurity/LoginSecurity.cmd new file mode 100644 index 0000000..952b3ed --- /dev/null +++ b/src/main/java/com/redstoner/modules/loginsecurity/LoginSecurity.cmd @@ -0,0 +1,49 @@ +command register { + perm utils.loginsecurity; + + [string:password] { + run register password; + help Protects your account with a password; + type player; + } +} + +command login { + perm utils.loginsecurity; + + [string:password] { + run login password; + help Logs you in; + type player; + } +} + +command cgpass { + perm utils.loginsecurity; + + [string:oldPassword] [string:newPassword] { + run cgpass oldPassword newPassword; + help Changes your password to the specified one; + type player; + } +} + +command rmpass { + perm utils.loginsecurity; + + [string:oldPassword] { + run rmpass oldPassword; + help Removes the password of your account; + type player; + } +} + +command rmotherpass { + perm utils.loginsecurity.admin; + + [string:playerName] { + run rmotherpass playerName; + help removes the password of another player; + perm utils.loginsecurity.admin; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/loginsecurity/LoginSecurity.java b/src/main/java/com/redstoner/modules/loginsecurity/LoginSecurity.java new file mode 100644 index 0000000..7bcb89a --- /dev/null +++ b/src/main/java/com/redstoner/modules/loginsecurity/LoginSecurity.java @@ -0,0 +1,263 @@ +package com.redstoner.modules.loginsecurity; + +import java.io.Serializable; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.scheduler.BukkitScheduler; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Main; +import com.redstoner.misc.mysql.JSONManager; +import com.redstoner.misc.mysql.MysqlHandler; +import com.redstoner.misc.mysql.elements.ConstraintOperator; +import com.redstoner.misc.mysql.elements.MysqlConstraint; +import com.redstoner.misc.mysql.elements.MysqlDatabase; +import com.redstoner.misc.mysql.elements.MysqlField; +import com.redstoner.misc.mysql.elements.MysqlTable; +import com.redstoner.misc.mysql.types.text.VarChar; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class LoginSecurity implements Module, Listener +{ + protected static Map<UUID, Location> loggingIn; + private MysqlTable table; + + @Override + public boolean onEnable() + { + Map<Serializable, Serializable> config = JSONManager.getConfiguration("loginsecurity.json"); + if (config == null || !config.containsKey("database") || !config.containsKey("table")) + { + getLogger().message(Bukkit.getConsoleSender(), true, + "Could not load the LoginSecurity config file, disabling!"); + return false; + } + try + { + MysqlDatabase database = MysqlHandler.INSTANCE.getDatabase((String) config.get("database")); + MysqlField uuid = new MysqlField("uuid", new VarChar(36), true); + MysqlField pass = new MysqlField("pass", new VarChar(88), true); + database.createTableIfNotExists((String) config.get("table"), uuid, pass); + table = database.getTable((String) config.get("table")); + } + catch (NullPointerException e) + { + getLogger().message(Bukkit.getConsoleSender(), true, "Could not use the LoginSecurity config, disabling!"); + return false; + } + loggingIn = new HashMap<>(); + Bukkit.getServer().getPluginManager().registerEvents(new CancelledEventsHandler(this), Main.plugin); + return true; + } + + public static Map<UUID, Location> getLoggingIn() + { + return loggingIn; + } + + @Command(hook = "register") + public void register(CommandSender sender, String password) + { + Player player = (Player) sender; + if (isRegistered(player)) + { + player.sendMessage(ChatColor.GREEN + "You are already registered!"); + return; + } + try + { + if (registerPlayer(player, password)) + { + player.sendMessage(ChatColor.GREEN + "Succesfully registered!"); + return; + } + } + catch (NoSuchAlgorithmException | NoSuchProviderException e) + { + e.printStackTrace(); + } + player.sendMessage(ChatColor.RED + "Failed to register, please contact an admin!"); + } + + @Command(hook = "login") + public void login(CommandSender sender, String password) + { + Player player = (Player) sender; + if (!isRegistered(player)) + { + player.sendMessage(ChatColor.RED + "You are not registered!"); + return; + } + if (CryptographyHandler.verify(password, getHash(player))) + { + loggingIn.remove(player.getUniqueId()); + } + else + { + player.sendMessage(ChatColor.RED + "Wrong password!"); + } + } + + @Command(hook = "cgpass") + public void cgpass(CommandSender sender, String oldPassword, String newPassword) + { + Player player = (Player) sender; + if (!isRegistered(player)) + { + player.sendMessage(ChatColor.RED + "You are not registered!"); + return; + } + if (!CryptographyHandler.verify(oldPassword, getHash(player))) + { + player.sendMessage(ChatColor.RED + "The old password you entered is wrong!"); + return; + } + if (oldPassword.equals(newPassword)) + { + player.sendMessage(ChatColor.RED + "You entered the same password!"); + return; + } + if (table.delete(getUuidConstraint(player))) + { + try + { + registerPlayer(player, newPassword); + player.sendMessage(ChatColor.GREEN + "Succesfully changed password!"); + } + catch (NoSuchAlgorithmException | NoSuchProviderException e) + { + e.printStackTrace(); + player.sendMessage(ChatColor.RED + "Failed to set new password!"); + } + } + else + { + player.sendMessage(ChatColor.RED + "Failed to remove old password from database!"); + } + } + + @Command(hook = "rmpass") + public void rmpass(CommandSender sender, String oldPassword) + { + Player player = (Player) sender; + if (!isRegistered(player)) + { + player.sendMessage(ChatColor.RED + "You are not registered!"); + return; + } + if (!CryptographyHandler.verify(oldPassword, getHash(player))) + { + player.sendMessage(ChatColor.RED + "The old password you entered is wrong!"); + return; + } + if (table.delete(getUuidConstraint(player))) + { + player.sendMessage(ChatColor.GREEN + "Succesfully removed password!"); + } + else + { + player.sendMessage(ChatColor.RED + "Failed to remove old password from database!"); + } + } + + @Command(hook = "rmotherpass") + public void rmotherpass(CommandSender sender, String playerName) + { + if (playerName.equals("")) + { + sender.sendMessage(ChatColor.RED + "That's not a valid player!"); + return; + } + @SuppressWarnings("deprecation") + OfflinePlayer player = Bukkit.getOfflinePlayer(playerName); + if (!isRegistered(player)) + { + sender.sendMessage(ChatColor.RED + "That player is not registered!"); + return; + } + if (table.delete(getUuidConstraint(player))) + { + sender.sendMessage(ChatColor.GREEN + "Successfully removed " + playerName + "'s password!"); + } + else + { + sender.sendMessage(ChatColor.RED + "Failed to remove " + playerName + "'s password!"); + } + } + + @EventHandler + public void onJoin(PlayerJoinEvent e) + { + Player player = e.getPlayer(); + if (!isRegistered(player)) + { + return; + } + getLogger().message(player, "You'll have to log in within 60s or you'll be kicked!"); + loggingIn.put(player.getUniqueId(), player.getLocation()); + BukkitScheduler scheduler = Bukkit.getScheduler(); + RepeatingLoginRunnable repeatingRunnable = new RepeatingLoginRunnable(this, player); + repeatingRunnable.setId(scheduler.scheduleSyncRepeatingTask(Main.plugin, repeatingRunnable, 0L, 2L)); + scheduler.scheduleSyncDelayedTask(Main.plugin, new Runnable() + { + @Override + public void run() + { + if (isLoggingIn(player)) + { + scheduler.cancelTask(repeatingRunnable.getId()); + player.kickPlayer("You didn't login in time!"); + } + } + }, 1200L); + } + + public boolean isLoggingIn(Player player) + { + return loggingIn.containsKey(player.getUniqueId()); + } + + public MysqlConstraint getUuidConstraint(OfflinePlayer player) + { + return new MysqlConstraint("uuid", ConstraintOperator.EQUAL, player.getUniqueId().toString()); + } + + public boolean isRegistered(OfflinePlayer player) + { + return table.get("uuid", getUuidConstraint(player)).length > 0; + } + + public String getHash(OfflinePlayer player) + { + return (String) table.get("pass", getUuidConstraint(player))[0]; + } + + public boolean registerPlayer(Player player, String password) + throws NoSuchAlgorithmException, NoSuchProviderException + { + String salt = CryptographyHandler.generateSalt(); + String hash = CryptographyHandler.hash(password, salt); + String toInsert = "$pbkdf2-sha256$200000$" + salt + "$" + hash; + return table.insert(player.getUniqueId().toString(), toInsert); + } +} diff --git a/src/main/java/com/redstoner/modules/loginsecurity/RepeatingLoginRunnable.java b/src/main/java/com/redstoner/modules/loginsecurity/RepeatingLoginRunnable.java new file mode 100644 index 0000000..4e8db6d --- /dev/null +++ b/src/main/java/com/redstoner/modules/loginsecurity/RepeatingLoginRunnable.java @@ -0,0 +1,37 @@ +package com.redstoner.modules.loginsecurity; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class RepeatingLoginRunnable implements Runnable { + private int id = -1; + private Player player; + private LoginSecurity mainClass; + + public RepeatingLoginRunnable(LoginSecurity mainClass, Player player) { + this.player = player; + this.mainClass = mainClass; + } + + @Override + public void run() { + if (!player.isOnline()) { + LoginSecurity.loggingIn.remove(player.getUniqueId()); + Bukkit.getScheduler().cancelTask(id); + } + + if (!mainClass.isLoggingIn(player)) { + player.sendMessage(ChatColor.GREEN + "Successfully logged in!"); + Bukkit.getScheduler().cancelTask(id); + } + } + + public void setId(int id) { + this.id = id; + } + + public int getId() { + return id; + } +} diff --git a/src/main/java/com/redstoner/modules/logs/LogEntry.java b/src/main/java/com/redstoner/modules/logs/LogEntry.java new file mode 100644 index 0000000..3ccc844 --- /dev/null +++ b/src/main/java/com/redstoner/modules/logs/LogEntry.java @@ -0,0 +1,71 @@ +package com.redstoner.modules.logs; + +public class LogEntry +{ + public final int line; + public final int global_line; + public final String filename; + public final String raw; + + public LogEntry(String raw, int line, int global_line) + { + this("Unkown", raw, line, global_line); + } + + public LogEntry(String filename, String raw, int line, int global_line) + { + this.raw = resolveColors(raw); + this.line = line; + this.global_line = global_line; + this.filename = filename; + } + + public String applyFormat(String format, boolean colors) + { + // Replace escaped % with placeholder + format = format.replace("%%", "§§"); + // Line numbers + format = format.replace("%l", "" + line); + format = format.replace("%L", "" + global_line); + // Filename + format = format.replace("%f", filename); + // Strip colors + if (!colors) + format = format.replace("%r", raw.replaceAll("$.", "")); + else + format = format.replace("%r", raw); + // Convert placeholder back + format = format.replace("§§", "%"); + return format; + } + + private String resolveColors(String message) + { + message = message.replace("[0;30;22m", "§0"); + message = message.replace("[0;34;22m", "§1"); + message = message.replace("[0;32;22m", "§2"); + message = message.replace("[0;36;22m", "§3"); + message = message.replace("[0;31;22m", "§4"); + message = message.replace("[0;35;22m", "§5"); + message = message.replace("[0;33;22m", "§6"); + message = message.replace("[0;37;22m", "§7"); + message = message.replace("[0;30;1m", "§8"); + message = message.replace("[0;34;1m", "§9"); + message = message.replace("[0;32;1m", "§a"); + message = message.replace("[0;36;1m", "§b"); + message = message.replace("[0;31;1m", "§c"); + message = message.replace("[0;35;1m", "§d"); + message = message.replace("[0;33;1m", "§e"); + message = message.replace("[0;37;1m", "§f"); + + message = message.replace("[5m", "§k"); + message = message.replace("[21m", "§l"); + message = message.replace("[9m", "§m"); + message = message.replace("[4m", "§n"); + message = message.replace("[3m", "§o"); + + message = message.replace("[m", "§r"); + + return message; + } +} diff --git a/src/main/java/com/redstoner/modules/logs/LogHandler.java b/src/main/java/com/redstoner/modules/logs/LogHandler.java new file mode 100644 index 0000000..76f3849 --- /dev/null +++ b/src/main/java/com/redstoner/modules/logs/LogHandler.java @@ -0,0 +1,200 @@ +package com.redstoner.modules.logs; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import java.util.zip.GZIPInputStream; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.redstoner.misc.Utils; +import com.redstoner.modules.datamanager.DataManager; + +public class LogHandler extends Thread +{ + private CommandSender sender; + private String regex, fileName; + private static ArrayList<CommandSender> stillSearching = new ArrayList<>(); + public int totalFiles = 0; + public int filesSearched = 0; + public int totalLines = 0; + public int currentLine = 0; + + protected LogHandler(CommandSender sender, String regex, String fileName) + { + this.sender = sender; + this.regex = regex; + this.fileName = fileName; + } + + public void doSearch() + { + if (stillSearching.contains(sender)) + { + Logs.logger.message(sender, true, "§4 DO NOT EVER TRY TO QUERY TWO SEARCHES AT ONCE. Go die...!"); + return; + } + stillSearching.add(sender); + this.start(); + } + + /** Searches the logs for a certain regex and forwards any matches to the sender. + * + * @param sender the issuer of the search + * @param regex the regex to search for. Will be wrapped in "^.*" and ".*$" if it is missing line delimiters + * @param fileName the name of the files to search through. May contain wildcards. */ + private void search(CommandSender sender, String regex, String fileName) + { + long starttime = System.currentTimeMillis(); + int matches = 0; + Logs.logger.message(sender, "Starting log search for &e" + regex + "&7 in &e" + fileName + + " &7now. &cPlease do not query any other searches until this one completes."); + try + { + if (!regex.startsWith("^")) + regex = "^.*" + regex; + if (!regex.endsWith("$")) + regex += ".*$"; + File logFolder = Logs.getLogsDir(); + Pattern fileNamePattern; + try + { + fileNamePattern = Pattern.compile(fileName); + } + catch (PatternSyntaxException e) + { + Logs.logger.message(sender, true, "An error occured trying to compile the filename pattern!"); + stillSearching.remove(sender); + return; + } + File[] files = logFolder.listFiles(new FilenameFilter() + { + @Override + public boolean accept(File dir, String name) + { + return fileNamePattern.matcher(name).matches(); + } + }); + totalFiles = files.length; + if (totalFiles == 0) + { + Logs.logger.message(sender, true, "No files found!"); + stillSearching.remove(sender); + return; + } + else + Logs.logger.message(sender, "A total of &e" + totalFiles + "&7 files will be searched!"); + + boolean progress = (boolean) DataManager.getOrDefault(Utils.getID(sender), "Logs", "progress", true); + Pattern searchPattern; + try + { + searchPattern = Pattern.compile(regex); + } + catch (PatternSyntaxException e) + { + Logs.logger.message(sender, true, "An error occured trying to compile the search pattern!"); + stillSearching.remove(sender); + return; + } + for (File file : files) + { + if (file.getName().endsWith(".gz")) + { + + BufferedReader inputReader = new BufferedReader( + new InputStreamReader(new GZIPInputStream(new FileInputStream(file)))); + matches += searchStream(inputReader, searchPattern, sender, file.getName()); + inputReader.close(); + } + else + { + BufferedReader inputReader = new BufferedReader(new FileReader(file)); + matches += searchStream(inputReader, searchPattern, sender, file.getName()); + inputReader.close(); + } + filesSearched++; + if (progress) + { + sender.sendMessage("§7So far, §e" + filesSearched + "§7/§e" + totalFiles + "§7 File(s) and §e" + + totalLines + "§7 Line(s) were searched."); + } + } + } + catch (Exception e) + { + Logs.logger.message(sender, true, + "An unexpected error occured, please check your search parameters and try again!"); + stillSearching.remove(sender); + return; + } + stillSearching.remove(sender); + if ((boolean) DataManager.getOrDefault(Utils.getID(sender), "Logs", "summary", true)) + { + String[] message = new String[2]; + message[0] = "§aYour search completed after " + (System.currentTimeMillis() - starttime) + "ms!"; + message[1] = "§7In total: §e" + filesSearched + "§7 File(s) and §e" + totalLines + + "§7 Line(s) were searched, §a" + matches + "§7 Match(es) were found!"; + Logs.logger.message(sender, message); + } + return; + } + + /** This function searches through an InputStream to find a regex. If it finds a match, it will forward that match to the sender and increase the match counter. + * + * @param inputReader the input reader containing the data + * @param regex the regex to search for + * @param sender the issuer of the search + * @param singleFile true if only a single file is being searched, false if the original filename contained wildcards. + * @param filename the name of the file that is currently being searched + * @return how many matches it found + * @throws IOException if something goes wrong */ + private int searchStream(BufferedReader inputReader, Pattern searchPattern, CommandSender sender, String filename) + throws IOException + { + String format = (String) DataManager.getOrDefault(Utils.getID(sender), "Logs", "format", Logs.defaultFormat); + boolean colors = (boolean) DataManager.getOrDefault(Utils.getID(sender), "Logs", "colors", true); + Player p = null; + if (sender instanceof Player) + p = (Player) sender; + int matches = 0; + String line = ""; + currentLine = 0; + while ((line = inputReader.readLine()) != null) + { + totalLines++; + currentLine++; + if (searchPattern.matcher(line).matches()) + { + if (((p != null) && (!p.isOnline()))) + { + stillSearching.remove(sender); + throw new IOException("The player has left during the search. Aborting now."); + } + LogEntry entry = new LogEntry(filename, line, currentLine, totalLines); + sender.sendMessage(entry.applyFormat(format, colors)); + matches++; + } + } + return matches; + } + + @Override + public void run() + { + try + { + search(sender, regex, fileName); + } + catch (Exception e) + {} + } +} diff --git a/src/main/java/com/redstoner/modules/logs/Logs.cmd b/src/main/java/com/redstoner/modules/logs/Logs.cmd new file mode 100644 index 0000000..c5283fe --- /dev/null +++ b/src/main/java/com/redstoner/modules/logs/Logs.cmd @@ -0,0 +1,34 @@ +command log { + perm utils.logs; + alias logs; + search [string:file(s)] [string:search...] { + run search_logs file(s) search; + help Performs the specified search operation on the logs. Wildcards are supported in filenames. Search string is a regex.; + type player; + } + format { + run show_format; + help Displays your current log output format with an example result.; + type player; + } + format_help { + run show_format_help; + help Displays all available placeholders for the formatting; + type player; + } + option_help { + run show_option_help; + help Displays all available options.; + type player; + } + set format [string:format] { + run set_format format; + help Sets a new log output format; + type player; + } + set [string:option] [boolean:state] { + run set_option option state; + help Allows you to enable or disable various features such as sumamries, live progress updates, etc...; + type player; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/logs/Logs.java b/src/main/java/com/redstoner/modules/logs/Logs.java new file mode 100644 index 0000000..b54bfc9 --- /dev/null +++ b/src/main/java/com/redstoner/modules/logs/Logs.java @@ -0,0 +1,157 @@ +package com.redstoner.modules.logs; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.command.CommandSender; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; +import com.redstoner.modules.ModuleLogger; +import com.redstoner.modules.datamanager.DataManager; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 4, compatible = 4) +public class Logs implements Module +{ + public static final String defaultFormat = "§7 > %f: %r"; + private final LogEntry example_1 = new LogEntry("1970-01-01-2.log.gz", + "[01:23:45] [Async Chat Thread - #1337/INFO]: §aFooBar §7→ §4THIS SERVER SUCKS", 14, 73); + private final LogEntry example_2 = new LogEntry("1970-01-01-2.log.gz", + "[01:23:45] [Server thread/INFO]: admin issued server command: /ban FooBar Ab00se", 15, 74); + protected static ModuleLogger logger; + + @Override + public void firstLoad() + { + Module.super.firstLoad(); + DataManager.setConfig("logs.root", "/etc/minecraft/redstoner/logs"); + } + + @Override + public boolean onEnable() + { + Module.super.onEnable(); + logger = getLogger(); + return true; + } + + public static File getLogsDir() + { + return new File((String) DataManager.getConfigOrDefault("logs.root", "../logs")); + } + + @Command(hook = "search_logs") + public boolean search_logs(CommandSender sender, String files, String search) + { + LogHandler handler = new LogHandler(sender, search, files); + handler.doSearch(); + return true; + } + + // FORMATTING + @Command(hook = "show_format") + public boolean show_format(CommandSender sender) + { + showExample(sender); + return true; + } + + @Command(hook = "set_format") + public boolean set_format(CommandSender sender, String format) + { + if (format.equals("--reset")) + format = defaultFormat; + format = format.replace("&", "§").replace("$$", "&"); + DataManager.setData(sender, "format", format); + showExample(sender, format); + return true; + } + + private void showExample(CommandSender sender) + { + showExample(sender, (String) DataManager.getOrDefault(sender, "format", defaultFormat)); + } + + private void showExample(CommandSender sender, String format) + { + sender.sendMessage(getLogger().getHeader()); + sender.sendMessage("Your format is: " + format); + sender.sendMessage("Here's an example of what it would look like in an actual log search:"); + boolean colors = (boolean) DataManager.getOrDefault(sender, "colors", true); + if ((boolean) DataManager.getOrDefault(sender, "progress", true)) + { + sender.sendMessage("§7So far, §e1§7/§e2§7 File(s) and §e68§7 Line(s) were searched."); + } + sender.sendMessage(example_1.applyFormat(format, colors)); + sender.sendMessage(example_2.applyFormat(format, colors)); + if ((boolean) DataManager.getOrDefault(sender, "summary", true)) + { + sender.sendMessage("§aSearch completed after 39ms!"); + sender.sendMessage( + "§7In total: §e2§7 File(s) and §e105§7 Line(s) were searched, §a2§7 Match(es) were found!"); + } + } + + @Command(hook = "show_format_help") + public boolean format_help(CommandSender sender) + { + //@noformat + String[] format_help = new String[] { + " &e%l&cine&7 -> Linenumber in the current file", + " &e%L&cine&7 -> Global linenumber (sum of all previous files + current line)", + " &e%f&cile&7 -> Complete filename", + " &e%r&caw&7 -> The raw line containing the text as it appears in the logs", + "", + " &7Use %% to gain a literal %."}; + //@format + getLogger().message(sender, format_help); + return true; + } + + // SEARCH OPTIONS + @Command(hook = "show_option_help") + public boolean show_options(CommandSender sender) + { + List<String> options = new ArrayList<>(Option.values().length + 1); + options.add("Available options are:"); + for (Option o : Option.values()) + options.add(" - " + o.toString()); + getLogger().message(sender, options.toArray(new String[] {})); + return true; + } + + @Command(hook = "set_option") + public boolean set_option(CommandSender sender, String option, boolean state) + { + option = option.toLowerCase(); + Option o = null; + try + { + o = Option.valueOf(option); + } + catch (IllegalArgumentException e) + {} + if (o == null) + { + getLogger().message(sender, true, + "Invalid option! To get a list of all available options, run &e/logs option_help"); + return true; + } + DataManager.setData(sender, option, state); + getLogger().message(sender, + "Successfully turned displaying of &e" + option + (state ? " &aon&7!" : " &coff&7!")); + return true; + } +} + +enum Option +{ + summary, + progress, + colors +} diff --git a/src/main/java/com/redstoner/modules/mentio/Mentio.cmd b/src/main/java/com/redstoner/modules/mentio/Mentio.cmd new file mode 100644 index 0000000..230adf8 --- /dev/null +++ b/src/main/java/com/redstoner/modules/mentio/Mentio.cmd @@ -0,0 +1,16 @@ +command mentio { + add [string:trigger] { + help Triggers you when the trigger gets said.; + run addmentio trigger; + } + delete [string:trigger] { + help Deletes a mentio.; + run delmentio trigger; + } + list { + help Lists your mentios.; + run listmentios; + } + perm utils.mentio; + type player; +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/mentio/Mentio.java b/src/main/java/com/redstoner/modules/mentio/Mentio.java new file mode 100644 index 0000000..3db8edf --- /dev/null +++ b/src/main/java/com/redstoner/modules/mentio/Mentio.java @@ -0,0 +1,180 @@ +package com.redstoner.modules.mentio; + +import java.io.File; +import java.util.ArrayList; +import java.util.UUID; +import java.util.regex.Pattern; + +import org.bukkit.Sound; +import org.bukkit.command.CommandSender; +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.AsyncPlayerChatEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; +import com.redstoner.modules.ignore.Ignore; + +import net.nemez.chatapi.click.Message; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Mentio implements Module, Listener +{ + private File mentioLocation = new File(Main.plugin.getDataFolder(), "mentio.json"); + private JSONObject mentios; + + @Override + public boolean onEnable() + { + loadMentios(); + return true; + } + + @Override + public void onDisable() + { + saveMentios(); + } + + @SuppressWarnings("unchecked") + @Command(hook = "addmentio") + public boolean addMentio(CommandSender sender, String trigger) + { + Player player = (Player) sender; + UUID uuid = player.getUniqueId(); + JSONArray playerMentios = (JSONArray) mentios.get(uuid.toString()); + if (playerMentios == null) + { + playerMentios = new JSONArray(); + playerMentios.add(player.getName()); + playerMentios.add(player.getDisplayName().split(" ")[0].replaceAll("§[0-9a-fk-o]", "")); + } + if (playerMentios.contains(trigger)) + getLogger().message(sender, true, "You already had that as a mentio!"); + else + { + playerMentios.add(trigger); + getLogger().message(sender, "Successfully added the trigger §e" + trigger + " §7for you!"); + mentios.put(uuid.toString(), playerMentios); + saveMentios(); + } + return true; + } + + @SuppressWarnings("unchecked") + @Command(hook = "delmentio") + public boolean delMentio(CommandSender sender, String trigger) + { + Player player = (Player) sender; + UUID uuid = player.getUniqueId(); + JSONArray playerMentios = (JSONArray) mentios.get(uuid.toString()); + if (playerMentios == null) + { + playerMentios = new JSONArray(); + playerMentios.add(player.getName()); + playerMentios.add(player.getDisplayName().split(" ")[0].replaceAll("§[0-9a-fk-o]", "")); + } + if (!playerMentios.remove(trigger)) + getLogger().message(sender, true, "You didn't have that as a mentio!"); + else + { + getLogger().message(sender, "Successfully removed the trigger §e" + trigger + " §7for you!"); + mentios.put(uuid.toString(), playerMentios); + saveMentios(); + } + return true; + } + + @SuppressWarnings("unchecked") + @Command(hook = "listmentios") + public boolean listMentios(CommandSender sender) + { + ArrayList<String> message = new ArrayList<>(); + Player player = (Player) sender; + UUID uuid = player.getUniqueId(); + JSONArray playerMentios = (JSONArray) mentios.get(uuid.toString()); + if (playerMentios == null) + { + playerMentios = new JSONArray(); + playerMentios.add(player.getName()); + playerMentios.add(player.getDisplayName().split(" ")[0].replaceAll("§[0-9a-fk-or]", "")); + } + for (Object raw : playerMentios) + { + String mentio = (String) raw; + message.add("&2 -> &e" + mentio); + } + getLogger().message(sender, message.toArray(new String[] {})); + return true; + } + + @SuppressWarnings("unchecked") + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerChat(AsyncPlayerChatEvent event) + { + if (event.isCancelled()) + return; + for (Player player : event.getRecipients()) + { + if (ModuleLoader.exists("Ignore") ? !Ignore.getIgnoredBy(event.getPlayer()).sendTo(player) : false) + return; + UUID uuid = player.getUniqueId(); + JSONArray playerMentios = (JSONArray) mentios.get(uuid.toString()); + if (playerMentios == null) + { + playerMentios = new JSONArray(); + playerMentios.add(player.getName()); + playerMentios.add(player.getDisplayName().split(" ")[0].replaceAll("§[0-9a-fk-o]", "")); + } + for (Object raw : playerMentios) + { + String mentio = (String) raw; + if (event.getMessage().toLowerCase().contains(mentio.toLowerCase())) + { + event.getRecipients().remove(player); + String temp = event.getMessage().replaceAll("(?i)" + Pattern.quote(mentio) + ".*", ""); + String lastColorCodes = "§r"; + char lastChar = ' '; + for (char c : temp.toCharArray()) + { + if (lastChar == '§') + lastColorCodes += "§" + c; + lastChar = c; + } + Message m = new Message(player, event.getPlayer()); + m.appendText(event.getFormat().replace("%1$s", event.getPlayer().getDisplayName()).replace("%2$s", + event.getMessage().replaceFirst("(?i)(" + Pattern.quote(mentio) + ")([^ ]*)", + "§a§o$1$2" + lastColorCodes))); + m.send(); + player.playSound(player.getLocation(), Sound.ENTITY_CHICKEN_EGG, 1, 1); + return; + } + } + } + } + + private void loadMentios() + { + mentios = JsonManager.getObject(mentioLocation); + if (mentios == null) + mentios = new JSONObject(); + } + + private void saveMentios() + { + JsonManager.save(mentios, mentioLocation); + } +} diff --git a/src/main/java/com/redstoner/modules/message/Message.cmd b/src/main/java/com/redstoner/modules/message/Message.cmd new file mode 100644 index 0000000..382e52e --- /dev/null +++ b/src/main/java/com/redstoner/modules/message/Message.cmd @@ -0,0 +1,43 @@ +command message { + alias m; + alias em; + alias msg; + alias emsg; + alias t; + alias et; + alias tell; + alias etell; + alias w; + alias ew; + alias whisper; + alias ewhisper; + [string:player] [string:message...] { + run message player message; + help Sends a direct message to a player.; + perm utils.message; + } +} + +command reply { + alias r; + alias er; + alias ereply; + [string:message...] { + run reply message; + help Sends a direct message to the last person you talked to.; + perm utils.message; + } +} + +command pmtoggle { + [empty] { + help Turns off your toggle.; + type player; + run pmtoggle_off; + } + [string:player] { + help Turns on your pmtoggle and locks onto <player>.; + type player; + run pmtoggle player; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/message/Message.java b/src/main/java/com/redstoner/modules/message/Message.java new file mode 100644 index 0000000..8c9f95d --- /dev/null +++ b/src/main/java/com/redstoner/modules/message/Message.java @@ -0,0 +1,226 @@ +package com.redstoner.modules.message; + +import java.util.HashMap; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; +import com.redstoner.modules.ignore.Ignore; +import com.redstoner.modules.socialspy.Socialspy; + +import net.nemez.chatapi.ChatAPI; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 4, compatible = 4) +public class Message implements Module +{ + HashMap<CommandSender, CommandSender> replyTargets = new HashMap<>(); + HashMap<Player, String> toggles = new HashMap<>(); + + @Override + public void migrate(Version old) + { + Module.super.migrate(old); + if (old.major() == 4 && old.minor() == 0 && old.revision() <= 3) + { + DataManager.setConfig("from", getDefaultFormatFrom()); + DataManager.setConfig("to", getDefaultFormatTo()); + } + } + + @Command(hook = "message", async = AsyncType.ALWAYS) + public boolean message(CommandSender sender, String target, String message) + { + CommandSender p; + if (target.equalsIgnoreCase("console")) + p = Bukkit.getConsoleSender(); + else + p = Bukkit.getPlayer(target); + if (p == null) + { + getLogger().message(sender, true, "That player couldn't be found!"); + return true; + } + else if (ModuleLoader.exists("Ignore") ? !Ignore.getIgnoredBy(sender).sendTo(p) : true) + { + getLogger().message(sender, true, Utils.getName(p) + " has ignored you. Your message was not sent."); + return true; + } + else + { + if (ModuleLoader.getModule("Socialspy") != null) + Socialspy.spyBroadcast(sender, p, message, "/m", new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return !(recipient.equals(sender) || recipient.equals(p)); + } + }); + + String format = (String) DataManager.getConfigOrDefault("to", getDefaultFormatTo()); + format = ChatAPI.colorify(null, format); + format = applyFormat(format, sender, p, message); + net.nemez.chatapi.click.Message m = new net.nemez.chatapi.click.Message(sender, null); + m.appendText(format); + m.send(); + + if (!sender.equals(p)) + { + format = (String) DataManager.getConfigOrDefault("from", getDefaultFormatFrom()); + format = ChatAPI.colorify(null, format); + format = applyFormat(format, sender, p, message); + net.nemez.chatapi.click.Message m2 = new net.nemez.chatapi.click.Message(p, null); + m2.appendText(format); + m2.send(); + } + replyTargets.put(sender, p); + replyTargets.put(p, sender); + + if (DataManager.getState(p, "afk")) + { + getLogger().message(sender, "&5That player is currently AFK and may not respond!"); + } + } + return true; + } + + @Command(hook = "reply", async = AsyncType.ALWAYS) + public boolean reply(CommandSender sender, String message) + { + CommandSender target = replyTargets.get(sender); + if (target == null || ((target instanceof OfflinePlayer) && !((OfflinePlayer) target).isOnline())) + { + getLogger().message(sender, true, "You don't have anyone to reply to!"); + return true; + } + else if (ModuleLoader.exists("Ignore") ? !Ignore.getIgnoredBy(sender).sendTo(target) : true) + { + getLogger().message(sender, true, Utils.getName(target) + " has ignored you. Your message was not sent."); + return true; + } + else + { + if (ModuleLoader.getModule("Socialspy") != null) + Socialspy.spyBroadcast(sender, target, message, "/r", new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return !(recipient.equals(sender) || recipient.equals(target)); + } + }); + + String format = (String) DataManager.getConfigOrDefault("to", getDefaultFormatTo()); + format = ChatAPI.colorify(null, format); + format = applyFormat(format, sender, target, message); + net.nemez.chatapi.click.Message m = new net.nemez.chatapi.click.Message(sender, null); + m.appendText(format); + m.send(); + + if (!sender.equals(target)) + { + format = (String) DataManager.getConfigOrDefault("from", getDefaultFormatFrom()); + format = ChatAPI.colorify(null, format); + format = applyFormat(format, sender, target, message); + net.nemez.chatapi.click.Message m2 = new net.nemez.chatapi.click.Message(target, null); + m2.appendText(format); + m2.send(); + } + } + replyTargets.put(sender, target); + replyTargets.put(target, sender); + return true; + } + + @Command(hook = "pmtoggle_off", async = AsyncType.ALWAYS) + public boolean pmtoggle_off(CommandSender sender) + { + Player player = (Player) sender; + if (toggles.remove(player) != null) + getLogger().message(player, "Your pmtoggle was removed!"); + else + getLogger().message(player, "You didn't have pmtoggle enabled! Use /pmtoggle <player> to enabled it."); + return true; + } + + @Command(hook = "pmtoggle", async = AsyncType.ALWAYS) + public boolean pmtoggle(CommandSender sender, String player) + { + Player p = Bukkit.getPlayer(player); + if (p == null && !player.equals("CONSOLE")) + { + getLogger().message(sender, "§cThat player couldn't be found!"); + return true; + } + toggles.put((Player) sender, player); + getLogger().message(sender, "Locked your pmtoggle onto §6" + player + "§7."); + return true; + } + + @EventHandler + public void onPlayerChat(AsyncPlayerChatEvent event) + { + Player player = event.getPlayer(); + if (toggles.containsKey(player)) + { + Bukkit.dispatchCommand(player, "m " + toggles.get(player) + " " + event.getMessage()); + event.setCancelled(true); + } + } + + @SuppressWarnings("unlikely-arg-type") + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) + { + toggles.remove(event.getPlayer()); + String player = event.getPlayer().getName(); + if (toggles.containsValue(player)) + for (Entry<Player, String> entry : toggles.entrySet()) + if (entry.getValue().equals(player)) + { + toggles.remove(player); + getLogger().message(entry.getKey(), + "We removed your pmtoggle for &6" + player + "&7, as they left the game."); + } + } + + public String applyFormat(String format, CommandSender sender, CommandSender target, String message) + { + format = format.replace("%%", "§§"); + format = format.replace("%s", Utils.getName(sender)); + format = format.replace("%S", sender.getName()); + format = format.replace("%t", Utils.getName(target)); + format = format.replace("%T", target.getName()); + format = format.replace("%m", message); + format = format.replaceAll("§§", "%"); + + return format; + } + + public String getDefaultFormatFrom() + { + return "&6[&9%s&6 -> &cme&6]&f %m"; + } + + public String getDefaultFormatTo() + { + return "&6[&cme&6 -> &9%t&6]&f %m"; + } +} diff --git a/src/main/java/com/redstoner/modules/misc/Misc.cmd b/src/main/java/com/redstoner/modules/misc/Misc.cmd new file mode 100644 index 0000000..53e73ad --- /dev/null +++ b/src/main/java/com/redstoner/modules/misc/Misc.cmd @@ -0,0 +1,66 @@ +command tempadd { + perm pex; + [string:user] [string:group] { + help Adds a user to a group for 1w.; + run tempadddef user group; + } + [string:user] [string:group] [string:duration] { + help Adds a user to a group for a specified duration.; + run tempadd user group duration; + } +} +command echo { + [string:text...] { + help Echoes back to you.; + run echo text; + } +} +command ping { + [empty] { + help Pongs :D; + run ping; + } + [string:password] { + help Pongs :D; + run ping2 password; + } +} +command sudo { + perm utils.sudo; + [string:name] [string:command...] { + help Sudo'es another user (or console); + run sudo name command; + } +} +command hasperm { + [flag:-f] [string:name] [string:node] { + perm utils.hasperm; + run hasperm -f name node; + help Checks if a player has a given permission node or not. Returns \"true/false\" in chat. When -f is set, it returns it unformatted.; + } +} +command nightvision { +alias nv; + [empty] { + run illuminate; + type player; + help Gives the player infinte night vision; + perm utils.illuminate; + } +} +command minecart { + alias cart; + perm utils.spawncart; + help Spawn's a Minecart; + type player; + + deafult [string type] { + run minecart_default type; + } + [string type] { + run minecart_type type; + } + [empty] { + run minecart; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/misc/Misc.java b/src/main/java/com/redstoner/modules/misc/Misc.java new file mode 100644 index 0000000..88e72ea --- /dev/null +++ b/src/main/java/com/redstoner/modules/misc/Misc.java @@ -0,0 +1,336 @@ +package com.redstoner.modules.misc; + +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +import net.nemez.chatapi.ChatAPI; +import net.nemez.chatapi.click.Message; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Misc implements Module, Listener +{ + private final String[] sudoBlacklist = new String[] {"(.*:)?e?sudo", "(.*:)?script.*", "(.*:)?stop", + "(.*:)?modules", "(.*:)?sayn", "(.*:)?pex", "(.*:)?console_.*", "(.*:)?op", "(.*:)?login", "(.*:)?register", + "(.*:)?.*pass"}; + JSONObject config; + JSONArray unprotectedRegions; + + @EventHandler + public void onFirstJoin(PlayerJoinEvent event) + { + Player player = event.getPlayer(); + if (!player.hasPlayedBefore()) + { + Utils.broadcast("", "\n§a§lPlease welcome §f" + player.getDisplayName() + " §a§lto Redstoner!\n", null); + String[] message = new String[] {" \n \n \n \n \n \n \n \n \n \n \n \n ", + " &4Welcome to the Redstoner Server!", " &6Before you ask us things, take a quick", + " &6look at &a&nredstoner.com/info", " \n&6thank you and happy playing ;)", " \n \n"}; + getLogger().message(player, message); + } + Material spawnBlock = player.getLocation().getBlock().getType(); + if (spawnBlock == Material.PORTAL || spawnBlock == Material.ENDER_PORTAL) + { + getLogger().message(player, "&4Looks like you spawned in a portal... Let me help you out"); + getLogger().message(player, "&6You can use /back if you &nreally&6 want to go back"); + player.teleport(player.getWorld().getSpawnLocation()); + } + } + + // Disables spectator teleportation + @EventHandler(priority = EventPriority.LOWEST) + public void onTeleport(PlayerTeleportEvent event) + { + Player player = event.getPlayer(); + if (!event.isCancelled() && event.getCause() == TeleportCause.SPECTATE && !player.hasPermission("utils.tp")) + { + event.setCancelled(true); + getLogger().message(event.getPlayer(), true, "Spectator teleportation is disabled!"); + } + } + + // Disables water and lava breaking stuff + @EventHandler + public void onLiquidFlow(BlockFromToEvent event) + { + Material m = event.getToBlock().getType(); + switch (m) + { + case AIR: + case WATER: + case STATIONARY_WATER: + case LAVA: + case STATIONARY_LAVA: + return; + default: + { + event.setCancelled(true); + } + } + } + + @Command(hook = "tempadddef") + public boolean tempAddDef(CommandSender sender, String user, String group) + { + return tempAdd(sender, user, group, "604800"); + } + + @Command(hook = "tempadd") + public boolean tempAdd(CommandSender sender, String user, String group, String duration) + { + // Use it to make a proper duration output later. Too lazy rn. + @SuppressWarnings("unused") + int i = 0; + try + { + i = Integer.valueOf(duration); + } + catch (NumberFormatException e) + { + getLogger().message(sender, true, "That is not a valid number!"); + return true; + } + Bukkit.dispatchCommand(sender, "pex user " + user + " group add " + group + " * " + duration); + getLogger().message(sender, "Added to group " + group + "for " + duration + " seconds."); + return true; + } + + @Command(hook = "echo") + public boolean echo(CommandSender sender, String text) + { + sender.sendMessage(ChatAPI.colorify(null, text)); + return true; + } + + @Command(hook = "ping") + public boolean ping(CommandSender sender) + { + if (sender instanceof Player) + { + int ping = getPing((Player) sender); + getLogger().message(sender, "Your ping is " + ping + "ms."); + } + else + { + sender.sendMessage("Pong!"); + } + return true; + } + + @Command(hook = "ping2") + public boolean ping(CommandSender sender, String password) + { + if (password.equals("pong")) + if (sender instanceof Player) + { + int ping = getPing((Player) sender); + getLogger().message(sender, new String[] {"Your ping is " + ping + "ms.", ping < 20 + ? "&aThat's gr8 m8 r8 8/8" + : (ping < 50 ? "F&eair enough you cunt!" + : (ping < 100 ? "&eShite, but not shite enough." + : "&cLooks like the server is about two months ahead of you. GET A NEW FRIGGIN' ISP ALREADY"))}); + } + else + getLogger().message(sender, true, + "M8 you shitty cunt are not supposed to run this shit it's for players only!!!"); + else + getLogger().message(sender, true, "&4WRONG PASSWORD, 4/3 ATTEMPTS FAILED! BAN COMMENCING!"); + return true; + } + + public int getPing(Player player) + { + return ((CraftPlayer) player).getHandle().ping; + } + + @Command(hook = "sudo") + public boolean sudo(CommandSender sender, String name, String command) + { + CommandSender target; + if (name.equalsIgnoreCase("console")) + { + target = Bukkit.getConsoleSender(); + } + else + target = Bukkit.getPlayer(name); + if (target == null) + { + getLogger().message(sender, false, "That player couldn't be found!"); + return true; + } + if (command.startsWith("/") || target.equals(Bukkit.getConsoleSender())) + { + String[] args = command.split(" "); + for (String regex : sudoBlacklist) + { + if (args[0].matches((target.equals(Bukkit.getConsoleSender()) ? "" : "\\/") + regex)) + { + getLogger().message(sender, true, "You can't sudo anyone into using that command!"); + return true; + } + } + Bukkit.dispatchCommand(target, command.replaceFirst("/", "")); + getLogger().message(sender, "Sudoed " + Utils.getName(target) + "&7 into running " + command); + } + else + { + ((Player) target).chat(command); + getLogger().message(sender, "Sudoed " + Utils.getName(target) + "&7 into saying " + command); + } + return true; + } + + @Command(hook = "hasperm") + public boolean hasPerm(CommandSender sender, boolean noformat, String name, String node) + { + Player p; + if (name.contains("-")) + try + { + p = Bukkit.getPlayer(UUID.fromString(name)); + } + catch (Exception e) + { + if (noformat) + sender.sendMessage("ERR: Invalid UUID"); + else + getLogger().message(sender, "That UUID is not valid!"); + return true; + } + else + p = Bukkit.getPlayer(name); + if (p == null) + { + if (noformat) + { + Message m = new Message(sender, null); + m.appendText("ERR: Invalid player"); + m.send(); + } + else + { + getLogger().message(sender, "That player couldn't be found!"); + } + return true; + } + + if (noformat) + { + Message m = new Message(sender, null); + m.appendText("" + p.hasPermission(node)); + m.send(); + } + else + { + getLogger().message(sender, "" + p.hasPermission(node)); + } + + return true; + } + + public boolean canBuild(Player player, Location location) + { + BlockBreakEvent event = new BlockBreakEvent(location.getBlock(), player); + Bukkit.getPluginManager().callEvent(event); + return event.isCancelled(); + } + + PotionEffect nightvision = new PotionEffect(PotionEffectType.NIGHT_VISION, Integer.MAX_VALUE, 0, false, false); + + @Command(hook = "illuminate") + public void illuminate(CommandSender sender) + { + Player player = (Player) sender; + if (player.hasPotionEffect(PotionEffectType.NIGHT_VISION)) + { + player.removePotionEffect(PotionEffectType.NIGHT_VISION); + getLogger().message(sender, "Night Vision Disabled."); + } + else + { + player.addPotionEffect(nightvision, true); + getLogger().message(sender, "Night Vision Enabled."); + } + } + + @Command(hook = "minecart") + public void minecart(CommandSender sender) { + String type = (String) DataManager.getOrDefault(sender, "minecart_default", "normal"); + minecartDefault(sender, type); + } + + @Command(hook = "minecart_type") + public void minecartType(CommandSender sender, String type) { + Player p = (Player) sender; + if (!canBuild(p, p.getLocation())) { + ChatAPI.sendActionBar(sender, "&cYou do not have permission to build here!"); + return; + } + + EntityType typeE = convertMinecartTypeString(type); + + if (typeE != null) { + p.getWorld().spawnEntity(p.getLocation(), typeE); + ChatAPI.sendActionBar(sender, "&aMinecart Spawned!"); + } + else + ChatAPI.sendActionBar(sender, "&cThe type of Minecart you've requested does not exist."); + } + + @Command(hook = "minecart_default") + public void minecartDefault(CommandSender sender, String type) { + EntityType typeE = convertMinecartTypeString(type); + + if (typeE != null) { + DataManager.setData(sender, "minecart_default", type); + ChatAPI.sendActionBar(sender, "&aMinecart Spawned!"); + } + else + ChatAPI.sendActionBar(sender, "&cThe type of Minecart you've requested does not exist."); + } + + public EntityType convertMinecartTypeString(String type) { + EntityType typeE = null; + + switch (type) { + case "normal": typeE = EntityType.MINECART; + case "chest": typeE = EntityType.MINECART_CHEST; + case "furnace": typeE = EntityType.MINECART_FURNACE; + case "hopper": typeE = EntityType.MINECART_HOPPER; + case "tnt": typeE = EntityType.MINECART_TNT; + case "command": typeE = EntityType.MINECART_COMMAND; + case "spawner": typeE = EntityType.MINECART_MOB_SPAWNER; + } + + return typeE; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/motd/Motd.cmd b/src/main/java/com/redstoner/modules/motd/Motd.cmd new file mode 100644 index 0000000..987d1fe --- /dev/null +++ b/src/main/java/com/redstoner/modules/motd/Motd.cmd @@ -0,0 +1,14 @@ +command setmotd { + [string:motd...] { + help Sets the motd. Use --reset to reset to default; + run setmotd motd; + perm utils.setmotd; + } +} +command getmotd { + [empty] { + help Returns the motd; + run getmotd; + perm utils.getmotd; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/motd/Motd.java b/src/main/java/com/redstoner/modules/motd/Motd.java new file mode 100644 index 0000000..1334e1a --- /dev/null +++ b/src/main/java/com/redstoner/modules/motd/Motd.java @@ -0,0 +1,59 @@ +package com.redstoner.modules.motd; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.ServerListPingEvent; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Motd implements Module, Listener +{ + private String default_motd, motd; + + @Command(hook = "setmotd", async = AsyncType.ALWAYS) + public boolean setMotd(CommandSender sender, String motd) + { + if (motd.equals("--reset")) + this.motd = default_motd; + else + this.motd = motd; + getLogger().message(sender, "The new motd is:\n" + this.motd); + return true; + } + + @Command(hook = "getmotd", async = AsyncType.ALWAYS) + public boolean getMotd(CommandSender sender) + { + getLogger().message(sender, motd == null ? default_motd : motd); + return true; + } + + @EventHandler + public void onServerPing(ServerListPingEvent event) + { + event.setMotd(motd); + } + + @Override + public boolean onEnable() + { + default_motd = Bukkit.getMotd(); + if (default_motd == null) + { + default_motd = "§6Sample text\n§4FIX YOUR SERVER!"; + } + motd = default_motd; + return true; + } +} diff --git a/src/main/java/com/redstoner/modules/nametags/Nametags.cmd b/src/main/java/com/redstoner/modules/nametags/Nametags.cmd new file mode 100644 index 0000000..4095b42 --- /dev/null +++ b/src/main/java/com/redstoner/modules/nametags/Nametags.cmd @@ -0,0 +1,11 @@ +command tab { + sort { + help Resorts the entirety of tab.; + run sort; + } + sort [string:player] { + help Resorts one player.; + run sortspecific player; + } + perm utils.tab.admin; +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/nametags/Nametags.java b/src/main/java/com/redstoner/modules/nametags/Nametags.java new file mode 100644 index 0000000..3a66b18 --- /dev/null +++ b/src/main/java/com/redstoner/modules/nametags/Nametags.java @@ -0,0 +1,130 @@ +package com.redstoner.modules.nametags; + +import java.util.ArrayList; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.server.ServerCommandEvent; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 2, compatible = 4) +public class Nametags implements Module, Listener +{ + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) + { + sortSpecific(event.getPlayer()); + } + + @EventHandler + public void commandPreprocessEvent(PlayerCommandPreprocessEvent event) + { + ArrayList<Player> toSort = new ArrayList<>(); + if (event.getMessage().contains("promote") || event.getMessage().contains("demote") + || event.getMessage().matches("pex user .* group (set|add|leave)")) + { + String[] args = event.getMessage().split(" "); + for (String s : args) + { + Player p = Bukkit.getPlayer(s); + if (p != null) + toSort.add(p); + } + } + Bukkit.getScheduler().scheduleSyncDelayedTask(Main.plugin, new Runnable() + { + @Override + public void run() + { + for (Player p : toSort) + sortSpecific(p); + } + }); + } + + @EventHandler + public void consoleCommand(ServerCommandEvent event) + { + ArrayList<Player> toSort = new ArrayList<>(); + if (event.getCommand().contains("promote") || event.getCommand().contains("demote") + || event.getCommand().matches("pex user .* group (set|add|leave)")) + { + String[] args = event.getCommand().split(" "); + for (String s : args) + { + Player p = Bukkit.getPlayer(s); + if (p != null) + toSort.add(p); + } + } + Bukkit.getScheduler().scheduleSyncDelayedTask(Main.plugin, new Runnable() + { + @Override + public void run() + { + for (Player p : toSort) + sortSpecific(p); + } + }); + } + + @Command(hook = "sort") + public boolean sortAll(CommandSender sender) + { + for (Player p : Bukkit.getOnlinePlayers()) + sortSpecific(p); + getLogger().message(sender, "Sorted tab for ya!"); + return true; + } + + @Command(hook = "sortspecific") + public boolean sortSpecific(CommandSender sender, String player) + { + Player p = Bukkit.getPlayer(player); + if (p == null) + { + getLogger().message(sender, true, "That player couldn't be found!"); + return true; + } + else + sortSpecific(p); + getLogger().message(sender, "Sorted §e" + player + " §7for ya!"); + return true; + } + + public void sortSpecific(Player player) + { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), + "scoreboard teams join " + getTeam(player) + " " + player.getName()); + } + + private String getTeam(Player player) + { + String[] teams = new String[] {"admin", "mod", "trainingmod", "trusted", "builder", "member", "visitor", + "bots"}; + char prefix = 'a'; + for (String team : teams) + { + if (player.hasPermission("group." + team)) + { + return prefix + "_" + team; + } + prefix++; + } + return (prefix - 1) + "_" + teams[teams.length - 1]; + } +} diff --git a/src/main/java/com/redstoner/modules/naming/Naming.cmd b/src/main/java/com/redstoner/modules/naming/Naming.cmd new file mode 100644 index 0000000..1b9bc1a --- /dev/null +++ b/src/main/java/com/redstoner/modules/naming/Naming.cmd @@ -0,0 +1,24 @@ +command anvil { + [empty] { + run anvil; + type player; + help Opens anvil GUI.; + perm utils.anvil; + } +} +command name { + [string:name...] { + run name name; + type player; + help Names item in hand.; + perm utils.name; + } +} +command lore { + [optional:-a] [string:lore...] { + run lore -a lore; + type player; + help Adds lore to item in hand.; + perm utils.lore; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/naming/Naming.java b/src/main/java/com/redstoner/modules/naming/Naming.java new file mode 100644 index 0000000..9564966 --- /dev/null +++ b/src/main/java/com/redstoner/modules/naming/Naming.java @@ -0,0 +1,75 @@ +package com.redstoner.modules.naming; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; + +import net.md_5.bungee.api.ChatColor; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Naming implements Module +{ + @Command(hook = "anvil") + public void anvil(CommandSender sender) + { + Player player = (Player) sender; + Inventory inv = Bukkit.getServer().createInventory(player, InventoryType.ANVIL); + player.openInventory(inv); + } + + @Command(hook = "name") + public void name(CommandSender sender, String name) + { + name = ChatColor.translateAlternateColorCodes('&', name); + ItemStack item = ((Player) sender).getInventory().getItemInMainHand(); + ItemMeta meta = item.getItemMeta(); + if (meta == null) + { + getLogger().message(sender, true, "You can not rename that item!"); + return; + } + meta.setDisplayName(name); + item.setItemMeta(meta); + getLogger().message(sender, "Name set to " + name); + ((Player) sender).updateInventory(); + } + + @Command(hook = "lore") + public void lore(CommandSender sender, boolean append, String lore) + { + ItemStack item = ((Player) sender).getInventory().getItemInMainHand(); + ItemMeta meta = item.getItemMeta(); + if (meta == null) + { + getLogger().message(sender, true, "You can not change the lore of that item!"); + return; + } + List<String> currentLore; + if (append) + currentLore = meta.getLore(); + else + currentLore = new ArrayList<String>(); + if (currentLore == null) + currentLore = new ArrayList<String>(); + lore = ChatColor.translateAlternateColorCodes('&', lore); + currentLore.add(lore); + meta.setLore(currentLore); + item.setItemMeta(meta); + getLogger().message(sender, "Lore set to " + lore); + ((Player) sender).updateInventory(); + } +} diff --git a/src/main/java/com/redstoner/modules/onlineplayers/OnlinePlayers.java b/src/main/java/com/redstoner/modules/onlineplayers/OnlinePlayers.java new file mode 100644 index 0000000..f09d100 --- /dev/null +++ b/src/main/java/com/redstoner/modules/onlineplayers/OnlinePlayers.java @@ -0,0 +1,92 @@ +package com.redstoner.modules.onlineplayers; + +import java.io.File; + +import org.bukkit.Bukkit; +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.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Version; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +@AutoRegisterListener +@Version(major = 4, minor = 0, revision = 3, compatible = 4) +@SuppressWarnings("unchecked") +public class OnlinePlayers implements Module, Listener +{ + private File saveFile = null; + private JSONObject output = null; + private JSONArray players = null; + + @Override + public void postEnable() + { + saveFile = new File(Main.plugin.getDataFolder(), "players.json"); + output = new JSONObject(); + players = new JSONArray(); + output.put("dataFormat", "v2"); + rescan(); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerJoin(PlayerJoinEvent event) + { + add(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerQuitEvent event) + { + remove(event.getPlayer()); + } + + public void rescan() + { + players = new JSONArray(); + for (Player p : Bukkit.getOnlinePlayers()) + add(p); + save(); + } + + public synchronized void add(Player player) + { + JSONObject jsonPlayer = new JSONObject(); + jsonPlayer.put("name", player.getName()); + jsonPlayer.put("UUID", player.getUniqueId().toString()); + jsonPlayer.put("joined", System.currentTimeMillis()); + jsonPlayer.put("vanished", DataManager.getState(player, "vanished")); + jsonPlayer.put("afk", DataManager.getState(player, "afk")); + players.add(jsonPlayer); + save(); + } + + public synchronized void remove(Player player) + { + JSONArray toRemove = new JSONArray(); + for (Object obj : players) + { + JSONObject o = (JSONObject) obj; + if (((String) o.get("UUID")).equals(player.getUniqueId().toString())) + toRemove.add(obj); + } + players.removeAll(toRemove); + save(); + } + + public synchronized void save() + { + output.put("players", players); + output.put("amount", players.size()); + JsonManager.save((JSONObject) output.clone(), saveFile); + } +} diff --git a/src/main/java/com/redstoner/modules/reports/Reports.cmd b/src/main/java/com/redstoner/modules/reports/Reports.cmd new file mode 100644 index 0000000..336c418 --- /dev/null +++ b/src/main/java/com/redstoner/modules/reports/Reports.cmd @@ -0,0 +1,24 @@ +command report { + [string:message...] { + type player; + help Report a player or incident; + run report message; + } +} +command rp { + perm utils.report; + + open { + help List all open reports; + run report_open; + } + close [int:id] { + help Close a report; + run report_close id; + } + tp [int:id] { + help Teleport to the location of a report; + run report_tp id; + type player; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/reports/Reports.java b/src/main/java/com/redstoner/modules/reports/Reports.java new file mode 100644 index 0000000..0e55ccc --- /dev/null +++ b/src/main/java/com/redstoner/modules/reports/Reports.java @@ -0,0 +1,154 @@ +package com.redstoner.modules.reports; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; + +import net.md_5.bungee.api.ChatColor; + +/** Report module. Allows reports to be created and handled by staff + * + * @author Redempt */ +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Reports implements Module +{ + private int task = 0; + private JSONArray reports; + private JSONArray archived; + private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd kk:mm"); + + @Override + public boolean onEnable() + { + reports = JsonManager.getArray(new File(Main.plugin.getDataFolder(), "reports.json")); + archived = JsonManager.getArray(new File(Main.plugin.getDataFolder(), "archived_reports.json")); + if (reports == null) + reports = new JSONArray(); + if (archived == null) + archived = new JSONArray(); + // Notify online staff of open reports + task = Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.plugin, () -> + { + if (reports.size() <= 0) + { + return; + } + for (Player player : Bukkit.getOnlinePlayers()) + { + if (player.hasPermission("utils.report")) + { + getLogger().message(player, "&cThere are &e" + reports.size() + + " &copen reports!"); + } + } + getLogger().info("&cThere are &e" + reports.size() + + " &copen reports!"); + }, 2400, 2400); + return true; + } + + @Override + public void onDisable() + { + // Save reports, cancel notifier task + Bukkit.getScheduler().cancelTask(task); + JsonManager.save(reports, new File(Main.plugin.getDataFolder(), "reports.json")); + JsonManager.save(archived, new File(Main.plugin.getDataFolder(), "archived_reports.json")); + } + + @Command(hook = "report_tp") + public void tpReport(CommandSender sender, int id) + { + // Check for invalid ID + Player player = (Player) sender; + if (id > reports.size() - 1 || id < 0) + { + getLogger().message(sender, true, "Invalid ID!"); + return; + } + JSONObject report = (JSONObject) reports.get(id); + String loc = (String) report.get("location"); + String[] split = loc.split(";"); + // Location from string + int x = Integer.parseInt(split[0]); + int y = Integer.parseInt(split[1]); + int z = Integer.parseInt(split[2]); + World world = Bukkit.getWorld(split[3]); + Location location = new Location(world, x, y, z); + player.teleport(location); + } + + @SuppressWarnings("unchecked") + @Command(hook = "report_close") + public void closeReport(CommandSender sender, int id) + { + // Check for invalid ID + if (id > reports.size() - 1 || id < 0) + { + getLogger().message(sender, true, "Invalid ID!"); + return; + } + // Move report to archived reports + JSONObject report = (JSONObject) reports.get(id); + reports.remove(id); + archived.add(report); + sender.sendMessage(ChatColor.GREEN + "Report #" + id + " closed!"); + } + + @Command(hook = "report_open") + public void listOpen(CommandSender sender) + { + int i = 0; + for (Object object : reports) + { + JSONObject report = (JSONObject) object; + String message = ""; + message += ChatColor.DARK_GRAY + "[" + ChatColor.YELLOW + i + ChatColor.DARK_GRAY + "]"; + message += "[" + ChatColor.YELLOW + report.get("time") + ChatColor.DARK_GRAY + "] "; + message += ChatColor.DARK_AQUA + "" + report.get("name"); + message += ChatColor.WHITE + ": " + ChatColor.YELLOW + report.get("message"); + sender.sendMessage(message); + i++; + } + if (i == 0) + { + sender.sendMessage(ChatColor.GREEN + "There are no open reports."); + } + } + + @SuppressWarnings("unchecked") + @Command(hook = "report") + public void report(CommandSender sender, String message) + { + Player player = (Player) sender; + // Create report JSONObject + JSONObject report = new JSONObject(); + report.put("name", player.getName()); + report.put("time", dateFormat.format(new Date())); + report.put("message", message); + String loc = ""; + // Location to string + loc += player.getLocation().getBlockX() + ";" + player.getLocation().getBlockY() + ";" + + player.getLocation().getBlockZ() + ";" + player.getLocation().getWorld().getName(); + report.put("location", loc); + reports.add(report); + sender.sendMessage(ChatColor.GREEN + "Report created!"); + } +} diff --git a/src/main/java/com/redstoner/modules/saylol/Saylol.cmd b/src/main/java/com/redstoner/modules/saylol/Saylol.cmd new file mode 100644 index 0000000..8cc4d44 --- /dev/null +++ b/src/main/java/com/redstoner/modules/saylol/Saylol.cmd @@ -0,0 +1,47 @@ +command lol { + add [string:text...] { + help Lols a text.; + run addlol text; + perm utils.lol.admin; + } + del [int:id] { + help Unlols a lol.; + run dellol id; + perm utils.lol.admin; + } + set [int:id] [string:text...] { + help Relols a lol.; + run setlol id text; + perm utils.lol.admin; + } + id [int:id] { + help Lols specifically.; + run lolid id; + perm utils.lol.id; + } + list [int:page] { + help Shows lols.; + run listlols page; + perm utils.lol.list; + } + list { + help Shows lols.; + run listlolsdef; + perm utils.lol.list; + } + search [flag:-i] [string:text...] { + help Search lols.; + run searchlol -i text; + perm utils.lol.search; + } + match [flag:-i] [string:regex...] { + help Search lols. But better.; + run matchlol -i regex; + perm utils.lol.match; + } + [empty] { + help Lols.; + run saylol; + perm utils.lol; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/saylol/Saylol.java b/src/main/java/com/redstoner/modules/saylol/Saylol.java new file mode 100644 index 0000000..7081aec --- /dev/null +++ b/src/main/java/com/redstoner/modules/saylol/Saylol.java @@ -0,0 +1,300 @@ +package com.redstoner.modules.saylol; + +import java.io.File; +import java.util.Random; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.json.simple.JSONArray; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.ignore.Ignore; + +import net.nemez.chatapi.ChatAPI; +import net.nemez.chatapi.click.ClickCallback; +import net.nemez.chatapi.click.Message; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Saylol implements Module +{ + private long lastLol = 0; + private File lolLocation = new File(Main.plugin.getDataFolder(), "lol.json"); + private JSONArray lols, handlers; + private final String LOL_PREFIX = "§8[§blol§8] "; + + @SuppressWarnings("unchecked") + @Override + public boolean onEnable() + { + lols = JsonManager.getArray(lolLocation); + if (lols == null) + lols = new JSONArray(); + handlers = new JSONArray(); + for (int i = 0; i < lols.size(); i++) + handlers.add(new ClickCallback(true, true, "") + { + @Override + public void run(CommandSender sender) + { + if (handlers.contains(this)) + clickAction((Player) sender, handlers.indexOf(this)); + else + getLogger().message(sender, true, "That lol no longer exists!"); + } + }); + return true; + } + + @Override + public void onDisable() + { + saveLolsSync(); + } + + @SuppressWarnings("unchecked") + @Command(hook = "addlol") + public boolean addLol(CommandSender sender, String text) + { + if (lols.contains(text)) + getLogger().message(sender, true, "This lol already exists!"); + else + { + getLogger().message(sender, "Successfully added a new lol!"); + lols.add("&e" + text); + handlers.add(new ClickCallback(true, true, "") + { + @Override + public void run(CommandSender sender) + { + if (handlers.contains(this)) + clickAction((Player) sender, handlers.indexOf(this)); + else + getLogger().message(sender, true, "That lol no longer exists!"); + } + }); + saveLols(); + } + return true; + } + + @Command(hook = "dellol") + public boolean delLol(CommandSender sender, int id) + { + if (lols.size() == 0) + { + getLogger().message(sender, true, "There are no lols yet!"); + return true; + } + if (id < 0 || id >= lols.size()) + { + getLogger().message(sender, true, "The ID must be at least 0 and at most " + (lols.size() - 1)); + return true; + } + getLogger().message(sender, "Successfully deleted the lol: " + lols.remove(id)); + handlers.remove(id); + saveLols(); + return true; + } + + @SuppressWarnings("unchecked") + @Command(hook = "setlol") + public boolean setLol(CommandSender sender, int id, String text) + { + if (lols.size() == 0) + { + getLogger().message(sender, true, "There are no lols yet!"); + return true; + } + if (id < 0 || id >= lols.size()) + { + getLogger().message(sender, true, "The ID must be at least 0 and at most " + (lols.size() - 1)); + return true; + } + getLogger().message(sender, "Successfully changed the lol: &e" + lols.get(id) + " &7to: &e" + text); + lols.set(id, text); + saveLols(); + return true; + } + + @Command(hook = "lolid") + public boolean lolId(CommandSender sender, int id) + { + if (lols.size() == 0) + { + getLogger().message(sender, true, "There are no lols yet!"); + return true; + } + long time = System.currentTimeMillis(); + if (time - lastLol < 15000) + { + getLogger().message(sender, true, + "You can't use saylol for another " + (14 - (int) Math.ceil((time - lastLol) / 1000)) + "s."); + return true; + } + if (id < 0 || id >= lols.size()) + { + getLogger().message(sender, true, "The ID must be at least 0 and at most " + (lols.size() - 1)); + return true; + } + String name; + if (sender instanceof Player) + name = ((Player) sender).getDisplayName(); + else + name = "&9" + sender.getName(); + Utils.broadcast(LOL_PREFIX, ChatAPI.colorify(null, name + "&8: &e" + lols.get(id)), new BroadcastFilter() + { + @Override + public boolean sendTo(CommandSender recipient) + { + return recipient.hasPermission("utils.lol.see"); + } + }); + lastLol = time; + return true; + } + + @Command(hook = "saylol") + public boolean saylol(CommandSender sender) + { + if (lols.size() == 0) + { + getLogger().message(sender, true, "There are no lols yet!"); + return true; + } + long time = System.currentTimeMillis(); + if (time - lastLol < 15000) + { + getLogger().message(sender, true, + "You can't use saylol for another " + (14 - (int) Math.ceil((time - lastLol) / 1000)) + "s."); + return true; + } + String name; + if (sender instanceof Player) + name = ((Player) sender).getDisplayName(); + else + name = "&9" + sender.getName(); + Random random = new Random(); + int id = random.nextInt(lols.size()); + Utils.broadcast(LOL_PREFIX, ChatAPI.colorify(null, name + "&8: &e" + lols.get(id)), + ModuleLoader.exists("Ignore")? Ignore.getIgnoredBy(sender) : null); + lastLol = time; + return true; + } + + @Command(hook = "listlols") + public boolean listLols(CommandSender sender, int page) + { + if (lols.size() == 0) + { + getLogger().message(sender, true, "There are no lols yet!"); + return true; + } + page = page - 1; + int start = page * 10; + int end = start + 10; + int pages = (int) Math.ceil(lols.size() / 10d); + if (start < 0) + { + getLogger().message(sender, true, "Page number too small, must be at least 0!"); + return true; + } + if (start > lols.size()) + { + getLogger().message(sender, true, "Page number too big, must be at most " + pages + "!"); + return true; + } + Message m = new Message(sender, null); + m.appendText(getLogger().getHeader().replace("\n", "")); + m.appendText("&ePage " + (page + 1) + "/" + pages + ":"); + for (int i = start; i < end && i < lols.size(); i++) + m.appendCallback("\n&a" + i + "&8: &e" + lols.get(i), getCallback(i)); + m.send(); + return true; + } + + @Command(hook = "listlolsdef") + public boolean listLolsDefault(CommandSender sender) + { + return listLols(sender, 1); + } + + @Command(hook = "searchlol") + public boolean search(CommandSender sender, boolean sensitive, String text) + { + Message m = new Message(sender, null); + m.appendText(getLogger().getHeader().replace("\n", "")); + boolean found = false; + if (!sensitive) + text = text.toLowerCase(); + for (int i = 0; i < lols.size(); i++) + { + String lol = (String) lols.get(i); + if ((sensitive ? lol : lol.toLowerCase()).contains(text)) + { + m.appendCallback("\n&a" + i + "&8: &e" + lol, getCallback(i)); + found = true; + } + } + if (!found) + getLogger().message(sender, "&cCouldn't find any matching lols."); + else + m.send(); + return true; + } + + @Command(hook = "matchlol") + public boolean match(CommandSender sender, boolean sensitive, String regex) + { + Message m = new Message(sender, null); + m.appendText(getLogger().getHeader().replace("\n", "")); + boolean found = false; + if (!sensitive) + regex = regex.toLowerCase(); + for (int i = 0; i < lols.size(); i++) + { + String lol = (String) lols.get(i); + if ((sensitive ? lol : lol.toLowerCase()).matches(regex)) + { + m.appendCallback("\n&a" + i + "&8: &e" + lol, getCallback(i)); + found = true; + } + } + if (!found) + getLogger().message(sender, "&cCouldn't find any matching lols."); + else + m.send(); + return true; + } + + public void saveLols() + { + JsonManager.save(lols, lolLocation); + } + + public void saveLolsSync() + { + JsonManager.saveSync(lols, lolLocation); + } + + public ClickCallback getCallback(int index) + { + return (ClickCallback) handlers.get(index); + } + + public void clickAction(Player player, int index) + { + if (player.hasPermission("utils.lol.id")) + Bukkit.dispatchCommand(player, "lol id " + index); + } +} diff --git a/src/main/java/com/redstoner/modules/scriptutils/Scriptutils.cmd b/src/main/java/com/redstoner/modules/scriptutils/Scriptutils.cmd new file mode 100644 index 0000000..c8498b2 --- /dev/null +++ b/src/main/java/com/redstoner/modules/scriptutils/Scriptutils.cmd @@ -0,0 +1,119 @@ +command script_restart { + [string:timeout] [string:name] [string:reason] { + help Prints bukkit restart message; + type console; + run script_restart timeout name reason; + } +} +command script_stop { + [string:timeout] [string:name] [string:reason] { + help Prints bukkit shut down message; + type console; + run script_stop timeout name reason; + } +} +command script_restart_abort { + [empty] { + help Prints the restart abort message; + type console; + run script_restart_abort; + } +} +command script_stop_abort { + [empty] { + help Prints the shut down abort message; + type console; + run script_stop_abort; + } +} +command script_backup_begin { + [empty] { + help Prints the backup started message, saves all worlds and turns off world saving; + type console; + run script_backup_begin; + } +} +command script_backup_end { + [empty] { + help Prints the backup finished message and turns on world saving; + type console; + run script_backup_end; + } +} +command script_backup_error { + [empty] { + help Prints the backup error message and turns on world saving; + type console; + run script_backup_error; + } +} +command script_trim { + [empty] { + help Prints the world trimming started message and starts trimming; + type console; + run script_trim; + } +} +command script_trim_result { + [string:size] [string:data...] { + help Prints the trimming finished message; + type console; + run script_trim_result size data; + } +} +command script_backup_database_begin { + [empty] { + help Prints the database backup started message and admin-chat warning; + type console; + run script_backup_database_begin; + } +} +command script_backup_database_dumps { + [empty] { + help Prints the database dumps cmpression started message; + type console; + run script_backup_database_dumps; + } +} +command script_backup_database_end { + [string:size] { + help Prints the database finished message and backup size in admin-chat; + type console; + run script_backup_database_end size; + } +} +command script_backup_database_error { + [empty] { + help Prints the database backup error message; + type console; + run script_backup_database_error; + } +} +command script_backup_database_abort { + [empty] { + help Prints the database backup abort message; + type console; + run script_backup_database_abort; + } +} +command script_spigot_update { + [empty] { + help Prints the spigot update message; + type console; + run script_spigot_update; + } +} +command script_disk_filled { + [string:percentage] { + help Prints the admin-chat warning for disk is filled; + type console; + run script_disk_filled percentage; + } +} +command script_shutdown { + [string:reason] { + help Saves all worlds, kicks players and shuts down the server; + type console; + run script_shutdown reason; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/scriptutils/Scriptutils.java b/src/main/java/com/redstoner/modules/scriptutils/Scriptutils.java new file mode 100644 index 0000000..1d634c0 --- /dev/null +++ b/src/main/java/com/redstoner/modules/scriptutils/Scriptutils.java @@ -0,0 +1,177 @@ +package com.redstoner.modules.scriptutils; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Scriptutils implements Module +{ + /** Prints Bukkit restart message + * arg 0 timeout + * arg 1 $(whoami); + * arg 2: reason */ + @Command(hook = "script_restart") + public void print_restart(CommandSender sender, String timeout, String name, String reason) + { + Utils.broadcast("", "§2§l=============================================", null); + Utils.broadcast("", "§r", null); + Utils.broadcast("", "§r", null); + Utils.broadcast("", "§9" + name + " is restarting the server.", null); + Utils.broadcast("", "§a§lServer is going to restart in " + timeout + " seconds.", null); + Utils.broadcast("", "§6§l" + reason, null); + Utils.broadcast("", "§r", null); + Utils.broadcast("", "§r", null); + Utils.broadcast("", "§2§l=============================================", null); + } + + /** Prints the Bukkit shut down message + * arg 0 timeout + * arg 1 $(whoami); + * arg 2: reason */ + @Command(hook = "script_stop") + public void print_stop(CommandSender sender, String timeout, String name, String reason) + { + Utils.broadcast("", "§2§l=============================================", null); + Utils.broadcast("", "§r", null); + Utils.broadcast("", "§r", null); + Utils.broadcast("", "§9" + name + " is shutting down the server.", null); + Utils.broadcast("", "§a§lServer is going to shut down in " + timeout + " seconds.", null); + Utils.broadcast("", "§6§l" + reason, null); + Utils.broadcast("", "§r", null); + Utils.broadcast("", "§r", null); + Utils.broadcast("", "§2§l=============================================", null); + } + + /** Prints the shut down abort message */ + @Command(hook = "script_stop_abort") + public void abort_stop(CommandSender sender) + { + Utils.broadcast("", "§4§oShut down has been aborted.", null); + } + + /** Prints the restart abort message */ + @Command(hook = "script_restart_abort") + public void abort_restart(CommandSender sender) + { + Utils.broadcast("", "§4§oRestart has been aborted.", null); + } + + /** Prints the backup started message, saves all worlds and turns off world saving */ + @Command(hook = "script_backup_begin") + public void print_backup_begin(CommandSender sender) + { + Utils.broadcast("", "§4 =§2 Starting backup now.", null); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "save-all"); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "save-off"); + } + + /** Prints the backup finished message and turns on world saving */ + @Command(hook = "script_backup_end") + public void print_backup_end(CommandSender sender) + { + Utils.broadcast("", "§4 =§2 Backup completed.", null); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "save-on"); + } + + /** Prints the backup error message and turns on world saving */ + @Command(hook = "script_backup_error") + public void print_backup_error(CommandSender sender) + { + Utils.broadcast("", "§4 =§c§l Error while backing up!", null); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "save-on"); + } + + /** Prints the world trimming started message and starts trimming */ + @Command(hook = "script_trim") + public void print_backup_trim(CommandSender sender) + { + Utils.broadcast("", "§4 =§3 Deleting all chunks beyond border now.", null); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "wb Creative trim 1000000 15"); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "wb trim confirm"); + } + + /** Prints the trimming finished message + * arg 0 size difference of world + * arg 1: world border trim data */ + @Command(hook = "script_trim_result") + public void print_backup_trim_res(CommandSender sender, String size, String data) + { + Utils.broadcast("", "§4 =§3 Chunk deletion saved " + data + " (§a" + size + "MB§3)", null); + } + + /** Prints the database backup started message and admin-chat warning */ + @Command(hook = "script_backup_database_begin") + public void print_backup_db_begin(CommandSender sender) + { + Utils.broadcast("", "§6 =§2 Starting database backup now.", null); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "ac §aLogblock may be unavailable!"); + } + + /** Prints the database dumps compression started message */ + @Command(hook = "script_backup_database_dumps") + public void print_backup_db_dumps(CommandSender sender) + { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "ac §aDumps completed, logblock available again."); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "ac §aNow compressing dumps, will take a while..."); + } + + /** Prints the database finished message and backup size in admin-chat + * arg 0 size of backup */ + @Command(hook = "script_backup_database_end") + public void print_backup_db_end(CommandSender sender, String size) + { + Utils.broadcast("", "§6 =§2 Database backup completed.", null); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "ac §abackup size: §2" + size + "MB§a."); + } + + /** Prints the database backup error message */ + @Command(hook = "script_backup_database_error") + public void print_backup_db_error(CommandSender sender) + { + Utils.broadcast("", "§6 =§c§l Error while backing up database!", null); + } + + /** Prints the database backup abort message */ + @Command(hook = "script_backup_database_abort") + public void print_backup_db_abort(CommandSender sender) + { + Utils.broadcast("", "§6 =§2 Database backup aborted.", null); + } + + /** Prints the spigot update message */ + @Command(hook = "script_spigot_update") + public void print_update(CommandSender sender) + { + Utils.broadcast("", "§9 =§2 A new Spigot version has been downloaded!", null); + Utils.broadcast("", "§9 =§2 Update will be applied after the next reboot.", null); + } + + /** Prints the admin-chat warning for disk is filled + * arg 0 fill percentage */ + @Command(hook = "script_disk_filled") + public void print_disk_filled(CommandSender sender, String percentage) + { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), + "ac §4§lWARNING:§6 Disk is filled > 96% (" + percentage + "%);"); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "ac §4 Server will shut down at 98%!"); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "ac §4 Contact an admin §nimmediately§4!"); + } + + /** Saves all worlds, kicks players and shuts down the server + * arg 0: reason */ + @Command(hook = "script_shutdown") + public void shutdown(CommandSender sender, String reason) + { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "save-all"); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "kickall " + reason); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "stop"); + } +} diff --git a/src/main/java/com/redstoner/modules/seen/Seen.cmd b/src/main/java/com/redstoner/modules/seen/Seen.cmd new file mode 100644 index 0000000..d17e655 --- /dev/null +++ b/src/main/java/com/redstoner/modules/seen/Seen.cmd @@ -0,0 +1,53 @@ +command seen { + [string:player] { + help Displays information about a player.; + perm utils.seen; + run seen player; + } + + [string:player] [flag:ips] { + help Displays information about a player.; + perm utils.seen; + run seen2 player ips; + } +} +command firstseen { + [empty] { + run firstseen; + type player; + help Gives the date and time they first joined; + perm utils.firstseen; + } + [string:person] { + run firstseenP person; + help Gives the date and time when a player first joined; + perm utils.firstseen.other; + } +} +command playtime { + [empty] { + type player; + run playtimeDef; + perm utils.playtime; + help Displays your total playtime!; + } + [string:name] { + run playtime name; + perm utils.playtime.others; + help Displays the playtime of another player. The player must be online!; + } +} + +command uuid { + [empty] { + type player; + run uuidDef; + perm utils.uuid; + help Displays your UUID (click to copy); + } + [string:name] { + run uuid name; + perm utils.uuid.other; + help Displays someone elses UUID (click to copy); + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/seen/Seen.java b/src/main/java/com/redstoner/modules/seen/Seen.java new file mode 100644 index 0000000..ed3324c --- /dev/null +++ b/src/main/java/com/redstoner/modules/seen/Seen.java @@ -0,0 +1,320 @@ +package com.redstoner.modules.seen; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.Statistic; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.earth2me.essentials.utils.DateUtil; +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +import net.nemez.chatapi.click.Message; + +@AutoRegisterListener +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 10, compatible = 4) +public class Seen implements Module, Listener +{ + HashMap<UUID, JSONArray> names = new HashMap<>(); + HashMap<UUID, JSONArray> ips = new HashMap<>(); + + @Override + public void postEnable() + { + Module.super.postEnable(); + for (Player player : Bukkit.getOnlinePlayers()) + loadData(player); + } + + @Command(hook = "seen", async = AsyncType.ALWAYS) + public boolean seen(CommandSender sender, String player) + { + return seen(sender, player, false); + } + + @SuppressWarnings("deprecation") + @Command(hook = "seen2", async = AsyncType.ALWAYS) + public boolean seen(CommandSender sender, String player, boolean show_ips) + { + ArrayList<String> message = new ArrayList<>(); + OfflinePlayer p; + if (Utils.isUUID(player)) + p = Bukkit.getOfflinePlayer(UUID.fromString(player)); + else + p = Bukkit.getPlayer(player); + boolean cansee = (sender instanceof Player ? p instanceof Player && ((Player) sender).canSee((Player) p) + : true); + if (p == null) + { + p = Bukkit.getOfflinePlayer(player); + if (p != null) + p = Bukkit.getOfflinePlayer(p.getUniqueId()); + } + if (p == null || (!p.isOnline() && !p.hasPlayedBefore()) || (!cansee && !p.getName().equalsIgnoreCase(player))) + { + getLogger().message(sender, true, "§e" + player + "§7 has never joined the server!"); + return true; + } + boolean online = cansee ? p instanceof Player : false; + String state; + long timestamp; + if (online) + { + state = "&aonline"; + timestamp = (long) DataManager.getData(p.getUniqueId().toString(), "lastjoined"); + } + else + { + state = "&coffline"; + timestamp = (long) DataManager.getOrDefault(p.getUniqueId().toString(), "lastquit", p.getLastPlayed()); + } + String time = DateUtil.formatDateDiff(timestamp); + message.add("&e" + p.getName() + " &7has been " + state + " &7for &e" + time + "&7."); + JSONArray _names; + if (online) + { + if (DataManager.getState((Player) p, "afk")) + { + message.add("They're currently &eAFK&7:"); + String reason = (String) DataManager.getOrDefault(p.getUniqueId().toString(), "AFK", "afk_reason", ""); + Long timeAFK = (Long) DataManager.getOrDefault(p.getUniqueId().toString(), "AFK", "afk_time", 0L); + + message.add(" &9For: " + DateUtil.formatDateDiff(timeAFK)); + if (reason.length() >= 1) + message.add(" &9Reason: " + reason); + } + if (DataManager.getState((Player) p, "vanished")) + message.add("They're currently &evanished&7!"); + _names = names.get(p.getUniqueId()); + } + else + { + _names = loadNames(p.getUniqueId()); + } + if (_names != null && _names.size() > 1) + message.add("They've also been known as: &e" + + _names.toJSONString().replaceAll("[\"\\[\\]]", "").replace(",", "&7, &e")); + if (sender.hasPermission("utils.seen.ip")) + { + if (show_ips) + { + JSONArray _ips; + if (online) + _ips = ips.get(p.getUniqueId()); + else + _ips = loadIPs(p.getUniqueId()); + if (_ips != null && _ips.size() > 0) + message.add("They've joined with the following IPs: &e" + + _ips.toJSONString().replaceAll("[\"\\[\\]]", "").replace(",", "&7, &e")); + } + message.add( + "Their current IP is: &a" + DataManager.getOrDefault(p.getUniqueId().toString(), "ip", "unknown")); + } + getLogger().message(sender, message.toArray(new String[] {})); + return true; + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) + { + DataManager.setData(event.getPlayer(), "lastjoined", System.currentTimeMillis()); + DataManager.setData(event.getPlayer(), "ip", event.getPlayer().getAddress().getHostString()); + loadData(event.getPlayer()); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) + { + DataManager.setData(event.getPlayer(), "lastquit", System.currentTimeMillis()); + unloadData(event.getPlayer()); + } + + @SuppressWarnings("unchecked") + public void loadData(Player player) + { + Thread t = new Thread(new Runnable() + { + @Override + public void run() + { + File jsonfile = new File(Main.plugin.getDataFolder(), "/seen/" + Utils.getID(player) + ".json"); + JSONObject json = JsonManager.getObject(jsonfile); + if (json == null) + { + json = new JSONObject(); + json.put("names", new JSONArray()); + json.put("ips", new JSONArray()); + } + JSONArray lnames = (JSONArray) json.get("names"); + if (!lnames.contains(player.getName())) + lnames.add(player.getName()); + json.put("names", lnames); + + JSONArray lips = (JSONArray) json.get("ips"); + String ip = player.getAddress().getHostString(); + if (!lips.contains(ip)) + lips.add(ip); + json.put("ips", lips); + + names.put(player.getUniqueId(), lnames); + ips.put(player.getUniqueId(), lips); + JsonManager.save(json, jsonfile); + } + }); + t.start(); + } + + public void unloadData(Player player) + { + this.names.remove(player.getUniqueId()); + this.ips.remove(player.getUniqueId()); + } + + public JSONArray loadNames(UUID uuid) + { + File jsonfile = new File(Main.plugin.getDataFolder(), "/seen/" + uuid + ".json"); + JSONObject json = JsonManager.getObject(jsonfile); + if (json == null) + return null; + else + return (JSONArray) json.get("names"); + } + + public JSONArray loadIPs(UUID uuid) + { + File jsonfile = new File(Main.plugin.getDataFolder(), "/seen/" + uuid + ".json"); + JSONObject json = JsonManager.getObject(jsonfile); + if (json == null) + return null; + else + return (JSONArray) json.get("ips"); + } + + @SuppressWarnings("deprecation") + @Command(hook = "firstseenP") + public void firstseen(CommandSender sender, String person) + { + OfflinePlayer oPlayer = Bukkit.getPlayer(person); + if (oPlayer == null) + oPlayer = Bukkit.getServer().getOfflinePlayer(person); + Long firstJoin = oPlayer.getFirstPlayed(); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + String disDate = format.format(new Date(firstJoin)); + if (disDate.equals("1970-01-01 00:00")) + { + getLogger().message(sender, true, "&3" + oPlayer.getName() + "&c has never joined."); + } + else + { + getLogger().message(sender, "&3" + oPlayer.getName() + " &efirst joined&a " + disDate + "&e."); + } + } + + @Command(hook = "firstseen") + public void firstseen(CommandSender sender) + { + firstseen(sender, sender.getName()); + } + + @Command(hook = "playtimeDef") + public boolean playtime(CommandSender sender) + { + return playtime(sender, sender.getName()); + } + + @Command(hook = "playtime") + public boolean playtime(CommandSender sender, String name) + { + if (name == null) + name = sender.getName(); + Player player = Bukkit.getPlayer(name); + if (player == null) + { + getLogger().message(sender, true, "§e" + name + + "§7 couldn't be found! Hint: Currently, you can only check statistics of players that are online!"); + return true; + } + int ticks_lived = player.getStatistic(Statistic.PLAY_ONE_TICK); + int days = ticks_lived / 1728000; + int hours = (ticks_lived % 1728000) / 72000; + int minutes = (ticks_lived % 72000) / 1200; + if (sender.getName().equals(name)) + { + getLogger().message(sender, + "You have played for &b" + + (days == 0 && hours == 0 && minutes == 0 ? "less than a minute." + : ("a total of: &e" + (days != 0 ? (days + "d ") : "") + + ((hours != 0 || days != 0) ? (hours + "h ") : "") + + ((minutes != 0 || hours != 0 || days != 0) ? (minutes + "m") : ""))) + + "&7."); + } + else + { + getLogger().message(sender, "&3" + name + " &7has played for " + + (days == 0 && hours == 0 && minutes == 0 ? "less than a minute." + : ("a total of: &e" + (days != 0 ? (days + "d ") : "") + + ((hours != 0 || days != 0) ? (hours + "h ") : "") + + ((minutes != 0 || hours != 0 || days != 0) ? (minutes + "m") : ""))) + + "&7."); + } + return true; + } + + @Command(hook = "uuidDef") + public boolean uuid(CommandSender sender) + { + Player player = (Player) sender; + Message m = new Message(sender, null); + m.appendText(getLogger().getPrefix()); + m.appendSuggestHover("&6> UUID: &e" + player.getUniqueId().toString(), player.getUniqueId().toString(), + "Click to copy into chatbox!"); + m.send(); + return true; + } + + @SuppressWarnings("deprecation") + @Command(hook = "uuid") + public boolean uuid(CommandSender sender, String name) + { + OfflinePlayer player = Bukkit.getPlayer(name); + if (player == null) + { + player = Bukkit.getOfflinePlayer(name); + if (player == null) + { + getLogger().error("That player couldn't be found!"); + return true; + } + } + Message m = new Message(sender, null); + m.appendText(getLogger().getPrefix()); + m.appendSuggestHover("&6> UUID: &e" + player.getUniqueId().toString(), player.getUniqueId().toString(), + "Click to copy into chatbox!"); + m.send(); + return true; + } +} diff --git a/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.cmd b/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.cmd new file mode 100644 index 0000000..1cfb0fd --- /dev/null +++ b/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.cmd @@ -0,0 +1,14 @@ +command signalstrength { + alias ss; + perm utils.signalstrength; + [int:strength] { + run ss strength; + type player; + help "Sets the amount of items in a container to achieve the given signal strength. Uses redstone dust."; + } + [int:strength] [string:material] { + run ssm strength material; + type player; + help "Sets the amount of itmes in a container to achieve the given signal strength. Uses the material specified."; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.java b/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.java new file mode 100644 index 0000000..b613b09 --- /dev/null +++ b/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.java @@ -0,0 +1,194 @@ +package com.redstoner.modules.signalstrength; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.Nameable; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 2, compatible = 4) +public class SignalStrength implements Module +{ + + private static final String namePrefix = ChatColor.GREEN.toString() + ChatColor.RESET + ChatColor.DARK_PURPLE + + "Signal Strength: " + ChatColor.RED + ChatColor.BOLD; + + private static String nameForSignalStrength(int strength) + { + return namePrefix + strength; + } + + private static boolean isSignalStrengthNameOrEmpty(String name) + { + return name == null || name.isEmpty() || name.startsWith(namePrefix); + } + + @Command(hook = "ss") + public boolean ss(CommandSender sender, int strength) + { + return ssm(sender, strength, Material.REDSTONE.toString()); + } + + @Command(hook = "ssm") + public boolean ssm(CommandSender sender, int strength, String material) + { + if (strength < 0 || strength > 15) + { + getLogger().message(sender, true, "The strength must be between 0 and 15!"); + return true; + } + + Player player = (Player) sender; + if (player.getGameMode() != GameMode.CREATIVE) + { + getLogger().message(sender, true, "You must be in creative mode to do that"); + return true; + } + + Material itemType = Material.matchMaterial(material); + if (itemType == null) + { + getLogger().message(sender, true, "The material " + material + " could not be recognized"); + return true; + } + + // Empty set in the first argument would make it always return the first block, because no block types are + // considered to be transparent. Only a value of null is treated as "air only". + Block targetBlock = player.getTargetBlock((Set<Material>) null, 5); + if (targetBlock == null) + { + getLogger().message(sender, true, "That command can only be used if a container is targeted!"); + return true; + } + Inventory inventory = getInventory(targetBlock); + if (inventory == null) + { + getLogger().message(sender, true, "That command can only be used if a container is targeted!"); + return true; + } + + // --------Get the stack size and required amount of items to achieve the desired signal strength--------- + int stackSize = itemType.getMaxStackSize(); + int slotCount = inventory.getSize(); + int itemCount = computeRequiredItemCount(strength, stackSize, slotCount); + if (itemCount == -1) + { + getLogger().message(sender, true, + "The desired signal strength could not be achieved with the requested item type"); + return true; + } + // #--------Add the other side of the chest if target is a double chest and check if player can build--------- + ArrayList<Block> containerBlocks = new ArrayList<>(); + containerBlocks.add(targetBlock); + + Material blockType = targetBlock.getType(); + if (inventory.getType() == InventoryType.CHEST) + { + Arrays.stream(new BlockFace[] {BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH}) + .map(targetBlock::getRelative).filter(b -> b.getType() == blockType).forEach(containerBlocks::add); + } + + for (Block containerBlock : containerBlocks) + { + if (!canBuild(player, containerBlock)) + { + getLogger().message(sender, true, "You can not build here!"); + return true; + } + } + // #----------------Insert items------------- + int fullStackCount = itemCount / stackSize; + int remaining = itemCount % stackSize; + for (Block containerBlock : containerBlocks) + { + // Below checks should evaluate to false, but let's be safe. + BlockState blockState = containerBlock.getState(); + if (!(blockState instanceof InventoryHolder)) + continue; + + if (blockState instanceof Nameable && isSignalStrengthNameOrEmpty(((Nameable) blockState).getCustomName())) + { + ((Nameable) blockState).setCustomName(nameForSignalStrength(strength)); + blockState.update(); + } + + Inventory inv = ((InventoryHolder) blockState).getInventory(); + if (inv == null) + continue; + + inv.clear(); + for (int i = 0; i < fullStackCount; i++) + inv.setItem(i, new ItemStack(itemType, stackSize)); + if (remaining > 0) + inv.setItem(fullStackCount, new ItemStack(itemType, remaining)); + + } + getLogger().message(sender, "Comparators attached to this " + enumNameToHumanName(blockType.name()) + + " will now put out a signal strength of " + strength); + return true; + } + + private static Inventory getInventory(Block b) + { + BlockState state = b.getState(); + if (state instanceof InventoryHolder) + return ((InventoryHolder) state).getInventory(); + return null; + } + + private static int computeRequiredItemCount(int strength, int stackSize, int slotCount) + { + int itemCount = -1; + if (strength == 0) + itemCount = 0; + else if (strength == 1) + itemCount = 1; + else + itemCount = (int) Math.ceil(slotCount * stackSize / 14.0 * (strength - 1)); + + // Reverse engineer the calculation to verify + int resultingStrength = itemCount == 0 ? 0 : (int) Math.floor(1 + 14.0 * itemCount / stackSize / slotCount); + if (resultingStrength != strength) + { + return -1; + } + // Clarification on these formulas at https://minecraft.gamepedia.com/Redstone_Comparator#Containers + return itemCount; + } + + private static boolean canBuild(Player p, Block b) + { + BlockPlaceEvent event = new BlockPlaceEvent(b, b.getState(), b.getRelative(BlockFace.DOWN), + p.getInventory().getItemInMainHand(), p, true, EquipmentSlot.HAND); + Bukkit.getPluginManager().callEvent(event); + return !event.isCancelled(); + } + + private static String enumNameToHumanName(String enumName) + { + return enumName.toLowerCase().replace('_', ' '); + } + +} diff --git a/src/main/java/com/redstoner/modules/skullclick/SkullClick.java b/src/main/java/com/redstoner/modules/skullclick/SkullClick.java new file mode 100644 index 0000000..d581d19 --- /dev/null +++ b/src/main/java/com/redstoner/modules/skullclick/SkullClick.java @@ -0,0 +1,56 @@ +package com.redstoner.modules.skullclick;
+
+import org.bukkit.block.BlockState;
+import org.bukkit.block.Skull;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.player.PlayerInteractEvent;
+
+import com.redstoner.annotations.AutoRegisterListener;
+import com.redstoner.annotations.Commands;
+import com.redstoner.annotations.Version;
+import com.redstoner.misc.CommandHolderType;
+import com.redstoner.modules.Module;
+
+@Commands(CommandHolderType.None)
+@Version(major = 4, minor = 0, revision = 0, compatible = 4)
+@AutoRegisterListener
+public class SkullClick implements Module, Listener
+{
+ private boolean seen = false;
+
+ @SuppressWarnings("deprecation")
+ @EventHandler
+ public void onClick(PlayerInteractEvent e)
+ {
+ // The event gets fired twice, once for mainhand and once for offhand. This fixes that.
+ if (seen)
+ {
+ seen = false;
+ return;
+ }
+ seen = true;
+ if (e.getAction() == Action.RIGHT_CLICK_BLOCK && !e.isCancelled())
+ {
+ BlockState block = e.getClickedBlock().getState();
+ if (block instanceof Skull)
+ {
+ Skull skull = (Skull) block;
+ String owner = skull.getOwner();
+ if (owner == null || owner.equals(""))
+ {
+ getLogger().message(e.getPlayer(), true, "That skull has no owner.");
+ }
+ else
+ {
+ getLogger().message(e.getPlayer(), "That's " + owner + ".");
+ }
+ if (!e.getPlayer().isSneaking())
+ {
+ e.setCancelled(true);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/redstoner/modules/socialspy/Socialspy.cmd b/src/main/java/com/redstoner/modules/socialspy/Socialspy.cmd new file mode 100644 index 0000000..32159b9 --- /dev/null +++ b/src/main/java/com/redstoner/modules/socialspy/Socialspy.cmd @@ -0,0 +1,72 @@ +command socialspy { + format { + run config_format_show; + help Displays your current format; + } + format --default { + run config_format_default; + help Resets your format back to the default; + } + format --reset { + run config_format_default; + help Resets your format back to the default; + } + format [string:format...] { + run config_format format; + help Specifies your ss format. Use /socialspy format_help to get info about how the format works.; + } + format_help { + run format_help; + help Displays info about the format command; + } + prefix { + run config_prefix_default; + help Resets your color back to the default (light gray color code); + } + prefix [string:prefix] { + run config_prefix prefix; + help Sets your prefix to the specified term.; + } + commands list { + run commands_list; + help Displays all commands you're listening to.; + } + commands add [string:command] { + run commands_add command; + help Adds a command to the list of commands that you're listening to.; + } + commands del [string:command] { + run commands_del command; + help Deletes a command from the list of commands that you're listening to.; + } + stripcolor on { + run stripcolor_on; + } + stripcolor off { + run stripcolor_off; + } + stripcolor partial { + run stripcolor_partial; + } + stripcolor { + run stripcolor; + } + on { + run on; + type player; + } + off { + run off; + type player; + } + [empty] { + run toggle; + type player; + } + perm utils.socialspy; + migrate { + run migrate; + type console; + } + type all; +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/socialspy/Socialspy.java b/src/main/java/com/redstoner/modules/socialspy/Socialspy.java new file mode 100644 index 0000000..e1caac9 --- /dev/null +++ b/src/main/java/com/redstoner/modules/socialspy/Socialspy.java @@ -0,0 +1,377 @@ +package com.redstoner.modules.socialspy; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.json.simple.JSONArray; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.misc.BroadcastFilter; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.CoreModule; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +import net.nemez.chatapi.click.Message; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 3, compatible = 4) +public class Socialspy implements CoreModule +{ + @Command(hook = "config_prefix_default") + public boolean prefixDefault(CommandSender sender) + { + return prefix(sender, getDefaultPrefix()); + } + + @Command(hook = "config_prefix") + public boolean prefix(CommandSender sender, String prefix) + { + getLogger().message(sender, "Set your prefix to: " + prefix); + DataManager.setData(sender, "prefix", prefix); + return true; + } + + @Command(hook = "config_format_default") + public boolean configFormatDefault(CommandSender sender) + { + return configFormat(sender, getDefaultFormat()); + } + + @Command(hook = "config_format_show") + public boolean configFormatShow(CommandSender sender) + { + String format = (String) DataManager.getOrDefault(sender, "format", getDefaultFormat()); + getLogger().message(sender, "Your current format is: " + format.replaceAll("[&§]", "&&")); + return true; + } + + @Command(hook = "config_format") + public boolean configFormat(CommandSender sender, String format) + { + getLogger().message(sender, "Set your format to: " + format); + DataManager.setData(sender, "format", format); + return true; + } + + @Command(hook = "stripcolor_on") + public boolean stripcolorOn(CommandSender sender) + { + getLogger().message(sender, "Enabled stripping colors!"); + DataManager.setData(sender, "stripcolor", "on"); + return true; + } + + @Command(hook = "stripcolor_off") + public boolean stripcolorOff(CommandSender sender) + { + getLogger().message(sender, "Disabled stripping colors!"); + DataManager.setData(sender, "stripcolor", "off"); + return true; + } + + @Command(hook = "stripcolor_partial") + public boolean stripcolor_partial(CommandSender sender) + { + getLogger().message(sender, "Now replacing colors with their colorcode equivalent!"); + DataManager.setData(sender, "stripcolor", "partial"); + return true; + } + + @Command(hook = "stripcolor") + public boolean stripcolor(CommandSender sender) + { + boolean b = DataManager.getOrDefault(sender, "stripcolor", "on").equals("on"); + getLogger().message(sender, (b ? "Disabled" : "Enabled") + " stripping colors!"); + DataManager.setData(sender, "stripcolor", !b); + return true; + } + + @Command(hook = "on") + public boolean spyOn(CommandSender sender) + { + getLogger().message(sender, "Enabled socialspy!"); + DataManager.setData(sender, "enabled", true); + return true; + } + + @Command(hook = "off") + public boolean spyOff(CommandSender sender) + { + getLogger().message(sender, "Disabled socialspy!"); + DataManager.setData(sender, "enabled", false); + return true; + } + + @Command(hook = "toggle") + public boolean spyToggle(CommandSender sender) + { + boolean b = (boolean) DataManager.getOrDefault(sender, "enabled", false); + getLogger().message(sender, (b ? "Disabled" : "Enabled") + " socialspy!"); + DataManager.setData(sender, "enabled", !b); + return true; + } + + @Command(hook = "format_help") + public boolean formatInfo(CommandSender sender) + { + getLogger().message(sender, + new String[] {" Format placeholders:", " &c%s&eender &7(display name) | &c%S&eender &7(real name)", + " &c%t&earget &7(display name) | &c%T&earget &7(real name)", + " &c%p&erefix &7(see prefix option)", " &c%m&eessage", " &c%c&eommand", + " Any other text will be put as literal text. Use %% to escape any %.", + " The default format is: §e" + getDefaultFormat().replaceAll("(?i)&([0-9a-fl-o])", "&&$1"), + " The default prefix is: §e" + getDefaultPrefix().replaceAll("(?i)&([0-9a-fl-o])", "&&$1")}); + return true; + } + + @Command(hook = "commands_list") + public boolean commands_list(CommandSender sender) + { + ArrayList<String> message = new ArrayList<>(); + JSONArray commands = (JSONArray) DataManager.getOrDefault(sender, "commands", getDefaultCommandList()); + if (commands == null || commands.size() == 0) + message.add("You are not listening to any commands!"); + else + { + message.add("You are listening to the following " + commands.size() + " commands:"); + message.add(Arrays.toString(commands.toArray()).replace(", /", "&7, &e/").replace("[", "[&e").replace("]", + "&7]")); + } + getLogger().message(sender, message.toArray(new String[] {})); + return true; + } + + @SuppressWarnings("unchecked") + private final JSONArray getDefaultCommandList() + { + JSONArray commands = new JSONArray(); + commands.add("/m"); + commands.add("/r"); + return commands; + } + + @SuppressWarnings("unchecked") + @Command(hook = "commands_add") + public boolean commands_add(CommandSender sender, String command) + { + JSONArray commands = (JSONArray) DataManager.getOrDefault(sender, "commands", getDefaultCommandList()); + commands.add(command); + DataManager.setData(sender, "commands", commands); + getLogger().message(sender, "You are now spying on &e" + command); + return true; + } + + @Command(hook = "commands_del") + public boolean commands_del(CommandSender sender, String command) + { + JSONArray commands = (JSONArray) DataManager.getOrDefault(sender, "commands", getDefaultCommandList()); + commands.remove(command); + DataManager.setData(sender, "commands", commands); + getLogger().message(sender, "You are no longer spying on &e" + command); + return true; + } + + public static void spyBroadcast(CommandSender sender, CommandSender target, String message, String command, + BroadcastFilter filter) + { + try + { + Module mod = ModuleLoader.getModule("Socialspy"); + Method m = mod.getClass().getDeclaredMethod("spyBroadcast_", CommandSender.class, CommandSender.class, + String.class, String.class, BroadcastFilter.class); + m.invoke(mod, sender, target, message, command, filter); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + public void spyBroadcast_(CommandSender sender, CommandSender target, String message, String command, + BroadcastFilter filter) + { + for (Player p : Bukkit.getOnlinePlayers()) + { + if ((boolean) DataManager.getOrDefault(p, "enabled", false)) + if (p.hasPermission("utils.socialspy")) + { + if (((JSONArray) DataManager.getOrDefault(p, "commands", getDefaultCommandList())) + .contains(command)) + if (filter == null || filter.sendTo(p)) + { + Message m = new Message(p, null); + m.appendText(formatMessage(p, sender, target, message, command)); + m.send(); + } + } + else + DataManager.setData(sender, "enabled", false); + } + if (((JSONArray) DataManager.getOrDefault(Bukkit.getConsoleSender(), "commands", getDefaultCommandList())) + .contains(command)) + { + Message m = new Message(Bukkit.getConsoleSender(), null); + m.appendText(formatMessage(Bukkit.getConsoleSender(), sender, target, message, command)); + m.send(); + } + } + + public static void spyBroadcast(CommandSender sender, String target, String message, String command, + BroadcastFilter filter) + { + try + { + Module mod = ModuleLoader.getModule("Socialspy"); + Method m = mod.getClass().getDeclaredMethod("spyBroadcast_", CommandSender.class, String.class, + String.class, String.class, BroadcastFilter.class); + m.invoke(mod, sender, target, message, command, filter); + } + catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) + {} + } + + public void spyBroadcast_(CommandSender sender, String target, String message, String command, + BroadcastFilter filter) + { + for (Player p : Bukkit.getOnlinePlayers()) + { + if ((boolean) DataManager.getOrDefault(p, "enabled", false)) + if (p.hasPermission("utils.socialspy")) + { + if (((JSONArray) DataManager.getOrDefault(p, "commands", getDefaultCommandList())) + .contains(command)) + if (filter == null || filter.sendTo(p)) + { + Message m = new Message(p, null); + m.appendText(formatMessage(p, sender, target, message, command)); + m.send(); + } + } + else + DataManager.setData(sender, "enabled", false); + } + if (((JSONArray) DataManager.getOrDefault(Bukkit.getConsoleSender(), "commands", getDefaultCommandList())) + .contains(command)) + { + Message m = new Message(Bukkit.getConsoleSender(), null); + m.appendText(formatMessage(Bukkit.getConsoleSender(), sender, target, message, command)); + m.send(); + } + } + + private String formatMessage(CommandSender formatHolder, CommandSender sender, CommandSender target, String message, + String command) + { + String format = (String) DataManager.getOrDefault(formatHolder, "format", getDefaultFormat()); + // Replace escaped % with placeholder + format = format.replace("%%", "§§"); + // Sender name + format = format.replace("%s", Utils.getName(sender)); + format = format.replace("%S", sender.getName()); + // Target name + format = format.replace("%t", Utils.getName(target)); + format = format.replace("%T", target.getName()); + // Prefix + String prefix = (String) DataManager.getOrDefault(formatHolder, "prefix", getDefaultPrefix()); + format = format.replace("%p", prefix); + // Apply colors to halfway replaced String + format = ChatColor.translateAlternateColorCodes('&', format); + // Insert command and message + format = format.replace("%c", command); + + // Color stripping + Object o = DataManager.getOrDefault(formatHolder, "stripcolor", "off"); + if (o instanceof Boolean) + { + boolean b = (boolean) o; + if (b) + o = "on"; + else + o = "off"; + DataManager.setData(formatHolder, "stripcolor", o); + } + String s = (String) o; + if (s.equals("on")) + message = ChatColor.stripColor(message).replaceAll("(?i)[&$][0-9a-fk-o]", ""); + else if (s.equals("partial")) + message = message.replaceAll("(?i)[§&]([0-9a-fk-o])", "&&$1"); + // Insert message + format = format.replace("%m", message); + + // Convert placeholder back + format = format.replace("§§", "%"); + return format; + } + + private String formatMessage(CommandSender formatHolder, CommandSender sender, String target, String message, + String command) + { + String format = (String) DataManager.getOrDefault(formatHolder, "format", getDefaultFormat()); + // Replace escaped % with placeholder + format = format.replace("%%", "§§"); + // Sender name + format = format.replace("%s", Utils.getName(sender)); + format = format.replace("%S", sender.getName()); + // Target name + format = format.replace("%t", target); + format = format.replace("%T", target); + // Prefix + String prefix = (String) DataManager.getOrDefault(formatHolder, "prefix", getDefaultPrefix()); + format = format.replace("%p", prefix); + // Apply colors to halfway replaced String + format = ChatColor.translateAlternateColorCodes('&', format); + // Insert command + format = format.replace("%c", command); + + // Color stripping + Object o = DataManager.getOrDefault(formatHolder, "stripcolor", "off"); + if (o instanceof Boolean) + { + boolean b = (boolean) o; + if (b) + o = "on"; + else + o = "off"; + DataManager.setData(formatHolder, "stripcolor", o); + } + String s = (String) o; + if (s.equals("on")) + message = ChatColor.stripColor(message).replaceAll("(?i)[&$][0-9a-fk-o]", ""); + else if (s.equals("partial")) + message = message.replaceAll("(?i)[§&]([0-9a-fk-o])", "&&$1"); + // Insert message + format = format.replace("%m", message); + + // Convert placeholder back + format = format.replace("§§", "%"); + return format; + } + + private final String getDefaultFormat() + { + return " %s &7to %t%p: %m"; + } + + private final String getDefaultPrefix() + { + return "&7"; + } + + @Command(hook = "migrate") + public boolean migrate(CommandSender sender) + { + DataManager.migrateAll("Message"); + return true; + } +} diff --git a/src/main/java/com/redstoner/modules/tag/Tag.cmd b/src/main/java/com/redstoner/modules/tag/Tag.cmd new file mode 100644 index 0000000..caa95ab --- /dev/null +++ b/src/main/java/com/redstoner/modules/tag/Tag.cmd @@ -0,0 +1,22 @@ +command tag { + add [string:player] [string:tag...] { + help Tags a player.; + run addtag player tag; + perm utils.tag; + } + del [string:player] [int:id] { + help Removes a tag.; + run deltag player id; + perm utils.tag; + } + check [string:player] { + help Lists all tags of a player.;\ + run checktag player; + perm utils.tag; + } + [string:player] [string:tag...] { + help Tags a player.; + run addtag player tag; + perm utils.tag; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/tag/Tag.java b/src/main/java/com/redstoner/modules/tag/Tag.java new file mode 100644 index 0000000..ae3302d --- /dev/null +++ b/src/main/java/com/redstoner/modules/tag/Tag.java @@ -0,0 +1,147 @@ +package com.redstoner.modules.tag; + +import java.io.File; +import java.util.ArrayList; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.JsonManager; +import com.redstoner.misc.Main; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 1, compatible = 4) +public class Tag implements Module +{ + private File tagLocation = new File(Main.plugin.getDataFolder(), "tag.json"); + private JSONObject tags; + + @Override + public boolean onEnable() + { + tags = JsonManager.getObject(tagLocation); + if (tags == null) + tags = new JSONObject(); + return true; + } + + @Override + public void onDisable() + { + saveTags(); + } + + @SuppressWarnings({"deprecation", "unchecked"}) + @Command(hook = "addtag", async = AsyncType.ALWAYS) + public boolean addTag(CommandSender sender, String name, String tag) + { + OfflinePlayer player = Bukkit.getOfflinePlayer(name); + if (player == null) + { + getLogger().message(sender, true, "That player doesn't exist!"); + return true; + } + UUID uuid = player.getUniqueId(); + JSONArray tagArray; + if (tags.containsKey(uuid.toString())) + tagArray = (JSONArray) tags.get(uuid.toString()); + else + tagArray = new JSONArray(); + tagArray.add(tag); + if (!tags.containsKey(uuid.toString())) + tags.put(uuid.toString(), tagArray); + getLogger().message(sender, "Successfully added note &e" + tag + " &7to player &e" + name + "&7!"); + saveTags(); + return true; + } + + @SuppressWarnings("deprecation") + @Command(hook = "deltag", async = AsyncType.ALWAYS) + public boolean delTag(CommandSender sender, String name, int id) + { + if (id < 1) + { + getLogger().message(sender, true, "The ID you entered is too small, it must be at least 1!"); + return true; + } + OfflinePlayer player = Bukkit.getOfflinePlayer(name); + if (player == null) + { + getLogger().message(sender, true, "That player doesn't exist!"); + return true; + } + UUID uuid = player.getUniqueId(); + if (!tags.containsKey(uuid.toString())) + { + getLogger().message(sender, true, "There are no notes about that player."); + return true; + } + JSONArray tagArray = (JSONArray) tags.get(uuid.toString()); + int size = tagArray.size(); + if (size == 0) + { + getLogger().message(sender, true, "There are no notes about that player."); + tags.remove(uuid.toString()); + saveTags(); + return true; + } + if (id > size) + { + getLogger().message(sender, true, "The number you entered is too big! It must be at most " + size + "!"); + return true; + } + getLogger().message(sender, "Successfully removed note: &e" + tagArray.remove(id - 1)); + if (tagArray.size() == 0) + tags.remove(uuid.toString()); + saveTags(); + return true; + } + + @SuppressWarnings("deprecation") + @Command(hook = "checktag", async = AsyncType.ALWAYS) + public boolean checkTags(CommandSender sender, String name) + { + OfflinePlayer player = Bukkit.getOfflinePlayer(name); + if (player == null) + { + getLogger().message(sender, true, "That player doesn't exist!"); + return true; + } + UUID uuid = player.getUniqueId(); + if (!tags.containsKey(uuid.toString())) + { + getLogger().message(sender, "There are no notes about that player."); + return true; + } + JSONArray tagArray = (JSONArray) tags.get(uuid.toString()); + int size = tagArray.size(); + if (size == 0) + { + tags.remove(uuid.toString()); + saveTags(); + return true; + } + ArrayList<String> message = new ArrayList<String>(); + message.add("There are &e" + size + "&7 notes about this player:"); + for (int i = 0; i < size; i++) + message.add("&a" + (i + 1) + "&8: &e" + tagArray.get(i)); + getLogger().message(sender, message.toArray(new String[] {})); + return true; + } + + public void saveTags() + { + JsonManager.save(tags, tagLocation); + } + +} diff --git a/src/main/java/com/redstoner/modules/teleport/Teleport.cmd b/src/main/java/com/redstoner/modules/teleport/Teleport.cmd new file mode 100644 index 0000000..4e5930e --- /dev/null +++ b/src/main/java/com/redstoner/modules/teleport/Teleport.cmd @@ -0,0 +1,142 @@ +command teleport { + alias eteleport; + alias tp; + alias etp; + alias to; + alias eto; + alias tpo; + alias etpo; + alias tp2p; + alias etp2p; + [player:string] { + run tp player; + } + [player:string] [player2:string] { + run tp2 player player2; + } +} + +command teleporthere { + alias eteleporthere; + alias tphere; + alias etphere; + alias tpohere; + alias etpohere; + [player:string] { + run tph player; + } +} + +command teleportask { + alias eteleportask; + alias tpa; + alias etpa; + alias tpr; + alias etpr; + alias tpask; + alias etpask; + [player:string] { + run tpa player; + } +} + +command teleportaskhere { + alias eteleportaskhere; + alias tpahere, + alias etpahere; + alias tprhere; + alias etrphere; + alias tpaskhere; + alias etpaskhere; + [player:string] { + run tpah player; + help ask another player to teleport to you.; + } +} + +command tpall { + alias etpall; + [empty] { + run tpall; + help Teleports everyone to you.; + } + [player] { + run tpall2 player; + help Teleports everyone to the specified player.; + } + perm utils.admin.teleport; +} + +command tpaall { + alias etpall; + [empty] { + run tpaall; + help Sends a tpa request to every player.; + perm utils.admin.teleport; + } + [player:string] { + run tpaall2 player; + help Sends a tpa request to every player.; + } + perm utils.admin.teleport; +} + +command tpaccept { + alias etpaccept; + alias tpyes; + alias etpyes; + [empty] { + run tpaccept; + help Accepts the latest pending tpa request.; + } + [index:int] { + run tpaccept2 index; + help Accepts the specified pending tpa request.; + } + perm utils.teleport.request; +} + +command tpacancel { + alias etpacencel; + [empty] { + run tpacancel; + help Cancels an outgoing pending tpa request.; + perm utils.teleport.request; + } +} + +command tpdeny { + alias etpdeny; + alias tpno; + alias etpno; + perm utils.teleport.request; + [empty] { + run tpdeny; + } + [index:int] { + run tpdeny2 index; + } +} + +command tplist { + alias etplist; + alias tpl; + alias etpl; + [empty] { + run tpl; + } +} + +command tptoggle { + alias etptoggle; + [status:string] { + run tptoggle status; + help sets your tpa status; + perm utils.teleport.toggle; + } + [command:string] [status:string] { + run tptoggle2 command status; + help sets your tpa status for only one command (e.g. tpa/tpahere).; + perm utils.teleport.toggle; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/teleport/Teleport.java b/src/main/java/com/redstoner/modules/teleport/Teleport.java new file mode 100644 index 0000000..7680852 --- /dev/null +++ b/src/main/java/com/redstoner/modules/teleport/Teleport.java @@ -0,0 +1,185 @@ +package com.redstoner.modules.teleport; + +import java.util.ArrayList; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +import net.nemez.chatapi.click.Message; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 0, compatible = 4) +public class Teleport implements Module +{ + public static final String PERMISSION_TELEPORT = "utils.admin.teleport"; + + public ArrayList<TPRequest> pending_requests; + + @Override + public void postEnable() + { + pending_requests = new ArrayList<TPRequest>(); + } + + @Command(hook = "tp") + public boolean teleport(CommandSender sender, String player) + { + if (!sender.hasPermission(PERMISSION_TELEPORT)) + return tpa(sender, player); + return true; + } + + @Command(hook = "tp2") + public boolean teleport(CommandSender sender, String player, String player2) + { + if (!sender.hasPermission(PERMISSION_TELEPORT)) + if (player2.equals(((Player) sender).getName())) + return tpahere(sender, player); + else + { + getLogger().message(sender, "You do not have the required permissions to run that Command!"); + return true; + } + Player p1 = Bukkit.getPlayer(player); + Player p2 = Bukkit.getPlayer(player2); + if (p1 == null || p2 == null) + { + getLogger().message(sender, true, "The specified player couldn't be found!"); + return true; + } + p1.teleport(p2); + getLogger().message(p1, "You have been teleported to: " + p2.getDisplayName()); + if (!sender.getName().equals(p1.getName())) + getLogger().message(sender, + p1.getDisplayName() + "&7 has been teleported to " + p2.getDisplayName() + "&7!"); + return true; + } + + @Command(hook = "tpa") + public boolean tpa(CommandSender sender, String player) + { + return true; + } + + @Command(hook = "tpahere") + public boolean tpahere(CommandSender sender, String player) + { + return true; + } + + @Command(hook = "tpmenu") + public boolean tpinventory(CommandSender sender) + { + + return true; + } + + protected void remove(TPRequest request) + { + + } +} + +class TPRequest implements Runnable +{ + private final Teleport holder; + private final Player sender; + private final Player target; + private final Type type; + private int index; + + Thread t; + + public TPRequest(Player sender, Player target, Type type, int index, Teleport holder) + { + this.sender = sender; + this.target = target; + this.type = type; + this.index = 0; + this.holder = holder; + } + + public Player getSender() + { + return sender; + } + + public Player getTarget() + { + return target; + } + + public Type getType() + { + return type; + } + + public int getIndex() + { + return index; + } + + public void setIndex(int index) + { + this.index = index; + } + + public void execute() + { + switch (type) + { + case tpa: + sender.teleport(target); + break; + case tpahere: + target.teleport(sender); + break; + } + } + + public void abort() + { + t.interrupt(); + } + + @Override + public void run() + { + t = Thread.currentThread(); + try + { + Thread.sleep(60000); + } + catch (InterruptedException e) + { + holder.remove(this); + Message m = new Message(sender, null); + if (DataManager.getState(sender, "AFK")) + { + m.appendText(target.getDisplayName() + " is AFK and might not respond. "); + m.appendSendChat("Try again?", "/" + type.toString() + " " + target.getName()); + } + if (DataManager.getState(sender, "BUSY")) + { + m.appendText(target.getDisplayName() + " is BUSY and might not respond. "); + m.appendSendChat("Try again?", "/" + type.toString() + " " + target.getName()); + } + return; + } + holder.remove(this); + } +} + +enum Type +{ + tpa, + tpahere; +} diff --git a/src/main/java/com/redstoner/modules/tilechunks/LaggyTileChunk.java b/src/main/java/com/redstoner/modules/tilechunks/LaggyTileChunk.java new file mode 100644 index 0000000..e2456d3 --- /dev/null +++ b/src/main/java/com/redstoner/modules/tilechunks/LaggyTileChunk.java @@ -0,0 +1,21 @@ +package com.redstoner.modules.tilechunks; + +import org.bukkit.Location; +import org.bukkit.World; + +public class LaggyTileChunk { + public final int x, y, z, amount; + public final World world; + + public LaggyTileChunk(int x, int y, int z, World world, int amount) { + this.x = x; + this.y = y; + this.z = z; + this.world = world; + this.amount = amount; + } + + public Location getLocation() { + return new Location(world, x, y, z); + } +} diff --git a/src/main/java/com/redstoner/modules/tilechunks/TileChunks.cmd b/src/main/java/com/redstoner/modules/tilechunks/TileChunks.cmd new file mode 100644 index 0000000..c0e0773 --- /dev/null +++ b/src/main/java/com/redstoner/modules/tilechunks/TileChunks.cmd @@ -0,0 +1,19 @@ +command lct { + perm utils.tilechunks; + + list { + run list_cmd; + help re-lists already scanned chunks; + } + + [int:amount] { + run scan_cmd amount; + help scans for laggy chunks; + } + + tp [int:number] { + run tp number; + help teleports to the specified chunk; + type player; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/tilechunks/TileChunks.java b/src/main/java/com/redstoner/modules/tilechunks/TileChunks.java new file mode 100644 index 0000000..75a3fd2 --- /dev/null +++ b/src/main/java/com/redstoner/modules/tilechunks/TileChunks.java @@ -0,0 +1,83 @@ +package com.redstoner.modules.tilechunks; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class TileChunks implements Module +{ + private List<LaggyTileChunk> laggyChunks = new ArrayList<>(); + + private void scan(int amount) + { + laggyChunks.clear(); + for (World world : Bukkit.getServer().getWorlds()) + { + for (Chunk chunk : world.getLoadedChunks()) + { + int amount2 = chunk.getTileEntities().length; + if (amount2 > amount) + { + Location entLoc = chunk.getTileEntities()[0].getLocation(); + laggyChunks.add(new LaggyTileChunk(entLoc.getBlockX(), entLoc.getBlockY(), entLoc.getBlockZ(), + world, amount2)); + } + } + } + } + + @Command(hook = "list_cmd") + public void list(CommandSender sender) + { + if (laggyChunks.size() > 0) + { + ArrayList<String> message = new ArrayList<>(); + for (LaggyTileChunk lc : laggyChunks) + { + message.add("§b[§a" + laggyChunks.indexOf(lc) + "§b]: §a" + lc.x + "§7, §a" + lc.y + "§7, §a" + lc.z + + " §7(" + lc.world.getName() + ") §a- §b" + lc.amount + " tile entities"); + } + message.add("§2-------------------"); + getLogger().message(sender, message.toArray(new String[] {})); + } + else + getLogger().message(sender, true, "Couldn't find any chunks with that many tile entities."); + } + + @Command(hook = "scan_cmd", async = AsyncType.ALWAYS) + public void scan_cmd(CommandSender sender, int amount) + { + scan(amount); + list(sender); + } + + @Command(hook = "tp") + public void tp(CommandSender sender, int number) + { + Player player = (Player) sender; + if (number < laggyChunks.size()) + { + player.teleport(laggyChunks.get(number).getLocation()); + getLogger().message(player, "§aTeleported to chunk " + number + "!"); + } + else + { + getLogger().message(sender, true, "§4Invalid chunk number! Use §e/lc list §4to show laggy chunks!"); + } + } +} diff --git a/src/main/java/com/redstoner/modules/vanish/Vanish.cmd b/src/main/java/com/redstoner/modules/vanish/Vanish.cmd new file mode 100644 index 0000000..618a4c1 --- /dev/null +++ b/src/main/java/com/redstoner/modules/vanish/Vanish.cmd @@ -0,0 +1,33 @@ +command vanish { + [empty] { + help Toggles your vanish status.; + type player; + run vanish; + perm utils.vanish; + } + on { + help Turns your vanish on.; + type player; + run vanish_on; + perm utils.vanish; + } + off { + help Turns your vanish off.; + type player; + run vanish_off; + perm utils.vanish; + } + [string:name] { + help Toggles someone elses vanish; + run vanish_other name; + perm utils.vanishother; + } +} +command imout { + [empty] { + help Makes you magically disappear; + type player; + perm utils.imout; + run imout; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/vanish/Vanish.java b/src/main/java/com/redstoner/modules/vanish/Vanish.java new file mode 100644 index 0000000..d4e57e8 --- /dev/null +++ b/src/main/java/com/redstoner/modules/vanish/Vanish.java @@ -0,0 +1,260 @@ +package com.redstoner.modules.vanish; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +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.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.AutoRegisterListener; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.datamanager.DataManager; + +@Commands(CommandHolderType.File) +@AutoRegisterListener +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Vanish implements Module, Listener +{ + private ArrayList<UUID> vanished = new ArrayList<>(); + List<String> imouted = new ArrayList<String>(); + private HashMap<UUID, ArrayList<UUID>> vanishOthers = new HashMap<>(); + + @Override + public void migrate(Version old) + { + Module.super.migrate(old); + if ((old.major() == 4) && (old.minor() == 0) && (old.revision() <= 1)) + { + DataManager.setConfig("indicator", "&7[V]"); + } + } + + @Command(hook = "vanish") + public boolean vanish(CommandSender sender) + { + UUID uid = ((Player) sender).getUniqueId(); + if (vanished.contains(uid)) + { + vanished.remove(uid); + getLogger().message(sender, "You are no longer vanished!"); + unvanishPlayer((Player) sender); + } + else + { + vanished.add(uid); + getLogger().message(sender, "You are now vanished!"); + vanishPlayer((Player) sender); + } + return true; + } + + @Command(hook = "vanish_on") + public boolean vanishOn(CommandSender sender) + { + UUID uid = ((Player) sender).getUniqueId(); + if (vanished.contains(uid)) + getLogger().message(sender, + "You were already vanished, however we refreshed the vanish for you just to be sure!"); + else + { + vanished.add(uid); + getLogger().message(sender, "You are now vanished!"); + } + vanishPlayer((Player) sender); + return true; + } + + @Command(hook = "vanish_off") + public boolean vanishOff(CommandSender sender) + { + UUID uid = ((Player) sender).getUniqueId(); + if (!vanished.contains(uid)) + getLogger().message(sender, + "You were not vanished, however we refreshed the vanish for you just to be sure!"); + else + { + vanished.remove(uid); + getLogger().message(sender, "You are no longer vanished!"); + } + unvanishPlayer((Player) sender); + return true; + } + + @Command(hook = "vanish_other") + public boolean vanishOther(CommandSender sender, String name) + { + Player player = Bukkit.getPlayer(name); + if (player == null) + { + getLogger().message(sender, "&cPlayer &6" + name + " &ccould not be found!"); + return true; + } + UUID uid = player.getUniqueId(); + if (player.hasPermission("utils.vanish")) + { + if (vanished.contains(uid)) + { + vanished.remove(uid); + getLogger().message(sender, "Successfully unvanished &e" + player.getDisplayName()); + getLogger().message(player, "You are no longer vanished!"); + } + else + { + vanished.add(uid); + getLogger().message(sender, "Successfully vanished &e" + player.getDisplayName()); + getLogger().message(player, "You are now vanished!"); + } + return true; + } + for (Entry<UUID, ArrayList<UUID>> entry : vanishOthers.entrySet()) + { + if (entry.getValue().contains(uid)) + { + entry.getValue().remove(uid); + getLogger().message(sender, "Successfully unvanished &e" + player.getDisplayName()); + getLogger().message(player, "You are no longer vanished!"); + if (entry.getValue().size() == 0) + vanishOthers.remove(entry.getKey()); + return true; + } + } + UUID uuid = ((Player) sender).getUniqueId(); + ArrayList<UUID> toAddTo = vanishOthers.get(uuid); + if (toAddTo == null) + toAddTo = new ArrayList<>(); + toAddTo.add(uid); + vanishOthers.put(uuid, toAddTo); + getLogger().message(sender, "Successfully vanished &e" + player.getDisplayName()); + getLogger().message(player, "You are now vanished!"); + return true; + } + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerJoin(PlayerJoinEvent event) + { + Player player = event.getPlayer(); + DataManager.setState(player, "vanished", vanished.contains(player.getUniqueId())); + if (vanished.contains(player.getUniqueId())) + { + for (Player p : Bukkit.getOnlinePlayers()) + { + if (!p.hasPermission("utils.vanish")) + p.hidePlayer(player); + } + event.setJoinMessage(null); + } + if (player.hasPermission("utils.vanish")) + return; + for (UUID uid : vanished) + { + Player p = Bukkit.getPlayer(uid); + if (p == null) + continue; + player.hidePlayer(p); + } + for (Entry<UUID, ArrayList<UUID>> entry : vanishOthers.entrySet()) + { + for (UUID uid : entry.getValue()) + { + Player p = Bukkit.getPlayer(uid); + if (p == null) + continue; + player.hidePlayer(p); + } + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerLeave(PlayerQuitEvent event) + { + Player player = event.getPlayer(); + UUID uid = player.getUniqueId(); + if (vanished.contains(player.getUniqueId())) + { + event.setQuitMessage(null); + } + if (vanishOthers.containsKey(uid)) + { + ArrayList<UUID> toUnvanish = vanishOthers.remove(uid); + for (UUID uuid : toUnvanish) + { + Player p = Bukkit.getPlayer(uuid); + if (p != null) + unvanishPlayer(p); + } + } + boolean wasVanished = false; + for (Entry<UUID, ArrayList<UUID>> entry : vanishOthers.entrySet()) + { + if (entry.getValue().contains(uid)) + { + entry.getValue().remove(uid); + wasVanished = true; + break; + } + } + if (wasVanished) + unvanishPlayer(player); + } + + @SuppressWarnings("deprecation") + private void vanishPlayer(Player player) + { + for (Player p : Bukkit.getOnlinePlayers()) + { + if (!p.hasPermission("utils.vanish")) + p.hidePlayer(player); + } + DataManager.setState(player, "vanished", true); + DataManager.setData(Utils.getID(player), "Seen", "lastquit", System.currentTimeMillis()); + } + + @SuppressWarnings("deprecation") + private void unvanishPlayer(Player player) + { + for (Player p : Bukkit.getOnlinePlayers()) + p.showPlayer(player); + DataManager.setState(player, "vanished", false); + DataManager.setData(Utils.getID(player), "Seen", "lastjoined", System.currentTimeMillis()); + } + + @Command(hook = "imout") + public void onImoutCommand(CommandSender sender) + { + String symbol; + Player s = (Player) sender; + String name = sender.getName(); + if (imouted.contains(name)) + { + symbol = "§a§l+"; + getLogger().message(sender, "§eWelcome back! You are no longer hidden", ""); + s.performCommand("vanish off"); + s.performCommand("act off"); + imouted.remove(name); + } + else + { + symbol = "§c§l-"; + getLogger().message(sender, "§e§oPoof!§e You are now gone!", ""); + s.performCommand("vanish on"); + s.performCommand("act on"); + imouted.add(name); + } + Utils.broadcast(symbol, " §7" + name, null); + } +} diff --git a/src/main/java/com/redstoner/modules/warn/Warn.cmd b/src/main/java/com/redstoner/modules/warn/Warn.cmd new file mode 100644 index 0000000..5021e0f --- /dev/null +++ b/src/main/java/com/redstoner/modules/warn/Warn.cmd @@ -0,0 +1,15 @@ +command warn { + [empty] { + run warn; + help Warns other players about definite lag; + perm utils.warn; + } +} + +command warnp { + [empty] { + run warnp; + help Warns other players about possible lag; + perm utils.warn; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/warn/Warn.java b/src/main/java/com/redstoner/modules/warn/Warn.java new file mode 100644 index 0000000..c272c67 --- /dev/null +++ b/src/main/java/com/redstoner/modules/warn/Warn.java @@ -0,0 +1,29 @@ +package com.redstoner.modules.warn; + +import org.bukkit.command.CommandSender; + +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class Warn implements Module +{ + @Command(hook = "warn") + public void warn_normal(CommandSender sender) + { + String name = Utils.getName(sender); + Utils.broadcast(null, "§2Lag incoming! - §9" + name, null); + } + + @Command(hook = "warnp") + public void warn_possible(CommandSender sender) + { + String name = Utils.getName(sender); + Utils.broadcast(null, "§2Possible lag incoming! - §9" + name, null); + } +} diff --git a/src/main/java/com/redstoner/modules/webtoken/WebToken.cmd b/src/main/java/com/redstoner/modules/webtoken/WebToken.cmd new file mode 100644 index 0000000..898d212 --- /dev/null +++ b/src/main/java/com/redstoner/modules/webtoken/WebToken.cmd @@ -0,0 +1,21 @@ +command token { + perm utils.webtoken; + + [empty] { + help Displays an already generated token; + type player; + perm utils.webtoken; + run token; + } +} + +command gettoken { + perm utils.webtoken; + + [string:email...] { + help Generates a token used for website authentication; + type player; + perm utils.webtoken; + run gettoken email; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/webtoken/WebToken.java b/src/main/java/com/redstoner/modules/webtoken/WebToken.java new file mode 100644 index 0000000..6a4a8b0 --- /dev/null +++ b/src/main/java/com/redstoner/modules/webtoken/WebToken.java @@ -0,0 +1,225 @@ +package com.redstoner.modules.webtoken; + +import java.io.IOException; +import java.util.Random; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.json.simple.parser.ParseException; + +import com.nemez.cmdmgr.Command; +import com.nemez.cmdmgr.Command.AsyncType; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.misc.mysql.Config; +import com.redstoner.misc.mysql.MysqlHandler; +import com.redstoner.misc.mysql.elements.ConstraintOperator; +import com.redstoner.misc.mysql.elements.MysqlConstraint; +import com.redstoner.misc.mysql.elements.MysqlDatabase; +import com.redstoner.misc.mysql.elements.MysqlTable; +import com.redstoner.modules.Module; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 1, revision = 0, compatible = 4) +public class WebToken implements Module +{ + private static final int TOKEN_LENGTH = 6; + private static final String CONSONANTS = "bcdfghjklmnpqrstvwxyz"; + private static final String VOWELS = "aeiou"; + private MysqlTable table; + + @Override + public boolean onEnable() + { + Config config; + try + { + config = Config.getConfig("WebToken.json"); + } + catch (IOException | ParseException e1) + { + e1.printStackTrace(); + return false; + } + if (config == null || !config.containsKey("database") || !config.containsKey("table")) + { + getLogger().error("Could not load the WebToken config file, disabling!"); + config.put("database", "redstoner"); + config.put("table", "webtoken"); + return false; + } + try + { + MysqlDatabase database = MysqlHandler.INSTANCE.getDatabase(config.get("database") + "?autoReconnect=true"); + table = database.getTable(config.get("table")); + } + catch (NullPointerException e) + { + getLogger().error("Could not use the WebToken config, aborting!"); + return false; + } + return true; + } + + private String getNextId() throws Exception + { + Object[] results = table.get("select id from register_tokens order by id desc limit 1;"); + if (results[0] instanceof Integer) + { + return ((int) results[0]) + 1 + ""; + } + else if (results[0] instanceof String) + { + int id = Integer.valueOf((String) results[0]); + return id + 1 + ""; + } + else + { + throw new Exception("Token query returned invalid result!"); + } + } + + private String query(String emailOrToken, UUID uuid) throws Exception + { + if (!(emailOrToken.equals("token") && emailOrToken.equals("email"))) + { + throw new Exception("Invalid database query: " + emailOrToken); + } + Object[] results = table.get(emailOrToken, + new MysqlConstraint("uuid", ConstraintOperator.EQUAL, uuid.toString().replaceAll("-", ""))); + if (results instanceof String[]) + { + String[] tokenResults = (String[]) results; + if (tokenResults.length == 1) + { + return tokenResults[0]; + } + else + { + return null; + } + } + else + { + throw new Exception("Token query returned invalid result!"); + } + } + + private boolean match(String string, String regex) + { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(string); + return matcher.find(); + } + + private void printToken(Player player, String email, String token) + { + String[] message = new String[] {"&aEmail: " + email, "&aToken: " + token, + "&cIMPORTANT: never share the token with anyone!", "&cIt could be used to claim your website account!"}; + getLogger().message(player, message); + } + + private String generateToken() + { + String token = ""; + Random random = new Random(); + int start = random.nextInt(2); + for (int i = 0; i < TOKEN_LENGTH; i++) + { + if (i % 2 == start) + { + token += CONSONANTS.charAt(random.nextInt(21)); + } + else + { + token += VOWELS.charAt(random.nextInt(5)); + } + } + return token; + } + + @Command(hook = "token", async = AsyncType.ALWAYS) + public void token(CommandSender sender) + { + Player player = (Player) sender; + UUID uuid = player.getUniqueId(); + try + { + String token = query("token", uuid); + if (token == null) + { + getLogger().message(player, true, "You don't have a token yet! Use &e/gettoken <email>&7 to get one."); + } + else + { + String email = query("email", uuid); + printToken(player, email, token); + } + } + catch (Exception e) + { + try + { + Thread.sleep(100); + String token = query("token", uuid); + if (token == null) + { + getLogger().message(player, true, + "You don't have a token yet! Use &e/gettoken <email>&7 to get one."); + } + else + { + String email = query("email", uuid); + printToken(player, email, token); + } + } + catch (Exception e2) + { + getLogger().message(player, true, "Error getting your token, please contact an admin!"); + e2.printStackTrace(); + } + } + } + + @Command(hook = "gettoken", async = AsyncType.ALWAYS) + public void token(CommandSender sender, String email) + { + Player player = (Player) sender; + if (match(email, "^.+@(.+\\..{2,}|\\[[0-9a-fA-F:.]+\\])$")) + { + String uuid = player.getUniqueId().toString().replaceAll("-", ""); + String token = generateToken(); + try + { + String id = getNextId(); + table.delete(new MysqlConstraint("uuid", ConstraintOperator.EQUAL, uuid)); + table.insert(id, uuid, token, email); + printToken(player, email, token); + } + catch (Exception e) + { + try + { + Thread.sleep(100); + String id = getNextId(); + table.delete(new MysqlConstraint("uuid", ConstraintOperator.EQUAL, uuid)); + table.insert(id, uuid, token, email); + printToken(player, email, token); + } + catch (Exception e2) + { + getLogger().message(player, true, "Error getting your token, please contact an admin!"); + e.printStackTrace(); + } + } + } + else + { + getLogger().message(player, true, "Hmm... That doesn't look like a valid email!"); + } + } +} |