Make moving.morepackets check server lag independent

This commit is contained in:
Evenprime 2012-02-05 18:13:45 +01:00
parent 03688f6e86
commit bf9450aceb
2 changed files with 46 additions and 52 deletions

View File

@ -1,7 +1,6 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving; package cc.co.evenprime.bukkit.nocheat.checks.moving;
import java.util.Locale; import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat; import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer; import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName; import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
@ -21,60 +20,41 @@ import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
public class MorePacketsCheck extends MovingCheck { public class MorePacketsCheck extends MovingCheck {
private final static int packetsPerTimeframe = 22; private final static int packetsPerTimeframe = 22;
private final static int bufferLimit = 30;
public MorePacketsCheck(NoCheat plugin) { public MorePacketsCheck(NoCheat plugin) {
super(plugin, "moving.morepackets", Permissions.MOVING_MOREPACKETS); super(plugin, "moving.morepackets", Permissions.MOVING_MOREPACKETS);
} }
/** /**
* 1. Collect packets processed within 20 server ticks = packetCounter * 1. Players get assigned a certain amount of "free" packets as a limit initially
* 2. Measure time taken for those 20 server ticks = elapsedTime * 2. Every move packet reduces that limit by 1
* 3. elapsedTime >> 1 second -> ignore next check * 3. If more than 1 second of time passed, the limit gets increased
* 4. limit = 22 x elapsedTime * by 22 * time in seconds, up to 50 and he gets a new "setback" location
* 5. difference = limit - packetCounter * 4. If the player reaches limit = 0 -> teleport him back to "setback"
* 6. buffer = buffer + difference; if(buffer > 20) buffer = 20; * 5. If there was a long pause (maybe lag), limit may be up to 100
* 7. if(buffer < 0) -> violation of size "buffer".
* 8. reset packetCounter, wait for next 20 ticks to pass by.
* *
*/ */
public PreciseLocation check(NoCheatPlayer player, MovingData data, MovingConfig cc) { public PreciseLocation check(NoCheatPlayer player, MovingData data, MovingConfig cc) {
PreciseLocation newToLocation = null; PreciseLocation newToLocation = null;
data.morePacketsCounter++;
if(!data.morePacketsSetbackPoint.isSet()) { if(!data.morePacketsSetbackPoint.isSet()) {
data.morePacketsSetbackPoint.set(data.from); data.morePacketsSetbackPoint.set(data.from);
} }
int ingameSeconds = plugin.getIngameSeconds(); long time = System.currentTimeMillis();
// Is at least a second gone by and has the server at least processed 20
// ticks since last time
if(ingameSeconds != data.lastElapsedIngameSeconds) {
int limit = (int) ((packetsPerTimeframe * plugin.getIngameSecondDuration()) / 1000L); // Take a packet from the buffer
data.morePacketsBuffer--;
int difference = limit - data.morePacketsCounter; // Player used up buffer, he fails the check
if(data.morePacketsBuffer < 0) {
data.morePacketsBuffer += difference; data.morePacketsVL = -data.morePacketsBuffer;
if(data.morePacketsBuffer > bufferLimit) data.morePacketsTotalVL++;
data.morePacketsBuffer = bufferLimit;
// Are we over the 22 event limit for that time frame now? (limit
// increases with time)
int packetsAboveLimit = (int) -data.morePacketsBuffer;
if(data.morePacketsBuffer < 0)
data.morePacketsBuffer = 0;
// Should we react? Only if the check doesn't get skipped and we
// went over the limit
if(!plugin.skipCheck() && packetsAboveLimit > 0) {
data.morePacketsVL += packetsAboveLimit;
data.morePacketsTotalVL += packetsAboveLimit;
data.morePacketsFailed++; data.morePacketsFailed++;
data.packets = packetsAboveLimit; data.packets = -data.morePacketsBuffer;
final boolean cancel = executeActions(player, cc.morePacketsActions.getActions(data.morePacketsVL)); final boolean cancel = executeActions(player, cc.morePacketsActions.getActions(data.morePacketsVL));
@ -82,17 +62,36 @@ public class MorePacketsCheck extends MovingCheck {
newToLocation = data.morePacketsSetbackPoint; newToLocation = data.morePacketsSetbackPoint;
} }
// No new setbackLocation was chosen if(data.morePacketsLastTime + 1000 < time) {
// More than 1 second elapsed, but how many?
double seconds = ((double)(time - data.morePacketsLastTime)) / 1000D;
// For each second, fill the buffer
data.morePacketsBuffer += packetsPerTimeframe * seconds;
// If there was a long pause (maybe server lag?)
// Allow buffer to grow up to 100
if(seconds > 2) {
if(data.morePacketsBuffer > 100) {
data.morePacketsBuffer = 100;
}
// Else only allow growth up to 50
} else {
if(data.morePacketsBuffer > 50) {
data.morePacketsBuffer = 50;
}
}
// Set the new "last" time
data.morePacketsLastTime = time;
// Set the new "setback" location
if(newToLocation == null) { if(newToLocation == null) {
data.morePacketsSetbackPoint.set(data.from); data.morePacketsSetbackPoint.set(data.from);
} }
} else if(data.morePacketsLastTime > time) {
if(data.morePacketsVL > 0) // Security check, maybe system time changed
// Shrink the "over limit" value by 20 % every second data.morePacketsLastTime = time;
data.morePacketsVL *= 0.8;
data.morePacketsCounter = 0; // Count from zero again
data.lastElapsedIngameSeconds = ingameSeconds;
} }
return newToLocation; return newToLocation;

View File

@ -33,6 +33,7 @@ public class MovingData implements DataItem {
public int jumpPhase; public int jumpPhase;
public double lastJumpAmplifier; public double lastJumpAmplifier;
public int onIce = 0;
public final PreciseLocation runflySetBackPoint = new PreciseLocation(); public final PreciseLocation runflySetBackPoint = new PreciseLocation();
@ -48,16 +49,13 @@ public class MovingData implements DataItem {
public double horizontalBuffer; public double horizontalBuffer;
public int bunnyhopdelay; public int bunnyhopdelay;
public int morePacketsCounter; public long morePacketsLastTime;
public int morePacketsBuffer = 30; public int morePacketsBuffer = 50;
public int packets;
public final PreciseLocation morePacketsSetbackPoint = new PreciseLocation(); public final PreciseLocation morePacketsSetbackPoint = new PreciseLocation();
public final PreciseLocation teleportTo = new PreciseLocation(); public final PreciseLocation teleportTo = new PreciseLocation();
public int lastElapsedIngameSeconds;
public final PreciseLocation from = new PreciseLocation(); public final PreciseLocation from = new PreciseLocation();
public final PreciseLocation to = new PreciseLocation(); public final PreciseLocation to = new PreciseLocation();
@ -66,7 +64,7 @@ public class MovingData implements DataItem {
public String checknamesuffix = ""; public String checknamesuffix = "";
public int onIce = 0; public int packets;
public void clearRunFlyData() { public void clearRunFlyData() {
runflySetBackPoint.reset(); runflySetBackPoint.reset();
@ -78,9 +76,6 @@ public class MovingData implements DataItem {
public void clearMorePacketsData() { public void clearMorePacketsData() {
morePacketsSetbackPoint.reset(); morePacketsSetbackPoint.reset();
morePacketsBuffer = 30;
lastElapsedIngameSeconds = 0;
morePacketsCounter = 0;
} }
@Override @Override