diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java index e50d9e835..5aa7d3734 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java @@ -45,6 +45,7 @@ public class StructureScript { private final String id; String tempID; private final Map cache; + private final TerraPlugin main; public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache) throws ParseException { Parser parser; @@ -81,6 +82,7 @@ public class StructureScript { block = parser.parse(); this.id = parser.getID(); tempID = id; + this.main = main; this.cache = Collections.synchronizedMap(new LinkedHashMap() { @Override protected boolean removeEldestEntry(Map.Entry eldest) { @@ -98,9 +100,9 @@ public class StructureScript { */ public boolean execute(Location location, Random random, Rotation rotation) { StructureBuffer buffer = new StructureBuffer(location); - Block.ReturnInfo level = block.apply(new TerraImplementationArguments(buffer, rotation, random, 0)); + boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0)); buffer.paste(); - return !level.getLevel().equals(Block.ReturnLevel.FAIL); + return level; } public boolean execute(Location location, Chunk chunk, Random random, Rotation rotation) { @@ -118,23 +120,31 @@ public class StructureScript { synchronized(cache) { return cache.computeIfAbsent(location, loc -> { StructureBuffer buf = new StructureBuffer(loc); - Block.ReturnInfo level = block.apply(new TerraImplementationArguments(buf, rotation, random, 0)); - buf.setSucceeded(!level.getLevel().equals(Block.ReturnLevel.FAIL)); + buf.setSucceeded(applyBlock(new TerraImplementationArguments(buf, rotation, random, 0))); return buf; }); } } public boolean executeInBuffer(Buffer buffer, Random random, Rotation rotation, int recursions) { - return !block.apply(new TerraImplementationArguments(buffer, rotation, random, recursions)).getLevel().equals(Block.ReturnLevel.FAIL); + return applyBlock(new TerraImplementationArguments(buffer, rotation, random, recursions)); } public boolean executeDirect(Location location, Random random, Rotation rotation) { DirectBuffer buffer = new DirectBuffer(location); - return !block.apply(new TerraImplementationArguments(buffer, rotation, random, 0)).getLevel().equals(Block.ReturnLevel.FAIL); + return applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0)); } public String getId() { return id; } + + private boolean applyBlock(TerraImplementationArguments arguments) { + try { + return !block.apply(arguments).getLevel().equals(Block.ReturnLevel.FAIL); + } catch(RuntimeException e) { + main.getLogger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage()); + return false; + } + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java index 3a23e54aa..313290d95 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java @@ -45,6 +45,9 @@ public class StructureFunction implements Function { public Boolean apply(ImplementationArguments implementationArguments) { TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + if(arguments.getRecursions() > main.getTerraConfig().getMaxRecursion()) + throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions()); + Vector2 xz = new Vector2(x.apply(implementationArguments).doubleValue(), z.apply(implementationArguments).doubleValue()); RotationUtil.rotateVector(xz, arguments.getRotation()); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java index bf2d2c2f6..87d475a26 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java @@ -20,7 +20,7 @@ public class BufferedLootApplication implements BufferedItem { public void paste(Location origin) { BlockState data = origin.getBlock().getState(); if(!(data instanceof Container)) { - main.getLogger().severe("Failed to place loot at " + origin + "; block " + data.toString() + " is not container."); + main.getLogger().severe("Failed to place loot at " + origin + "; block " + data + " is not container."); return; } Container container = (Container) data; diff --git a/common/src/main/java/com/dfsek/terra/config/base/PluginConfig.java b/common/src/main/java/com/dfsek/terra/config/base/PluginConfig.java index b61d8291a..9b7691f73 100644 --- a/common/src/main/java/com/dfsek/terra/config/base/PluginConfig.java +++ b/common/src/main/java/com/dfsek/terra/config/base/PluginConfig.java @@ -51,6 +51,10 @@ public class PluginConfig implements ConfigTemplate { @Default private boolean dumpDefaultConfig = true; + @Value("script.max-recursion") + @Default + private int maxRecursion = 1000; + public void load(TerraPlugin main) { Logger logger = main.getLogger(); logger.info("Loading config values"); @@ -99,4 +103,8 @@ public class PluginConfig implements ConfigTemplate { public int getSamplerCache() { return samplerCache; } + + public int getMaxRecursion() { + return maxRecursion; + } } diff --git a/platforms/bukkit/src/main/resources/config.yml b/platforms/bukkit/src/main/resources/config.yml index 4d652784a..adb7d8522 100644 --- a/platforms/bukkit/src/main/resources/config.yml +++ b/platforms/bukkit/src/main/resources/config.yml @@ -8,4 +8,6 @@ cache: structure: 32 sampler: 128 master-disable: - caves: false \ No newline at end of file + caves: false +script: + max-recursion: 1000 \ No newline at end of file