Skip to content

Commit bb808f2

Browse files
committed
Fix evaluator staff-type mishaps, and prevent evaluating patterns after catching a mishap
1 parent fe3f2ec commit bb808f2

File tree

5 files changed

+58
-28
lines changed

5 files changed

+58
-28
lines changed

CHANGELOG.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
88

99
### Changed
1010

11-
- A message is now displayed if attempting to use an Evaluator when not debugging, instead of silently failing.
11+
- A message is now displayed if attempting to use an Evaluator when not debugging, instead of silently failing.
12+
- Evaluators are now prevented from evaluating patterns after an Uncaught Mishap breakpoint is hit.
1213

1314
### Fixed
1415

15-
- The Evaluator was unable to cast any spells requiring media.
16-
- When debugging, spells requiring media would fail if a Debugger was not in the hand that the debug session was started with.
16+
- Evaluators were unable to cast any spells requiring media.
17+
- When debugging, spells requiring media would fail if a Debugger was not in the hand that the debug session was started with.
18+
- Evaluator mishaps were unintentionally caught by the Uncaught Mishaps option, and did not apply side effects to the stack.
1719

1820
## 0.2.0+1.20.1
1921

Common/src/main/kotlin/gay/object/hexdebug/adapter/DebugAdapter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ open class DebugAdapter(val player: ServerPlayer) : IDebugProtocolServer {
122122

123123
fun resetEvaluator() {
124124
setEvaluatorState(ItemEvaluator.EvalState.DEFAULT)
125-
debugger?.also {
126-
it.resetEvaluator()
125+
if (debugger?.resetEvaluator() == true) {
127126
sendStoppedEvent("step")
128127
}
129128
}

Common/src/main/kotlin/gay/object/hexdebug/debugger/Enums.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package gay.`object`.hexdebug.debugger
22

3-
enum class StopReason(val value: String) {
4-
STEP("step"),
5-
BREAKPOINT("breakpoint"),
6-
EXCEPTION("exception"),
7-
ENTRY("entry"),
8-
TERMINATED("terminated"),
3+
enum class StopReason(val value: String, val stopImmediately: Boolean) {
4+
STEP("step", false),
5+
BREAKPOINT("breakpoint", true),
6+
EXCEPTION("exception", true),
7+
STARTED("entry", true),
8+
TERMINATED("terminated", true),
99
}
1010

1111
enum class DebugStepType {

Common/src/main/kotlin/gay/object/hexdebug/debugger/HexDebugger.kt

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import at.petrak.hexcasting.api.casting.mishaps.Mishap
1313
import at.petrak.hexcasting.api.casting.mishaps.MishapInternalException
1414
import at.petrak.hexcasting.common.casting.PatternRegistryManifest
1515
import at.petrak.hexcasting.common.casting.actions.eval.OpEval
16+
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
1617
import gay.`object`.hexdebug.adapter.LaunchArgs
1718
import gay.`object`.hexdebug.casting.eval.FrameBreakpoint
1819
import gay.`object`.hexdebug.casting.eval.IDebugCastEnv
@@ -67,7 +68,9 @@ class HexDebugger(
6768

6869
val evaluatorUIPatterns = mutableListOf<ResolvedPattern>()
6970

70-
private var evaluatorResetData: Pair<SpellContinuation, CastingImage>? = null
71+
private var evaluatorResetData: EvaluatorResetData? = null
72+
73+
private var isAtCaughtMishap = false
7174

7275
private var lastResolutionType = ResolvedPatternType.UNRESOLVED
7376

@@ -379,29 +382,43 @@ class HexDebugger(
379382
* Use [DebugAdapter.evaluate][gay.object.hexdebug.adapter.DebugAdapter.evaluate] instead.
380383
*/
381384
internal fun evaluate(env: CastingEnvironment, list: SpellList): DebugStepResult {
385+
val vm = getVM(env)
386+
387+
if (isAtCaughtMishap) {
388+
// manually trigger the mishap sound
389+
// TODO: this feels scuffed.
390+
env.postExecution(
391+
CastResult(NullIota(), nextContinuation, null, listOf(), lastResolutionType, HexEvalSounds.MISHAP)
392+
)
393+
return DebugStepResult(StopReason.EXCEPTION, clientInfo = getClientView(vm))
394+
}
395+
382396
val startedEvaluating = evaluatorResetData == null
383397
if (startedEvaluating) {
384-
evaluatorResetData = Pair(nextContinuation, image)
398+
evaluatorResetData = EvaluatorResetData(nextContinuation, image, lastResolutionType, isAtCaughtMishap)
385399
}
400+
386401
nextContinuation = nextContinuation.pushFrame(FrameEvaluate(list, false))
387-
return executeNextDebugStep(getVM(env)).copy(startedEvaluating = startedEvaluating)
402+
return executeNextDebugStep(vm, doStaffMishaps = true).copy(startedEvaluating = startedEvaluating)
388403
}
389404

390405
/**
391406
* Use [DebugAdapter.resetEvaluator][gay.object.hexdebug.adapter.DebugAdapter.resetEvaluator] instead.
392407
*/
393-
internal fun resetEvaluator() {
394-
evaluatorResetData?.also { (continuation, image) ->
395-
nextContinuation = continuation
396-
this.image = image
397-
evaluatorResetData = null
408+
internal fun resetEvaluator() = (evaluatorResetData != null).also { _ ->
409+
evaluatorResetData?.also {
410+
nextContinuation = it.continuation
411+
image = it.image
412+
lastResolutionType = it.lastResolutionType
413+
isAtCaughtMishap = it.isAtCaughtMishap
398414
}
415+
evaluatorResetData = null
399416
evaluatorUIPatterns.clear()
400417
}
401418

402419
fun start(): DebugStepResult {
403420
return if (launchArgs.stopOnEntry) {
404-
DebugStepResult(StopReason.ENTRY)
421+
DebugStepResult(StopReason.STARTED)
405422
} else if (isAtBreakpoint()) {
406423
DebugStepResult(StopReason.BREAKPOINT)
407424
} else {
@@ -418,12 +435,11 @@ class HexDebugger(
418435
var hitBreakpoint = false
419436

420437
while (true) {
421-
val result = executeNextDebugStep(vm, exactlyOnce = true).let {
422-
if (it.isDone) return it
423-
lastResult?.plus(it) ?: it
424-
}
438+
val result = executeNextDebugStep(vm, exactlyOnce = true).let { lastResult?.plus(it) ?: it }
425439
lastResult = result
426440

441+
if (result.reason.stopImmediately) return result
442+
427443
if (isAtBreakpoint()) {
428444
hitBreakpoint = true
429445
}
@@ -466,7 +482,11 @@ class HexDebugger(
466482
fun executeOnce() = executeNextDebugStep(getVM())
467483

468484
// Copy of CastingVM.queueExecuteAndWrapIotas to allow stepping by one pattern at a time.
469-
private fun executeNextDebugStep(vm: CastingVM, exactlyOnce: Boolean = false): DebugStepResult {
485+
private fun executeNextDebugStep(
486+
vm: CastingVM,
487+
exactlyOnce: Boolean = false,
488+
doStaffMishaps: Boolean = false,
489+
): DebugStepResult {
470490
var stepResult = DebugStepResult(StopReason.STEP)
471491

472492
var continuation = nextContinuation // bind locally so we can do smart casting
@@ -496,13 +516,14 @@ class HexDebugger(
496516
// if something went wrong, push a breakpoint or stop immediately
497517
// and save the old image so we can see the stack BEFORE the mishap instead of after
498518
// TODO: maybe implement a way to see the stack at each call frame instead?
499-
val (newContinuation, preMishapImage) = if (castResult.resolutionType.success) {
519+
val (newContinuation, preMishapImage) = if (castResult.resolutionType.success || doStaffMishaps) {
500520
Pair(castResult.continuation, null)
501521
} else if (ExceptionBreakpointType.UNCAUGHT_MISHAPS in exceptionBreakpoints) {
522+
isAtCaughtMishap = true
502523
stepResult = stepResult.copy(reason = StopReason.EXCEPTION)
503524
Pair(castResult.continuation.pushFrame(FrameBreakpoint.fatal()), vm.image)
504525
} else {
505-
Pair(Done, vm.image)
526+
Pair(Done, null)
506527
}
507528

508529
// we use this when printing to the console, so this should happen BEFORE vm.env.postExecution (ie. for mishaps)
@@ -560,6 +581,7 @@ class HexDebugger(
560581
info.earlyExit = info.earlyExit || !castResult.resolutionType.success
561582

562583
// this needs to be after performSideEffects, since that's where mishaps mess with the stack
584+
// note: preMishapImage is only non-null if we actually encountered a mishap
563585
if (preMishapImage != null) vm.image = preMishapImage
564586

565587
if (exactlyOnce || shouldStopAtFrame(continuation)) {
@@ -738,6 +760,13 @@ class HexDebugger(
738760
}
739761
}
740762
}
763+
764+
data class EvaluatorResetData(
765+
val continuation: SpellContinuation,
766+
val image: CastingImage,
767+
val lastResolutionType: ResolvedPatternType,
768+
val isAtCaughtMishap: Boolean,
769+
)
741770
}
742771

743772
val SpellContinuation.frame get() = (this as? NotDone)?.frame

Common/src/main/kotlin/gay/object/hexdebug/items/ItemEvaluator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ItemEvaluator(properties: Properties) : ItemStaff(properties) {
2626
val itemStack = player.getItemInHand(hand)
2727

2828
if (world.isClientSide) {
29-
if (player.isShiftKeyDown) {
29+
if (player.isShiftKeyDown && evalState == EvalState.MODIFIED) {
3030
player.playSound(HexSounds.STAFF_RESET, 1f, 1f)
3131
}
3232
return InteractionResultHolder.success(itemStack)

0 commit comments

Comments
 (0)