From 1e4397c8d171ba6ac0c45190ed3c801e5b94fb49 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Fri, 9 Dec 2016 22:37:28 +1100 Subject: [PATCH] ChunkListener fixes --- .../boydti/fawe/bukkit/v0/ChunkListener.java | 128 ++++++++++++------ .../java/com/boydti/fawe/config/Settings.java | 6 +- .../factory/HashTagPatternParser.java | 99 ++++++++------ 3 files changed, 143 insertions(+), 90 deletions(-) diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java index 388ca6d4..8a8f0711 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java @@ -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 badChunks = new HashSet<>(); - private HashMap counter = new HashMap<>(); + private HashMap 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; diff --git a/core/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java index 9c182b3b..6fa10a54 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -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; } diff --git a/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java b/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java index 250b5f54..a7e04754 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java @@ -80,7 +80,22 @@ public class HashTagPatternParser extends InputParser{ e.prepend(currentInput.substring(0, currentInput.length() - nextInput.length())); throw e; } + } + public List handleRemainder(String input, String... expected) throws InputParseException { + List 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{ return new NoZPattern(catchSuggestion(input, rest, context)); } case "#mask": { - List 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[]{"", "", ""}; - throw new SuggestInputParseException(input, input + ":" + StringMan.join(Arrays.copyOfRange(args, len, 3), ":")); - } else { - throw new SuggestInputParseException(input, "#mask:::"); - } - } + List split3 = handleRemainder(rest, "#mask", "", "", ""); 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{ MaskFactory factory = worldEdit.getMaskFactory(); Mask mask = factory.parseFromInput(split3.get(0), context); if (mask == null | primary == null || secondary == null) { - throw new SuggestInputParseException(input, "#mask:::"); + throw new SuggestInputParseException(null, "#mask:::"); } 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 split3 = handleRemainder(rest, "#offset", "", "", "", ""); + 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::::"); + } catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) { + throw new SuggestInputParseException(null, "#offset::::"); } 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 split3 = handleRemainder(rest, "#surfacespread", "", "", "", ""); + 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::::"); + } catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) { + throw new SuggestInputParseException(null, "#surfacespread::::"); } } 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 split3 = handleRemainder(rest, "#solidspread", "", "", "", ""); + 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::::"); + } catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) { + throw new SuggestInputParseException(null, "#solidspread::::"); } } 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 split3 = handleRemainder(rest, "#spread", "", "", "", ""); + 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::::"); + } catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) { + throw new SuggestInputParseException(null, "#spread::::"); } } case "#l": @@ -277,11 +284,17 @@ public class HashTagPatternParser extends InputParser{ } } default: - if (input.equals("")) { - throw new SuggestInputParseException(input, ALL_PATTERNS); - } - if (input.equals("")) { - throw new SuggestInputParseException(input, BundledBlockData.getInstance().getBlockNames()); + switch (input) { + case "": + case "": + case "": + throw new SuggestInputParseException(input, "0", "-3", "7"); + case "": + case "": + case "": + throw new SuggestInputParseException(input, ALL_PATTERNS); + case "": + throw new SuggestInputParseException(input, BundledBlockData.getInstance().getBlockNames()); } List items = split(input, ','); if (items.size() == 1) {