antigrief false positives tweaks
This commit is contained in:
@@ -19,6 +19,7 @@ class KickCommand extends ApplianceCommand<Kick> {
|
||||
|
||||
@Override
|
||||
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception {
|
||||
if(args.length < 1) throw new Error("Es muss ein Spielername angegeben werden!");
|
||||
this.getAppliance().kick(
|
||||
args[0],
|
||||
Arrays.stream(args).skip(1).collect(Collectors.joining(" "))
|
||||
|
@@ -96,6 +96,11 @@ public class AntiGrief extends Appliance {
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
long getInhabitedTime() {
|
||||
return Objects.requireNonNull(Bukkit.getWorld(this.worldId))
|
||||
.getChunkAt(this.chunkX, this.chunkX).getInhabitedTime();
|
||||
}
|
||||
|
||||
void addIncident(GriefIncident incident) {
|
||||
long b = incident.timestamp / BUCKET_DURATION_MS;
|
||||
this.scores.merge(b, (double) incident.severity.weight, Double::sum);
|
||||
@@ -126,13 +131,13 @@ public class AntiGrief extends Appliance {
|
||||
/** Maximum retention time for individual incidents in milliseconds. */
|
||||
private static final long INCIDENT_RETAIN_MS = 60 * 60 * 1000;
|
||||
/** Spike factor against EMA baseline. Triggers if current score >= baseline * FACTOR_SPIKE. */
|
||||
private static final double FACTOR_SPIKE = 3.0;
|
||||
private static final double FACTOR_SPIKE = 5.0;
|
||||
/** Absolute threshold for spike detection. Triggers if current score exceeds this value. */
|
||||
private static final double HARD_THRESHOLD = 20.0;
|
||||
private static final double HARD_THRESHOLD = 50.0;
|
||||
/** Cooldown time in ms to suppress repeated alerts for the same area. */
|
||||
private static final long ALERT_COOLDOWN_MS = 2 * 60 * 1000;
|
||||
/** Smoothing factor for EMA baseline. Lower = smoother, higher = more reactive. 0.0 < EMA_ALPHA <= 1.0 */
|
||||
private static final double EMA_ALPHA = 0.3;
|
||||
private static final double EMA_ALPHA = 0.2;
|
||||
|
||||
/** Stores direct incidents mapped by player UUID. */
|
||||
private final Map<UUID, Set<GriefIncident>> directGriefRegistry = new ConcurrentHashMap<>();
|
||||
@@ -159,8 +164,6 @@ public class AntiGrief extends Appliance {
|
||||
this.areas
|
||||
.computeIfAbsent(areaKey, key -> new AreaState(incident.worldId, chunk.getX(), chunk.getZ()))
|
||||
.addIncident(incident);
|
||||
|
||||
Bukkit.broadcast(text(String.format("%d, %d: %s - %s: {%s}", chunk.getX(), chunk.getZ(), incident.severity, incident.event, incident.data)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -169,17 +172,17 @@ public class AntiGrief extends Appliance {
|
||||
final long now = System.currentTimeMillis();
|
||||
final long bucketIdx = this.bucketIdx(now);
|
||||
|
||||
this.areas.forEach((areaKey, st) -> {
|
||||
final double currentScore = st.currentScore(bucketIdx);
|
||||
this.areas.forEach((areaKey, state) -> {
|
||||
final double currentScore = state.currentScore(bucketIdx);
|
||||
if (currentScore <= 0.0) return;
|
||||
|
||||
final double base = (st.ema == 0.0) ? currentScore : st.ema;
|
||||
final double base = (state.ema == 0.0) ? currentScore : state.ema;
|
||||
final double newBase = EMA_ALPHA * currentScore + (1 - EMA_ALPHA) * base;
|
||||
st.ema = newBase;
|
||||
state.ema = Math.max(3, newBase);
|
||||
|
||||
boolean spike = currentScore >= HARD_THRESHOLD || currentScore >= base * FACTOR_SPIKE;
|
||||
if (spike && (now - st.lastAlertAt) >= ALERT_COOLDOWN_MS) {
|
||||
st.lastAlertAt = now;
|
||||
if (spike && (now - state.lastAlertAt) >= ALERT_COOLDOWN_MS) {
|
||||
state.lastAlertAt = now;
|
||||
Bukkit.getScheduler().runTask(Main.instance(), () ->
|
||||
this.alertAdmins(areaKey, bucketIdx, currentScore, newBase)
|
||||
);
|
||||
|
@@ -4,6 +4,7 @@ import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener;
|
||||
import eu.mhsl.craftattack.spawn.craftattack.appliances.security.antiGrief.AntiGrief;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.PistonMoveReaction;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.*;
|
||||
|
||||
@@ -57,6 +58,17 @@ public class FireRelatedGriefListener extends ApplianceListener<AntiGrief> {
|
||||
|
||||
@EventHandler
|
||||
public void blockBurned(BlockBurnEvent event) {
|
||||
if(event.getBlock().isReplaceable()) return;
|
||||
if(event.getBlock().isPassable()) return;
|
||||
if(event.getBlock().getPistonMoveReaction().equals(PistonMoveReaction.BREAK)) return;
|
||||
if(event.getBlock().getType().name().endsWith("_LEAVES")) return;
|
||||
if(event.getBlock().getType().name().endsWith("_LOG")) return;
|
||||
List<Material> allowed = List.of(
|
||||
Material.MOSS_BLOCK,
|
||||
Material.MOSS_CARPET
|
||||
);
|
||||
if(allowed.contains(event.getBlock().getType())) return;
|
||||
|
||||
this.getAppliance().trackPassive(
|
||||
event.getBlock().getChunk(),
|
||||
new AntiGrief.GriefIncident(
|
||||
|
@@ -10,12 +10,14 @@ import org.bukkit.event.block.BlockFromToEvent;
|
||||
import org.bukkit.event.player.PlayerBucketEmptyEvent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class LiquidRelatedGriefListener extends ApplianceListener<AntiGrief> {
|
||||
@EventHandler
|
||||
public void liquidFlow(BlockFromToEvent event) {
|
||||
if(event.getToBlock().isEmpty()) return;
|
||||
if(event.getToBlock().isSolid()) return;
|
||||
if(ThreadLocalRandom.current().nextDouble() < 0.95) return;
|
||||
|
||||
this.getAppliance().trackPassive(
|
||||
event.getToBlock().getChunk(),
|
||||
|
Reference in New Issue
Block a user