diff --git a/.classpath b/.classpath index 0ab4720..cc4498e 100644 --- a/.classpath +++ b/.classpath @@ -6,7 +6,7 @@ - + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index ebfb89d..d089a9b 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,8 +1,11 @@ eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=15 -org.eclipse.jdt.core.compiler.compliance=15 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=15 +org.eclipse.jdt.core.compiler.source=17 diff --git a/en-us.yml b/en-us.yml index 5dbd15b..811bff5 100644 --- a/en-us.yml +++ b/en-us.yml @@ -83,6 +83,7 @@ actions: kitpvpkill: kill recover: recovered inv of money: money + gamemode: switched gamemode to pos: position activity: activity hurt: hurt diff --git a/implement.bat b/implement.bat new file mode 100644 index 0000000..9eea688 --- /dev/null +++ b/implement.bat @@ -0,0 +1,2 @@ +@Echo off +copy %UserProfile%\eclipse-workspace\AuxProtect\target\AuxProtect-1.1-pre6.jar %UserProfile%\Documents\TestServer\Test1\plugins\AuxProtect.jar \ No newline at end of file diff --git a/plugin.yml b/plugin.yml index 49f216a..280cd43 100644 --- a/plugin.yml +++ b/plugin.yml @@ -1,5 +1,5 @@ name: AuxProtect -version: 1.1-pre5 +version: 1.1-pre7 main: dev.heliosares.auxprotect.AuxProtect description: A plugin designed to supplement CoreProtect in a few ways. api-version: 1.13 diff --git a/pom.xml b/pom.xml index 2e7d1bc..919621c 100644 --- a/pom.xml +++ b/pom.xml @@ -2,16 +2,19 @@ 4.0.0 AuxProtect AuxProtect - 1.1-pre5 + 1.1-pre7 AuxProtect - ${testserver}/plugins + ${project.artifactId}-${project.version} ${basedir} true - * + plugin.yml + en-us.yml + config.yml + bungee.yml @@ -21,9 +24,30 @@ maven-compiler-plugin 3.8.1 - 15 + 17 + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + package + + + + + + + + + + run + + + + @@ -113,7 +137,7 @@ auctionhouse 1.0 system - ${jars}/AuctionHouse-1.18-3.1.jar + ${jars}/AuctionHouse-1.18.2-3.2.2.jar com.github.7sat @@ -123,7 +147,7 @@ - ${env.USERPROFILE}/eclipse-workspace\jars + ${env.USERPROFILE}/eclipse-workspace/jars ${env.USERPROFILE}/Documents/TestServer/Test1/ \ No newline at end of file diff --git a/scripts/implement.cmd b/scripts/implement.cmd new file mode 100644 index 0000000..7b2f4ef --- /dev/null +++ b/scripts/implement.cmd @@ -0,0 +1,2 @@ +@Echo off +copy %UserProfile%\eclipse-workspace\AuxProtect\target\AuxProtect.jar %UserProfile%\Documents\TestServer\Test1\plugins\AuxProtect.jar \ No newline at end of file diff --git a/src/dev/heliosares/auxprotect/APPlayer.java b/src/dev/heliosares/auxprotect/APPlayer.java index 7996c77..ed42832 100644 --- a/src/dev/heliosares/auxprotect/APPlayer.java +++ b/src/dev/heliosares/auxprotect/APPlayer.java @@ -12,8 +12,9 @@ public class APPlayer { public long lastLoggedActivity; public Location lastLocation; public long lastCheckedMovement; - public double moved; - public double[] activity = new double[20]; + public double movedAmountThisMinute; + public boolean hasMovedThisMinute; + public double[] activity = new double[30]; public int activityIndex; public long lastNotifyInactive; diff --git a/src/dev/heliosares/auxprotect/AuxProtect.java b/src/dev/heliosares/auxprotect/AuxProtect.java index 1f66046..fc53e55 100644 --- a/src/dev/heliosares/auxprotect/AuxProtect.java +++ b/src/dev/heliosares/auxprotect/AuxProtect.java @@ -207,7 +207,7 @@ public class AuxProtect extends JavaPlugin implements IAuxProtect { if (System.currentTimeMillis() - apPlayer.lastCheckedMovement > 1000) { if (apPlayer.lastLocation != null && apPlayer.lastLocation.getWorld().equals(apPlayer.player.getWorld())) { - apPlayer.moved += Math + apPlayer.movedAmountThisMinute += Math .min(apPlayer.lastLocation.distance(apPlayer.player.getLocation()), 10); } apPlayer.lastLocation = apPlayer.player.getLocation(); @@ -221,7 +221,13 @@ public class AuxProtect extends JavaPlugin implements IAuxProtect { if (apPlayer.player.getWorld().getName().equals("flat") && config.isPrivate()) { apPlayer.activity[apPlayer.activityIndex] += 100; } - apPlayer.activity[apPlayer.activityIndex] += Math.floor((apPlayer.moved + 7) / 10); + apPlayer.addActivity(Math.floor((apPlayer.movedAmountThisMinute + 7) / 10)); + apPlayer.movedAmountThisMinute = 0; + + if (apPlayer.hasMovedThisMinute) { + apPlayer.addActivity(1); + apPlayer.hasMovedThisMinute = false; + } add(new DbEntry(AuxProtect.getLabel(apPlayer.player), EntryAction.ACTIVITY, false, apPlayer.player.getLocation(), "", @@ -239,7 +245,8 @@ public class AuxProtect extends JavaPlugin implements IAuxProtect { inactive++; } } - if (tallied >= 10 && (double) inactive / (double) tallied > 0.8) { + if (tallied >= 15 && (double) inactive / (double) tallied > 0.75 + && !MyPermission.BYPASS_INACTIVE.hasPermission(apPlayer.player)) { if (System.currentTimeMillis() - apPlayer.lastNotifyInactive > 600000L) { apPlayer.lastNotifyInactive = System.currentTimeMillis(); String msg = String.format(lang.translate("inactive-alert"), @@ -260,7 +267,6 @@ public class AuxProtect extends JavaPlugin implements IAuxProtect { apPlayer.activityIndex = 0; } apPlayer.activity[apPlayer.activityIndex] = 0; - apPlayer.moved = 0; } } } diff --git a/src/dev/heliosares/auxprotect/command/APCommand.java b/src/dev/heliosares/auxprotect/command/APCommand.java index a286198..08cdc12 100644 --- a/src/dev/heliosares/auxprotect/command/APCommand.java +++ b/src/dev/heliosares/auxprotect/command/APCommand.java @@ -25,6 +25,7 @@ public class APCommand implements CommandExecutor { private ActivityCommand activityCommand; private XrayCommand xrayCommand; private MoneyCommand moneyCommand; + private RetentionCommand retentionCommand; public APCommand(AuxProtect plugin) { this.plugin = plugin; @@ -35,6 +36,7 @@ public class APCommand implements CommandExecutor { activityCommand = new ActivityCommand(plugin); xrayCommand = new XrayCommand(plugin); moneyCommand = new MoneyCommand(plugin); + retentionCommand = new RetentionCommand(plugin); } @Override @@ -71,6 +73,12 @@ public class APCommand implements CommandExecutor { return true; } return moneyCommand.onCommand(sender, command, label, args); + } else if (args[0].equalsIgnoreCase("retention")) { + if (!MyPermission.LOOKUP_RETENTION.hasPermission(sender)) { + sender.sendMessage(plugin.translate("no-permission")); + return true; + } + return retentionCommand.onCommand(sender, command, label, args); } else if ((args[0].equalsIgnoreCase("x") || args[0].equalsIgnoreCase("xray")) && plugin.config.isPrivate()) { if (!MyPermission.LOOKUP_XRAY.hasPermission(sender)) { diff --git a/src/dev/heliosares/auxprotect/command/APCommandTab.java b/src/dev/heliosares/auxprotect/command/APCommandTab.java index 7c2ef4f..36fd89b 100644 --- a/src/dev/heliosares/auxprotect/command/APCommandTab.java +++ b/src/dev/heliosares/auxprotect/command/APCommandTab.java @@ -40,14 +40,17 @@ public class APCommandTab implements TabCompleter { if (MyPermission.LOOKUP_ACTIVITY.hasPermission(sender)) { possible.add("activity"); } + if (MyPermission.LOOKUP_RETENTION.hasPermission(sender)) { + possible.add("retention"); + } + if (MyPermission.LOOKUP_MONEY.hasPermission(sender)) { + possible.add("money"); + } } if (MyPermission.ADMIN.hasPermission(sender)) { possible.add("debug"); possible.add("stats"); } - if (MyPermission.LOOKUP_MONEY.hasPermission(sender)) { - possible.add("money"); - } if (MyPermission.HELP.hasPermission(sender)) { possible.add("help"); } diff --git a/src/dev/heliosares/auxprotect/command/LookupCommand.java b/src/dev/heliosares/auxprotect/command/LookupCommand.java index 4eb4ab7..704ec4f 100644 --- a/src/dev/heliosares/auxprotect/command/LookupCommand.java +++ b/src/dev/heliosares/auxprotect/command/LookupCommand.java @@ -17,6 +17,7 @@ import dev.heliosares.auxprotect.utils.MoneySolver; import dev.heliosares.auxprotect.utils.MyPermission; import dev.heliosares.auxprotect.utils.MySender; import dev.heliosares.auxprotect.utils.PlayTimeSolver; +import dev.heliosares.auxprotect.utils.RetentionSolver; import dev.heliosares.auxprotect.utils.TimeUtil; import dev.heliosares.auxprotect.utils.XraySolver; @@ -127,6 +128,7 @@ public class LookupCommand { boolean bw = false; boolean money = false; boolean activity = false; + boolean retention = false; long startTime = 0; long endTime = System.currentTimeMillis(); for (int i = 1; i < args.length; i++) { @@ -160,6 +162,13 @@ public class LookupCommand { } money = true; continue; + } else if (args[i].equalsIgnoreCase("#retention")) { + if (!MyPermission.LOOKUP_RETENTION.hasPermission(sender)) { + sender.sendMessage(plugin.translate("no-permission-flag")); + return; + } + retention = true; + continue; } String[] split = args[i].split(":"); @@ -430,6 +439,8 @@ public class LookupCommand { return; } + } else if (retention) { + RetentionSolver.showRetention(plugin, sender, rs, startTime, endTime); } else { String uuid = sender.getUniqueId().toString(); Results result = new Results(plugin, rs, sender, sender.isBungee() ? "apb" : "ap"); diff --git a/src/dev/heliosares/auxprotect/command/LookupCommandTab.java b/src/dev/heliosares/auxprotect/command/LookupCommandTab.java index 08feb06..1386733 100644 --- a/src/dev/heliosares/auxprotect/command/LookupCommandTab.java +++ b/src/dev/heliosares/auxprotect/command/LookupCommandTab.java @@ -127,6 +127,9 @@ public class LookupCommandTab implements TabCompleter { if (MyPermission.LOOKUP_ACTIVITY.hasPermission(sender)) { possible.add("#activity"); } + if (MyPermission.LOOKUP_RETENTION.hasPermission(sender)) { + possible.add("#retention"); + } } List output = new ArrayList<>(); diff --git a/src/dev/heliosares/auxprotect/command/RetentionCommand.java b/src/dev/heliosares/auxprotect/command/RetentionCommand.java new file mode 100644 index 0000000..d82984f --- /dev/null +++ b/src/dev/heliosares/auxprotect/command/RetentionCommand.java @@ -0,0 +1,27 @@ +package dev.heliosares.auxprotect.command; + +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + +import dev.heliosares.auxprotect.AuxProtect; + +public class RetentionCommand implements CommandExecutor { + + private AuxProtect plugin; + + public RetentionCommand(AuxProtect plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length != 2) { + sender.sendMessage(plugin.translate("lookup-invalid-syntax")); + return true; + } + Bukkit.dispatchCommand(sender, String.format("ap lookup #retention time:%s action:username", args[1])); + return true; + } +} diff --git a/src/dev/heliosares/auxprotect/command/XrayCommand.java b/src/dev/heliosares/auxprotect/command/XrayCommand.java index c8c9be4..a72ac88 100644 --- a/src/dev/heliosares/auxprotect/command/XrayCommand.java +++ b/src/dev/heliosares/auxprotect/command/XrayCommand.java @@ -241,8 +241,8 @@ public class XrayCommand implements CommandExecutor { new BukkitRunnable() { @Override public void run() { - Bukkit.getServer().dispatchCommand(sender, (String.format("ap tp %d %d %d %s", - newEnt.x, newEnt.y, newEnt.z, newEnt.world))); + Bukkit.getServer().dispatchCommand(sender, (String.format("ap tp %d %d %d %s %d %d", + newEnt.x, newEnt.y, newEnt.z, newEnt.world, 45, 0))); } }.runTask(plugin); } @@ -367,8 +367,8 @@ public class XrayCommand implements CommandExecutor { if (player != null) { uuid = player.getUniqueId().toString(); } - entries.sort((o1, o2) -> o1.getUser().compareTo(o2.getUser())); entries.sort((o1, o2) -> o1.world.compareTo(o2.world)); + entries.sort((o1, o2) -> o1.getUser().compareTo(o2.getUser())); XrayResults result = new XrayResults(plugin, entries, sender); result.showPage(1, 1); XrayCommand.this.results.put(uuid, result); diff --git a/src/dev/heliosares/auxprotect/database/EntryAction.java b/src/dev/heliosares/auxprotect/database/EntryAction.java index bb7e8cc..a57769b 100644 --- a/src/dev/heliosares/auxprotect/database/EntryAction.java +++ b/src/dev/heliosares/auxprotect/database/EntryAction.java @@ -47,6 +47,7 @@ public class EntryAction { // SKIPPED 135 public static final EntryAction RECOVER = new EntryAction("recover", 136); public static final EntryAction MONEY = new EntryAction("money", 137); + public static final EntryAction GAMEMODE = new EntryAction("gamemode", 138); // END DEFAULT (255) // START SPAM(256) @@ -58,6 +59,7 @@ public class EntryAction { public static final EntryAction LAND = new EntryAction("land", 262); public static final EntryAction ELYTRA = new EntryAction("elytra", 263, 264); public static final EntryAction ACTIVITY = new EntryAction("activity", 265); + public static final EntryAction TOTEM = new EntryAction("totem", 266); // END SPAM(511) // START IGNOREABANDONED(512) diff --git a/src/dev/heliosares/auxprotect/database/Results.java b/src/dev/heliosares/auxprotect/database/Results.java index 1c731cc..06ad2f8 100644 --- a/src/dev/heliosares/auxprotect/database/Results.java +++ b/src/dev/heliosares/auxprotect/database/Results.java @@ -81,8 +81,19 @@ public class Results { + "\n§7Click to copy epoch time."))) .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, en.getTime() + "e")); - message.append(String.format(" §f- §9%s §f%s §9%s§f", en.getUser(), - en.getAction().getText(plugin, en.getState()), en.getTarget())).event((HoverEvent) null); + // message.append(String.format(" §f- §9%s §f%s §9%s§f", en.getUser(), + // en.getAction().getText(plugin, en.getState()), + // en.getTarget())).event((HoverEvent) null); + message.append(" §f- ").event((HoverEvent) null); + HoverEvent clickToCopy = new HoverEvent(HoverEvent.Action.SHOW_TEXT, + new Text("Click to copy to clipboard")); + message.append("§9" + en.getUser()).event(clickToCopy) + .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, en.getUser())); + message.append(" §f" + en.getAction().getText(plugin, en.getState())).event((HoverEvent) null) + .event((ClickEvent) null); + message.append(" §9" + en.getTarget()).event(clickToCopy) + .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, en.getTarget())); + String data = en.getData(); if (data != null && data.contains(InvSerialization.itemSeparator)) { data = data.split(InvSerialization.itemSeparator)[0]; @@ -93,30 +104,33 @@ public class Results { .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§fClick to view!"))); } } - if (en.getAction().equals( EntryAction.INVENTORY)) { + if (en.getAction().equals(EntryAction.INVENTORY)) { if (MyPermission.INV.hasPermission(player)) { message.append(" §a[View]") .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format(commandPrefix + " inv %d", i))) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§fClick to view!"))); } - } else if (en.getAction() .equals( EntryAction.KILL)) { + } else if (en.getAction().equals(EntryAction.KILL)) { if (MyPermission.INV.hasPermission(player) && !en.getTarget().startsWith("#")) { message.append(" §a[View Inv]").event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format(commandPrefix + " l u:%s a:inventory target:death before:%de after:%de", en.getTarget(), en.getTime() + 50L, en.getTime() - 50L))) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§fClick to view!"))); } - message.append(" §7(" + data + ")"); + message.append(" §7(" + data + ")").event(clickToCopy) + .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, en.getData())); } else if (data != null && data.length() > 0) { - message.append(" §7(" + data + ")"); + message.append(" §7(" + data + ")").event(clickToCopy) + .event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, en.getData())); } if (en.world != null && !en.world.equals("$null")) { String tpCommand = String.format(commandPrefix + " tp %d %d %d %s", en.x, en.y, en.z, en.world); if (en.getAction().getTable().hasLook()) { tpCommand += String.format(" %d %d", en.pitch, en.yaw); } - message.append(String.format("\n §7§l^ §7(x%d/y%d/z%d/%s)", en.x, en.y, en.z, en.world)) + message.append("\n §7§l^ ").event((HoverEvent) null).event((ClickEvent) null); + message.append(String.format("§7(x%d/y%d/z%d/%s)", en.x, en.y, en.z, en.world)) .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, tpCommand)) .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("§7" + tpCommand))); if (en.getAction().getTable().hasLook()) { diff --git a/src/dev/heliosares/auxprotect/database/SQLManager.java b/src/dev/heliosares/auxprotect/database/SQLManager.java index f8a81a6..b60eaba 100644 --- a/src/dev/heliosares/auxprotect/database/SQLManager.java +++ b/src/dev/heliosares/auxprotect/database/SQLManager.java @@ -655,6 +655,28 @@ public class SQLManager { return rowList; } + public HashMap getAllUids() throws SQLException { + HashMap out = new HashMap<>(); + + synchronized (connection) { + + String stmt = "SELECT * FROM " + Table.AUXPROTECT_UIDS.toString() + ";"; + plugin.debug(stmt, 3); + try (PreparedStatement pstmt = connection.prepareStatement(stmt)) { + pstmt.setFetchSize(500); + try (ResultSet results = pstmt.executeQuery()) { + while (results.next()) { + int uid = results.getInt("uid"); + String uuid = results.getString("uuid"); + out.put(uid, uuid); + } + } + } + } + + return out; + } + private void putRaw(Table table, ArrayList datas) throws SQLException, ClassCastException, IndexOutOfBoundsException { checkAsync(); @@ -1364,6 +1386,34 @@ public class SQLManager { return null; } + public HashMap getUsernamesFromUID(int uid) { + HashMap out = new HashMap<>(); + String stmt = "SELECT * FROM " + Table.AUXPROTECT_LONGTERM.toString() + " WHERE action_id=? AND uid=?;"; + plugin.debug(stmt, 3); + checkAsync(); + synchronized (connection) { + try (PreparedStatement pstmt = connection.prepareStatement(stmt)) { + pstmt.setInt(1, EntryAction.USERNAME.id); + pstmt.setInt(2, uid); + try (ResultSet results = pstmt.executeQuery()) { + while (results.next()) { + long time = results.getLong("time"); + String username = results.getString("target"); + if (username != null) { + out.put(time, username); + } + } + } catch (SQLException e) { + plugin.print(e); + } + } catch (SQLException e) { + plugin.print(e); + } + } + + return out; + } + public int getUIDFromUsername(String username) { if (username == null) { return -1; diff --git a/src/dev/heliosares/auxprotect/listeners/AuctionHouseListener.java b/src/dev/heliosares/auxprotect/listeners/AuctionHouseListener.java index eef90cc..790d32a 100644 --- a/src/dev/heliosares/auxprotect/listeners/AuctionHouseListener.java +++ b/src/dev/heliosares/auxprotect/listeners/AuctionHouseListener.java @@ -5,6 +5,7 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import com.spawnchunk.auctionhouse.events.ListItemEvent; import com.spawnchunk.auctionhouse.events.PurchaseItemEvent; @@ -21,7 +22,7 @@ public class AuctionHouseListener implements Listener { this.plugin = plugin; } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onListItemEvent(ListItemEvent e) { Location l = null; if (e.getSeller() instanceof Player) { @@ -38,7 +39,7 @@ public class AuctionHouseListener implements Listener { plugin.formatMoney(e.getPrice()) + InvSerialization.toBase64(e.getItem()))); } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPurchaseItemEvent(PurchaseItemEvent e) { Location l = null; if (e.getBuyer() instanceof Player) { diff --git a/src/dev/heliosares/auxprotect/listeners/ChestShopListener.java b/src/dev/heliosares/auxprotect/listeners/ChestShopListener.java index f436a1b..b1b5eee 100644 --- a/src/dev/heliosares/auxprotect/listeners/ChestShopListener.java +++ b/src/dev/heliosares/auxprotect/listeners/ChestShopListener.java @@ -2,6 +2,7 @@ package dev.heliosares.auxprotect.listeners; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; @@ -19,7 +20,7 @@ public class ChestShopListener implements Listener { this.plugin = plugin; } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onShopPostTransactionEvent(TransactionEvent e) { boolean state = e.getTransactionType() == TransactionType.BUY; int qty = 0; diff --git a/src/dev/heliosares/auxprotect/listeners/DynamicShopListener.java b/src/dev/heliosares/auxprotect/listeners/DynamicShopListener.java index c410dd7..d89cff5 100644 --- a/src/dev/heliosares/auxprotect/listeners/DynamicShopListener.java +++ b/src/dev/heliosares/auxprotect/listeners/DynamicShopListener.java @@ -17,7 +17,7 @@ public class DynamicShopListener implements Listener { this.plugin = plugin; } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onShopBuySellEvent(ShopBuySellEvent e) { ItemStack item = e.getItemStack(); boolean buy = e.isBuy(); diff --git a/src/dev/heliosares/auxprotect/listeners/EconomyShopGUIListener.java b/src/dev/heliosares/auxprotect/listeners/EconomyShopGUIListener.java index 441597a..5f14470 100644 --- a/src/dev/heliosares/auxprotect/listeners/EconomyShopGUIListener.java +++ b/src/dev/heliosares/auxprotect/listeners/EconomyShopGUIListener.java @@ -17,11 +17,8 @@ public class EconomyShopGUIListener implements Listener { this.plugin = plugin; } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPreTransactionEvent(PreTransactionEvent e) { - if (e.isCancelled()) { - return; - } ItemStack item = e.getItemStack(); boolean state = e.getTransactionMode().contains("BUY"); String data = "ESG, " + plugin.formatMoney(e.getPrice()) + ", QTY: " + item.getAmount(); diff --git a/src/dev/heliosares/auxprotect/listeners/EntityListener.java b/src/dev/heliosares/auxprotect/listeners/EntityListener.java index 479c829..ab7393f 100644 --- a/src/dev/heliosares/auxprotect/listeners/EntityListener.java +++ b/src/dev/heliosares/auxprotect/listeners/EntityListener.java @@ -2,6 +2,7 @@ package dev.heliosares.auxprotect.listeners; import java.util.ArrayList; +import org.bukkit.Material; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemFrame; @@ -16,7 +17,11 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.hanging.HangingBreakEvent; import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.projectiles.ProjectileSource; import org.spigotmc.event.entity.EntityDismountEvent; import org.spigotmc.event.entity.EntityMountEvent; @@ -40,33 +45,22 @@ public class EntityListener implements Listener { blacklistedDamageCauses.add(DamageCause.ENTITY_SWEEP_ATTACK); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onEntityDismountEvent(EntityDismountEvent e) { - if (e.isCancelled()) { - return; - } - DbEntry entry = new DbEntry(AuxProtect.getLabel(e.getEntity()), EntryAction.MOUNT, false, e.getDismounted().getLocation(), AuxProtect.getLabel(e.getDismounted()), ""); plugin.add(entry); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onEntityMountEvent(EntityMountEvent e) { - if (e.isCancelled()) { - return; - } - DbEntry entry = new DbEntry(AuxProtect.getLabel(e.getEntity()), EntryAction.MOUNT, true, e.getMount().getLocation(), AuxProtect.getLabel(e.getMount()), ""); plugin.add(entry); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void entityDamageByEntityEvent(EntityDamageByEntityEvent e) { - if (e.isCancelled()) { - return; - } if (e.getEntity() instanceof ItemFrame) { final ItemFrame item = (ItemFrame) e.getEntity(); if (item.getItem() != null) { @@ -112,13 +106,34 @@ public class EntityListener implements Listener { EntryAction action = EntryAction.HURT; if (e.getEntity() instanceof LivingEntity && ((LivingEntity) e.getEntity()).getHealth() - e.getFinalDamage() <= 0) { - action = EntryAction.KILL; + boolean totem = false; + LivingEntity livingEntity = (LivingEntity) e.getEntity(); + EntityEquipment equip = livingEntity.getEquipment(); + if (equip != null) { + ItemStack hand = equip.getItem(EquipmentSlot.HAND); + ItemStack offhand = equip.getItem(EquipmentSlot.OFF_HAND); + if (hand != null && hand.getType() == Material.TOTEM_OF_UNDYING) { + totem = true; + } else if (offhand != null && offhand.getType() == Material.TOTEM_OF_UNDYING) { + totem = true; + } + } + if (!totem) { + action = EntryAction.KILL; + } } DbEntry entry = new DbEntry(sourceName, action, false, e.getEntity().getLocation(), targetName, itemname); plugin.add(entry); } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onResurrect(EntityResurrectEvent e) { + DbEntry entry = new DbEntry(AuxProtect.getLabel(e.getEntity()), EntryAction.TOTEM, false, + e.getEntity().getLocation(), "", ""); + plugin.add(entry); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onHangingBreakEvent(HangingBreakEvent e) { if (e.getCause() == RemoveCause.ENTITY) { return; @@ -139,11 +154,8 @@ public class EntityListener implements Listener { } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void entityDamageEvent(EntityDamageEvent e) { - if (e.isCancelled()) { - return; - } if (e.getEntity().isDead()) { return; } diff --git a/src/dev/heliosares/auxprotect/listeners/InventoryListener.java b/src/dev/heliosares/auxprotect/listeners/InventoryListener.java index e55a1d2..d85e2c0 100644 --- a/src/dev/heliosares/auxprotect/listeners/InventoryListener.java +++ b/src/dev/heliosares/auxprotect/listeners/InventoryListener.java @@ -23,15 +23,12 @@ public class InventoryListener implements Listener { this.plugin = plugin; } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onInventoryOpenEvent(InventoryOpenEvent e) { - if(e.isCancelled()) { - return; - } log(e.getPlayer(), e.getInventory(), true); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onInventoryCloseEvent(InventoryCloseEvent e) { log(e.getPlayer(), e.getInventory(), false); } diff --git a/src/dev/heliosares/auxprotect/listeners/PlayerListener.java b/src/dev/heliosares/auxprotect/listeners/PlayerListener.java index f20d0f1..4aba241 100644 --- a/src/dev/heliosares/auxprotect/listeners/PlayerListener.java +++ b/src/dev/heliosares/auxprotect/listeners/PlayerListener.java @@ -20,6 +20,7 @@ import org.bukkit.event.entity.PlayerLeashEntityEvent; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerItemConsumeEvent; @@ -75,14 +76,10 @@ public class PlayerListener implements Listener { mobs.add(EntityType.SALMON); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerInteractEntityEvent(PlayerInteractEntityEvent e) { plugin.getAPPlayer(e.getPlayer()).addActivity(1); - if (e.isCancelled()) { - return; - } - ItemStack mainhand = e.getPlayer().getInventory().getItemInMainHand(); ItemStack offhand = e.getPlayer().getInventory().getItemInOffHand(); if ((mainhand != null && mainhand.getType() == Material.WATER_BUCKET) @@ -113,7 +110,7 @@ public class PlayerListener implements Listener { } } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerInteractEvent(PlayerInteractEvent e) { plugin.getAPPlayer(e.getPlayer()).addActivity(1); @@ -130,21 +127,21 @@ public class PlayerListener implements Listener { } } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onEntityToggleGlideEvent(EntityToggleGlideEvent e) { - if (e.isCancelled()) { - return; - } DbEntry entry = new DbEntry(AuxProtect.getLabel(e.getEntity()), EntryAction.ELYTRA, e.isGliding(), e.getEntity().getLocation(), "", ""); plugin.add(entry); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerGameModeChangeEvent(PlayerGameModeChangeEvent e) { + plugin.add(new DbEntry(AuxProtect.getLabel(e.getPlayer()), EntryAction.GAMEMODE, false, + e.getPlayer().getLocation(), e.getNewGameMode().toString(), "")); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onConsume(PlayerItemConsumeEvent e) { - if (e.isCancelled()) { - return; - } String sup = ""; if (e.getItem().getType() == Material.POTION && e.getItem().getItemMeta() instanceof PotionMeta) { PotionMeta pm = (PotionMeta) e.getItem().getItemMeta(); @@ -155,7 +152,7 @@ public class PlayerListener implements Listener { plugin.add(entry); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerJoinEvent(PlayerJoinEvent e) { APPlayer apPlayer = plugin.getAPPlayer(e.getPlayer()); apPlayer.lastMoved = System.currentTimeMillis(); @@ -204,13 +201,14 @@ public class PlayerListener implements Listener { } } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerMoveEvent(PlayerMoveEvent e) { APPlayer player = plugin.getAPPlayer(e.getPlayer()); player.lastMoved = System.currentTimeMillis(); + player.hasMovedThisMinute = true; } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerTeleport(PlayerTeleportEvent e) { plugin.add(new DbEntry(AuxProtect.getLabel(e.getPlayer()), EntryAction.TP, false, e.getFrom(), "", "")); plugin.add(new DbEntry(AuxProtect.getLabel(e.getPlayer()), EntryAction.TP, true, e.getTo(), "", "")); @@ -237,7 +235,7 @@ public class PlayerListener implements Listener { }.runTaskLater(plugin, 5); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerQuitEvent(PlayerQuitEvent e) { logMoney(plugin, e.getPlayer(), "leave"); logSession(e.getPlayer(), false, ""); @@ -248,11 +246,8 @@ public class PlayerListener implements Listener { plugin.removeAPPlayer(e.getPlayer()); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerKickEvent(PlayerKickEvent e) { - if (e.isCancelled()) { - return; - } plugin.add(new DbEntry(AuxProtect.getLabel(e.getPlayer()), EntryAction.KICK, false, e.getPlayer().getLocation(), "", e.getReason())); } @@ -271,22 +266,15 @@ public class PlayerListener implements Listener { new DbEntry(AuxProtect.getLabel(player), EntryAction.SESSION, login, player.getLocation(), "", supp)); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerLeashEntityEvent(PlayerLeashEntityEvent e) { - if (e.isCancelled()) { - return; - } - DbEntry entry = new DbEntry(AuxProtect.getLabel(e.getPlayer()), EntryAction.LEASH, true, e.getEntity().getLocation(), AuxProtect.getLabel(e.getEntity()), ""); plugin.add(entry); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerUnleashEntityEvent(PlayerUnleashEntityEvent e) { - if (e.isCancelled()) { - return; - } if (!(e.getEntity() instanceof LivingEntity)) { return; } @@ -302,36 +290,30 @@ public class PlayerListener implements Listener { plugin.add(entry); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerRespawnEvent(PlayerRespawnEvent e) { plugin.add(new DbEntry(AuxProtect.getLabel(e.getPlayer()), EntryAction.RESPAWN, false, e.getRespawnLocation(), "", "")); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onCommand(PlayerCommandPreprocessEvent e) { - plugin.getAPPlayer(e.getPlayer()).addActivity(3); - if (e.isCancelled()) { - return; - } + plugin.getAPPlayer(e.getPlayer()).addActivity(5); plugin.add(new DbEntry(AuxProtect.getLabel(e.getPlayer()), EntryAction.COMMAND, false, e.getPlayer().getLocation(), e.getMessage(), "")); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onChat(AsyncPlayerChatEvent e) { - plugin.getAPPlayer(e.getPlayer()).addActivity(3); + plugin.getAPPlayer(e.getPlayer()).addActivity(5); if (e.isCancelled()) { return; } } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onDropEvent(PlayerDropItemEvent e) { - if (e.isCancelled()) { - return; - } if (isChartMap(e.getItemDrop().getItemStack())) { e.getItemDrop().remove(); return; @@ -351,11 +333,8 @@ public class PlayerListener implements Listener { } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPickupEvent(EntityPickupItemEvent e) { - if (e.isCancelled()) { - return; - } if (e.getEntity() instanceof Player) { Player player = (Player) e.getEntity(); diff --git a/src/dev/heliosares/auxprotect/listeners/ProjectileListener.java b/src/dev/heliosares/auxprotect/listeners/ProjectileListener.java index a25a51a..34445be 100644 --- a/src/dev/heliosares/auxprotect/listeners/ProjectileListener.java +++ b/src/dev/heliosares/auxprotect/listeners/ProjectileListener.java @@ -37,11 +37,8 @@ public class ProjectileListener implements Listener { whitelist.add(EntityType.ARROW); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onProjectileLaunchEvent(ProjectileLaunchEvent e) { - if (e.isCancelled()) { - return; - } if (!(e.getEntity().getShooter() instanceof Player)) { return; } @@ -51,7 +48,7 @@ public class ProjectileListener implements Listener { logEntity(e.getEntity(), EntryAction.LAUNCH, true); } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onProjectileHit(ProjectileHitEvent e) { if (e.getHitBlock() == null) { return; @@ -65,7 +62,7 @@ public class ProjectileListener implements Listener { logEntity(e.getEntity(), EntryAction.LAND, false); } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerPickupArrowEvent(PlayerPickupArrowEvent e) { logEntity(e.getArrow(), EntryAction.GRAB, false); } diff --git a/src/dev/heliosares/auxprotect/listeners/ShopGUIPlusListener.java b/src/dev/heliosares/auxprotect/listeners/ShopGUIPlusListener.java index 6eb563b..fa9a192 100644 --- a/src/dev/heliosares/auxprotect/listeners/ShopGUIPlusListener.java +++ b/src/dev/heliosares/auxprotect/listeners/ShopGUIPlusListener.java @@ -1,6 +1,7 @@ package dev.heliosares.auxprotect.listeners; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import dev.heliosares.auxprotect.AuxProtect; @@ -17,7 +18,7 @@ public class ShopGUIPlusListener implements Listener { this.plugin = plugin; } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onShopPostTransactionEvent(ShopPostTransactionEvent e) { if (e.getResult().getAmount() == 0) { return; diff --git a/src/dev/heliosares/auxprotect/utils/ActivitySolver.java b/src/dev/heliosares/auxprotect/utils/ActivitySolver.java index 0bcdc13..0b69171 100644 --- a/src/dev/heliosares/auxprotect/utils/ActivitySolver.java +++ b/src/dev/heliosares/auxprotect/utils/ActivitySolver.java @@ -11,6 +11,7 @@ import dev.heliosares.auxprotect.database.DbEntry; import dev.heliosares.auxprotect.database.EntryAction; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ComponentBuilder; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.ComponentBuilder.FormatRetention; @@ -20,18 +21,23 @@ public class ActivitySolver { public static BaseComponent[] solveActivity(ArrayList entries, long lookupStartMillis, int minutes, String player) { ComponentBuilder message = new ComponentBuilder().append("", FormatRetention.NONE); - if (minutes > 120) { - message.append("Time period too long. Max 2 hours."); + if (minutes > 60 * 12) { + message.append("Time period too long. Max 12 hours."); return message.create(); } LocalDateTime startTime = Instant.ofEpochMilli(lookupStartMillis).atZone(ZoneId.systemDefault()) .toLocalDateTime().withSecond(0).withNano(0); DateTimeFormatter formatterDateTime = DateTimeFormatter.ofPattern("ddMMM hh:mm a"); + DateTimeFormatter formatterHour = DateTimeFormatter.ofPattern("Ka"); final long startMillis = startTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); int[] counter = new int[minutes]; for (int i = 0; i < counter.length; i++) { counter[i] = -1; } + String line = "§7§m"; + for (int i = 0; i < 14; i++) { + line += (char) 65293; + } long lastTime = startMillis; for (int i = entries.size() - 1, minute = 0; i >= 0; i--) { DbEntry entry = entries.get(i); @@ -65,13 +71,18 @@ public class ActivitySolver { minute++; } int shiftMinutes = 0; - while ((counter.length + shiftMinutes) % 30 != 0) { + // while ((counter.length + shiftMinutes) % 30 != 0) { + for (int i = 0; i < (startTime.getMinute() % 30); i++) { message.append(AuxProtect.BLOCK + "").color(ChatColor.BLACK); shiftMinutes++; } for (int i = 0; i < counter.length; i++) { LocalDateTime time = startTime.plusMinutes(i); + if (time.getMinute() == 0) { + message.append(line + String.format("§f %s ", time.format(formatterHour)) + line + "\n") + .event((ClickEvent) null).event((HoverEvent) null); + } int activity = counter[i]; @@ -79,8 +90,10 @@ public class ActivitySolver { if (activity < 0) { hovertext += "§7Offline"; - } else { + } else if (activity > 0) { hovertext += "§7Activity Level §9" + activity; + } else { + hovertext += "§cNo Activity"; } message.append(AuxProtect.BLOCK + "") @@ -94,7 +107,7 @@ public class ActivitySolver { } else if (activity == 0) { message.color(ChatColor.of("#4e0808")); // Dark red } else { - message.color(ChatColor.BLACK); + message.color(ChatColor.DARK_GRAY); } if ((i + 1 + shiftMinutes) % 30 == 0 && i < counter.length - 1) { message.append("\n"); diff --git a/src/dev/heliosares/auxprotect/utils/MyPermission.java b/src/dev/heliosares/auxprotect/utils/MyPermission.java index 1db411f..b2d6d17 100644 --- a/src/dev/heliosares/auxprotect/utils/MyPermission.java +++ b/src/dev/heliosares/auxprotect/utils/MyPermission.java @@ -6,7 +6,8 @@ public enum MyPermission { ADMIN("admin"), LOOKUP("lookup"), PURGE("purge"), TP("tp"), HELP("help"), LOOKUP_XRAY("lookup.xray"), LOOKUP_XRAY_OVERWRITE("lookup.xray.overwrite"), LOOKUP_PLAYTIME("lookup.playtime"), LOOKUP_ACTIVITY("lookup.activity"), INV("inv"), INV_EDIT("inv.edit"), INV_RECOVER("inv.recover"), - LOOKUP_MONEY("lookup.money"), SQL("sql"), NOTIFY_INACTIVE("notify.inactive"); + LOOKUP_MONEY("lookup.money"), SQL("sql"), NOTIFY_INACTIVE("inactive.notify"), BYPASS_INACTIVE("inactive.bypass"), + LOOKUP_RETENTION("lookup.retention"); public final String node; diff --git a/src/dev/heliosares/auxprotect/utils/RetentionSolver.java b/src/dev/heliosares/auxprotect/utils/RetentionSolver.java new file mode 100644 index 0000000..626fffb --- /dev/null +++ b/src/dev/heliosares/auxprotect/utils/RetentionSolver.java @@ -0,0 +1,85 @@ +package dev.heliosares.auxprotect.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.Statistic; + +import dev.heliosares.auxprotect.IAuxProtect; +import dev.heliosares.auxprotect.database.DbEntry; + +public class RetentionSolver { + + public static void showRetention(IAuxProtect plugin, MySender sender, ArrayList entries, long startTime, + long endTime) { + long start = System.currentTimeMillis(); + Set lookupUids = new HashSet<>(); + for (DbEntry entry : entries) { + if (entry.getAction().id != 769) { + continue; + } + lookupUids.add(entry.getUid()); + } + + HashMap playtimes = new HashMap<>(); + HashMap thresholds = new HashMap<>(); + thresholds.put(1 * 60 * 20, 0); + thresholds.put(5 * 60 * 20, 0); + thresholds.put(10 * 60 * 20, 0); + thresholds.put(30 * 60 * 20, 0); + thresholds.put(60 * 60 * 20, 0); + thresholds.put(3 * 60 * 60 * 20, 0); + int onlinern = 0; + for (int uid : lookupUids) { + HashMap usernames = plugin.getSqlManager().getUsernamesFromUID(uid); + boolean valid = true; + for (long time : usernames.keySet()) { + if (time < startTime) { + valid = false; + break; + } + } + if (!valid) { + continue; + } + OfflinePlayer player = Bukkit + .getOfflinePlayer(UUID.fromString(plugin.getSqlManager().getUUIDFromUID(uid).substring(1))); + if (player == null) { + sender.sendMessage("§cPlayer not found. UID=" + uid); + return; + } + int playtime = player.getStatistic(Statistic.PLAY_ONE_MINUTE); + playtimes.put(player, playtime); + for (int threshold : thresholds.keySet()) { + if (playtime >= threshold) { + thresholds.put(threshold, thresholds.get(threshold) + 1); + } + } + if (player.isOnline()) { + onlinern++; + } + } + for (Entry entry : thresholds.entrySet()) { + double val = (double) entry.getValue() / (double) playtimes.size() * 100; + String time = ""; + int key = entry.getKey(); + key /= 60 * 20; + if (key % 60 == 0) { + time = (key / 60) + "h"; + } else { + time = key + "m"; + } + sender.sendMessage(String.format("§7Above %s: §9%s §7(%d/%d)", time, Math.round(val) + "%", + entry.getValue(), playtimes.size())); + } + sender.sendMessage(String.format("§7Online now: §9%s §7(%d/%d)", + Math.round((double) onlinern / (double) playtimes.size() * 100) + "%", onlinern, playtimes.size())); + sender.sendMessage(String.format("§7(%sms)", "" + (System.currentTimeMillis() - start))); + } +} \ No newline at end of file