diff --git a/pom.xml b/pom.xml index 04504f1..f036002 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ xyz.etztech QoL - 1.0 + 1.2 jar @@ -58,6 +58,16 @@ spigot-api 1.13.1-R0.1-SNAPSHOT + + xyz.etztech + EtzCore + 1.0 + + + net.ess3 + Essentials + 2.14-SNAPSHOT + commons-lang commons-lang @@ -76,6 +86,14 @@ spigot-repo https://hub.spigotmc.org/nexus/content/groups/public/ + + etztech-repo + http://repo.etztech.xyz + + + ess-repo + http://repo.ess3.net/content/groups/essentials + mvn-repo https://mvnrepository.com/artifact/ diff --git a/src/main/java/xyz/etztech/qol/QoL.java b/src/main/java/xyz/etztech/qol/QoL.java index 3aa3cc6..705ec9e 100644 --- a/src/main/java/xyz/etztech/qol/QoL.java +++ b/src/main/java/xyz/etztech/qol/QoL.java @@ -1,5 +1,7 @@ package xyz.etztech.qol; +import com.earth2me.essentials.Essentials; +import net.ess3.api.IEssentials; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.configuration.file.FileConfiguration; @@ -8,6 +10,7 @@ import org.bukkit.plugin.java.JavaPlugin; import xyz.etztech.qol.commands.*; import xyz.etztech.qol.listeners.*; import xyz.etztech.qol.other.LinkCommand; +import xyz.etztech.qol.other.TPSRunnable; import java.util.ArrayList; import java.util.List; @@ -16,9 +19,8 @@ import java.util.logging.Logger; public class QoL extends JavaPlugin { private static QoL instance; - /** - * Connection Pool - */ + private static IEssentials essentials = null; + public static FileConfiguration config; private Logger log = Logger.getLogger( "Minecraft" ); @@ -35,6 +37,12 @@ public class QoL extends JavaPlugin { reloadConfig(); saveResource("qol.png", false); + //Essentials hook + if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) { + log("Hooked into Essentials for TPS alert."); + essentials = (Essentials) Bukkit.getPluginManager().getPlugin("Essentials"); + } + if( isEnabled() ) { @@ -50,6 +58,8 @@ public class QoL extends JavaPlugin { getServer().getPluginManager().registerEvents(blockIgniteListener, this); CommandPreprocessListener commandPreprocessListener = new CommandPreprocessListener(this); getServer().getPluginManager().registerEvents(commandPreprocessListener, this); + DeathListener deathListener = new DeathListener(this); + getServer().getPluginManager().registerEvents(deathListener, this); // Add commands MainCommand mainCommand = new MainCommand(this); @@ -72,6 +82,8 @@ public class QoL extends JavaPlugin { this.getCommand("timeout").setExecutor(timeoutCommand); ColorsCommand colorsCommand = new ColorsCommand(this); this.getCommand("colors").setExecutor(colorsCommand); + WorldInfoCommand worldInfoCommand = new WorldInfoCommand(this); + this.getCommand("worldinfo").setExecutor(worldInfoCommand); @@ -111,6 +123,9 @@ public class QoL extends JavaPlugin { }, 0, EtzTechUtil.minutesToTicks(frequency)); } + // TPS Check + Bukkit.getScheduler().scheduleSyncRepeatingTask(QoL.getInstance(), new TPSRunnable(this), 0, EtzTechUtil.minutesToTicks(1)); + } } @@ -189,6 +204,8 @@ public class QoL extends JavaPlugin { } } + + public static boolean hasSM(Player player) { return mutes.contains(player.getUniqueId().toString()); } @@ -221,6 +238,11 @@ public class QoL extends JavaPlugin { return links; } + public static IEssentials getEssentials() { + return essentials; + } + + private void runTask(final String command) { Bukkit.getScheduler().runTask(QoL.instance, new Runnable() { @Override diff --git a/src/main/java/xyz/etztech/qol/commands/WorldInfoCommand.java b/src/main/java/xyz/etztech/qol/commands/WorldInfoCommand.java new file mode 100644 index 0000000..636feb3 --- /dev/null +++ b/src/main/java/xyz/etztech/qol/commands/WorldInfoCommand.java @@ -0,0 +1,59 @@ +package xyz.etztech.qol.commands; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import xyz.etztech.qol.Lang; +import xyz.etztech.qol.QoL; + +import java.util.*; + +public class WorldInfoCommand implements CommandExecutor { + + QoL plugin; + + public WorldInfoCommand(QoL plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("qol.worldinfo")) { + sender.sendMessage(Lang.NO_PERMISSION.getDef()); + } + + Map> worlds = new HashMap<>(); + + for (World world : Bukkit.getServer().getWorlds()) { + for (Player player : world.getPlayers()) { + if (worlds.containsKey(world.getName())) { + worlds.get(world.getName()).add(getName(world.getName(), player)); + } else { + worlds.put(world.getName(), new ArrayList<>(Arrays.asList(getName(world.getName(), player)))); + } + } + } + + StringBuilder message = new StringBuilder(ChatColor.GOLD + "===== World Info ====="); + for (String world : worlds.keySet()) { + message.append("\n").append(ChatColor.YELLOW).append(world).append(": ").append(StringUtils.join(worlds.get(world).toArray(), ChatColor.YELLOW + ", ")); + } + sender.sendMessage(message.toString()); + + return true; + } + + private String getName(String world, Player player) { + int range = plugin.getConfig().getInt("worldinfo." + world, 0); + ChatColor color = ChatColor.GREEN; + if (range > 0 && (player.getLocation().getBlockX() > range || player.getLocation().getBlockZ() > range)) { + color = ChatColor.RED; + } + return color + player.getName(); + } +} diff --git a/src/main/java/xyz/etztech/qol/listeners/CommandPreprocessListener.java b/src/main/java/xyz/etztech/qol/listeners/CommandPreprocessListener.java index d98599a..64c0a2b 100644 --- a/src/main/java/xyz/etztech/qol/listeners/CommandPreprocessListener.java +++ b/src/main/java/xyz/etztech/qol/listeners/CommandPreprocessListener.java @@ -3,24 +3,17 @@ package xyz.etztech.qol.listeners; import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.TextComponent; import org.apache.commons.lang.StringUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.message.BasicNameValuePair; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import xyz.etztech.core.CoreUtils; +import xyz.etztech.core.web.CoreWeb; import xyz.etztech.qol.QoL; import xyz.etztech.qol.other.LinkCommand; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; public class CommandPreprocessListener implements Listener { @@ -41,13 +34,22 @@ public class CommandPreprocessListener implements Listener { Player sender = event.getPlayer(); // Command Auditing - if (plugin.getConfig().getBoolean("audit.enabled") && QoL.getAudits().contains(base)) { - Map post = new HashMap<>(); - post.put("username", "QoL Auditor"); - post.put("content", sender.getName() + " executed command: " + command); - String webhook = plugin.getConfig().getString("audit.webhook"); - if (StringUtils.isNotEmpty(webhook)) { - POST(webhook, post); + if (sender.hasPermission("qol.audit") && plugin.getConfig().getBoolean("audit.enabled")) { + boolean auditable = false; + for (String audit : QoL.getAudits()) { + if (noSlash(command).startsWith(noSlash(audit))) { + auditable = true; + break; + } + } + if (auditable) { + Map post = new HashMap<>(); + post.put("username", "QoL Auditor"); + post.put("content", "[" + StringUtils.capitalize(sender.getGameMode().name().toLowerCase()) + "] " + sender.getName() + " executed command: " + command); + String webhook = plugin.getConfig().getString("audit.webhook"); + if (StringUtils.isNotEmpty(webhook)) { + CoreWeb.asyncPost(plugin, webhook, post); + } } } @@ -64,31 +66,11 @@ public class CommandPreprocessListener implements Listener { } - private static String POST(String url, Map data) { - StringBuffer result = new StringBuffer(); - try { - HttpClient client = HttpClients.createDefault(); - HttpPost post = new HttpPost(url); - List params = new ArrayList<>(); - for (String key : data.keySet()) { - params.add(new BasicNameValuePair(key, data.get(key))); - } - post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); - client.execute(post); - } catch (Exception ex) { - log("POST request failed. (" + url + ")"); - } - - return result.toString(); + public String noSlash(String command) { + return command.startsWith("/") ? command.substring(1) : command; } - private static void log(String message) { - try { - Bukkit.getConsoleSender().sendMessage(message); - } catch (Exception ex) { - System.out.println(message); - } - } + diff --git a/src/main/java/xyz/etztech/qol/listeners/DeathListener.java b/src/main/java/xyz/etztech/qol/listeners/DeathListener.java new file mode 100644 index 0000000..c958dae --- /dev/null +++ b/src/main/java/xyz/etztech/qol/listeners/DeathListener.java @@ -0,0 +1,41 @@ +package xyz.etztech.qol.listeners; + +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import xyz.etztech.qol.QoL; + +import java.util.Arrays; + + +public class DeathListener implements Listener { + + QoL plugin; + + public DeathListener(QoL plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onDeath(PlayerDeathEvent event) { + String message = event.getDeathMessage(); + event.setDeathMessage(""); + + Location location = event.getEntity().getLocation(); + String coords = StringUtils.join(Arrays.asList(location.getBlockX(), location.getBlockY(), location.getBlockZ()), ", "); + + TextComponent newMessage = new TextComponent(message); + newMessage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Location: " + coords).create())); + + for (Player player : Bukkit.getOnlinePlayers()) { + player.spigot().sendMessage(newMessage); + } + } +} diff --git a/src/main/java/xyz/etztech/qol/other/TPSRunnable.java b/src/main/java/xyz/etztech/qol/other/TPSRunnable.java new file mode 100644 index 0000000..0d1c130 --- /dev/null +++ b/src/main/java/xyz/etztech/qol/other/TPSRunnable.java @@ -0,0 +1,38 @@ +package xyz.etztech.qol.other; + +import net.ess3.api.IEssentials; +import org.apache.commons.lang.StringUtils; +import xyz.etztech.core.web.CoreWeb; +import xyz.etztech.qol.QoL; + +import java.util.HashMap; +import java.util.Map; + +public class TPSRunnable implements Runnable { + private QoL plugin; + + public TPSRunnable(QoL plugin) { + this.plugin = plugin; + } + + + @Override + public void run() { + IEssentials essentials = QoL.getEssentials(); + if (essentials != null) { + double tps = essentials.getTimer().getAverageTPS(); + int threshold = plugin.getConfig().getInt("tps.threshold", 0); + String webhook = plugin.getConfig().getString("tps.webhook", ""); + String message = "@here TPS has fallen below " + threshold + "!"; + if (tps < threshold) { + plugin.log(message); + if (StringUtils.isNotEmpty(webhook)) { + Map data = new HashMap<>(); + data.put("username", "TPS Alert"); + data.put("content", message); + CoreWeb.asyncPost(plugin, webhook, data); + } + } + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 07d4281..7f69269 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -18,6 +18,17 @@ audit: - mute - unban +# TPS alert +# Set to 0 to cancel +tps: + threshold: 12 + webhook: '' + +# The range after which a player will be marked as "outside the border" +worldinfo: + world: 5000 + world_nether: 500 + world_the_end: 10000 # To disable, set minutes to 0 schedule: diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 36f5318..e438e4d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -17,6 +17,9 @@ commands: description: UUID utility command portal: description: Nether Portal utility command + worldinfo: + description: World Info utility command + aliases: [wi] makeme: description: MakeMe utility command sudo: @@ -30,29 +33,35 @@ commands: description: Timeout command permissions: qol.admin: - description: Ability to reload the plugin - default: op + description: Ability to reload the plugin + default: op qol.priority: - description: Allows a player on past the player cap - default: op + description: Allows a player on past the player cap + default: op qol.uuid: - description: Ability to use the UUID command - default: op + description: Ability to use the UUID command + default: op qol.history: - description: Ability to use the Name History command - default: op + description: Ability to use the Name History command + default: op qol.portal: - description: Ability to use the Portal command - default: op + description: Ability to use the Portal command + default: op + qol.worldinfo: + description: Ability to use the World Info command + deafult: op qol.sudo: - description: Ability to use the Sudo command - default: op + description: Ability to use the Sudo command + default: op qol.makeme: description: Ability to use the MakeMe command default: true qol.shadowmute: description: Ability to use the Shadow Mute command default: op + qol.audit: + description: Audits command usage + default: op qol.whitelist.bypass: description: Allows someone into the server when Whitelist is enabled default: op