maybe 1/3 done with reworking the backend
This commit is contained in:
parent
ecd2e65fad
commit
9cf873a40c
16 changed files with 173 additions and 91 deletions
|
@ -2,6 +2,7 @@ package at.petrak.hexcasting.api
|
|||
|
||||
import at.petrak.hexcasting.common.casting.CastException
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.OperatorSideEffect
|
||||
|
||||
/**
|
||||
* A SimpleOperator that always costs the same amount of mana.
|
||||
|
@ -13,15 +14,15 @@ interface ConstManaOperator : Operator {
|
|||
|
||||
fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>>
|
||||
|
||||
override fun modifyStack(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
if (this.argc > stack.size)
|
||||
throw CastException(CastException.Reason.NOT_ENOUGH_ARGS, this.argc, stack.size)
|
||||
val args = stack.takeLast(this.argc)
|
||||
// there's gotta be a better way to do this
|
||||
for (_idx in 0 until this.argc)
|
||||
stack.removeLast()
|
||||
val args = stack.dropLast(this.argc)
|
||||
val newData = this.execute(args, ctx)
|
||||
stack.addAll(newData)
|
||||
return OperationResult(this.manaCost, emptyList())
|
||||
|
||||
val sideEffects = mutableListOf<OperatorSideEffect>(OperatorSideEffect.ConsumeMana(this.manaCost))
|
||||
|
||||
return OperationResult(stack, sideEffects)
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package at.petrak.hexcasting.api
|
||||
|
||||
import at.petrak.hexcasting.common.casting.OperatorSideEffect
|
||||
|
||||
/**
|
||||
* What happens when an operator is through?
|
||||
*
|
||||
* This has the mana cost and some spells that might be cast.
|
||||
*/
|
||||
data class OperationResult(val manaCost: Int, val spells: List<RenderedSpell>)
|
||||
data class OperationResult(val newStack: List<SpellDatum<*>>, val sideEffects: List<OperatorSideEffect>)
|
||||
|
|
|
@ -14,12 +14,18 @@ import net.minecraft.world.phys.Vec3
|
|||
*/
|
||||
interface Operator {
|
||||
/**
|
||||
* Operate on the stack and return the mana cost.
|
||||
* Operate on the stack. Return the new stack and any side effects of the cast.
|
||||
*
|
||||
* Although this is passed a [MutableList], this is only for the convenience of implementors.
|
||||
* It is a clone of the stack and modifying it does nothing. You must return the new stack
|
||||
* with the [OperationResult].
|
||||
*
|
||||
* A particle effect at the cast site and various messages and advancements are done automagically.
|
||||
*/
|
||||
fun modifyStack(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult
|
||||
fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult
|
||||
|
||||
/**
|
||||
* Do you need to be enlightened to cast this spell?
|
||||
* Do you need to be enlightened to use this operator?
|
||||
*/
|
||||
val isGreat: Boolean get() = false
|
||||
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package at.petrak.hexcasting.api
|
||||
|
||||
import at.petrak.hexcasting.common.casting.CastException
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
|
||||
/**
|
||||
* An operator that acts in the expected method of popping some arguments
|
||||
* and pushing some more arguments, not returning any spells.
|
||||
*/
|
||||
interface SimpleOperator : Operator {
|
||||
val argc: Int
|
||||
fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): Pair<List<SpellDatum<*>>, Int>
|
||||
|
||||
override fun modifyStack(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
if (this.argc > stack.size)
|
||||
throw CastException(CastException.Reason.NOT_ENOUGH_ARGS, this.argc, stack.size)
|
||||
val args = stack.takeLast(this.argc)
|
||||
// there's gotta be a better way to do this
|
||||
for (_idx in 0 until this.argc)
|
||||
stack.removeLast()
|
||||
val (newData, mana) = this.execute(args, ctx)
|
||||
stack.addAll(newData)
|
||||
return OperationResult(mana, emptyList())
|
||||
}
|
||||
}
|
|
@ -2,19 +2,28 @@ package at.petrak.hexcasting.api
|
|||
|
||||
import at.petrak.hexcasting.common.casting.CastException
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.OperatorSideEffect
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
interface SpellOperator : Operator {
|
||||
val argc: Int
|
||||
|
||||
fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): Pair<RenderedSpell, Int>
|
||||
fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): Triple<RenderedSpell, Int, List<Vec3>>
|
||||
|
||||
override fun modifyStack(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
if (this.argc > stack.size)
|
||||
throw CastException(CastException.Reason.NOT_ENOUGH_ARGS, this.argc, stack.size)
|
||||
val args = stack.takeLast(this.argc)
|
||||
for (_idx in 0 until this.argc)
|
||||
stack.removeLast()
|
||||
val (spell, mana) = this.execute(args, ctx)
|
||||
return OperationResult(mana, listOf(spell))
|
||||
val args = stack.dropLast(this.argc)
|
||||
val (spell, mana, particlePoses) = this.execute(args, ctx)
|
||||
|
||||
val sideEffects = mutableListOf(
|
||||
OperatorSideEffect.ConsumeMana(mana),
|
||||
OperatorSideEffect.AttemptSpell(spell, this.isGreat)
|
||||
)
|
||||
for (pos in particlePoses) {
|
||||
sideEffects.add(OperatorSideEffect.Particles(pos))
|
||||
}
|
||||
|
||||
return OperationResult(stack, sideEffects)
|
||||
}
|
||||
}
|
|
@ -78,7 +78,8 @@ public class HexAdditionalRenderers {
|
|||
Consumer<float[]> v = (point) -> {
|
||||
var color = -1;
|
||||
if (finalCap != null) {
|
||||
color = finalCap.getColor(owner, time, new Vec3(point[0], point[1], point[2]));
|
||||
color = CapPreferredColorizer.getColor(finalCap.colorizer, owner, time,
|
||||
new Vec3(point[0], point[1], point[2]));
|
||||
}
|
||||
buf.vertex(neo, point[0], point[1], point[2])
|
||||
.color(color)
|
||||
|
|
|
@ -24,10 +24,12 @@ data class CastingContext(
|
|||
val castingHand: InteractionHand,
|
||||
) {
|
||||
private var depth: Int = 0
|
||||
|
||||
val world: ServerLevel get() = caster.getLevel()
|
||||
val otherHand: InteractionHand get() = HexUtils.OtherHand(this.castingHand)
|
||||
val position: Vec3 get() = caster.position()
|
||||
|
||||
|
||||
fun getSpellbook(): ItemStack {
|
||||
val handItem =
|
||||
caster.getItemInHand(this.otherHand)
|
||||
|
|
|
@ -2,22 +2,22 @@ package at.petrak.hexcasting.common.casting
|
|||
|
||||
import at.petrak.hexcasting.HexMod
|
||||
import at.petrak.hexcasting.api.PatternRegistry
|
||||
import at.petrak.hexcasting.api.RenderedSpell
|
||||
import at.petrak.hexcasting.api.SpellDatum
|
||||
import at.petrak.hexcasting.common.items.HexItems
|
||||
import at.petrak.hexcasting.common.items.ItemWand
|
||||
import at.petrak.hexcasting.common.items.magic.ItemPackagedSpell
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexDamageSources
|
||||
import at.petrak.hexcasting.common.lib.HexStatistics
|
||||
import at.petrak.hexcasting.datagen.Advancements
|
||||
import at.petrak.hexcasting.hexmath.HexPattern
|
||||
import net.minecraft.Util
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
import kotlin.random.Random
|
||||
|
@ -33,8 +33,11 @@ class CastingHarness private constructor(
|
|||
var parenthesized: MutableList<HexPattern>,
|
||||
var escapeNext: Boolean,
|
||||
val ctx: CastingContext,
|
||||
val prepackagedColorizer: ItemStack?
|
||||
) {
|
||||
constructor(ctx: CastingContext) : this(mutableListOf(), 0, mutableListOf(), false, ctx)
|
||||
|
||||
constructor(ctx: CastingContext) : this(mutableListOf(), 0, mutableListOf(), false, ctx, null)
|
||||
|
||||
|
||||
/**
|
||||
* When the server gets a packet from the client with a new pattern,
|
||||
|
@ -42,7 +45,6 @@ class CastingHarness private constructor(
|
|||
*/
|
||||
fun update(newPat: HexPattern, world: ServerLevel): CastResult {
|
||||
return try {
|
||||
var spellsToCast = emptyList<RenderedSpell>()
|
||||
var exn: CastException? = null
|
||||
val operator = try {
|
||||
PatternRegistry.matchPattern(newPat, world)
|
||||
|
@ -89,34 +91,9 @@ class CastingHarness private constructor(
|
|||
throw CastException(CastException.Reason.TOO_MANY_CLOSE_PARENS)
|
||||
} else {
|
||||
// we know the operator is ok here
|
||||
val (manaCost, spells) = operator!!.modifyStack(this.stack, this.ctx)
|
||||
|
||||
|
||||
val leftover = this.withdrawMana(manaCost, ctx.canOvercast)
|
||||
if (ctx.caster.isDeadOrDying)
|
||||
return CastResult.Died
|
||||
else if (leftover > 0) {
|
||||
if (!ctx.canOvercast) {
|
||||
ctx.caster.sendMessage(
|
||||
TranslatableComponent("hexcasting.message.cant_overcast"),
|
||||
Util.NIL_UUID
|
||||
)
|
||||
}
|
||||
return CastResult.QuitCasting
|
||||
}
|
||||
|
||||
|
||||
// is great IMPLIES caster is enlightened
|
||||
if (!operator.isGreat || ctx.isCasterEnlightened) {
|
||||
spellsToCast = spells
|
||||
} else if (operator.isGreat) {
|
||||
ctx.caster.sendMessage(
|
||||
TranslatableComponent("hexcasting.message.cant_great_spell"),
|
||||
Util.NIL_UUID
|
||||
)
|
||||
Advancements.FAIL_GREAT_SPELL_TRIGGER.trigger(ctx.caster)
|
||||
}
|
||||
val (stackPrime, sideEffects) = operator!!.operate(this.stack, this.ctx)
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (spellsToCast.isNotEmpty()) {
|
||||
|
@ -201,6 +178,18 @@ class CastingHarness private constructor(
|
|||
return costLeft
|
||||
}
|
||||
|
||||
fun getColorizer(): ItemStack {
|
||||
if (this.prepackagedColorizer != null)
|
||||
return this.prepackagedColorizer
|
||||
|
||||
val maybeCap = this.ctx.caster.getCapability(HexCapabilities.PREFERRED_COLORIZER).resolve()
|
||||
if (maybeCap.isEmpty) {
|
||||
// uh oh
|
||||
return ItemStack(HexItems.DYE_COLORIZERS[0].get())
|
||||
}
|
||||
return maybeCap.get().colorizer
|
||||
}
|
||||
|
||||
|
||||
fun serializeToNBT(): CompoundTag {
|
||||
val out = CompoundTag()
|
||||
|
@ -218,6 +207,10 @@ class CastingHarness private constructor(
|
|||
parensTag.add(pat.serializeToNBT())
|
||||
out.put(TAG_PARENTHESIZED, parensTag)
|
||||
|
||||
if (this.prepackagedColorizer != null) {
|
||||
out.put(TAG_PREPACKAGED_COLORIZER, this.prepackagedColorizer.serializeNBT())
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
|
@ -227,6 +220,7 @@ class CastingHarness private constructor(
|
|||
const val TAG_PAREN_COUNT = "open_parens"
|
||||
const val TAG_PARENTHESIZED = "parenthesized"
|
||||
const val TAG_ESCAPE_NEXT = "escape_next"
|
||||
const val TAG_PREPACKAGED_COLORIZER = "prepackaged_colorizer"
|
||||
|
||||
@JvmStatic
|
||||
fun DeserializeFromNBT(nbt: Tag?, caster: ServerPlayer, wandHand: InteractionHand): CastingHarness {
|
||||
|
@ -250,7 +244,13 @@ class CastingHarness private constructor(
|
|||
val parenCount = nbt.getInt(TAG_PAREN_COUNT)
|
||||
val escapeNext = nbt.getBoolean(TAG_ESCAPE_NEXT)
|
||||
|
||||
CastingHarness(stack, parenCount, parenthesized, escapeNext, ctx)
|
||||
val colorizer = if (nbt.contains(TAG_PREPACKAGED_COLORIZER)) {
|
||||
ItemStack.of(nbt.getCompound(TAG_PREPACKAGED_COLORIZER))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
CastingHarness(stack, parenCount, parenthesized, escapeNext, ctx, colorizer)
|
||||
} catch (exn: Exception) {
|
||||
HexMod.LOGGER.warn("Couldn't load harness from nbt tag, falling back to default: $nbt: $exn")
|
||||
CastingHarness(ctx)
|
||||
|
@ -266,7 +266,7 @@ class CastingHarness private constructor(
|
|||
object QuitCasting : CastResult()
|
||||
|
||||
/** Finished casting */
|
||||
data class Cast(val spells: List<RenderedSpell>, val quit: Boolean) : CastResult()
|
||||
data class Cast(val sideEffects: List<OperatorSideEffect>, val quit: Boolean) : CastResult()
|
||||
|
||||
/** uh-oh */
|
||||
data class Error(val exn: CastException) : CastResult()
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package at.petrak.hexcasting.common.casting
|
||||
|
||||
import at.petrak.hexcasting.api.RenderedSpell
|
||||
import at.petrak.hexcasting.api.SpellDatum
|
||||
import at.petrak.hexcasting.common.casting.colors.CapPreferredColorizer
|
||||
import at.petrak.hexcasting.datagen.Advancements
|
||||
import com.mojang.math.Vector3f
|
||||
import net.minecraft.Util
|
||||
import net.minecraft.core.particles.DustParticleOptions
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import net.minecraft.util.FastColor
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.random.Random
|
||||
import kotlin.random.nextInt
|
||||
|
||||
/**
|
||||
* Things that happen after a spell is cast.
|
||||
*/
|
||||
sealed class OperatorSideEffect {
|
||||
/** Return whether to cancel all further [OperatorSideEffect] */
|
||||
abstract fun performEffect(harness: CastingHarness): Boolean
|
||||
|
||||
/** Try to cast a spell */
|
||||
data class AttemptSpell(val spell: RenderedSpell, val isGreat: Boolean) : OperatorSideEffect() {
|
||||
override fun performEffect(harness: CastingHarness): Boolean {
|
||||
return if (this.isGreat && !harness.ctx.isCasterEnlightened) {
|
||||
harness.ctx.caster.sendMessage(
|
||||
TranslatableComponent("hexcasting.message.cant_great_spell"),
|
||||
Util.NIL_UUID
|
||||
)
|
||||
Advancements.FAIL_GREAT_SPELL_TRIGGER.trigger(harness.ctx.caster)
|
||||
true
|
||||
} else {
|
||||
this.spell.cast(harness.ctx)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class ConsumeMana(val amount: Int) : OperatorSideEffect() {
|
||||
override fun performEffect(harness: CastingHarness): Boolean {
|
||||
val overcastOk = harness.ctx.canOvercast
|
||||
val leftoverMana = harness.withdrawMana(this.amount, overcastOk)
|
||||
if (leftoverMana > 0 && overcastOk) {
|
||||
harness.ctx.caster.sendMessage(
|
||||
TranslatableComponent("hexcasting.message.cant_overcast"),
|
||||
Util.NIL_UUID
|
||||
)
|
||||
}
|
||||
return leftoverMana > 0
|
||||
}
|
||||
}
|
||||
|
||||
data class Particles(val position: Vec3) : OperatorSideEffect() {
|
||||
override fun performEffect(harness: CastingHarness): Boolean {
|
||||
val colorizer = harness.getColorizer()
|
||||
|
||||
for (i in 0 until 6) {
|
||||
// For the colors, pick any random time to get a mix of colors
|
||||
val color =
|
||||
CapPreferredColorizer.getColor(colorizer, harness.ctx.caster, Random.nextFloat() * 256f, Vec3.ZERO)
|
||||
val r = FastColor.ARGB32.red(color)
|
||||
val g = FastColor.ARGB32.green(color)
|
||||
val b = FastColor.ARGB32.blue(color)
|
||||
harness.ctx.world.addParticle(
|
||||
DustParticleOptions(Vector3f(r.toFloat(), g.toFloat(), b.toFloat()), 1f),
|
||||
position.x,
|
||||
position.y,
|
||||
position.z,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
object AddGarbage : OperatorSideEffect() {
|
||||
override fun performEffect(harness: CastingHarness): Boolean {
|
||||
val idx = Random.nextInt(0..harness.stack.size)
|
||||
harness.stack.add(idx, SpellDatum.make(Widget.GARBAGE))
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,11 +5,11 @@ import at.petrak.hexcasting.common.items.HexItems;
|
|||
import at.petrak.hexcasting.common.items.colorizer.ItemDyeColorizer;
|
||||
import at.petrak.hexcasting.common.items.colorizer.ItemPoliticalColorizer;
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.FastColor;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
@ -44,8 +44,8 @@ public class CapPreferredColorizer implements ICapabilitySerializable<CompoundTa
|
|||
* @param position a position for the icosahedron, a randomish number for particles.
|
||||
* @return an AARRGGBB color.
|
||||
*/
|
||||
public int getColor(LocalPlayer asker, float time, Vec3 position) {
|
||||
var proto = this.colorizer.getItem();
|
||||
public static int getColor(ItemStack colorizer, Player asker, float time, Vec3 position) {
|
||||
var proto = colorizer.getItem();
|
||||
if (proto instanceof ItemDyeColorizer dye) {
|
||||
return DyeColor.values()[dye.getDyeIdx()].getTextColor() | 0xff_000000;
|
||||
} else if (proto instanceof ItemPoliticalColorizer politics) {
|
||||
|
@ -68,7 +68,7 @@ public class CapPreferredColorizer implements ICapabilitySerializable<CompoundTa
|
|||
return 0xff_ff00dc; // missing color
|
||||
}
|
||||
|
||||
private int morphBetweenColors(int[] colors, Vec3 gradientDir, float time, Vec3 position) {
|
||||
private static int morphBetweenColors(int[] colors, Vec3 gradientDir, float time, Vec3 position) {
|
||||
float fIdx = ((time + (float) gradientDir.dot(position)) % 1f) * colors.length;
|
||||
|
||||
int baseIdx = Mth.floor(fIdx);
|
||||
|
|
|
@ -9,7 +9,7 @@ import at.petrak.hexcasting.common.casting.CastingContext
|
|||
import at.petrak.hexcasting.common.casting.CastingHarness
|
||||
|
||||
object OpEval : Operator {
|
||||
override fun modifyStack(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
val instrs: List<SpellDatum<*>> = stack.getChecked(stack.lastIndex)
|
||||
stack.removeLastOrNull()
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import kotlin.math.max
|
|||
import kotlin.math.roundToInt
|
||||
|
||||
object OpEvalDelay : Operator {
|
||||
override fun modifyStack(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
val instrs: List<SpellDatum<*>> = stack.getChecked(stack.lastIndex - 1)
|
||||
val delay: Double = stack.getChecked(stack.lastIndex)
|
||||
stack.removeLastOrNull()
|
||||
|
|
|
@ -11,7 +11,7 @@ import at.petrak.hexcasting.common.casting.CastingHarness
|
|||
import at.petrak.hexcasting.hexmath.HexPattern
|
||||
|
||||
object OpForEach : Operator {
|
||||
override fun modifyStack(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
val last = stack.lastIndex
|
||||
val maybeProgram = stack[last - 1]
|
||||
val vals = stack.getChecked<List<SpellDatum<*>>>(last)
|
||||
|
|
|
@ -16,12 +16,13 @@ object OpAddMotion : SpellOperator {
|
|||
override val argc: Int
|
||||
get() = 2
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): Pair<RenderedSpell, Int> {
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): Triple<RenderedSpell, Int, List<Vec3>> {
|
||||
val target = args.getChecked<Entity>(0)
|
||||
val motion = args.getChecked<Vec3>(1)
|
||||
return Pair(
|
||||
return Triple(
|
||||
Spell(target, motion),
|
||||
(motion.lengthSqr() * 10_000f).toInt()
|
||||
(motion.lengthSqr() * 10_000f).toInt(),
|
||||
listOf(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ object OpColorize : SpellOperator {
|
|||
val otherHandItem = ctx.caster.getItemInHand(ctx.otherHand)
|
||||
if (CapPreferredColorizer.isColorizer(otherHandItem.item)) {
|
||||
val copied = ItemStack(otherHandItem.item, 1)
|
||||
otherHandItem.shrink(1)
|
||||
ctx.withdrawItem(otherHandItem.item, 1, true)
|
||||
cap.colorizer = copied
|
||||
|
||||
HexMessages.getNetwork().send(PacketDistributor.PLAYER.with { ctx.caster }, MsgColorizerUpdateAck(cap))
|
||||
|
|
|
@ -9,7 +9,7 @@ import net.minecraft.Util
|
|||
import net.minecraft.network.chat.TextComponent
|
||||
|
||||
object OpPrint : Operator {
|
||||
override fun modifyStack(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
val datum = stack[stack.lastIndex]
|
||||
return OperationResult(0, listOf(Spell(datum)))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue