diff --git a/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElement.java b/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElement.java index f6ed4c71..f3486a44 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElement.java +++ b/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElement.java @@ -96,7 +96,7 @@ public interface IStructureElement { "Default implementation of survivalPlaceBlock hit! Things aren't going to work well! IStructureElement class: {}", getClass().getName()); if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor)) return PlaceResult.REJECT; - return PlaceResult.SKIP; + return PlaceResult.REJECT_CONTINUE; } /** @@ -206,7 +206,7 @@ public interface IStructureElement { if (StructureLibAPI.isDebugEnabled()) LOGGER.info( "Fallback shim code of survivalPlaceBlock hit! Things aren't going to work well! IStructureElement class: {}", getClass().getName()); - return PlaceResult.SKIP; + return PlaceResult.REJECT_CONTINUE; } /** @@ -268,16 +268,21 @@ public interface IStructureElement { enum PlaceResult { /** - * This element either exists already, or does not yet have an implementation for survivalPlaceBlock, or some - * other unforeseen situations. TODO this definition doesn't seem right. Should we separate SKIP from EXISTS, or - * SKIP from ERROR? + * The element's check passed, the position is already valid. No placement is needed. In the walker: continue + * iteration (no error, not counted as placed). In ofChain: short-circuits, remaining alternatives are skipped. */ SKIP, /** - * This element's space is occupied by other stuff and require player attention, or player missing required - * resource, or the block cannot be placed due to obscure mechanisms, or some other unforeseen situations. + * The element cannot handle this position (occupied, missing resources, etc.). In the walker: stop iteration + * with error particles. In ofChain: try next alternative. */ REJECT, + /** + * This element has no survivalPlaceBlock implementation (default fallback), or otherwise cannot place but is + * not an error condition. In the walker: continue iteration silently (like SKIP). In ofChain: try next + * alternative (like REJECT), so a better-suited element can handle it. + */ + REJECT_CONTINUE, /** * Autoplace cannot proceed within this tick. To proceed further would require stopping the placement and wait * for next round. diff --git a/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElementChain.java b/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElementChain.java index 87218270..2168e925 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElementChain.java +++ b/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElementChain.java @@ -97,47 +97,51 @@ public interface IStructureElementChain extends IStructureElement { @Override default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s, EntityPlayerMP actor, Consumer chatter) { - boolean haveSkip = false; + boolean allContinue = true; List bufferedNoise = new ArrayList<>(); for (IStructureElement fallback : fallbacks()) { PlaceResult result = fallback.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, bufferedNoise::add); switch (result) { + case REJECT_CONTINUE: + break; case REJECT: + allContinue = false; break; case SKIP: - haveSkip = true; - break; + bufferedNoise.forEach(chatter); + return PlaceResult.SKIP; default: return result; } } // dump all that noise back into upstream bufferedNoise.forEach(chatter); - // TODO need reconsider to ensure this is the right course of action - return haveSkip ? PlaceResult.SKIP : PlaceResult.REJECT; + return allContinue ? PlaceResult.REJECT_CONTINUE : PlaceResult.REJECT; } @Override default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) { - boolean haveSkip = false; + boolean allContinue = true; List bufferedNoise = new ArrayList<>(); for (IStructureElement fallback : fallbacks()) { PlaceResult result = fallback .survivalPlaceBlock(t, world, x, y, z, trigger, env.withChatter(bufferedNoise::add)); switch (result) { + case REJECT_CONTINUE: + break; case REJECT: + allContinue = false; break; case SKIP: - haveSkip = true; - break; + bufferedNoise.forEach(env.getChatter()); + return PlaceResult.SKIP; default: return result; } } // dump all that noise back into upstream bufferedNoise.forEach(env.getChatter()); - // TODO need reconsider to ensure this is the right course of action - return haveSkip ? PlaceResult.SKIP : PlaceResult.REJECT; + return allContinue ? PlaceResult.REJECT_CONTINUE : PlaceResult.REJECT; } } diff --git a/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElementCheckOnly.java b/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElementCheckOnly.java index ee8144a5..7465903e 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElementCheckOnly.java +++ b/src/main/java/com/gtnewhorizon/structurelib/structure/IStructureElementCheckOnly.java @@ -27,12 +27,12 @@ public interface IStructureElementCheckOnly extends IStructureElement { @Override default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s, EntityPlayerMP actor, Consumer chatter) { - return PlaceResult.SKIP; + return PlaceResult.REJECT_CONTINUE; } @Override default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) { - return PlaceResult.SKIP; + return PlaceResult.REJECT_CONTINUE; } } diff --git a/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java b/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java index f4832571..fe50c197 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java +++ b/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java @@ -791,7 +791,7 @@ public class StructureUtility { public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) { Pair hint = getHint(trigger); - if (hint == null) return PlaceResult.REJECT; // TODO or SKIP? + if (hint == null) return PlaceResult.REJECT; Block block = world.getBlock(x, y, z); int meta = world.getBlockMetadata(x, y, z); TIER tier = tierExtractor.convert(block, meta); @@ -2032,11 +2032,11 @@ public class StructureUtility { /** * Enable this structure element only if given predicate returns true. *

- * Return SKIP when survival auto place if given predicate returns false. + * Return REJECT_CONTINUE when survival auto place if given predicate returns false. */ public static IStructureElement onlyIf(Predicate predicate, IStructureElement downstream) { - return onlyIf(predicate, downstream, PlaceResult.SKIP); + return onlyIf(predicate, downstream, PlaceResult.REJECT_CONTINUE); } /** @@ -2111,10 +2111,10 @@ public class StructureUtility { * using {@link #isAir()}. It will not attempt to capture any errors though, so next one will not be tried if * previous one would crash. *

- * (*): For survival auto place, it will * REJECT, if all structure element REJECT * SKIP, if 1 or more structure - * element SKIP and the rest structure element (0 or more) REJECT * any other result, **immediately** upon any - * structure element returns these other results. This behavior is not 100% fixed and might change later on, but we - * will send the notice on a best effort basis. + * (*): For survival auto place, it will: REJECT, if any structure element returns REJECT (and none returned ACCEPT, + * STOP, ACCEPT_STOP, or SKIP); REJECT_CONTINUE, if all structure elements return REJECT_CONTINUE (none returned + * REJECT); SKIP, as soon as any structure element returns SKIP; any other result, immediately upon any structure + * element returning those. *

* Take care while chaining, as it will try to call every structure element until it returns true. If none does it * will finally return false. diff --git a/src/main/java/com/gtnewhorizon/structurelib/structure/SurvivalBuildStructureWalker.java b/src/main/java/com/gtnewhorizon/structurelib/structure/SurvivalBuildStructureWalker.java index 02b61922..79f06f5c 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/structure/SurvivalBuildStructureWalker.java +++ b/src/main/java/com/gtnewhorizon/structurelib/structure/SurvivalBuildStructureWalker.java @@ -43,9 +43,10 @@ class SurvivalBuildStructureWalker implements IStructureWalker { env.offsetABC[2] = c; env.setSource(params.getSource()); PlaceResult placeResult = element.survivalPlaceBlock(object, world, x, y, z, trigger, env); - if (placeResult != PlaceResult.SKIP && built == -1) built = 0; + if (placeResult != PlaceResult.SKIP && placeResult != PlaceResult.REJECT_CONTINUE && built == -1) built = 0; switch (placeResult) { case SKIP: + case REJECT_CONTINUE: return true; case ACCEPT: if (check) element.check(object, world, x, y, z);