diff --git a/pom.xml b/pom.xml
index 920fcf6..d837218 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
AuxProtect
AuxProtect
- 1.3
+ 1.3.1
AuxProtect
${project.artifactId}-${project.version}
@@ -160,20 +160,20 @@
org.spigotmc
spigot-api
- 1.20.4-R0.1-SNAPSHOT
+ 1.21-R0.1-SNAPSHOT
provided
net.md-5
bungeecord-api
- 1.20-R0.1-SNAPSHOT
+ 1.21-R0.1-SNAPSHOT
jar
provided
net.md-5
bungeecord-api
- 1.20-R0.1-SNAPSHOT
+ 1.21-R0.1-SNAPSHOT
javadoc
provided
diff --git a/src/main/java/dev/heliosares/auxprotect/core/Activity.java b/src/main/java/dev/heliosares/auxprotect/core/Activity.java
new file mode 100644
index 0000000..004080a
--- /dev/null
+++ b/src/main/java/dev/heliosares/auxprotect/core/Activity.java
@@ -0,0 +1,34 @@
+package dev.heliosares.auxprotect.core;
+
+public enum Activity {
+
+ IN_SPAWN('$', 100),
+ COMMAND('/', 5),
+ CHAT('c', 5),
+ DAMAGE('d', 0.25),
+ INTERACT_ENTITY('e', 1),
+ INTERACT_BLOCK('f', 1),
+ INTERACT_AIR('g', 1),
+ CLICK_ITEM('i', 1),
+ OPEN_INVENTORY('o', 1),
+ PICKUP('p', 1),
+ DROP('q', 1),
+ BLOCK_BREAK('r', 1),
+ BLOCK_PLACE('s', 1);
+
+
+ public final char character;
+ public final double score;
+
+ Activity(char character, double score) {
+ this.character = character;
+ this.score = score;
+ }
+
+ public static Activity getByChar(char c) {
+ for (Activity value : values()) {
+ if (value.character == c) return value;
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/dev/heliosares/auxprotect/core/ActivityRecord.java b/src/main/java/dev/heliosares/auxprotect/core/ActivityRecord.java
new file mode 100644
index 0000000..8502e00
--- /dev/null
+++ b/src/main/java/dev/heliosares/auxprotect/core/ActivityRecord.java
@@ -0,0 +1,85 @@
+package dev.heliosares.auxprotect.core;
+
+import net.md_5.bungee.api.ChatColor;
+
+import javax.annotation.Nonnull;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+public record ActivityRecord(@Nonnull List activities, double distanceMoved) {
+ @Override
+ public String toString() {
+ StringBuilder activityString = new StringBuilder(getActivityString());
+
+ activityString.append(";");
+ final double moved = distanceMoved();
+ if (moved > 1E-6) {
+ if (moved >= 10) {
+ activityString.append((int) Math.round(moved));
+ } else {
+ activityString.append(Math.round(moved * 10) / 10D);
+ }
+ }
+ return activityString.toString();
+ }
+
+ public String getActivityString() {
+ StringBuilder activityString = new StringBuilder();
+
+ for (Activity a : activities()) {
+ activityString.append(a.character);
+ }
+
+ return activityString.toString();
+ }
+
+ public double countScore() {
+ double score = Math.floor((distanceMoved()) / 10);
+
+ if (distanceMoved() > 1E-6) score++;
+
+ for (Activity activity : activities()) {
+ score += activity.score;
+ }
+
+ return score;
+ }
+
+ public static ActivityRecord parse(String data) throws IllegalArgumentException {
+ if (data == null) return null;
+
+ if (data.matches("\\d+")) {
+ throw new IllegalArgumentException("Legacy activity");
+ }
+ if (!data.matches("[^;]*;(\\d+(\\.\\d)?)?")) {
+ throw new IllegalArgumentException("Invalid activity string");
+ }
+ List activities = new ArrayList<>();
+ if (data.startsWith(";")) data = " " + data;
+ if (data.endsWith(";")) data += " ";
+ String[] parts = data.split(";");
+
+ if (parts.length != 2) {
+ throw new IllegalArgumentException("Invalid activity string format");
+ }
+
+ for (char c : parts[0].trim().toCharArray()) {
+ activities.add(Activity.getByChar(c));
+ }
+
+ double distance = parts[1].isBlank() ? 0 : Double.parseDouble(parts[1].trim());
+
+ return new ActivityRecord(activities, distance);
+ }
+
+ public String getHoverText() {
+ StringBuilder hoverText = new StringBuilder("\n\n");
+ hoverText.append(ChatColor.COLOR_CHAR + "7Activity: " + ChatColor.COLOR_CHAR + "9").append(getActivityString()).append("\n");
+ for (Activity activity : new HashSet<>(activities())) {
+ hoverText.append(ChatColor.COLOR_CHAR + "7 ").append(activity.character).append(" = ").append(activity.toString().toLowerCase()).append(" (").append(activity.score).append(")\n");
+ }
+ hoverText.append(ChatColor.COLOR_CHAR + "7Moved " + ChatColor.COLOR_CHAR + "9").append(distanceMoved()).append(ChatColor.COLOR_CHAR).append("7 Blocks");
+ return hoverText.toString();
+ }
+}
diff --git a/src/main/java/dev/heliosares/auxprotect/database/Results.java b/src/main/java/dev/heliosares/auxprotect/database/Results.java
index 3fde922..39b153f 100644
--- a/src/main/java/dev/heliosares/auxprotect/database/Results.java
+++ b/src/main/java/dev/heliosares/auxprotect/database/Results.java
@@ -1,9 +1,9 @@
package dev.heliosares.auxprotect.database;
import dev.heliosares.auxprotect.adapters.sender.SenderAdapter;
-import dev.heliosares.auxprotect.api.AuxProtectAPI;
import dev.heliosares.auxprotect.core.APPermission;
import dev.heliosares.auxprotect.core.APPlayer;
+import dev.heliosares.auxprotect.core.ActivityRecord;
import dev.heliosares.auxprotect.core.IAuxProtect;
import dev.heliosares.auxprotect.core.Language;
import dev.heliosares.auxprotect.core.Parameters;
@@ -24,6 +24,9 @@ import org.bukkit.inventory.ItemStack;
import java.io.IOException;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Random;
@@ -185,14 +188,32 @@ public class Results {
}
String data = entry.getData();
if (data != null && !data.isEmpty()) {
+ HoverEvent hoverEvent = clickToCopy;
+ if (entry.getAction().equals(EntryAction.ACTIVITY)) {
+ try {
+ ActivityRecord record = ActivityRecord.parse(data);
+ if (record != null) {
+ message.append(" " + org.bukkit.ChatColor.COLOR_CHAR + "a" + record.countScore());
+ hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.L.RESULTS__CLICK_TO_COPY.translate() + record.getHoverText()));
+ }
+ } catch (IllegalArgumentException ignored) {
+ }
+ }
if (entry.getAction().equals(EntryAction.SESSION) && !APPermission.LOOKUP_ACTION.dot(EntryAction.SESSION.toString().toLowerCase()).dot("ip").hasPermission(player)) {
message.append(" " + ChatColor.COLOR_CHAR + "8[" + ChatColor.COLOR_CHAR + "7" + Language.L.RESULTS__REDACTED.translate() + ChatColor.COLOR_CHAR + "8]");
message.event((ClickEvent) null).event((HoverEvent) null);
} else {
message.append(" " + ChatColor.COLOR_CHAR + "8[" + ChatColor.COLOR_CHAR + "7" + data + ChatColor.COLOR_CHAR + "8]");
- message.event(clickToCopy).event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, data));
+ message.event(hoverEvent).event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, data));
}
}
+ if (entry.getAction().equals(EntryAction.ACTIVITY)) {
+ message.append(" " + ChatColor.COLOR_CHAR + "8[" + ChatColor.COLOR_CHAR + "7Copy Minute Range" + ChatColor.COLOR_CHAR + "8]");
+ ZonedDateTime zonedDateTime = Instant.ofEpochMilli(entry.getTime()).atZone(ZoneId.systemDefault());
+ ZonedDateTime start = zonedDateTime.withSecond(0).withNano(0);
+ ZonedDateTime end = start.plusMinutes(1).minusNanos(1000000);
+ message.event(clickToCopy).event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, start.toInstant().toEpochMilli() + "e-" + end.toInstant().toEpochMilli() + "e"));
+ }
}
}
if (entry.getWorld() != null && !entry.getWorld().equals("$null") && coords) {
diff --git a/src/main/java/dev/heliosares/auxprotect/spigot/APPlayerSpigot.java b/src/main/java/dev/heliosares/auxprotect/spigot/APPlayerSpigot.java
index 33ca003..f9447fc 100644
--- a/src/main/java/dev/heliosares/auxprotect/spigot/APPlayerSpigot.java
+++ b/src/main/java/dev/heliosares/auxprotect/spigot/APPlayerSpigot.java
@@ -1,6 +1,8 @@
package dev.heliosares.auxprotect.spigot;
import dev.heliosares.auxprotect.core.APPlayer;
+import dev.heliosares.auxprotect.core.Activity;
+import dev.heliosares.auxprotect.core.ActivityRecord;
import dev.heliosares.auxprotect.core.IAuxProtect;
import dev.heliosares.auxprotect.database.DbEntry;
import dev.heliosares.auxprotect.database.EntryAction;
@@ -13,11 +15,12 @@ import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
public class APPlayerSpigot extends APPlayer {
- public final double[] activity = new double[30];
+ private final List activityStack = new ArrayList<>();
+ private ArrayList currentActivity;
private final Player player;
private final List posBlob = new ArrayList<>();
public long lastLoggedMoney;
@@ -25,12 +28,10 @@ public class APPlayerSpigot extends APPlayer {
public long lastLoggedInventoryDiff;
public long lastLoggedPos;
public long lastMoved;
- public long lastLoggedActivity;
public Location lastLocation;
public long lastCheckedMovement;
- public double movedAmountThisMinute;
+ private double movedAmountThisMinute;
public boolean hasMovedThisMinute;
- public int activityIndex;
public long lastNotifyInactive;
// hotbar, main, armor, offhand, echest
private List invDiffItems;
@@ -41,7 +42,6 @@ public class APPlayerSpigot extends APPlayer {
super(plugin, player);
this.player = player;
- Arrays.fill(activity, -1);
}
@Override
@@ -49,8 +49,45 @@ public class APPlayerSpigot extends APPlayer {
return player.getName();
}
- public void addActivity(double d) {
- activity[activityIndex] += d;
+ public void addActivity(Activity a) {
+ synchronized (activityStack) {
+ if (currentActivity == null) currentActivity = new ArrayList<>();
+ currentActivity.add(a);
+ }
+ }
+
+ public String concludeActivityForMinute() {
+ synchronized (activityStack) {
+ while (activityStack.size() >= 30) {
+ activityStack.remove(0);
+ }
+ ActivityRecord record = null;
+ if (currentActivity != null || movedAmountThisMinute > 1E-6) {
+ if (currentActivity == null) currentActivity = new ArrayList<>();
+ record = new ActivityRecord(currentActivity, movedAmountThisMinute);
+ }
+ activityStack.add(record);
+ currentActivity = null;
+ movedAmountThisMinute = 0;
+ hasMovedThisMinute = false;
+
+ if (record == null) return null;
+ return record.toString();
+ }
+ }
+
+ public void move() {
+ synchronized (activityStack) {
+ if (lastLocation != null && Objects.equals(lastLocation.getWorld(), getPlayer().getWorld())) {
+ movedAmountThisMinute += Math.min(lastLocation.distance(getPlayer().getLocation()), 10);
+ }
+ lastLocation = getPlayer().getLocation();
+ lastCheckedMovement = System.currentTimeMillis();
+ }
+ }
+
+ public List getActivityStack() {
+ return activityStack;
}
public long logInventory(String reason) {
diff --git a/src/main/java/dev/heliosares/auxprotect/spigot/AuxProtectSpigot.java b/src/main/java/dev/heliosares/auxprotect/spigot/AuxProtectSpigot.java
index 4c57c8c..0a972a2 100644
--- a/src/main/java/dev/heliosares/auxprotect/spigot/AuxProtectSpigot.java
+++ b/src/main/java/dev/heliosares/auxprotect/spigot/AuxProtectSpigot.java
@@ -6,6 +6,8 @@ import dev.heliosares.auxprotect.adapters.sender.SpigotSenderAdapter;
import dev.heliosares.auxprotect.api.AuxProtectAPI;
import dev.heliosares.auxprotect.core.APConfig;
import dev.heliosares.auxprotect.core.APPermission;
+import dev.heliosares.auxprotect.core.Activity;
+import dev.heliosares.auxprotect.core.ActivityRecord;
import dev.heliosares.auxprotect.core.IAuxProtect;
import dev.heliosares.auxprotect.core.Language;
import dev.heliosares.auxprotect.core.PlatformType;
@@ -64,6 +66,7 @@ import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
+import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -358,6 +361,7 @@ public final class AuxProtectSpigot extends JavaPlugin implements IAuxProtect {
new BukkitRunnable() {
private boolean running;
+ private int lastLoggedActivityMinute = -1;
@Override
public void run() {
@@ -371,6 +375,15 @@ public final class AuxProtectSpigot extends JavaPlugin implements IAuxProtect {
synchronized (apPlayers) {
players = new ArrayList<>(apPlayers.values());
}
+ Calendar calendar = Calendar.getInstance();
+ int minute = calendar.get(Calendar.MINUTE);
+ int second = calendar.get(Calendar.SECOND);
+
+ boolean logActivity = lastLoggedActivityMinute != minute && second >= 30;
+ // Put in the middle of the minute to make parsing it later easier
+ if (logActivity) {
+ lastLoggedActivityMinute = minute;
+ }
for (APPlayerSpigot apPlayer : players) {
if (!apPlayer.getPlayer().isOnline()) {
continue;
@@ -403,43 +416,25 @@ public final class AuxProtectSpigot extends JavaPlugin implements IAuxProtect {
}
if (System.currentTimeMillis() - apPlayer.lastCheckedMovement >= 1000) {
- if (apPlayer.lastLocation != null
- && Objects.equals(apPlayer.lastLocation.getWorld(), apPlayer.getPlayer().getWorld())) {
- apPlayer.movedAmountThisMinute += Math
- .min(apPlayer.lastLocation.distance(apPlayer.getPlayer().getLocation()), 10);
- }
- apPlayer.lastLocation = apPlayer.getPlayer().getLocation();
apPlayer.lastCheckedMovement = System.currentTimeMillis();
+ apPlayer.move();
}
- if (apPlayer.lastLoggedActivity == 0) {
- apPlayer.lastLoggedActivity = System.currentTimeMillis();
- }
- if (System.currentTimeMillis() - apPlayer.lastLoggedActivity > 60000L && config.isPrivate()) {
+ if (logActivity && config.isPrivate()) {
if (apPlayer.getPlayer().getWorld().getName().equals("flat") && config.isPrivate()) {
- apPlayer.activity[apPlayer.activityIndex] += 100;
- }
- apPlayer.addActivity(Math.floor((apPlayer.movedAmountThisMinute + 7) / 10));
- apPlayer.movedAmountThisMinute = 0;
-
- if (apPlayer.hasMovedThisMinute) {
- apPlayer.addActivity(1);
- apPlayer.hasMovedThisMinute = false;
+ apPlayer.addActivity(Activity.IN_SPAWN);
}
- add(new DbEntry(AuxProtectSpigot.getLabel(apPlayer.getPlayer()), EntryAction.ACTIVITY, false,
- apPlayer.getPlayer().getLocation(), "",
- (int) Math.round(apPlayer.activity[apPlayer.activityIndex]) + ""));
- apPlayer.lastLoggedActivity = System.currentTimeMillis();
+ add(new DbEntry(AuxProtectSpigot.getLabel(apPlayer.getPlayer()), EntryAction.ACTIVITY, false, apPlayer.getPlayer().getLocation(), "", apPlayer.concludeActivityForMinute()));
int tallied = 0;
int inactive = 0;
- for (double activity : apPlayer.activity) {
- if (activity < 0) {
+ for (ActivityRecord record : apPlayer.getActivityStack()) {
+ if (record == null || record.activities().isEmpty()) {
continue;
}
tallied++;
- if (activity < 10) {
+ if (record.countScore() < 10) {
inactive++;
}
}
@@ -459,12 +454,6 @@ public final class AuxProtectSpigot extends JavaPlugin implements IAuxProtect {
apPlayer.getPlayer().getLocation(), "inactive", inactive + "/" + tallied));
}
}
-
- apPlayer.activityIndex++;
- if (apPlayer.activityIndex >= apPlayer.activity.length) {
- apPlayer.activityIndex = 0;
- }
- apPlayer.activity[apPlayer.activityIndex] = 0;
}
}
} finally {
diff --git a/src/main/java/dev/heliosares/auxprotect/spigot/listeners/EntityListener.java b/src/main/java/dev/heliosares/auxprotect/spigot/listeners/EntityListener.java
index ecbb01f..663ee97 100644
--- a/src/main/java/dev/heliosares/auxprotect/spigot/listeners/EntityListener.java
+++ b/src/main/java/dev/heliosares/auxprotect/spigot/listeners/EntityListener.java
@@ -1,6 +1,7 @@
package dev.heliosares.auxprotect.spigot.listeners;
import dev.heliosares.auxprotect.core.APPermission;
+import dev.heliosares.auxprotect.core.Activity;
import dev.heliosares.auxprotect.core.IAuxProtect;
import dev.heliosares.auxprotect.database.DbEntry;
import dev.heliosares.auxprotect.database.EntryAction;
@@ -26,8 +27,10 @@ import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
+import org.bukkit.event.entity.EntityDismountEvent;
import org.bukkit.event.entity.EntityDropItemEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
+import org.bukkit.event.entity.EntityMountEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.EntityResurrectEvent;
import org.bukkit.event.entity.EntityTameEvent;
@@ -41,8 +44,6 @@ import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.map.MapRenderer;
import org.bukkit.projectiles.ProjectileSource;
import org.bukkit.scheduler.BukkitRunnable;
-import org.spigotmc.event.entity.EntityDismountEvent;
-import org.spigotmc.event.entity.EntityMountEvent;
import java.util.ArrayList;
@@ -147,7 +148,7 @@ public class EntityListener implements Listener {
if (e.getCause() == DamageCause.THORNS) {
itemname += "THORNS";
} else if (source instanceof Player sourcePl) {
- plugin.getAPPlayer(sourcePl).addActivity(0.25);
+ plugin.getAPPlayer(sourcePl).addActivity(Activity.DAMAGE);
itemname += sourcePl.getInventory().getItemInMainHand().getType().toString().toLowerCase();
}
@@ -252,7 +253,7 @@ public class EntityListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerDropEvent(PlayerDropItemEvent e) {
- plugin.getAPPlayer(e.getPlayer()).addActivity(1);
+ plugin.getAPPlayer(e.getPlayer()).addActivity(Activity.DROP);
if (isChartMap(e.getItemDrop().getItemStack())) {
e.getItemDrop().remove();
@@ -266,7 +267,7 @@ public class EntityListener implements Listener {
public void onPickupEvent(EntityPickupItemEvent e) {
if (e.getEntity() instanceof Player player) {
- plugin.getAPPlayer(player).addActivity(1);
+ plugin.getAPPlayer(player).addActivity(Activity.PICKUP);
if (isChartMap(e.getItem().getItemStack()) && !APPermission.LOOKUP_MONEY.hasPermission(player)) {
e.setCancelled(true);
diff --git a/src/main/java/dev/heliosares/auxprotect/spigot/listeners/InventoryListener.java b/src/main/java/dev/heliosares/auxprotect/spigot/listeners/InventoryListener.java
index 1d45f32..ee4a8b4 100644
--- a/src/main/java/dev/heliosares/auxprotect/spigot/listeners/InventoryListener.java
+++ b/src/main/java/dev/heliosares/auxprotect/spigot/listeners/InventoryListener.java
@@ -1,6 +1,7 @@
package dev.heliosares.auxprotect.spigot.listeners;
import dev.heliosares.auxprotect.api.AuxProtectAPI;
+import dev.heliosares.auxprotect.core.Activity;
import dev.heliosares.auxprotect.database.DbEntry;
import dev.heliosares.auxprotect.database.EntryAction;
import dev.heliosares.auxprotect.database.SingleItemEntry;
@@ -10,6 +11,7 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@@ -35,6 +37,7 @@ public class InventoryListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryOpenEvent(InventoryOpenEvent e) {
+ plugin.getAPPlayer((Player) e.getPlayer()).addActivity(Activity.OPEN_INVENTORY);
log(e.getPlayer(), e.getInventory(), true);
}
@@ -79,11 +82,12 @@ public class InventoryListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent e) {
+ plugin.getAPPlayer((Player) e.getWhoClicked()).addActivity(Activity.CLICK_ITEM);
+
InventoryType type = e.getWhoClicked().getOpenInventory().getTopInventory().getType();
if (e.getSlotType() != InventoryType.SlotType.RESULT) return;
if (e.getCurrentItem() == null || e.getCurrentItem().getType() == Material.AIR) return;
-
EntryAction action;
String data = "";
ItemStack[] entryItems;
diff --git a/src/main/java/dev/heliosares/auxprotect/spigot/listeners/PlayerListener.java b/src/main/java/dev/heliosares/auxprotect/spigot/listeners/PlayerListener.java
index 6cb2507..86f583a 100644
--- a/src/main/java/dev/heliosares/auxprotect/spigot/listeners/PlayerListener.java
+++ b/src/main/java/dev/heliosares/auxprotect/spigot/listeners/PlayerListener.java
@@ -2,6 +2,7 @@ package dev.heliosares.auxprotect.spigot.listeners;
import dev.heliosares.auxprotect.adapters.sender.SpigotSenderAdapter;
import dev.heliosares.auxprotect.core.APPermission;
+import dev.heliosares.auxprotect.core.Activity;
import dev.heliosares.auxprotect.core.Language;
import dev.heliosares.auxprotect.database.DbEntry;
import dev.heliosares.auxprotect.database.EntryAction;
@@ -27,6 +28,8 @@ 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.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityPlaceEvent;
import org.bukkit.event.entity.EntityToggleGlideEvent;
import org.bukkit.event.entity.PlayerLeashEntityEvent;
@@ -115,7 +118,7 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerInteractEntityEvent(PlayerInteractEntityEvent e) {
- plugin.getAPPlayer(e.getPlayer()).addActivity(1);
+ plugin.getAPPlayer(e.getPlayer()).addActivity(Activity.INTERACT_ENTITY);
ItemStack item = e.getPlayer().getInventory().getItem(e.getHand());
@@ -156,7 +159,7 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerInteractEvent(PlayerInteractEvent e) {
- plugin.getAPPlayer(e.getPlayer()).addActivity(1);
+ plugin.getAPPlayer(e.getPlayer()).addActivity(e.getClickedBlock() == null ? Activity.INTERACT_AIR : Activity.INTERACT_BLOCK);
if (e.useInteractedBlock() == Result.DENY) {
return;
@@ -351,7 +354,7 @@ public class PlayerListener implements Listener {
return;
}
- boolean tether = entity.getLeashHolder().getType() == EntityType.LEASH_HITCH;
+ boolean tether = entity.getLeashHolder().getType().toString().startsWith("LEASH_");
DbEntry entry = new DbEntry(AuxProtectSpigot.getLabel(e.getPlayer()), EntryAction.LEASH, false,
e.getEntity().getLocation(), AuxProtectSpigot.getLabel(e.getEntity()), tether ? "was tethered" : "");
@@ -366,7 +369,7 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onCommand(PlayerCommandPreprocessEvent e) {
- plugin.getAPPlayer(e.getPlayer()).addActivity(5);
+ plugin.getAPPlayer(e.getPlayer()).addActivity(Activity.COMMAND);
plugin.add(new DbEntry(AuxProtectSpigot.getLabel(e.getPlayer()), EntryAction.COMMAND, false,
e.getPlayer().getLocation(), e.getMessage(), ""));
@@ -374,11 +377,21 @@ public class PlayerListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void onChat(AsyncPlayerChatEvent e) {
- plugin.getAPPlayer(e.getPlayer()).addActivity(5);
+ plugin.getAPPlayer(e.getPlayer()).addActivity(Activity.CHAT);
plugin.add(new DbEntry(AuxProtectSpigot.getLabel(e.getPlayer()), EntryAction.CHAT, false, e.getPlayer().getLocation(), e.getMessage().trim(), ""));
if (plugin.getAPConfig().isDemoMode()) {
e.getPlayer().sendMessage(ChatColor.COLOR_CHAR + "cChat is disabled.");
e.setCancelled(true);
}
}
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onBlockPlace(BlockPlaceEvent e) {
+ plugin.getAPPlayer(e.getPlayer()).addActivity(Activity.BLOCK_PLACE);
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onBlockBreak(BlockBreakEvent e) {
+ plugin.getAPPlayer(e.getPlayer()).addActivity(Activity.BLOCK_BREAK);
+ }
}
diff --git a/src/main/java/dev/heliosares/auxprotect/spigot/listeners/ProjectileListener.java b/src/main/java/dev/heliosares/auxprotect/spigot/listeners/ProjectileListener.java
index 05db829..8ff5253 100644
--- a/src/main/java/dev/heliosares/auxprotect/spigot/listeners/ProjectileListener.java
+++ b/src/main/java/dev/heliosares/auxprotect/spigot/listeners/ProjectileListener.java
@@ -29,11 +29,14 @@ public class ProjectileListener implements Listener {
this.whitelist = new ArrayList<>();
whitelist.add(EntityType.ENDER_PEARL);
whitelist.add(EntityType.TRIDENT);
- whitelist.add(EntityType.FISHING_HOOK);
whitelist.add(EntityType.SNOWBALL);
whitelist.add(EntityType.EGG);
- whitelist.add(EntityType.SPLASH_POTION);
whitelist.add(EntityType.ARROW);
+ for (EntityType type : EntityType.values()) {
+ if (type.toString().contains("POTION") || type.toString().contains("FISHING_")) {
+ whitelist.add(type);
+ }
+ }
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
diff --git a/src/main/java/dev/heliosares/auxprotect/utils/ActivitySolver.java b/src/main/java/dev/heliosares/auxprotect/utils/ActivitySolver.java
index 183fea0..0945b6e 100644
--- a/src/main/java/dev/heliosares/auxprotect/utils/ActivitySolver.java
+++ b/src/main/java/dev/heliosares/auxprotect/utils/ActivitySolver.java
@@ -1,5 +1,6 @@
package dev.heliosares.auxprotect.utils;
+import dev.heliosares.auxprotect.core.ActivityRecord;
import dev.heliosares.auxprotect.database.DbEntry;
import dev.heliosares.auxprotect.database.EntryAction;
import dev.heliosares.auxprotect.spigot.AuxProtectSpigot;
@@ -23,6 +24,8 @@ import java.util.List;
public class ActivitySolver {
public static BaseComponent[][] solveActivity(List entries, long rangeStart, long rangeEnd) {
+ if (entries.isEmpty()) return null;
+
ComponentBuilder message = new ComponentBuilder().append("", FormatRetention.NONE);
LocalDateTime startTime = Instant.ofEpochMilli(rangeStart).atZone(ZoneId.systemDefault()).toLocalDateTime()
.withSecond(0).withNano(0);
@@ -30,7 +33,7 @@ public class ActivitySolver {
DateTimeFormatter formatterHour = DateTimeFormatter.ofPattern("Ka");
final long startMillis = startTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
final int minutes = (int) Math.ceil((rangeEnd - rangeStart) / 1000.0 / 60.0);
- int[] counter = new int[minutes];
+ double[] counter = new double[minutes];
Location[] locations = new Location[minutes];
Arrays.fill(counter, -1);
StringBuilder line = new StringBuilder("" + ChatColor.COLOR_CHAR + "7" + ChatColor.COLOR_CHAR + "m");
@@ -41,6 +44,9 @@ public class ActivitySolver {
components.add(message.create());
message = new ComponentBuilder();
+ ActivityRecord[] activityRecords = new ActivityRecord[minutes];
+ long[] times = new long[minutes];
+
long lastTime = startMillis;
for (int i = entries.size() - 1, minute = 0; i >= 0; i--) {
DbEntry entry = entries.get(i);
@@ -70,9 +76,23 @@ public class ActivitySolver {
counter[minute] = 0;
}
- int activity = Integer.parseInt(entry.getData());
+
+ double activity = 0;
+ try {
+ ActivityRecord record = ActivityRecord.parse(entry.getData());
+ activityRecords[minute] = record;
+ if (record != null) {
+ activity = record.countScore();
+ }
+ } catch (IllegalArgumentException e) {
+ try {
+ activity = Integer.parseInt(entry.getData());
+ } catch (IllegalArgumentException ignored) {
+ }
+ }
counter[minute] += activity;
locations[minute] = new Location(Bukkit.getWorld(entry.getWorld()), entry.getX(), entry.getY(), entry.getZ());
+ times[minute] = entry.getTime();
lastTime = entry.getTime();
minute++;
@@ -103,7 +123,7 @@ public class ActivitySolver {
message.color(ChatColor.BLACK);
} else {
- int activity = counter[i];
+ double activity = counter[i];
String hovertext = ChatColor.COLOR_CHAR + "9" + time.format(formatterDateTime) + "\n";
@@ -116,14 +136,19 @@ public class ActivitySolver {
}
ClickEvent clickevent = null;
if (locations[i] != null) {
- hovertext += String.format("\n\n" + ChatColor.COLOR_CHAR + "7(x%d/y%d/z%d/%s)\n" + ChatColor.COLOR_CHAR + "7Click to teleport", locations[i].getBlockX(),
+ hovertext += String.format("\n\n" + ChatColor.COLOR_CHAR + "7(x%d/y%d/z%d/%s)\n", locations[i].getBlockX(),
locations[i].getBlockY(), locations[i].getBlockZ(), locations[i].getWorld().getName());
- clickevent = new ClickEvent(ClickEvent.Action.RUN_COMMAND,
- String.format("/auxprotect tp %d %d %d %s", locations[i].getBlockX(),
- locations[i].getBlockY(), locations[i].getBlockZ(),
- locations[i].getWorld().getName()));
}
+ ActivityRecord activityRecord = activityRecords[i];
+ if (activityRecord != null) {
+ hovertext += activityRecord.getHoverText();
+ }
+
+ hovertext += "\n\n";
+ hovertext += ChatColor.COLOR_CHAR + "9Click to view";
+ clickevent = new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/auxprotect lookup a:activity t:" + times[i] + "e");
+
message.append(AuxProtectSpigot.BLOCK + "")
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(hovertext))).event(clickevent);
if (activity >= 20) {
diff --git a/src/main/test/dev/heliosares/auxprotect/core/ActivityTest.java b/src/main/test/dev/heliosares/auxprotect/core/ActivityTest.java
new file mode 100644
index 0000000..34b1879
--- /dev/null
+++ b/src/main/test/dev/heliosares/auxprotect/core/ActivityTest.java
@@ -0,0 +1,56 @@
+package dev.heliosares.auxprotect.core;
+
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class ActivityTest {
+ @Test
+ public void checkNoDuplicateCharacters() {
+ Set chars = new HashSet<>();
+ for (Activity activity : Activity.values()) {
+ if (!chars.add(activity.character)) {
+ throw new IllegalArgumentException("Duplicate characters " + activity.character);
+ }
+ }
+ }
+
+ @Test
+ public void testActivityParsing() {
+ ActivityRecord record = new ActivityRecord(List.of(Activity.values()), 0.69);
+ String data = record.toString();
+ System.out.println(data);
+
+ ActivityRecord parsed = ActivityRecord.parse(data);
+ String dataParsed = parsed.toString();
+
+ assertEquals(data, dataParsed);
+
+ assertEquals(record.distanceMoved(), parsed.distanceMoved(), 0.1);
+
+ assertEquals(record.activities(), parsed.activities());
+
+ assertNotNull(ActivityRecord.parse(";"));
+ assertNotNull(ActivityRecord.parse(";0"));
+ assertNotNull(ActivityRecord.parse(";0.0"));
+ assertNotNull(ActivityRecord.parse("/;0.0"));
+ assertNotNull(ActivityRecord.parse("/;0"));
+ assertNotNull(ActivityRecord.parse("/;"));
+ assertNotNull(ActivityRecord.parse("///;"));
+ }
+
+ @Test
+ public void testActivityScoring() {
+ ActivityRecord record = new ActivityRecord(List.of(Activity.values()), 0);
+ double totalScore = 0;
+ for (Activity activity : Activity.values()) {
+ totalScore += activity.score;
+ }
+ assertEquals(totalScore, record.countScore(), 1E-6);
+ }
+}