Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Added a config toggle (default false) for the effect that makes iota-holding items display their entire NBT data when Advanced Tooltips is enabled ([#1021](https://github.com/FallingColors/HexMod/pull/1021)) @Robotgiggle
- Added a pattern display overlay for pattern-holding items (ie scrolls or slates) while holding shift in the inventory ([#879](https://github.com/FallingColors/HexMod/pull/879)) @SamsTheNerd
- Added connected textures for Akashic Ligatures when using Continuity or Optifine ([#885](https://github.com/FallingColors/HexMod/pull/885)) @kineticneticat
- Added Interjection, Meditation, and Recollection for advanced pattern-list creation ([#1103](https://github.com/FallingColors/HexMod/pull/1103)) @Robotgiggle
- Added Similarity Distillation and Dissimilarity Distillation for comparing iota types ([#1114](https://github.com/FallingColors/HexMod/pull/1114)) @IridescentVoid

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ interface Action {
*
* The userdata tag is copied for you, so you don't need to worry about mutation messing up things
* behind the scenes.
*
* Note that `image.parenCount` will always be 0 here - if it's greater, [operateInParens] is used instead.
*/
@Throws(Mishap::class)
fun operate(
Expand All @@ -51,8 +53,8 @@ interface Action {
* The behavior of this action when inside parentheses (meaning `image.parenCount` will always be greater than 0).
* By default, this just adds the pattern to the parenthesized list without updating the op count or performing any of its effects.
*
* Note that behavior defined here can throw mishaps as usual. However, mishapping here will not affect the paren count,
* so the caster will still be in list-building mode after the mishap resolves.
* Note that behavior defined here can throw mishaps as usual. However, mishapping here while staffcasting will not
* affect the paren count, so the caster will still be in list-building mode after the mishap resolves.
*/
@Throws(Mishap::class)
fun operateInParens(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,13 @@ data class CastingImage private constructor(
fun withResetEscape() = this.copy(parenCount = 0, parenthesized = listOf(), escapeNext = false)

/**
* Returns a copy of this with the provided iota added to the parenthesized list.
* Returns a copy of this with the provided iota added to the parenthesized list. `escaped` is used by
* [OpUndo][at.petrak.hexcasting.common.casting.actions.escaping.OpUndo] to determine whether undoing the
* parenthesized iota should adjust the paren count (escaped parens do not affect the count).
*/
fun withNewParenthesized(iota: Iota): CastingImage {
fun withNewParenthesized(iota: Iota, escaped: Boolean = false): CastingImage {
val newParens = this.parenthesized.toMutableList()
newParens.add(ParenthesizedIota(iota, false))
newParens.add(ParenthesizedIota(iota, escaped))
return this.copy(parenthesized = newParens)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,9 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) {
if (this.image.parenCount > 0) {
// if we're inside parentheses, add the iota to the list with escaped set to true
val newParens = this.image.parenthesized.toMutableList()
newParens.add(ParenthesizedIota(iota, true))
newImage = this.image.copy(
escapeNext = false,
parenthesized = newParens
)
escapeNext = false
).withNewParenthesized(iota, escaped = true)
} else {
// if we're not in parentheses, just push the iota to the stack
val newStack = this.image.stack.toMutableList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import net.minecraft.server.level.ServerLevel
/**
* A list of patterns to be evaluated in sequence.
* @property list the *remaining* list of patterns to be evaluated
* @property isMetacasting only for sound effects, if this is being cast from a hermes / iris
* @property isMetacasting if this is being cast from a meta-evaluation pattern
*/
data class FrameEvaluate(val list: SpellList, val isMetacasting: Boolean) : ContinuationFrame {
// Discard this frame and keep discarding frames.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ protected Iota(@NotNull IotaType<?> type, @NotNull Object payload) {
return new CastResult(
this,
continuation,
vm.getImage().withNewParenthesized(this),
vm.getImage().withNewParenthesized(this, false),
List.of(),
ResolvedPatternType.ESCAPED,
HexEvalSounds.NORMAL_EXECUTE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import at.petrak.hexcasting.api.casting.eval.*;
import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect;
import at.petrak.hexcasting.api.casting.eval.vm.CastingVM;
import at.petrak.hexcasting.api.casting.eval.vm.FrameEvaluate;
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.api.casting.mishaps.Mishap;
Expand Down Expand Up @@ -123,7 +124,7 @@ public boolean executable() {
return new CastResult(
this,
continuation,
vm.getImage().withNewParenthesized(this),
vm.getImage().withNewParenthesized(this, false),
List.of(),
ResolvedPatternType.ESCAPED,
HexEvalSounds.NORMAL_EXECUTE);
Expand Down Expand Up @@ -167,10 +168,16 @@ public boolean executable() {
result.getSound());

} catch (Mishap mishap) {
// If a mishap happens mid-parens at the top level (ie when staffcasting), keep any in-progress parens.
// If a mishap happens mid-parens while metacasting, wipe the parens - if we didn't do this, any open paren
// levels would remain open even though the metacast itself has mishapped and thus been aborted.
boolean wipeParens = continuation instanceof SpellContinuation.NotDone cnd
&& cnd.getFrame() instanceof FrameEvaluate frameEval
&& frameEval.isMetacasting();
return new CastResult(
this,
continuation,
null,
wipeParens ? vm.getImage().withResetEscape() : null,
List.of(new OperatorSideEffect.DoMishap(mishap, new Mishap.Context(this.getPattern(), castedName.get()))),
mishap.resolutionType(vm.getEnv()),
HexEvalSounds.MISHAP);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,8 @@ class GuiSpellcasting constructor(

// TODO this is the kinda hacky bit
if (info.resolutionType == ResolvedPatternType.UNDONE) {
// find the last escaped pattern (or the opening paren if there's nothing else) and set it to UNDONE
this.patterns.reversed().drop(1).firstOrNull {
it.type == ResolvedPatternType.ESCAPED ||
(it.type == ResolvedPatternType.EVALUATED && it.pattern.angles == HexActions.OPEN_PAREN.prototype.angles)
}?.let { it.type = ResolvedPatternType.UNDONE }
// find the last undo-able pattern and set its coloring to UNDONE
this.patterns.reversed().drop(1).firstOrNull { canBeUndone(it) }?.let { it.type = ResolvedPatternType.UNDONE }
// use the normal EVALUATED coloring for the Evanition that was just drawn
this.patterns.getOrNull(index)?.let { it.type = ResolvedPatternType.EVALUATED }
} else this.patterns.getOrNull(index)?.let {
Expand All @@ -88,6 +85,22 @@ class GuiSpellcasting constructor(
this.calculateIotaDisplays()
}

fun canBeUndone(resolvedPat: ResolvedPattern): Boolean {
return when (resolvedPat.type) {
// standard escaped patterns can always be undone
ResolvedPatternType.ESCAPED -> true
// everything else cannot be undone, with three exceptions:
// - unescaped Introspection and Meditation can be undone if there's nothing else left to undo
// - Interjection can always be undone (undoing its inserted iota) despite using the EVALUATED coloring
ResolvedPatternType.EVALUATED -> {
resolvedPat.pattern.angles == HexActions.OPEN_PAREN.prototype.angles ||
resolvedPat.pattern.angles == HexActions.OPEN_N_PARENS.prototype.angles ||
resolvedPat.pattern.angles == HexActions.READ_INTO_PARENS.prototype.angles
}
else -> false
}
}

fun calculateIotaDisplays() {
val mc = Minecraft.getInstance()
val width = (this.width * LHS_IOTAS_ALLOCATION).toInt()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package at.petrak.hexcasting.common.casting.actions.escaping

import at.petrak.hexcasting.api.casting.castables.Action
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.eval.OperationResult
import at.petrak.hexcasting.api.casting.eval.ParenthesizedOperationResult
import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.casting.iota.DoubleIota
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.iota.ListIota
import at.petrak.hexcasting.api.casting.mishaps.MishapNeedsParens
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds

object OpCloseAllParens : Action {
override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult {
throw MishapNeedsParens()
}

override fun operateInParens(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation, thisIota: Iota): ParenthesizedOperationResult {
val newStack = image.stack.toMutableList()
newStack.add(DoubleIota(image.parenCount.toDouble()))
newStack.add(ListIota(image.parenthesized.toList().map { it.iota }))
val image2 = image.copy(
stack = newStack,
parenCount = 0,
parenthesized = listOf()
)
return ParenthesizedOperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE, ResolvedPatternType.EVALUATED)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package at.petrak.hexcasting.common.casting.actions.escaping

import at.petrak.hexcasting.api.casting.castables.Action
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.eval.OperationResult
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.casting.getPositiveInt
import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds

object OpOpenNParens : Action {
override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult {
val newStack = image.stack.toMutableList()
val layers = newStack.getPositiveInt(newStack.lastIndex)
newStack.removeLast()
val image2 = image.copy(
stack = newStack,
parenCount = layers
)
return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE)
}

// Since there's no nice way to determine how many new layers it should open when drawn inside parens, we don't
// override operateInParens() at all. This pattern is just treated as any other pattern when parenthesized.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package at.petrak.hexcasting.common.casting.actions.escaping

import at.petrak.hexcasting.api.casting.castables.Action
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.eval.OperationResult
import at.petrak.hexcasting.api.casting.eval.ParenthesizedOperationResult
import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.api.casting.mishaps.MishapNeedsParens
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import at.petrak.hexcasting.xplat.IXplatAbstractions

object OpReadIntoParens : Action {
override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult {
throw MishapNeedsParens()
}

override fun operateInParens(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation, thisIota: Iota): ParenthesizedOperationResult {
val (handStack) = env.getHeldItemToOperateOn {
val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it)
dataHolder != null && (dataHolder.readIota(env.world) != null || dataHolder.emptyIota() != null)
} ?: env.getHeldItemToOperateOn {
// If there are no data holders that are readable, find a data holder that isn't readable
// so that the error message is more helpful.
val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it)
dataHolder != null
} ?: throw MishapBadOffhandItem.of(null, "iota.read")

val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack)
?: throw MishapBadOffhandItem.of(handStack, "iota.read")

val datum = datumHolder.readIota(env.world)
?: datumHolder.emptyIota()
?: throw MishapBadOffhandItem.of(handStack, "iota.read")

return ParenthesizedOperationResult(
image.withNewParenthesized(datum, escaped = true), // inserted parens should not adjust paren count
listOf(), continuation,
HexEvalSounds.NORMAL_EXECUTE,
ResolvedPatternType.EVALUATED
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ object OpUndo : Action {
val last = newParens.removeLastOrNull()
var newParenCount = image.parenCount
if (last == null) {
// if there was nothing in the parenthesized list, undo the initial open paren
newParenCount--
// If there was nothing in the parenthesized list, undo the initial open paren.
// This gets set to 0 rather than just decremented in case we started with open-n-parens.
newParenCount = 0
} else if (last.iota is PatternIota && !last.escaped) {
// adjust paren count if undoing a non-escaped open or close paren
when (last.iota.pattern.angles) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,12 @@ public class HexActions {
new ActionRegistryEntry(HexPattern.fromAngles("qqq", HexDir.WEST), OpOpenParen.INSTANCE));
public static final ActionRegistryEntry CLOSE_PAREN = make("close_paren",
new ActionRegistryEntry(HexPattern.fromAngles("eee", HexDir.EAST), OpCloseParen.INSTANCE));
public static final ActionRegistryEntry OPEN_N_PARENS = make("open_n_parens",
new ActionRegistryEntry(HexPattern.fromAngles("eqqqe", HexDir.SOUTH_WEST), OpOpenNParens.INSTANCE));
public static final ActionRegistryEntry CLOSE_ALL_PARENS = make("close_all_parens",
new ActionRegistryEntry(HexPattern.fromAngles("qeeeq", HexDir.SOUTH_EAST), OpCloseAllParens.INSTANCE));
public static final ActionRegistryEntry READ_INTO_PARENS = make("read_into_parens",
new ActionRegistryEntry(HexPattern.fromAngles("aqqqqqwded", HexDir.EAST), OpReadIntoParens.INSTANCE));
public static final ActionRegistryEntry UNDO = make("undo",
new ActionRegistryEntry(HexPattern.fromAngles("eeedw", HexDir.EAST), OpUndo.INSTANCE));

Expand Down
Loading
Loading