Merge branch 'minor-patterns' of https://github.com/gamma-delta/HexMod
This commit is contained in:
commit
7b87da018c
84 changed files with 1302 additions and 933 deletions
|
@ -10,6 +10,7 @@ import at.petrak.hexcasting.common.command.HexCommands
|
|||
import at.petrak.hexcasting.common.entities.HexEntities
|
||||
import at.petrak.hexcasting.common.items.HexItems
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.common.lib.HexSounds
|
||||
import at.petrak.hexcasting.common.lib.HexStatistics
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping
|
||||
|
@ -77,6 +78,7 @@ object HexMod {
|
|||
evBus.register(HexCommands::class.java)
|
||||
evBus.register(TickScheduler)
|
||||
evBus.register(HexCapabilities::class.java)
|
||||
evBus.register(HexPlayerDataHelper::class.java)
|
||||
evBus.register(OpFlight)
|
||||
evBus.register(Brainsweeping::class.java)
|
||||
|
||||
|
@ -104,4 +106,4 @@ object HexMod {
|
|||
|
||||
@JvmStatic
|
||||
fun getLogger() = this.LOGGER
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,11 @@ import at.petrak.hexcasting.HexConfig;
|
|||
import at.petrak.hexcasting.api.spell.ParticleSpray;
|
||||
import at.petrak.hexcasting.common.casting.CastingContext;
|
||||
import at.petrak.hexcasting.common.casting.CastingHarness;
|
||||
import at.petrak.hexcasting.common.casting.ManaHelper;
|
||||
import at.petrak.hexcasting.common.casting.SpellCircleContext;
|
||||
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer;
|
||||
import at.petrak.hexcasting.common.items.HexItems;
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities;
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper;
|
||||
import at.petrak.hexcasting.common.lib.HexSounds;
|
||||
import at.petrak.paucal.api.PaucalBlockEntity;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
@ -108,8 +109,7 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
|
|||
this.nextBlock = this.getBlockPos();
|
||||
this.trackedBlocks = new ArrayList<>();
|
||||
this.knownBlocks = new HashSet<>();
|
||||
var maybeCap = activator.getCapability(HexCapabilities.PREFERRED_COLORIZER).resolve();
|
||||
maybeCap.ifPresent(capPreferredColorizer -> this.colorizer = capPreferredColorizer.colorizer);
|
||||
this.colorizer = HexPlayerDataHelper.getColorizer(activator);
|
||||
|
||||
this.level.setBlockAndUpdate(this.getBlockPos(),
|
||||
this.getBlockState().setValue(BlockAbstractImpetus.ENERGIZED, true));
|
||||
|
@ -171,8 +171,10 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
|
|||
|
||||
@Override
|
||||
protected void loadModData(CompoundTag tag) {
|
||||
if (tag.contains(TAG_ACTIVATOR) && tag.contains(TAG_COLORIZER) && tag.contains(TAG_NEXT_BLOCK)
|
||||
&& tag.contains(TAG_TRACKED_BLOCKS)) {
|
||||
if (tag.contains(TAG_ACTIVATOR, Tag.TAG_INT_ARRAY) &&
|
||||
tag.contains(TAG_COLORIZER, Tag.TAG_COMPOUND) &&
|
||||
tag.contains(TAG_NEXT_BLOCK, Tag.TAG_COMPOUND) &&
|
||||
tag.contains(TAG_TRACKED_BLOCKS, Tag.TAG_COMPOUND)) {
|
||||
this.activator = tag.getUUID(TAG_ACTIVATOR);
|
||||
this.colorizer = FrozenColorizer.deserialize(tag.getCompound(TAG_COLORIZER));
|
||||
this.nextBlock = NbtUtils.readBlockPos(tag.getCompound(TAG_NEXT_BLOCK));
|
||||
|
@ -185,12 +187,20 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
|
|||
this.trackedBlocks.add(pos);
|
||||
this.knownBlocks.add(pos);
|
||||
}
|
||||
} else {
|
||||
this.activator = null;
|
||||
this.colorizer = null;
|
||||
this.nextBlock = null;
|
||||
this.foundAll = false;
|
||||
this.trackedBlocks = new ArrayList<>();
|
||||
this.knownBlocks = new HashSet<>();
|
||||
}
|
||||
|
||||
this.mana = tag.getInt(TAG_MANA);
|
||||
if (tag.contains(TAG_LAST_MISHAP)) {
|
||||
if (tag.contains(TAG_LAST_MISHAP, Tag.TAG_STRING)) {
|
||||
this.lastMishap = Component.Serializer.fromJson(tag.getString(TAG_LAST_MISHAP));
|
||||
}
|
||||
} else
|
||||
this.lastMishap = null;
|
||||
}
|
||||
|
||||
void stepCircle() {
|
||||
|
@ -288,6 +298,7 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
|
|||
var harness = new CastingHarness(ctx);
|
||||
|
||||
var castSpell = false;
|
||||
var makeSound = false;
|
||||
BlockPos erroredPos = null;
|
||||
for (var tracked : this.trackedBlocks) {
|
||||
var bs = this.level.getBlockState(tracked);
|
||||
|
@ -297,6 +308,8 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
|
|||
var info = harness.executeNewPattern(newPattern, splayer.getLevel());
|
||||
if (info.getWasSpellCast()) {
|
||||
castSpell = true;
|
||||
if (info.getHasCastingSound())
|
||||
makeSound = true;
|
||||
}
|
||||
if (info.getWasPrevPatternInvalid()) {
|
||||
erroredPos = tracked;
|
||||
|
@ -306,15 +319,17 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
|
|||
}
|
||||
}
|
||||
|
||||
if (castSpell) {
|
||||
if (castSpell && makeSound) {
|
||||
this.level.playSound(null, this.getBlockPos(), HexSounds.SPELL_CIRCLE_CAST.get(), SoundSource.BLOCKS,
|
||||
2f, 1f);
|
||||
}
|
||||
|
||||
if (erroredPos != null) {
|
||||
this.setLastMishap(null);
|
||||
this.setChanged();
|
||||
this.sfx(erroredPos, false);
|
||||
}
|
||||
} else
|
||||
this.setLastMishap(null);
|
||||
|
||||
this.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,8 +506,8 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
|
|||
@NotNull
|
||||
@Override
|
||||
public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) {
|
||||
var manamount = getManaAmount(stack);
|
||||
if (manamount != null) {
|
||||
var manamount = ManaHelper.extractMana(stack, -1, true, simulate);
|
||||
if (manamount > 0) {
|
||||
if (!simulate) {
|
||||
BlockEntityAbstractImpetus.this.mana += manamount;
|
||||
BlockEntityAbstractImpetus.this.setChanged();
|
||||
|
@ -516,23 +531,7 @@ public abstract class BlockEntityAbstractImpetus extends PaucalBlockEntity imple
|
|||
|
||||
@Override
|
||||
public boolean isItemValid(int slot, @NotNull ItemStack stack) {
|
||||
return getManaAmount(stack) != null;
|
||||
}
|
||||
|
||||
// a separate method from the ctx or harness or whatever cause it's different and special
|
||||
private static @Nullable Integer getManaAmount(ItemStack stack) {
|
||||
int baseAmt;
|
||||
if (stack.is(HexItems.AMETHYST_DUST.get())) {
|
||||
baseAmt = HexConfig.dustManaAmount.get();
|
||||
} else if (stack.is(Items.AMETHYST_SHARD)) {
|
||||
baseAmt = HexConfig.shardManaAmount.get();
|
||||
} else if (stack.is(HexItems.CHARGED_AMETHYST.get())) {
|
||||
baseAmt = HexConfig.chargedCrystalManaAmount.get();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return baseAmt * stack.getCount();
|
||||
return ManaHelper.extractMana(stack, -1, false, true) > 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -30,9 +30,14 @@ public interface DataHolder {
|
|||
}
|
||||
}
|
||||
|
||||
boolean canWrite(CompoundTag tag, @Nullable SpellDatum<?> datum);
|
||||
@Nullable
|
||||
default SpellDatum<?> emptyDatum(ItemStack stack) {
|
||||
return null;
|
||||
}
|
||||
|
||||
void writeDatum(CompoundTag tag, @Nullable SpellDatum<?> datum);
|
||||
boolean canWrite(ItemStack stack, @Nullable SpellDatum<?> datum);
|
||||
|
||||
void writeDatum(ItemStack stack, @Nullable SpellDatum<?> datum);
|
||||
|
||||
static void appendHoverText(DataHolder self, ItemStack pStack, List<Component> pTooltipComponents,
|
||||
TooltipFlag pIsAdvanced) {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package at.petrak.hexcasting.api.item;
|
||||
|
||||
public interface IManaReservoir {
|
||||
|
||||
int getMana();
|
||||
int getMaxMana();
|
||||
void setMana(int mana);
|
||||
|
||||
boolean canRecharge();
|
||||
boolean canProvide();
|
||||
|
||||
int getConsumptionPriority();
|
||||
|
||||
boolean canConstructBattery();
|
||||
|
||||
default int withdrawMana(int cost, boolean simulate) {
|
||||
var manaHere = getMana();
|
||||
if (cost < 0)
|
||||
cost = manaHere;
|
||||
if (!simulate) {
|
||||
var manaLeft = manaHere - cost;
|
||||
setMana(manaLeft);
|
||||
}
|
||||
return Math.min(cost, manaHere);
|
||||
}
|
||||
}
|
32
src/main/java/at/petrak/hexcasting/api/item/ManaHolder.java
Normal file
32
src/main/java/at/petrak/hexcasting/api/item/ManaHolder.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package at.petrak.hexcasting.api.item;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
/**
|
||||
* Don't use this interface's methods directly. Instead, use an IManaReservoir capability.
|
||||
*/
|
||||
public interface ManaHolder {
|
||||
int getMana(ItemStack stack);
|
||||
int getMaxMana(ItemStack stack);
|
||||
void setMana(ItemStack stack, int mana);
|
||||
|
||||
boolean manaProvider(ItemStack stack);
|
||||
|
||||
default float getManaFullness(ItemStack stack) {
|
||||
int max = getMaxMana(stack);
|
||||
if (max == 0)
|
||||
return 0;
|
||||
return (float) getMana(stack) / (float) max;
|
||||
}
|
||||
|
||||
default int withdrawMana(ItemStack stack, int cost, boolean simulate) {
|
||||
var manaHere = getMana(stack);
|
||||
if (cost < 0)
|
||||
cost = manaHere;
|
||||
if (!simulate) {
|
||||
var manaLeft = manaHere - cost;
|
||||
setMana(stack, manaLeft);
|
||||
}
|
||||
return Math.min(cost, manaHere);
|
||||
}
|
||||
}
|
19
src/main/java/at/petrak/hexcasting/api/item/SpellHolder.java
Normal file
19
src/main/java/at/petrak/hexcasting/api/item/SpellHolder.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package at.petrak.hexcasting.api.item;
|
||||
|
||||
import at.petrak.hexcasting.hexmath.HexPattern;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SpellHolder extends ManaHolder {
|
||||
|
||||
boolean canDrawManaFromInventory(ItemStack stack);
|
||||
|
||||
@Nullable
|
||||
List<HexPattern> getPatterns(ItemStack stack);
|
||||
|
||||
void writePattern(ItemStack stack, List<HexPattern> patterns, int mana);
|
||||
|
||||
void clearPatterns(ItemStack stack);
|
||||
}
|
|
@ -7,21 +7,24 @@ import at.petrak.hexcasting.common.casting.mishaps.MishapNotEnoughArgs
|
|||
interface SpellOperator : Operator {
|
||||
val argc: Int
|
||||
|
||||
val hasCastingSound: Boolean get() = true
|
||||
|
||||
fun execute(
|
||||
args: List<SpellDatum<*>>,
|
||||
ctx: CastingContext
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>>
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>>?
|
||||
|
||||
override fun operate(stack: MutableList<SpellDatum<*>>, ctx: CastingContext): OperationResult {
|
||||
if (this.argc > stack.size)
|
||||
throw MishapNotEnoughArgs(this.argc, stack.size)
|
||||
val args = stack.takeLast(this.argc)
|
||||
for (_i in 0 until this.argc) stack.removeLast()
|
||||
val (spell, mana, particles) = this.execute(args, ctx)
|
||||
val executeResult = this.execute(args, ctx) ?: return OperationResult(stack, listOf())
|
||||
val (spell, mana, particles) = executeResult
|
||||
|
||||
val sideEffects = mutableListOf(
|
||||
OperatorSideEffect.ConsumeMana(mana),
|
||||
OperatorSideEffect.AttemptSpell(spell, this.isGreat)
|
||||
OperatorSideEffect.AttemptSpell(spell, this.isGreat, this.hasCastingSound)
|
||||
)
|
||||
for (spray in particles) {
|
||||
sideEffects.add(OperatorSideEffect.Particles(spray))
|
||||
|
@ -30,4 +33,4 @@ interface SpellOperator : Operator {
|
|||
return OperationResult(stack, sideEffects)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package at.petrak.hexcasting.client;
|
||||
|
||||
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
|
||||
import at.petrak.hexcasting.common.casting.colors.CapPreferredColorizer;
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.sentinel.CapSentinel;
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.sentinel.Sentinel;
|
||||
import at.petrak.hexcasting.common.items.HexItems;
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities;
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
@ -31,11 +30,10 @@ public class HexAdditionalRenderers {
|
|||
@SubscribeEvent
|
||||
public static void overlayLevel(RenderLevelLastEvent evt) {
|
||||
var player = Minecraft.getInstance().player;
|
||||
var maybeSentinelCap = player.getCapability(HexCapabilities.SENTINEL).resolve();
|
||||
if (maybeSentinelCap.isPresent()) {
|
||||
var cap = maybeSentinelCap.get();
|
||||
if (cap.hasSentinel && player.getLevel().dimension().equals(cap.dimension)) {
|
||||
renderSentinel(cap, player, evt.getPoseStack(), evt.getPartialTick());
|
||||
if (player != null) {
|
||||
var sentinel = HexPlayerDataHelper.getSentinel(player);
|
||||
if (sentinel.hasSentinel() && player.getLevel().dimension().equals(sentinel.dimension())) {
|
||||
renderSentinel(sentinel, player, evt.getPoseStack(), evt.getPartialTick());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +45,8 @@ public class HexAdditionalRenderers {
|
|||
}
|
||||
}
|
||||
|
||||
private static void renderSentinel(CapSentinel sentinel, LocalPlayer owner,
|
||||
PoseStack ps, float partialTicks) {
|
||||
private static void renderSentinel(Sentinel sentinel, LocalPlayer owner,
|
||||
PoseStack ps, float partialTicks) {
|
||||
ps.pushPose();
|
||||
|
||||
// zero vector is the player
|
||||
|
@ -56,9 +54,9 @@ public class HexAdditionalRenderers {
|
|||
var camera = mc.gameRenderer.getMainCamera();
|
||||
var playerPos = camera.getPosition();
|
||||
ps.translate(
|
||||
sentinel.position.x - playerPos.x,
|
||||
sentinel.position.y - playerPos.y,
|
||||
sentinel.position.z - playerPos.z);
|
||||
sentinel.position().x - playerPos.x,
|
||||
sentinel.position().y - playerPos.y,
|
||||
sentinel.position().z - playerPos.z);
|
||||
|
||||
var time = mc.level.getLevelData().getGameTime() + partialTicks;
|
||||
var bobSpeed = 1f / 20;
|
||||
|
@ -66,7 +64,7 @@ public class HexAdditionalRenderers {
|
|||
ps.translate(0, Mth.sin(bobSpeed * time) * magnitude, 0);
|
||||
var spinSpeed = 1f / 30;
|
||||
ps.mulPose(Quaternion.fromXYZ(new Vector3f(0, spinSpeed * time, 0)));
|
||||
if (sentinel.extendsRange) {
|
||||
if (sentinel.extendsRange()) {
|
||||
ps.mulPose(Quaternion.fromXYZ(new Vector3f(spinSpeed * time / 8f, 0, 0)));
|
||||
}
|
||||
|
||||
|
@ -83,21 +81,12 @@ public class HexAdditionalRenderers {
|
|||
RenderSystem.disableCull();
|
||||
RenderSystem.lineWidth(5f);
|
||||
|
||||
var maybeColorizerCap = owner.getCapability(HexCapabilities.PREFERRED_COLORIZER).resolve();
|
||||
CapPreferredColorizer cap = null;
|
||||
if (maybeColorizerCap.isPresent()) {
|
||||
cap = maybeColorizerCap.get();
|
||||
}
|
||||
|
||||
CapPreferredColorizer finalCap = cap;
|
||||
var colorizer = HexPlayerDataHelper.getColorizer(mc.player);
|
||||
BiConsumer<float[], float[]> v = (l, r) -> {
|
||||
int lcolor = -1, rcolor = -1;
|
||||
int lcolor = colorizer.getColor(time, new Vec3(l[0], l[1], l[2])),
|
||||
rcolor = colorizer.getColor(time, new Vec3(r[0], r[1], r[2]));
|
||||
var normal = new Vector3f(r[0] - l[0], r[1] - l[1], r[2] - l[2]);
|
||||
normal.normalize();
|
||||
if (finalCap != null) {
|
||||
lcolor = finalCap.colorizer.getColor(time, new Vec3(l[0], l[1], l[2]));
|
||||
rcolor = finalCap.colorizer.getColor(time, new Vec3(r[0], r[1], r[2]));
|
||||
}
|
||||
buf.vertex(neo, l[0], l[1], l[2])
|
||||
.color(lcolor)
|
||||
.normal(ps.last().normal(), normal.x(), normal.y(), normal.z())
|
||||
|
|
|
@ -8,6 +8,7 @@ import at.petrak.hexcasting.common.items.ItemSlate;
|
|||
import at.petrak.hexcasting.hexmath.HexPattern;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.world.inventory.tooltip.TooltipComponent;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
@ -35,11 +36,11 @@ public class HexTooltips {
|
|||
if (!stack.isEmpty()) {
|
||||
if (stack.is(HexItems.SCROLL.get())) {
|
||||
var tag = stack.getOrCreateTag();
|
||||
if (tag.contains(ItemScroll.TAG_PATTERN)) {
|
||||
if (tag.contains(ItemScroll.TAG_PATTERN, Tag.TAG_COMPOUND)) {
|
||||
var pattern = HexPattern.DeserializeFromNBT(tag.getCompound(ItemScroll.TAG_PATTERN));
|
||||
evt.getTooltipElements().add(Either.right(new PatternTooltipGreeble(
|
||||
pattern,
|
||||
tag.contains(ItemScroll.TAG_OP_ID)
|
||||
tag.contains(ItemScroll.TAG_OP_ID, Tag.TAG_STRING)
|
||||
? PatternTooltipGreeble.ANCIENT_BG : PatternTooltipGreeble.PRISTINE_BG)));
|
||||
}
|
||||
} else if (stack.is(HexItems.SLATE.get()) && ItemSlate.hasPattern(stack)) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.HexConfig;
|
|||
import at.petrak.hexcasting.api.circle.BlockAbstractImpetus;
|
||||
import at.petrak.hexcasting.api.circle.BlockEntityAbstractImpetus;
|
||||
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
|
||||
import at.petrak.hexcasting.api.item.ManaHolder;
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum;
|
||||
import at.petrak.hexcasting.client.be.BlockEntityAkashicBookshelfRenderer;
|
||||
import at.petrak.hexcasting.client.be.BlockEntitySlateRenderer;
|
||||
|
@ -28,18 +29,21 @@ import net.minecraft.client.renderer.item.ItemProperties;
|
|||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.ComparatorBlock;
|
||||
import net.minecraft.world.level.block.RepeaterBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.ComparatorBlockEntity;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.ComparatorMode;
|
||||
import net.minecraftforge.client.event.EntityRenderersEvent;
|
||||
import net.minecraftforge.client.event.ParticleFactoryRegisterEvent;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -89,28 +93,26 @@ public class RegisterClientStuff {
|
|||
return 0f;
|
||||
}
|
||||
});
|
||||
for (RegistryObject<Item> packager : new RegistryObject[]{
|
||||
HexItems.CYPHER,
|
||||
HexItems.TRINKET,
|
||||
HexItems.ARTIFACT,
|
||||
for (ItemPackagedSpell packager : new ItemPackagedSpell[]{
|
||||
HexItems.CYPHER.get(),
|
||||
HexItems.TRINKET.get(),
|
||||
HexItems.ARTIFACT.get(),
|
||||
}) {
|
||||
ItemProperties.register(packager.get(), ItemPackagedSpell.HAS_PATTERNS_PRED,
|
||||
ItemProperties.register(packager, ItemPackagedSpell.HAS_PATTERNS_PRED,
|
||||
(stack, level, holder, holderID) ->
|
||||
stack.getOrCreateTag().contains(ItemPackagedSpell.TAG_PATTERNS) ? 1f : 0f
|
||||
packager.getPatterns(stack) != null ? 1f : 0f
|
||||
);
|
||||
}
|
||||
|
||||
ItemProperties.register(HexItems.BATTERY.get(), ItemManaBattery.MANA_PREDICATE,
|
||||
(stack, level, holder, holderID) -> {
|
||||
var item = (ItemManaBattery) stack.getItem();
|
||||
var tag = stack.getOrCreateTag();
|
||||
return item.getManaFullness(tag);
|
||||
var item = (ManaHolder) stack.getItem();
|
||||
return item.getManaFullness(stack);
|
||||
});
|
||||
ItemProperties.register(HexItems.BATTERY.get(), ItemManaBattery.MAX_MANA_PREDICATE,
|
||||
(stack, level, holder, holderID) -> {
|
||||
var item = (ItemManaBattery) stack.getItem();
|
||||
var tag = stack.getOrCreateTag();
|
||||
var max = item.getMaxManaAmt(tag);
|
||||
var max = item.getMaxMana(stack);
|
||||
return (float) Math.sqrt((float) max / HexConfig.chargedCrystalManaAmount.get() / 10);
|
||||
});
|
||||
|
||||
|
@ -202,6 +204,34 @@ public class RegisterClientStuff {
|
|||
new TextComponent(String.valueOf(state.getValue(BlockStateProperties.POWER)))
|
||||
.withStyle(ChatFormatting.RED))
|
||||
));
|
||||
|
||||
ScryingLensOverlayRegistry.addDisplayer(Blocks.COMPARATOR,
|
||||
(state, pos, observer, world, lensHand) -> {
|
||||
BlockEntity be = world.getBlockEntity(pos);
|
||||
if (be instanceof ComparatorBlockEntity comparator) {
|
||||
return List.of(
|
||||
new Pair<>(
|
||||
new ItemStack(Items.REDSTONE),
|
||||
new TextComponent(String.valueOf(comparator.getOutputSignal()))
|
||||
.withStyle(ChatFormatting.RED)),
|
||||
new Pair<>(
|
||||
new ItemStack(Items.REDSTONE_TORCH),
|
||||
new TextComponent(state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE ? ">" : "-")
|
||||
.withStyle(ChatFormatting.RED)));
|
||||
} else
|
||||
return List.of();
|
||||
});
|
||||
|
||||
ScryingLensOverlayRegistry.addDisplayer(Blocks.REPEATER,
|
||||
(state, pos, observer, world, lensHand) -> List.of(
|
||||
new Pair<>(
|
||||
new ItemStack(Items.REDSTONE),
|
||||
new TextComponent(String.valueOf(state.getValue(RepeaterBlock.POWERED) ? 15 : 0))
|
||||
.withStyle(ChatFormatting.RED)),
|
||||
new Pair<>(
|
||||
new ItemStack(Items.CLOCK),
|
||||
new TextComponent(String.valueOf(state.getValue(RepeaterBlock.DELAY)))
|
||||
.withStyle(ChatFormatting.YELLOW))));
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
|
|
|
@ -184,7 +184,7 @@ class GuiSpellcasting(private val handOpenedWith: InteractionHand,
|
|||
if (playSound) {
|
||||
Minecraft.getInstance().soundManager.play(
|
||||
SimpleSoundInstance(
|
||||
HexSounds.START_PATTERN.get(),
|
||||
HexSounds.ADD_LINE.get(),
|
||||
SoundSource.PLAYERS,
|
||||
0.25f,
|
||||
1f + (Math.random().toFloat() - 0.5f) * 0.1f,
|
||||
|
|
|
@ -103,6 +103,7 @@ public class ConjureParticle extends TextureSheetParticle {
|
|||
public void begin(BufferBuilder buf, TextureManager texMan) {
|
||||
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
|
||||
RenderSystem.depthMask(false);
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ class GridSoundInstance(val player: Player) : AbstractTickableSoundInstance(HexS
|
|||
val normalVector = calculateVectorFromPitchAndYaw(player.xRot, player.yRot)
|
||||
val newPos = player.eyePosition
|
||||
.add(normalVector)
|
||||
.add(horizontalPlanarVector.scale(2 * (mousePosX - 0.5)))
|
||||
.add(verticalPlanarVector.scale(2 * (mousePosY - 0.5)))
|
||||
.add(horizontalPlanarVector.scale(PAN_SCALE * 2 * (mousePosX - 0.5)))
|
||||
.add(verticalPlanarVector.scale(PAN_SCALE * 2 * (mousePosY - 0.5)))
|
||||
this.x = newPos.x
|
||||
this.y = newPos.y
|
||||
this.z = newPos.z
|
||||
|
@ -57,4 +57,8 @@ class GridSoundInstance(val player: Player) : AbstractTickableSoundInstance(HexS
|
|||
val azimuthVertical = Mth.sin(radiansPitch).toDouble()
|
||||
return Vec3(zComponent * azimuthHorizontal, -azimuthVertical, xComponent * azimuthHorizontal)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PAN_SCALE = 0.5
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,9 +92,7 @@ public class BlockEntityConjured extends PaucalBlockEntity {
|
|||
|
||||
@Override
|
||||
protected void loadModData(CompoundTag tag) {
|
||||
if (tag.contains(TAG_COLORIZER)) {
|
||||
this.setColorizer(FrozenColorizer.deserialize(tag.getCompound(TAG_COLORIZER)));
|
||||
}
|
||||
this.setColorizer(FrozenColorizer.deserialize(tag.getCompound(TAG_COLORIZER)));
|
||||
}
|
||||
|
||||
public FrozenColorizer getColorizer() {
|
||||
|
|
|
@ -55,7 +55,7 @@ public class BlockAkashicBookshelf extends BlockAkashicFloodfiller implements En
|
|||
var stack = pPlayer.getItemInHand(pHand);
|
||||
if (stack.getItem() instanceof ItemScroll scroll) {
|
||||
if (!pLevel.isClientSide()) {
|
||||
scroll.writeDatum(stack.getOrCreateTag(), SpellDatum.make(shelf.getPattern()));
|
||||
scroll.writeDatum(stack, SpellDatum.make(shelf.getPattern()));
|
||||
}
|
||||
pLevel.playSound(pPlayer, pPos, HexSounds.SCROLL_SCRIBBLE.get(), SoundSource.BLOCKS, 1f, 1f);
|
||||
return InteractionResult.sidedSuccess(pLevel.isClientSide);
|
||||
|
|
|
@ -5,6 +5,7 @@ import at.petrak.hexcasting.hexmath.HexPattern;
|
|||
import at.petrak.paucal.api.PaucalBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -29,14 +30,14 @@ public class BlockEntitySlate extends PaucalBlockEntity {
|
|||
|
||||
@Override
|
||||
protected void loadModData(CompoundTag tag) {
|
||||
if (tag.contains(TAG_PATTERN)) {
|
||||
if (tag.contains(TAG_PATTERN, Tag.TAG_COMPOUND)) {
|
||||
CompoundTag patternTag = tag.getCompound(TAG_PATTERN);
|
||||
if (HexPattern.IsHexPattern(patternTag))
|
||||
this.pattern = HexPattern.DeserializeFromNBT(patternTag);
|
||||
else
|
||||
this.pattern = null;
|
||||
|
||||
}
|
||||
} else
|
||||
this.pattern = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ public class BlockSlate extends BlockCircleComponent implements EntityBlock, Sim
|
|||
if (be instanceof BlockEntitySlate slate) {
|
||||
ItemStack stack = new ItemStack(HexItems.SLATE.get());
|
||||
if (slate.pattern != null)
|
||||
HexItems.SLATE.get().writeDatum(stack.getOrCreateTag(), SpellDatum.make(slate.pattern));
|
||||
HexItems.SLATE.get().writeDatum(stack, SpellDatum.make(slate.pattern));
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
|||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
|
@ -79,8 +80,9 @@ public class BlockEntityStoredPlayerImpetus extends BlockEntityAbstractImpetus {
|
|||
@Override
|
||||
protected void loadModData(CompoundTag tag) {
|
||||
super.loadModData(tag);
|
||||
if (tag.contains(TAG_STORED_PLAYER)) {
|
||||
if (tag.contains(TAG_STORED_PLAYER, Tag.TAG_INT_ARRAY)) {
|
||||
this.storedPlayer = tag.getUUID(TAG_STORED_PLAYER);
|
||||
}
|
||||
} else
|
||||
this.storedPlayer = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import at.petrak.hexcasting.common.casting.mishaps.MishapEntityTooFarAway
|
|||
import at.petrak.hexcasting.common.casting.mishaps.MishapEvalTooDeep
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapLocationTooFarAway
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.common.lib.RegisterHelper.prefix
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
@ -38,15 +39,15 @@ data class CastingContext(
|
|||
|
||||
private val entitiesGivenMotion = mutableSetOf<Entity>()
|
||||
|
||||
inline fun getHeldItemToOperateOn(acceptItemIf: (ItemStack) -> Boolean): ItemStack {
|
||||
inline fun getHeldItemToOperateOn(acceptItemIf: (ItemStack) -> Boolean): Pair<ItemStack, InteractionHand> {
|
||||
if (this.spellCircle == null) {
|
||||
return caster.getItemInHand(otherHand)
|
||||
return caster.getItemInHand(otherHand) to otherHand
|
||||
}
|
||||
|
||||
val handItem = caster.getItemInHand(castingHand)
|
||||
if (!acceptItemIf(handItem))
|
||||
return caster.getItemInHand(otherHand)
|
||||
return handItem
|
||||
return caster.getItemInHand(otherHand) to otherHand
|
||||
return handItem to castingHand
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,16 +80,14 @@ data class CastingContext(
|
|||
}
|
||||
|
||||
fun isVecInRange(vec: Vec3): Boolean {
|
||||
val maybeSentinel = this.caster.getCapability(HexCapabilities.SENTINEL).resolve()
|
||||
if (maybeSentinel.isPresent) {
|
||||
val sentinel = maybeSentinel.get()
|
||||
if (sentinel.hasSentinel
|
||||
&& sentinel.extendsRange
|
||||
&& world.dimension() == sentinel.dimension
|
||||
&& vec.distanceToSqr(sentinel.position) < Operator.MAX_DISTANCE_FROM_SENTINEL * Operator.MAX_DISTANCE_FROM_SENTINEL
|
||||
)
|
||||
return true
|
||||
}
|
||||
val sentinel = HexPlayerDataHelper.getSentinel(caster)
|
||||
if (sentinel.hasSentinel
|
||||
&& sentinel.extendsRange
|
||||
&& world.dimension() == sentinel.dimension
|
||||
&& vec.distanceToSqr(sentinel.position) < Operator.MAX_DISTANCE_FROM_SENTINEL * Operator.MAX_DISTANCE_FROM_SENTINEL
|
||||
)
|
||||
return true
|
||||
|
||||
|
||||
if (this.spellCircle != null) {
|
||||
// we use the eye position cause thats where the caster gets their "position" from
|
||||
|
@ -152,8 +151,9 @@ data class CastingContext(
|
|||
|
||||
val inv = this.caster.inventory
|
||||
// TODO: withdraw from ender chest given a specific ender charm?
|
||||
val stacksToExamine = inv.items.asReversed().toMutableList()
|
||||
val stacksToExamine = inv.items.toMutableList().apply { removeAt(inv.selected) }.asReversed().toMutableList()
|
||||
stacksToExamine.addAll(inv.offhand)
|
||||
stacksToExamine.add(inv.getSelected())
|
||||
|
||||
fun matches(stack: ItemStack): Boolean =
|
||||
!stack.isEmpty && stack.`is`(item)
|
||||
|
|
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.HexConfig
|
|||
import at.petrak.hexcasting.HexMod
|
||||
import at.petrak.hexcasting.api.PatternRegistry
|
||||
import at.petrak.hexcasting.api.circle.BlockEntityAbstractImpetus
|
||||
import at.petrak.hexcasting.api.item.SpellHolder
|
||||
import at.petrak.hexcasting.api.spell.Operator
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
|
@ -14,6 +15,7 @@ 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.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.common.lib.HexStatistics
|
||||
import at.petrak.hexcasting.datagen.HexAdvancements
|
||||
import at.petrak.hexcasting.hexmath.HexPattern
|
||||
|
@ -112,6 +114,7 @@ class CastingHarness private constructor(
|
|||
fun performSideEffects(sideEffects: List<OperatorSideEffect>): ControllerInfo {
|
||||
var wasSpellCast = false
|
||||
var wasPrevPatternInvalid = false
|
||||
var hasCastingSound = false
|
||||
for (haskellProgrammersShakingandCryingRN in sideEffects) {
|
||||
val mustStop = haskellProgrammersShakingandCryingRN.performEffect(this)
|
||||
if (mustStop) {
|
||||
|
@ -120,12 +123,16 @@ class CastingHarness private constructor(
|
|||
}
|
||||
|
||||
|
||||
if (haskellProgrammersShakingandCryingRN is OperatorSideEffect.AttemptSpell)
|
||||
if (haskellProgrammersShakingandCryingRN is OperatorSideEffect.AttemptSpell) {
|
||||
wasSpellCast = true
|
||||
if (haskellProgrammersShakingandCryingRN.hasCastingSound)
|
||||
hasCastingSound = true
|
||||
}
|
||||
}
|
||||
|
||||
return ControllerInfo(
|
||||
wasSpellCast,
|
||||
hasCastingSound,
|
||||
this.stack.isEmpty() && this.parenCount == 0 && !this.escapeNext,
|
||||
wasPrevPatternInvalid,
|
||||
generateDescs()
|
||||
|
@ -268,13 +275,13 @@ class CastingHarness private constructor(
|
|||
} else {
|
||||
val casterStack = this.ctx.caster.getItemInHand(this.ctx.castingHand)
|
||||
val casterItem = casterStack.item
|
||||
val ipsCanDrawFromInv = if (casterItem is ItemPackagedSpell) {
|
||||
val tag = casterStack.orCreateTag
|
||||
val manaAvailable = tag.getInt(ItemPackagedSpell.TAG_MANA)
|
||||
val ipsCanDrawFromInv = if (casterItem is SpellHolder) {
|
||||
val mana = casterStack.getCapability(HexCapabilities.MANA).resolve().get()
|
||||
val manaAvailable = mana.mana
|
||||
val manaToTake = min(costLeft, manaAvailable)
|
||||
tag.putInt(ItemPackagedSpell.TAG_MANA, manaAvailable - manaToTake)
|
||||
mana.mana = manaAvailable - manaToTake
|
||||
costLeft -= manaToTake
|
||||
casterItem.canDrawManaFromInventory()
|
||||
casterItem.canDrawManaFromInventory(casterStack)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -283,7 +290,7 @@ class CastingHarness private constructor(
|
|||
.filter(ManaHelper::isManaItem)
|
||||
.sortedWith(Comparator(ManaHelper::compare).reversed())
|
||||
for (stack in manableItems) {
|
||||
costLeft -= ManaHelper.extractMana(stack, costLeft)!!
|
||||
costLeft -= ManaHelper.extractMana(stack, costLeft)
|
||||
if (costLeft <= 0)
|
||||
break
|
||||
}
|
||||
|
@ -319,12 +326,7 @@ class CastingHarness private constructor(
|
|||
if (this.prepackagedColorizer != null)
|
||||
return this.prepackagedColorizer
|
||||
|
||||
val maybeCap = this.ctx.caster.getCapability(HexCapabilities.PREFERRED_COLORIZER).resolve()
|
||||
if (maybeCap.isEmpty) {
|
||||
// uh oh
|
||||
return FrozenColorizer.DEFAULT
|
||||
}
|
||||
return maybeCap.get().colorizer
|
||||
return HexPlayerDataHelper.getColorizer(ctx.caster)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ import net.minecraft.network.chat.Component
|
|||
*/
|
||||
data class ControllerInfo(
|
||||
val wasSpellCast: Boolean,
|
||||
val hasCastingSound: Boolean,
|
||||
val isStackClear: Boolean,
|
||||
val wasPrevPatternInvalid: Boolean,
|
||||
val stackDesc: List<Component>
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,99 +1,57 @@
|
|||
package at.petrak.hexcasting.common.casting
|
||||
|
||||
import at.petrak.hexcasting.HexConfig
|
||||
import at.petrak.hexcasting.common.items.HexItems
|
||||
import at.petrak.hexcasting.common.items.magic.ItemManaBattery
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object ManaHelper {
|
||||
@JvmStatic
|
||||
fun isManaItem(stack: ItemStack): Boolean {
|
||||
return stack.`is`(HexItems.AMETHYST_DUST.get())
|
||||
|| stack.`is`(Items.AMETHYST_SHARD)
|
||||
|| stack.`is`(HexItems.CHARGED_AMETHYST.get())
|
||||
|| stack.item is ItemManaBattery
|
||||
return stack.getCapability(HexCapabilities.MANA).map { it.canProvide() }.orElse(false) && extractMana(stack, simulate = true) > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to extract the given amount of mana from this item.
|
||||
* This may mutate the itemstack.
|
||||
* Extract [cost] mana from [stack]. If [cost] is less than zero, extract all mana instead.
|
||||
* This may mutate [stack] (and may consume it) unless [simulate] is set.
|
||||
*
|
||||
* Return the actual amount of mana extracted, or null if this cannot have mana extracted.
|
||||
*/
|
||||
fun extractMana(stack: ItemStack, cost: Int): Int? {
|
||||
val base = when (stack.item) {
|
||||
HexItems.AMETHYST_DUST.get() -> HexConfig.dustManaAmount.get()
|
||||
Items.AMETHYST_SHARD -> HexConfig.shardManaAmount.get()
|
||||
HexItems.CHARGED_AMETHYST.get() -> HexConfig.chargedCrystalManaAmount.get()
|
||||
HexItems.BATTERY.get() -> {
|
||||
val battery = stack.item as ItemManaBattery
|
||||
return battery.withdrawMana(stack.orCreateTag, cost)
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
val itemsReqd = ceil(cost.toFloat() / base.toFloat()).toInt()
|
||||
val actualItemsConsumed = min(stack.count, itemsReqd)
|
||||
stack.shrink(actualItemsConsumed)
|
||||
return base * actualItemsConsumed
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the entirety of the mana out of this.
|
||||
* This may mutate the itemstack (and will probably consume it).
|
||||
* If [drainForBatteries] is false, this will only consider forms of mana that can be used to make new batteries.
|
||||
*
|
||||
* Return the amount of mana extracted, or null if this cannot have mana extracted.
|
||||
* Return the amount of mana extracted. This may be over [cost] if mana is wasted.
|
||||
*/
|
||||
fun extractAllMana(stack: ItemStack): Int? {
|
||||
val base = when (stack.item) {
|
||||
HexItems.AMETHYST_DUST.get() -> HexConfig.dustManaAmount.get()
|
||||
Items.AMETHYST_SHARD -> HexConfig.shardManaAmount.get()
|
||||
HexItems.CHARGED_AMETHYST.get() -> HexConfig.chargedCrystalManaAmount.get()
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun extractMana(stack: ItemStack, cost: Int = -1, drainForBatteries: Boolean = false, simulate: Boolean = false): Int {
|
||||
val manaCapability = stack.getCapability(HexCapabilities.MANA).resolve()
|
||||
|
||||
HexItems.BATTERY.get() -> {
|
||||
val battery = stack.item as ItemManaBattery
|
||||
val tag = stack.orCreateTag
|
||||
val manaThere = battery.getManaAmt(tag)
|
||||
return battery.withdrawMana(tag, manaThere)
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
val count = stack.count
|
||||
stack.shrink(count)
|
||||
return base * count
|
||||
if (!manaCapability.isPresent)
|
||||
return 0
|
||||
|
||||
val manaReservoir = manaCapability.get()
|
||||
|
||||
if (drainForBatteries && !manaReservoir.canConstructBattery())
|
||||
return 0
|
||||
|
||||
return manaReservoir.withdrawMana(cost, simulate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorted from least important to most important
|
||||
*/
|
||||
fun compare(astack: ItemStack, bstack: ItemStack): Int {
|
||||
val aitem = astack.item
|
||||
val bitem = bstack.item
|
||||
val aMana = astack.getCapability(HexCapabilities.MANA).resolve()
|
||||
val bMana = bstack.getCapability(HexCapabilities.MANA).resolve()
|
||||
|
||||
return if (aitem != bitem) {
|
||||
fun intcode(item: Item): Int =
|
||||
when (item) {
|
||||
HexItems.CHARGED_AMETHYST.get() -> 1
|
||||
Items.AMETHYST_SHARD -> 2
|
||||
HexItems.AMETHYST_DUST.get() -> 3
|
||||
HexItems.BATTERY.get() -> 4
|
||||
else -> 0
|
||||
}
|
||||
intcode(aitem) - intcode(bitem)
|
||||
} else if (aitem == HexItems.BATTERY.get()) {
|
||||
val atag = astack.orCreateTag
|
||||
val btag = bstack.orCreateTag
|
||||
val battery = aitem as ItemManaBattery
|
||||
battery.getManaAmt(atag) - battery.getManaAmt(btag)
|
||||
return if (astack.item != bstack.item) {
|
||||
aMana.map { it.consumptionPriority }.orElse(0) - bMana.map { it.consumptionPriority }.orElse(0)
|
||||
} else if (aMana.isPresent && bMana.isPresent) {
|
||||
aMana.get().mana - bMana.get().mana
|
||||
} else {
|
||||
astack.count - bstack.count
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun barColor(mana: Int, maxMana: Int): Int {
|
||||
val amt = if (maxMana == 0) {
|
||||
0f
|
||||
|
@ -107,6 +65,7 @@ object ManaHelper {
|
|||
return Mth.color(r / 255f, g / 255f, b / 255f)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun barWidth(mana: Int, maxMana: Int): Int {
|
||||
val amt = if (maxMana == 0) {
|
||||
0f
|
||||
|
@ -115,4 +74,4 @@ object ManaHelper {
|
|||
}
|
||||
return (13f * amt).roundToInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ sealed class OperatorSideEffect {
|
|||
abstract fun performEffect(harness: CastingHarness): Boolean
|
||||
|
||||
/** Try to cast a spell */
|
||||
data class AttemptSpell(val spell: RenderedSpell, val isGreat: Boolean) : OperatorSideEffect() {
|
||||
data class AttemptSpell(val spell: RenderedSpell, val isGreat: Boolean, val hasCastingSound: Boolean = true) : OperatorSideEffect() {
|
||||
override fun performEffect(harness: CastingHarness): Boolean {
|
||||
return if (this.isGreat && !harness.ctx.isCasterEnlightened) {
|
||||
harness.ctx.caster.sendMessage(
|
||||
|
@ -94,4 +94,4 @@ sealed class OperatorSideEffect {
|
|||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,9 +135,11 @@ public class RegisterPatterns {
|
|||
OpIdentityKindOf.INSTANCE);
|
||||
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("ewq", HexDir.EAST), prefix("floor"),
|
||||
OpFloor.INSTANCE);
|
||||
OpFloor.INSTANCE);
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qwe", HexDir.EAST), prefix("ceil"),
|
||||
OpCeil.INSTANCE);
|
||||
OpCeil.INSTANCE);
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("eqaqe", HexDir.NORTH_WEST), prefix("logarithm"),
|
||||
OpLog.INSTANCE);
|
||||
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qqqqqaa", HexDir.SOUTH_EAST), prefix("sin"),
|
||||
OpSin.INSTANCE);
|
||||
|
@ -153,7 +155,7 @@ public class RegisterPatterns {
|
|||
OpArcTan.INSTANCE);
|
||||
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("eqqq", HexDir.NORTH_WEST), prefix("random"),
|
||||
OpRandom.INSTANCE);
|
||||
OpRandom.INSTANCE);
|
||||
|
||||
// == Spells ==
|
||||
|
||||
|
@ -197,6 +199,9 @@ public class RegisterPatterns {
|
|||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wqaqwd", HexDir.NORTH_EAST), prefix("edify"),
|
||||
OpEdifySapling.INSTANCE);
|
||||
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("adaa", HexDir.WEST), prefix("beep"),
|
||||
OpBeep.INSTANCE);
|
||||
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("waqqqqq", HexDir.EAST), prefix("craft/cypher"),
|
||||
new OpMakePackagedSpell<>(HexItems.CYPHER.get(), 100_000));
|
||||
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("wwaqqqqqeaqeaeqqqeaeq", HexDir.EAST),
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
package at.petrak.hexcasting.common.casting.colors;
|
||||
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The colorizer item favored by this player.
|
||||
*/
|
||||
public class CapPreferredColorizer implements ICapabilitySerializable<CompoundTag> {
|
||||
public static final String CAP_NAME = "preferred_colorizer";
|
||||
public static final String TAG_COLOR = "colorizer";
|
||||
|
||||
public FrozenColorizer colorizer;
|
||||
|
||||
public CapPreferredColorizer(FrozenColorizer colorizer) {
|
||||
this.colorizer = colorizer;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||
return HexCapabilities.PREFERRED_COLORIZER.orEmpty(cap, LazyOptional.of(() -> this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeNBT() {
|
||||
var tag = new CompoundTag();
|
||||
tag.put(TAG_COLOR, this.colorizer.serialize());
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag nbt) {
|
||||
if (nbt.contains(TAG_COLOR, Tag.TAG_COMPOUND)) {
|
||||
var colorizerTag = nbt.getCompound(TAG_COLOR);
|
||||
this.colorizer = FrozenColorizer.deserialize(colorizerTag);
|
||||
} else {
|
||||
this.colorizer = FrozenColorizer.DEFAULT;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,10 @@ import java.util.UUID;
|
|||
* A colorizer item and the player who owned it at the time of making the color.
|
||||
*/
|
||||
public record FrozenColorizer(Item item, UUID owner) {
|
||||
private static final int[] MINIMUM_LUMINANCE_COLOR_WHEEL = {
|
||||
0xFF200000, 0xFF202000, 0xFF002000, 0xFF002020, 0xFF000020, 0xFF200020
|
||||
};
|
||||
|
||||
public static final String TAG_ITEM = "item";
|
||||
public static final String TAG_OWNER = "owner";
|
||||
|
||||
|
@ -38,6 +42,8 @@ public record FrozenColorizer(Item item, UUID owner) {
|
|||
}
|
||||
|
||||
public static FrozenColorizer deserialize(CompoundTag tag) {
|
||||
if (tag.isEmpty())
|
||||
return FrozenColorizer.DEFAULT;
|
||||
try {
|
||||
var itemID = new ResourceLocation(tag.getString(TAG_ITEM));
|
||||
var item = ForgeRegistries.ITEMS.getValue(itemID);
|
||||
|
@ -55,11 +61,36 @@ public record FrozenColorizer(Item item, UUID owner) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets a color with a minimum luminance applied.
|
||||
* @param time absolute world time in ticks
|
||||
* @param position a position for the icosahedron, a randomish number for particles.
|
||||
* @return an AARRGGBB color.
|
||||
*/
|
||||
public int getColor(float time, Vec3 position) {
|
||||
int raw = getRawColor(time, position);
|
||||
|
||||
int r = (raw & 0xFF0000) >> 16;
|
||||
int g = (raw & 0xFF00) >> 8;
|
||||
int b = (raw & 0xFF);
|
||||
double luminance = 0.2126 * r / 0xFF + 0.7152 * g / 0xFF + 0.0722 * b / 0xFF; // Standard relative luminance calculation
|
||||
|
||||
if (luminance < 0.1) {
|
||||
int rawMod = morphBetweenColors(MINIMUM_LUMINANCE_COLOR_WHEEL, new Vec3(0.1, 0.1, 0.1), time / 20 / 20, position);
|
||||
|
||||
r += (rawMod & 0xFF0000) >> 16;
|
||||
g += (rawMod & 0xFF00) >> 8;
|
||||
b += (rawMod & 0xFF);
|
||||
}
|
||||
|
||||
return 0xff_000000 | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param time absolute world time in ticks
|
||||
* @param position a position for the icosahedron, a randomish number for particles.
|
||||
* @return an AARRGGBB color.
|
||||
*/
|
||||
public int getRawColor(float time, Vec3 position) {
|
||||
if (this.item instanceof ItemDyeColorizer dye) {
|
||||
return dye.getDyeColor().getTextColor() | 0xff_000000;
|
||||
} else if (this.item instanceof ItemPrideColorizer politics) {
|
||||
|
|
|
@ -5,16 +5,17 @@ import at.petrak.hexcasting.common.casting.CastingContext
|
|||
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class MishapBadOffhandItem(val item: ItemStack, val wanted: Component) : Mishap() {
|
||||
class MishapBadOffhandItem(val item: ItemStack, val hand: InteractionHand, val wanted: Component) : Mishap() {
|
||||
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
|
||||
dyeColor(DyeColor.BROWN)
|
||||
|
||||
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
|
||||
val item = ctx.caster.getItemInHand(ctx.otherHand).copy()
|
||||
ctx.caster.setItemInHand(ctx.otherHand, ItemStack.EMPTY.copy())
|
||||
val item = ctx.caster.getItemInHand(hand).copy()
|
||||
ctx.caster.setItemInHand(hand, ItemStack.EMPTY.copy())
|
||||
|
||||
val delta = ctx.caster.lookAngle.scale(0.5)
|
||||
yeetItem(item, ctx, delta)
|
||||
|
@ -29,8 +30,8 @@ class MishapBadOffhandItem(val item: ItemStack, val wanted: Component) : Mishap(
|
|||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun of(item: ItemStack, stub: String, vararg args: Any): MishapBadOffhandItem {
|
||||
return MishapBadOffhandItem(item, TranslatableComponent("hexcasting.mishap.bad_item.$stub", *args))
|
||||
fun of(item: ItemStack, hand: InteractionHand, stub: String, vararg args: Any): MishapBadOffhandItem {
|
||||
return MishapBadOffhandItem(item, hand, TranslatableComponent("hexcasting.mishap.bad_item.$stub", *args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ class MishapInvalidIota(
|
|||
@JvmStatic
|
||||
fun ofClass(perpetrator: SpellDatum<*>, reverseIdx: Int, cls: Class<*>): MishapInvalidIota {
|
||||
val key = "hexcasting.mishap.invalid_value.class." + when {
|
||||
Double::class.java.isAssignableFrom(cls) -> "double"
|
||||
Double::class.java.isAssignableFrom(cls) || Double::class.javaObjectType.isAssignableFrom(cls) -> "double"
|
||||
Vec3::class.java.isAssignableFrom(cls) -> "vector"
|
||||
List::class.java.isAssignableFrom(cls) -> "list"
|
||||
Widget::class.java.isAssignableFrom(cls) -> "widget"
|
||||
|
@ -66,4 +66,4 @@ class MishapInvalidIota(
|
|||
return MishapInvalidIota(perpetrator, reverseIdx, TranslatableComponent(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,15 @@ object OpRead : ConstManaOperator {
|
|||
override val argc = 0
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val handStack = ctx.getHeldItemToOperateOn {
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn {
|
||||
val item = it.item
|
||||
item is DataHolder && item.readDatum(it, ctx.world) != null
|
||||
item is DataHolder && (item.readDatum(it, ctx.world) != null || item.emptyDatum(it) != null)
|
||||
}
|
||||
|
||||
val handItem = handStack.item
|
||||
val datum = (handItem as? DataHolder)?.readDatum(handStack, ctx.world) ?: throw MishapBadOffhandItem.of(handStack, "iota.read")
|
||||
val datum = (handItem as? DataHolder)?.readDatum(handStack, ctx.world)
|
||||
?: (handItem as? DataHolder)?.emptyDatum(handStack)
|
||||
?: throw MishapBadOffhandItem.of(handStack, hand, "iota.read")
|
||||
|
||||
return listOf(datum)
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ object OpTheCoolerRead : ConstManaOperator {
|
|||
ctx.assertEntityInRange(target)
|
||||
|
||||
|
||||
val datum = item.readDatum(stack, ctx.world) ?: throw MishapBadItem.of(stack, "iota.read")
|
||||
val datum = item.readDatum(stack, ctx.world)
|
||||
?: item.emptyDatum(stack)
|
||||
?: throw MishapBadItem.of(stack, "iota.read")
|
||||
return listOf(datum)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,19 +20,17 @@ object OpWrite : SpellOperator {
|
|||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val datum = args[0]
|
||||
|
||||
val handStack = ctx.getHeldItemToOperateOn {
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn {
|
||||
val item = it.item
|
||||
if (item is DataHolder) {
|
||||
val tag = it.orCreateTag
|
||||
item.canWrite(tag, datum)
|
||||
item.canWrite(it, datum)
|
||||
} else false
|
||||
}
|
||||
|
||||
val handItem = handStack.item as? DataHolder ?: throw MishapBadOffhandItem.of(handStack, "iota.write")
|
||||
val tag = handStack.orCreateTag
|
||||
val handItem = handStack.item as? DataHolder ?: throw MishapBadOffhandItem.of(handStack, hand, "iota.write")
|
||||
|
||||
if (!handItem.canWrite(tag, datum))
|
||||
throw MishapBadOffhandItem.of(handStack, "iota.readonly", datum.display())
|
||||
if (!handItem.canWrite(handStack, datum))
|
||||
throw MishapBadOffhandItem.of(handStack, hand, "iota.readonly", datum.display())
|
||||
|
||||
val trueName = MishapOthersName.getTrueNameFromDatum(datum, ctx.caster)
|
||||
if (trueName != null)
|
||||
|
@ -47,18 +45,16 @@ object OpWrite : SpellOperator {
|
|||
|
||||
private data class Spell(val datum: SpellDatum<*>) : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
val handStack = ctx.getHeldItemToOperateOn {
|
||||
val (handStack) = ctx.getHeldItemToOperateOn {
|
||||
val item = it.item
|
||||
if (item is DataHolder) {
|
||||
val tag = it.orCreateTag
|
||||
item.canWrite(tag, datum)
|
||||
item.canWrite(it, datum)
|
||||
} else false
|
||||
}
|
||||
val handItem = handStack.item
|
||||
|
||||
if (handItem is DataHolder) {
|
||||
val tag = handStack.orCreateTag
|
||||
handItem.writeDatum(tag, datum)
|
||||
handItem.writeDatum(handStack, datum)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import at.petrak.hexcasting.common.casting.CastingContext
|
|||
import at.petrak.hexcasting.common.casting.mishaps.MishapNoAkashicRecord
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapOthersName
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.common.lib.HexSounds
|
||||
import at.petrak.hexcasting.hexmath.HexPattern
|
||||
import net.minecraft.core.BlockPos
|
||||
|
@ -56,13 +57,12 @@ object OpAkashicWrite : SpellOperator {
|
|||
1f, 0.8f
|
||||
)
|
||||
|
||||
ctx.caster.getCapability(HexCapabilities.PREFERRED_COLORIZER).ifPresent {
|
||||
// val normal = record.blockState.getValue(BlockAkashicBookshelf.FACING).normal
|
||||
// ParticleSpray(
|
||||
// Vec3.atCenterOf(record.blockPos), Vec3.atBottomCenterOf(normal),
|
||||
// 0.5, Math.PI / 4, 10
|
||||
// ).sprayParticles(ctx.world, it.colorizer)
|
||||
}
|
||||
// val colorizer = HexPlayerDataHelper.getColorizer(ctx.caster)
|
||||
// val normal = record.blockState.getValue(BlockAkashicBookshelf.FACING).normal
|
||||
// ParticleSpray(
|
||||
// Vec3.atCenterOf(record.blockPos), Vec3.atBottomCenterOf(normal),
|
||||
// 0.5, Math.PI / 4, 10
|
||||
// ).sprayParticles(ctx.world, colorizer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import at.petrak.hexcasting.common.casting.OperatorSideEffect
|
|||
import at.petrak.hexcasting.common.casting.mishaps.MishapInvalidIota
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapNotEnoughArgs
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object OpLastNToList : Operator {
|
||||
val manaCost: Int
|
||||
|
@ -21,7 +23,7 @@ object OpLastNToList : Operator {
|
|||
val arg = stack.takeLast(1).getChecked<Double>(0)
|
||||
val datum = stack[stack.lastIndex]
|
||||
stack.removeLast()
|
||||
if (arg < 0 || arg > stack.size) {
|
||||
if (arg < 0 || arg > stack.size || abs(arg.roundToInt() - arg) >= 0.05f) {
|
||||
throw MishapInvalidIota(
|
||||
datum,
|
||||
0,
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.math
|
||||
|
||||
import at.petrak.hexcasting.api.spell.ConstManaOperator
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapDivideByZero
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapInvalidIota
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import kotlin.math.acos
|
||||
import kotlin.math.asin
|
||||
import kotlin.math.log
|
||||
|
||||
object OpLog : ConstManaOperator {
|
||||
override val argc: Int
|
||||
get() = 2
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val value = args.getChecked<Double>(0)
|
||||
val base = args.getChecked<Double>(1)
|
||||
if (value <= 0.0 || base <= 0.0 || base == 1.0)
|
||||
throw MishapDivideByZero.of(value, base, "logarithm")
|
||||
return spellListOf(log(value, base))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells
|
||||
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
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.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.common.network.HexMessages
|
||||
import at.petrak.hexcasting.common.network.MsgBeepAck
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import net.minecraftforge.network.PacketDistributor.TargetPoint
|
||||
|
||||
object OpBeep : SpellOperator {
|
||||
override val argc = 3
|
||||
|
||||
override fun execute(
|
||||
args: List<SpellDatum<*>>,
|
||||
ctx: CastingContext
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val target = args.getChecked<Vec3>(0)
|
||||
val instrument = args.getChecked<Double>(1).toInt().coerceIn(0, NoteBlockInstrument.values().size - 1)
|
||||
val note = args.getChecked<Double>(2).toInt().coerceIn(0, 24)
|
||||
ctx.assertVecInRange(target)
|
||||
|
||||
return Triple(
|
||||
Spell(target, note, NoteBlockInstrument.values()[instrument]),
|
||||
1_000,
|
||||
listOf(ParticleSpray.Cloud(target, 1.0))
|
||||
)
|
||||
}
|
||||
|
||||
override val hasCastingSound: Boolean
|
||||
get() = false
|
||||
|
||||
private data class Spell(val target: Vec3, val note: Int, val instrument: NoteBlockInstrument) : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
HexMessages.getNetwork().send(PacketDistributor.NEAR.with {
|
||||
TargetPoint(
|
||||
target.x, target.y, target.z,
|
||||
128.0 * 128.0, ctx.world.dimension()
|
||||
)
|
||||
}, MsgBeepAck(target, note, instrument))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import at.petrak.hexcasting.common.casting.CastingContext
|
|||
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapBadOffhandItem
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.common.network.HexMessages
|
||||
import at.petrak.hexcasting.common.network.MsgColorizerUpdateAck
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
|
@ -19,10 +20,11 @@ object OpColorize : SpellOperator {
|
|||
args: List<SpellDatum<*>>,
|
||||
ctx: CastingContext
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val handStack = ctx.getHeldItemToOperateOn { FrozenColorizer.isColorizer(it.item) }
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn { FrozenColorizer.isColorizer(it.item) }
|
||||
if (!FrozenColorizer.isColorizer(handStack.item)) {
|
||||
throw MishapBadOffhandItem.of(
|
||||
handStack,
|
||||
hand,
|
||||
"colorizer"
|
||||
)
|
||||
}
|
||||
|
@ -35,18 +37,11 @@ object OpColorize : SpellOperator {
|
|||
|
||||
private object Spell : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
val maybeCap = ctx.caster.getCapability(HexCapabilities.PREFERRED_COLORIZER).resolve()
|
||||
if (!maybeCap.isPresent)
|
||||
return
|
||||
val cap = maybeCap.get()
|
||||
|
||||
val handStack = ctx.getHeldItemToOperateOn { FrozenColorizer.isColorizer(it.item) }
|
||||
val (handStack) = ctx.getHeldItemToOperateOn { FrozenColorizer.isColorizer(it.item) }
|
||||
if (FrozenColorizer.isColorizer(handStack.item)) {
|
||||
val item = handStack.item
|
||||
if (ctx.withdrawItem(handStack.item, 1, true)) {
|
||||
cap.colorizer = FrozenColorizer(item, ctx.caster.uuid)
|
||||
HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with { ctx.caster }, MsgColorizerUpdateAck(cap))
|
||||
HexPlayerDataHelper.setColorizer(ctx.caster, FrozenColorizer(item, ctx.caster.uuid))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import at.petrak.hexcasting.common.blocks.HexBlocks
|
|||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapBadBlock
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
@ -45,13 +46,10 @@ class OpConjure(val light: Boolean) : SpellOperator {
|
|||
if (state != null) {
|
||||
ctx.world.setBlock(pos, state, 2)
|
||||
|
||||
val maybeCap = ctx.caster.getCapability(HexCapabilities.PREFERRED_COLORIZER).resolve()
|
||||
if (!maybeCap.isPresent)
|
||||
return
|
||||
val cap = maybeCap.get()
|
||||
val colorizer = HexPlayerDataHelper.getColorizer(ctx.caster)
|
||||
|
||||
if (ctx.world.getBlockState(pos).block is BlockConjured) {
|
||||
BlockConjured.setColor(ctx.world, pos, cap.colorizer)
|
||||
BlockConjured.setColor(ctx.world, pos, colorizer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells
|
||||
|
||||
import at.petrak.hexcasting.api.item.DataHolder
|
||||
import at.petrak.hexcasting.api.item.SpellHolder
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray
|
||||
import at.petrak.hexcasting.api.spell.RenderedSpell
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
|
@ -16,16 +17,17 @@ class OpErase : SpellOperator {
|
|||
args: List<SpellDatum<*>>,
|
||||
ctx: CastingContext
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val handStack = ctx.getHeldItemToOperateOn {
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn {
|
||||
val item = it.item
|
||||
item is ItemPackagedSpell || (item is DataHolder && it.hasTag() && item.canWrite(it.orCreateTag, null))
|
||||
(item is SpellHolder && item.getPatterns(it) != null) ||
|
||||
(item is DataHolder && it.hasTag() && item.canWrite(it, null))
|
||||
}
|
||||
val handItem = handStack.item
|
||||
if (handItem !is ItemPackagedSpell &&
|
||||
if ((handItem !is SpellHolder || handItem.getPatterns(handStack) == null) &&
|
||||
(handItem !is DataHolder ||
|
||||
!handStack.hasTag() ||
|
||||
!handItem.canWrite(handStack.orCreateTag, null))) {
|
||||
throw MishapBadOffhandItem.of(handStack, "eraseable")
|
||||
!handItem.canWrite(handStack, null))) {
|
||||
throw MishapBadOffhandItem.of(handStack, hand, "eraseable")
|
||||
}
|
||||
|
||||
return Triple(Spell, 10_000, listOf())
|
||||
|
@ -33,19 +35,17 @@ class OpErase : SpellOperator {
|
|||
|
||||
private object Spell : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
val handStack = ctx.getHeldItemToOperateOn {
|
||||
val (handStack) = ctx.getHeldItemToOperateOn {
|
||||
val item = it.item
|
||||
item is ItemPackagedSpell || (item is DataHolder && it.hasTag() && item.canWrite(it.orCreateTag, null))
|
||||
(item is SpellHolder && item.getPatterns(it) != null) ||
|
||||
(item is DataHolder && it.hasTag() && item.canWrite(it, null))
|
||||
}
|
||||
val handItem = handStack.item
|
||||
if (handStack.hasTag()) {
|
||||
val tag = handStack.orCreateTag
|
||||
if (handItem is ItemPackagedSpell) {
|
||||
tag.remove(ItemPackagedSpell.TAG_MANA)
|
||||
tag.remove(ItemPackagedSpell.TAG_MAX_MANA)
|
||||
tag.remove(ItemPackagedSpell.TAG_PATTERNS)
|
||||
} else if (handItem is DataHolder && handItem.canWrite(tag, null)) {
|
||||
handItem.writeDatum(tag, null)
|
||||
if (handItem is SpellHolder && handItem.getPatterns(handStack) != null) {
|
||||
handItem.clearPatterns(handStack)
|
||||
} else if (handItem is DataHolder && handItem.canWrite(handStack, null)) {
|
||||
handItem.writeDatum(handStack, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import at.petrak.hexcasting.api.spell.SpellDatum
|
|||
import at.petrak.hexcasting.api.spell.SpellOperator
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.ManaHelper
|
||||
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapBadItem
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapBadOffhandItem
|
||||
import at.petrak.hexcasting.common.items.HexItems
|
||||
import at.petrak.hexcasting.common.items.magic.ItemManaHolder
|
||||
|
@ -23,26 +23,28 @@ object OpMakeBattery : SpellOperator {
|
|||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val entity = args.getChecked<ItemEntity>(0)
|
||||
|
||||
val otherHandItem = ctx.getHeldItemToOperateOn { it.item == Items.GLASS_BOTTLE }
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn { it.item == Items.GLASS_BOTTLE }
|
||||
|
||||
if (otherHandItem.item != Items.GLASS_BOTTLE) {
|
||||
if (handStack.item != Items.GLASS_BOTTLE) {
|
||||
throw MishapBadOffhandItem.of(
|
||||
otherHandItem,
|
||||
handStack,
|
||||
hand,
|
||||
"bottle"
|
||||
)
|
||||
}
|
||||
if (otherHandItem.count != 1) {
|
||||
if (handStack.count != 1) {
|
||||
throw MishapBadOffhandItem.of(
|
||||
otherHandItem,
|
||||
handStack,
|
||||
hand,
|
||||
"only_one"
|
||||
)
|
||||
}
|
||||
|
||||
ctx.assertEntityInRange(entity)
|
||||
|
||||
if (!ManaHelper.isManaItem(entity.item)) {
|
||||
throw MishapBadOffhandItem.of(
|
||||
otherHandItem,
|
||||
if (!ManaHelper.isManaItem(entity.item) || ManaHelper.extractMana(entity.item, drainForBatteries = true, simulate = true) <= 0) {
|
||||
throw MishapBadItem.of(
|
||||
entity.item,
|
||||
"mana"
|
||||
)
|
||||
}
|
||||
|
@ -52,17 +54,17 @@ object OpMakeBattery : SpellOperator {
|
|||
|
||||
private data class Spell(val itemEntity: ItemEntity) : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
val handStack = ctx.getHeldItemToOperateOn { it.item == Items.GLASS_BOTTLE }
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn { it.item == Items.GLASS_BOTTLE }
|
||||
if (handStack.item == Items.GLASS_BOTTLE && itemEntity.isAlive) {
|
||||
val manaAmt = ManaHelper.extractAllMana(itemEntity.item)
|
||||
if (manaAmt != null) {
|
||||
val replaceItem = ItemStack(HexItems.BATTERY.get())
|
||||
val tag = replaceItem.orCreateTag
|
||||
tag.putInt(ItemManaHolder.TAG_MANA, manaAmt)
|
||||
tag.putInt(ItemManaHolder.TAG_MAX_MANA, manaAmt)
|
||||
|
||||
ctx.caster.setItemInHand(ctx.otherHand, replaceItem)
|
||||
val entityStack = itemEntity.item.copy()
|
||||
val manaAmt = ManaHelper.extractMana(entityStack, drainForBatteries = true)
|
||||
if (manaAmt > 0) {
|
||||
ctx.caster.setItemInHand(hand, ItemManaHolder.withMana(ItemStack(HexItems.BATTERY.get()), manaAmt, manaAmt))
|
||||
}
|
||||
|
||||
itemEntity.item = entityStack
|
||||
if (entityStack.isEmpty)
|
||||
itemEntity.kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells
|
||||
|
||||
import at.petrak.hexcasting.api.item.SpellHolder
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray
|
||||
import at.petrak.hexcasting.api.spell.RenderedSpell
|
||||
|
@ -7,11 +8,13 @@ import at.petrak.hexcasting.api.spell.SpellDatum
|
|||
import at.petrak.hexcasting.api.spell.SpellOperator
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.ManaHelper
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapBadItem
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapBadOffhandItem
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapInvalidIota
|
||||
import at.petrak.hexcasting.common.items.magic.ItemPackagedSpell
|
||||
import at.petrak.hexcasting.hexmath.HexPattern
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
|
||||
|
@ -29,15 +32,15 @@ class OpMakePackagedSpell<T : ItemPackagedSpell>(val itemType: T, val cost: Int)
|
|||
throw MishapInvalidIota(it, 0, TranslatableComponent("hexcasting.mishap.invalid_value.list.pattern"))
|
||||
}
|
||||
|
||||
val otherHandItem = ctx.caster.getItemInHand(ctx.otherHand)
|
||||
if (!otherHandItem.`is`(itemType)) {
|
||||
throw MishapBadOffhandItem(otherHandItem, itemType.description)
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn { it.`is`(itemType) }
|
||||
if (!handStack.`is`(itemType)) {
|
||||
throw MishapBadOffhandItem(handStack, hand, itemType.description)
|
||||
}
|
||||
|
||||
ctx.assertEntityInRange(entity)
|
||||
if (!ManaHelper.isManaItem(entity.item)) {
|
||||
throw MishapBadOffhandItem.of(
|
||||
otherHandItem,
|
||||
if (!ManaHelper.isManaItem(entity.item) || ManaHelper.extractMana(entity.item, drainForBatteries = true, simulate = true) <= 0) {
|
||||
throw MishapBadItem.of(
|
||||
entity.item,
|
||||
"mana"
|
||||
)
|
||||
}
|
||||
|
@ -45,32 +48,24 @@ class OpMakePackagedSpell<T : ItemPackagedSpell>(val itemType: T, val cost: Int)
|
|||
return Triple(Spell(entity, patterns), cost, listOf(ParticleSpray.Burst(entity.position(), 0.5)))
|
||||
}
|
||||
|
||||
private data class Spell(val itemEntity: ItemEntity, val patterns: List<HexPattern>) : RenderedSpell {
|
||||
private inner class Spell(val itemEntity: ItemEntity, val patterns: List<HexPattern>) : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
val otherHandItem = ctx.caster.getItemInHand(ctx.otherHand)
|
||||
val tag = otherHandItem.orCreateTag
|
||||
if (otherHandItem.item is ItemPackagedSpell
|
||||
&& !tag.contains(ItemPackagedSpell.TAG_MANA)
|
||||
&& !tag.contains(ItemPackagedSpell.TAG_MAX_MANA)
|
||||
&& !tag.contains(ItemPackagedSpell.TAG_PATTERNS)
|
||||
val (handStack) = ctx.getHeldItemToOperateOn { it.`is`(itemType) }
|
||||
val handItem = handStack.item
|
||||
if (handItem is SpellHolder
|
||||
&& handItem.getPatterns(handStack) == null
|
||||
&& itemEntity.isAlive
|
||||
) {
|
||||
val manaAmt = ManaHelper.extractAllMana(itemEntity.item)
|
||||
if (manaAmt != null) {
|
||||
val tag = otherHandItem.orCreateTag
|
||||
tag.putInt(ItemPackagedSpell.TAG_MANA, manaAmt)
|
||||
tag.putInt(ItemPackagedSpell.TAG_MAX_MANA, manaAmt)
|
||||
|
||||
val patsTag = ListTag()
|
||||
for (pat in patterns) {
|
||||
patsTag.add(pat.serializeToNBT())
|
||||
}
|
||||
tag.put(ItemPackagedSpell.TAG_PATTERNS, patsTag)
|
||||
|
||||
if (itemEntity.item.isEmpty)
|
||||
itemEntity.kill()
|
||||
val entityStack = itemEntity.item.copy()
|
||||
val manaAmt = ManaHelper.extractMana(entityStack, drainForBatteries = true)
|
||||
if (manaAmt > 0) {
|
||||
handItem.writePattern(handStack, patterns, manaAmt)
|
||||
}
|
||||
|
||||
itemEntity.item = entityStack
|
||||
if (entityStack.isEmpty)
|
||||
itemEntity.kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells
|
||||
|
||||
import at.petrak.hexcasting.api.item.ManaHolder
|
||||
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray
|
||||
import at.petrak.hexcasting.api.spell.RenderedSpell
|
||||
|
@ -10,7 +11,7 @@ import at.petrak.hexcasting.common.casting.ManaHelper
|
|||
import at.petrak.hexcasting.common.casting.mishaps.MishapBadItem
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapBadOffhandItem
|
||||
import at.petrak.hexcasting.common.items.magic.ItemManaHolder
|
||||
import net.minecraft.util.Mth
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
|
||||
object OpRecharge : SpellOperator {
|
||||
|
@ -18,12 +19,18 @@ object OpRecharge : SpellOperator {
|
|||
override fun execute(
|
||||
args: List<SpellDatum<*>>,
|
||||
ctx: CastingContext
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val handStack = ctx.getHeldItemToOperateOn { it.item is ItemManaHolder }
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>>? {
|
||||
val (handStack, hand) = ctx.getHeldItemToOperateOn {
|
||||
val mana = it.getCapability(HexCapabilities.MANA).resolve()
|
||||
mana.isPresent && mana.get().canRecharge() && mana.get().mana < mana.get().maxMana
|
||||
}
|
||||
|
||||
if (handStack.item !is ItemManaHolder)
|
||||
val mana = handStack.getCapability(HexCapabilities.MANA).resolve()
|
||||
|
||||
if (!mana.isPresent || !mana.get().canRecharge())
|
||||
throw MishapBadOffhandItem.of(
|
||||
handStack,
|
||||
hand,
|
||||
"rechargable"
|
||||
)
|
||||
|
||||
|
@ -37,27 +44,33 @@ object OpRecharge : SpellOperator {
|
|||
)
|
||||
}
|
||||
|
||||
if (mana.get().mana >= mana.get().maxMana)
|
||||
return null
|
||||
|
||||
return Triple(Spell(entity), 100_000, listOf(ParticleSpray.Burst(entity.position(), 0.5)))
|
||||
}
|
||||
|
||||
private data class Spell(val itemEntity: ItemEntity) : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
val handStack = ctx.getHeldItemToOperateOn { it.item is ItemManaHolder }
|
||||
val (handStack) = ctx.getHeldItemToOperateOn {
|
||||
val mana = it.getCapability(HexCapabilities.MANA).resolve()
|
||||
mana.isPresent && mana.get().canRecharge() && mana.get().mana < mana.get().maxMana
|
||||
}
|
||||
val mana = handStack.getCapability(HexCapabilities.MANA).resolve()
|
||||
|
||||
if (handStack.item is ItemManaHolder && itemEntity.isAlive) {
|
||||
val manaAmt = ManaHelper.extractAllMana(itemEntity.item)
|
||||
if (manaAmt != null) {
|
||||
val tag = handStack.orCreateTag
|
||||
val maxMana = if (tag.contains(ItemManaHolder.TAG_MAX_MANA))
|
||||
tag.getInt(ItemManaHolder.TAG_MAX_MANA)
|
||||
else
|
||||
Int.MAX_VALUE
|
||||
val existingMana = if (tag.contains(ItemManaHolder.TAG_MANA))
|
||||
tag.getInt(ItemManaHolder.TAG_MANA)
|
||||
else
|
||||
0
|
||||
tag.putInt(ItemManaHolder.TAG_MANA, Mth.clamp(existingMana + manaAmt, 0, maxMana))
|
||||
}
|
||||
if (mana.isPresent && itemEntity.isAlive) {
|
||||
val entityStack = itemEntity.item.copy()
|
||||
|
||||
val maxMana = mana.get().maxMana
|
||||
val existingMana = mana.get().mana
|
||||
|
||||
val manaAmt = ManaHelper.extractMana(entityStack, maxMana - existingMana)
|
||||
|
||||
mana.get().mana = manaAmt + existingMana
|
||||
|
||||
itemEntity.item = entityStack
|
||||
if (entityStack.isEmpty)
|
||||
itemEntity.kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells.great;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public record FlightAbility(boolean allowed, int timeLeft, ResourceKey<Level> dimension, Vec3 origin, double radius) {
|
||||
public static FlightAbility deny() {
|
||||
return new FlightAbility(false, 0, Level.OVERWORLD, Vec3.ZERO, 0);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import at.petrak.hexcasting.api.spell.SpellDatum
|
|||
import at.petrak.hexcasting.api.spell.SpellOperator
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.common.network.HexMessages
|
||||
import at.petrak.hexcasting.common.network.MsgAddMotionAck
|
||||
import net.minecraft.core.Direction
|
||||
|
@ -51,16 +52,8 @@ object OpFlight : SpellOperator {
|
|||
// Don't accidentally clobber someone else's flight
|
||||
return
|
||||
}
|
||||
val maybeCap = target.getCapability(HexCapabilities.FLIGHT).resolve()
|
||||
if (!maybeCap.isPresent) {
|
||||
// uh oh
|
||||
return
|
||||
}
|
||||
val cap = maybeCap.get()
|
||||
cap.allowed = true
|
||||
cap.flightTime = time
|
||||
cap.radius = radius
|
||||
cap.origin = origin
|
||||
|
||||
HexPlayerDataHelper.setFlight(target, FlightAbility(true, time, target.level.dimension(), origin, radius))
|
||||
|
||||
target.abilities.mayfly = true
|
||||
target.abilities.flying = true
|
||||
|
@ -71,65 +64,20 @@ object OpFlight : SpellOperator {
|
|||
}
|
||||
}
|
||||
|
||||
const val CAP_NAME = "flight"
|
||||
const val TAG_ALLOWED = "can_fly"
|
||||
const val TAG_FLIGHT_TIME = "flight_time"
|
||||
const val TAG_ORIGIN = "origin"
|
||||
const val TAG_RADIUS = "radius"
|
||||
|
||||
class CapFlight(var allowed: Boolean, var flightTime: Int, var origin: Vec3, var radius: Double) :
|
||||
ICapabilitySerializable<CompoundTag> {
|
||||
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> =
|
||||
HexCapabilities.FLIGHT.orEmpty(cap, LazyOptional.of { this })
|
||||
|
||||
override fun serializeNBT(): CompoundTag {
|
||||
val out = CompoundTag()
|
||||
|
||||
if (this.allowed) {
|
||||
out.putBoolean(TAG_ALLOWED, this.allowed)
|
||||
out.putInt(TAG_FLIGHT_TIME, flightTime)
|
||||
out.put(TAG_ORIGIN, this.origin.serializeToNBT())
|
||||
out.putDouble(TAG_RADIUS, this.radius)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
override fun deserializeNBT(nbt: CompoundTag) {
|
||||
this.allowed = nbt.getBoolean(TAG_ALLOWED)
|
||||
if (this.allowed) {
|
||||
this.flightTime = nbt.getInt(TAG_FLIGHT_TIME)
|
||||
this.origin = HexUtils.DeserializeVec3FromNBT(nbt.getLongArray(TAG_ORIGIN))
|
||||
this.radius = nbt.getDouble(TAG_RADIUS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun tickDownFlight(evt: LivingEvent.LivingUpdateEvent) {
|
||||
val entity = evt.entityLiving
|
||||
if (entity !is ServerPlayer) return
|
||||
val maybeCap = entity.getCapability(HexCapabilities.FLIGHT).resolve()
|
||||
if (!maybeCap.isPresent) {
|
||||
// nah we were just capping
|
||||
return
|
||||
}
|
||||
val cap = maybeCap.get()
|
||||
|
||||
if (cap.allowed) {
|
||||
cap.flightTime--
|
||||
if (cap.flightTime < 0 || cap.origin.distanceToSqr(entity.position()) > cap.radius * cap.radius) {
|
||||
val flight = HexPlayerDataHelper.getFlight(entity)
|
||||
|
||||
if (flight.allowed) {
|
||||
val flightTime = flight.timeLeft - 1
|
||||
if (flightTime < 0 || flight.origin.distanceToSqr(entity.position()) > flight.radius * flight.radius || flight.dimension != entity.level.dimension()) {
|
||||
if (!entity.isOnGround) {
|
||||
entity.fallDistance = 1_000_000f
|
||||
/*
|
||||
val move = entity.deltaMovement
|
||||
HexMessages.getNetwork()
|
||||
.send(
|
||||
PacketDistributor.PLAYER.with { entity },
|
||||
MsgAddMotionAck(Vec3(0.0, -move.y - 100.0, 0.0))
|
||||
)
|
||||
*/
|
||||
}
|
||||
cap.allowed = false
|
||||
HexPlayerDataHelper.setFlight(entity, FlightAbility.deny())
|
||||
|
||||
if (!entity.isCreative && !entity.isSpectator) {
|
||||
val abilities = entity.abilities
|
||||
|
@ -137,8 +85,9 @@ object OpFlight : SpellOperator {
|
|||
abilities.mayfly = false
|
||||
entity.onUpdateAbilities()
|
||||
}
|
||||
}
|
||||
} else
|
||||
HexPlayerDataHelper.setFlight(entity, FlightAbility(true, flightTime, flight.dimension, flight.origin, flight.radius))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells.sentinel;
|
||||
|
||||
import at.petrak.hexcasting.HexUtils;
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
// it *really* doesn't like this being kotlin
|
||||
public class CapSentinel implements ICapabilitySerializable<CompoundTag> {
|
||||
public static final String CAP_NAME = "sentinel";
|
||||
public static final String TAG_EXISTS = "exists";
|
||||
public static final String TAG_EXTENDS_RANGE = "extends_range";
|
||||
public static final String TAG_POSITION = "position";
|
||||
public static final String TAG_DIMENSION = "dimension";
|
||||
|
||||
public boolean hasSentinel;
|
||||
public boolean extendsRange;
|
||||
public Vec3 position;
|
||||
public ResourceKey<Level> dimension;
|
||||
|
||||
public CapSentinel(boolean hasSentinel, boolean extendsRange, Vec3 position, ResourceKey<Level> dimension) {
|
||||
this.hasSentinel = hasSentinel;
|
||||
this.extendsRange = extendsRange;
|
||||
this.position = position;
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, Direction dir) {
|
||||
return HexCapabilities.SENTINEL.orEmpty(cap, LazyOptional.of(() -> this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeNBT() {
|
||||
var tag = new CompoundTag();
|
||||
tag.putBoolean(TAG_EXISTS, this.hasSentinel);
|
||||
tag.putBoolean(TAG_EXTENDS_RANGE, this.extendsRange);
|
||||
tag.put(TAG_POSITION, HexUtils.serializeToNBT(this.position));
|
||||
tag.putString(TAG_DIMENSION, dimension.location().toString());
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag tag) {
|
||||
this.hasSentinel = tag.getBoolean(TAG_EXISTS);
|
||||
this.extendsRange = tag.getBoolean(TAG_EXTENDS_RANGE);
|
||||
this.dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(tag.getString(TAG_DIMENSION)));
|
||||
this.position = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_POSITION));
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.spell.SpellDatum
|
|||
import at.petrak.hexcasting.api.spell.SpellOperator
|
||||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.common.network.HexMessages
|
||||
import at.petrak.hexcasting.common.network.MsgSentinelStatusUpdateAck
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
@ -32,17 +33,7 @@ class OpCreateSentinel(val extendsRange: Boolean) : SpellOperator {
|
|||
|
||||
private data class Spell(val target: Vec3, val extendsRange: Boolean) : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
val maybeCap = ctx.caster.getCapability(HexCapabilities.SENTINEL).resolve()
|
||||
if (!maybeCap.isPresent)
|
||||
return
|
||||
|
||||
val cap = maybeCap.get()
|
||||
cap.hasSentinel = true
|
||||
cap.extendsRange = extendsRange
|
||||
cap.position = target
|
||||
cap.dimension = ctx.world.dimension()
|
||||
|
||||
HexMessages.getNetwork().send(PacketDistributor.PLAYER.with { ctx.caster }, MsgSentinelStatusUpdateAck(cap))
|
||||
HexPlayerDataHelper.setSentinel(ctx.caster, Sentinel(true, extendsRange, target, ctx.world.dimension()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.spell.SpellOperator
|
|||
import at.petrak.hexcasting.common.casting.CastingContext
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapLocationInWrongDimension
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.common.network.HexMessages
|
||||
import at.petrak.hexcasting.common.network.MsgSentinelStatusUpdateAck
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
|
@ -18,12 +19,10 @@ object OpDestroySentinel : SpellOperator {
|
|||
ctx: CastingContext
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
||||
val particles = mutableListOf<ParticleSpray>()
|
||||
val maybeCap = ctx.caster.getCapability(HexCapabilities.SENTINEL).resolve()
|
||||
maybeCap.ifPresent {
|
||||
if (it.dimension != ctx.world.dimension())
|
||||
throw MishapLocationInWrongDimension(it.dimension.location())
|
||||
particles.add(ParticleSpray.Cloud(it.position, 2.0))
|
||||
}
|
||||
val sentinel = HexPlayerDataHelper.getSentinel(ctx.caster)
|
||||
if (sentinel.dimension != ctx.world.dimension())
|
||||
throw MishapLocationInWrongDimension(sentinel.dimension.location())
|
||||
particles.add(ParticleSpray.Cloud(sentinel.position, 2.0))
|
||||
|
||||
return Triple(
|
||||
Spell,
|
||||
|
@ -34,14 +33,7 @@ object OpDestroySentinel : SpellOperator {
|
|||
|
||||
private object Spell : RenderedSpell {
|
||||
override fun cast(ctx: CastingContext) {
|
||||
val maybeCap = ctx.caster.getCapability(HexCapabilities.SENTINEL).resolve()
|
||||
if (!maybeCap.isPresent)
|
||||
return
|
||||
|
||||
val cap = maybeCap.get()
|
||||
cap.hasSentinel = false
|
||||
|
||||
HexMessages.getNetwork().send(PacketDistributor.PLAYER.with { ctx.caster }, MsgSentinelStatusUpdateAck(cap))
|
||||
HexPlayerDataHelper.setSentinel(ctx.caster, Sentinel.none())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,21 +7,18 @@ import at.petrak.hexcasting.common.casting.CastingContext
|
|||
import at.petrak.hexcasting.common.casting.Widget
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapLocationInWrongDimension
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
|
||||
object OpGetSentinelPos : ConstManaOperator {
|
||||
override val argc = 0
|
||||
override val manaCost = 1_000
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val maybeCap = ctx.caster.getCapability(HexCapabilities.SENTINEL).resolve()
|
||||
if (!maybeCap.isPresent)
|
||||
return spellListOf(Widget.NULL)
|
||||
|
||||
val cap = maybeCap.get()
|
||||
if (cap.dimension != ctx.world.dimension())
|
||||
throw MishapLocationInWrongDimension(cap.dimension.location())
|
||||
val sentinel = HexPlayerDataHelper.getSentinel(ctx.caster)
|
||||
if (sentinel.dimension != ctx.world.dimension())
|
||||
throw MishapLocationInWrongDimension(sentinel.dimension.location())
|
||||
return spellListOf(
|
||||
if (cap.hasSentinel)
|
||||
cap.position
|
||||
if (sentinel.hasSentinel)
|
||||
sentinel.position
|
||||
else
|
||||
Widget.NULL
|
||||
)
|
||||
|
|
|
@ -8,6 +8,7 @@ import at.petrak.hexcasting.common.casting.CastingContext
|
|||
import at.petrak.hexcasting.common.casting.Widget
|
||||
import at.petrak.hexcasting.common.casting.mishaps.MishapLocationInWrongDimension
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
object OpGetSentinelWayfind : ConstManaOperator {
|
||||
|
@ -16,18 +17,15 @@ object OpGetSentinelWayfind : ConstManaOperator {
|
|||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val from = args.getChecked<Vec3>(0)
|
||||
|
||||
val maybeCap = ctx.caster.getCapability(HexCapabilities.SENTINEL).resolve()
|
||||
if (!maybeCap.isPresent)
|
||||
return spellListOf(Widget.NULL)
|
||||
val sentinel = HexPlayerDataHelper.getSentinel(ctx.caster)
|
||||
|
||||
val cap = maybeCap.get()
|
||||
if (cap.dimension != ctx.world.dimension())
|
||||
throw MishapLocationInWrongDimension(cap.dimension.location())
|
||||
if (sentinel.dimension != ctx.world.dimension())
|
||||
throw MishapLocationInWrongDimension(sentinel.dimension.location())
|
||||
|
||||
val sentinelPos = if (!cap.hasSentinel)
|
||||
val sentinelPos = if (!sentinel.hasSentinel)
|
||||
return spellListOf(Widget.NULL)
|
||||
else
|
||||
cap.position
|
||||
sentinel.position
|
||||
|
||||
return spellListOf(sentinelPos.subtract(from).normalize())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.spells.sentinel;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public record Sentinel(boolean hasSentinel, boolean extendsRange, Vec3 position,
|
||||
ResourceKey<Level> dimension) {
|
||||
public static Sentinel none() {
|
||||
return new Sentinel(false, false, Vec3.ZERO, Level.OVERWORLD);
|
||||
}
|
||||
}
|
|
@ -39,4 +39,4 @@ object OpFisherman : Operator {
|
|||
|
||||
return OperationResult(stack, sideEffects)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ public class HexCommands {
|
|||
@SubscribeEvent
|
||||
public static void register(RegisterCommandsEvent evt) {
|
||||
var dp = evt.getDispatcher();
|
||||
ListPatsCommand.register(dp);
|
||||
ListPatternsCommand.register(dp);
|
||||
RecalcPatternsCommand.register(dp);
|
||||
BrainsweepCommand.register(dp);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package at.petrak.hexcasting.common.command;
|
||||
|
||||
import at.petrak.hexcasting.api.PatternRegistry;
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum;
|
||||
import at.petrak.hexcasting.common.items.HexItems;
|
||||
import at.petrak.hexcasting.common.items.ItemScroll;
|
||||
import at.petrak.hexcasting.hexmath.HexPattern;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.arguments.ResourceLocationArgument;
|
||||
|
@ -15,27 +15,25 @@ import net.minecraft.network.chat.TranslatableComponent;
|
|||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ListPatsCommand {
|
||||
public class ListPatternsCommand {
|
||||
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
dispatcher.register(Commands.literal("hexcasting:patterns")
|
||||
.requires(dp -> dp.hasPermission(Commands.LEVEL_ADMINS))
|
||||
.then(Commands.literal("list").executes(ctx -> {
|
||||
|
||||
var lookup = PatternRegistry.getPerWorldPatterns(ctx.getSource().getLevel());
|
||||
var listing = lookup.keySet()
|
||||
var listing = lookup.entrySet()
|
||||
.stream()
|
||||
.map(key -> new Pair<>(lookup.get(key).getFirst(), key))
|
||||
.sorted((a, b) -> a.getFirst().compareNamespaced(b.getFirst()))
|
||||
.sorted((a, b) -> a.getValue().getFirst().compareNamespaced(b.getValue().getFirst()))
|
||||
.toList();
|
||||
|
||||
var bob = new StringBuilder("Patterns in this world:");
|
||||
ctx.getSource().sendSuccess(new TranslatableComponent("command.hexcasting.pats.listing"), false);
|
||||
for (var pair : listing) {
|
||||
bob.append('\n');
|
||||
bob.append(pair.getFirst());
|
||||
bob.append(": ");
|
||||
bob.append(pair.getSecond());
|
||||
ctx.getSource().sendSuccess(new TextComponent(pair.getValue().getFirst().toString())
|
||||
.append(": ")
|
||||
.append(SpellDatum.make(HexPattern.FromAnglesSig(pair.getKey(), pair.getValue().getSecond())).display()), false);
|
||||
}
|
||||
ctx.getSource().sendSuccess(new TextComponent(bob.toString()), true);
|
||||
|
||||
|
||||
return lookup.size();
|
||||
}))
|
|
@ -8,6 +8,7 @@ import at.petrak.hexcasting.hexmath.HexPattern;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
|
@ -58,7 +59,7 @@ public class EntityWallScroll extends HangingEntity implements IEntityAdditional
|
|||
this.scroll = scroll;
|
||||
|
||||
var tag = scroll.getTag();
|
||||
if (tag != null && tag.contains(ItemScroll.TAG_PATTERN)) {
|
||||
if (tag != null && tag.contains(ItemScroll.TAG_PATTERN, Tag.TAG_COMPOUND)) {
|
||||
this.pattern = HexPattern.DeserializeFromNBT(tag.getCompound(ItemScroll.TAG_PATTERN));
|
||||
if (this.level.isClientSide) {
|
||||
var pair = RenderLib.getCenteredPattern(pattern, 128, 128, 16f);
|
||||
|
@ -66,7 +67,7 @@ public class EntityWallScroll extends HangingEntity implements IEntityAdditional
|
|||
this.zappyPoints = RenderLib.makeZappy(dots, 10f, 0.8f, 0f);
|
||||
}
|
||||
|
||||
this.isAncient = tag.contains(ItemScroll.TAG_OP_ID);
|
||||
this.isAncient = tag.contains(ItemScroll.TAG_OP_ID, Tag.TAG_STRING);
|
||||
} else {
|
||||
this.pattern = null;
|
||||
this.zappyPoints = null;
|
||||
|
|
|
@ -4,10 +4,7 @@ import at.petrak.hexcasting.HexMod;
|
|||
import at.petrak.hexcasting.common.blocks.HexBlocks;
|
||||
import at.petrak.hexcasting.common.items.colorizer.ItemDyeColorizer;
|
||||
import at.petrak.hexcasting.common.items.colorizer.ItemPrideColorizer;
|
||||
import at.petrak.hexcasting.common.items.magic.ItemArtifact;
|
||||
import at.petrak.hexcasting.common.items.magic.ItemCypher;
|
||||
import at.petrak.hexcasting.common.items.magic.ItemManaBattery;
|
||||
import at.petrak.hexcasting.common.items.magic.ItemTrinket;
|
||||
import at.petrak.hexcasting.common.items.magic.*;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
|
@ -40,11 +37,8 @@ public class HexItems {
|
|||
1_000_000_000,
|
||||
};
|
||||
for (int manamount : manamounts) {
|
||||
var stack = new ItemStack(BATTERY.get(), 1);
|
||||
var tag = stack.getOrCreateTag();
|
||||
tag.putInt(ItemManaBattery.TAG_MANA, manamount);
|
||||
tag.putInt(ItemManaBattery.TAG_MAX_MANA, manamount);
|
||||
items.add(stack);
|
||||
var stack = new ItemStack(BATTERY.get());
|
||||
items.add(ItemManaHolder.withMana(stack, manamount, manamount));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -39,12 +39,12 @@ public class ItemAbacus extends Item implements DataHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(CompoundTag tag, SpellDatum<?> datum) {
|
||||
public boolean canWrite(ItemStack stack, SpellDatum<?> datum) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDatum(CompoundTag tag, SpellDatum<?> datum) {
|
||||
public void writeDatum(ItemStack stack, SpellDatum<?> datum) {
|
||||
// nope
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ public class ItemAbacus extends Item implements DataHolder {
|
|||
|
||||
var tag = stack.getOrCreateTag();
|
||||
double oldNum = 0d;
|
||||
if (tag.contains(TAG_VALUE, Tag.TAG_DOUBLE)) {
|
||||
if (tag.contains(TAG_VALUE, Tag.TAG_ANY_NUMERIC)) {
|
||||
oldNum = tag.getDouble(TAG_VALUE);
|
||||
}
|
||||
tag.putDouble(TAG_VALUE, 0d);
|
||||
|
|
|
@ -3,7 +3,9 @@ package at.petrak.hexcasting.common.items;
|
|||
import at.petrak.hexcasting.HexMod;
|
||||
import at.petrak.hexcasting.api.item.DataHolder;
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum;
|
||||
import at.petrak.hexcasting.common.casting.Widget;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
|
@ -29,7 +31,7 @@ public class ItemFocus extends Item implements DataHolder {
|
|||
return null;
|
||||
}
|
||||
var tag = stack.getTag();
|
||||
if (!tag.contains(TAG_DATA)) {
|
||||
if (!tag.contains(TAG_DATA, Tag.TAG_COMPOUND)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -37,12 +39,19 @@ public class ItemFocus extends Item implements DataHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(CompoundTag tag, SpellDatum<?> datum) {
|
||||
return !tag.getBoolean(TAG_SEALED);
|
||||
public @Nullable SpellDatum<?> emptyDatum(ItemStack stack) {
|
||||
return SpellDatum.make(Widget.NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDatum(CompoundTag tag, SpellDatum<?> datum) {
|
||||
public boolean canWrite(ItemStack stack, SpellDatum<?> datum) {
|
||||
return !stack.hasTag() || !stack.getTag().getBoolean(TAG_SEALED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDatum(ItemStack stack, SpellDatum<?> datum) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
|
||||
if (!tag.getBoolean(TAG_SEALED)) {
|
||||
if (datum == null)
|
||||
tag.remove(TAG_DATA);
|
||||
|
|
|
@ -9,6 +9,7 @@ import at.petrak.hexcasting.hexmath.HexPattern;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -42,7 +43,7 @@ public class ItemScroll extends Item implements DataHolder {
|
|||
@Override
|
||||
public @Nullable CompoundTag readDatumTag(ItemStack stack) {
|
||||
var stackTag = stack.getTag();
|
||||
if (stackTag == null || !stackTag.contains(TAG_PATTERN)) {
|
||||
if (stackTag == null || !stackTag.contains(TAG_PATTERN, Tag.TAG_COMPOUND)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -53,14 +54,14 @@ public class ItemScroll extends Item implements DataHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(CompoundTag tag, SpellDatum<?> datum) {
|
||||
return datum != null && datum.getType() == DatumType.PATTERN && !tag.contains(TAG_PATTERN);
|
||||
public boolean canWrite(ItemStack stack, SpellDatum<?> datum) {
|
||||
return datum != null && datum.getType() == DatumType.PATTERN && (!stack.hasTag() || !stack.getTag().contains(TAG_PATTERN, Tag.TAG_COMPOUND));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDatum(CompoundTag tag, SpellDatum<?> datum) {
|
||||
if (this.canWrite(tag, datum) && datum.getPayload() instanceof HexPattern pat) {
|
||||
tag.put(TAG_PATTERN, pat.serializeToNBT());
|
||||
public void writeDatum(ItemStack stack, SpellDatum<?> datum) {
|
||||
if (this.canWrite(stack, datum) && datum.getPayload() instanceof HexPattern pat) {
|
||||
stack.getOrCreateTag().put(TAG_PATTERN, pat.serializeToNBT());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,10 +107,10 @@ public class ItemScroll extends Item implements DataHolder {
|
|||
@Override
|
||||
public Component getName(ItemStack pStack) {
|
||||
var tag = pStack.getOrCreateTag();
|
||||
if (tag.contains(TAG_OP_ID)) {
|
||||
if (tag.contains(TAG_OP_ID, Tag.TAG_STRING)) {
|
||||
return new TranslatableComponent("item.hexcasting.scroll.of",
|
||||
new TranslatableComponent("hexcasting.spell." + ResourceLocation.tryParse(tag.getString(TAG_OP_ID))));
|
||||
} else if (tag.contains(TAG_PATTERN)) {
|
||||
} else if (tag.contains(TAG_PATTERN, Tag.TAG_COMPOUND)) {
|
||||
return new TranslatableComponent("item.hexcasting.scroll");
|
||||
} else {
|
||||
return new TranslatableComponent("item.hexcasting.scroll.empty");
|
||||
|
|
|
@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.spell.SpellDatum;
|
|||
import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate;
|
||||
import at.petrak.hexcasting.hexmath.HexPattern;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -30,9 +31,9 @@ public class ItemSlate extends BlockItem implements DataHolder {
|
|||
|
||||
public static boolean hasPattern(ItemStack stack) {
|
||||
var tag = stack.getTag();
|
||||
if (tag != null && tag.contains("BlockEntityTag")) {
|
||||
if (tag != null && tag.contains("BlockEntityTag", Tag.TAG_COMPOUND)) {
|
||||
var bet = tag.getCompound("BlockEntityTag");
|
||||
return bet.contains(BlockEntitySlate.TAG_PATTERN);
|
||||
return bet.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -44,7 +45,7 @@ public class ItemSlate extends BlockItem implements DataHolder {
|
|||
return null;
|
||||
}
|
||||
var beTag = stackTag.getCompound("BlockEntityTag");
|
||||
if (!beTag.contains(BlockEntitySlate.TAG_PATTERN)) {
|
||||
if (!beTag.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -55,21 +56,24 @@ public class ItemSlate extends BlockItem implements DataHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(CompoundTag tag, SpellDatum<?> datum) {
|
||||
public boolean canWrite(ItemStack stack, SpellDatum<?> datum) {
|
||||
if (datum == null || datum.getType() != DatumType.PATTERN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var beTag = tag.getCompound("BlockEntityTag");
|
||||
return !beTag.contains(BlockEntitySlate.TAG_PATTERN);
|
||||
if (!stack.hasTag())
|
||||
return true;
|
||||
|
||||
var beTag = stack.getTagElement("BlockEntityTag");
|
||||
return beTag == null || !beTag.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDatum(CompoundTag tag, SpellDatum<?> datum) {
|
||||
if (this.canWrite(tag, datum) && datum.getPayload() instanceof HexPattern pat) {
|
||||
var beTag = tag.getCompound("BlockEntityTag");
|
||||
public void writeDatum(ItemStack stack, SpellDatum<?> datum) {
|
||||
if (this.canWrite(stack, datum) && datum.getPayload() instanceof HexPattern pat) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
var beTag = stack.getOrCreateTagElement("BlockEntityTag");
|
||||
beTag.put(BlockEntitySlate.TAG_PATTERN, pat.serializeToNBT());
|
||||
tag.put("BlockEntityTag", beTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package at.petrak.hexcasting.common.items;
|
|||
import at.petrak.hexcasting.HexMod;
|
||||
import at.petrak.hexcasting.api.item.DataHolder;
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum;
|
||||
import at.petrak.hexcasting.common.casting.Widget;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
@ -40,10 +41,9 @@ public class ItemSpellbook extends Item implements DataHolder {
|
|||
public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip,
|
||||
TooltipFlag isAdvanced) {
|
||||
var tag = stack.getOrCreateTag();
|
||||
if (tag.contains(TAG_SELECTED_PAGE)) {
|
||||
if (tag.contains(TAG_SELECTED_PAGE, Tag.TAG_ANY_NUMERIC)) {
|
||||
var pageIdx = tag.getInt(TAG_SELECTED_PAGE);
|
||||
var pages = tag.getCompound(ItemSpellbook.TAG_PAGES);
|
||||
int highest = HighestPage(pages);
|
||||
int highest = HighestPage(stack);
|
||||
if (highest != 0) {
|
||||
tooltip.add(new TranslatableComponent("hexcasting.tooltip.spellbook.page",
|
||||
new TextComponent(String.valueOf(pageIdx)).withStyle(ChatFormatting.WHITE),
|
||||
|
@ -65,9 +65,9 @@ public class ItemSpellbook extends Item implements DataHolder {
|
|||
public void inventoryTick(ItemStack stack, Level pLevel, Entity pEntity, int pSlotId, boolean pIsSelected) {
|
||||
var tag = stack.getOrCreateTag();
|
||||
int index;
|
||||
if (ArePagesEmpty(tag)) {
|
||||
if (ArePagesEmpty(stack)) {
|
||||
index = 0;
|
||||
} else if (!tag.contains(TAG_SELECTED_PAGE)) {
|
||||
} else if (!tag.contains(TAG_SELECTED_PAGE, Tag.TAG_ANY_NUMERIC)) {
|
||||
index = 1;
|
||||
} else {
|
||||
index = tag.getInt(TAG_SELECTED_PAGE);
|
||||
|
@ -86,8 +86,11 @@ public class ItemSpellbook extends Item implements DataHolder {
|
|||
tag.put(TAG_PAGE_NAMES, names);
|
||||
}
|
||||
|
||||
public static boolean ArePagesEmpty(CompoundTag tag) {
|
||||
return !tag.contains(ItemSpellbook.TAG_PAGES) ||
|
||||
public static boolean ArePagesEmpty(ItemStack stack) {
|
||||
if (!stack.hasTag())
|
||||
return true;
|
||||
CompoundTag tag = stack.getTag();
|
||||
return !tag.contains(ItemSpellbook.TAG_PAGES, Tag.TAG_COMPOUND) ||
|
||||
tag.getCompound(ItemSpellbook.TAG_PAGES).isEmpty();
|
||||
}
|
||||
|
||||
|
@ -99,13 +102,13 @@ public class ItemSpellbook extends Item implements DataHolder {
|
|||
var tag = stack.getTag();
|
||||
|
||||
int idx;
|
||||
if (tag.contains(TAG_SELECTED_PAGE)) {
|
||||
if (tag.contains(TAG_SELECTED_PAGE, Tag.TAG_ANY_NUMERIC)) {
|
||||
idx = tag.getInt(TAG_SELECTED_PAGE);
|
||||
} else {
|
||||
idx = 0;
|
||||
}
|
||||
var key = String.valueOf(idx);
|
||||
if (tag.contains(TAG_PAGES)) {
|
||||
if (tag.contains(TAG_PAGES, Tag.TAG_COMPOUND)) {
|
||||
var pagesTag = tag.getCompound(TAG_PAGES);
|
||||
if (pagesTag.contains(key)) {
|
||||
return pagesTag.getCompound(key);
|
||||
|
@ -118,23 +121,31 @@ public class ItemSpellbook extends Item implements DataHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(CompoundTag tag, SpellDatum<?> datum) {
|
||||
public @Nullable SpellDatum<?> emptyDatum(ItemStack stack) {
|
||||
return SpellDatum.make(Widget.NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(ItemStack stack, SpellDatum<?> datum) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void writeDatum(CompoundTag tag, SpellDatum<?> datum) {
|
||||
@Override
|
||||
public void writeDatum(ItemStack stack, SpellDatum<?> datum) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
|
||||
int idx;
|
||||
if (tag.contains(TAG_SELECTED_PAGE)) {
|
||||
if (tag.contains(TAG_SELECTED_PAGE, Tag.TAG_ANY_NUMERIC)) {
|
||||
idx = tag.getInt(TAG_SELECTED_PAGE);
|
||||
// But we want to write to page *1* to start if this is our first page
|
||||
if (idx == 0 && ArePagesEmpty(tag)) {
|
||||
if (idx == 0 && ArePagesEmpty(stack)) {
|
||||
idx = 1;
|
||||
}
|
||||
} else {
|
||||
idx = 1;
|
||||
}
|
||||
var key = String.valueOf(idx);
|
||||
if (tag.contains(TAG_PAGES)) {
|
||||
if (tag.contains(TAG_PAGES, Tag.TAG_COMPOUND)) {
|
||||
if (datum == null)
|
||||
tag.getCompound(TAG_PAGES).remove(key);
|
||||
else
|
||||
|
@ -146,7 +157,12 @@ public class ItemSpellbook extends Item implements DataHolder {
|
|||
}
|
||||
}
|
||||
|
||||
public static int HighestPage(CompoundTag tag) {
|
||||
public static int HighestPage(ItemStack stack) {
|
||||
if (!stack.hasTag())
|
||||
return 0;
|
||||
CompoundTag tag = stack.getTagElement(TAG_PAGES);
|
||||
if (tag == null)
|
||||
return 0;
|
||||
var highestKey = tag.getAllKeys().stream().flatMap(s -> {
|
||||
try {
|
||||
return Stream.of(Integer.parseInt(s));
|
||||
|
@ -157,11 +173,12 @@ public class ItemSpellbook extends Item implements DataHolder {
|
|||
return highestKey.orElse(0);
|
||||
}
|
||||
|
||||
public static void RotatePageIdx(ItemStack stack, CompoundTag tag, boolean increase) {
|
||||
public static void RotatePageIdx(ItemStack stack, boolean increase) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
int newIdx;
|
||||
if (ArePagesEmpty(tag)) {
|
||||
if (ArePagesEmpty(stack)) {
|
||||
newIdx = 0;
|
||||
} else if (tag.contains(TAG_SELECTED_PAGE)) {
|
||||
} else if (tag.contains(TAG_SELECTED_PAGE, Tag.TAG_ANY_NUMERIC)) {
|
||||
var delta = increase ? 1 : -1;
|
||||
newIdx = Math.max(1, tag.getInt(TAG_SELECTED_PAGE) + delta);
|
||||
} else {
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
package at.petrak.hexcasting.common.items;
|
||||
|
||||
import at.petrak.hexcasting.common.casting.CastingContext;
|
||||
import at.petrak.hexcasting.common.casting.CastingHarness;
|
||||
import at.petrak.hexcasting.common.casting.ResolvedPattern;
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper;
|
||||
import at.petrak.hexcasting.common.lib.HexSounds;
|
||||
import at.petrak.hexcasting.common.network.HexMessages;
|
||||
import at.petrak.hexcasting.common.network.MsgOpenSpellGuiAck;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
|
@ -19,12 +14,7 @@ import net.minecraft.world.item.ItemStack;
|
|||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemWand extends Item {
|
||||
public static final String TAG_HARNESS = "hexcasting:spell_harness";
|
||||
public static final String TAG_PATTERNS = "hexcasting:spell_patterns";
|
||||
|
||||
public ItemWand(Properties pProperties) {
|
||||
super(pProperties);
|
||||
|
@ -35,24 +25,14 @@ public class ItemWand extends Item {
|
|||
if (player.isShiftKeyDown()) {
|
||||
if (world.isClientSide()) {
|
||||
player.playSound(HexSounds.FAIL_PATTERN.get(), 1f, 1f);
|
||||
} else {
|
||||
player.getPersistentData().remove(TAG_HARNESS);
|
||||
player.getPersistentData().remove(TAG_PATTERNS);
|
||||
} else if (player instanceof ServerPlayer serverPlayer) {
|
||||
HexPlayerDataHelper.clearCastingData(serverPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
if (!world.isClientSide() && player instanceof ServerPlayer serverPlayer) {
|
||||
CompoundTag harnessTag = player.getPersistentData().getCompound(TAG_HARNESS);
|
||||
ListTag patternsTag = player.getPersistentData().getList(TAG_PATTERNS, Tag.TAG_COMPOUND);
|
||||
|
||||
var ctx = new CastingContext(serverPlayer, hand);
|
||||
CastingHarness harness = CastingHarness.DeserializeFromNBT(harnessTag, ctx);
|
||||
|
||||
List<ResolvedPattern> patterns = new ArrayList<>(patternsTag.size());
|
||||
|
||||
for (int i = 0; i < patternsTag.size(); i++) {
|
||||
patterns.add(ResolvedPattern.DeserializeFromNBT(patternsTag.getCompound(i)));
|
||||
}
|
||||
var harness = HexPlayerDataHelper.getHarness(serverPlayer, hand);
|
||||
var patterns = HexPlayerDataHelper.getPatterns(serverPlayer);
|
||||
|
||||
HexMessages.getNetwork().send(PacketDistributor.PLAYER.with(() -> serverPlayer),
|
||||
new MsgOpenSpellGuiAck(hand, patterns, harness.generateDescs()));
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package at.petrak.hexcasting.common.items.magic;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ItemArtifact extends ItemPackagedSpell {
|
||||
public ItemArtifact(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDrawManaFromInventory() {
|
||||
public boolean canDrawManaFromInventory(ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package at.petrak.hexcasting.common.items.magic;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ItemCypher extends ItemPackagedSpell {
|
||||
public ItemCypher(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDrawManaFromInventory() {
|
||||
public boolean canDrawManaFromInventory(ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package at.petrak.hexcasting.common.items.magic;
|
|||
|
||||
import at.petrak.hexcasting.HexMod;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ItemManaBattery extends ItemManaHolder {
|
||||
public static final ResourceLocation MANA_PREDICATE = new ResourceLocation(HexMod.MOD_ID, "mana");
|
||||
|
@ -10,4 +11,9 @@ public class ItemManaBattery extends ItemManaHolder {
|
|||
public ItemManaBattery(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean manaProvider(ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package at.petrak.hexcasting.common.items.magic;
|
||||
|
||||
import at.petrak.hexcasting.api.item.ManaHolder;
|
||||
import at.petrak.hexcasting.common.casting.ManaHelper;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
|
@ -13,56 +15,61 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ItemManaHolder extends Item {
|
||||
public static final String TAG_MANA = "hexcasting:mana";
|
||||
public static final String TAG_MAX_MANA = "hexcasting:start_mana";
|
||||
public abstract class ItemManaHolder extends Item implements ManaHolder {
|
||||
private static final String TAG_MANA = "hexcasting:mana";
|
||||
private static final String TAG_MAX_MANA = "hexcasting:start_mana";
|
||||
|
||||
public ItemManaHolder(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
|
||||
public int getManaAmt(CompoundTag tag) {
|
||||
return tag.getInt(TAG_MANA);
|
||||
public static ItemStack withMana(ItemStack stack, int mana, int maxMana) {
|
||||
Item item = stack.getItem();
|
||||
if (item instanceof ItemManaHolder) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
tag.putInt(TAG_MANA, mana);
|
||||
tag.putInt(TAG_MAX_MANA, maxMana);
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
public int getMaxManaAmt(CompoundTag tag) {
|
||||
return tag.getInt(TAG_MAX_MANA);
|
||||
@Override
|
||||
public int getMana(ItemStack stack) {
|
||||
if (!stack.hasTag())
|
||||
return 0;
|
||||
return stack.getTag().getInt(TAG_MANA);
|
||||
}
|
||||
|
||||
public float getManaFullness(CompoundTag tag) {
|
||||
return (float) getManaAmt(tag) / (float) getMaxManaAmt(tag);
|
||||
@Override
|
||||
public int getMaxMana(ItemStack stack) {
|
||||
if (!stack.hasTag())
|
||||
return 0;
|
||||
return stack.getTag().getInt(TAG_MAX_MANA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the actual amount of mana extracted.
|
||||
*/
|
||||
public int withdrawMana(CompoundTag tag, int cost) {
|
||||
var manaHere = getManaAmt(tag);
|
||||
var manaLeft = manaHere - cost;
|
||||
tag.putInt(TAG_MANA, Math.max(0, manaLeft));
|
||||
return Math.min(cost, manaHere);
|
||||
@Override
|
||||
public void setMana(ItemStack stack, int mana) {
|
||||
stack.getOrCreateTag().putInt(TAG_MANA, Mth.clamp(mana, 0, getMaxMana(stack)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBarVisible(ItemStack pStack) {
|
||||
var tag = pStack.getOrCreateTag();
|
||||
return tag.contains(TAG_MANA);
|
||||
return getMaxMana(pStack) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBarColor(ItemStack pStack) {
|
||||
var tag = pStack.getOrCreateTag();
|
||||
var mana = getManaAmt(tag);
|
||||
var maxMana = getMaxManaAmt(tag);
|
||||
return ManaHelper.INSTANCE.barColor(mana, maxMana);
|
||||
var mana = getMana(pStack);
|
||||
var maxMana = getMaxMana(pStack);
|
||||
return ManaHelper.barColor(mana, maxMana);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBarWidth(ItemStack pStack) {
|
||||
var tag = pStack.getOrCreateTag();
|
||||
var mana = tag.getInt(TAG_MANA);
|
||||
var maxMana = tag.getInt(TAG_MAX_MANA);
|
||||
return ManaHelper.INSTANCE.barWidth(mana, maxMana);
|
||||
var mana = getMana(pStack);
|
||||
var maxMana = getMaxMana(pStack);
|
||||
return ManaHelper.barWidth(mana, maxMana);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,16 +85,12 @@ public abstract class ItemManaHolder extends Item {
|
|||
@Override
|
||||
public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, List<Component> pTooltipComponents,
|
||||
TooltipFlag pIsAdvanced) {
|
||||
if (pIsAdvanced.isAdvanced()) {
|
||||
var imh = (ItemManaHolder) pStack.getItem();
|
||||
var tag = pStack.getOrCreateTag();
|
||||
if (tag.contains(TAG_MANA) && tag.contains(TAG_MAX_MANA)) {
|
||||
pTooltipComponents.add(
|
||||
new TranslatableComponent("item.hexcasting.manaholder.amount",
|
||||
String.format("%,d", imh.getManaAmt(tag)),
|
||||
String.format("%,d", imh.getMaxManaAmt(tag)),
|
||||
100f * imh.getManaFullness(tag)).withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
if (pIsAdvanced.isAdvanced() && getMaxMana(pStack) > 0) {
|
||||
pTooltipComponents.add(
|
||||
new TranslatableComponent("item.hexcasting.manaholder.amount",
|
||||
String.format("%,d", getMana(pStack)),
|
||||
String.format("%,d", getMaxMana(pStack)),
|
||||
100f * getManaFullness(pStack)).withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
|
||||
super.appendHoverText(pStack, pLevel, pTooltipComponents, pIsAdvanced);
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package at.petrak.hexcasting.common.items.magic;
|
||||
|
||||
import at.petrak.hexcasting.HexMod;
|
||||
import at.petrak.hexcasting.api.item.SpellHolder;
|
||||
import at.petrak.hexcasting.common.casting.CastingContext;
|
||||
import at.petrak.hexcasting.common.casting.CastingHarness;
|
||||
import at.petrak.hexcasting.common.lib.HexSounds;
|
||||
import at.petrak.hexcasting.hexmath.HexPattern;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
@ -18,6 +20,7 @@ import net.minecraft.world.entity.player.Player;
|
|||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.UseAnim;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -25,7 +28,7 @@ import java.util.List;
|
|||
/**
|
||||
* Item that holds a list of patterns in it ready to be cast
|
||||
*/
|
||||
public abstract class ItemPackagedSpell extends ItemManaHolder {
|
||||
public abstract class ItemPackagedSpell extends ItemManaHolder implements SpellHolder {
|
||||
public static final String TAG_PATTERNS = "patterns";
|
||||
public static final ResourceLocation HAS_PATTERNS_PRED = new ResourceLocation(HexMod.MOD_ID, "has_patterns");
|
||||
|
||||
|
@ -35,13 +38,50 @@ public abstract class ItemPackagedSpell extends ItemManaHolder {
|
|||
|
||||
public abstract boolean singleUse();
|
||||
|
||||
public abstract boolean canDrawManaFromInventory();
|
||||
@Override
|
||||
public boolean manaProvider(ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<HexPattern> getPatterns(ItemStack stack) {
|
||||
if (!stack.hasTag())
|
||||
return null;
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (!tag.contains(TAG_PATTERNS, Tag.TAG_LIST))
|
||||
return null;
|
||||
|
||||
var out = new ArrayList<HexPattern>();
|
||||
var patsTag = tag.getList(TAG_PATTERNS, Tag.TAG_COMPOUND);
|
||||
for (var patTag : patsTag) {
|
||||
out.add(HexPattern.DeserializeFromNBT((CompoundTag) patTag));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writePattern(ItemStack stack, List<HexPattern> patterns, int mana) {
|
||||
ListTag patsTag = new ListTag();
|
||||
for (HexPattern pat : patterns)
|
||||
patsTag.add(pat.serializeToNBT());
|
||||
|
||||
stack.getOrCreateTag().put(ItemPackagedSpell.TAG_PATTERNS, patsTag);
|
||||
|
||||
withMana(stack, mana, mana);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearPatterns(ItemStack stack) {
|
||||
stack.removeTagKey(ItemPackagedSpell.TAG_PATTERNS);
|
||||
withMana(stack, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand usedHand) {
|
||||
var stack = player.getItemInHand(usedHand);
|
||||
var tag = stack.getOrCreateTag();
|
||||
if (!tag.contains(TAG_PATTERNS)) {
|
||||
List<HexPattern> patterns = getPatterns(stack);
|
||||
if (patterns == null) {
|
||||
return InteractionResultHolder.fail(stack);
|
||||
}
|
||||
|
||||
|
@ -51,7 +91,6 @@ public abstract class ItemPackagedSpell extends ItemManaHolder {
|
|||
var sPlayer = (ServerPlayer) player;
|
||||
var ctx = new CastingContext(sPlayer, usedHand);
|
||||
var harness = new CastingHarness(ctx);
|
||||
List<HexPattern> patterns = getPatterns(tag);
|
||||
for (var pattern : patterns) {
|
||||
var info = harness.executeNewPattern(pattern, sPlayer.getLevel());
|
||||
if (info.getWasPrevPatternInvalid()) {
|
||||
|
@ -89,13 +128,4 @@ public abstract class ItemPackagedSpell extends ItemManaHolder {
|
|||
public UseAnim getUseAnimation(ItemStack pStack) {
|
||||
return UseAnim.BLOCK;
|
||||
}
|
||||
|
||||
private static List<HexPattern> getPatterns(CompoundTag tag) {
|
||||
var out = new ArrayList<HexPattern>();
|
||||
var patsTag = tag.getList(TAG_PATTERNS, Tag.TAG_COMPOUND);
|
||||
for (var patTag : patsTag) {
|
||||
out.add(HexPattern.DeserializeFromNBT((CompoundTag) patTag));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package at.petrak.hexcasting.common.items.magic;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ItemTrinket extends ItemPackagedSpell {
|
||||
public ItemTrinket(Properties pProperties) {
|
||||
super(pProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDrawManaFromInventory() {
|
||||
public boolean canDrawManaFromInventory(ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,133 +1,148 @@
|
|||
package at.petrak.hexcasting.common.lib;
|
||||
|
||||
import at.petrak.hexcasting.HexMod;
|
||||
import at.petrak.hexcasting.common.casting.colors.CapPreferredColorizer;
|
||||
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer;
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.great.OpFlight;
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.sentinel.CapSentinel;
|
||||
import at.petrak.hexcasting.common.items.ItemWand;
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping;
|
||||
import at.petrak.hexcasting.common.network.HexMessages;
|
||||
import at.petrak.hexcasting.common.network.MsgColorizerUpdateAck;
|
||||
import at.petrak.hexcasting.common.network.MsgSentinelStatusUpdateAck;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import at.petrak.hexcasting.HexConfig;
|
||||
import at.petrak.hexcasting.api.item.IManaReservoir;
|
||||
import at.petrak.hexcasting.api.item.ManaHolder;
|
||||
import at.petrak.hexcasting.common.items.HexItems;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.capabilities.CapabilityToken;
|
||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.common.capabilities.*;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class HexCapabilities {
|
||||
public static final Capability<OpFlight.CapFlight> FLIGHT = CapabilityManager.get(new CapabilityToken<>() {
|
||||
|
||||
private static final ResourceLocation MANA_HOLDER_CAPABILITY = new ResourceLocation("hexcasting", "mana_holder");
|
||||
private static final ResourceLocation MANA_ITEM_CAPABILITY = new ResourceLocation("hexcasting", "mana_item");
|
||||
|
||||
public static final Capability<IManaReservoir> MANA = CapabilityManager.get(new CapabilityToken<>() {
|
||||
});
|
||||
public static final Capability<CapSentinel> SENTINEL = CapabilityManager.get(new CapabilityToken<>() {
|
||||
});
|
||||
public static final Capability<CapPreferredColorizer> PREFERRED_COLORIZER =
|
||||
CapabilityManager.get(new CapabilityToken<>() {
|
||||
});
|
||||
public static final Capability<Brainsweeping.Cap> BRAINSWEPT = CapabilityManager.get(
|
||||
new CapabilityToken<>() {
|
||||
});
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerCaps(RegisterCapabilitiesEvent evt) {
|
||||
evt.register(OpFlight.CapFlight.class);
|
||||
evt.register(CapSentinel.class);
|
||||
evt.register(CapPreferredColorizer.class);
|
||||
evt.register(Brainsweeping.Cap.class);
|
||||
evt.register(IManaReservoir.class);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void attachCaps(AttachCapabilitiesEvent<Entity> evt) {
|
||||
if (evt.getObject() instanceof Player) {
|
||||
evt.addCapability(new ResourceLocation(HexMod.MOD_ID, OpFlight.CAP_NAME),
|
||||
// generate a new instance of the capability
|
||||
new OpFlight.CapFlight(false, 0, Vec3.ZERO, 0.0));
|
||||
evt.addCapability(new ResourceLocation(HexMod.MOD_ID, CapSentinel.CAP_NAME),
|
||||
new CapSentinel(false, false, Vec3.ZERO, Level.OVERWORLD));
|
||||
evt.addCapability(new ResourceLocation(HexMod.MOD_ID, CapPreferredColorizer.CAP_NAME),
|
||||
new CapPreferredColorizer(FrozenColorizer.DEFAULT));
|
||||
} else if (evt.getObject() instanceof Villager) {
|
||||
evt.addCapability(new ResourceLocation(HexMod.MOD_ID, Brainsweeping.CAP_NAME),
|
||||
new Brainsweeping.Cap());
|
||||
public static void attachCaps(AttachCapabilitiesEvent<ItemStack> evt) {
|
||||
ItemStack stack = evt.getObject();
|
||||
if (stack.getItem() instanceof ManaHolder holder)
|
||||
evt.addCapability(MANA_HOLDER_CAPABILITY, new SimpleProvider<>(MANA, LazyOptional.of(() -> new ManaHolderReservoir(holder, stack))));
|
||||
else if (stack.is(HexItems.AMETHYST_DUST.get()))
|
||||
evt.addCapability(MANA_ITEM_CAPABILITY, new SimpleProvider<>(MANA, LazyOptional.of(() -> new ItemReservoir(HexConfig.dustManaAmount, 3, stack))));
|
||||
else if (stack.is(Items.AMETHYST_SHARD))
|
||||
evt.addCapability(MANA_ITEM_CAPABILITY, new SimpleProvider<>(MANA, LazyOptional.of(() -> new ItemReservoir(HexConfig.shardManaAmount, 2, stack))));
|
||||
else if (stack.is(HexItems.CHARGED_AMETHYST.get()))
|
||||
evt.addCapability(MANA_ITEM_CAPABILITY, new SimpleProvider<>(MANA, LazyOptional.of(() -> new ItemReservoir(HexConfig.chargedCrystalManaAmount, 1, stack))));
|
||||
}
|
||||
|
||||
private record SimpleProvider<CAP>(Capability<CAP> capability, LazyOptional<CAP> instance) implements ICapabilityProvider {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||
return cap == capability ? instance.cast() : LazyOptional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
// if I were forge i sould simply design an actually useful and useable cap system
|
||||
@SubscribeEvent
|
||||
public static void copyCapsOnDeath(PlayerEvent.Clone evt) {
|
||||
var eitherSidePlayer = evt.getPlayer();
|
||||
// this apparently defines it in outside scope. the more you know.
|
||||
if (!(eitherSidePlayer instanceof ServerPlayer player)) {
|
||||
return;
|
||||
private record ItemReservoir(ForgeConfigSpec.IntValue baseWorth,
|
||||
int consumptionPriority,
|
||||
ItemStack stack) implements IManaReservoir {
|
||||
@Override
|
||||
public int getMana() {
|
||||
return baseWorth.get() * stack.getCount();
|
||||
}
|
||||
|
||||
|
||||
var proto = evt.getOriginal();
|
||||
|
||||
// Copy harness data from this to new player
|
||||
player.getPersistentData().put(ItemWand.TAG_PATTERNS,
|
||||
proto.getPersistentData().getList(ItemWand.TAG_PATTERNS, Tag.TAG_COMPOUND));
|
||||
player.getPersistentData().put(ItemWand.TAG_HARNESS,
|
||||
proto.getPersistentData().getCompound(ItemWand.TAG_HARNESS));
|
||||
|
||||
// Copy caps from this to new player
|
||||
proto.reviveCaps();
|
||||
var protoCapSentinel = proto.getCapability(SENTINEL).resolve();
|
||||
protoCapSentinel.ifPresent(protoSentinel -> {
|
||||
var capSentinel = player.getCapability(SENTINEL);
|
||||
capSentinel.ifPresent(sentinel -> {
|
||||
sentinel.hasSentinel = protoSentinel.hasSentinel;
|
||||
sentinel.position = protoSentinel.position;
|
||||
sentinel.extendsRange = protoSentinel.extendsRange;
|
||||
sentinel.dimension = protoSentinel.dimension;
|
||||
});
|
||||
});
|
||||
var protoCapColor = proto.getCapability(PREFERRED_COLORIZER).resolve();
|
||||
protoCapColor.ifPresent(protoColorizer -> {
|
||||
var capColorizer = player.getCapability(PREFERRED_COLORIZER);
|
||||
capColorizer.ifPresent(colorizer -> {
|
||||
colorizer.colorizer = protoColorizer.colorizer;
|
||||
});
|
||||
});
|
||||
proto.invalidateCaps();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void syncCapsOnLogin(PlayerEvent.PlayerLoggedInEvent evt) {
|
||||
if (!(evt.getPlayer() instanceof ServerPlayer player)) {
|
||||
return;
|
||||
@Override
|
||||
public int getMaxMana() {
|
||||
return getMana();
|
||||
}
|
||||
|
||||
syncCaps(player);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void syncCapsOnRejoin(PlayerEvent.PlayerRespawnEvent evt) {
|
||||
if (!(evt.getPlayer() instanceof ServerPlayer player)) {
|
||||
return;
|
||||
@Override
|
||||
public void setMana(int mana) {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
syncCaps(player);
|
||||
@Override
|
||||
public boolean canRecharge() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProvide() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConsumptionPriority() {
|
||||
return consumptionPriority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConstructBattery() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int withdrawMana(int cost, boolean simulate) {
|
||||
int worth = baseWorth.get();
|
||||
if (cost < 0)
|
||||
cost = worth * stack.getCount();
|
||||
double itemsRequired = cost / (double) worth;
|
||||
int itemsUsed = Math.min((int) Math.ceil(itemsRequired), stack.getCount());
|
||||
if (!simulate)
|
||||
stack.shrink(itemsUsed);
|
||||
return itemsUsed * worth;
|
||||
}
|
||||
}
|
||||
|
||||
private static void syncCaps(ServerPlayer player) {
|
||||
var capSentinel = player.getCapability(HexCapabilities.SENTINEL).resolve();
|
||||
capSentinel.ifPresent(sentinel -> HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with(() -> player), new MsgSentinelStatusUpdateAck(sentinel)));
|
||||
private record ManaHolderReservoir(ManaHolder holder,
|
||||
ItemStack stack) implements IManaReservoir {
|
||||
|
||||
var capColorizer = player.getCapability(HexCapabilities.PREFERRED_COLORIZER).resolve();
|
||||
capColorizer.ifPresent(colorizer -> HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with(() -> player), new MsgColorizerUpdateAck(colorizer)));
|
||||
@Override
|
||||
public int getMana() {
|
||||
return holder.getMana(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxMana() {
|
||||
return holder.getMaxMana(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMana(int mana) {
|
||||
holder.setMana(stack, mana);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRecharge() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProvide() {
|
||||
return holder.manaProvider(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getConsumptionPriority() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConstructBattery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int withdrawMana(int cost, boolean simulate) {
|
||||
return holder.withdrawMana(stack, cost, simulate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
package at.petrak.hexcasting.common.lib;
|
||||
|
||||
import at.petrak.hexcasting.HexUtils;
|
||||
import at.petrak.hexcasting.common.casting.CastingContext;
|
||||
import at.petrak.hexcasting.common.casting.CastingHarness;
|
||||
import at.petrak.hexcasting.common.casting.ResolvedPattern;
|
||||
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer;
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.great.FlightAbility;
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.sentinel.Sentinel;
|
||||
import at.petrak.hexcasting.common.network.HexMessages;
|
||||
import at.petrak.hexcasting.common.network.MsgColorizerUpdateAck;
|
||||
import at.petrak.hexcasting.common.network.MsgSentinelStatusUpdateAck;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HexPlayerDataHelper {
|
||||
public static final String TAG_SENTINEL_EXISTS = "hexcasting:sentinel_exists";
|
||||
public static final String TAG_SENTINEL_GREATER = "hexcasting:sentinel_extends_range";
|
||||
public static final String TAG_SENTINEL_POSITION = "hexcasting:sentinel_position";
|
||||
public static final String TAG_SENTINEL_DIMENSION = "hexcasting:sentinel_dimension";
|
||||
|
||||
public static final String TAG_COLOR = "hexcasting:colorizer";
|
||||
|
||||
public static final String TAG_FLIGHT_ALLOWED = "hexcasting:flight_allowed";
|
||||
public static final String TAG_FLIGHT_TIME = "hexcasting:flight_time";
|
||||
public static final String TAG_FLIGHT_ORIGIN = "hexcasting:flight_origin";
|
||||
public static final String TAG_FLIGHT_DIMENSION = "hexcasting:flight_origin";
|
||||
public static final String TAG_FLIGHT_RADIUS = "hexcasting:flight_radius";
|
||||
|
||||
public static final String TAG_HARNESS = "hexcasting:spell_harness";
|
||||
public static final String TAG_PATTERNS = "hexcasting:spell_patterns";
|
||||
|
||||
@SubscribeEvent
|
||||
public static void copyDataOnDeath(PlayerEvent.Clone evt) {
|
||||
var eitherSidePlayer = evt.getPlayer();
|
||||
// this apparently defines it in outside scope. the more you know.
|
||||
if (!(eitherSidePlayer instanceof ServerPlayer player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var eitherSideProto = evt.getOriginal();
|
||||
if (!(eitherSideProto instanceof ServerPlayer proto)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy data from this to new player
|
||||
setFlight(player, getFlight(proto));
|
||||
setSentinel(player, getSentinel(proto));
|
||||
setColorizer(player, getColorizer(proto));
|
||||
setHarness(player, getHarness(proto, InteractionHand.MAIN_HAND));
|
||||
setPatterns(player, getPatterns(proto));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void syncDataOnLogin(PlayerEvent.PlayerLoggedInEvent evt) {
|
||||
if (!(evt.getPlayer() instanceof ServerPlayer player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
syncSentinel(player);
|
||||
syncColorizer(player);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void syncDataOnRejoin(PlayerEvent.PlayerRespawnEvent evt) {
|
||||
if (!(evt.getPlayer() instanceof ServerPlayer player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
syncSentinel(player);
|
||||
syncColorizer(player);
|
||||
}
|
||||
|
||||
private static void syncSentinel(ServerPlayer player) {
|
||||
HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with(() -> player), new MsgSentinelStatusUpdateAck(getSentinel(player)));
|
||||
|
||||
}
|
||||
|
||||
private static void syncColorizer(ServerPlayer player) {
|
||||
HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with(() -> player), new MsgColorizerUpdateAck(getColorizer(player)));
|
||||
}
|
||||
|
||||
public static void setFlight(ServerPlayer player, FlightAbility flight) {
|
||||
CompoundTag tag = player.getPersistentData();
|
||||
tag.putBoolean(TAG_FLIGHT_ALLOWED, flight.allowed());
|
||||
if (flight.allowed()) {
|
||||
tag.putInt(TAG_FLIGHT_TIME, flight.timeLeft());
|
||||
tag.put(TAG_FLIGHT_ORIGIN, HexUtils.serializeToNBT(flight.origin()));
|
||||
tag.putString(TAG_FLIGHT_DIMENSION, flight.dimension().location().toString());
|
||||
tag.putDouble(TAG_FLIGHT_RADIUS, flight.radius());
|
||||
} else {
|
||||
tag.remove(TAG_FLIGHT_TIME);
|
||||
tag.remove(TAG_FLIGHT_ORIGIN);
|
||||
tag.remove(TAG_FLIGHT_RADIUS);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setColorizer(Player player, FrozenColorizer colorizer) {
|
||||
CompoundTag tag = player.getPersistentData();
|
||||
tag.put(TAG_COLOR, colorizer.serialize());
|
||||
|
||||
if (player instanceof ServerPlayer serverPlayer)
|
||||
syncColorizer(serverPlayer);
|
||||
}
|
||||
|
||||
public static void setSentinel(Player player, Sentinel sentinel) {
|
||||
CompoundTag tag = player.getPersistentData();
|
||||
tag.putBoolean(TAG_SENTINEL_EXISTS, sentinel.hasSentinel());
|
||||
if (sentinel.hasSentinel()) {
|
||||
tag.putBoolean(TAG_SENTINEL_GREATER, sentinel.extendsRange());
|
||||
tag.put(TAG_SENTINEL_POSITION, HexUtils.serializeToNBT(sentinel.position()));
|
||||
tag.putString(TAG_SENTINEL_DIMENSION, sentinel.dimension().location().toString());
|
||||
} else {
|
||||
tag.remove(TAG_SENTINEL_GREATER);
|
||||
tag.remove(TAG_SENTINEL_POSITION);
|
||||
tag.remove(TAG_SENTINEL_DIMENSION);
|
||||
}
|
||||
|
||||
if (player instanceof ServerPlayer serverPlayer)
|
||||
syncSentinel(serverPlayer);
|
||||
}
|
||||
|
||||
public static void setHarness(ServerPlayer player, CastingHarness harness) {
|
||||
player.getPersistentData().put(TAG_HARNESS, harness == null ? new CompoundTag() : harness.serializeToNBT());
|
||||
}
|
||||
|
||||
public static void setPatterns(ServerPlayer player, List<ResolvedPattern> patterns) {
|
||||
var listTag = new ListTag();
|
||||
for (ResolvedPattern pattern : patterns) {
|
||||
listTag.add(pattern.serializeToNBT());
|
||||
}
|
||||
player.getPersistentData().put(TAG_PATTERNS, listTag);
|
||||
}
|
||||
|
||||
public static FlightAbility getFlight(ServerPlayer player) {
|
||||
CompoundTag tag = player.getPersistentData();
|
||||
boolean allowed = tag.getBoolean(TAG_FLIGHT_ALLOWED);
|
||||
if (allowed) {
|
||||
var timeLeft = tag.getInt(TAG_FLIGHT_TIME);
|
||||
var origin = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_FLIGHT_ORIGIN));
|
||||
var radius = tag.getDouble(TAG_FLIGHT_RADIUS);
|
||||
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION)));
|
||||
return new FlightAbility(true, timeLeft, dimension, origin, radius);
|
||||
}
|
||||
return FlightAbility.deny();
|
||||
}
|
||||
|
||||
public static FrozenColorizer getColorizer(Player player) {
|
||||
return FrozenColorizer.deserialize(player.getPersistentData().getCompound(TAG_COLOR));
|
||||
}
|
||||
|
||||
public static Sentinel getSentinel(Player player) {
|
||||
CompoundTag tag = player.getPersistentData();
|
||||
var exists = tag.getBoolean(TAG_SENTINEL_EXISTS);
|
||||
if (!exists)
|
||||
return Sentinel.none();
|
||||
var extendsRange = tag.getBoolean(TAG_SENTINEL_GREATER);
|
||||
var position = HexUtils.DeserializeVec3FromNBT(tag.getLongArray(TAG_SENTINEL_POSITION));
|
||||
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(tag.getString(TAG_SENTINEL_DIMENSION)));
|
||||
|
||||
return new Sentinel(true, extendsRange, position, dimension);
|
||||
}
|
||||
|
||||
public static CastingHarness getHarness(ServerPlayer player, InteractionHand hand) {
|
||||
var ctx = new CastingContext(player, hand);
|
||||
return CastingHarness.DeserializeFromNBT(player.getPersistentData().getCompound(TAG_HARNESS), ctx);
|
||||
}
|
||||
|
||||
public static List<ResolvedPattern> getPatterns(ServerPlayer player) {
|
||||
ListTag patternsTag = player.getPersistentData().getList(TAG_PATTERNS, Tag.TAG_COMPOUND);
|
||||
|
||||
List<ResolvedPattern> patterns = new ArrayList<>(patternsTag.size());
|
||||
|
||||
for (int i = 0; i < patternsTag.size(); i++) {
|
||||
patterns.add(ResolvedPattern.DeserializeFromNBT(patternsTag.getCompound(i)));
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
|
||||
public static void clearCastingData(ServerPlayer player) {
|
||||
player.getPersistentData().remove(TAG_HARNESS);
|
||||
player.getPersistentData().remove(TAG_PATTERNS);
|
||||
}
|
||||
}
|
|
@ -1,55 +1,35 @@
|
|||
package at.petrak.hexcasting.common.misc;
|
||||
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities;
|
||||
import at.petrak.hexcasting.mixin.AccessorLivingEntity;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.Brain;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraft.world.entity.npc.VillagerDataHolder;
|
||||
import net.minecraftforge.event.entity.living.LivingConversionEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
public class Brainsweeping {
|
||||
public static final String CAP_NAME = "brainsweeping";
|
||||
|
||||
public static class Cap implements ICapabilitySerializable<CompoundTag> {
|
||||
public boolean brainswept = false;
|
||||
public static final String TAG_BRAINSWEPT = "hexcasting:brainswept";
|
||||
|
||||
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||
return HexCapabilities.BRAINSWEPT.orEmpty(cap, LazyOptional.of(() -> this));
|
||||
}
|
||||
|
||||
public CompoundTag serializeNBT() {
|
||||
var out = new CompoundTag();
|
||||
out.putBoolean("brainswept", this.brainswept);
|
||||
return out;
|
||||
}
|
||||
|
||||
public void deserializeNBT(CompoundTag tag) {
|
||||
this.brainswept = tag.getBoolean("brainswept");
|
||||
}
|
||||
public static boolean isBrainswept(LivingEntity entity) {
|
||||
return entity instanceof VillagerDataHolder && entity.getPersistentData().getBoolean(TAG_BRAINSWEPT);
|
||||
}
|
||||
|
||||
public static boolean isBrainswept(Villager villager) {
|
||||
var maybeCap = villager.getCapability(HexCapabilities.BRAINSWEPT).resolve();
|
||||
return maybeCap.map(cap -> cap.brainswept).orElse(false);
|
||||
}
|
||||
public static void brainsweep(LivingEntity entity) {
|
||||
if (entity instanceof VillagerDataHolder) {
|
||||
entity.getPersistentData().putBoolean(TAG_BRAINSWEPT, true);
|
||||
|
||||
public static void brainsweep(Villager villager) {
|
||||
var maybeCap = villager.getCapability(HexCapabilities.BRAINSWEPT).resolve();
|
||||
maybeCap.ifPresent(cap -> {
|
||||
cap.brainswept = true;
|
||||
|
||||
var brain = villager.getBrain();
|
||||
if (villager.level instanceof ServerLevel slevel) {
|
||||
brain.stopAll(slevel, villager);
|
||||
if (entity instanceof Villager villager) {
|
||||
Brain<Villager> brain = villager.getBrain();
|
||||
if (entity.level instanceof ServerLevel slevel) {
|
||||
brain.stopAll(slevel, villager);
|
||||
}
|
||||
((AccessorLivingEntity) entity).hex$SetBrain(brain.copyWithoutBehaviors());
|
||||
}
|
||||
((AccessorLivingEntity) villager).hex$SetBrain(brain.copyWithoutBehaviors());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
@ -60,7 +40,11 @@ public class Brainsweeping {
|
|||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void copyBrainsweepToZombie(LivingConversionEvent evt) {
|
||||
|
||||
public static void copyBrainsweepBetweenZombieAndVillager(LivingConversionEvent.Post evt) {
|
||||
var outcome = evt.getOutcome();
|
||||
var original = evt.getEntityLiving();
|
||||
if (outcome instanceof VillagerDataHolder && original instanceof VillagerDataHolder) {
|
||||
if (isBrainswept(original)) brainsweep(outcome);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,5 +39,7 @@ public class HexMessages {
|
|||
MsgCastParticleAck::deserialize, MsgCastParticleAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgOpenSpellGuiAck.class, MsgOpenSpellGuiAck::serialize,
|
||||
MsgOpenSpellGuiAck::deserialize, MsgOpenSpellGuiAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgBeepAck.class, MsgBeepAck::serialize,
|
||||
MsgBeepAck::deserialize, MsgBeepAck::handle);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Sent server->client to synchronize OpAddMotion when the target is a player.
|
||||
*/
|
||||
public record MsgBeepAck(Vec3 target, int note, NoteBlockInstrument instrument) {
|
||||
public static MsgBeepAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
var x = buf.readDouble();
|
||||
var y = buf.readDouble();
|
||||
var z = buf.readDouble();
|
||||
var note = buf.readInt();
|
||||
var instrument = buf.readEnum(NoteBlockInstrument.class);
|
||||
return new MsgBeepAck(new Vec3(x, y, z), note, instrument);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
buf.writeDouble(this.target.x);
|
||||
buf.writeDouble(this.target.y);
|
||||
buf.writeDouble(this.target.z);
|
||||
buf.writeInt(this.note);
|
||||
buf.writeEnum(instrument);
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() ->
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
var world = minecraft.level;
|
||||
if (world != null){
|
||||
float pitch = (float) Math.pow(2, (note - 12) / 12.0);
|
||||
world.playLocalSound(target.x, target.y, target.z, instrument.getSoundEvent(), SoundSource.PLAYERS, 3, pitch, false);
|
||||
world.addParticle(ParticleTypes.NOTE, target.x, target.y + 0.2, target.z, note / 24.0, 0, 0);
|
||||
}
|
||||
})
|
||||
);
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.common.casting.colors.CapPreferredColorizer;
|
||||
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer;
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities;
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
@ -15,32 +14,27 @@ import java.util.function.Supplier;
|
|||
/**
|
||||
* Sent server->client to synchronize the status of the sentinel.
|
||||
*/
|
||||
public record MsgColorizerUpdateAck(CapPreferredColorizer update) {
|
||||
public record MsgColorizerUpdateAck(FrozenColorizer update) {
|
||||
public static MsgColorizerUpdateAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
var tag = buf.readAnySizeNbt();
|
||||
var colorizer = new CapPreferredColorizer(FrozenColorizer.DEFAULT);
|
||||
colorizer.deserializeNBT(tag);
|
||||
var colorizer = FrozenColorizer.deserialize(tag);
|
||||
return new MsgColorizerUpdateAck(colorizer);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
buf.writeNbt(this.update.serializeNBT());
|
||||
buf.writeNbt(this.update.serialize());
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() ->
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
var player = Minecraft.getInstance().player;
|
||||
var maybeCap = player.getCapability(HexCapabilities.PREFERRED_COLORIZER).resolve();
|
||||
if (!maybeCap.isPresent()) {
|
||||
return;
|
||||
if (player != null) {
|
||||
HexPlayerDataHelper.setColorizer(player, update);
|
||||
}
|
||||
|
||||
var cap = maybeCap.get();
|
||||
cap.colorizer = update().colorizer;
|
||||
})
|
||||
);
|
||||
ctx.get().setPacketHandled(true);
|
||||
|
|
|
@ -23,6 +23,7 @@ public record MsgNewSpellPatternAck(ControllerInfo info) {
|
|||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
var wasSpellCast = buf.readBoolean();
|
||||
var hasCastingSound = buf.readBoolean();
|
||||
var isStackEmpty = buf.readBoolean();
|
||||
var wasPrevPatternInvalid = buf.readBoolean();
|
||||
var descsLen = buf.readInt();
|
||||
|
@ -32,7 +33,7 @@ public record MsgNewSpellPatternAck(ControllerInfo info) {
|
|||
}
|
||||
|
||||
return new MsgNewSpellPatternAck(
|
||||
new ControllerInfo(wasSpellCast, isStackEmpty, wasPrevPatternInvalid, desc)
|
||||
new ControllerInfo(wasSpellCast, hasCastingSound, isStackEmpty, wasPrevPatternInvalid, desc)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -40,6 +41,7 @@ public record MsgNewSpellPatternAck(ControllerInfo info) {
|
|||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
buf.writeBoolean(this.info.getWasSpellCast());
|
||||
buf.writeBoolean(this.info.getHasCastingSound());
|
||||
buf.writeBoolean(this.info.isStackClear());
|
||||
buf.writeBoolean(this.info.getWasPrevPatternInvalid());
|
||||
buf.writeInt(this.info.getStackDesc().size());
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.common.casting.*;
|
||||
import at.petrak.hexcasting.common.casting.ControllerInfo;
|
||||
import at.petrak.hexcasting.common.casting.ResolvedPattern;
|
||||
import at.petrak.hexcasting.common.casting.ResolvedPatternValidity;
|
||||
import at.petrak.hexcasting.common.items.ItemWand;
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper;
|
||||
import at.petrak.hexcasting.common.lib.HexSounds;
|
||||
import at.petrak.hexcasting.hexmath.HexCoord;
|
||||
import at.petrak.hexcasting.hexmath.HexPattern;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
|
@ -26,7 +27,7 @@ import java.util.function.Supplier;
|
|||
public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern, List<ResolvedPattern> resolvedPatterns) {
|
||||
public static MsgNewSpellPatternSyn deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
var hand = InteractionHand.values()[buf.readInt()];
|
||||
var hand = buf.readEnum(InteractionHand.class);
|
||||
var pattern = HexPattern.DeserializeFromNBT(buf.readAnySizeNbt());
|
||||
|
||||
var resolvedPatternsLen = buf.readInt();
|
||||
|
@ -39,7 +40,7 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
|
|||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
buf.writeInt(this.handUsed.ordinal());
|
||||
buf.writeEnum(handUsed);
|
||||
buf.writeNbt(this.pattern.serializeToNBT());
|
||||
buf.writeInt(this.resolvedPatterns.size());
|
||||
for (var pat : this.resolvedPatterns) {
|
||||
|
@ -67,45 +68,32 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
|
|||
autoFail = true;
|
||||
}
|
||||
|
||||
var ctx = new CastingContext(sender, this.handUsed);
|
||||
var tag = sender.getPersistentData();
|
||||
var harness = CastingHarness.DeserializeFromNBT(tag.getCompound(ItemWand.TAG_HARNESS), ctx);
|
||||
var harness = HexPlayerDataHelper.getHarness(sender, this.handUsed);
|
||||
|
||||
ControllerInfo clientInfo;
|
||||
if (autoFail) {
|
||||
clientInfo = new ControllerInfo(false, harness.getStack().isEmpty(), true, harness.generateDescs());
|
||||
clientInfo = new ControllerInfo(false, false, harness.getStack().isEmpty(), true, harness.generateDescs());
|
||||
} else {
|
||||
clientInfo = harness.executeNewPattern(this.pattern, sender.getLevel());
|
||||
|
||||
if (clientInfo.getWasSpellCast()) {
|
||||
if (clientInfo.getWasSpellCast() && clientInfo.getHasCastingSound()) {
|
||||
sender.level.playSound(null, sender.getX(), sender.getY(), sender.getZ(),
|
||||
HexSounds.ACTUALLY_CAST.get(), SoundSource.PLAYERS, 1f,
|
||||
1f + ((float) Math.random() - 0.5f) * 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
ListTag patterns = new ListTag();
|
||||
|
||||
CompoundTag nextHarnessTag;
|
||||
if (clientInfo.isStackClear()) {
|
||||
// discard the changes
|
||||
nextHarnessTag = new CompoundTag();
|
||||
HexPlayerDataHelper.setHarness(sender, null);
|
||||
HexPlayerDataHelper.setPatterns(sender, List.of());
|
||||
} else {
|
||||
// save the changes
|
||||
nextHarnessTag = harness.serializeToNBT();
|
||||
if (!resolvedPatterns.isEmpty()) {
|
||||
resolvedPatterns.get(resolvedPatterns.size() - 1)
|
||||
.setValid(clientInfo.getWasPrevPatternInvalid() ?
|
||||
ResolvedPatternValidity.ERROR : ResolvedPatternValidity.OK);
|
||||
}
|
||||
for (var pat : resolvedPatterns) {
|
||||
patterns.add(pat.serializeToNBT());
|
||||
}
|
||||
HexPlayerDataHelper.setHarness(sender, harness);
|
||||
if (!resolvedPatterns.isEmpty())
|
||||
resolvedPatterns.get(resolvedPatterns.size() - 1).setValid(clientInfo.getWasPrevPatternInvalid() ?
|
||||
ResolvedPatternValidity.ERROR : ResolvedPatternValidity.OK);
|
||||
HexPlayerDataHelper.setPatterns(sender, resolvedPatterns);
|
||||
}
|
||||
|
||||
tag.put(ItemWand.TAG_HARNESS, nextHarnessTag);
|
||||
tag.put(ItemWand.TAG_PATTERNS, patterns);
|
||||
|
||||
HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with(() -> sender), new MsgNewSpellPatternAck(clientInfo));
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public record MsgOpenSpellGuiAck(InteractionHand hand, List<ResolvedPattern> pat
|
|||
public static MsgOpenSpellGuiAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
var hand = InteractionHand.values()[buf.readInt()];
|
||||
var hand = buf.readEnum(InteractionHand.class);
|
||||
|
||||
var patternsLen = buf.readInt();
|
||||
var patterns = new ArrayList<ResolvedPattern>(patternsLen);
|
||||
|
@ -41,7 +41,7 @@ public record MsgOpenSpellGuiAck(InteractionHand hand, List<ResolvedPattern> pat
|
|||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
buf.writeInt(this.hand.ordinal());
|
||||
buf.writeEnum(this.hand);
|
||||
|
||||
buf.writeInt(this.patterns.size());
|
||||
for (var pattern : this.patterns) {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.sentinel.CapSentinel;
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilities;
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.sentinel.Sentinel;
|
||||
import at.petrak.hexcasting.common.lib.HexPlayerDataHelper;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
@ -16,35 +17,36 @@ import java.util.function.Supplier;
|
|||
/**
|
||||
* Sent server->client to synchronize the status of the sentinel.
|
||||
*/
|
||||
public record MsgSentinelStatusUpdateAck(CapSentinel update) {
|
||||
public record MsgSentinelStatusUpdateAck(Sentinel update) {
|
||||
public static MsgSentinelStatusUpdateAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
var tag = buf.readAnySizeNbt();
|
||||
var sentinel = new CapSentinel(false, false, Vec3.ZERO, Level.OVERWORLD);
|
||||
sentinel.deserializeNBT(tag);
|
||||
var exists = buf.readBoolean();
|
||||
var greater = buf.readBoolean();
|
||||
var origin = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
|
||||
var dimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, buf.readResourceLocation());
|
||||
|
||||
var sentinel = new Sentinel(exists, greater, origin, dimension);
|
||||
return new MsgSentinelStatusUpdateAck(sentinel);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
buf.writeNbt(this.update.serializeNBT());
|
||||
buf.writeBoolean(update.hasSentinel());
|
||||
buf.writeBoolean(update.extendsRange());
|
||||
buf.writeDouble(update.position().x);
|
||||
buf.writeDouble(update.position().y);
|
||||
buf.writeDouble(update.position().z);
|
||||
buf.writeResourceLocation(update.dimension().location());
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() ->
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
var player = Minecraft.getInstance().player;
|
||||
var maybeCap = player.getCapability(HexCapabilities.SENTINEL).resolve();
|
||||
if (!maybeCap.isPresent()) {
|
||||
return;
|
||||
if (player != null) {
|
||||
HexPlayerDataHelper.setSentinel(player, update);
|
||||
}
|
||||
|
||||
var cap = maybeCap.get();
|
||||
cap.hasSentinel = update().hasSentinel;
|
||||
cap.extendsRange = update().extendsRange;
|
||||
cap.position = update().position;
|
||||
cap.dimension = update().dimension;
|
||||
})
|
||||
);
|
||||
ctx.get().setPacketHandled(true);
|
||||
|
|
|
@ -26,7 +26,7 @@ import java.util.function.Supplier;
|
|||
public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolean isCtrl) {
|
||||
public static MsgShiftScrollSyn deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
var hand = InteractionHand.values()[buf.readInt()];
|
||||
var hand = buf.readEnum(InteractionHand.class);
|
||||
var scrollDelta = buf.readDouble();
|
||||
var isCtrl = buf.readBoolean();
|
||||
return new MsgShiftScrollSyn(hand, scrollDelta, isCtrl);
|
||||
|
@ -34,7 +34,7 @@ public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolea
|
|||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
buf.writeInt(this.hand.ordinal());
|
||||
buf.writeEnum(this.hand);
|
||||
buf.writeDouble(this.scrollDelta);
|
||||
buf.writeBoolean(this.isCtrl);
|
||||
}
|
||||
|
@ -57,10 +57,10 @@ public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolea
|
|||
|
||||
private void spellbook(ServerPlayer sender, ItemStack stack) {
|
||||
var tag = stack.getOrCreateTag();
|
||||
ItemSpellbook.RotatePageIdx(stack, tag, this.scrollDelta < 0.0);
|
||||
ItemSpellbook.RotatePageIdx(stack, this.scrollDelta < 0.0);
|
||||
|
||||
var newIdx = tag.getInt(ItemSpellbook.TAG_SELECTED_PAGE);
|
||||
var len = ItemSpellbook.HighestPage(tag.getCompound(ItemSpellbook.TAG_PAGES));
|
||||
var len = ItemSpellbook.HighestPage(stack);
|
||||
|
||||
MutableComponent component;
|
||||
if (hand == InteractionHand.OFF_HAND && stack.hasCustomHoverName()) {
|
||||
|
@ -106,7 +106,7 @@ public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolea
|
|||
var datumTag = HexItems.ABACUS.get().readDatumTag(stack);
|
||||
if (datumTag != null) {
|
||||
var popup = SpellDatum.DisplayFromTag(datumTag);
|
||||
sender.displayClientMessage(new TranslatableComponent("hexcasting.tooltip.abacus", popup).withStyle(ChatFormatting.GREEN, ChatFormatting.BOLD), true);
|
||||
sender.displayClientMessage(new TranslatableComponent("hexcasting.tooltip.abacus", popup).withStyle(ChatFormatting.GREEN), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ data class HexPattern(val startDir: HexDir, val angles: MutableList<HexAngle> =
|
|||
|
||||
@JvmStatic
|
||||
fun IsHexPattern(tag: CompoundTag): Boolean {
|
||||
return tag.contains(TAG_START_DIR, Tag.TAG_BYTE.toInt()) && tag.contains(TAG_ANGLES, Tag.TAG_BYTE_ARRAY.toInt())
|
||||
return tag.contains(TAG_START_DIR, Tag.TAG_ANY_NUMERIC.toInt()) && tag.contains(TAG_ANGLES, Tag.TAG_BYTE_ARRAY.toInt())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
|
30
src/main/java/at/petrak/hexcasting/mixin/MixinMob.java
Normal file
30
src/main/java/at/petrak/hexcasting/mixin/MixinMob.java
Normal file
|
@ -0,0 +1,30 @@
|
|||
package at.petrak.hexcasting.mixin;
|
||||
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
// Prevents the villager from any of its brain goals or making ambient noise
|
||||
@Mixin(Mob.class)
|
||||
public class MixinMob {
|
||||
@Inject(method = "serverAiStep", at = @At("HEAD"), cancellable = true)
|
||||
private void onRegisterBrainGoals(CallbackInfo ci) {
|
||||
var self = (Mob) (Object) this;
|
||||
if (Brainsweeping.isBrainswept(self)) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getAmbientSound", at = @At("HEAD"), cancellable = true)
|
||||
protected void onGetAmbientSound(CallbackInfoReturnable<SoundEvent> ci) {
|
||||
var self = (Mob) (Object) this;
|
||||
if (Brainsweeping.isBrainswept(self)) {
|
||||
ci.setReturnValue(null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,11 @@
|
|||
package at.petrak.hexcasting.mixin;
|
||||
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
// Prevents the villager from any of its brain goals or making ambient noise
|
||||
@Mixin(Villager.class)
|
||||
|
@ -19,12 +17,4 @@ public class MixinVillager {
|
|||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getAmbientSound", at = @At("HEAD"), cancellable = true)
|
||||
protected void onGetAmbientSound(CallbackInfoReturnable<SoundEvent> ci) {
|
||||
var self = (Villager) (Object) this;
|
||||
if (Brainsweeping.isBrainswept(self)) {
|
||||
ci.setReturnValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
"hexcasting.tooltip.abacus": "%d",
|
||||
"hexcasting.tooltip.abacus.reset": "Reset to 0",
|
||||
"hexcasting.tooltip.abacus.reset.nice": "nice",
|
||||
"hexcasting.tooltip.lens.impetus.mana": "%s Dusts",
|
||||
"hexcasting.tooltip.lens.impetus.mana": "%s dust",
|
||||
"hexcasting.tooltip.lens.impetus.storedplayer": "Bound to %s",
|
||||
"hexcasting.tooltip.lens.impetus.storedplayer.none": "Unbound",
|
||||
"hexcasting.tooltip.lens.pattern.invalid": "Invalid Pattern",
|
||||
|
@ -130,6 +130,7 @@
|
|||
|
||||
"death.attack.hexcasting.overcast": "%s's mind was consumed into energy",
|
||||
|
||||
"command.hexcasting.pats.listing": "Patterns in this world:",
|
||||
"command.hexcasting.pats.all": "Gave you all %d scrolls",
|
||||
"command.hexcasting.pats.specific.success": "Gave you %s with id %s",
|
||||
"command.hexcasting.recalc": "Recalculated patterns",
|
||||
|
@ -187,17 +188,17 @@
|
|||
"hexcasting.spell.hexcasting:get_entity/item": "Entity Prfn.: Item",
|
||||
"hexcasting.spell.hexcasting:get_entity/player": "Entity Prfn.: Player",
|
||||
"hexcasting.spell.hexcasting:get_entity/living": "Entity Prfn.: Living",
|
||||
"hexcasting.spell.hexcasting:zone_entity": "Zone Dstln.: Any",
|
||||
"hexcasting.spell.hexcasting:zone_entity/animal": "Zone Dstln.: Animal",
|
||||
"hexcasting.spell.hexcasting:zone_entity/monster": "Zone Dstln.: Monster",
|
||||
"hexcasting.spell.hexcasting:zone_entity/item": "Zone Dstln.: Item",
|
||||
"hexcasting.spell.hexcasting:zone_entity/player": "Zone Dstln.: Player",
|
||||
"hexcasting.spell.hexcasting:zone_entity/living": "Zone Dstln.: Living",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_animal": "Zone Dstln.: Non-Animal",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_monster": "Zone Dstln.: Non-Monster",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_item": "Zone Dstln.: Non-Item",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_player": "Zone Dstln.: Non-Player",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_living": "Zone Dstln.: Non-Living",
|
||||
"hexcasting.spell.hexcasting:zone_entity": "Zone Dstl.: Any",
|
||||
"hexcasting.spell.hexcasting:zone_entity/animal": "Zone Dstl.: Animal",
|
||||
"hexcasting.spell.hexcasting:zone_entity/monster": "Zone Dstl.: Monster",
|
||||
"hexcasting.spell.hexcasting:zone_entity/item": "Zone Dstl.: Item",
|
||||
"hexcasting.spell.hexcasting:zone_entity/player": "Zone Dstl.: Player",
|
||||
"hexcasting.spell.hexcasting:zone_entity/living": "Zone Dstl.: Living",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_animal": "Zone Dstl.: Non-Animal",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_monster": "Zone Dstl.: Non-Monster",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_item": "Zone Dstl.: Non-Item",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_player": "Zone Dstl.: Non-Player",
|
||||
"hexcasting.spell.hexcasting:zone_entity/not_living": "Zone Dstl.: Non-Living",
|
||||
"hexcasting.spell.hexcasting:undo": "Novice's Gambit",
|
||||
"hexcasting.spell.hexcasting:const/null": "Nullary Reflection",
|
||||
"hexcasting.spell.hexcasting:duplicate": "Gemini Decomposition",
|
||||
|
@ -207,8 +208,8 @@
|
|||
"hexcasting.spell.hexcasting:swizzle": "Swindler's Gambit",
|
||||
"hexcasting.spell.hexcasting:add": "Additive Distillation",
|
||||
"hexcasting.spell.hexcasting:sub": "Subtractive Distillation",
|
||||
"hexcasting.spell.hexcasting:mul_dot": "Multiplicative Dstln.",
|
||||
"hexcasting.spell.hexcasting:div_cross": "Division Dstln.",
|
||||
"hexcasting.spell.hexcasting:mul_dot": "Multiplicative Dstl.",
|
||||
"hexcasting.spell.hexcasting:div_cross": "Division Dstl.",
|
||||
"hexcasting.spell.hexcasting:abs_len": "Length Purification",
|
||||
"hexcasting.spell.hexcasting:pow_proj": "Power Distillation",
|
||||
"hexcasting.spell.hexcasting:construct_vec": "Vector Exaltation",
|
||||
|
@ -233,8 +234,10 @@
|
|||
"hexcasting.spell.hexcasting:arccos": "Inverse Cosine Prfn.",
|
||||
"hexcasting.spell.hexcasting:arctan": "Inverse Tangent Prfn.",
|
||||
"hexcasting.spell.hexcasting:random": "Entropy Reflection",
|
||||
"hexcasting.spell.hexcasting:logarithm": "Logarithmic Distillation",
|
||||
"hexcasting.spell.hexcasting:coerce_axial": "Axial Purification",
|
||||
"hexcasting.spell.hexcasting:print": "Reveal",
|
||||
"hexcasting.spell.hexcasting:beep": "Make Note",
|
||||
"hexcasting.spell.hexcasting:explode": "Explosion",
|
||||
"hexcasting.spell.hexcasting:explode/fire": "Fireball",
|
||||
"hexcasting.spell.hexcasting:add_motion": "Impulse",
|
||||
|
@ -352,6 +355,7 @@
|
|||
"hexcasting.mishap.divide_by_zero.divide": "Attempted to divide %s by %s",
|
||||
"hexcasting.mishap.divide_by_zero.project": "Attempted to project %s onto %s",
|
||||
"hexcasting.mishap.divide_by_zero.exponent": "Attempted to raise %s to the %s",
|
||||
"hexcasting.mishap.divide_by_zero.logarithm": "Attempted to get the logarithm of %s in base %s",
|
||||
"hexcasting.mishap.divide_by_zero.zero": "zero",
|
||||
"hexcasting.mishap.divide_by_zero.zero.power": "zeroth power",
|
||||
"hexcasting.mishap.divide_by_zero.zero.vec": "the zero vector",
|
||||
|
@ -399,7 +403,7 @@
|
|||
|
||||
"hexcasting.entry.couldnt_cast": "A Frustration",
|
||||
"hexcasting.page.couldnt_cast.1": "Argh! Why won't it let me cast the spell?!$(br2)The scroll I found rings with authenticity. I can $(italic)feel/$ it humming in the scroll-- the pattern is true, or as true as it can be. The spell is $(italic)right there/$.$(p)But it feels if it's on the other side of some thin membrane. I called it-- it tried to manifest-- yet it $(italic)COULD NOT/$.",
|
||||
"hexcasting.page.couldnt_cast.2": "It felt like the barrier may have weakened ever so slightly from the force that I exerted on the spell; yet despite my greatest efforts-- my deepest focus, my finest amethyst, my precisest drawings-- it $(italic)refuses/$ to cross the barrier. It's maddening.$(p)$(italic)This/$ is where my arcane studies? Cursed by impotence, cursed to lose my rightful powers?$(br2)I should take a deep breath. I should meditate on what I have learned, even if it wasn't very much...",
|
||||
"hexcasting.page.couldnt_cast.2": "It felt like the barrier may have weakened ever so slightly from the force that I exerted on the spell; yet despite my greatest efforts-- my deepest focus, my finest amethyst, my precisest drawings-- it $(italic)refuses/$ to cross the barrier. It's maddening.$(p)$(italic)This/$ is where my arcane studies end? Cursed by impotence, cursed to lose my rightful powers?$(br2)I should take a deep breath. I should meditate on what I have learned, even if it wasn't very much...",
|
||||
"hexcasting.page.couldnt_cast.3": "...After careful reflection... I have discovered a change in myself.$(p)It seems... in lieu of $(item)amethyst/$, I've unlocked the ability to cast spells using my own mind and life energy-- just as I read of in the legends of old.$(p)I'm not sure why I can now. It's just... the truth-knowledge-burden was always there, and I see it now. I know it. I bear it.$(br2)Fortunately, I feel my limits as well-- I would get approximately two $(item)Charged Amethyst/$'s worth of _media out of my health at its prime.",
|
||||
"hexcasting.page.couldnt_cast.4": "I shudder to even consider it-- I've kept my mind mostly intact so far, in my studies. But the fact is-- I form one side of a tenuous link.$(p)I'm connected to some other side-- a side whose boundary has thinned from that trauma. A place where simple actions spell out eternal glory.$(p)Is it so wrong, to want it for myself?",
|
||||
|
||||
|
@ -520,7 +524,7 @@
|
|||
"hexcasting.page.pigments.1": "Although their names were lost to time, the old practitioners of my art seem to have identified themselves by a color, emblematic of them and their spells. It seems a special kind of pigment, offered to Nature in the right way, would \"[...] paint one's thoughts in a manner pleasing to Nature, inducing a miraculous change in personal colour.\"",
|
||||
"hexcasting.page.pigments.2": "I'm not certain on the specifics of how it works, but I believe I have isolated the formulae for many different colors of pigments. To use a pigment, I hold it in one hand while casting $(l:patterns/spells/colorize)$(action)Internalize Pigment/$ with the other, consuming the pigment and marking my mind with its color.$(br2)The pigments seem to affect the color of the sparks of media emitted out of a staff when I cast a _Hex, as well as my $(l:patterns/spells/sentinels)$(action)Sentinel/$.",
|
||||
"hexcasting.page.pigments.3.header": "Chromatic Pigments",
|
||||
"hexcasting.page.pigments.3": "Pigments all the colors of the rainbow.",
|
||||
"hexcasting.page.pigments.3": "Pigments in all the colors of the rainbow.",
|
||||
"hexcasting.page.pigments.4": "And finally, a pigment with a color wholly unique to me.$(br2)$(italic)And all the colors I am inside have not been invented yet./$",
|
||||
|
||||
"hexcasting.entry.edified": "Edified Trees",
|
||||
|
@ -629,6 +633,7 @@
|
|||
"hexcasting.page.math.abs_len.2": "Replaces a number with its absolute value, or a vector with its length.",
|
||||
"hexcasting.page.math.pow_proj.1": "Perform exponentiation or vector projection.",
|
||||
"hexcasting.page.math.pow_proj.2": "With two numbers, combines them by raising the first to the power of the second.$(li)With a number and a vector, removes the number and raises each component of the vector to the number's power.$(li)With two vectors, combines them into the $(l:https://en.wikipedia.org/wiki/Vector_projection)vector projection/$ of the top of the stack onto the second-from-the-top.$(br2)In the first and second cases, the first argument or its components are the base, and the second argument or its components are the exponent.",
|
||||
"hexcasting.page.math.logarithm": "Removes the number at the top of the stack, then takes the logarithm of the number at the top using the other number as its base.",
|
||||
"hexcasting.page.math.floor": "\"Floors\" a number, cutting off the fractional component and leaving an integer value.",
|
||||
"hexcasting.page.math.ceil": "\"Ceilings\" a number, raising it to the next integer value if it has a fractional component.",
|
||||
"hexcasting.page.math.construct_vec": "Combine three numbers at the top of the stack into a vector's X, Y, and Z components (top to bottom).",
|
||||
|
@ -755,6 +760,8 @@
|
|||
"hexcasting.page.basic_spell.explode.fire.2": "Costs three $(item)Amethyst Shards/$, plus about one extra $(item)Amethyst Shard/$ per point of explosion power. Otherwise, the same as $(l:patterns/spells/basic_spell#hexcasting:explosion)$(action)Explosion/$, except with fire.",
|
||||
"hexcasting.page.basic_spell.add_motion": "Remove an entity and direction from the stack, then give a shove to the given entity in the given direction. The strength of the impulse is determined by the length of the vector.$(br)Costs units of $(item)Amethyst Dust/$ equal to the square of the length of the vector.",
|
||||
"hexcasting.page.basic_spell.blink": "Remove an entity and length from the stack, then teleport the given entity along its look vector by the given length.$(br)Costs about 1 $(item)Amethyst Shard/$ per block travelled.",
|
||||
"hexcasting.page.basic_spell.beep.1": "Remove a vector and two numbers from the stack. Plays a instrument defined by the first number at the given location, with a note defined by the second number. Costs a negligible amount of _media.",
|
||||
"hexcasting.page.basic_spell.beep.2": "There appear to be 16 different instruments and 25 different notes. Both are indexed by zero.",
|
||||
|
||||
"hexcasting.entry.blockworks": "Blockworks",
|
||||
"hexcasting.page.blockworks.place_block": "Remove a location from the stack, then pick a block item and place it at the given location.$(br)Costs about 1 $(item)Amethyst Dust/$.",
|
||||
|
|
|
@ -85,6 +85,22 @@
|
|||
"type": "patchouli:text",
|
||||
"text": "hexcasting.page.math.pow_proj.2"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:logarithm",
|
||||
"anchor": "hexcasting:logarithm",
|
||||
"input": "num, num",
|
||||
"output": "num",
|
||||
"text": "hexcasting.page.math.logarithm"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:random",
|
||||
"anchor": "hexcasting:random",
|
||||
"input": "",
|
||||
"output": "num",
|
||||
"text": "hexcasting.page.math.random"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:floor",
|
||||
|
@ -117,22 +133,6 @@
|
|||
"output": "num, num, num",
|
||||
"text": "hexcasting.page.math.deconstruct_vec"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:coerce_axial",
|
||||
"anchor": "hexcasting:coerce_axial",
|
||||
"input": "vec",
|
||||
"output": "vec",
|
||||
"text": "hexcasting.page.math.coerce_axial"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:random",
|
||||
"anchor": "hexcasting:random",
|
||||
"input": "vec",
|
||||
"output": "vec",
|
||||
"text": "hexcasting.page.math.random"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:sin",
|
||||
|
@ -180,6 +180,14 @@
|
|||
"input": "num",
|
||||
"output": "num",
|
||||
"text": "hexcasting.page.math.arctan"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:coerce_axial",
|
||||
"anchor": "hexcasting:coerce_axial",
|
||||
"input": "vec",
|
||||
"output": "vec",
|
||||
"text": "hexcasting.page.math.coerce_axial"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -45,6 +45,18 @@
|
|||
"input": "entity, number",
|
||||
"output": "",
|
||||
"text": "hexcasting.page.basic_spell.blink"
|
||||
},
|
||||
{
|
||||
"type": "hexcasting:pattern",
|
||||
"op_id": "hexcasting:beep",
|
||||
"anchor": "hexcasting:beep",
|
||||
"input": "vector, number, number",
|
||||
"output": "",
|
||||
"text": "hexcasting.page.basic_spell.beep.1"
|
||||
},
|
||||
{
|
||||
"type": "patchouli:text",
|
||||
"text": "hexcasting.page.basic_spell.beep.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
"refmap": "hexcasting.mixins.refmap.json",
|
||||
"package": "at.petrak.hexcasting.mixin",
|
||||
"mixins": [
|
||||
"AccessorLivingEntity", "MixinVillager"
|
||||
"AccessorLivingEntity",
|
||||
"MixinMob",
|
||||
"MixinVillager"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue