update destroy water to work on any fluid and add extinguish/ignite fire spells
This commit is contained in:
parent
bb60de40f8
commit
7e0723aee1
6 changed files with 177 additions and 4 deletions
|
@ -98,9 +98,12 @@ public class RegisterPatterns {
|
|||
OpColorize.INSTANCE);
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aqawqadaq", HexDir.SOUTH_EAST), prefix("create_water"),
|
||||
OpCreateWater.INSTANCE);
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("dedwedade", HexDir.SOUTH_WEST),
|
||||
prefix("destroy_water"),
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("dedwedade", HexDir.SOUTH_WEST), prefix("destroy_water"),
|
||||
OpDestroyWater.INSTANCE);
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("ddedwdwd", HexDir.EAST), prefix("ignite"),
|
||||
OpIgnite.INSTANCE);
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aaqawawa", HexDir.WEST), prefix("extinguish"),
|
||||
OpExtinguish.INSTANCE);
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqa", HexDir.NORTH_EAST), prefix("conjure_block"),
|
||||
new OpConjure(false));
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqd", HexDir.NORTH_EAST), prefix("conjure_light"),
|
||||
|
|
|
@ -11,12 +11,12 @@ import net.minecraft.core.Direction
|
|||
import net.minecraft.core.particles.ParticleTypes
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.tags.FluidTags
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.BucketPickup
|
||||
import net.minecraft.world.level.block.LiquidBlock
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraft.world.level.material.Material
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
|
@ -42,6 +42,9 @@ object OpDestroyWater : SpellOperator {
|
|||
val todo = ArrayDeque<BlockPos>()
|
||||
val seen = HashSet<BlockPos>()
|
||||
todo.add(BlockPos(target))
|
||||
for (dir in Direction.values()) { // a little extra range on the initial cast to make it feel more intuitive
|
||||
todo.add(BlockPos(target).relative(dir))
|
||||
}
|
||||
|
||||
var successes = 0
|
||||
while (todo.isNotEmpty() && successes <= MAX_DESTROY_COUNT) {
|
||||
|
@ -51,7 +54,7 @@ object OpDestroyWater : SpellOperator {
|
|||
if (distFromFocus < Operator.MAX_DISTANCE * Operator.MAX_DISTANCE && seen.add(here)) {
|
||||
// never seen this pos in my life
|
||||
val fluid = ctx.world.getFluidState(here)
|
||||
if (fluid.`is`(FluidTags.WATER)) {
|
||||
if (fluid != Fluids.EMPTY.defaultFluidState()) {
|
||||
val blockstate = ctx.world.getBlockState(here)
|
||||
val material = blockstate.material
|
||||
val success =
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells
|
||||
|
||||
import at.petrak.hexcasting.api.Operator
|
||||
import at.petrak.hexcasting.api.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.RenderedSpell
|
||||
import at.petrak.hexcasting.api.SpellDatum
|
||||
import at.petrak.hexcasting.api.SpellOperator
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.particles.ParticleTypes
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.context.UseOnContext
|
||||
import net.minecraft.world.level.block.*
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
object OpExtinguish : SpellOperator {
|
||||
override val argc = 1
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): Triple<RenderedSpell, Int, List<Vec3>> {
|
||||
val target = args.getChecked<Vec3>(0)
|
||||
ctx.assertVecInRange(target)
|
||||
|
||||
return Triple(
|
||||
Spell(target),
|
||||
200_000,
|
||||
listOf(target)
|
||||
)
|
||||
}
|
||||
|
||||
const val MAX_DESTROY_COUNT = 1024
|
||||
|
||||
private data class Spell(val target: Vec3) : RenderedSpell {
|
||||
|
||||
override fun cast(ctx: CastingContext) {
|
||||
// how many levels of "borrowed" code are we on now
|
||||
val todo = ArrayDeque<BlockPos>()
|
||||
val seen = HashSet<BlockPos>()
|
||||
todo.add(BlockPos(target))
|
||||
|
||||
var successes = 0
|
||||
while (todo.isNotEmpty() && successes <= MAX_DESTROY_COUNT) {
|
||||
val here = todo.removeFirst()
|
||||
val distFromFocus =
|
||||
ctx.caster.position().distanceToSqr(Vec3(here.x.toDouble(), here.y.toDouble(), here.z.toDouble()))
|
||||
val distFromTarget =
|
||||
target.distanceTo(Vec3(here.x.toDouble(), here.y.toDouble(), here.z.toDouble())) // max distance to prevent runaway shenanigans
|
||||
if (distFromFocus < Operator.MAX_DISTANCE * Operator.MAX_DISTANCE && seen.add(here) && distFromTarget < 10) {
|
||||
// never seen this pos in my life
|
||||
val blockstate = ctx.world.getBlockState(here)
|
||||
val success =
|
||||
when (blockstate.block) {
|
||||
is BaseFireBlock -> {ctx.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3); true}
|
||||
is CampfireBlock -> {if (blockstate.getValue(CampfireBlock.LIT)) { // check if campfire is lit before putting it out
|
||||
val wilson = Items.WOODEN_SHOVEL // summon shovel from the ether to do our bidding
|
||||
val hereVec = (Vec3(here.x.toDouble(), here.y.toDouble(), here.z.toDouble()))
|
||||
wilson.useOn(UseOnContext(ctx.world, null, InteractionHand.MAIN_HAND, ItemStack(wilson.asItem()), BlockHitResult(hereVec, Direction.UP, here, false))); true}
|
||||
else false}
|
||||
is AbstractCandleBlock -> {
|
||||
if (blockstate.getValue(AbstractCandleBlock.LIT)) { // same check for candles
|
||||
AbstractCandleBlock.extinguish(null, blockstate, ctx.world, here); true}
|
||||
else false}
|
||||
is NetherPortalBlock -> {ctx.world.setBlock(here, Blocks.AIR.defaultBlockState(), 3); true}
|
||||
else -> false
|
||||
}
|
||||
|
||||
if (success) {
|
||||
ctx.world.sendParticles(
|
||||
ParticleTypes.SMOKE,
|
||||
here.x + 0.5 + Math.random() * 0.4 - 0.2,
|
||||
here.y + 0.5 + Math.random() * 0.4 - 0.2,
|
||||
here.z + 0.5 + Math.random() * 0.4 - 0.2,
|
||||
2,
|
||||
0.0,
|
||||
0.05,
|
||||
0.0,
|
||||
0.0
|
||||
)
|
||||
successes++
|
||||
}
|
||||
for (dir in Direction.values()) {
|
||||
todo.add(here.relative(dir))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (successes > 0) {
|
||||
ctx.world.playSound(
|
||||
null,
|
||||
target.x,
|
||||
target.y,
|
||||
target.z,
|
||||
SoundEvents.FIRE_EXTINGUISH,
|
||||
SoundSource.BLOCKS,
|
||||
1.0f,
|
||||
0.95f
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells
|
||||
|
||||
import at.petrak.hexcasting.HexMod
|
||||
import at.petrak.hexcasting.api.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.RenderedSpell
|
||||
import at.petrak.hexcasting.api.SpellDatum
|
||||
import at.petrak.hexcasting.api.SpellOperator
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.item.FireChargeItem
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.context.UseOnContext
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
object OpIgnite : SpellOperator {
|
||||
override val argc = 1
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): Triple<RenderedSpell, Int, List<Vec3>> {
|
||||
val target = args.getChecked<Vec3>(0)
|
||||
ctx.assertVecInRange(target)
|
||||
|
||||
return Triple(
|
||||
Spell(target),
|
||||
10_000,
|
||||
listOf(target)
|
||||
)
|
||||
}
|
||||
|
||||
private data class Spell(val target: Vec3) : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
// steal petra code that steals bucket code
|
||||
val maxwell = Items.FIRE_CHARGE
|
||||
if (maxwell is FireChargeItem) {
|
||||
// help
|
||||
maxwell.useOn(UseOnContext(ctx.world, null, InteractionHand.MAIN_HAND, ItemStack(maxwell.asItem()), BlockHitResult(target, Direction.UP, BlockPos(target), false)))
|
||||
} else {
|
||||
HexMod.getLogger().warn("Items.FIRE_CHARGE wasn't a FireChargeItem?")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -132,6 +132,8 @@
|
|||
"hexcasting.spell.hexcasting:erase": "Erase Item",
|
||||
"hexcasting.spell.hexcasting:create_water": "Create Water",
|
||||
"hexcasting.spell.hexcasting:destroy_water": "Destroy Water",
|
||||
"hexcasting.spell.hexcasting:ignite": "Ignite Block",
|
||||
"hexcasting.spell.hexcasting:extinguish": "Extinguish Area",
|
||||
"hexcasting.spell.hexcasting:conjure_block": "Conjure Block",
|
||||
"hexcasting.spell.hexcasting:conjure_light": "Conjure Light",
|
||||
"hexcasting.spell.hexcasting:bonemeal": "Overgrow",
|
||||
|
|
|
@ -61,6 +61,22 @@
|
|||
"input": "vector",
|
||||
"output": "",
|
||||
"text": "hexcasting.page.blockworks7"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:ignite",
|
||||
"anchor": "hexcasting:ignite",
|
||||
"input": "vector",
|
||||
"output": "",
|
||||
"text": "Start a fire on top of the given location, as if a $(item)Fire Charge/$ was applied. Costs about one $(item)Amethyst Dust/$."
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:extinguish",
|
||||
"anchor": "hexcasting:extinguish",
|
||||
"input": "vector",
|
||||
"output": "",
|
||||
"text": "Extinguish blocks in a large area. Costs about two $(item)Amethyst Crystal/$s."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue