ChunkListener fixes

This commit is contained in:
Jesse Boyd 2016-12-09 22:37:28 +11:00
parent 502b620bde
commit 1e4397c8d1
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
3 changed files with 143 additions and 90 deletions

View File

@ -3,7 +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.object.IntegerPair;
import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import java.util.HashMap;
@ -11,6 +11,7 @@ import java.util.HashSet;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -18,6 +19,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
public class ChunkListener implements Listener {
@ -33,7 +35,7 @@ public class ChunkListener implements Listener {
counter.clear();
lastZ = Integer.MIN_VALUE;
for (Long badChunk : badChunks) {
counter.put(badChunk, new IntegerPair(Settings.TICK_LIMITER.PHYSICS, Settings.TICK_LIMITER.ITEMS));
counter.put(badChunk, new IntegerTrio(Settings.TICK_LIMITER.PHYSICS, Settings.TICK_LIMITER.ITEMS, Settings.TICK_LIMITER.FALLING));
}
badChunks.clear();
}
@ -45,11 +47,11 @@ public class ChunkListener implements Listener {
public static boolean itemFreeze = false;
private HashSet<Long> badChunks = new HashSet<>();
private HashMap<Long, IntegerPair> counter = new HashMap<>();
private HashMap<Long, IntegerTrio> counter = new HashMap<>();
private int lastX = Integer.MIN_VALUE, lastZ = Integer.MIN_VALUE;
private IntegerPair lastCount;
private IntegerTrio lastCount;
public IntegerPair getCount(int cx, int cz) {
public IntegerTrio getCount(int cx, int cz) {
if (lastX == cx && lastZ == cz) {
return lastCount;
}
@ -58,7 +60,7 @@ public class ChunkListener implements Listener {
long pair = MathMan.pairInt(cx, cz);
lastCount = counter.get(pair);
if (lastCount == null) {
lastCount = new IntegerPair(0,0);
lastCount = new IntegerTrio();
counter.put(pair, lastCount);
}
return lastCount;
@ -73,14 +75,21 @@ public class ChunkListener implements Listener {
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPhysics(BlockPhysicsEvent event) {
if (physicsFreeze) {
event.setCancelled(true);
return;
}
int id = event.getChangedTypeId();
public boolean isRedstone(int id) {
switch (id) {
// wire
case 55:
// comparator
case 149:
case 150:
// diode
case 93:
case 94:
// torch
case 75:
case 76:
// rail
case 27:
case 23: // dispensor
case 158: // dropper
case 25:
@ -89,8 +98,6 @@ public class ChunkListener implements Listener {
case 33:
// tnt
case 44:
// wire
case 55:
// door
case 96: // trapdoor
case 167:
@ -100,47 +107,77 @@ public class ChunkListener implements Listener {
case 185:
case 186:
case 187:
case 64: // door
case 71:
case 193:
case 194:
case 195:
case 196:
case 197:
// diode
case 93:
case 94:
// torch
case 75:
case 76:
// comparator
case 149:
case 150:
// lamp
case 123:
case 124:
// rail
case 27:
// BUD
case 73: // ore
case 74:
case 8: // water
case 9:
case 34: // piston
return;
return true;
default:
return false;
}
Block block = event.getBlock();
int cx = block.getX() >> 4;
int cz = block.getZ() >> 4;
IntegerPair count = getCount(cx, cz);
if (++count.x >= Settings.TICK_LIMITER.PHYSICS) {
if (count.x == Settings.TICK_LIMITER.PHYSICS) {
badChunks.add(MathMan.pairInt(cx, cz));
Fawe.debug("[Tick Limiter] Detected and cancelled lag source at " + block.getLocation());
}
}
private int lastPhysY = 0;
@EventHandler(priority = EventPriority.LOWEST)
public void onPhysics(BlockPhysicsEvent event) {
if (physicsFreeze) {
event.setCancelled(true);
return;
}
Block block = event.getBlock();
int x = block.getX();
int z = block.getZ();
int cx = x >> 4;
int cz = z >> 4;
IntegerTrio count = getCount(cx, cz);
if (count.x >= Settings.TICK_LIMITER.PHYSICS) {
event.setCancelled(true);
return;
}
if (event.getChangedType() == block.getType()) {
int y = block.getY();
if (y != lastPhysY) {
lastPhysY = y;
if (++count.x == Settings.TICK_LIMITER.PHYSICS) {
badChunks.add(MathMan.pairInt(cx, cz));
Fawe.debug("[Tick Limiter] Detected and cancelled physics lag source at " + block.getLocation());
}
return;
}
lastPhysY = y;
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockChange(EntityChangeBlockEvent event) {
if (physicsFreeze) {
event.setCancelled(true);
return;
}
Material to = event.getTo();
if (to == Material.AIR) {
Block block = event.getBlock();
int x = block.getX();
int z = block.getZ();
int cx = x >> 4;
int cz = z >> 4;
IntegerTrio count = getCount(cx, cz);
if (++count.y >= Settings.TICK_LIMITER.FALLING) {
if (count.y == Settings.TICK_LIMITER.FALLING) {
count.x = Settings.TICK_LIMITER.PHYSICS;
badChunks.add(MathMan.pairInt(cx, cz));
Fawe.debug("[Tick Limiter] Detected and cancelled falling block lag source at " + block.getLocation());
}
event.setCancelled(true);
return;
}
}
}
@EventHandler(priority = EventPriority.LOWEST)
@ -152,12 +189,13 @@ public class ChunkListener implements Listener {
Location loc = event.getLocation();
int cx = loc.getBlockX() >> 4;
int cz = loc.getBlockZ() >> 4;
IntegerPair count = getCount(cx, cz);
IntegerTrio count = getCount(cx, cz);
if (++count.z >= Settings.TICK_LIMITER.ITEMS) {
if (count.z == Settings.TICK_LIMITER.ITEMS) {
count.x = Settings.TICK_LIMITER.PHYSICS;
cleanup(loc.getChunk());
badChunks.add(MathMan.pairInt(cx, cz));
Fawe.debug("[Tick Limiter] Detected and cancelled lag source at " + loc);
Fawe.debug("[Tick Limiter] Detected and cancelled item lag source at " + loc);
}
event.setCancelled(true);
return;

View File

@ -246,10 +246,12 @@ public class Settings extends Config {
public static class TICK_LIMITER {
@Comment("Enable the limiter")
public static boolean ENABLED = true;
@Comment("Max falling blocks per tick (per chunk)")
public static int FALLING = 512;
@Comment("Max physics per tick (per chunk)")
public static int PHYSICS = 4096;
public static int PHYSICS = 512;
@Comment("Max item spawns per tick (per chunk)")
public static int ITEMS = 512;
public static int ITEMS = 48;
}

View File

@ -80,7 +80,22 @@ public class HashTagPatternParser extends InputParser<Pattern>{
e.prepend(currentInput.substring(0, currentInput.length() - nextInput.length()));
throw e;
}
}
public List<String> handleRemainder(String input, String... expected) throws InputParseException {
List<String> remainder = split(input, ':');
int len = remainder.size();
if (len != expected.length - 1) {
if (len <= expected.length - 1 && len != 0) {
if (remainder.get(len - 1).endsWith(":")) {
throw new SuggestInputParseException(null, ALL_PATTERNS).prepend(expected[0] + ":" + input);
}
throw new SuggestInputParseException(null, expected[0] + ":" + input + ":" + StringMan.join(Arrays.copyOfRange(expected, len + 1, 3), ":"));
} else {
throw new SuggestInputParseException(null, StringMan.join(expected, ":"));
}
}
return remainder;
}
@Override
@ -157,19 +172,7 @@ public class HashTagPatternParser extends InputParser<Pattern>{
return new NoZPattern(catchSuggestion(input, rest, context));
}
case "#mask": {
List<String> split3 = split(rest, ':');
int len = split3.size();
if (len != 3) {
if (len <= 3) {
if (split3.get(len - 1).endsWith(":")) {
throw new SuggestInputParseException(null, ALL_PATTERNS).prepend(input);
}
String[] args = new String[]{"<mask>", "<pattern-if>", "<pattern-else>"};
throw new SuggestInputParseException(input, input + ":" + StringMan.join(Arrays.copyOfRange(args, len, 3), ":"));
} else {
throw new SuggestInputParseException(input, "#mask:<mask>:<pattern-if>:<pattern-else>");
}
}
List<String> split3 = handleRemainder(rest, "#mask", "<mask>", "<pattern-if>", "<pattern-else>");
Pattern primary = catchSuggestion(input, split3.get(1), context);
Pattern secondary = catchSuggestion(input, split3.get(2), context);
PatternExtent extent = new PatternExtent(primary);
@ -181,56 +184,60 @@ public class HashTagPatternParser extends InputParser<Pattern>{
MaskFactory factory = worldEdit.getMaskFactory();
Mask mask = factory.parseFromInput(split3.get(0), context);
if (mask == null | primary == null || secondary == null) {
throw new SuggestInputParseException(input, "#mask:<mask>:<pattern-if>:<pattern-else>");
throw new SuggestInputParseException(null, "#mask:<mask>:<pattern-if>:<pattern-else>");
}
return new MaskedPattern(mask, extent, secondary);
}
case "#offset":
try {
int x = (int) Math.abs(Expression.compile(split2[1]).evaluate());
int y = (int) Math.abs(Expression.compile(split2[2]).evaluate());
int z = (int) Math.abs(Expression.compile(split2[3]).evaluate());
rest = rest.substring(split2[1].length() + split2[2].length() + split2[3].length() + 3);
List<String> split3 = handleRemainder(rest, "#offset", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size() - 1), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new OffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException e) {
throw new SuggestInputParseException(input, "#offset:<dx>:<dy>:<dz>:<pattern>");
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#offset:<dx>:<dy>:<dz>:<pattern>");
}
case "#surfacespread": {
try {
int x = (int) Math.abs(Expression.compile(split2[1]).evaluate());
int y = (int) Math.abs(Expression.compile(split2[2]).evaluate());
int z = (int) Math.abs(Expression.compile(split2[3]).evaluate());
rest = rest.substring(split2[1].length() + split2[2].length() + split2[3].length() + 3);
List<String> split3 = handleRemainder(rest, "#surfacespread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size() - 1), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new SurfaceRandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException e) {
throw new SuggestInputParseException(input, "#surfacespread:<dx>:<dy>:<dz>:<pattern>");
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#surfacespread:<dx>:<dy>:<dz>:<pattern>");
}
}
case "#solidspread": {
try {
int x = (int) Math.abs(Expression.compile(split2[1]).evaluate());
int y = (int) Math.abs(Expression.compile(split2[2]).evaluate());
int z = (int) Math.abs(Expression.compile(split2[3]).evaluate());
rest = rest.substring(split2[1].length() + split2[2].length() + split2[3].length() + 3);
List<String> split3 = handleRemainder(rest, "#solidspread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size() - 1), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new SolidRandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException e) {
throw new SuggestInputParseException(input, "#solidspread:<dx>:<dy>:<dz>:<pattern>");
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#solidspread:<dx>:<dy>:<dz>:<pattern>");
}
}
case "#randomoffset":
case "#spread": {
try {
int x = (int) Math.abs(Expression.compile(split2[1]).evaluate());
int y = (int) Math.abs(Expression.compile(split2[2]).evaluate());
int z = (int) Math.abs(Expression.compile(split2[3]).evaluate());
rest = rest.substring(split2[1].length() + split2[2].length() + split2[3].length() + 3);
List<String> split3 = handleRemainder(rest, "#spread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size() - 1), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new RandomOffsetPattern(pattern, x, y, z);
} catch (NumberFormatException | ExpressionException e) {
throw new SuggestInputParseException(input, "#spread:<dx>:<dy>:<dz>:<pattern>");
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#spread:<dx>:<dy>:<dz>:<pattern>");
}
}
case "#l":
@ -277,11 +284,17 @@ public class HashTagPatternParser extends InputParser<Pattern>{
}
}
default:
if (input.equals("<pattern>")) {
throw new SuggestInputParseException(input, ALL_PATTERNS);
}
if (input.equals("<block>")) {
throw new SuggestInputParseException(input, BundledBlockData.getInstance().getBlockNames());
switch (input) {
case "<dx>":
case "<dy>":
case "<dz>":
throw new SuggestInputParseException(input, "0", "-3", "7");
case "<pattern>":
case "<pattern-if>":
case "<pattern-else>":
throw new SuggestInputParseException(input, ALL_PATTERNS);
case "<block>":
throw new SuggestInputParseException(input, BundledBlockData.getInstance().getBlockNames());
}
List<String> items = split(input, ',');
if (items.size() == 1) {