possibly implement hoppering into impetus. i dont know.

This commit is contained in:
gamma-delta 2022-03-20 23:23:31 -05:00
parent 2a7f816be7
commit 9adcbabad3
5 changed files with 178 additions and 17 deletions

View file

@ -5,13 +5,13 @@ import net.minecraft.world.item.Tiers;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
public class HexConfig { public class HexConfig {
public static ForgeConfigSpec.DoubleValue manaToHealthRate;
public static ForgeConfigSpec.IntValue dustManaAmount; public static ForgeConfigSpec.IntValue dustManaAmount;
public static ForgeConfigSpec.IntValue shardManaAmount; public static ForgeConfigSpec.IntValue shardManaAmount;
public static ForgeConfigSpec.IntValue chargedCrystalManaAmount; public static ForgeConfigSpec.IntValue chargedCrystalManaAmount;
public static ForgeConfigSpec.IntValue smallBudAmount;
public static ForgeConfigSpec.IntValue mediumBudAmount;
public static ForgeConfigSpec.IntValue largeBudAmount;
public static ForgeConfigSpec.DoubleValue manaToHealthRate;
public static ForgeConfigSpec.IntValue opBreakHarvestLevel; public static ForgeConfigSpec.IntValue opBreakHarvestLevel;
public static ForgeConfigSpec.IntValue maxRecurseDepth; public static ForgeConfigSpec.IntValue maxRecurseDepth;
@ -20,19 +20,18 @@ public class HexConfig {
public HexConfig(ForgeConfigSpec.Builder builder) { public HexConfig(ForgeConfigSpec.Builder builder) {
manaToHealthRate = builder.comment("How many points of mana a half-heart is worth when casting from HP") builder.push("Mana Amounts");
.defineInRange("manaToHealthRate", 200_000.0 / 20.0, 0.0, Double.POSITIVE_INFINITY);
builder.push("items");
dustManaAmount = builder.comment("How much mana a single Amethyst Dust item is worth") dustManaAmount = builder.comment("How much mana a single Amethyst Dust item is worth")
.defineInRange("dustManaAmount", 10_000, 0, Integer.MAX_VALUE); .defineInRange("dustManaAmount", 10_000, 0, Integer.MAX_VALUE);
shardManaAmount = builder.comment("How much mana a single Amethyst Shard item is worth") shardManaAmount = builder.comment("How much mana a single Amethyst Shard item is worth")
.defineInRange("shardManaAmount", 50_000, 0, Integer.MAX_VALUE); .defineInRange("shardManaAmount", 50_000, 0, Integer.MAX_VALUE);
chargedCrystalManaAmount = builder.comment("How much mana a single Charged Amethyst Crystal item is worth") chargedCrystalManaAmount = builder.comment("How much mana a single Charged Amethyst Crystal item is worth")
.defineInRange("chargedCrystalManaAmount", 100_000, 0, Integer.MAX_VALUE); .defineInRange("chargedCrystalManaAmount", 100_000, 0, Integer.MAX_VALUE);
manaToHealthRate = builder.comment("How many points of mana a half-heart is worth when casting from HP")
.defineInRange("manaToHealthRate", 200_000.0 / 20.0, 0.0, Double.POSITIVE_INFINITY);
builder.pop(); builder.pop();
builder.push("spells"); builder.push("Spells");
maxRecurseDepth = builder.comment("How many times a spell can recursively cast other spells") maxRecurseDepth = builder.comment("How many times a spell can recursively cast other spells")
.defineInRange("maxRecurseDepth", 64, 0, Integer.MAX_VALUE); .defineInRange("maxRecurseDepth", 64, 0, Integer.MAX_VALUE);
opBreakHarvestLevel = builder.comment( opBreakHarvestLevel = builder.comment(
@ -41,7 +40,7 @@ public class HexConfig {
).defineInRange("opBreakHarvestLevel", 3, 0, 4); ).defineInRange("opBreakHarvestLevel", 3, 0, 4);
builder.pop(); builder.pop();
builder.push("spell_circles"); builder.push("Spell Circles");
maxSpellCircleLength = builder.comment("The maximum number of slates in a spell circle") maxSpellCircleLength = builder.comment("The maximum number of slates in a spell circle")
.defineInRange("maxSpellCircleLength", 256, 4, Integer.MAX_VALUE); .defineInRange("maxSpellCircleLength", 256, 4, Integer.MAX_VALUE);
} }

View file

@ -7,9 +7,11 @@ import at.petrak.hexcasting.common.blocks.ModBlockEntity;
import at.petrak.hexcasting.common.casting.CastingContext; import at.petrak.hexcasting.common.casting.CastingContext;
import at.petrak.hexcasting.common.casting.CastingHarness; import at.petrak.hexcasting.common.casting.CastingHarness;
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer; 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.HexCapabilities;
import at.petrak.hexcasting.common.lib.HexSounds; import at.petrak.hexcasting.common.lib.HexSounds;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.NbtUtils;
@ -21,17 +23,25 @@ import net.minecraft.tags.BlockTags;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
public abstract class BlockEntityAbstractImpetus extends ModBlockEntity { public abstract class BlockEntityAbstractImpetus extends ModBlockEntity implements ICapabilityProvider {
public static final String public static final String
TAG_ACTIVATOR = "activator", TAG_ACTIVATOR = "activator",
TAG_COLORIZER = "colorizer", TAG_COLORIZER = "colorizer",
@ -49,10 +59,13 @@ public abstract class BlockEntityAbstractImpetus extends ModBlockEntity {
@Nullable @Nullable
private List<BlockPos> trackedBlocks = null; private List<BlockPos> trackedBlocks = null;
private boolean foundAll = false; private boolean foundAll = false;
private int mana = 0; private int mana = 0;
private LazyOptional<IItemHandler> inventoryHandlerLazy;
public BlockEntityAbstractImpetus(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) { public BlockEntityAbstractImpetus(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) {
super(pType, pWorldPosition, pBlockState); super(pType, pWorldPosition, pBlockState);
inventoryHandlerLazy = LazyOptional.of(() -> ITEM_HANDLER);
} }
abstract public boolean playerAlwaysInRange(); abstract public boolean playerAlwaysInRange();
@ -278,6 +291,21 @@ public abstract class BlockEntityAbstractImpetus extends ModBlockEntity {
return scale[note]; return scale[note];
} }
@NotNull
@Override
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return inventoryHandlerLazy.cast();
}
return super.getCapability(cap, side);
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
inventoryHandlerLazy.invalidate();
}
@Override @Override
protected void saveModData(CompoundTag tag) { protected void saveModData(CompoundTag tag) {
if (this.activator != null && this.colorizer != null && this.nextBlock != null && this.trackedBlocks != null) { if (this.activator != null && this.colorizer != null && this.nextBlock != null && this.trackedBlocks != null) {
@ -321,4 +349,62 @@ public abstract class BlockEntityAbstractImpetus extends ModBlockEntity {
private static final int[] BLUES_SCALE = {0, 3, 5, 6, 7, 10, 12}; private static final int[] BLUES_SCALE = {0, 3, 5, 6, 7, 10, 12};
private static final int[] BAD_TIME = {0, 0, 12, 7, 6, 5, 3, 0, 3, 5}; private static final int[] BAD_TIME = {0, 0, 12, 7, 6, 5, 3, 0, 3, 5};
private static final int[] SUSSY_BAKA = {5, 8, 10, 11, 10, 8, 5, 3, 7, 5}; private static final int[] SUSSY_BAKA = {5, 8, 10, 11, 10, 8, 5, 3, 7, 5};
protected IItemHandler ITEM_HANDLER = new IItemHandler() {
@Override
public int getSlots() {
return 1;
}
@NotNull
@Override
public ItemStack getStackInSlot(int slot) {
return ItemStack.EMPTY;
}
@NotNull
@Override
public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) {
var manamount = getManaAmount(stack);
if (manamount != null) {
if (!simulate) {
BlockEntityAbstractImpetus.this.mana += manamount;
}
return ItemStack.EMPTY.copy();
}
return stack.copy();
}
@NotNull
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
return ItemStack.EMPTY.copy();
}
@Override
public int getSlotLimit(int slot) {
return 64;
}
@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();
}
};
} }

View file

@ -17,7 +17,7 @@ import java.util.function.Predicate
import kotlin.math.min import kotlin.math.min
/** /**
* Info about the moment the spell started being cast. * Transient info about the moment the spell started being cast.
*/ */
data class CastingContext( data class CastingContext(
val caster: ServerPlayer, val caster: ServerPlayer,

View file

@ -2,8 +2,8 @@ package at.petrak.hexcasting.common.casting
import at.petrak.hexcasting.HexConfig import at.petrak.hexcasting.HexConfig
import at.petrak.hexcasting.HexMod import at.petrak.hexcasting.HexMod
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.PatternRegistry import at.petrak.hexcasting.api.PatternRegistry
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.common.casting.colors.FrozenColorizer import at.petrak.hexcasting.common.casting.colors.FrozenColorizer
import at.petrak.hexcasting.common.items.ItemWand import at.petrak.hexcasting.common.items.ItemWand
@ -33,10 +33,16 @@ class CastingHarness private constructor(
var parenthesized: List<HexPattern>, var parenthesized: List<HexPattern>,
var escapeNext: Boolean, var escapeNext: Boolean,
val ctx: CastingContext, val ctx: CastingContext,
val prepackagedColorizer: FrozenColorizer? val spellCircleContext: SpellCircleContext?,
val prepackagedColorizer: FrozenColorizer? // for trinkets with colorizers
) { ) {
constructor(ctx: CastingContext) : this(mutableListOf(), 0, mutableListOf(), false, ctx, null) @JvmOverloads
constructor(
ctx: CastingContext,
spellCircleContext: SpellCircleContext? = null,
prepackagedColorizer: FrozenColorizer? = null
) : this(mutableListOf(), 0, mutableListOf(), false, ctx, spellCircleContext, prepackagedColorizer)
/** /**
* Given a pattern, do all the updating/side effects/etc required. * Given a pattern, do all the updating/side effects/etc required.
@ -52,8 +58,8 @@ class CastingHarness private constructor(
* handle it functionally. * handle it functionally.
*/ */
fun getUpdate(newPat: HexPattern, world: ServerLevel): CastResult { fun getUpdate(newPat: HexPattern, world: ServerLevel): CastResult {
this.ctx.caster.awardStat(HexStatistics.PATTERNS_DRAWN)
try { try {
this.ctx.caster.awardStat(HexStatistics.PATTERNS_DRAWN)
// wouldn't it be nice to be able to go paren' // wouldn't it be nice to be able to go paren'
// i guess i'll call it paren2 // i guess i'll call it paren2
val paren2 = this.handleParentheses(newPat) val paren2 = this.handleParentheses(newPat)
@ -321,6 +327,10 @@ class CastingHarness private constructor(
out.put(TAG_PREPACKAGED_COLORIZER, this.prepackagedColorizer.serialize()) out.put(TAG_PREPACKAGED_COLORIZER, this.prepackagedColorizer.serialize())
} }
if (this.spellCircleContext != null) {
out.put(TAG_SPELL_CIRCLE, this.spellCircleContext.serializeToNBT())
}
return out return out
} }
@ -331,6 +341,7 @@ class CastingHarness private constructor(
const val TAG_PARENTHESIZED = "parenthesized" const val TAG_PARENTHESIZED = "parenthesized"
const val TAG_ESCAPE_NEXT = "escape_next" const val TAG_ESCAPE_NEXT = "escape_next"
const val TAG_PREPACKAGED_COLORIZER = "prepackaged_colorizer" const val TAG_PREPACKAGED_COLORIZER = "prepackaged_colorizer"
const val TAG_SPELL_CIRCLE = "spell_circle"
@JvmStatic @JvmStatic
fun DeserializeFromNBT(nbt: Tag?, caster: ServerPlayer, wandHand: InteractionHand): CastingHarness { fun DeserializeFromNBT(nbt: Tag?, caster: ServerPlayer, wandHand: InteractionHand): CastingHarness {
@ -360,7 +371,13 @@ class CastingHarness private constructor(
null null
} }
CastingHarness(stack, parenCount, parenthesized, escapeNext, ctx, colorizer) val spellCircleContext = if (nbt.contains(TAG_SPELL_CIRCLE)) {
SpellCircleContext.DeserializeFromNBT(nbt.getCompound(TAG_SPELL_CIRCLE))
} else {
null
}
CastingHarness(stack, parenCount, parenthesized, escapeNext, ctx, spellCircleContext, colorizer)
} catch (exn: Exception) { } catch (exn: Exception) {
HexMod.LOGGER.warn("Couldn't load harness from nbt tag, falling back to default: $nbt: $exn") HexMod.LOGGER.warn("Couldn't load harness from nbt tag, falling back to default: $nbt: $exn")
CastingHarness(ctx) CastingHarness(ctx)

View file

@ -0,0 +1,59 @@
package at.petrak.hexcasting.common.casting
import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.phys.AABB
/**
* Optional field on a [CastingContext] for the spell circle
*/
data class SpellCircleContext(val impetusPos: BlockPos, val aabb: AABB, val playerAlwaysInRange: Boolean) {
fun serializeToNBT(): CompoundTag {
val out = CompoundTag()
out.putInt(TAG_IMPETUS_X, impetusPos.x)
out.putInt(TAG_IMPETUS_Y, impetusPos.y)
out.putInt(TAG_IMPETUS_Z, impetusPos.z)
out.putDouble(TAG_MIN_X, aabb.minX)
out.putDouble(TAG_MIN_Y, aabb.minY)
out.putDouble(TAG_MIN_Z, aabb.minZ)
out.putDouble(TAG_MAX_X, aabb.maxX)
out.putDouble(TAG_MAX_Y, aabb.maxY)
out.putDouble(TAG_MAX_Z, aabb.maxZ)
out.putBoolean(TAG_PLAYER_ALWAYS_IN_RANGE, playerAlwaysInRange)
return out
}
companion object {
const val TAG_IMPETUS_X = "impetus_x"
const val TAG_IMPETUS_Y = "impetus_y"
const val TAG_IMPETUS_Z = "impetus_z"
const val TAG_MIN_X = "min_x"
const val TAG_MIN_Y = "min_y"
const val TAG_MIN_Z = "min_z"
const val TAG_MAX_X = "max_x"
const val TAG_MAX_Y = "max_y"
const val TAG_MAX_Z = "max_z"
const val TAG_PLAYER_ALWAYS_IN_RANGE = "player_always_in_range"
fun DeserializeFromNBT(tag: CompoundTag): SpellCircleContext {
val impX = tag.getInt(TAG_IMPETUS_X)
val impY = tag.getInt(TAG_IMPETUS_Y)
val impZ = tag.getInt(TAG_IMPETUS_Z)
val minX = tag.getDouble(TAG_MIN_X)
val minY = tag.getDouble(TAG_MIN_Y)
val minZ = tag.getDouble(TAG_MIN_Z)
val maxX = tag.getDouble(TAG_MAX_X)
val maxY = tag.getDouble(TAG_MAX_Y)
val maxZ = tag.getDouble(TAG_MAX_Z)
val playerAIR = tag.getBoolean(TAG_PLAYER_ALWAYS_IN_RANGE)
return SpellCircleContext(BlockPos(impX, impY, impZ), AABB(minX, minY, minZ, maxX, maxY, maxZ), playerAIR)
}
}
}