From 320db39675a64217c516f50e0beb747f5731c942 Mon Sep 17 00:00:00 2001 From: gdavid04 Date: Thu, 28 Oct 2021 00:18:18 +0200 Subject: [PATCH 1/5] Inline Error Catcher --- .../vazkii/psi/api/spell/CompiledSpell.java | 55 +++++----------- .../vazkii/psi/api/spell/EnumPieceType.java | 3 +- .../vazkii/psi/api/spell/IErrorCatcher.java | 57 ---------------- .../vazkii/psi/api/spell/SpellMetadata.java | 3 + .../psi/api/spell/SpellRuntimeException.java | 2 + .../psi/api/spell/param/ParamError.java | 28 ++++++++ .../api/spell/piece/PieceErrorHandler.java | 66 ------------------- .../psi/api/spell/piece/PieceOperator.java | 2 +- .../psi/common/core/helpers/SpellHelpers.java | 25 +++++++ .../psi/common/spell/SpellCompiler.java | 55 +--------------- .../common/spell/other/PieceErrorCatch.java | 54 +++++++++------ 11 files changed, 113 insertions(+), 237 deletions(-) delete mode 100644 src/main/java/vazkii/psi/api/spell/IErrorCatcher.java create mode 100644 src/main/java/vazkii/psi/api/spell/param/ParamError.java delete mode 100644 src/main/java/vazkii/psi/api/spell/piece/PieceErrorHandler.java diff --git a/src/main/java/vazkii/psi/api/spell/CompiledSpell.java b/src/main/java/vazkii/psi/api/spell/CompiledSpell.java index 2d5c129a8..288e90276 100644 --- a/src/main/java/vazkii/psi/api/spell/CompiledSpell.java +++ b/src/main/java/vazkii/psi/api/spell/CompiledSpell.java @@ -15,6 +15,7 @@ import vazkii.psi.api.PsiAPI; import vazkii.psi.api.internal.IPlayerData; +import vazkii.psi.api.spell.param.ParamError; import vazkii.psi.common.network.MessageRegister; import vazkii.psi.common.network.message.MessageSpellError; @@ -31,10 +32,8 @@ public class CompiledSpell { public final SpellMetadata metadata = new SpellMetadata(); public final Stack actions = new Stack<>(); - public final Map errorHandlers = new HashMap<>(); public final Map actionMap = new HashMap<>(); - public Action currentAction; public final boolean[][] spotsEvaluated; public CompiledSpell(Spell source) { @@ -52,14 +51,11 @@ public boolean execute(SpellContext context) throws SpellRuntimeException { IPlayerData data = PsiAPI.internalHandler.getDataForPlayer(context.caster); while (!context.actions.isEmpty()) { Action a = context.actions.pop(); - currentAction = a; PsiAPI.internalHandler.setCrashData(this, a.piece); a.execute(data, context); PsiAPI.internalHandler.setCrashData(null, null); - currentAction = null; - if (context.stopped) { return false; } @@ -93,9 +89,7 @@ public void safeExecute(SpellContext context) { if (!context.shouldSuppressErrors()) { context.caster.sendMessage(new TranslationTextComponent(e.getMessage()).setStyle(Style.EMPTY.setFormatting(TextFormatting.RED)), Util.DUMMY_UUID); - int x = context.cspell.currentAction.piece.x + 1; - int y = context.cspell.currentAction.piece.y + 1; - MessageSpellError message = new MessageSpellError("psi.spellerror.position", x, y); + MessageSpellError message = new MessageSpellError("psi.spellerror.position", e.x + 1, e.y + 1); MessageRegister.sendToPlayer(message, context.caster); } } @@ -119,6 +113,15 @@ public Action(SpellPiece piece) { public void execute(IPlayerData data, SpellContext context) throws SpellRuntimeException { try { + for (SpellParam param : piece.paramSides.keySet()) { + if (!(param instanceof ParamError)) { + Object v = piece.getRawParamValue(context, param); + if (v instanceof SpellRuntimeException) { + throw (SpellRuntimeException) v; + } + } + } + data.markPieceExecuted(piece); Object o = piece.execute(context); @@ -127,40 +130,16 @@ public void execute(IPlayerData data, SpellContext context) throws SpellRuntimeE context.evaluatedObjects[piece.x][piece.y] = o; } } catch (SpellRuntimeException exception) { - if (errorHandlers.containsKey(piece)) { - if (!errorHandlers.get(piece).suppress(piece, context, exception)) { - throw exception; - } - return; + exception.x = piece.x; + exception.y = piece.y; + if (metadata.errorSuppressed[piece.x][piece.y]) { + context.evaluatedObjects[piece.x][piece.y] = exception; + } else { + throw exception; } - throw exception; } } } - public class CatchHandler { - - public final SpellPiece handlerPiece; - public final IErrorCatcher handler; - - public CatchHandler(SpellPiece handlerPiece) { - this.handlerPiece = handlerPiece; - this.handler = (IErrorCatcher) handlerPiece; - } - - public boolean suppress(SpellPiece piece, SpellContext context, SpellRuntimeException exception) { - boolean handled = handler.catchException(piece, context, exception); - if (handled) { - Class eval = piece.getEvaluationType(); - if (eval != null && eval != Void.class) { - context.evaluatedObjects[piece.x][piece.y] = - handler.supplyReplacementValue(piece, context, exception); - } - } - - return handled; - } - } - } diff --git a/src/main/java/vazkii/psi/api/spell/EnumPieceType.java b/src/main/java/vazkii/psi/api/spell/EnumPieceType.java index 633d9ef3f..08be5db4f 100644 --- a/src/main/java/vazkii/psi/api/spell/EnumPieceType.java +++ b/src/main/java/vazkii/psi/api/spell/EnumPieceType.java @@ -18,8 +18,7 @@ public enum EnumPieceType { CONSTANT, CONNECTOR, MODIFIER, // eg: Error Suppressor - TRICK, - ERROR_HANDLER; + TRICK; public boolean isTrick() { return this == TRICK || this == MODIFIER; diff --git a/src/main/java/vazkii/psi/api/spell/IErrorCatcher.java b/src/main/java/vazkii/psi/api/spell/IErrorCatcher.java deleted file mode 100644 index 829d08d1c..000000000 --- a/src/main/java/vazkii/psi/api/spell/IErrorCatcher.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This class is distributed as part of the Psi Mod. - * Get the Source Code in github: - * https://github.com/Vazkii/Psi - * - * Psi is Open Source and distributed under the - * Psi License: https://psi.vazkii.net/license.php - */ -package vazkii.psi.api.spell; - -import javax.annotation.Nonnull; - -/** - * Interface for a SpellPiece that can catch exceptions of pieces it's attached to. - * Pieces implementing this should be of type {@link EnumPieceType#ERROR_HANDLER}. - */ -public interface IErrorCatcher { - - /** - * Handles the exception thrown by the piece. If false is returned, the exception will be rethrown. - * Please set the result value to a default if you catch an exception, to prevent NullPointerExceptions. - *

- * Unlike other spell-related methods, this method should not throw SpellRuntimeExceptions. - * It should either ensure it can handle the error, or return false. - * - * @param errorPiece The piece which is throwing the exception. - * @param context The erroring context. - * @param exception The exception. - * @return Whether to suppress the exception. - */ - boolean catchException(SpellPiece errorPiece, SpellContext context, SpellRuntimeException exception); - - /** - * Set the result value to a default if you catch an exception, to prevent NullPointerExceptions. - * This is only called if catchException returns true, and the piece has a return type. - * The returned value's type should match that of the piece it's handling. - *

- * Unlike other spell-related methods, this method should not throw SpellRuntimeExceptions. - * It should ensure it can handle the error in - * {@link #catchException(SpellPiece, SpellContext, SpellRuntimeException)}. - * - * @param errorPiece The piece which is throwing the exception. - * @param context The erroring context. - * @param exception The exception. - * @return Whether to suppress the exception. - */ - @Nonnull - Object supplyReplacementValue(SpellPiece errorPiece, SpellContext context, SpellRuntimeException exception); - - /** - * Selects which params are handled error sources and which are executed inputs. - * - * @return true if param is a handled error source - */ - boolean catchParam(SpellParam param); - -} diff --git a/src/main/java/vazkii/psi/api/spell/SpellMetadata.java b/src/main/java/vazkii/psi/api/spell/SpellMetadata.java index 359abf529..4a2b8a53f 100644 --- a/src/main/java/vazkii/psi/api/spell/SpellMetadata.java +++ b/src/main/java/vazkii/psi/api/spell/SpellMetadata.java @@ -28,12 +28,15 @@ public final class SpellMetadata { * Should errors from this spell not be sent to the player's chat? */ public boolean errorsSuppressed = false; + public final boolean[][] errorSuppressed; public SpellMetadata() { for (EnumSpellStat stat : EnumSpellStat.class.getEnumConstants()) { stats.put(stat, 0); statMultipliers.put(stat, 1.0); } + + errorSuppressed = new boolean[SpellGrid.GRID_SIZE][SpellGrid.GRID_SIZE]; } /** diff --git a/src/main/java/vazkii/psi/api/spell/SpellRuntimeException.java b/src/main/java/vazkii/psi/api/spell/SpellRuntimeException.java index c7cc7b8d9..ea894525d 100644 --- a/src/main/java/vazkii/psi/api/spell/SpellRuntimeException.java +++ b/src/main/java/vazkii/psi/api/spell/SpellRuntimeException.java @@ -37,6 +37,8 @@ public class SpellRuntimeException extends Exception { public static final String COMPARATOR = "psi.spellerror.comparator"; public static final String NAN = "psi.spellerror.nan"; + public int x, y; + public SpellRuntimeException(String s) { super(s); } diff --git a/src/main/java/vazkii/psi/api/spell/param/ParamError.java b/src/main/java/vazkii/psi/api/spell/param/ParamError.java new file mode 100644 index 000000000..faf6b85e4 --- /dev/null +++ b/src/main/java/vazkii/psi/api/spell/param/ParamError.java @@ -0,0 +1,28 @@ +/* + * This class is distributed as part of the Psi Mod. + * Get the Source Code in github: + * https://github.com/Vazkii/Psi + * + * Psi is Open Source and distributed under the + * Psi License: https://psi.vazkii.net/license.php + */ +package vazkii.psi.api.spell.param; + +import vazkii.psi.api.spell.SpellParam; + +public class ParamError extends SpellParam { + + public ParamError(String name, int color, boolean canDisable) { + super(name, color, canDisable); + } + + public ParamError(String name, int color, boolean canDisable, ArrowType arrowType) { + super(name, color, canDisable, arrowType); + } + + @Override + public Class getRequiredType() { + return Any.class; + } + +} diff --git a/src/main/java/vazkii/psi/api/spell/piece/PieceErrorHandler.java b/src/main/java/vazkii/psi/api/spell/piece/PieceErrorHandler.java deleted file mode 100644 index 3b0ac2c97..000000000 --- a/src/main/java/vazkii/psi/api/spell/piece/PieceErrorHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This class is distributed as part of the Psi Mod. - * Get the Source Code in github: - * https://github.com/Vazkii/Psi - * - * Psi is Open Source and distributed under the - * Psi License: https://psi.vazkii.net/license.php - */ -package vazkii.psi.api.spell.piece; - -import vazkii.psi.api.spell.EnumPieceType; -import vazkii.psi.api.spell.EnumSpellStat; -import vazkii.psi.api.spell.IErrorCatcher; -import vazkii.psi.api.spell.Spell; -import vazkii.psi.api.spell.SpellCompilationException; -import vazkii.psi.api.spell.SpellContext; -import vazkii.psi.api.spell.SpellMetadata; -import vazkii.psi.api.spell.SpellParam; -import vazkii.psi.api.spell.SpellPiece; -import vazkii.psi.api.spell.param.ParamAny; - -public abstract class PieceErrorHandler extends SpellPiece implements IErrorCatcher { - - protected SpellParam piece; - - public PieceErrorHandler(Spell spell) { - super(spell); - } - - @Override - public EnumPieceType getPieceType() { - return EnumPieceType.ERROR_HANDLER; - } - - @Override - public void initParams() { - addParam(piece = new ParamAny(paramName(), SpellParam.BROWN, false)); - } - - @Override - public void addToMetadata(SpellMetadata meta) throws SpellCompilationException { - meta.addStat(EnumSpellStat.COMPLEXITY, 1); - } - - @Override - public Object evaluate() { - return null; - } - - @Override - public Object execute(SpellContext context) { - return null; - } - - @Override - public Class getEvaluationType() { - return Void.class; - } - - protected abstract String paramName(); - - @Override - public boolean catchParam(SpellParam param) { - return param == piece; - } -} diff --git a/src/main/java/vazkii/psi/api/spell/piece/PieceOperator.java b/src/main/java/vazkii/psi/api/spell/piece/PieceOperator.java index ff411311c..49f466f29 100644 --- a/src/main/java/vazkii/psi/api/spell/piece/PieceOperator.java +++ b/src/main/java/vazkii/psi/api/spell/piece/PieceOperator.java @@ -25,7 +25,7 @@ public PieceOperator(Spell spell) { @Override public EnumPieceType getPieceType() { - return EnumPieceType.SELECTOR; + return EnumPieceType.OPERATOR; } @Override diff --git a/src/main/java/vazkii/psi/common/core/helpers/SpellHelpers.java b/src/main/java/vazkii/psi/common/core/helpers/SpellHelpers.java index 37b7ffe4a..6558f57e4 100644 --- a/src/main/java/vazkii/psi/common/core/helpers/SpellHelpers.java +++ b/src/main/java/vazkii/psi/common/core/helpers/SpellHelpers.java @@ -8,6 +8,10 @@ */ package vazkii.psi.common.core.helpers; +import java.util.HashSet; +import java.util.Set; +import java.util.Map.Entry; + import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -17,6 +21,7 @@ import vazkii.psi.api.spell.SpellParam; import vazkii.psi.api.spell.SpellPiece; import vazkii.psi.api.spell.SpellRuntimeException; +import vazkii.psi.api.spell.SpellParam.Side; public class SpellHelpers { @@ -128,4 +133,24 @@ public static Vector3 checkPos(SpellPiece piece, SpellContext context, SpellPara return position; } + public static boolean isLoop(SpellPiece piece) { + return isLoop(piece, new HashSet<>()); + } + + public static boolean isLoop(SpellPiece piece, Set visited) { + if (piece == null) return false; + if (visited.contains(piece)) return true; + visited.add(piece); + for (Entry, Side> param : piece.paramSides.entrySet()) { + if (!param.getValue().isEnabled()) continue; + try { + SpellPiece other = piece.spell.grid.getPieceAtSideWithRedirections(piece.x, piece.y, param.getValue()); + if (isLoop(other, new HashSet<>(visited))) return true; + } catch (SpellCompilationException e) { + return true; + } + } + return false; + } + } diff --git a/src/main/java/vazkii/psi/common/spell/SpellCompiler.java b/src/main/java/vazkii/psi/common/spell/SpellCompiler.java index 65f54f879..66dd560e7 100644 --- a/src/main/java/vazkii/psi/common/spell/SpellCompiler.java +++ b/src/main/java/vazkii/psi/common/spell/SpellCompiler.java @@ -12,10 +12,8 @@ import vazkii.psi.api.spell.CompiledSpell; import vazkii.psi.api.spell.CompiledSpell.Action; -import vazkii.psi.api.spell.CompiledSpell.CatchHandler; import vazkii.psi.api.spell.EnumPieceType; import vazkii.psi.api.spell.EnumSpellStat; -import vazkii.psi.api.spell.IErrorCatcher; import vazkii.psi.api.spell.ISpellCompiler; import vazkii.psi.api.spell.Spell; import vazkii.psi.api.spell.SpellCompilationException; @@ -55,10 +53,6 @@ public CompiledSpell doCompile(Spell spell) throws SpellCompilationException { redirectionPieces.clear(); compiled = new CompiledSpell(spell); - for (SpellPiece piece : findPieces(EnumPieceType.ERROR_HANDLER::equals)) { - buildHandler(piece); - } - List tricks = findPieces(EnumPieceType::isTrick); if (tricks.isEmpty()) { throw new SpellCompilationException(SpellCompilationException.NO_TRICKS); @@ -97,16 +91,8 @@ public void buildPiece(SpellPiece piece, Set visited) throws SpellCo piece.addToMetadata(compiled.metadata); } - // error handler params must be evaluated before the handled piece - CatchHandler catchHandler = compiled.errorHandlers.get(piece); - if (catchHandler != null) { - buildPiece(catchHandler.handlerPiece, new HashSet<>(visited)); - } - EnumSet usedSides = EnumSet.noneOf(SpellParam.Side.class); - HashSet params = new HashSet<>(); - HashSet handledErrors = new HashSet<>(); for (SpellParam param : piece.paramSides.keySet()) { if (checkSideDisabled(param, piece, usedSides)) { continue; @@ -123,46 +109,7 @@ public void buildPiece(SpellPiece piece, Set visited) throws SpellCo throw new SpellCompilationException(SpellCompilationException.INVALID_PARAM, piece.x, piece.y); } - if (piece instanceof IErrorCatcher && ((IErrorCatcher) piece).catchParam(param)) { - handledErrors.add(pieceAt); - } else { - params.add(pieceAt); - } - } - for (SpellPiece pieceAt : params) { - HashSet visitedCopy = new HashSet<>(visited); - // error handler params can't depend on handled pieces - visitedCopy.addAll(handledErrors); - buildPiece(pieceAt, visitedCopy); - } - } - - public void buildHandler(SpellPiece piece) throws SpellCompilationException { - if (!(piece instanceof IErrorCatcher)) { - return; - } - IErrorCatcher errorCatcher = (IErrorCatcher) piece; - CompiledSpell.CatchHandler errorHandler = compiled.new CatchHandler(piece); - - EnumSet usedSides = EnumSet.noneOf(SpellParam.Side.class); - - for (SpellParam param : piece.paramSides.keySet()) { - if (!errorCatcher.catchParam(param) || checkSideDisabled(param, piece, usedSides)) { - continue; - } - - SpellParam.Side side = piece.paramSides.get(param); - - SpellPiece pieceAt = compiled.sourceSpell.grid.getPieceAtSideWithRedirections(piece.x, piece.y, side, this::buildRedirect); - - if (pieceAt == null) { - throw new SpellCompilationException(SpellCompilationException.NULL_PARAM, piece.x, piece.y); - } - if (!param.canAccept(pieceAt)) { - throw new SpellCompilationException(SpellCompilationException.INVALID_PARAM, piece.x, piece.y); - } - - compiled.errorHandlers.put(pieceAt, errorHandler); + buildPiece(pieceAt, new HashSet<>(visited)); } } diff --git a/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java b/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java index f908e66ff..01bee5a09 100644 --- a/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java +++ b/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java @@ -11,16 +11,19 @@ import vazkii.psi.api.spell.Spell; import vazkii.psi.api.spell.SpellCompilationException; import vazkii.psi.api.spell.SpellContext; +import vazkii.psi.api.spell.SpellMetadata; import vazkii.psi.api.spell.SpellParam; +import vazkii.psi.api.spell.SpellParam.Any; +import vazkii.psi.api.spell.SpellParam.Side; import vazkii.psi.api.spell.SpellPiece; import vazkii.psi.api.spell.SpellRuntimeException; import vazkii.psi.api.spell.param.ParamAny; -import vazkii.psi.api.spell.piece.PieceErrorHandler; +import vazkii.psi.api.spell.param.ParamError; +import vazkii.psi.api.spell.piece.PieceOperator; +import vazkii.psi.common.core.helpers.SpellHelpers; -import javax.annotation.Nonnull; - -public class PieceErrorCatch extends PieceErrorHandler { - SpellParam fallback; +public class PieceErrorCatch extends PieceOperator { + SpellParam target, fallback; public PieceErrorCatch(Spell spell) { super(spell); @@ -28,12 +31,12 @@ public PieceErrorCatch(Spell spell) { @Override public void initParams() { - super.initParams(); + addParam(target = new ParamError(SpellParam.GENERIC_NAME_TARGET, SpellParam.BROWN, false)); addParam(fallback = new ParamAny(SpellParam.PSI_PREFIX + "fallback", SpellParam.GRAY, false) { @Override public boolean canAccept(SpellPiece other) { try { - SpellParam.Side side = paramSides.get(piece); + SpellParam.Side side = paramSides.get(target); SpellPiece actualPiece = spell.grid.getPieceAtSideWithRedirections(x, y, side); return super.canAccept(other) && actualPiece.getEvaluationType().isAssignableFrom(other.getEvaluationType()); } catch (SpellCompilationException e) { @@ -44,24 +47,37 @@ public boolean canAccept(SpellPiece other) { } @Override - protected String paramName() { - return SpellParam.GENERIC_NAME_TARGET; + public void addToMetadata(SpellMetadata meta) throws SpellCompilationException { + super.addToMetadata(meta); + SpellPiece piece = spell.grid.getPieceAtSideWithRedirections(x, y, paramSides.get(target)); + if (piece != null) { + meta.errorSuppressed[piece.x][piece.y] = true; + } } @Override - public boolean catchException(SpellPiece errorPiece, SpellContext context, SpellRuntimeException exception) { - try { - SpellParam.Side side = paramSides.get(piece); - SpellPiece actualPiece = spell.grid.getPieceAtSideWithRedirections(x, y, side); - return errorPiece == actualPiece; - } catch (SpellCompilationException e) { - return false; + public Object execute(SpellContext context) throws SpellRuntimeException { + Object value = getRawParamValue(context, target); + if (value instanceof SpellRuntimeException) { + value = getRawParamValue(context, fallback); } + return value; } - @Nonnull @Override - public Object supplyReplacementValue(SpellPiece errorPiece, SpellContext context, SpellRuntimeException exception) { - return getRawParamValue(context, fallback); + public Class getEvaluationType() { + if (!isInGrid || paramSides.get(target) == Side.OFF) { + return Any.class; + } + SpellPiece piece; + try { + piece = spell.grid.getPieceAtSideWithRedirections(x, y, paramSides.get(target)); + if (piece == null || SpellHelpers.isLoop(this)) { + return Any.class; + } + return piece.getEvaluationType(); + } catch (SpellCompilationException e) { + return Any.class; + } } } From 52cdc38a451fa7892214b045b9f6f5b754473f5f Mon Sep 17 00:00:00 2001 From: gdavid04 Date: Thu, 28 Oct 2021 00:27:37 +0200 Subject: [PATCH 2/5] Fix error messages --- .../java/vazkii/psi/api/spell/CompiledSpell.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/vazkii/psi/api/spell/CompiledSpell.java b/src/main/java/vazkii/psi/api/spell/CompiledSpell.java index 288e90276..c66b4116c 100644 --- a/src/main/java/vazkii/psi/api/spell/CompiledSpell.java +++ b/src/main/java/vazkii/psi/api/spell/CompiledSpell.java @@ -112,16 +112,15 @@ public Action(SpellPiece piece) { } public void execute(IPlayerData data, SpellContext context) throws SpellRuntimeException { - try { - for (SpellParam param : piece.paramSides.keySet()) { - if (!(param instanceof ParamError)) { - Object v = piece.getRawParamValue(context, param); - if (v instanceof SpellRuntimeException) { - throw (SpellRuntimeException) v; - } + for (SpellParam param : piece.paramSides.keySet()) { + if (!(param instanceof ParamError)) { + Object v = piece.getRawParamValue(context, param); + if (v instanceof SpellRuntimeException) { + throw (SpellRuntimeException) v; } } - + } + try { data.markPieceExecuted(piece); Object o = piece.execute(context); From c85007d17bf382f64ee06a4e58983ccbc7aeab37 Mon Sep 17 00:00:00 2001 From: gdavid04 Date: Thu, 28 Oct 2021 00:34:27 +0200 Subject: [PATCH 3/5] Fix error suppression flag not being added correctly --- src/main/java/vazkii/psi/api/spell/SpellPiece.java | 8 ++++++++ src/main/java/vazkii/psi/common/spell/SpellCompiler.java | 9 +++++++++ .../vazkii/psi/common/spell/other/PieceErrorCatch.java | 3 +-- .../psi/common/spell/other/PieceErrorSuppressor.java | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/vazkii/psi/api/spell/SpellPiece.java b/src/main/java/vazkii/psi/api/spell/SpellPiece.java index 7a57b1526..e6181c870 100644 --- a/src/main/java/vazkii/psi/api/spell/SpellPiece.java +++ b/src/main/java/vazkii/psi/api/spell/SpellPiece.java @@ -135,6 +135,14 @@ public void addToMetadata(SpellMetadata meta) throws SpellCompilationException { // NO-OP } + /** + * Adds this piece's stats to the Spell's metadata. + * Also called on pieces not referenced anywhere in the spell. + */ + public void addModifierToMetadata(SpellMetadata meta) throws SpellCompilationException { + // NO-OP + } + /** * Adds a {@link SpellParam} to this piece. */ diff --git a/src/main/java/vazkii/psi/common/spell/SpellCompiler.java b/src/main/java/vazkii/psi/common/spell/SpellCompiler.java index 66dd560e7..2de550ccc 100644 --- a/src/main/java/vazkii/psi/common/spell/SpellCompiler.java +++ b/src/main/java/vazkii/psi/common/spell/SpellCompiler.java @@ -53,6 +53,15 @@ public CompiledSpell doCompile(Spell spell) throws SpellCompilationException { redirectionPieces.clear(); compiled = new CompiledSpell(spell); + for (int i = 0; i < SpellGrid.GRID_SIZE; i++) { + for (int j = 0; j < SpellGrid.GRID_SIZE; j++) { + SpellPiece piece = compiled.sourceSpell.grid.gridData[j][i]; + if (piece != null) { + piece.addModifierToMetadata(compiled.metadata); + } + } + } + List tricks = findPieces(EnumPieceType::isTrick); if (tricks.isEmpty()) { throw new SpellCompilationException(SpellCompilationException.NO_TRICKS); diff --git a/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java b/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java index 01bee5a09..f53ab2f89 100644 --- a/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java +++ b/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java @@ -47,8 +47,7 @@ public boolean canAccept(SpellPiece other) { } @Override - public void addToMetadata(SpellMetadata meta) throws SpellCompilationException { - super.addToMetadata(meta); + public void addModifierToMetadata(SpellMetadata meta) throws SpellCompilationException { SpellPiece piece = spell.grid.getPieceAtSideWithRedirections(x, y, paramSides.get(target)); if (piece != null) { meta.errorSuppressed[piece.x][piece.y] = true; diff --git a/src/main/java/vazkii/psi/common/spell/other/PieceErrorSuppressor.java b/src/main/java/vazkii/psi/common/spell/other/PieceErrorSuppressor.java index d0099bea1..b414fea71 100644 --- a/src/main/java/vazkii/psi/common/spell/other/PieceErrorSuppressor.java +++ b/src/main/java/vazkii/psi/common/spell/other/PieceErrorSuppressor.java @@ -26,7 +26,7 @@ public String getSortingName() { } @Override - public void addToMetadata(SpellMetadata meta) { + public void addModifierToMetadata(SpellMetadata meta) { meta.errorsSuppressed = true; } From 70f5df512fb8a786b079b7c2f2d7e1ce9f98b73c Mon Sep 17 00:00:00 2001 From: gdavid04 Date: Thu, 28 Oct 2021 11:55:58 +0200 Subject: [PATCH 4/5] Dependent evaluation type cleanup --- .../java/vazkii/psi/api/spell/SpellPiece.java | 8 ++++++ .../psi/common/core/helpers/SpellHelpers.java | 25 ------------------- .../common/spell/other/PieceErrorCatch.java | 23 ++++++++++++----- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/main/java/vazkii/psi/api/spell/SpellPiece.java b/src/main/java/vazkii/psi/api/spell/SpellPiece.java index e6181c870..156dff320 100644 --- a/src/main/java/vazkii/psi/api/spell/SpellPiece.java +++ b/src/main/java/vazkii/psi/api/spell/SpellPiece.java @@ -99,6 +99,14 @@ public void initParams() { */ public abstract Class getEvaluationType(); + /** + * Gets what type this piece evaluates as. Use for parameter dependent evaluation + * types to avoid infinite loops. Only called for pieces in a spell grid. + */ + public Class getEvaluationType(Set visited) { + return getEvaluationType(); + } + /** * Evaluates this piece for the purpose of spell metadata calculation. If the piece * is not a constant, you can safely return null. diff --git a/src/main/java/vazkii/psi/common/core/helpers/SpellHelpers.java b/src/main/java/vazkii/psi/common/core/helpers/SpellHelpers.java index 6558f57e4..37b7ffe4a 100644 --- a/src/main/java/vazkii/psi/common/core/helpers/SpellHelpers.java +++ b/src/main/java/vazkii/psi/common/core/helpers/SpellHelpers.java @@ -8,10 +8,6 @@ */ package vazkii.psi.common.core.helpers; -import java.util.HashSet; -import java.util.Set; -import java.util.Map.Entry; - import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -21,7 +17,6 @@ import vazkii.psi.api.spell.SpellParam; import vazkii.psi.api.spell.SpellPiece; import vazkii.psi.api.spell.SpellRuntimeException; -import vazkii.psi.api.spell.SpellParam.Side; public class SpellHelpers { @@ -133,24 +128,4 @@ public static Vector3 checkPos(SpellPiece piece, SpellContext context, SpellPara return position; } - public static boolean isLoop(SpellPiece piece) { - return isLoop(piece, new HashSet<>()); - } - - public static boolean isLoop(SpellPiece piece, Set visited) { - if (piece == null) return false; - if (visited.contains(piece)) return true; - visited.add(piece); - for (Entry, Side> param : piece.paramSides.entrySet()) { - if (!param.getValue().isEnabled()) continue; - try { - SpellPiece other = piece.spell.grid.getPieceAtSideWithRedirections(piece.x, piece.y, param.getValue()); - if (isLoop(other, new HashSet<>(visited))) return true; - } catch (SpellCompilationException e) { - return true; - } - } - return false; - } - } diff --git a/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java b/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java index f53ab2f89..633944410 100644 --- a/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java +++ b/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java @@ -8,6 +8,9 @@ */ package vazkii.psi.common.spell.other; +import java.util.HashSet; +import java.util.Set; + import vazkii.psi.api.spell.Spell; import vazkii.psi.api.spell.SpellCompilationException; import vazkii.psi.api.spell.SpellContext; @@ -20,7 +23,6 @@ import vazkii.psi.api.spell.param.ParamAny; import vazkii.psi.api.spell.param.ParamError; import vazkii.psi.api.spell.piece.PieceOperator; -import vazkii.psi.common.core.helpers.SpellHelpers; public class PieceErrorCatch extends PieceOperator { SpellParam target, fallback; @@ -65,18 +67,27 @@ public Object execute(SpellContext context) throws SpellRuntimeException { @Override public Class getEvaluationType() { - if (!isInGrid || paramSides.get(target) == Side.OFF) { + if (isInGrid && paramSides.get(target) != Side.OFF) { + return getEvaluationType(new HashSet<>()); + } + return Any.class; + } + + @Override + public Class getEvaluationType(Set visited) { + if (visited.contains(this)) { return Any.class; } - SpellPiece piece; + visited.add(this); try { - piece = spell.grid.getPieceAtSideWithRedirections(x, y, paramSides.get(target)); - if (piece == null || SpellHelpers.isLoop(this)) { + SpellPiece piece = spell.grid.getPieceAtSideWithRedirections(x, y, paramSides.get(target)); + if (piece == null) { return Any.class; } - return piece.getEvaluationType(); + return piece.getEvaluationType(visited); } catch (SpellCompilationException e) { return Any.class; } } + } From a470a777137d65f42204507ecfd4de4ed3690ed2 Mon Sep 17 00:00:00 2001 From: gdavid04 Date: Thu, 28 Oct 2021 12:20:55 +0200 Subject: [PATCH 5/5] Run spotless --- .../java/vazkii/psi/common/spell/other/PieceErrorCatch.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java b/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java index 633944410..d482b6b1a 100644 --- a/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java +++ b/src/main/java/vazkii/psi/common/spell/other/PieceErrorCatch.java @@ -8,9 +8,6 @@ */ package vazkii.psi.common.spell.other; -import java.util.HashSet; -import java.util.Set; - import vazkii.psi.api.spell.Spell; import vazkii.psi.api.spell.SpellCompilationException; import vazkii.psi.api.spell.SpellContext; @@ -24,6 +21,9 @@ import vazkii.psi.api.spell.param.ParamError; import vazkii.psi.api.spell.piece.PieceOperator; +import java.util.HashSet; +import java.util.Set; + public class PieceErrorCatch extends PieceOperator { SpellParam target, fallback;