From d7cc141b94902045c24a12b701085ee2fa167195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sat, 27 Sep 2025 07:42:13 +0200 Subject: [PATCH] added antiGrief inhabited chunk time calculation --- .../spawn/core/util/NumberUtil.java | 6 +++++ .../security/antiGrief/AntiGrief.java | 25 ++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/eu/mhsl/craftattack/spawn/core/util/NumberUtil.java b/core/src/main/java/eu/mhsl/craftattack/spawn/core/util/NumberUtil.java index 9e8cd8d..2df53c1 100644 --- a/core/src/main/java/eu/mhsl/craftattack/spawn/core/util/NumberUtil.java +++ b/core/src/main/java/eu/mhsl/craftattack/spawn/core/util/NumberUtil.java @@ -8,4 +8,10 @@ public class NumberUtil { return out; } + + public static > T clamp(T value, T min, T max) { + if (value.compareTo(min) < 0) return min; + if (value.compareTo(max) > 0) return max; + return value; + } } diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/security/antiGrief/AntiGrief.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/security/antiGrief/AntiGrief.java index b9aacf8..5865e06 100644 --- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/security/antiGrief/AntiGrief.java +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/security/antiGrief/AntiGrief.java @@ -2,6 +2,7 @@ package eu.mhsl.craftattack.spawn.craftattack.appliances.security.antiGrief; import eu.mhsl.craftattack.spawn.core.Main; import eu.mhsl.craftattack.spawn.core.appliance.Appliance; +import eu.mhsl.craftattack.spawn.core.util.NumberUtil; import eu.mhsl.craftattack.spawn.craftattack.appliances.security.antiGrief.listener.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; @@ -139,6 +140,11 @@ public class AntiGrief extends Appliance { /** Smoothing factor for EMA baseline. Lower = smoother, higher = more reactive. 0.0 < EMA_ALPHA <= 1.0 */ private static final double EMA_ALPHA = 0.2; + /** Minimal chunk inhabited time to start registering scores linearly to INHABITED_FULL_MS */ + private static final int INHABITED_MIN_MS = 60 * 60 * 1000; + /** Max time to reach 100% effect on the score */ + private static final int INHABITED_FULL_MS = 24 * 60 * 60 * 1000; + /** Stores direct incidents mapped by player UUID. */ private final Map> directGriefRegistry = new ConcurrentHashMap<>(); /** Stores passive incidents mapped by chunk key. */ @@ -176,15 +182,18 @@ public class AntiGrief extends Appliance { final double currentScore = state.currentScore(bucketIdx); if (currentScore <= 0.0) return; - final double base = (state.ema == 0.0) ? currentScore : state.ema; - final double newBase = EMA_ALPHA * currentScore + (1 - EMA_ALPHA) * base; + final double adjustedScore = adjustScoreToInhabitantTime(state, currentScore); + if (adjustedScore <= 0.0) return; + + final double base = (state.ema == 0.0) ? adjustedScore : state.ema; + final double newBase = EMA_ALPHA * adjustedScore + (1 - EMA_ALPHA) * base; state.ema = Math.max(3, newBase); - boolean spike = currentScore >= HARD_THRESHOLD || currentScore >= base * FACTOR_SPIKE; + final boolean spike = adjustedScore >= HARD_THRESHOLD || adjustedScore >= base * FACTOR_SPIKE; if (spike && (now - state.lastAlertAt) >= ALERT_COOLDOWN_MS) { state.lastAlertAt = now; Bukkit.getScheduler().runTask(Main.instance(), () -> - this.alertAdmins(areaKey, bucketIdx, currentScore, newBase) + this.alertAdmins(areaKey, bucketIdx, adjustedScore, newBase) ); } }); @@ -212,6 +221,14 @@ public class AntiGrief extends Appliance { }, Ticks.TICKS_PER_SECOND * 30, Ticks.TICKS_PER_SECOND * 30); } + private static double adjustScoreToInhabitantTime(AreaState state, double currentScore) { + final long inhabitedMs = state.getInhabitedTime() * Ticks.SINGLE_TICK_DURATION_MS / Ticks.TICKS_PER_SECOND; + + double factor = (double) (inhabitedMs - INHABITED_MIN_MS) / (double) (INHABITED_FULL_MS - INHABITED_MIN_MS); + factor = NumberUtil.clamp(factor, 0.0, 1.0); + return currentScore * factor; + } + private void alertAdmins(long areaKey, long bucketIdx, double curr, double baseline) { AreaState meta = this.areas.get(areaKey); if (meta == null) return;