/* * Decompiled with CFR 0.152. * * Could not load the following classes: * org.bukkit.entity.Player */ package de.maxhenkel.voicechat.net; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import org.bukkit.entity.Player; public class PacketRateLimiter { private final ConcurrentHashMap rateLimiters = new ConcurrentHashMap(); private final int maxPacketsPerSecond; private final int timeWindowSeconds = 5; public PacketRateLimiter(int maxPacketsPerSecond) { this.maxPacketsPerSecond = maxPacketsPerSecond; } public boolean allow(UUID player) { if (this.maxPacketsPerSecond <= 0) { return true; } RateLimiter limiter = this.rateLimiters.computeIfAbsent(player, id -> new RateLimiter(this.maxPacketsPerSecond * 5, 5000L)); return limiter.tryAcquire(); } public void onPlayerLoggedOut(Player player) { this.rateLimiters.remove(player.getUniqueId()); } private static class RateLimiter { private final int threshold; private final long timePerTokenNanos; private long lastLeakNanos; private long amount; public RateLimiter(int threshold, long windowMillis) { this.threshold = threshold; this.timePerTokenNanos = windowMillis * 1000000L / (long)threshold; this.lastLeakNanos = System.nanoTime(); this.amount = 0L; } public boolean tryAcquire() { long currentTime = System.nanoTime(); long elapsed = currentTime - this.lastLeakNanos; long leakedTokens = elapsed / this.timePerTokenNanos; if (leakedTokens > 0L) { this.amount -= leakedTokens; if (this.amount < 0L) { this.amount = 0L; } this.lastLeakNanos += leakedTokens * this.timePerTokenNanos; } if (this.amount >= (long)this.threshold) { return false; } ++this.amount; return true; } } }