fix double-use of getHeldItemToOperateOn

This commit is contained in:
yrsegal@gmail.com 2022-08-22 22:28:55 -04:00
parent 473a5a9834
commit ed2abee735
12 changed files with 51 additions and 83 deletions

View file

@ -14,8 +14,8 @@ import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.GameType import net.minecraft.world.level.GameType
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
@ -150,14 +150,14 @@ data class CastingContext(
* Return whether the withdrawal was successful. * Return whether the withdrawal was successful.
*/ */
// https://github.com/VazkiiMods/Psi/blob/master/src/main/java/vazkii/psi/common/spell/trick/block/PieceTrickPlaceBlock.java#L143 // https://github.com/VazkiiMods/Psi/blob/master/src/main/java/vazkii/psi/common/spell/trick/block/PieceTrickPlaceBlock.java#L143
fun withdrawItem(item: Item, count: Int, actuallyRemove: Boolean): Boolean { fun withdrawItem(item: ItemStack, count: Int, actuallyRemove: Boolean): Boolean {
if (this.caster.isCreative) return true if (this.caster.isCreative) return true
// TODO: withdraw from ender chest given a specific ender charm? // TODO: withdraw from ender chest given a specific ender charm?
val stacksToExamine = DiscoveryHandlers.collectItemSlots(this) val stacksToExamine = DiscoveryHandlers.collectItemSlots(this)
fun matches(stack: ItemStack): Boolean = fun matches(stack: ItemStack): Boolean =
!stack.isEmpty && stack.`is`(item) !stack.isEmpty && ItemEntity.areMergable(stack, item)
val presentCount = stacksToExamine.fold(0) { acc, stack -> val presentCount = stacksToExamine.fold(0) { acc, stack ->
acc + if (matches(stack)) stack.count else 0 acc + if (matches(stack)) stack.count else 0

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.common.casting.operators package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.addldata.DataHolder
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.RenderedSpell import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
@ -35,22 +36,15 @@ object OpWrite : SpellOperator {
throw MishapOthersName(trueName) throw MishapOthersName(trueName)
return Triple( return Triple(
Spell(datum), Spell(datum, datumHolder),
0, 0,
listOf() listOf()
) )
} }
private data class Spell(val datum: SpellDatum<*>) : RenderedSpell { private data class Spell(val datum: SpellDatum<*>, val datumHolder: DataHolder) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val (handStack) = ctx.getHeldItemToOperateOn { datumHolder.writeDatum(datum, false)
val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it)
datumHolder != null && datumHolder.writeDatum(datum, true)
}
val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack)
datumHolder?.writeDatum(datum, false)
} }
} }
} }

View file

@ -15,22 +15,21 @@ object OpBreakBlock : SpellOperator {
override fun execute( override fun execute(
args: List<SpellDatum<*>>, args: List<SpellDatum<*>>,
ctx: CastingContext ctx: CastingContext
): Triple<RenderedSpell, Int, List<ParticleSpray>> { ): Triple<RenderedSpell, Int, List<ParticleSpray>>? {
val pos = args.getChecked<Vec3>(0, argc) val pos = args.getChecked<Vec3>(0, argc)
ctx.assertVecInRange(pos) ctx.assertVecInRange(pos)
val centered = Vec3.atCenterOf(BlockPos(pos)) val bpos = BlockPos(pos)
val centered = Vec3.atCenterOf(bpos)
return Triple( return Triple(
Spell(pos), Spell(bpos),
(ManaConstants.DUST_UNIT * 1.125).toInt(), (ManaConstants.DUST_UNIT * 1.125).toInt(),
listOf(ParticleSpray.burst(centered, 1.0)) listOf(ParticleSpray.burst(centered, 1.0))
) )
} }
private data class Spell(val v: Vec3) : RenderedSpell { private data class Spell(val pos: BlockPos) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val pos = BlockPos(v)
if (!ctx.canEditBlockAt(pos)) if (!ctx.canEditBlockAt(pos))
return return

View file

@ -9,6 +9,7 @@ import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.world.item.ItemStack
object OpColorize : SpellOperator { object OpColorize : SpellOperator {
override val argc = 0 override val argc = 0
@ -26,23 +27,20 @@ object OpColorize : SpellOperator {
) )
} }
return Triple( return Triple(
Spell, Spell(handStack),
ManaConstants.DUST_UNIT, ManaConstants.DUST_UNIT,
listOf() listOf()
) )
} }
private object Spell : RenderedSpell { private data class Spell(val stack: ItemStack) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val handStack = ctx.getHeldItemToOperateOn(IXplatAbstractions.INSTANCE::isColorizer).first.copy() if (ctx.withdrawItem(stack, 1, true)) {
if (IXplatAbstractions.INSTANCE.isColorizer(handStack)) {
if (ctx.withdrawItem(handStack.item, 1, true)) {
IXplatAbstractions.INSTANCE.setColorizer( IXplatAbstractions.INSTANCE.setColorizer(
ctx.caster, ctx.caster,
FrozenColorizer(handStack, ctx.caster.uuid) FrozenColorizer(stack, ctx.caster.uuid)
) )
} }
} }
} }
} }
}

View file

@ -52,8 +52,6 @@ object OpDestroyWater : SpellOperator {
var successes = 0 var successes = 0
while (todo.isNotEmpty() && successes <= MAX_DESTROY_COUNT) { while (todo.isNotEmpty() && successes <= MAX_DESTROY_COUNT) {
val here = todo.removeFirst() val here = todo.removeFirst()
val distFromFocus =
ctx.caster.position().distanceToSqr(Vec3.atCenterOf(here))
if (ctx.canEditBlockAt(here) && seen.add(here)) { if (ctx.canEditBlockAt(here) && seen.add(here)) {
// never seen this pos in my life // never seen this pos in my life
val fluid = ctx.world.getFluidState(here) val fluid = ctx.world.getFluidState(here)

View file

@ -8,6 +8,7 @@ import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.world.item.ItemStack
class OpErase : SpellOperator { class OpErase : SpellOperator {
override val argc = 0 override val argc = 0
@ -33,22 +34,15 @@ class OpErase : SpellOperator {
} }
return Triple( return Triple(
Spell, Spell(handStack),
ManaConstants.DUST_UNIT, listOf() ManaConstants.DUST_UNIT, listOf()
) )
} }
private object Spell : RenderedSpell { private data class Spell(val stack: ItemStack) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val (handStack) = ctx.getHeldItemToOperateOn { val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(stack)
val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(it) val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(stack)
val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it)
(hexHolder?.hasHex() == true) ||
(datumHolder?.writeDatum(null, true) == true)
}
val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(handStack)
val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack)
if (hexHolder?.hasHex() == true) if (hexHolder?.hasHex() == true)
hexHolder.clearHex() hexHolder.clearHex()

View file

@ -2,11 +2,7 @@ package at.petrak.hexcasting.common.casting.operators.spells
import at.petrak.hexcasting.api.misc.ManaConstants import at.petrak.hexcasting.api.misc.ManaConstants
import at.petrak.hexcasting.api.mod.HexItemTags import at.petrak.hexcasting.api.mod.HexItemTags
import at.petrak.hexcasting.api.spell.getChecked import at.petrak.hexcasting.api.spell.*
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
@ -14,6 +10,7 @@ import at.petrak.hexcasting.api.utils.extractMana
import at.petrak.hexcasting.api.utils.isManaItem import at.petrak.hexcasting.api.utils.isManaItem
import at.petrak.hexcasting.common.items.magic.ItemManaHolder import at.petrak.hexcasting.common.items.magic.ItemManaHolder
import at.petrak.hexcasting.common.lib.HexItems import at.petrak.hexcasting.common.lib.HexItems
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
@ -59,14 +56,13 @@ object OpMakeBattery : SpellOperator {
) )
} }
return Triple(Spell(entity), return Triple(Spell(entity, hand),
ManaConstants.CRYSTAL_UNIT, listOf(ParticleSpray.burst(entity.position(), 0.5))) ManaConstants.CRYSTAL_UNIT, listOf(ParticleSpray.burst(entity.position(), 0.5)))
} }
private data class Spell(val itemEntity: ItemEntity) : RenderedSpell { private data class Spell(val itemEntity: ItemEntity, val hand: InteractionHand) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val (handStack, hand) = ctx.getHeldItemToOperateOn { it.`is`(HexItemTags.PHIAL_BASE) } if (itemEntity.isAlive) {
if (handStack.`is`(HexItemTags.PHIAL_BASE) && itemEntity.isAlive) {
val entityStack = itemEntity.item.copy() val entityStack = itemEntity.item.copy()
val manaAmt = extractMana(entityStack, drainForBatteries = true) val manaAmt = extractMana(entityStack, drainForBatteries = true)
if (manaAmt > 0) { if (manaAmt > 0) {

View file

@ -1,11 +1,6 @@
package at.petrak.hexcasting.common.casting.operators.spells package at.petrak.hexcasting.common.casting.operators.spells
import at.petrak.hexcasting.api.spell.getChecked import at.petrak.hexcasting.api.spell.*
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.SpellList
import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
@ -15,6 +10,7 @@ import at.petrak.hexcasting.api.utils.isManaItem
import at.petrak.hexcasting.common.items.magic.ItemPackagedHex import at.petrak.hexcasting.common.items.magic.ItemPackagedHex
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack
class OpMakePackagedSpell<T : ItemPackagedHex>(val itemType: T, val cost: Int) : SpellOperator { class OpMakePackagedSpell<T : ItemPackagedHex>(val itemType: T, val cost: Int) : SpellOperator {
override val argc = 2 override val argc = 2
@ -53,13 +49,12 @@ class OpMakePackagedSpell<T : ItemPackagedHex>(val itemType: T, val cost: Int) :
if (trueName != null) if (trueName != null)
throw MishapOthersName(trueName) throw MishapOthersName(trueName)
return Triple(Spell(entity, patterns), cost, listOf(ParticleSpray.burst(entity.position(), 0.5))) return Triple(Spell(entity, patterns, handStack), cost, listOf(ParticleSpray.burst(entity.position(), 0.5)))
} }
private inner class Spell(val itemEntity: ItemEntity, val patterns: List<SpellDatum<*>>) : RenderedSpell { private inner class Spell(val itemEntity: ItemEntity, val patterns: List<SpellDatum<*>>, val stack: ItemStack) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val (handStack) = ctx.getHeldItemToOperateOn { it.`is`(itemType) } val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(stack)
val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(handStack)
if (hexHolder != null if (hexHolder != null
&& !hexHolder.hasHex() && !hexHolder.hasHex()
&& itemEntity.isAlive && itemEntity.isAlive

View file

@ -29,13 +29,8 @@ object OpPlaceBlock : SpellOperator {
val pos = BlockPos(target) val pos = BlockPos(target)
// TODO: does this even work?? why are we returning null?? what does that *do*?
if (!ctx.canEditBlockAt(pos))
return null
val blockHit = BlockHitResult( val blockHit = BlockHitResult(
Vec3.ZERO, ctx.caster.direction, pos, false target, ctx.caster.direction, pos, false
) )
val itemUseCtx = UseOnContext(ctx.caster, ctx.castingHand, blockHit) val itemUseCtx = UseOnContext(ctx.caster, ctx.castingHand, blockHit)
val placeContext = BlockPlaceContext(itemUseCtx) val placeContext = BlockPlaceContext(itemUseCtx)
@ -59,7 +54,7 @@ object OpPlaceBlock : SpellOperator {
return return
val blockHit = BlockHitResult( val blockHit = BlockHitResult(
Vec3.ZERO, ctx.caster.direction, pos, false vec, ctx.caster.direction, pos, false
) )
val bstate = ctx.world.getBlockState(pos) val bstate = ctx.world.getBlockState(pos)
@ -80,13 +75,12 @@ object OpPlaceBlock : SpellOperator {
val itemUseCtx = UseOnContext(ctx.caster, ctx.castingHand, blockHit) val itemUseCtx = UseOnContext(ctx.caster, ctx.castingHand, blockHit)
val placeContext = BlockPlaceContext(itemUseCtx) val placeContext = BlockPlaceContext(itemUseCtx)
if (bstate.canBeReplaced(placeContext)) { if (bstate.canBeReplaced(placeContext)) {
val placee = placeeStack.item as BlockItem if (ctx.withdrawItem(placeeStack, 1, false)) {
if (ctx.withdrawItem(placee, 1, false)) {
val res = spoofedStack.useOn(placeContext) val res = spoofedStack.useOn(placeContext)
ctx.caster.setItemInHand(ctx.castingHand, oldStack) ctx.caster.setItemInHand(ctx.castingHand, oldStack)
if (res != InteractionResult.FAIL) { if (res != InteractionResult.FAIL) {
ctx.withdrawItem(placee, 1, true) ctx.withdrawItem(placeeStack, 1, true)
ctx.world.playSound( ctx.world.playSound(
ctx.caster, ctx.caster,

View file

@ -9,6 +9,7 @@ import at.petrak.hexcasting.api.utils.extractMana
import at.petrak.hexcasting.api.utils.isManaItem import at.petrak.hexcasting.api.utils.isManaItem
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack
object OpRecharge : SpellOperator { object OpRecharge : SpellOperator {
override val argc = 1 override val argc = 1
@ -44,19 +45,15 @@ object OpRecharge : SpellOperator {
return null return null
return Triple( return Triple(
Spell(entity), Spell(entity, handStack),
ManaConstants.SHARD_UNIT, ManaConstants.SHARD_UNIT,
listOf(ParticleSpray.burst(entity.position(), 0.5)) listOf(ParticleSpray.burst(entity.position(), 0.5))
) )
} }
private data class Spell(val itemEntity: ItemEntity) : RenderedSpell { private data class Spell(val itemEntity: ItemEntity, val stack: ItemStack) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val (handStack) = ctx.getHeldItemToOperateOn { val mana = IXplatAbstractions.INSTANCE.findManaHolder(stack)
val mana = IXplatAbstractions.INSTANCE.findManaHolder(it)
mana != null && mana.canRecharge() && mana.insertMana(-1, true) != 0
}
val mana = IXplatAbstractions.INSTANCE.findManaHolder(handStack)
if (mana != null && itemEntity.isAlive) { if (mana != null && itemEntity.isAlive) {
val entityStack = itemEntity.item.copy() val entityStack = itemEntity.item.copy()

View file

@ -25,7 +25,7 @@ object OpBrainsweep : SpellOperator {
override fun execute( override fun execute(
args: List<SpellDatum<*>>, args: List<SpellDatum<*>>,
ctx: CastingContext ctx: CastingContext
): Triple<RenderedSpell, Int, List<ParticleSpray>> { ): Triple<RenderedSpell, Int, List<ParticleSpray>>? {
val sacrifice = args.getChecked<Villager>(0, argc) val sacrifice = args.getChecked<Villager>(0, argc)
val pos = args.getChecked<Vec3>(1, argc) val pos = args.getChecked<Vec3>(1, argc)
ctx.assertVecInRange(pos) ctx.assertVecInRange(pos)
@ -35,6 +35,10 @@ object OpBrainsweep : SpellOperator {
throw MishapAlreadyBrainswept(sacrifice) throw MishapAlreadyBrainswept(sacrifice)
val bpos = BlockPos(pos) val bpos = BlockPos(pos)
if (!ctx.canEditBlockAt(bpos))
return null
val state = ctx.world.getBlockState(bpos) val state = ctx.world.getBlockState(bpos)
val recman = ctx.world.recipeManager val recman = ctx.world.recipeManager
@ -56,9 +60,8 @@ object OpBrainsweep : SpellOperator {
val recipe: BrainsweepRecipe val recipe: BrainsweepRecipe
) : RenderedSpell { ) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
if (ctx.canEditBlockAt(pos)) {
ctx.world.setBlockAndUpdate(pos, BrainsweepRecipe.copyProperties(state, recipe.result)) ctx.world.setBlockAndUpdate(pos, BrainsweepRecipe.copyProperties(state, recipe.result))
}
Brainsweeping.brainsweep(sacrifice) Brainsweeping.brainsweep(sacrifice)
if (HexConfig.server().doVillagersTakeOffenseAtMindMurder()) { if (HexConfig.server().doVillagersTakeOffenseAtMindMurder()) {
sacrifice.tellWitnessesThatIWasMurdered(ctx.caster) sacrifice.tellWitnessesThatIWasMurdered(ctx.caster)

View file

@ -46,7 +46,7 @@ object OpTeleport : SpellOperator {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val distance = delta.length() val distance = delta.length()
if (distance < 32768.0) { if (distance < 32768.0) {
OpTeleport.teleportRespectSticky(teleportee, delta) teleportRespectSticky(teleportee, delta)
} }
if (teleportee is ServerPlayer && teleportee == ctx.caster) { if (teleportee is ServerPlayer && teleportee == ctx.caster) {