diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/afk/AFKTracker.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/afk/AFKTracker.java index 1a58cc11a..ea3f77486 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/afk/AFKTracker.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/afk/AFKTracker.java @@ -17,10 +17,14 @@ package com.djrapitops.plan.gathering.afk; import com.djrapitops.plan.gathering.cache.SessionCache; +import com.djrapitops.plan.gathering.domain.ActiveSession; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.TimeSettings; -import java.util.*; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; /** * Keeps track how long player has been afk during a session @@ -29,15 +33,15 @@ import java.util.*; */ public class AFKTracker { + public static final long IGNORES_AFK = -1L; + private final Set usedAFKCommand; - private final Map lastMovement; private final PlanConfig config; private Long afkThresholdMs; public AFKTracker(PlanConfig config) { this.config = config; usedAFKCommand = new HashSet<>(); - lastMovement = new HashMap<>(); } public long getAfkThreshold() { @@ -47,26 +51,41 @@ public class AFKTracker { return afkThresholdMs; } - public void hasIgnorePermission(UUID uuid) { - lastMovement.put(uuid, -1L); + public void hasIgnorePermission(UUID playerUUID) { + storeLastMovement(playerUUID, IGNORES_AFK); } - public void usedAfkCommand(UUID uuid, long time) { - Long lastMoved = lastMovement.getOrDefault(uuid, time); - if (lastMoved == -1) { + private void storeLastMovement(UUID playerUUID, long time) { + SessionCache.getCachedSession(playerUUID) + .ifPresent(activeSession -> activeSession.setLastMovementForAfkCalculation(time)); + } + + private long getLastMovement(UUID playerUUID, long time) { + return getLastMovement(playerUUID) + .orElse(time); + } + + private Optional getLastMovement(UUID playerUUID) { + return SessionCache.getCachedSession(playerUUID) + .map(ActiveSession::getLastMovementForAfkCalculation); + } + + public void usedAfkCommand(UUID playerUUID, long time) { + long lastMoved = getLastMovement(playerUUID, time); + if (lastMoved == IGNORES_AFK) { return; } - usedAFKCommand.add(uuid); - lastMovement.put(uuid, time - getAfkThreshold()); + usedAFKCommand.add(playerUUID); + storeLastMovement(playerUUID, time - getAfkThreshold()); } - public long performedAction(UUID uuid, long time) { - Long lastMoved = lastMovement.getOrDefault(uuid, time); + public long performedAction(UUID playerUUID, long time) { + long lastMoved = getLastMovement(playerUUID, time); // Ignore afk permission - if (lastMoved == -1) { + if (lastMoved == IGNORES_AFK) { return 0L; } - lastMovement.put(uuid, time); + storeLastMovement(playerUUID, time); try { if (time - lastMoved < getAfkThreshold()) { @@ -74,31 +93,30 @@ public class AFKTracker { return 0L; } - long removeAfkCommandEffect = usedAFKCommand.contains(uuid) ? getAfkThreshold() : 0; + long removeAfkCommandEffect = usedAFKCommand.contains(playerUUID) ? getAfkThreshold() : 0; long timeAFK = time - lastMoved - removeAfkCommandEffect; - SessionCache.getCachedSession(uuid) + SessionCache.getCachedSession(playerUUID) .ifPresent(session -> session.addAfkTime(timeAFK)); return timeAFK; } finally { - usedAFKCommand.remove(uuid); + usedAFKCommand.remove(playerUUID); } } public long loggedOut(UUID uuid, long time) { long timeAFK = performedAction(uuid, time); - lastMovement.remove(uuid); usedAFKCommand.remove(uuid); return timeAFK; } - public boolean isAfk(UUID uuid) { + public boolean isAfk(UUID playerUUID) { long time = System.currentTimeMillis(); - Long lastMoved = lastMovement.get(uuid); - if (lastMoved == null || lastMoved == -1) { + Optional lastMoved = getLastMovement(playerUUID); + if (!lastMoved.isPresent() || lastMoved.get() == IGNORES_AFK) { return false; } - return time - lastMoved > getAfkThreshold(); + return time - lastMoved.get() > getAfkThreshold(); } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/ActiveSession.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/ActiveSession.java index c45c3ec29..b94b54403 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/ActiveSession.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/ActiveSession.java @@ -32,6 +32,8 @@ public class ActiveSession { private final DataMap extraData; private long afkTime; + private long lastMovementForAfkCalculation; + public ActiveSession(UUID playerUUID, ServerUUID serverUUID, long start, String world, String gameMode) { this.playerUUID = playerUUID; this.serverUUID = serverUUID; @@ -43,6 +45,8 @@ public class ActiveSession { extraData.put(MobKillCounter.class, new MobKillCounter()); extraData.put(DeathCounter.class, new DeathCounter()); extraData.put(PlayerKills.class, new PlayerKills()); + + lastMovementForAfkCalculation = start; } public static ActiveSession fromPlayerJoin(PlayerJoin join) { @@ -147,5 +151,13 @@ public class ActiveSession { '}'; } + public long getLastMovementForAfkCalculation() { + return lastMovementForAfkCalculation; + } + + public void setLastMovementForAfkCalculation(long lastMovementForAfkCalculation) { + this.lastMovementForAfkCalculation = lastMovementForAfkCalculation; + } + public static class FirstSession {} } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/placeholder/PlayerPlaceHolders.java b/Plan/common/src/main/java/com/djrapitops/plan/placeholder/PlayerPlaceHolders.java index e9e1546ce..786436838 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/placeholder/PlayerPlaceHolders.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/placeholder/PlayerPlaceHolders.java @@ -16,6 +16,7 @@ */ package com.djrapitops.plan.placeholder; +import com.djrapitops.plan.delivery.domain.container.PlayerContainer; import com.djrapitops.plan.delivery.domain.keys.PlayerKeys; import com.djrapitops.plan.delivery.domain.mutators.PerServerMutator; import com.djrapitops.plan.delivery.domain.mutators.PingMutator; @@ -23,6 +24,9 @@ import com.djrapitops.plan.delivery.domain.mutators.PlayerVersusMutator; import com.djrapitops.plan.delivery.domain.mutators.SessionsMutator; import com.djrapitops.plan.delivery.formatting.Formatter; import com.djrapitops.plan.delivery.formatting.Formatters; +import com.djrapitops.plan.gathering.afk.AFKTracker; +import com.djrapitops.plan.gathering.cache.SessionCache; +import com.djrapitops.plan.gathering.domain.ActiveSession; import com.djrapitops.plan.gathering.domain.PlayerKill; import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.identification.ServerInfo; @@ -71,6 +75,9 @@ public class PlayerPlaceHolders implements Placeholders { Formatter year = formatters.yearLong(); Formatter time = formatters.timeAmount(); + placeholders.register("player_is_afk", this::isAfk); + placeholders.register("player_is_afk_badge", player -> isAfk(player) ? "AFK" : ""); + placeholders.register("player_banned", player -> player.getValue(PlayerKeys.BANNED) .orElse(Boolean.FALSE) @@ -159,10 +166,18 @@ public class PlayerPlaceHolders implements Placeholders { ).getGroup() ); - registerKillPlaceholders(placeholders, time); + registerKillPlaceholders(placeholders); } - private void registerKillPlaceholders(PlanPlaceholders placeholders, Formatter time) { + private boolean isAfk(PlayerContainer player) { + return SessionCache.getCachedSession(player.getUnsafe(PlayerKeys.UUID)) + .map(ActiveSession::getLastMovementForAfkCalculation) + .filter(lastMovement -> lastMovement != AFKTracker.IGNORES_AFK + && now() - lastMovement > config.get(TimeSettings.AFK_THRESHOLD)) + .isPresent(); + } + + private void registerKillPlaceholders(PlanPlaceholders placeholders) { placeholders.register("player_player_caused_deaths", player -> PlayerVersusMutator.forContainer(player).toPlayerDeathCount() );