This commit is contained in:
Jesse Boyd 2018-01-11 14:26:33 +11:00
parent 274bc6d9a7
commit 9366acd6dc
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
5 changed files with 121 additions and 15 deletions

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.IFawe;
import com.boydti.fawe.bukkit.chat.BukkitChatManager;
import com.boydti.fawe.bukkit.listener.BrushListener;
import com.boydti.fawe.bukkit.listener.BukkitImageListener;
import com.boydti.fawe.bukkit.listener.CFIPacketListener;
import com.boydti.fawe.bukkit.listener.RenderListener;
import com.boydti.fawe.bukkit.regions.FactionsFeature;
@ -20,11 +21,11 @@ import com.boydti.fawe.bukkit.util.ItemUtil;
import com.boydti.fawe.bukkit.util.VaultUtil;
import com.boydti.fawe.bukkit.util.cui.CUIListener;
import com.boydti.fawe.bukkit.util.cui.StructureCUI;
import com.boydti.fawe.bukkit.listener.BukkitImageListener;
import com.boydti.fawe.bukkit.util.image.BukkitImageViewer;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
import com.boydti.fawe.bukkit.v0.ChunkListener;
import com.boydti.fawe.bukkit.v0.ChunkListener_8;
import com.boydti.fawe.bukkit.v0.ChunkListener_9;
import com.boydti.fawe.bukkit.v1_10.BukkitQueue_1_10;
import com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11;
import com.boydti.fawe.bukkit.v1_12.BukkitQueue_1_12;
@ -147,7 +148,13 @@ public class FaweBukkit implements IFawe, Listener {
Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin);
// The tick limiter
new ChunkListener();
try {
Class.forName("sun.misc.SharedSecrets");
new ChunkListener_8();
} catch( ClassNotFoundException e )
{
new ChunkListener_9();
}
}
});
}

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.v0;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.bukkit.FaweBukkit;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.util.FaweTimer;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
@ -21,12 +22,11 @@ import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import sun.misc.SharedSecrets;
public class ChunkListener implements Listener {
public abstract class ChunkListener implements Listener {
private int rateLimit = 0;
private int[] badLimit = new int[]{Settings.IMP.TICK_LIMITER.PHYSICS, Settings.IMP.TICK_LIMITER.FALLING, Settings.IMP.TICK_LIMITER.ITEMS};
private int[] badLimit = new int[]{Settings.IMP.TICK_LIMITER.PHYSICS_MS, Settings.IMP.TICK_LIMITER.FALLING, Settings.IMP.TICK_LIMITER.ITEMS};
public ChunkListener() {
if (Settings.IMP.TICK_LIMITER.ENABLED) {
@ -55,6 +55,9 @@ public class ChunkListener implements Listener {
}
}
protected abstract int getDepth(Exception ex);
protected abstract StackTraceElement getElement(Exception ex, int index);
public static boolean physicsFreeze = false;
public static boolean itemFreeze = false;
@ -91,6 +94,9 @@ public class ChunkListener implements Listener {
private boolean physCancel;
private long physCancelPair;
private long physStart;
private long physTick;
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPhysics(BlockPhysicsEvent event) {
if (physCancel) {
@ -105,25 +111,34 @@ public class ChunkListener implements Listener {
event.setCancelled(true);
return;
}
} else {
if ((++physSkip & 1023) != 0) return;
FaweTimer timer = Fawe.get().getTimer();
if (timer.getTick() != physTick) {
physTick = timer.getTick();
physStart = System.currentTimeMillis();
return;
} else if (System.currentTimeMillis() - physStart < Settings.IMP.TICK_LIMITER.PHYSICS_MS) {
return;
}
}
if (physicsFreeze) {
event.setCancelled(true);
return;
}
// For performance reasons, skip most checks
if ((++physSkip & 2047) != 0) return;
if (event.getChangedTypeId() == 0) return;
Exception e = new Exception();
int depth = SharedSecrets.getJavaLangAccess().getStackTraceDepth(e);
if (depth >= Settings.IMP.TICK_LIMITER.PHYSICS) {
int depth = getDepth(e);
if (depth >= 256) {
for (int frame = 25; frame < 33; frame++) {
StackTraceElement elem = SharedSecrets.getJavaLangAccess().getStackTraceElement(e, frame);
StackTraceElement elem = getElement(e, frame);
String methodName = elem.getMethodName();
// setAir (hacky, but this needs to be efficient)
if (methodName.charAt(0) == 's' && methodName.length() == 6) {
Block block = event.getBlock();
int cx = block.getX() >> 4;
int cz = block.getZ() >> 4;
physCancelPair = MathMan.pairInt(cx, cz);
if (rateLimit <= 0) {
rateLimit = 20;
Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled physics lag source at " + block.getLocation());
@ -145,12 +160,21 @@ public class ChunkListener implements Listener {
cancel(cx - 1, cz);
cancel(cx, cz + 1);
cancel(cx, cz - 1);
cancel(cx - 1, cz - 1);
cancel(cx - 1, cz + 1);
cancel(cx + 1, cz - 1);
cancel(cx + 1, cz + 1);
}
private void cancel(int cx, int cz) {
long key = MathMan.pairInt(cx, cz);
badChunks.put(key, (Boolean) true);
counter.put(key, badLimit);
int[] count = getCount(cx, cz);
count[0] = Integer.MAX_VALUE;
count[1] = Integer.MAX_VALUE;
count[2] = Integer.MAX_VALUE;
}
// Falling
@ -202,10 +226,10 @@ public class ChunkListener implements Listener {
Exception e = new Exception();
int start = 14;
int end = 22;
int depth = Math.min(end, SharedSecrets.getJavaLangAccess().getStackTraceDepth(e));
int depth = Math.min(end, getDepth(e));
for (int frame = start; frame < depth; frame++) {
StackTraceElement elem = SharedSecrets.getJavaLangAccess().getStackTraceElement(e, frame);
StackTraceElement elem = getElement(e, frame);
String className = elem.getClassName();
int len = className.length();
if (className != null) {

View File

@ -0,0 +1,16 @@
package com.boydti.fawe.bukkit.v0;
import sun.misc.SharedSecrets;
public class ChunkListener_8 extends ChunkListener {
@Override
protected int getDepth(Exception ex) {
return SharedSecrets.getJavaLangAccess().getStackTraceDepth(ex);
}
@Override
protected StackTraceElement getElement(Exception ex, int index) {
return SharedSecrets.getJavaLangAccess().getStackTraceElement(ex, index);
}
}

View File

@ -0,0 +1,59 @@
package com.boydti.fawe.bukkit.v0;
import com.boydti.fawe.config.Settings;
import java.lang.reflect.Method;
public class ChunkListener_9 extends ChunkListener {
private Method methodDepth;
private Method methodGetStackTraceElement;
private Exception exception;
private StackTraceElement[] elements;
public ChunkListener_9() {
if (Settings.IMP.TICK_LIMITER.ENABLED) {
try {
this.methodDepth = Throwable.class.getDeclaredMethod("getStackTraceDepth");
this.methodDepth.setAccessible(true);
this.methodGetStackTraceElement = Throwable.class.getDeclaredMethod("getStackTraceElement", int.class);
this.methodGetStackTraceElement.setAccessible(true);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
private StackTraceElement[] getElements(Exception ex) {
if (elements == null || ex != exception) {
exception = ex;
elements = ex.getStackTrace();
}
return elements;
}
@Override
protected int getDepth(Exception ex) {
if (methodDepth != null) {
try {
return (int) methodDepth.invoke(ex);
} catch (Throwable t) {
methodDepth = null;
t.printStackTrace();
}
}
return getElements(ex).length;
}
@Override
protected StackTraceElement getElement(Exception ex, int i) {
if (methodGetStackTraceElement != null) {
try {
return (StackTraceElement) methodGetStackTraceElement.invoke(ex, i);
} catch (Throwable t) {
methodGetStackTraceElement = null;
t.printStackTrace();
}
}
return getElements(ex)[i];
}
}

View File

@ -353,8 +353,8 @@ public class Settings extends Config {
public int INTERVAL = 20;
@Comment("Max falling blocks per interval (per chunk)")
public int FALLING = 64;
@Comment("Max physics per interval (per chunk)")
public int PHYSICS = 256;
@Comment("Max physics per interval (excluding redstone)")
public int PHYSICS_MS = 50;
@Comment("Max item spawns per interval (per chunk)")
public int ITEMS = 256;
}