WITH CATLIKE TREAD! UPON OUR PREY WE STEAL! IN SILENCE DREAD! OUR CAUTIOUS WAY WE FEEL! NO SOUND AT ALL! WE NEVER SPEAK A WORD! A FLY'S FOOTFALL WOULD BE DISTINCTLY HEARD!

This commit is contained in:
gamma-delta 2022-11-15 21:09:30 -06:00
parent 03dd09c6de
commit 9ca5738317
16 changed files with 135 additions and 100 deletions

View file

@ -115,9 +115,9 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
} }
public void applyScryingLensOverlay(List<Pair<ItemStack, Component>> lines, public void applyScryingLensOverlay(List<Pair<ItemStack, Component>> lines,
BlockState state, BlockPos pos, BlockState state, BlockPos pos,
Player observer, Level world, Player observer, Level world,
Direction hitFace) { Direction hitFace) {
if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) { if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) {
if (beai.getMedia() < 0) { if (beai.getMedia() < 0) {
lines.add(new Pair<>(new ItemStack(HexItems.AMETHYST_DUST), ItemCreativeUnlocker.infiniteMedia(world))); lines.add(new Pair<>(new ItemStack(HexItems.AMETHYST_DUST), ItemCreativeUnlocker.infiniteMedia(world)));
@ -286,7 +286,6 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
new SpellCircleContext(this.getBlockPos(), bounds, this.activatorAlwaysInRange())); new SpellCircleContext(this.getBlockPos(), bounds, this.activatorAlwaysInRange()));
var harness = new CastingHarness(ctx); var harness = new CastingHarness(ctx);
var makeSound = false;
BlockPos erroredPos = null; BlockPos erroredPos = null;
for (var tracked : this.trackedBlocks) { for (var tracked : this.trackedBlocks) {
var bs = this.level.getBlockState(tracked); var bs = this.level.getBlockState(tracked);
@ -294,9 +293,6 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
var newPattern = cc.getPattern(tracked, bs, this.level); var newPattern = cc.getPattern(tracked, bs, this.level);
if (newPattern != null) { if (newPattern != null) {
var info = harness.executeIota(new PatternIota(newPattern), splayer.getLevel()); var info = harness.executeIota(new PatternIota(newPattern), splayer.getLevel());
if (info.getMakesCastSound()) {
makeSound = true;
}
if (!info.getResolutionType().getSuccess()) { if (!info.getResolutionType().getSuccess()) {
erroredPos = tracked; erroredPos = tracked;
break; break;
@ -305,11 +301,6 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
} }
} }
if (makeSound) {
this.level.playSound(null, this.getBlockPos(), HexSounds.SPELL_CIRCLE_CAST, SoundSource.BLOCKS,
2f, 1f);
}
if (erroredPos != null) { if (erroredPos != null) {
this.sfx(erroredPos, false); this.sfx(erroredPos, false);
} else { } else {
@ -541,19 +532,22 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
@Override @Override
public boolean canPlaceItem(int index, ItemStack stack) { public boolean canPlaceItem(int index, ItemStack stack) {
if (remainingMediaCapacity() == 0) if (remainingMediaCapacity() == 0) {
return false; return false;
}
if (stack.is(HexItems.CREATIVE_UNLOCKER)) if (stack.is(HexItems.CREATIVE_UNLOCKER)) {
return true; return true;
}
var mediamount = extractMediaFromItem(stack, true); var mediamount = extractMediaFromItem(stack, true);
return mediamount > 0; return mediamount > 0;
} }
public int extractMediaFromItem(ItemStack stack, boolean simulate) { public int extractMediaFromItem(ItemStack stack, boolean simulate) {
if (this.media < 0) if (this.media < 0) {
return 0; return 0;
}
return MediaHelper.extractMedia(stack, remainingMediaCapacity(), true, simulate); return MediaHelper.extractMedia(stack, remainingMediaCapacity(), true, simulate);
} }
@ -576,8 +570,9 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
} }
public int remainingMediaCapacity() { public int remainingMediaCapacity() {
if (this.media < 0) if (this.media < 0) {
return 0; return 0;
}
return Math.max(0, MAX_CAPACITY - this.media); return Math.max(0, MAX_CAPACITY - this.media);
} }
} }

View file

@ -28,9 +28,18 @@ import kotlin.math.min
data class CastingContext( data class CastingContext(
val caster: ServerPlayer, val caster: ServerPlayer,
val castingHand: InteractionHand, val castingHand: InteractionHand,
val source: CastSource,
val spellCircle: SpellCircleContext? = null val spellCircle: SpellCircleContext? = null
) { ) {
constructor(caster: ServerPlayer, castingHand: InteractionHand) : this(caster, castingHand, null) constructor(caster: ServerPlayer, castingHand: InteractionHand, source: CastSource) : this(
caster,
castingHand,
source,
null
)
constructor(caster: ServerPlayer, castingHand: InteractionHand, spellCircleContext: SpellCircleContext) :
this(caster, castingHand, CastSource.SPELL_CIRCLE, spellCircleContext)
private var depth: Int = 0 private var depth: Int = 0
@ -223,7 +232,8 @@ data class CastingContext(
DiscoveryHandlers.addOperativeSlotDiscoverer { DiscoveryHandlers.addOperativeSlotDiscoverer {
val slots = mutableListOf<ItemStack>() val slots = mutableListOf<ItemStack>()
val anchorSlot = if (it.castingHand == InteractionHand.MAIN_HAND) (it.caster.inventory.selected + 1) % 9 else 0 val anchorSlot =
if (it.castingHand == InteractionHand.MAIN_HAND) (it.caster.inventory.selected + 1) % 9 else 0
slots.add(it.caster.getItemInHand(it.otherHand)) slots.add(it.caster.getItemInHand(it.otherHand))
for (delta in 0 until 9) { for (delta in 0 until 9) {
@ -234,4 +244,10 @@ data class CastingContext(
} }
} }
} }
enum class CastSource {
STAFF,
PACKAGED_HEX,
SPELL_CIRCLE,
}
} }

View file

@ -27,6 +27,8 @@ import net.minecraft.nbt.Tag
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.sounds.SoundSource
import net.minecraft.world.level.gameevent.GameEvent
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import kotlin.math.min import kotlin.math.min
@ -91,7 +93,7 @@ class CastingHarness private constructor(
// Initialize the continuation stack to a single top-level eval for all iotas. // Initialize the continuation stack to a single top-level eval for all iotas.
var continuation = SpellContinuation.Done.pushFrame(ContinuationFrame.Evaluate(SpellList.LList(0, iotas))) var continuation = SpellContinuation.Done.pushFrame(ContinuationFrame.Evaluate(SpellList.LList(0, iotas)))
// Begin aggregating info // Begin aggregating info
val info = TempControllerInfo(playSound = false, earlyExit = false) val info = TempControllerInfo(earlyExit = false)
var lastResolutionType = ResolvedPatternType.UNRESOLVED var lastResolutionType = ResolvedPatternType.UNRESOLVED
while (continuation is SpellContinuation.NotDone && !info.earlyExit) { while (continuation is SpellContinuation.NotDone && !info.earlyExit) {
// Take the top of the continuation stack... // Take the top of the continuation stack...
@ -111,7 +113,8 @@ class CastingHarness private constructor(
mishap, mishap,
Mishap.Context(pattern ?: HexPattern(HexDir.WEST), operator) Mishap.Context(pattern ?: HexPattern(HexDir.WEST), operator)
) )
) ),
EvalSound.MISHAP,
) )
} }
// Then write all pertinent data back to the harness for the next iteration. // Then write all pertinent data back to the harness for the next iteration.
@ -120,7 +123,7 @@ class CastingHarness private constructor(
} }
continuation = result.continuation continuation = result.continuation
lastResolutionType = result.resolutionType lastResolutionType = result.resolutionType
performSideEffects(info, result.sideEffects) performSideEffects(info, result.sideEffects, result.sound)
info.earlyExit = info.earlyExit || !lastResolutionType.success info.earlyExit = info.earlyExit || !lastResolutionType.success
} }
@ -132,7 +135,6 @@ class CastingHarness private constructor(
val (stackDescs, parenDescs, ravenmind) = generateDescs() val (stackDescs, parenDescs, ravenmind) = generateDescs()
return ControllerInfo( return ControllerInfo(
info.playSound,
this.stack.isEmpty() && this.parenCount == 0 && !this.escapeNext, this.stack.isEmpty() && this.parenCount == 0 && !this.escapeNext,
lastResolutionType, lastResolutionType,
stackDescs, stackDescs,
@ -145,7 +147,7 @@ class CastingHarness private constructor(
fun getUpdate(iota: Iota, world: ServerLevel, continuation: SpellContinuation): CastResult { fun getUpdate(iota: Iota, world: ServerLevel, continuation: SpellContinuation): CastResult {
try { try {
this.handleParentheses(iota)?.let { (data, resolutionType) -> this.handleParentheses(iota)?.let { (data, resolutionType) ->
return@getUpdate CastResult(continuation, data, resolutionType, listOf()) return@getUpdate CastResult(continuation, data, resolutionType, listOf(), EvalSound.GENERIC)
} }
return if (iota is PatternIota) { return if (iota is PatternIota) {
@ -161,6 +163,7 @@ class CastingHarness private constructor(
Mishap.Context(HexPattern(HexDir.WEST), null) Mishap.Context(HexPattern(HexDir.WEST), null)
) )
), ),
EvalSound.MISHAP
) )
} }
} catch (mishap: Mishap) { } catch (mishap: Mishap) {
@ -171,11 +174,16 @@ class CastingHarness private constructor(
listOf( listOf(
OperatorSideEffect.DoMishap( OperatorSideEffect.DoMishap(
mishap, mishap,
Mishap.Context((iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST), getOperatorForPattern(iota, world)) Mishap.Context(
(iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST),
getOperatorForPattern(iota, world)
)
) )
), ),
EvalSound.MISHAP
) )
} catch (exception: Exception) { } catch (exception: Exception) {
// This means something very bad has happened
exception.printStackTrace() exception.printStackTrace()
return CastResult( return CastResult(
continuation, continuation,
@ -184,9 +192,13 @@ class CastingHarness private constructor(
listOf( listOf(
OperatorSideEffect.DoMishap( OperatorSideEffect.DoMishap(
MishapError(exception), MishapError(exception),
Mishap.Context((iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST), getOperatorForPattern(iota, world)) Mishap.Context(
(iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST),
getOperatorForPattern(iota, world)
)
) )
) ),
EvalSound.MISHAP
) )
} }
} }
@ -260,11 +272,28 @@ class CastingHarness private constructor(
hereFd hereFd
} }
var soundType =
if (this.ctx.source == CastingContext.CastSource.STAFF) EvalSound.GENERIC else EvalSound.NONE;
for (se in sideEffects) {
if (se is OperatorSideEffect.AttemptSpell) {
if (se.hasCastingSound) {
soundType = soundType.greaterOf(EvalSound.SPELL_BOINK)
} else {
// WITH CATLIKE TREAD
// UPON OUR PREY WE STEAL
soundType = EvalSound.NONE
break
}
} else if (se is OperatorSideEffect.DoMishap) {
soundType = EvalSound.MISHAP
}
}
return CastResult( return CastResult(
cont2, cont2,
fd, fd,
ResolvedPatternType.EVALUATED, ResolvedPatternType.EVALUATED,
sideEffects, sideEffects,
soundType,
) )
} catch (mishap: Mishap) { } catch (mishap: Mishap) {
@ -273,19 +302,7 @@ class CastingHarness private constructor(
null, null,
mishap.resolutionType(ctx), mishap.resolutionType(ctx),
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, actionIdPair?.first))), listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, actionIdPair?.first))),
) EvalSound.MISHAP
} catch (exception: Exception) {
exception.printStackTrace()
return CastResult(
continuation,
null,
ResolvedPatternType.ERRORED,
listOf(
OperatorSideEffect.DoMishap(
MishapError(exception),
Mishap.Context(newPat, actionIdPair?.first)
)
)
) )
} }
} }
@ -293,19 +310,21 @@ class CastingHarness private constructor(
/** /**
* Execute the side effects of a pattern, updating our aggregated info. * Execute the side effects of a pattern, updating our aggregated info.
*/ */
fun performSideEffects(info: TempControllerInfo, sideEffects: List<OperatorSideEffect>) { fun performSideEffects(info: TempControllerInfo, sideEffects: List<OperatorSideEffect>, sound: EvalSound) {
for (haskellProgrammersShakingandCryingRN in sideEffects) { for (haskellProgrammersShakingandCryingRN in sideEffects) {
val mustStop = haskellProgrammersShakingandCryingRN.performEffect(this) val mustStop = haskellProgrammersShakingandCryingRN.performEffect(this)
if (mustStop) { if (mustStop) {
info.earlyExit = true info.earlyExit = true
break break
} }
}
if (haskellProgrammersShakingandCryingRN is OperatorSideEffect.AttemptSpell && sound.soundEvent()?.let {
haskellProgrammersShakingandCryingRN.hasCastingSound this.ctx.world.playSound(
) { null, this.ctx.position.x, this.ctx.position.y, this.ctx.position.z, it,
info.playSound = true SoundSource.PLAYERS, 1f, 1f
} )
// TODO: is it worth mixing in to the immut map and making our own game event with blackjack and hookers
this.ctx.world.gameEvent(this.ctx.caster, GameEvent.ITEM_INTERACT_FINISH, this.ctx.position)
} }
} }
@ -618,7 +637,6 @@ class CastingHarness private constructor(
} }
data class TempControllerInfo( data class TempControllerInfo(
var playSound: Boolean,
var earlyExit: Boolean, var earlyExit: Boolean,
) )
@ -627,5 +645,6 @@ class CastingHarness private constructor(
val newData: FunctionalData?, val newData: FunctionalData?,
val resolutionType: ResolvedPatternType, val resolutionType: ResolvedPatternType,
val sideEffects: List<OperatorSideEffect>, val sideEffects: List<OperatorSideEffect>,
val sound: EvalSound,
) )
} }

View file

@ -61,16 +61,16 @@ sealed interface ContinuationFrame {
harness: CastingHarness harness: CastingHarness
): CastResult { ): CastResult {
// If there are patterns left... // If there are patterns left...
if (list.nonEmpty) { return if (list.nonEmpty) {
val newCont = if (list.cdr.nonEmpty) { // yay TCO val newCont = if (list.cdr.nonEmpty) { // yay TCO
// ...enqueue the evaluation of the rest of the patterns... // ...enqueue the evaluation of the rest of the patterns...
continuation.pushFrame(Evaluate(list.cdr)) continuation.pushFrame(Evaluate(list.cdr))
} else continuation } else continuation
// ...before evaluating the first one in the list. // ...before evaluating the first one in the list.
return harness.getUpdate(list.car, level, newCont) harness.getUpdate(list.car, level, newCont)
} else { } else {
// If there are no patterns (e.g. empty Hermes), just return OK. // If there are no patterns (e.g. empty Hermes), just return OK.
return CastResult(continuation, null, ResolvedPatternType.EVALUATED, listOf()) CastResult(continuation, null, ResolvedPatternType.EVALUATED, listOf(), EvalSound.NONE)
} }
} }
@ -98,7 +98,8 @@ sealed interface ContinuationFrame {
continuation, continuation,
FunctionalData(harness.stack.toList(), 0, listOf(), false, harness.ravenmind), FunctionalData(harness.stack.toList(), 0, listOf(), false, harness.ravenmind),
ResolvedPatternType.EVALUATED, ResolvedPatternType.EVALUATED,
listOf() listOf(),
EvalSound.NONE,
) )
} }
@ -163,11 +164,13 @@ sealed interface ContinuationFrame {
} }
val tStack = stack.toMutableList() val tStack = stack.toMutableList()
tStack.add(stackTop) tStack.add(stackTop)
// TODO: this means we could have Thoth casting do a different sound
return CastResult( return CastResult(
newCont, newCont,
FunctionalData(tStack, 0, listOf(), false, harness.ravenmind), FunctionalData(tStack, 0, listOf(), false, harness.ravenmind),
ResolvedPatternType.EVALUATED, ResolvedPatternType.EVALUATED,
listOf() listOf(),
EvalSound.NONE,
) )
} }

View file

@ -6,7 +6,6 @@ import net.minecraft.nbt.CompoundTag
* Information for the sake of the GUI. * Information for the sake of the GUI.
*/ */
data class ControllerInfo( data class ControllerInfo(
val makesCastSound: Boolean,
val isStackClear: Boolean, val isStackClear: Boolean,
val resolutionType: ResolvedPatternType, val resolutionType: ResolvedPatternType,
val stack: List<CompoundTag>, val stack: List<CompoundTag>,
@ -14,3 +13,4 @@ data class ControllerInfo(
val ravenmind: CompoundTag?, val ravenmind: CompoundTag?,
val parenCount: Int, val parenCount: Int,
) )

View file

@ -0,0 +1,34 @@
package at.petrak.hexcasting.api.spell.casting
import at.petrak.hexcasting.common.lib.HexSounds
import net.minecraft.sounds.SoundEvent
/**
* Sound that plays as a side-effect-adjacent when casting
*/
enum class EvalSound {
/** Silence */
NONE,
/** The generic "bvwonh" sound for non-spell ops */
GENERIC,
/** The "bwoink!" for spell ops */
SPELL_BOINK,
/** The "gvwoh" for mishaps */
MISHAP;
/**
* Which sound type has the greater priority?
*/
fun greaterOf(that: EvalSound): EvalSound =
EvalSound.values()[maxOf(this.ordinal, that.ordinal)]
fun soundEvent(): SoundEvent? = when (this) {
NONE -> null
GENERIC -> HexSounds.ADD_PATTERN
SPELL_BOINK -> HexSounds.ACTUALLY_CAST
MISHAP -> HexSounds.FAIL_PATTERN
}
}

View file

@ -9,9 +9,7 @@ import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.mishaps.Mishap import at.petrak.hexcasting.api.spell.mishaps.Mishap
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.common.lib.HexItems import at.petrak.hexcasting.common.lib.HexItems
import at.petrak.hexcasting.common.lib.HexSounds
import net.minecraft.Util import net.minecraft.Util
import net.minecraft.sounds.SoundSource
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
@ -44,6 +42,7 @@ sealed class OperatorSideEffect {
this.spell.cast(harness.ctx) this.spell.cast(harness.ctx)
if (awardStat) if (awardStat)
harness.ctx.caster.awardStat(HexStatistics.SPELLS_CAST) harness.ctx.caster.awardStat(HexStatistics.SPELLS_CAST)
return false return false
} }
} }
@ -92,11 +91,6 @@ sealed class OperatorSideEffect {
) )
) )
harness.ctx.world.playSound(
null, harness.ctx.position.x, harness.ctx.position.y, harness.ctx.position.z,
HexSounds.FAIL_PATTERN, SoundSource.PLAYERS, 1f, 1f
)
mishap.execute(harness.ctx, errorCtx, harness.stack) mishap.execute(harness.ctx, errorCtx, harness.stack)
return true return true

View file

@ -65,22 +65,6 @@ class GuiSpellcasting constructor(
it.type = info.resolutionType it.type = info.resolutionType
} }
val mc = Minecraft.getInstance()
if (info.resolutionType.success) {
mc.soundManager.play(
SimpleSoundInstance(
HexSounds.ADD_PATTERN,
SoundSource.PLAYERS,
0.5f,
1f + (Math.random().toFloat() - 0.5f) * 0.1f,
randSrc,
this.ambianceSoundInstance!!.x,
this.ambianceSoundInstance!!.y,
this.ambianceSoundInstance!!.z,
)
)
}
this.cachedStack = info.stack this.cachedStack = info.stack
this.cachedParens = info.parenthesized this.cachedParens = info.parenthesized
this.cachedRavenmind = info.ravenmind this.cachedRavenmind = info.ravenmind

View file

@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.common.network.MsgBeepAck import at.petrak.hexcasting.common.network.MsgBeepAck
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument import net.minecraft.world.level.block.state.properties.NoteBlockInstrument
import net.minecraft.world.level.gameevent.GameEvent
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
object OpBeep : SpellAction { object OpBeep : SpellAction {
@ -33,6 +34,7 @@ object OpBeep : SpellAction {
private data class Spell(val target: Vec3, val note: Int, val instrument: NoteBlockInstrument) : RenderedSpell { private data class Spell(val target: Vec3, val note: Int, val instrument: NoteBlockInstrument) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
IXplatAbstractions.INSTANCE.sendPacketNear(target, 128.0, ctx.world, MsgBeepAck(target, note, instrument)) IXplatAbstractions.INSTANCE.sendPacketNear(target, 128.0, ctx.world, MsgBeepAck(target, note, instrument))
ctx.world.gameEvent(null, GameEvent.NOTE_BLOCK_PLAY, target)
} }
} }
} }

View file

@ -43,6 +43,7 @@ public class ItemStaff extends Item {
} }
player.awardStat(Stats.ITEM_USED.get(this)); player.awardStat(Stats.ITEM_USED.get(this));
// player.gameEvent(GameEvent.ITEM_INTERACT_START);
return InteractionResultHolder.success(player.getItemInHand(hand)); return InteractionResultHolder.success(player.getItemInHand(hand));
} }

View file

@ -6,14 +6,12 @@ import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.iota.Iota; import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.HexIotaTypes; import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexSounds;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stat; import net.minecraft.stats.Stat;
import net.minecraft.stats.Stats; import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
@ -108,7 +106,7 @@ public abstract class ItemPackagedHex extends ItemMediaHolder implements HexHold
return InteractionResultHolder.fail(stack); return InteractionResultHolder.fail(stack);
} }
var sPlayer = (ServerPlayer) player; var sPlayer = (ServerPlayer) player;
var ctx = new CastingContext(sPlayer, usedHand); var ctx = new CastingContext(sPlayer, usedHand, CastingContext.CastSource.PACKAGED_HEX);
var harness = new CastingHarness(ctx); var harness = new CastingHarness(ctx);
var info = harness.executeIotas(instrs, sPlayer.getLevel()); var info = harness.executeIotas(instrs, sPlayer.getLevel());
@ -123,11 +121,6 @@ public abstract class ItemPackagedHex extends ItemMediaHolder implements HexHold
player.awardStat(stat); player.awardStat(stat);
sPlayer.getCooldowns().addCooldown(this, 5); sPlayer.getCooldowns().addCooldown(this, 5);
if (info.getMakesCastSound()) {
sPlayer.level.playSound(null, sPlayer.getX(), sPlayer.getY(), sPlayer.getZ(),
HexSounds.ACTUALLY_CAST, SoundSource.PLAYERS, 1f,
1f + ((float) Math.random() - 0.5f) * 0.2f);
}
if (broken) { if (broken) {
stack.shrink(1); stack.shrink(1);

View file

@ -27,7 +27,6 @@ public record MsgNewSpellPatternAck(ControllerInfo info, int index) implements I
public static MsgNewSpellPatternAck deserialize(ByteBuf buffer) { public static MsgNewSpellPatternAck deserialize(ByteBuf buffer) {
var buf = new FriendlyByteBuf(buffer); var buf = new FriendlyByteBuf(buffer);
var wasSpellCast = buf.readBoolean();
var isStackEmpty = buf.readBoolean(); var isStackEmpty = buf.readBoolean();
var resolutionType = buf.readEnum(ResolvedPatternType.class); var resolutionType = buf.readEnum(ResolvedPatternType.class);
var index = buf.readInt(); var index = buf.readInt();
@ -39,13 +38,12 @@ public record MsgNewSpellPatternAck(ControllerInfo info, int index) implements I
var parenCount = buf.readVarInt(); var parenCount = buf.readVarInt();
return new MsgNewSpellPatternAck( return new MsgNewSpellPatternAck(
new ControllerInfo(wasSpellCast, isStackEmpty, resolutionType, stack, parens, raven, parenCount), index new ControllerInfo(isStackEmpty, resolutionType, stack, parens, raven, parenCount), index
); );
} }
@Override @Override
public void serialize(FriendlyByteBuf buf) { public void serialize(FriendlyByteBuf buf) {
buf.writeBoolean(this.info.getMakesCastSound());
buf.writeBoolean(this.info.isStackClear()); buf.writeBoolean(this.info.isStackClear());
buf.writeEnum(this.info.getResolutionType()); buf.writeEnum(this.info.getResolutionType());
buf.writeInt(this.index); buf.writeInt(this.index);

View file

@ -8,14 +8,12 @@ import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType;
import at.petrak.hexcasting.api.spell.iota.PatternIota; import at.petrak.hexcasting.api.spell.iota.PatternIota;
import at.petrak.hexcasting.api.spell.math.HexCoord; import at.petrak.hexcasting.api.spell.math.HexCoord;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexSounds;
import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.hexcasting.xplat.IXplatAbstractions;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import java.util.ArrayList; import java.util.ArrayList;
@ -62,6 +60,7 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
public void handle(MinecraftServer server, ServerPlayer sender) { public void handle(MinecraftServer server, ServerPlayer sender) {
server.execute(() -> { server.execute(() -> {
// TODO: should we maybe not put tons of logic in a packet class
var held = sender.getItemInHand(this.handUsed); var held = sender.getItemInHand(this.handUsed);
if (held.is(HexItemTags.STAVES)) { if (held.is(HexItemTags.STAVES)) {
boolean autoFail = false; boolean autoFail = false;
@ -87,16 +86,10 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
ControllerInfo clientInfo; ControllerInfo clientInfo;
if (autoFail) { if (autoFail) {
var descs = harness.generateDescs(); var descs = harness.generateDescs();
clientInfo = new ControllerInfo(false, harness.getStack().isEmpty(), ResolvedPatternType.INVALID, clientInfo = new ControllerInfo(harness.getStack().isEmpty(), ResolvedPatternType.INVALID,
descs.getFirst(), descs.getSecond(), descs.getThird(), harness.getParenCount()); descs.getFirst(), descs.getSecond(), descs.getThird(), harness.getParenCount());
} else { } else {
clientInfo = harness.executeIota(new PatternIota(this.pattern), sender.getLevel()); clientInfo = harness.executeIota(new PatternIota(this.pattern), sender.getLevel());
if (clientInfo.getMakesCastSound()) {
sender.level.playSound(null, sender.getX(), sender.getY(), sender.getZ(),
HexSounds.ACTUALLY_CAST, SoundSource.PLAYERS, 1f,
1f + ((float) Math.random() - 0.5f) * 0.2f);
}
} }
if (clientInfo.isStackClear()) { if (clientInfo.isStackClear()) {
@ -110,7 +103,8 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
IXplatAbstractions.INSTANCE.setPatterns(sender, resolvedPatterns); IXplatAbstractions.INSTANCE.setPatterns(sender, resolvedPatterns);
} }
IXplatAbstractions.INSTANCE.sendPacketToPlayer(sender, new MsgNewSpellPatternAck(clientInfo, resolvedPatterns.size() - 1)); IXplatAbstractions.INSTANCE.sendPacketToPlayer(sender,
new MsgNewSpellPatternAck(clientInfo, resolvedPatterns.size() - 1));
} }
}); });
} }

View file

@ -19,7 +19,7 @@ public class CCHarness implements Component {
} }
public CastingHarness getHarness(InteractionHand hand) { public CastingHarness getHarness(InteractionHand hand) {
var ctx = new CastingContext(this.owner, hand); var ctx = new CastingContext(this.owner, hand, CastingContext.CastSource.STAFF);
if (this.lazyLoadedTag.isEmpty()) { if (this.lazyLoadedTag.isEmpty()) {
return new CastingHarness(ctx); return new CastingHarness(ctx);
} else { } else {

View file

@ -424,7 +424,8 @@ public class FabricXplatImpl implements IXplatAbstractions {
@Override @Override
public boolean isBreakingAllowed(Level world, BlockPos pos, BlockState state, Player player) { public boolean isBreakingAllowed(Level world, BlockPos pos, BlockState state, Player player) {
return PlayerBlockBreakEvents.BEFORE.invoker().beforeBlockBreak(world, player, pos, state, world.getBlockEntity(pos)); return PlayerBlockBreakEvents.BEFORE.invoker()
.beforeBlockBreak(world, player, pos, state, world.getBlockEntity(pos));
} }
@Override @Override

View file

@ -232,7 +232,8 @@ public class ForgeXplatImpl implements IXplatAbstractions {
@Override @Override
public CastingHarness getHarness(ServerPlayer player, InteractionHand hand) { public CastingHarness getHarness(ServerPlayer player, InteractionHand hand) {
var ctx = new CastingContext(player, hand); // This is always from a staff because we don't need to load the harness when casting from item
var ctx = new CastingContext(player, hand, CastingContext.CastSource.STAFF);
return CastingHarness.fromNBT(player.getPersistentData().getCompound(TAG_HARNESS), ctx); return CastingHarness.fromNBT(player.getPersistentData().getCompound(TAG_HARNESS), ctx);
} }