diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java index 2a9440d6..b282d928 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java @@ -2,7 +2,6 @@ package at.petrak.hexcasting.api.casting.eval; import at.petrak.hexcasting.api.casting.ParticleSpray; import at.petrak.hexcasting.api.casting.PatternShapeMatch; -import at.petrak.hexcasting.api.casting.eval.SpellCircleContext; import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound; import at.petrak.hexcasting.api.casting.mishaps.Mishap; import at.petrak.hexcasting.api.casting.mishaps.MishapDisallowedSpell; @@ -10,7 +9,6 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapEntityTooFarAway; import at.petrak.hexcasting.api.casting.mishaps.MishapLocationTooFarAway; import at.petrak.hexcasting.api.misc.FrozenColorizer; import at.petrak.hexcasting.api.mod.HexConfig; -import com.mojang.datafixers.util.Pair; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; @@ -50,23 +48,22 @@ public abstract class CastingEnvironment { * Get the caster. Might be null! *

* Implementations should NOT rely on this in general, use the methods on this class instead. - * This is mostly for things like mishaps. + * This is mostly for spells (flight, etc) */ @Nullable public abstract ServerPlayer getCaster(); + /** + * Get an interface used to do mishaps + */ + public abstract MishapEnvironment getMishapEnvironment(); + /** * Get the sound that this I/O module makes. *

*/ public abstract EvalSound getSoundType(); - /** - * Get the spell circle running this cast. Might be null if not casting from a spell circle! - */ - @Nullable - public abstract SpellCircleContext getSpellCircle(); - /** * If something about this ARE itself is invalid, mishap. *

@@ -134,9 +131,11 @@ public abstract class CastingEnvironment { throw new MishapLocationTooFarAway(vec, "too_far"); } } + public final void assertVecInRange(BlockPos vec) throws MishapLocationTooFarAway { - this.assertVecInRange(new Vec3(vec.x(), vec.y(), vec.z())); + this.assertVecInRange(new Vec3(vec.getX(), vec.getY(), vec.getZ())); } + public final boolean canEditBlockAt(BlockPos vec) { // TODO winfy: fill this in return false; @@ -200,9 +199,15 @@ public abstract class CastingEnvironment { } public static record HeldItemInfo(ItemStack stack, InteractionHand hand) { - public ItemStack component1() { return stack; } - public InteractionHand component2() { return hand; } + public ItemStack component1() { + return stack; + } + + public InteractionHand component2() { + return hand; + } } + /** * Return the slot from which to take blocks and items. */ diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/MishapEnvironment.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/MishapEnvironment.java new file mode 100644 index 00000000..54699144 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/MishapEnvironment.java @@ -0,0 +1,50 @@ +package at.petrak.hexcasting.api.casting.eval; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; + +/** + * Kinda like {@link CastingEnvironment} but for executing mishaps. + *

+ * To avoid horrible O(mn) scope problems we offer a set of stock bad effects. + * The player is exposed nullably if you like though. + */ +public abstract class MishapEnvironment { + @Nullable + protected final ServerPlayer caster; + protected final ServerLevel world; + + protected MishapEnvironment(ServerLevel world, @Nullable ServerPlayer caster) { + this.caster = caster; + this.world = world; + } + + public abstract void yeetHeldItemsTowards(Vec3 targetPos); + + public abstract void dropHeldItems(); + + public abstract void drown(); + + public abstract void damage(float healthProportion); + + public abstract void removeXp(int amount); + + public abstract void blind(int ticks); + + protected void yeetItem(ItemStack stack, Vec3 srcPos, Vec3 delta) { + var entity = new ItemEntity( + this.world, + srcPos.x, srcPos.y, srcPos.z, + stack, + delta.x + (Math.random() - 0.5) * 0.1, + delta.y + (Math.random() - 0.5) * 0.1, + delta.z + (Math.random() - 0.5) * 0.1 + ); + entity.setPickUpDelay(40); + this.world.addWithUUID(entity); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index 27cc2008..15c57f3b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -128,7 +128,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { null, listOf( OperatorSideEffect.DoMishap( - MishapError(exception), + MishapInternalException(exception), Mishap.Context( (iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST), null diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt index 98b8ac90..92ee5a68 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/Mishap.kt @@ -13,11 +13,8 @@ import at.petrak.hexcasting.ktxt.* import net.minecraft.Util import net.minecraft.core.BlockPos import net.minecraft.network.chat.Component -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.InteractionHand import net.minecraft.world.damagesource.DamageSource import net.minecraft.world.entity.LivingEntity -import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.item.DyeColor import net.minecraft.world.item.ItemStack import net.minecraft.world.phys.Vec3 @@ -69,40 +66,6 @@ abstract class Mishap : Throwable() { protected fun actionName(name: Component?): Component = name ?: "hexcasting.spell.null".asTranslatedComponent.lightPurple - protected fun yeetHeldItemsTowards(env: CastingEnvironment, targetPos: Vec3) { - // Knock the player's items out of their hands - val items = mutableListOf() - val caster = env.caster - if (caster != null) { - // FIXME: handle null caster case - return - } - for (hand in InteractionHand.values()) { - items.add(caster.getItemInHand(hand).copy()) - caster.setItemInHand(hand, ItemStack.EMPTY) - } - - val pos = caster.position() - val delta = targetPos.subtract(pos).normalize().scale(0.5) - - for (item in items) { - yeetItem(env, item, pos, delta) - } - } - - protected fun yeetItem(env: CastingEnvironment, stack: ItemStack, pos: Vec3, delta: Vec3) { - val entity = ItemEntity( - env.world, - pos.x, pos.y, pos.z, - stack, - delta.x + (Math.random() - 0.5) * 0.1, - delta.y + (Math.random() - 0.5) * 0.1, - delta.z + (Math.random() - 0.5) * 0.1 - ) - entity.setPickUpDelay(40) - env.world.addWithUUID(entity) - } - protected fun blockAtPos(ctx: CastingEnvironment, pos: BlockPos): Component { return ctx.world.getBlockState(pos).block.name } @@ -111,7 +74,7 @@ abstract class Mishap : Throwable() { companion object { @JvmStatic - public fun trulyHurt(entity: LivingEntity, source: DamageSource, amount: Float) { + fun trulyHurt(entity: LivingEntity, source: DamageSource, amount: Float) { entity.setHurtWithStamp(source, entity.level.gameTime) val targetHealth = entity.health - amount diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt index cb8e7463..2553f4c7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadBrainsweep.kt @@ -1,10 +1,10 @@ package at.petrak.hexcasting.api.casting.mishaps -import at.petrak.hexcasting.api.misc.FrozenColorizer -import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.casting.ParticleSpray import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.misc.FrozenColorizer +import at.petrak.hexcasting.api.misc.HexDamageSources import net.minecraft.core.BlockPos import net.minecraft.world.entity.Mob import net.minecraft.world.item.DyeColor @@ -15,6 +15,7 @@ class MishapBadBrainsweep(val mob: Mob, val pos: BlockPos) : Mishap() { dyeColor(DyeColor.GREEN) override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { + // TODO: you can just instakill things with this trulyHurt(mob, HexDamageSources.overcastDamageFrom(ctx.caster), mob.health) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt index 143be43e..6942ac1a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadEntity.kt @@ -15,7 +15,7 @@ class MishapBadEntity(val entity: Entity, val wanted: Component) : Mishap() { dyeColor(DyeColor.BROWN) override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { - yeetHeldItemsTowards(ctx, entity.position()) + ctx.mishapEnvironment.yeetHeldItemsTowards(entity.position()) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt index 8cd78780..ba804ff4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt @@ -14,8 +14,7 @@ class MishapBadOffhandItem(val item: ItemStack, val hand: InteractionHand, val w dyeColor(DyeColor.BROWN) override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { - // FIXME: Missing implementation in mishap - //yeetHeldItem(ctx, hand) + ctx.mishapEnvironment.dropHeldItems() } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item.isEmpty) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt index be14215a..46b5e5be 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapDivideByZero.kt @@ -1,12 +1,11 @@ package at.petrak.hexcasting.api.casting.mishaps -import at.petrak.hexcasting.api.misc.FrozenColorizer -import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.DoubleIota import at.petrak.hexcasting.api.casting.iota.GarbageIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.Vec3Iota +import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.utils.asTranslatedComponent import net.minecraft.network.chat.Component import net.minecraft.world.item.DyeColor @@ -19,11 +18,7 @@ class MishapDivideByZero(val operand1: Component, val operand2: Component, val s override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { stack.add(GarbageIota()) - val caster = ctx.caster - if (caster != null) { - // FIXME case where caster is null - trulyHurt(caster, HexDamageSources.OVERCAST, caster.health / 2) - } + ctx.mishapEnvironment.damage(0.5f) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt index 37cc1e98..b2d375c8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityTooFarAway.kt @@ -12,8 +12,7 @@ class MishapEntityTooFarAway(val entity: Entity) : Mishap() { dyeColor(DyeColor.PINK) override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { - // Knock the player's items out of their hands - yeetHeldItemsTowards(ctx, entity.position()) + ctx.mishapEnvironment.yeetHeldItemsTowards(entity.position()) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooDeep.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooDeep.kt index 9070c3ef..be522af6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooDeep.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEvalTooDeep.kt @@ -1,8 +1,8 @@ package at.petrak.hexcasting.api.casting.mishaps -import at.petrak.hexcasting.api.misc.FrozenColorizer -import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.misc.FrozenColorizer import net.minecraft.world.item.DyeColor class MishapEvalTooDeep : Mishap() { @@ -10,11 +10,7 @@ class MishapEvalTooDeep : Mishap() { dyeColor(DyeColor.BLUE) override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { - // FIXME what if caster is null - val caster = ctx.caster - if (caster != null) { - caster.airSupply -= 290 - } + ctx.mishapEnvironment.drown() } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapError.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt similarity index 89% rename from Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapError.kt rename to Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt index 8a5cec36..4c47ddad 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapError.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInternalException.kt @@ -5,7 +5,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.misc.FrozenColorizer import net.minecraft.world.item.DyeColor -class MishapError(val exception: Exception) : Mishap() { +class MishapInternalException(val exception: Exception) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenColorizer = dyeColor(DyeColor.BLACK) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationTooFarAway.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationTooFarAway.kt index 5869754a..e79203d0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationTooFarAway.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapLocationTooFarAway.kt @@ -13,7 +13,7 @@ class MishapLocationTooFarAway(val location: Vec3, val type: String = "too_far") dyeColor(DyeColor.MAGENTA) override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { - yeetHeldItemsTowards(ctx, location) + ctx.mishapEnvironment.yeetHeldItemsTowards(this.location) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt index b1addc1c..7eae838c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapNoAkashicRecord.kt @@ -1,8 +1,8 @@ package at.petrak.hexcasting.api.casting.mishaps -import at.petrak.hexcasting.api.misc.FrozenColorizer -import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.misc.FrozenColorizer import net.minecraft.core.BlockPos import net.minecraft.world.item.DyeColor @@ -11,11 +11,7 @@ class MishapNoAkashicRecord(val pos: BlockPos) : Mishap() { dyeColor(DyeColor.PURPLE) override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { - val caster = ctx.caster - if (caster != null) { - // FIXME: handle null case - caster.giveExperiencePoints(-100) - } + ctx.mishapEnvironment.removeXp(100) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt index 15d68ce0..65380ca8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt @@ -1,12 +1,10 @@ package at.petrak.hexcasting.api.casting.mishaps -import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.EntityIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota -import net.minecraft.world.effect.MobEffectInstance -import net.minecraft.world.effect.MobEffects +import at.petrak.hexcasting.api.misc.FrozenColorizer import net.minecraft.world.entity.player.Player import net.minecraft.world.item.DyeColor @@ -19,11 +17,7 @@ class MishapOthersName(val confidant: Player) : Mishap() { override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { val seconds = if (this.confidant == ctx.caster) 5 else 60; - val caster = ctx.caster - if (caster != null) { - // FIXME: handle null caster case - caster.addEffect(MobEffectInstance(MobEffects.BLINDNESS, seconds * 20)) - } + ctx.mishapEnvironment.blind(seconds * 20) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/env/PlayerBasedMishapEnv.java b/Common/src/main/java/at/petrak/hexcasting/common/casting/env/PlayerBasedMishapEnv.java new file mode 100644 index 00000000..87c5fd12 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/env/PlayerBasedMishapEnv.java @@ -0,0 +1,59 @@ +package at.petrak.hexcasting.common.casting.env; + +import at.petrak.hexcasting.api.casting.eval.MishapEnvironment; +import at.petrak.hexcasting.api.casting.mishaps.Mishap; +import at.petrak.hexcasting.api.misc.HexDamageSources; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +public class PlayerBasedMishapEnv extends MishapEnvironment { + public PlayerBasedMishapEnv(ServerPlayer player) { + super(player.getLevel(), player); + } + + @Override + public void yeetHeldItemsTowards(Vec3 targetPos) { + var pos = this.caster.position(); + var delta = targetPos.subtract(pos).normalize().scale(0.5); + + for (var hand : InteractionHand.values()) { + var stack = this.caster.getItemInHand(hand); + this.caster.setItemInHand(hand, ItemStack.EMPTY); + this.yeetItem(stack, pos, delta); + } + } + + @Override + public void dropHeldItems() { + var delta = this.caster.getLookAngle(); + this.yeetHeldItemsTowards(this.caster.position().add(delta)); + } + + @Override + public void damage(float healthProportion) { + Mishap.trulyHurt(this.caster, HexDamageSources.OVERCAST, this.caster.getHealth() * healthProportion); + } + + @Override + public void drown() { + if (this.caster.getAirSupply() < 200) { + this.caster.hurt(DamageSource.DROWN, 2f); + } + this.caster.setAirSupply(0); + } + + @Override + public void removeXp(int amount) { + this.caster.giveExperiencePoints(-amount); + } + + @Override + public void blind(int ticks) { + this.caster.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, ticks)); + } +}