mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2025-01-29 11:41:43 +01:00
Fixes #870
This commit is contained in:
parent
274bc6d9a7
commit
9366acd6dc
@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
|
|||||||
import com.boydti.fawe.IFawe;
|
import com.boydti.fawe.IFawe;
|
||||||
import com.boydti.fawe.bukkit.chat.BukkitChatManager;
|
import com.boydti.fawe.bukkit.chat.BukkitChatManager;
|
||||||
import com.boydti.fawe.bukkit.listener.BrushListener;
|
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.CFIPacketListener;
|
||||||
import com.boydti.fawe.bukkit.listener.RenderListener;
|
import com.boydti.fawe.bukkit.listener.RenderListener;
|
||||||
import com.boydti.fawe.bukkit.regions.FactionsFeature;
|
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.VaultUtil;
|
||||||
import com.boydti.fawe.bukkit.util.cui.CUIListener;
|
import com.boydti.fawe.bukkit.util.cui.CUIListener;
|
||||||
import com.boydti.fawe.bukkit.util.cui.StructureCUI;
|
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.util.image.BukkitImageViewer;
|
||||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
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_10.BukkitQueue_1_10;
|
||||||
import com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11;
|
import com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11;
|
||||||
import com.boydti.fawe.bukkit.v1_12.BukkitQueue_1_12;
|
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);
|
Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin);
|
||||||
|
|
||||||
// The tick limiter
|
// The tick limiter
|
||||||
new ChunkListener();
|
try {
|
||||||
|
Class.forName("sun.misc.SharedSecrets");
|
||||||
|
new ChunkListener_8();
|
||||||
|
} catch( ClassNotFoundException e )
|
||||||
|
{
|
||||||
|
new ChunkListener_9();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.v0;
|
|||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.bukkit.FaweBukkit;
|
import com.boydti.fawe.bukkit.FaweBukkit;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
|
import com.boydti.fawe.util.FaweTimer;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
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.EntityChangeBlockEvent;
|
||||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||||
import org.bukkit.event.world.ChunkLoadEvent;
|
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 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() {
|
public ChunkListener() {
|
||||||
if (Settings.IMP.TICK_LIMITER.ENABLED) {
|
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 physicsFreeze = false;
|
||||||
public static boolean itemFreeze = false;
|
public static boolean itemFreeze = false;
|
||||||
|
|
||||||
@ -91,6 +94,9 @@ public class ChunkListener implements Listener {
|
|||||||
private boolean physCancel;
|
private boolean physCancel;
|
||||||
private long physCancelPair;
|
private long physCancelPair;
|
||||||
|
|
||||||
|
private long physStart;
|
||||||
|
private long physTick;
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
public void onPhysics(BlockPhysicsEvent event) {
|
public void onPhysics(BlockPhysicsEvent event) {
|
||||||
if (physCancel) {
|
if (physCancel) {
|
||||||
@ -105,25 +111,34 @@ public class ChunkListener implements Listener {
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
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) {
|
if (physicsFreeze) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// For performance reasons, skip most checks
|
|
||||||
if ((++physSkip & 2047) != 0) return;
|
|
||||||
if (event.getChangedTypeId() == 0) return;
|
if (event.getChangedTypeId() == 0) return;
|
||||||
Exception e = new Exception();
|
Exception e = new Exception();
|
||||||
int depth = SharedSecrets.getJavaLangAccess().getStackTraceDepth(e);
|
int depth = getDepth(e);
|
||||||
if (depth >= Settings.IMP.TICK_LIMITER.PHYSICS) {
|
if (depth >= 256) {
|
||||||
for (int frame = 25; frame < 33; frame++) {
|
for (int frame = 25; frame < 33; frame++) {
|
||||||
StackTraceElement elem = SharedSecrets.getJavaLangAccess().getStackTraceElement(e, frame);
|
StackTraceElement elem = getElement(e, frame);
|
||||||
String methodName = elem.getMethodName();
|
String methodName = elem.getMethodName();
|
||||||
// setAir (hacky, but this needs to be efficient)
|
// setAir (hacky, but this needs to be efficient)
|
||||||
if (methodName.charAt(0) == 's' && methodName.length() == 6) {
|
if (methodName.charAt(0) == 's' && methodName.length() == 6) {
|
||||||
Block block = event.getBlock();
|
Block block = event.getBlock();
|
||||||
int cx = block.getX() >> 4;
|
int cx = block.getX() >> 4;
|
||||||
int cz = block.getZ() >> 4;
|
int cz = block.getZ() >> 4;
|
||||||
|
physCancelPair = MathMan.pairInt(cx, cz);
|
||||||
if (rateLimit <= 0) {
|
if (rateLimit <= 0) {
|
||||||
rateLimit = 20;
|
rateLimit = 20;
|
||||||
Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled physics lag source at " + block.getLocation());
|
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 - 1, cz);
|
||||||
cancel(cx, cz + 1);
|
cancel(cx, cz + 1);
|
||||||
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) {
|
private void cancel(int cx, int cz) {
|
||||||
long key = MathMan.pairInt(cx, cz);
|
long key = MathMan.pairInt(cx, cz);
|
||||||
badChunks.put(key, (Boolean) true);
|
badChunks.put(key, (Boolean) true);
|
||||||
counter.put(key, badLimit);
|
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
|
// Falling
|
||||||
@ -202,10 +226,10 @@ public class ChunkListener implements Listener {
|
|||||||
Exception e = new Exception();
|
Exception e = new Exception();
|
||||||
int start = 14;
|
int start = 14;
|
||||||
int end = 22;
|
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++) {
|
for (int frame = start; frame < depth; frame++) {
|
||||||
StackTraceElement elem = SharedSecrets.getJavaLangAccess().getStackTraceElement(e, frame);
|
StackTraceElement elem = getElement(e, frame);
|
||||||
String className = elem.getClassName();
|
String className = elem.getClassName();
|
||||||
int len = className.length();
|
int len = className.length();
|
||||||
if (className != null) {
|
if (className != null) {
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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];
|
||||||
|
}
|
||||||
|
}
|
@ -353,8 +353,8 @@ public class Settings extends Config {
|
|||||||
public int INTERVAL = 20;
|
public int INTERVAL = 20;
|
||||||
@Comment("Max falling blocks per interval (per chunk)")
|
@Comment("Max falling blocks per interval (per chunk)")
|
||||||
public int FALLING = 64;
|
public int FALLING = 64;
|
||||||
@Comment("Max physics per interval (per chunk)")
|
@Comment("Max physics per interval (excluding redstone)")
|
||||||
public int PHYSICS = 256;
|
public int PHYSICS_MS = 50;
|
||||||
@Comment("Max item spawns per interval (per chunk)")
|
@Comment("Max item spawns per interval (per chunk)")
|
||||||
public int ITEMS = 256;
|
public int ITEMS = 256;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user