@Override protected float getScore(List<Character> chars, long ts) { lastAdd = ts; final char[] a = DigestedWords.toArray(chars); final String key = new String(a); ActionFrequency freq = entries.get(key); if (freq == null){ freq = new ActionFrequency(nBuckets, durBucket); entries.put(key, freq); return 0.0f; } freq.update(ts); float score = Math.min(1.0f, freq.score(factor)); freq.add(ts, 1.0f); return score; }
/** * Update and then reduce all given ActionFrequency instances by the given * amount, without capping the result. * * @param amount * The amount to subtract. * @param freqs */ public static void subtract(final long time, final float amount, final ActionFrequency... freqs) { for (int i = 0; i < freqs.length; i++) { final ActionFrequency freq = freqs[i]; freq.update(time); freq.setBucket(0, freq.bucketScore(0) - amount); } }
/** * Reset tick and tick stats to 0 (!). */ public static void reset() { tick = 0; timeLast = 0; for (int i = 0; i < lagMaxTicks; i++) { tickDurations[i] = 0; tickDurationsSq[i] = 0; } for (int i = 0; i < spikeDurations.length; i++) { spikes[i].clear(0); } }
/** * Checks hasBypass on violation only. * @param player * @param time * @param data * @param cc * @return If to cancel. */ public boolean check(final Player player, final long time, final NetData data, final NetConfig cc, final IPlayerData pData) { data.keepAliveFreq.add(time, 1f); final float first = data.keepAliveFreq.bucketScore(0); if (first > 1f) { // Trigger a violation. final double vl = Math.max(first - 1f, data.keepAliveFreq.score(1f) - data.keepAliveFreq.numberOfBuckets()); if (executeActions(player, vl, 1.0, cc.keepAliveFrequencyActions).willCancel()) { return true; } } return false; }
final long winDur = packetFreq.bucketDuration(); final int winNum = packetFreq.numberOfBuckets(); final long totalDur = winDur * winNum; final long tDiff = time - packetFreq.lastAccess(); if (tDiff >= winDur && tDiff < totalDur) { float sc0 = packetFreq.bucketScore(0); if (sc0 > maxPackets) { // TODO: Ideal vs. max. packets. final float sci = packetFreq.bucketScore(i); if (sci < maxPackets) { packetFreq.setBucket(i, sci + consume); if (sci > 0f) { packetFreq.setBucket(0, maxPackets + sc0); packetFreq.add(time, packets); boolean used = false; for (burnStart = 1; burnStart < winNum; burnStart ++) { if (packetFreq.bucketScore(burnStart) > 0f) { if (packetFreq.bucketScore(j) == 0f) { empty += 1; final float trailing = Math.max(packetFreq.trailingScore(burnStart, 1f), burnScore * (winNum - burnStart - empty)); final float leading = packetFreq.leadingScore(burnStart, 1f);
public boolean check(final Player player, final ChatConfig cc, final ChatData data) { final long now = System.currentTimeMillis(); // Skip if is too close to the startup time. if (now - TickTask.getTimeStart() < cc.loginsStartupDelay) return false; // Split into 6 buckets always. final long durBucket = 1000L * cc.loginsSeconds / 6; final ActionFrequency freq = getActionFrequency(player.getWorld().getName(), 6, durBucket, cc.loginsPerWorldCount); freq.update(now); final boolean cancel = freq.score(1f) > cc.loginsLimit; // TODO: >= ... This will be 1 after the first login (!). if (!cancel) freq.add(1f); return cancel; }
/** * Always update data, check bypass on violation only. * * @param player * @param time * @param data * @param cc * @return */ public boolean check(final Player player, final DataPacketFlying packetData, final long time, final NetData data, final NetConfig cc, final IPlayerData pData) { data.flyingFrequencyAll.add(time, 1f); final float allScore = data.flyingFrequencyAll.score(1f); if (allScore / cc.flyingFrequencySeconds > cc.flyingFrequencyPPS && executeActions(player, allScore / cc.flyingFrequencySeconds - cc.flyingFrequencyPPS, 1.0 / cc.flyingFrequencySeconds, cc.flyingFrequencyActions).willCancel()) { return true; } else { return false; } }
/** * Deserialize from a string. * @param line * @return */ public static ActionFrequency fromLine(final String line) { // TODO: Backwards-compatible lastUpdate ? String[] split = line.split(","); if (split.length < 3) throw new RuntimeException("Bad argument length."); // TODO final int n = Integer.parseInt(split[0]); final long durBucket = Long.parseLong(split[1]); final long time = Long.parseLong(split[2]); final float[] buckets = new float[split.length -3]; if (split.length - 3 != buckets.length) throw new RuntimeException("Bad argument length."); // TODO for (int i = 3; i < split.length; i ++) { buckets[i - 3] = Float.parseFloat(split[i]); } ActionFrequency freq = new ActionFrequency(n, durBucket); freq.setTime(time); for (int i = 0; i < buckets.length; i ++) { freq.setBucket(i, buckets[i]); } return freq; } }
public boolean check(final Player player, final long time, final NetData data, final NetConfig cc, final IPlayerData pData) { data.attackFrequencySeconds.add(time, 1f); double maxVL = 0.0; float maxLimit = 0f; float sum = data.attackFrequencySeconds.bucketScore(0); // HALF float limit = cc.attackFrequencyLimitSecondsHalf; if (sum - limit > maxVL) { sum += data.attackFrequencySeconds.bucketScore(1); limit = cc.attackFrequencyLimitSecondsOne; if (sum - limit > maxVL) { sum += data.attackFrequencySeconds.sliceScore(2, 4, 1f); limit = cc.attackFrequencyLimitSecondsTwo; if (sum - limit > maxVL) { sum += data.attackFrequencySeconds.sliceScore(4, 8, 1f); limit = cc.attackFrequencyLimitSecondsFour; if (sum - limit > maxVL) { sum += data.attackFrequencySeconds.sliceScore(8, 16, 1f); limit = cc.attackFrequencyLimitSecondsEight; if (sum - limit > maxVL) {
public FightData(final FightConfig config){ speedBuckets = new ActionFrequency(config.speedBuckets, config.speedBucketDur); // Start with full fast-heal buffer. fastHealBuffer = config.fastHealBuffer; }
/** * Get a weighted sum score, weight for bucket i: w(i) = factor^i. * @param factor * @return */ public final float score(final float factor) { return sliceScore(0, buckets.length, factor); }
/** * @deprecated Use instead: score(float). * @param factor * @return */ public final float getScore(final float factor) { return score(factor); }
/** * @deprecated Use instead: score(float). * @param factor * @return */ public final float getScore(final int bucket) { return bucketScore(bucket); }
/** * Update and add (updates reference and update time). * @param now * @param amount */ public final void add(final long now, final float amount) { update(now); buckets[0] += amount; }
/** * Feed the check but no violations processing (convenience method). * @param player * @param weight * @param now * @param pData */ public static final void feed(final Player player, final float weight, final long now, final IPlayerData pData){ pData.getGenericInstance(CombinedData.class).improbableCount.add(now, weight); }
/** * Actual state. * * @param player * @param data * * @param cc * * @return If to cancel a packet event. */ public boolean check(final Player player, final NetData data, final NetConfig cc) { data.packetFrequency.add(System.currentTimeMillis(), 1f); final long fDur = data.packetFrequency.bucketDuration() * data.packetFrequency.numberOfBuckets(); double amount = data.packetFrequency.score(1f) * 1000f / (float) fDur; // if (data.debug) { // debug(player, "Basic amount: " + amount); // } if (amount > cc.packetFrequencyPacketsPerSecond) { amount /= TickTask.getLag(fDur); if (amount > cc.packetFrequencyPacketsPerSecond) { if (executeActions(player, amount - cc.packetFrequencyPacketsPerSecond, 1.0, cc.packetFrequencyActions).willCancel()) { return true; } } } return false; // Cancel state. }
/** * Get heavy lag spikes of the last hour (> 450 ms supposedly, first * duration bigger than 150 ms). * * @return the heavy lag spikes * @deprecated What is heavy :) ? */ public static final int getHeavyLagSpikes() { spikes[1].update(System.currentTimeMillis()); return (int) spikes[1].score(1f); }