fix OpBreakBlock to work with circles, as well as making it easier to do the same with OpMakeBattery in the future
This commit is contained in:
parent
25402313e7
commit
05d0f928dd
5 changed files with 81 additions and 56 deletions
|
@ -168,14 +168,6 @@ public abstract class CastingEnvironment {
|
|||
return HexUtils.otherHand(this.getCastingHand());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the item in the "other hand."
|
||||
* <p>
|
||||
* If that hand is empty, or if they cannot have that hand, return Empty.
|
||||
* Probably return a clone of Empty, actually...
|
||||
*/
|
||||
public abstract ItemStack getAlternateItem();
|
||||
|
||||
/**
|
||||
* Get all the item stacks this env can use.
|
||||
*/
|
||||
|
@ -251,6 +243,9 @@ public abstract class CastingEnvironment {
|
|||
if (stackOk.test(stack)) {
|
||||
presentCount += stack.getCount();
|
||||
matches.add(stack);
|
||||
|
||||
if (presentCount >= count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (presentCount < count) {
|
||||
|
@ -261,7 +256,7 @@ public abstract class CastingEnvironment {
|
|||
return true;
|
||||
} // Otherwise do the removal
|
||||
|
||||
var remaining = presentCount;
|
||||
var remaining = count;
|
||||
for (ItemStack match : matches) {
|
||||
var toWithdraw = Math.min(match.getCount(), remaining);
|
||||
match.shrink(toWithdraw);
|
||||
|
@ -275,6 +270,12 @@ public abstract class CastingEnvironment {
|
|||
throw new IllegalStateException("unreachable");
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to replace the first stack found which matches the predicate with the stack to replace with.
|
||||
* @return whether it was successful.
|
||||
*/
|
||||
public abstract boolean replaceItem(Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand);
|
||||
|
||||
/**
|
||||
* The order/mode stacks should be discovered in
|
||||
*/
|
||||
|
|
|
@ -15,13 +15,13 @@ import net.minecraft.server.level.ServerLevel;
|
|||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static at.petrak.hexcasting.api.casting.eval.env.PlayerBasedCastEnv.SENTINEL_RADIUS;
|
||||
|
||||
|
@ -128,11 +128,6 @@ public class CircleCastEnv extends CastingEnvironment {
|
|||
return InteractionHand.MAIN_HAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getAlternateItem() {
|
||||
return ItemStack.EMPTY.copy(); // TODO: adjacent inventory/item frame?
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ItemStack> getUsableStacks(StackDiscoveryMode mode) {
|
||||
return new ArrayList<>(); // TODO: Could do something like get items in inventories adjacent to the circle?
|
||||
|
@ -143,6 +138,11 @@ public class CircleCastEnv extends CastingEnvironment {
|
|||
return List.of(); // TODO: Adjacent inv!
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceItem(Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand) {
|
||||
return false; // TODO: Adjacent inv!
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrozenPigment getPigment() {
|
||||
var impetus = this.getImpetus();
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
|
@ -121,6 +122,48 @@ public abstract class PlayerBasedCastEnv extends CastingEnvironment {
|
|||
this.castingHand));
|
||||
}
|
||||
|
||||
ItemStack getAlternateItem() {
|
||||
var otherHand = HexUtils.otherHand(this.castingHand);
|
||||
var stack = this.caster.getItemInHand(otherHand);
|
||||
if (stack.isEmpty()) {
|
||||
return ItemStack.EMPTY.copy();
|
||||
} else {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceItem(Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand) {
|
||||
if (caster == null)
|
||||
return false;
|
||||
|
||||
if (hand != null && stackOk.test(caster.getItemInHand(hand))) {
|
||||
caster.setItemInHand(hand, replaceWith);
|
||||
return true;
|
||||
}
|
||||
|
||||
Inventory inv = this.caster.getInventory();
|
||||
for (int i = inv.items.size() - 1; i >= 0; i--) {
|
||||
if (i != inv.selected) {
|
||||
if (stackOk.test(inv.items.get(i))) {
|
||||
inv.setItem(i, replaceWith);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stackOk.test(caster.getItemInHand(getOtherHand()))) {
|
||||
caster.setItemInHand(getOtherHand(), replaceWith);
|
||||
return true;
|
||||
}
|
||||
if (stackOk.test(caster.getItemInHand(getCastingHand()))) {
|
||||
caster.setItemInHand(getCastingHand(), replaceWith);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVecInRange(Vec3 vec) {
|
||||
var sentinel = HexAPI.instance().getSentinel(this.caster);
|
||||
|
@ -140,17 +183,6 @@ public abstract class PlayerBasedCastEnv extends CastingEnvironment {
|
|||
return this.caster.gameMode.getGameModeForPlayer() != GameType.ADVENTURE && this.world.mayInteract(this.caster, vec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getAlternateItem() {
|
||||
var otherHand = HexUtils.otherHand(this.castingHand);
|
||||
var stack = this.caster.getItemInHand(otherHand);
|
||||
if (stack.isEmpty()) {
|
||||
return ItemStack.EMPTY.copy();
|
||||
} else {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the player's inventory for media ADs and use them.
|
||||
*/
|
||||
|
|
|
@ -31,9 +31,6 @@ object OpMakeBattery : SpellAction {
|
|||
val (handStack, hand) = env.getHeldItemToOperateOn { it.`is`(HexTags.Items.PHIAL_BASE) }
|
||||
?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), null, "bottle") // TODO: hack
|
||||
|
||||
if (hand == null)
|
||||
throw MishapBadOffhandItem.of(handStack, null, "havent_handled_null_hand_yet") // TODO: hack!
|
||||
|
||||
if (!handStack.`is`(HexTags.Items.PHIAL_BASE)) {
|
||||
throw MishapBadOffhandItem.of(
|
||||
handStack,
|
||||
|
@ -64,28 +61,27 @@ object OpMakeBattery : SpellAction {
|
|||
}
|
||||
|
||||
return SpellAction.Result(
|
||||
Spell(entity, hand),
|
||||
Spell(entity, handStack, hand),
|
||||
MediaConstants.CRYSTAL_UNIT,
|
||||
listOf(ParticleSpray.burst(entity.position(), 0.5))
|
||||
)
|
||||
}
|
||||
|
||||
private data class Spell(val itemEntity: ItemEntity, val hand: InteractionHand) : RenderedSpell {
|
||||
private data class Spell(val itemEntity: ItemEntity, val handStack: ItemStack, val hand: InteractionHand?) : RenderedSpell {
|
||||
override fun cast(env: CastingEnvironment) {
|
||||
if (itemEntity.isAlive) {
|
||||
val entityStack = itemEntity.item.copy()
|
||||
val mediamount = extractMedia(entityStack, drainForBatteries = true)
|
||||
if (mediamount > 0) {
|
||||
env.caster?.setItemInHand(
|
||||
hand,
|
||||
ItemMediaHolder.withMedia(ItemStack(HexItems.BATTERY), mediamount, mediamount)
|
||||
) ?: return
|
||||
}
|
||||
if (!itemEntity.isAlive)
|
||||
return
|
||||
|
||||
itemEntity.item = entityStack
|
||||
if (entityStack.isEmpty)
|
||||
itemEntity.kill()
|
||||
val entityStack = itemEntity.item.copy()
|
||||
val mediamount = extractMedia(entityStack, drainForBatteries = true)
|
||||
if (mediamount > 0) {
|
||||
if (!env.replaceItem({ it == handStack }, ItemMediaHolder.withMedia(ItemStack(HexItems.BATTERY), mediamount, mediamount), hand))
|
||||
return
|
||||
}
|
||||
|
||||
itemEntity.item = entityStack
|
||||
if (entityStack.isEmpty)
|
||||
itemEntity.kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
|
|||
import at.petrak.hexcasting.api.casting.getBlockPos
|
||||
import at.petrak.hexcasting.api.casting.iota.Iota
|
||||
import at.petrak.hexcasting.api.casting.mishaps.MishapBadBlock
|
||||
import at.petrak.hexcasting.api.casting.mishaps.MishapBadOffhandItem
|
||||
import at.petrak.hexcasting.api.misc.MediaConstants
|
||||
import at.petrak.hexcasting.xplat.IXplatAbstractions
|
||||
import net.minecraft.core.BlockPos
|
||||
|
@ -16,12 +17,12 @@ import net.minecraft.core.particles.ParticleTypes
|
|||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.item.BlockItem
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.item.context.UseOnContext
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
// TODO: how to handle in cirles
|
||||
object OpPlaceBlock : SpellAction {
|
||||
override val argc: Int
|
||||
get() = 1
|
||||
|
@ -36,8 +37,10 @@ object OpPlaceBlock : SpellAction {
|
|||
val blockHit = BlockHitResult(
|
||||
Vec3.atCenterOf(pos), env.caster?.direction ?: Direction.NORTH, pos, false
|
||||
)
|
||||
val itemUseCtx = env.caster?.let { UseOnContext(it, env.castingHand, blockHit) }
|
||||
?: throw NotImplementedError("how to implement this")
|
||||
val itemUseCtx = env
|
||||
.getHeldItemToOperateOn { it.item is BlockItem }
|
||||
?.stack?.let { UseOnContext(env.world, env.caster, env.castingHand, it, blockHit) }
|
||||
?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, env.castingHand, "placeable")
|
||||
val placeContext = BlockPlaceContext(itemUseCtx)
|
||||
|
||||
val worldState = env.world.getBlockState(pos)
|
||||
|
@ -53,10 +56,10 @@ object OpPlaceBlock : SpellAction {
|
|||
|
||||
private data class Spell(val pos: BlockPos) : RenderedSpell {
|
||||
override fun cast(env: CastingEnvironment) {
|
||||
val caster = env.caster ?: return // TODO: Fix!
|
||||
val caster = env.caster
|
||||
|
||||
val blockHit = BlockHitResult(
|
||||
Vec3.atCenterOf(pos), caster.direction, pos, false
|
||||
Vec3.atCenterOf(pos), caster?.direction ?: Direction.NORTH, pos, false
|
||||
)
|
||||
|
||||
val bstate = env.world.getBlockState(pos)
|
||||
|
@ -67,20 +70,17 @@ object OpPlaceBlock : SpellAction {
|
|||
|
||||
if (!placeeStack.isEmpty) {
|
||||
// https://github.com/VazkiiMods/Psi/blob/master/src/main/java/vazkii/psi/common/spell/trick/block/PieceTrickPlaceBlock.java#L143
|
||||
val oldStack = caster.getItemInHand(env.castingHand)
|
||||
val spoofedStack = placeeStack.copy()
|
||||
|
||||
// we temporarily give the player the stack, place it using mc code, then give them the old stack back.
|
||||
spoofedStack.count = 1
|
||||
caster.setItemInHand(env.castingHand, spoofedStack)
|
||||
|
||||
val itemUseCtx = UseOnContext(caster, env.castingHand, blockHit)
|
||||
val itemUseCtx = UseOnContext(env.world, caster, env.castingHand, spoofedStack, blockHit)
|
||||
val placeContext = BlockPlaceContext(itemUseCtx)
|
||||
if (bstate.canBeReplaced(placeContext)) {
|
||||
if (env.withdrawItem({ it == placeeStack }, 1, false)) {
|
||||
val res = spoofedStack.useOn(placeContext)
|
||||
|
||||
caster.setItemInHand(env.castingHand, oldStack)
|
||||
if (res != InteractionResult.FAIL) {
|
||||
env.withdrawItem({ it == placeeStack }, 1, true)
|
||||
|
||||
|
@ -96,11 +96,7 @@ object OpPlaceBlock : SpellAction {
|
|||
4, 0.1, 0.2, 0.1, 0.1
|
||||
)
|
||||
}
|
||||
} else {
|
||||
caster.setItemInHand(env.castingHand, oldStack)
|
||||
}
|
||||
} else {
|
||||
caster.setItemInHand(env.castingHand, oldStack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue