Merge branch 'main' into arbitrary-brainsweeps

This commit is contained in:
petrak@ 2022-11-22 09:44:20 -06:00
commit 30701702c7
100 changed files with 1788 additions and 1586 deletions

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.api.addldata;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;

View file

@ -0,0 +1,83 @@
package at.petrak.hexcasting.api.addldata;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.common.entities.EntityWallScroll;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
import java.util.function.Supplier;
public abstract class ItemDelegatingEntityIotaHolder implements ADIotaHolder {
private final Supplier<ItemStack> stackSupplier;
private final Consumer<ItemStack> save;
public ItemDelegatingEntityIotaHolder(Supplier<ItemStack> stackSupplier, Consumer<ItemStack> save) {
this.stackSupplier = stackSupplier;
this.save = save;
}
@Override
public @Nullable CompoundTag readIotaTag() {
var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get());
return delegate == null ? null : delegate.readIotaTag();
}
@Override
public boolean writeIota(@Nullable Iota datum, boolean simulate) {
var stacc = this.stackSupplier.get();
var delegate = IXplatAbstractions.INSTANCE.findDataHolder(stacc);
var success = delegate != null && delegate.writeIota(datum, simulate);
if (success && !simulate) {
this.save.accept(stacc);
}
return success;
}
@Override
public @Nullable Iota readIota(ServerLevel world) {
var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get());
return delegate == null ? null : delegate.readIota(world);
}
@Override
public @Nullable Iota emptyIota() {
var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get());
return delegate == null ? null : delegate.emptyIota();
}
public static class ToItemEntity extends ItemDelegatingEntityIotaHolder {
public ToItemEntity(ItemEntity entity) {
super(entity::getItem, stack -> {
// https://github.com/VazkiiMods/Botania/blob/e6d095ff5010074b45408d6cce8ee1e328af3383/Xplat/src/main/java/vazkii/botania/common/helper/EntityHelper.java#L16
entity.setItem(ItemStack.EMPTY);
entity.setItem(stack);
entity.setUnlimitedLifetime();
});
}
}
public static class ToItemFrame extends ItemDelegatingEntityIotaHolder {
public ToItemFrame(ItemFrame entity) {
super(entity::getItem, entity::setItem);
}
}
public static class ToWallScroll extends ItemDelegatingEntityIotaHolder {
public ToWallScroll(EntityWallScroll entity) {
super(() -> entity.scroll.copy(), stack -> {
});
}
@Override
public boolean writeIota(@Nullable Iota datum, boolean simulate) {
return false;
}
}
}

View file

@ -4,7 +4,7 @@ import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.ClientTickCounter;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;

View file

@ -28,8 +28,6 @@ public class HexConfig {
}
public interface ClientConfigAccess {
double patternPointSpeedMultiplier();
boolean ctrlTogglesOffStrokeOrder();
boolean invertSpellbookScrollDirection();
@ -38,7 +36,6 @@ public class HexConfig {
double gridSnapThreshold();
double DEFAULT_PATTERN_POINT_SPEED_MULTIPLIER = 1;
boolean DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER = false;
boolean DEFAULT_INVERT_SPELLBOOK_SCROLL = false;
boolean DEFAULT_INVERT_ABACUS_SCROLL = false;
@ -60,9 +57,11 @@ public class HexConfig {
ScrollQuantity scrollsForLootTable(ResourceLocation lootTable);
int DEFAULT_MAX_RECURSE_DEPTH = 64;
int DEFAULT_MAX_RECURSE_DEPTH = 512;
int DEFAULT_MAX_SPELL_CIRCLE_LENGTH = 1024;
int DEFAULT_OP_BREAK_HARVEST_LEVEL = 3;
boolean DEFAULT_VILLAGERS_DISLIKE_MIND_MURDER = true;
List<String> DEFAULT_FEW_SCROLL_TABLES = List.of("minecraft:chests/jungle_temple",
"minecraft:chests/simple_dungeon", "minecraft:chests/village/village_cartographer");
List<String> DEFAULT_SOME_SCROLL_TABLES = List.of("minecraft:chests/bastion_treasure",

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.api.spell
import at.petrak.hexcasting.api.PatternRegistry
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.api.utils.lightPurple

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.api.spell
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.spell.iota.Iota
/**

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs

View file

@ -12,6 +12,12 @@ import at.petrak.hexcasting.api.mod.HexStatistics
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.SpellList
import at.petrak.hexcasting.api.spell.casting.eval.ContinuationFrame
import at.petrak.hexcasting.api.spell.casting.eval.FrameEvaluate
import at.petrak.hexcasting.api.spell.casting.eval.FunctionalData
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.sideeffects.EvalSound
import at.petrak.hexcasting.api.spell.casting.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.iota.ListIota
import at.petrak.hexcasting.api.spell.iota.PatternIota
@ -19,7 +25,8 @@ import at.petrak.hexcasting.api.spell.math.HexDir
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.*
import at.petrak.hexcasting.api.utils.*
import at.petrak.hexcasting.common.lib.HexIotaTypes
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.ChatFormatting
import net.minecraft.nbt.CompoundTag
@ -75,13 +82,13 @@ class CastingHarness private constructor(
}
private fun getPatternForFrame(frame: ContinuationFrame): HexPattern? {
if (frame !is ContinuationFrame.Evaluate) return null
if (frame !is FrameEvaluate) return null
return (frame.list.car as? PatternIota)?.pattern
}
private fun getOperatorForFrame(frame: ContinuationFrame, world: ServerLevel): Action? {
if (frame !is ContinuationFrame.Evaluate) return null
if (frame !is FrameEvaluate) return null
return getOperatorForPattern(frame.list.car, world)
}
@ -91,10 +98,11 @@ class CastingHarness private constructor(
*/
fun executeIotas(iotas: List<Iota>, world: ServerLevel): ControllerInfo {
// Initialize the continuation stack to a single top-level eval for all iotas.
var continuation = SpellContinuation.Done.pushFrame(ContinuationFrame.Evaluate(SpellList.LList(0, iotas)))
var continuation = SpellContinuation.Done.pushFrame(FrameEvaluate(SpellList.LList(0, iotas), false))
// Begin aggregating info
val info = TempControllerInfo(earlyExit = false)
var lastResolutionType = ResolvedPatternType.UNRESOLVED
var sound = HexEvalSounds.NOTHING
while (continuation is SpellContinuation.NotDone && !info.earlyExit) {
// Take the top of the continuation stack...
val next = continuation.frame
@ -114,7 +122,7 @@ class CastingHarness private constructor(
Mishap.Context(pattern ?: HexPattern(HexDir.WEST), operator)
)
),
EvalSound.MISHAP,
HexEvalSounds.MISHAP,
)
}
// Then write all pertinent data back to the harness for the next iteration.
@ -123,8 +131,22 @@ class CastingHarness private constructor(
}
continuation = result.continuation
lastResolutionType = result.resolutionType
performSideEffects(info, result.sideEffects, result.sound)
performSideEffects(info, result.sideEffects)
info.earlyExit = info.earlyExit || !lastResolutionType.success
sound = if (result.sound == HexEvalSounds.MISHAP) {
HexEvalSounds.MISHAP
} else {
sound.greaterOf(result.sound)
}
}
sound.sound?.let {
this.ctx.world.playSound(
null, this.ctx.position.x, this.ctx.position.y, this.ctx.position.z, it,
SoundSource.PLAYERS, 1f, 1f
)
// TODO: is it worth mixing in to the immut map and making our own game event with blackjack and hookers
this.ctx.world.gameEvent(this.ctx.caster, GameEvent.ITEM_INTERACT_FINISH, this.ctx.position)
}
if (continuation is SpellContinuation.NotDone) {
@ -146,14 +168,15 @@ class CastingHarness private constructor(
fun getUpdate(iota: Iota, world: ServerLevel, continuation: SpellContinuation): CastResult {
try {
// TODO we can have a special intro/retro sound
this.handleParentheses(iota)?.let { (data, resolutionType) ->
return@getUpdate CastResult(continuation, data, resolutionType, listOf(), EvalSound.GENERIC)
return@getUpdate CastResult(continuation, data, resolutionType, listOf(), HexEvalSounds.OPERATOR)
}
return if (iota is PatternIota) {
updateWithPattern(iota.pattern, world, continuation)
if (iota is PatternIota) {
return updateWithPattern(iota.pattern, world, continuation)
} else {
CastResult(
return CastResult(
continuation,
null,
ResolvedPatternType.INVALID, // Should never matter
@ -163,7 +186,7 @@ class CastingHarness private constructor(
Mishap.Context(HexPattern(HexDir.WEST), null)
)
),
EvalSound.MISHAP
HexEvalSounds.MISHAP
)
}
} catch (mishap: Mishap) {
@ -180,7 +203,7 @@ class CastingHarness private constructor(
)
)
),
EvalSound.MISHAP
HexEvalSounds.MISHAP
)
} catch (exception: Exception) {
// This means something very bad has happened
@ -198,7 +221,7 @@ class CastingHarness private constructor(
)
)
),
EvalSound.MISHAP
HexEvalSounds.MISHAP
)
}
}
@ -272,20 +295,22 @@ class CastingHarness private constructor(
hereFd
}
var soundType =
if (this.ctx.source == CastingContext.CastSource.STAFF) EvalSound.GENERIC else EvalSound.NONE;
var soundType = if (this.ctx.source == CastingContext.CastSource.STAFF) {
HexEvalSounds.OPERATOR
} else {
HexEvalSounds.NOTHING
}
for (se in sideEffects) {
if (se is OperatorSideEffect.AttemptSpell) {
if (se.hasCastingSound) {
soundType = soundType.greaterOf(EvalSound.SPELL_BOINK)
soundType = if (se.hasCastingSound) {
soundType.greaterOf(HexEvalSounds.SPELL)
} else {
// WITH CATLIKE TREAD
// UPON OUR PREY WE STEAL
soundType = EvalSound.NONE
break
HexEvalSounds.NOTHING
}
} else if (se is OperatorSideEffect.DoMishap) {
soundType = EvalSound.MISHAP
soundType = HexEvalSounds.MISHAP
}
}
return CastResult(
@ -302,7 +327,7 @@ class CastingHarness private constructor(
null,
mishap.resolutionType(ctx),
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, actionIdPair?.first))),
EvalSound.MISHAP
HexEvalSounds.MISHAP
)
}
}
@ -310,7 +335,7 @@ class CastingHarness private constructor(
/**
* Execute the side effects of a pattern, updating our aggregated info.
*/
fun performSideEffects(info: TempControllerInfo, sideEffects: List<OperatorSideEffect>, sound: EvalSound) {
fun performSideEffects(info: TempControllerInfo, sideEffects: List<OperatorSideEffect>) {
for (haskellProgrammersShakingandCryingRN in sideEffects) {
val mustStop = haskellProgrammersShakingandCryingRN.performEffect(this)
if (mustStop) {
@ -318,14 +343,6 @@ class CastingHarness private constructor(
break
}
}
sound.soundEvent()?.let {
this.ctx.world.playSound(
null, this.ctx.position.x, this.ctx.position.y, this.ctx.position.z, it,
SoundSource.PLAYERS, 1f, 1f
)
// TODO: is it worth mixing in to the immut map and making our own game event with blackjack and hookers
this.ctx.world.gameEvent(this.ctx.caster, GameEvent.ITEM_INTERACT_FINISH, this.ctx.position)
}
}
fun generateDescs() = Triple(
@ -382,6 +399,7 @@ class CastingHarness private constructor(
escapeNext = true,
) to ResolvedPatternType.EVALUATED
}
SpecialPatterns.INTROSPECTION.anglesSignature() -> {
// we have escaped the parens onto the stack; we just also record our count.
val newParens = this.parenthesized.toMutableList()
@ -391,6 +409,7 @@ class CastingHarness private constructor(
parenCount = this.parenCount + 1
) to if (this.parenCount == 0) ResolvedPatternType.EVALUATED else ResolvedPatternType.ESCAPED
}
SpecialPatterns.RETROSPECTION.anglesSignature() -> {
val newParenCount = this.parenCount - 1
displayDepth--
@ -415,6 +434,7 @@ class CastingHarness private constructor(
) to ResolvedPatternType.ESCAPED
}
}
else -> {
val newParens = this.parenthesized.toMutableList()
newParens.add(iota)
@ -438,14 +458,17 @@ class CastingHarness private constructor(
escapeNext = true
) to ResolvedPatternType.EVALUATED
}
SpecialPatterns.INTROSPECTION.anglesSignature() -> {
this.getFunctionalData().copy(
parenCount = this.parenCount + 1
) to ResolvedPatternType.EVALUATED
}
SpecialPatterns.RETROSPECTION.anglesSignature() -> {
throw MishapTooManyCloseParens()
}
else -> {
null
}

View file

@ -1,214 +0,0 @@
package at.petrak.hexcasting.api.spell.casting
import at.petrak.hexcasting.api.spell.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingHarness.CastResult
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.iota.ListIota
import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.api.utils.getList
import at.petrak.hexcasting.api.utils.hasList
import at.petrak.hexcasting.api.utils.serializeToNBT
import at.petrak.hexcasting.common.lib.HexIotaTypes
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.server.level.ServerLevel
// TODO this should probably be a registry too
/**
* A single frame of evaluation during the execution of a spell.
*
* Specifically, an evaluation will keep a stack of these frames.
* An evaluation with no meta-eval will consist of a single [Evaluate(rest of the pats)] at all times.
* When an Eval is invoked, we push Evaluate(pats) to the top of the stack.
*
* Evaluation is performed by repeatedly popping the top-most (i.e. innermost) frame from the stack,
* then evaluating that frame (and possibly allowing it to push other frames (e.g. if it's a Hermes)).
*
* Once the stack of frames is empty, there are no more computations to run, so we're done.
*/
sealed interface ContinuationFrame {
/**
* Step the evaluation forward once.
* For Evaluate, this consumes one pattern; for ForEach this queues the next iteration of the outer loop.
* @return the result of this pattern step
*/
fun evaluate(continuation: SpellContinuation, level: ServerLevel, harness: CastingHarness): CastResult
/**
* The OpHalt instruction wants us to "jump to" the END of the nearest meta-eval.
* In other words, we should consume Evaluate frames until we hit a FinishEval or Thoth frame.
* @return whether the break should stop here, alongside the new stack state (e.g. for finalizing a Thoth)
*/
fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>>
/**
* Serializes this frame. Used for things like delays, where we pause execution.
*/
fun serializeToNBT(): CompoundTag
/**
* A list of patterns to be evaluated in sequence.
* @property list the *remaining* list of patterns to be evaluated
*/
data class Evaluate(val list: SpellList) : ContinuationFrame {
// Discard this frame and keep discarding frames.
override fun breakDownwards(stack: List<Iota>) = false to stack
// Step the list of patterns, evaluating a single one.
override fun evaluate(
continuation: SpellContinuation,
level: ServerLevel,
harness: CastingHarness
): CastResult {
// If there are patterns left...
return if (list.nonEmpty) {
val newCont = if (list.cdr.nonEmpty) { // yay TCO
// ...enqueue the evaluation of the rest of the patterns...
continuation.pushFrame(Evaluate(list.cdr))
} else continuation
// ...before evaluating the first one in the list.
harness.getUpdate(list.car, level, newCont)
} else {
// If there are no patterns (e.g. empty Hermes), just return OK.
CastResult(continuation, null, ResolvedPatternType.EVALUATED, listOf(), EvalSound.NONE)
}
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "evaluate"
"patterns" %= list.serializeToNBT()
}
}
/**
* A stack marker representing the end of a Hermes evaluation,
* so that we know when to stop removing frames during a Halt.
*/
object FinishEval : ContinuationFrame {
// Don't do anything else to the stack, just finish the halt statement.
override fun breakDownwards(stack: List<Iota>) = true to stack
// Evaluating it does nothing; it's only a boundary condition.
override fun evaluate(
continuation: SpellContinuation,
level: ServerLevel,
harness: CastingHarness
): CastResult {
return CastResult(
continuation,
FunctionalData(harness.stack.toList(), 0, listOf(), false, harness.ravenmind),
ResolvedPatternType.EVALUATED,
listOf(),
EvalSound.NONE,
)
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "end"
}
}
/**
* A frame representing all the state for a Thoth evaluation.
* Pushed by an OpForEach.
* @property first whether the input stack state is the first one (since we don't want to save the base-stack before any changes are made)
* @property data list of *remaining* datums to ForEach over
* @property code code to run per datum
* @property baseStack the stack state at Thoth entry
* @property acc concatenated list of final stack states after Thoth exit
*/
data class ForEach(
val data: SpellList,
val code: SpellList,
val baseStack: List<Iota>?,
val acc: MutableList<Iota>
) : ContinuationFrame {
/** When halting, we add the stack state at halt to the stack accumulator, then return the original pre-Thoth stack, plus the accumulator. */
override fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>> {
val newStack = baseStack?.toMutableList() ?: mutableListOf()
acc.addAll(stack)
newStack.add(ListIota(acc))
return true to newStack
}
/** Step the Thoth computation, enqueueing one code evaluation. */
override fun evaluate(
continuation: SpellContinuation,
level: ServerLevel,
harness: CastingHarness
): CastResult {
// If this isn't the very first Thoth step (i.e. no Thoth computations run yet)...
val stack = if (baseStack == null) {
// init stack to the harness stack...
harness.stack.toList()
} else {
// else save the stack to the accumulator and reuse the saved base stack.
acc.addAll(harness.stack)
baseStack
}
// If we still have data to process...
val (stackTop, newCont) = if (data.nonEmpty) {
// Increment the evaluation depth,
harness.ctx.incDepth()
// push the next datum to the top of the stack,
data.car to continuation
// put the next Thoth object back on the stack for the next Thoth cycle,
.pushFrame(ForEach(data.cdr, code, stack, acc))
// and prep the Thoth'd code block for evaluation.
.pushFrame(Evaluate(code))
} else {
// Else, dump our final list onto the stack.
ListIota(acc) to continuation
}
val tStack = stack.toMutableList()
tStack.add(stackTop)
// TODO: this means we could have Thoth casting do a different sound
return CastResult(
newCont,
FunctionalData(tStack, 0, listOf(), false, harness.ravenmind),
ResolvedPatternType.EVALUATED,
listOf(),
EvalSound.NONE,
)
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "foreach"
"data" %= data.serializeToNBT()
"code" %= code.serializeToNBT()
if (baseStack != null)
"base" %= baseStack.serializeToNBT()
"accumulator" %= acc.serializeToNBT()
}
}
companion object {
@JvmStatic
fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame {
return when (tag.getString("type")) {
"eval" -> Evaluate(
HexIotaTypes.LIST.deserialize(
tag.getList("patterns", Tag.TAG_COMPOUND),
world
)!!.list
)
"end" -> FinishEval
"foreach" -> ForEach(
HexIotaTypes.LIST.deserialize(tag.getList("data", Tag.TAG_COMPOUND), world)!!.list,
HexIotaTypes.LIST.deserialize(tag.getList("code", Tag.TAG_COMPOUND), world)!!.list,
if (tag.hasList("base", Tag.TAG_COMPOUND))
HexIotaTypes.LIST.deserialize(tag.getList("base", Tag.TAG_COMPOUND), world)!!.list.toList()
else
null,
HexIotaTypes.LIST.deserialize(
tag.getList("accumulator", Tag.TAG_COMPOUND),
world
)!!.list.toMutableList()
)
else -> Evaluate(SpellList.LList(0, listOf()))
}
}
}
}

View file

@ -1,34 +0,0 @@
package at.petrak.hexcasting.api.spell.casting
import at.petrak.hexcasting.common.lib.HexSounds
import net.minecraft.sounds.SoundEvent
/**
* Sound that plays as a side-effect-adjacent when casting
*/
enum class EvalSound {
/** Silence */
NONE,
/** The generic "bvwonh" sound for non-spell ops */
GENERIC,
/** The "bwoink!" for spell ops */
SPELL_BOINK,
/** The "gvwoh" for mishaps */
MISHAP;
/**
* Which sound type has the greater priority?
*/
fun greaterOf(that: EvalSound): EvalSound =
EvalSound.values()[maxOf(this.ordinal, that.ordinal)]
fun soundEvent(): SoundEvent? = when (this) {
NONE -> null
GENERIC -> HexSounds.ADD_PATTERN
SPELL_BOINK -> HexSounds.ACTUALLY_CAST
MISHAP -> HexSounds.FAIL_PATTERN
}
}

View file

@ -0,0 +1,78 @@
package at.petrak.hexcasting.api.spell.casting.eval
import at.petrak.hexcasting.api.spell.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingHarness
import at.petrak.hexcasting.api.spell.casting.CastingHarness.CastResult
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.utils.getList
import at.petrak.hexcasting.api.utils.hasList
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.server.level.ServerLevel
// TODO this should probably be a registry too
/**
* A single frame of evaluation during the execution of a spell.
*
* Specifically, an evaluation will keep a stack of these frames.
* An evaluation with no meta-eval will consist of a single [Evaluate(rest of the pats)] at all times.
* When an Eval is invoked, we push Evaluate(pats) to the top of the stack.
*
* Evaluation is performed by repeatedly popping the top-most (i.e. innermost) frame from the stack,
* then evaluating that frame (and possibly allowing it to push other frames (e.g. if it's a Hermes)).
*
* Once the stack of frames is empty, there are no more computations to run, so we're done.
*
*/
sealed interface ContinuationFrame {
/**
* Step the evaluation forward once.
* For Evaluate, this consumes one pattern; for ForEach this queues the next iteration of the outer loop.
* @return the result of this pattern step
*/
fun evaluate(continuation: SpellContinuation, level: ServerLevel, harness: CastingHarness): CastResult
/**
* The OpHalt instruction wants us to "jump to" the END of the nearest meta-eval.
* In other words, we should consume Evaluate frames until we hit a FinishEval or Thoth frame.
* @return whether the break should stop here, alongside the new stack state (e.g. for finalizing a Thoth)
*/
fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>>
/**
* Serializes this frame. Used for things like delays, where we pause execution.
*/
fun serializeToNBT(): CompoundTag
companion object {
@JvmStatic
fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame {
return when (tag.getString("type")) {
"eval" -> FrameEvaluate(
HexIotaTypes.LIST.deserialize(
tag.getList("patterns", Tag.TAG_COMPOUND),
world
)!!.list,
tag.getBoolean("isMetacasting")
)
"end" -> FrameFinishEval
"foreach" -> FrameForEach(
HexIotaTypes.LIST.deserialize(tag.getList("data", Tag.TAG_COMPOUND), world)!!.list,
HexIotaTypes.LIST.deserialize(tag.getList("code", Tag.TAG_COMPOUND), world)!!.list,
if (tag.hasList("base", Tag.TAG_COMPOUND))
HexIotaTypes.LIST.deserialize(tag.getList("base", Tag.TAG_COMPOUND), world)!!.list.toList()
else
null,
HexIotaTypes.LIST.deserialize(
tag.getList("accumulator", Tag.TAG_COMPOUND),
world
)!!.list.toMutableList()
)
else -> FrameEvaluate(SpellList.LList(0, listOf()), false)
}
}
}
}

View file

@ -0,0 +1,51 @@
package at.petrak.hexcasting.api.spell.casting.eval
import at.petrak.hexcasting.api.spell.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingHarness
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.api.utils.serializeToNBT
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import net.minecraft.server.level.ServerLevel
/**
* A list of patterns to be evaluated in sequence.
* @property list the *remaining* list of patterns to be evaluated
* @property isMetacasting only for sound effects, if this is being cast from a hermes / iris
*/
data class FrameEvaluate(val list: SpellList, val isMetacasting: Boolean) : ContinuationFrame {
// Discard this frame and keep discarding frames.
override fun breakDownwards(stack: List<Iota>) = false to stack
// Step the list of patterns, evaluating a single one.
override fun evaluate(
continuation: SpellContinuation,
level: ServerLevel,
harness: CastingHarness
): CastingHarness.CastResult {
// If there are patterns left...
return if (list.nonEmpty) {
val newCont = if (list.cdr.nonEmpty) { // yay TCO
// ...enqueue the evaluation of the rest of the patterns...
continuation.pushFrame(FrameEvaluate(list.cdr, this.isMetacasting))
} else continuation
// ...before evaluating the first one in the list.
val update = harness.getUpdate(list.car, level, newCont)
if (this.isMetacasting && update.sound != HexEvalSounds.MISHAP) {
update.copy(sound = HexEvalSounds.HERMES)
} else {
update
}
} else {
// If there are no patterns (e.g. empty Hermes), just return OK.
CastingHarness.CastResult(continuation, null, ResolvedPatternType.EVALUATED, listOf(), HexEvalSounds.HERMES)
}
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "evaluate"
"patterns" %= list.serializeToNBT()
"isMetacasting" %= isMetacasting
}
}

View file

@ -0,0 +1,36 @@
package at.petrak.hexcasting.api.spell.casting.eval
import at.petrak.hexcasting.api.spell.casting.CastingHarness
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import net.minecraft.server.level.ServerLevel
/**
* A stack marker representing the end of a Hermes evaluation,
* so that we know when to stop removing frames during a Halt.
*/
object FrameFinishEval : ContinuationFrame {
// Don't do anything else to the stack, just finish the halt statement.
override fun breakDownwards(stack: List<Iota>) = true to stack
// Evaluating it does nothing; it's only a boundary condition.
override fun evaluate(
continuation: SpellContinuation,
level: ServerLevel,
harness: CastingHarness
): CastingHarness.CastResult {
return CastingHarness.CastResult(
continuation,
FunctionalData(harness.stack.toList(), 0, listOf(), false, harness.ravenmind),
ResolvedPatternType.EVALUATED,
listOf(),
HexEvalSounds.NOTHING,
)
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "end"
}
}

View file

@ -0,0 +1,87 @@
package at.petrak.hexcasting.api.spell.casting.eval
import at.petrak.hexcasting.api.spell.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingHarness
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.iota.ListIota
import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.api.utils.serializeToNBT
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import net.minecraft.server.level.ServerLevel
/**
* A frame representing all the state for a Thoth evaluation.
* Pushed by an OpForEach.
* @property first whether the input stack state is the first one (since we don't want to save the base-stack before any changes are made)
* @property data list of *remaining* datums to ForEach over
* @property code code to run per datum
* @property baseStack the stack state at Thoth entry
* @property acc concatenated list of final stack states after Thoth exit
*/
data class FrameForEach(
val data: SpellList,
val code: SpellList,
val baseStack: List<Iota>?,
val acc: MutableList<Iota>
) : ContinuationFrame {
/** When halting, we add the stack state at halt to the stack accumulator, then return the original pre-Thoth stack, plus the accumulator. */
override fun breakDownwards(stack: List<Iota>): Pair<Boolean, List<Iota>> {
val newStack = baseStack?.toMutableList() ?: mutableListOf()
acc.addAll(stack)
newStack.add(ListIota(acc))
return true to newStack
}
/** Step the Thoth computation, enqueueing one code evaluation. */
override fun evaluate(
continuation: SpellContinuation,
level: ServerLevel,
harness: CastingHarness
): CastingHarness.CastResult {
// If this isn't the very first Thoth step (i.e. no Thoth computations run yet)...
val stack = if (baseStack == null) {
// init stack to the harness stack...
harness.stack.toList()
} else {
// else save the stack to the accumulator and reuse the saved base stack.
acc.addAll(harness.stack)
baseStack
}
// If we still have data to process...
val (stackTop, newCont) = if (data.nonEmpty) {
// Increment the evaluation depth,
harness.ctx.incDepth()
// push the next datum to the top of the stack,
data.car to continuation
// put the next Thoth object back on the stack for the next Thoth cycle,
.pushFrame(FrameForEach(data.cdr, code, stack, acc))
// and prep the Thoth'd code block for evaluation.
.pushFrame(FrameEvaluate(code, true))
} else {
// Else, dump our final list onto the stack.
ListIota(acc) to continuation
}
val tStack = stack.toMutableList()
tStack.add(stackTop)
// TODO: this means we could have Thoth casting do a different sound
return CastingHarness.CastResult(
newCont,
FunctionalData(tStack, 0, listOf(), false, harness.ravenmind),
ResolvedPatternType.EVALUATED,
listOf(),
HexEvalSounds.THOTH,
)
}
override fun serializeToNBT() = NBTBuilder {
"type" %= "foreach"
"data" %= data.serializeToNBT()
"code" %= code.serializeToNBT()
if (baseStack != null)
"base" %= baseStack.serializeToNBT()
"accumulator" %= acc.serializeToNBT()
}
}

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.casting
package at.petrak.hexcasting.api.spell.casting.eval
import at.petrak.hexcasting.api.spell.iota.Iota

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.casting
package at.petrak.hexcasting.api.spell.casting.eval
/**
* A continuation during the execution of a spell.

View file

@ -0,0 +1,18 @@
package at.petrak.hexcasting.api.spell.casting.sideeffects;
import net.minecraft.sounds.SoundEvent;
import org.jetbrains.annotations.Nullable;
/**
* The kind of sound that plays after a cast.
*
* @param sound the actual sound file
* @param priority the priority of this sound. the sound with the highest priority in a given cast will be
* playd.
* shortcutMetacasting takes precedence over this.
*/
public record EvalSound(@Nullable SoundEvent sound, int priority) {
public EvalSound greaterOf(EvalSound that) {
return (this.priority > that.priority) ? this : that;
}
}

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.casting
package at.petrak.hexcasting.api.spell.casting.sideeffects
import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus
@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.mod.HexStatistics
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.casting.CastingHarness
import at.petrak.hexcasting.api.spell.mishaps.Mishap
import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.common.lib.HexItems

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.Tag;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.Tag;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull;

View file

@ -1,15 +1,12 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import net.minecraft.client.gui.Font;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextColor;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.FormattedCharSequence;
import javax.annotation.Nullable;
import java.util.List;
// Take notes from ForgeRegistryEntry
public abstract class IotaType<T extends Iota> {
@ -31,15 +28,6 @@ public abstract class IotaType<T extends Iota> {
*/
public abstract Component display(Tag tag);
/**
* Get a display of this datum from the {@code data} tag, with a maximum width.
* This is for use on the client.
*/
public List<FormattedCharSequence> displayWithWidth(Tag tag, int maxWidth, Font font) {
var display = this.display(tag);
return font.split(display, maxWidth);
}
/**
* Get the color associated with this datum type.
*/

View file

@ -2,16 +2,13 @@ package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.api.spell.SpellList;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.Font;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.FormattedCharSequence;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -112,54 +109,6 @@ public class ListIota extends Iota {
return Component.translatable("hexcasting.tooltip.list_contents", out).withStyle(ChatFormatting.DARK_PURPLE);
}
@Override
public List<FormattedCharSequence> displayWithWidth(Tag tag, int maxWidth, Font font) {
// We aim to not break one iota between lines
var listTag = HexUtils.downcast(tag, ListTag.TYPE);
var start = FormattedCharSequence.forward(listTag.isEmpty() ? "[]" : "[", Style.EMPTY.withColor(ChatFormatting.DARK_PURPLE));
var cursor = font.width(start);
var currentLine = new ArrayList<>(List.of(start));
var out = new ArrayList<FormattedCharSequence>();
for (int i = 0; i < listTag.size(); i++) {
Tag subtag = listTag.get(i);
var cSubtag = HexUtils.downcast(subtag, CompoundTag.TYPE);
var translation = HexIotaTypes.getDisplay(cSubtag);
var currentElement = translation.getVisualOrderText();
String addl;
if (i < listTag.size() - 1) {
addl = ", ";
} else {
// Last go-around, so add the closing bracket
addl = "]";
}
currentElement = FormattedCharSequence.composite(currentElement,
FormattedCharSequence.forward(addl, Style.EMPTY.withColor(ChatFormatting.DARK_PURPLE)));
var width = font.width(currentElement);
if (cursor + width > maxWidth) {
out.add(FormattedCharSequence.composite(currentLine));
currentLine = new ArrayList<>();
// Indent further lines by two spaces
var indentation = FormattedCharSequence.forward(" ", Style.EMPTY);
var lineStart = FormattedCharSequence.composite(indentation, currentElement);
currentLine.add(lineStart);
cursor = font.width(lineStart);
} else {
currentLine.add(currentElement);
cursor += width;
}
}
if (!currentLine.isEmpty()) {
out.add(FormattedCharSequence.composite(currentLine));
}
return out;
}
@Override
public int color() {
return 0xff_aa00aa;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
@ -15,7 +15,8 @@ import org.jetbrains.annotations.Nullable;
public class NullIota extends Iota {
private static final Object NULL_SUBSTITUTE = new Object();
public static final Component DISPLAY = Component.translatable("hexcasting.tooltip.null_iota").withStyle(ChatFormatting.GRAY);
public static final Component DISPLAY =
Component.translatable("hexcasting.tooltip.null_iota").withStyle(ChatFormatting.GRAY);
public NullIota() {
// We have to pass *something* here, but there's nothing that actually needs to go there,

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.LongArrayTag;
import net.minecraft.nbt.Tag;

View file

@ -5,7 +5,7 @@ package at.petrak.hexcasting.api.utils
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.iota.ListIota
import at.petrak.hexcasting.api.spell.math.HexCoord
import at.petrak.hexcasting.common.lib.HexIotaTypes
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import net.minecraft.ChatFormatting
import net.minecraft.nbt.*
import net.minecraft.network.chat.Component

View file

@ -18,7 +18,7 @@ import at.petrak.hexcasting.common.items.magic.ItemMediaBattery;
import at.petrak.hexcasting.common.items.magic.ItemPackagedHex;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import at.petrak.hexcasting.common.lib.HexBlocks;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.xplat.IClientXplatAbstractions;
import com.mojang.datafixers.util.Pair;
@ -56,11 +56,11 @@ import java.util.function.UnaryOperator;
public class RegisterClientStuff {
public static void init() {
registerDataHolderOverrides(HexItems.FOCUS,
stack -> HexItems.FOCUS.readIotaTag(stack) != null,
ItemFocus::isSealed);
stack -> HexItems.FOCUS.readIotaTag(stack) != null,
ItemFocus::isSealed);
registerDataHolderOverrides(HexItems.SPELLBOOK,
stack -> HexItems.SPELLBOOK.readIotaTag(stack) != null,
ItemSpellbook::isSealed);
stack -> HexItems.SPELLBOOK.readIotaTag(stack) != null,
ItemSpellbook::isSealed);
registerPackagedSpellOverrides(HexItems.CYPHER);
registerPackagedSpellOverrides(HexItems.TRINKET);
@ -68,23 +68,23 @@ public class RegisterClientStuff {
var x = IClientXplatAbstractions.INSTANCE;
x.registerItemProperty(HexItems.BATTERY, ItemMediaBattery.MEDIA_PREDICATE,
(stack, level, holder, holderID) -> {
var item = (MediaHolderItem) stack.getItem();
return item.getMediaFullness(stack);
});
(stack, level, holder, holderID) -> {
var item = (MediaHolderItem) stack.getItem();
return item.getMediaFullness(stack);
});
x.registerItemProperty(HexItems.BATTERY, ItemMediaBattery.MAX_MEDIA_PREDICATE,
(stack, level, holder, holderID) -> {
var item = (ItemMediaBattery) stack.getItem();
var max = item.getMaxMedia(stack);
return (float) Math.sqrt((float) max / MediaConstants.CRYSTAL_UNIT / 10);
});
(stack, level, holder, holderID) -> {
var item = (ItemMediaBattery) stack.getItem();
var max = item.getMaxMedia(stack);
return (float) Math.sqrt((float) max / MediaConstants.CRYSTAL_UNIT / 10);
});
registerScrollOverrides(HexItems.SCROLL_SMOL);
registerScrollOverrides(HexItems.SCROLL_MEDIUM);
registerScrollOverrides(HexItems.SCROLL_LARGE);
x.registerItemProperty(HexItems.SLATE, ItemSlate.WRITTEN_PRED,
(stack, level, holder, holderID) -> ItemSlate.hasPattern(stack) ? 1f : 0f);
(stack, level, holder, holderID) -> ItemSlate.hasPattern(stack) ? 1f : 0f);
registerWandOverrides(HexItems.STAFF_OAK);
registerWandOverrides(HexItems.STAFF_BIRCH);
@ -158,117 +158,117 @@ public class RegisterClientStuff {
private static void addScryingLensStuff() {
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.getBlock() instanceof BlockAbstractImpetus,
(lines, state, pos, observer, world, direction) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) {
beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction);
}
});
(state, pos, observer, world, direction) -> state.getBlock() instanceof BlockAbstractImpetus,
(lines, state, pos, observer, world, direction) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) {
beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction);
}
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.NOTE_BLOCK,
(lines, state, pos, observer, world, direction) -> {
int note = state.getValue(NoteBlock.NOTE);
(lines, state, pos, observer, world, direction) -> {
int note = state.getValue(NoteBlock.NOTE);
float rCol = Math.max(0.0F, Mth.sin((note / 24F + 0.0F) * Mth.TWO_PI) * 0.65F + 0.35F);
float gCol = Math.max(0.0F, Mth.sin((note / 24F + 0.33333334F) * Mth.TWO_PI) * 0.65F + 0.35F);
float bCol = Math.max(0.0F, Mth.sin((note / 24F + 0.6666667F) * Mth.TWO_PI) * 0.65F + 0.35F);
float rCol = Math.max(0.0F, Mth.sin((note / 24F + 0.0F) * Mth.TWO_PI) * 0.65F + 0.35F);
float gCol = Math.max(0.0F, Mth.sin((note / 24F + 0.33333334F) * Mth.TWO_PI) * 0.65F + 0.35F);
float bCol = Math.max(0.0F, Mth.sin((note / 24F + 0.6666667F) * Mth.TWO_PI) * 0.65F + 0.35F);
int noteColor = 0xFF_000000 | Mth.color(rCol, gCol, bCol);
int noteColor = 0xFF_000000 | Mth.color(rCol, gCol, bCol);
var instrument = state.getValue(NoteBlock.INSTRUMENT);
var instrument = state.getValue(NoteBlock.INSTRUMENT);
lines.add(new Pair<>(
new ItemStack(Items.MUSIC_DISC_CHIRP),
Component.literal(String.valueOf(instrument.ordinal()))
.withStyle(color(instrumentColor(instrument)))));
lines.add(new Pair<>(
new ItemStack(Items.NOTE_BLOCK),
Component.literal(String.valueOf(note))
.withStyle(color(noteColor))));
});
lines.add(new Pair<>(
new ItemStack(Items.MUSIC_DISC_CHIRP),
Component.literal(String.valueOf(instrument.ordinal()))
.withStyle(color(instrumentColor(instrument)))));
lines.add(new Pair<>(
new ItemStack(Items.NOTE_BLOCK),
Component.literal(String.valueOf(note))
.withStyle(color(noteColor))));
});
ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_BOOKSHELF,
(lines, state, pos, observer, world, direction) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) {
var iotaTag = tile.getIotaTag();
if (iotaTag != null) {
var display = HexIotaTypes.getDisplay(iotaTag);
lines.add(new Pair<>(new ItemStack(Items.BOOK), display));
}
(lines, state, pos, observer, world, direction) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) {
var iotaTag = tile.getIotaTag();
if (iotaTag != null) {
var display = HexIotaTypes.getDisplay(iotaTag);
lines.add(new Pair<>(new ItemStack(Items.BOOK), display));
}
});
}
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.COMPARATOR,
(lines, state, pos, observer, world, direction) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(true);
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE),
Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
(lines, state, pos, observer, world, direction) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(true);
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE),
Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
boolean compare = state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE;
boolean compare = state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE;
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE_TORCH),
Component.literal(compare ? ">=" : "-")
.withStyle(redstoneColor(compare ? 0 : 15))));
});
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE_TORCH),
Component.literal(compare ? ">=" : "-")
.withStyle(redstoneColor(compare ? 0 : 15))));
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.POWERED_RAIL,
(lines, state, pos, observer, world, direction) -> {
int power = getPoweredRailStrength(world, pos, state);
lines.add(new Pair<>(
new ItemStack(Items.POWERED_RAIL),
Component.literal(String.valueOf(power))
.withStyle(redstoneColor(power, 9))));
});
(lines, state, pos, observer, world, direction) -> {
int power = getPoweredRailStrength(world, pos, state);
lines.add(new Pair<>(
new ItemStack(Items.POWERED_RAIL),
Component.literal(String.valueOf(power))
.withStyle(redstoneColor(power, 9))));
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.REPEATER,
(lines, state, pos, observer, world, direction) -> lines.add(new Pair<>(
new ItemStack(Items.CLOCK),
Component.literal(String.valueOf(state.getValue(RepeaterBlock.DELAY)))
.withStyle(ChatFormatting.YELLOW))));
(lines, state, pos, observer, world, direction) -> lines.add(new Pair<>(
new ItemStack(Items.CLOCK),
Component.literal(String.valueOf(state.getValue(RepeaterBlock.DELAY)))
.withStyle(ChatFormatting.YELLOW))));
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.getBlock() instanceof BeehiveBlock,
(lines, state, pos, observer, world, direction) -> {
int count = ScryingLensOverlayRegistry.getBeeValue();
lines.add(new Pair<>(new ItemStack(Items.BEE_NEST), count == -1 ? Component.empty() :
Component.translatable(
"hexcasting.tooltip.lens.bee" + (count == 1 ? ".single" : ""),
count
)));
});
(state, pos, observer, world, direction) -> state.getBlock() instanceof BeehiveBlock,
(lines, state, pos, observer, world, direction) -> {
int count = ScryingLensOverlayRegistry.getBeeValue();
lines.add(new Pair<>(new ItemStack(Items.BEE_NEST), count == -1 ? Component.empty() :
Component.translatable(
"hexcasting.tooltip.lens.bee" + (count == 1 ? ".single" : ""),
count
)));
});
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.isSignalSource() && !state.is(
Blocks.COMPARATOR),
(lines, state, pos, observer, world, direction) -> {
int signalStrength = 0;
if (state.getBlock() instanceof RedStoneWireBlock) {
signalStrength = state.getValue(RedStoneWireBlock.POWER);
} else {
for (Direction dir : Direction.values()) {
signalStrength = Math.max(signalStrength, state.getSignal(world, pos, dir));
}
(state, pos, observer, world, direction) -> state.isSignalSource() && !state.is(
Blocks.COMPARATOR),
(lines, state, pos, observer, world, direction) -> {
int signalStrength = 0;
if (state.getBlock() instanceof RedStoneWireBlock) {
signalStrength = state.getValue(RedStoneWireBlock.POWER);
} else {
for (Direction dir : Direction.values()) {
signalStrength = Math.max(signalStrength, state.getSignal(world, pos, dir));
}
}
lines.add(0, new Pair<>(
new ItemStack(Items.REDSTONE),
Component.literal(String.valueOf(signalStrength))
.withStyle(redstoneColor(signalStrength))));
});
lines.add(0, new Pair<>(
new ItemStack(Items.REDSTONE),
Component.literal(String.valueOf(signalStrength))
.withStyle(redstoneColor(signalStrength))));
});
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.hasAnalogOutputSignal(),
(lines, state, pos, observer, world, direction) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(false);
lines.add(
new Pair<>(
new ItemStack(Items.COMPARATOR),
Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
});
(state, pos, observer, world, direction) -> state.hasAnalogOutputSignal(),
(lines, state, pos, observer, world, direction) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(false);
lines.add(
new Pair<>(
new ItemStack(Items.COMPARATOR),
Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
});
}
private static UnaryOperator<Style> color(int color) {
@ -305,15 +305,15 @@ public class RegisterClientStuff {
private static void registerDataHolderOverrides(IotaHolderItem item, Predicate<ItemStack> hasIota,
Predicate<ItemStack> isSealed) {
IClientXplatAbstractions.INSTANCE.registerItemProperty((Item) item, ItemFocus.OVERLAY_PRED,
(stack, level, holder, holderID) -> {
if (!hasIota.test(stack) && !NBTHelper.hasString(stack, IotaHolderItem.TAG_OVERRIDE_VISUALLY)) {
return 0;
}
if (!isSealed.test(stack)) {
return 1;
}
return 2;
});
(stack, level, holder, holderID) -> {
if (!hasIota.test(stack) && !NBTHelper.hasString(stack, IotaHolderItem.TAG_OVERRIDE_VISUALLY)) {
return 0;
}
if (!isSealed.test(stack)) {
return 1;
}
return 2;
});
}
private static int getPoweredRailStrength(Level level, BlockPos pos, BlockState state) {
@ -325,7 +325,8 @@ public class RegisterClientStuff {
}
// Copypasta from PoweredRailBlock.class
private static int findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean travelPositive, int depth) {
private static int findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean travelPositive,
int depth) {
if (depth >= 8) {
return 0;
} else {
@ -417,7 +418,8 @@ public class RegisterClientStuff {
} else if (shape == RailShape.NORTH_SOUTH && (otherShape == RailShape.EAST_WEST || otherShape == RailShape.ASCENDING_EAST || otherShape == RailShape.ASCENDING_WEST)) {
return 0;
} else if (otherState.getValue(PoweredRailBlock.POWERED)) {
return level.hasNeighborSignal(pos) ? 8 - depth : findPoweredRailSignal(level, pos, otherState, travelPositive, depth + 1);
return level.hasNeighborSignal(pos) ? 8 - depth : findPoweredRailSignal(level, pos, otherState,
travelPositive, depth + 1);
} else {
return 0;
}
@ -426,37 +428,37 @@ public class RegisterClientStuff {
private static void registerScrollOverrides(ItemScroll scroll) {
IClientXplatAbstractions.INSTANCE.registerItemProperty(scroll, ItemScroll.ANCIENT_PREDICATE,
(stack, level, holder, holderID) -> NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) ? 1f : 0f);
(stack, level, holder, holderID) -> NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) ? 1f : 0f);
}
private static void registerPackagedSpellOverrides(ItemPackagedHex item) {
IClientXplatAbstractions.INSTANCE.registerItemProperty(item, ItemPackagedHex.HAS_PATTERNS_PRED,
(stack, level, holder, holderID) ->
item.hasHex(stack) ? 1f : 0f
(stack, level, holder, holderID) ->
item.hasHex(stack) ? 1f : 0f
);
}
private static void registerWandOverrides(ItemStaff item) {
IClientXplatAbstractions.INSTANCE.registerItemProperty(item, ItemStaff.FUNNY_LEVEL_PREDICATE,
(stack, level, holder, holderID) -> {
if (!stack.hasCustomHoverName()) {
return 0;
}
var name = stack.getHoverName().getString().toLowerCase(Locale.ROOT);
if (name.contains("old")) {
return 1f;
} else if (name.contains("wand of the forest")) {
return 2f;
} else {
return 0f;
}
});
(stack, level, holder, holderID) -> {
if (!stack.hasCustomHoverName()) {
return 0;
}
var name = stack.getHoverName().getString().toLowerCase(Locale.ROOT);
if (name.contains("old")) {
return 1f;
} else if (name.contains("wand of the forest")) {
return 2f;
} else {
return 0f;
}
});
}
public static void registerBlockEntityRenderers(@NotNull BlockEntityRendererRegisterererer registerer) {
registerer.registerBlockEntityRenderer(HexBlockEntities.SLATE_TILE, BlockEntitySlateRenderer::new);
registerer.registerBlockEntityRenderer(HexBlockEntities.AKASHIC_BOOKSHELF_TILE,
BlockEntityAkashicBookshelfRenderer::new);
BlockEntityAkashicBookshelfRenderer::new);
}
@FunctionalInterface

View file

@ -11,12 +11,11 @@ import at.petrak.hexcasting.api.spell.math.HexCoord
import at.petrak.hexcasting.api.spell.math.HexDir
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.api.utils.gold
import at.petrak.hexcasting.client.*
import at.petrak.hexcasting.client.ktxt.accumulatedScroll
import at.petrak.hexcasting.client.sound.GridSoundInstance
import at.petrak.hexcasting.common.lib.HexIotaTypes
import at.petrak.hexcasting.common.lib.HexSounds
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import at.petrak.hexcasting.common.network.MsgNewSpellPatternSyn
import at.petrak.hexcasting.xplat.IClientXplatAbstractions
import com.mojang.blaze3d.systems.RenderSystem
@ -44,7 +43,7 @@ class GuiSpellcasting constructor(
) : Screen("gui.hexcasting.spellcasting".asTranslatedComponent) {
private var stackDescs: List<FormattedCharSequence> = listOf()
private var parenDescs: List<FormattedCharSequence> = listOf()
private var ravenmind: List<FormattedCharSequence>? = null
private var ravenmind: FormattedCharSequence? = null
private var drawState: PatternDrawState = PatternDrawState.BetweenPatterns
private val usedSpots: MutableSet<HexCoord> = HashSet()
@ -76,14 +75,15 @@ class GuiSpellcasting constructor(
val mc = Minecraft.getInstance()
val width = (this.width * LHS_IOTAS_ALLOCATION).toInt()
this.stackDescs =
this.cachedStack.flatMap { HexIotaTypes.getDisplayWithMaxWidth(it, width, mc.font).asReversed() }
this.cachedStack.map { HexIotaTypes.getDisplayWithMaxWidth(it, width, mc.font) }
.asReversed()
this.parenDescs = if (this.cachedParens.isNotEmpty())
this.cachedParens.flatMap { HexIotaTypes.getDisplayWithMaxWidth(it, width, mc.font) }
else if (this.parenCount > 0)
listOf("...".gold.visualOrderText)
else
emptyList()
// this.parenDescs = if (this.cachedParens.isNotEmpty())
// this.cachedParens.flatMap { HexIotaTypes.getDisplayWithMaxWidth(it, width, mc.font) }
// else if (this.parenCount > 0)
// listOf("...".gold.visualOrderText)
// else
// emptyList()
this.parenDescs = emptyList()
this.ravenmind =
this.cachedRavenmind?.let {
HexIotaTypes.getDisplayWithMaxWidth(
@ -383,23 +383,23 @@ class GuiSpellcasting constructor(
ps.pushPose()
ps.translate(10.0, 10.0, 0.0)
if (this.parenCount > 0) {
val boxHeight = (this.parenDescs.size + 1f) * 10f
RenderSystem.setShader(GameRenderer::getPositionColorShader)
RenderSystem.defaultBlendFunc()
drawBox(ps, 0f, 0f, (this.width * LHS_IOTAS_ALLOCATION + 5).toFloat(), boxHeight, 7.5f)
ps.translate(0.0, 0.0, 1.0)
val time = ClientTickCounter.getTotal() * 0.16f
val opacity = (Mth.map(cos(time), -1f, 1f, 200f, 255f)).toInt()
val color = 0x00_ffffff or (opacity shl 24)
RenderSystem.setShader { prevShader }
for (desc in this.parenDescs) {
font.draw(ps, desc, 10f, 7f, color)
ps.translate(0.0, 10.0, 0.0)
}
ps.translate(0.0, 15.0, 0.0)
}
// if (this.parenCount > 0) {
// val boxHeight = (this.parenDescs.size + 1f) * 10f
// RenderSystem.setShader(GameRenderer::getPositionColorShader)
// RenderSystem.defaultBlendFunc()
// drawBox(ps, 0f, 0f, (this.width * LHS_IOTAS_ALLOCATION + 5).toFloat(), boxHeight, 7.5f)
// ps.translate(0.0, 0.0, 1.0)
//
// val time = ClientTickCounter.getTotal() * 0.16f
// val opacity = (Mth.map(cos(time), -1f, 1f, 200f, 255f)).toInt()
// val color = 0x00_ffffff or (opacity shl 24)
// RenderSystem.setShader { prevShader }
// for (desc in this.parenDescs) {
// font.draw(ps, desc, 10f, 7f, color)
// ps.translate(0.0, 10.0, 0.0)
// }
// ps.translate(0.0, 15.0, 0.0)
// }
if (this.stackDescs.isNotEmpty()) {
val boxHeight = (this.stackDescs.size + 1f) * 10f
@ -415,30 +415,27 @@ class GuiSpellcasting constructor(
}
ps.popPose()
if (!this.ravenmind.isNullOrEmpty()) {
if (this.ravenmind != null) {
val kotlinBad = this.ravenmind!!
ps.pushPose()
ps.translate(this.width * 0.8, 10.0, 0.0)
val boxHeight = (kotlinBad.size + 0.5f) * 10f
val boxHeight = 15f
val addlScale = 1.5f
ps.translate(this.width * (1.0 - RHS_IOTAS_ALLOCATION * addlScale) - 10, 10.0, 0.0)
RenderSystem.setShader(GameRenderer::getPositionColorShader)
RenderSystem.enableBlend()
drawBox(
ps, 0f, 0f,
((this.width * RHS_IOTAS_ALLOCATION + 5) * addlScale).toFloat(), boxHeight * addlScale,
(this.width * RHS_IOTAS_ALLOCATION * addlScale).toFloat(), boxHeight * addlScale,
)
ps.translate(5.0, 5.0, 1.0)
ps.scale(addlScale, addlScale, 1f)
val time = ClientTickCounter.getTotal() * 0.42f
val time = ClientTickCounter.getTotal() * 0.2f
val opacity = (Mth.map(sin(time), -1f, 1f, 150f, 255f)).toInt()
val color = 0x00_ffffff or (opacity shl 24)
RenderSystem.setShader { prevShader }
for (desc in kotlinBad) {
font.draw(ps, desc, 0f, 0f, color)
ps.translate(0.0, 10.0, 0.0)
}
font.draw(ps, kotlinBad, 0f, 0f, color)
ps.popPose()
}
@ -479,7 +476,7 @@ class GuiSpellcasting constructor(
companion object {
const val LHS_IOTAS_ALLOCATION = 0.7
const val RHS_IOTAS_ALLOCATION = 0.1
const val RHS_IOTAS_ALLOCATION = 0.15
fun drawBox(ps: PoseStack, x: Float, y: Float, w: Float, h: Float, leftMargin: Float = 2.5f) {
RenderSystem.setShader(GameRenderer::getPositionColorShader)

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;

View file

@ -4,7 +4,7 @@ import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;

View file

@ -27,6 +27,7 @@ import at.petrak.hexcasting.common.casting.operators.math.*;
import at.petrak.hexcasting.common.casting.operators.math.bit.*;
import at.petrak.hexcasting.common.casting.operators.math.logic.*;
import at.petrak.hexcasting.common.casting.operators.math.trig.*;
import at.petrak.hexcasting.common.casting.operators.rw.*;
import at.petrak.hexcasting.common.casting.operators.selectors.OpGetCaster;
import at.petrak.hexcasting.common.casting.operators.selectors.OpGetEntitiesBy;
import at.petrak.hexcasting.common.casting.operators.selectors.OpGetEntityAt;
@ -58,291 +59,291 @@ public class RegisterPatterns {
// == Getters ==
PatternRegistry.mapPattern(HexPattern.fromAngles("qaq", HexDir.NORTH_EAST), modLoc("get_caster"),
OpGetCaster.INSTANCE);
OpGetCaster.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aa", HexDir.EAST), modLoc("entity_pos/eye"),
new OpEntityPos(false));
new OpEntityPos(false));
PatternRegistry.mapPattern(HexPattern.fromAngles("dd", HexDir.NORTH_EAST), modLoc("entity_pos/foot"),
new OpEntityPos(true));
new OpEntityPos(true));
PatternRegistry.mapPattern(HexPattern.fromAngles("wa", HexDir.EAST), modLoc("get_entity_look"),
OpEntityLook.INSTANCE);
OpEntityLook.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("awq", HexDir.NORTH_EAST), modLoc("get_entity_height"),
OpEntityHeight.INSTANCE);
OpEntityHeight.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wq", HexDir.EAST), modLoc("get_entity_velocity"),
OpEntityVelocity.INSTANCE);
OpEntityVelocity.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wqaawdd", HexDir.EAST), modLoc("raycast"),
OpBlockRaycast.INSTANCE);
OpBlockRaycast.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("weddwaa", HexDir.EAST), modLoc("raycast/axis"),
OpBlockAxisRaycast.INSTANCE);
OpBlockAxisRaycast.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("weaqa", HexDir.EAST), modLoc("raycast/entity"),
OpEntityRaycast.INSTANCE);
OpEntityRaycast.INSTANCE);
// == spell circle getters ==
PatternRegistry.mapPattern(HexPattern.fromAngles("eaqwqae", HexDir.SOUTH_WEST),
modLoc("circle/impetus_pos"), OpImpetusPos.INSTANCE);
modLoc("circle/impetus_pos"), OpImpetusPos.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eaqwqaewede", HexDir.SOUTH_WEST),
modLoc("circle/impetus_dir"), OpImpetusDir.INSTANCE);
modLoc("circle/impetus_dir"), OpImpetusDir.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eaqwqaewdd", HexDir.SOUTH_WEST),
modLoc("circle/bounds/min"), new OpCircleBounds(false));
modLoc("circle/bounds/min"), new OpCircleBounds(false));
PatternRegistry.mapPattern(HexPattern.fromAngles("aqwqawaaqa", HexDir.WEST),
modLoc("circle/bounds/max"), new OpCircleBounds(true));
modLoc("circle/bounds/max"), new OpCircleBounds(true));
// == Modify Stack ==
PatternRegistry.mapPattern(HexPattern.fromAngles("aawdd", HexDir.EAST), modLoc("swap"),
new OpTwiddling(2, new int[]{1, 0}));
new OpTwiddling(2, new int[]{1, 0}));
PatternRegistry.mapPattern(HexPattern.fromAngles("aaeaa", HexDir.EAST), modLoc("rotate"),
new OpTwiddling(3, new int[]{1, 2, 0}));
new OpTwiddling(3, new int[]{1, 2, 0}));
PatternRegistry.mapPattern(HexPattern.fromAngles("ddqdd", HexDir.NORTH_EAST), modLoc("rotate_reverse"),
new OpTwiddling(3, new int[]{2, 0, 1}));
new OpTwiddling(3, new int[]{2, 0, 1}));
PatternRegistry.mapPattern(HexPattern.fromAngles("aadaa", HexDir.EAST), modLoc("duplicate"),
new OpTwiddling(1, new int[]{0, 0}));
new OpTwiddling(1, new int[]{0, 0}));
PatternRegistry.mapPattern(HexPattern.fromAngles("aaedd", HexDir.EAST), modLoc("over"),
new OpTwiddling(2, new int[]{0, 1, 0}));
new OpTwiddling(2, new int[]{0, 1, 0}));
PatternRegistry.mapPattern(HexPattern.fromAngles("ddqaa", HexDir.EAST), modLoc("tuck"),
new OpTwiddling(2, new int[]{1, 0, 1}));
new OpTwiddling(2, new int[]{1, 0, 1}));
PatternRegistry.mapPattern(HexPattern.fromAngles("aadadaaw", HexDir.EAST), modLoc("2dup"),
new OpTwiddling(2, new int[]{0, 1, 0, 1}));
new OpTwiddling(2, new int[]{0, 1, 0, 1}));
PatternRegistry.mapPattern(HexPattern.fromAngles("qwaeawqaeaqa", HexDir.NORTH_WEST), modLoc("stack_len"),
OpStackSize.INSTANCE);
OpStackSize.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aadaadaa", HexDir.EAST), modLoc("duplicate_n"),
OpDuplicateN.INSTANCE);
OpDuplicateN.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("ddad", HexDir.WEST), modLoc("fisherman"),
OpFisherman.INSTANCE);
OpFisherman.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aada", HexDir.EAST), modLoc("fisherman/copy"),
OpFishermanButItCopies.INSTANCE);
OpFishermanButItCopies.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qaawdde", HexDir.SOUTH_EAST), modLoc("swizzle"),
OpAlwinfyHasAscendedToABeingOfPureMath.INSTANCE);
OpAlwinfyHasAscendedToABeingOfPureMath.INSTANCE);
// == Math ==
PatternRegistry.mapPattern(HexPattern.fromAngles("waaw", HexDir.NORTH_EAST), modLoc("add"),
OpAdd.INSTANCE);
OpAdd.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wddw", HexDir.NORTH_WEST), modLoc("sub"),
OpSub.INSTANCE);
OpSub.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("waqaw", HexDir.SOUTH_EAST), modLoc("mul_dot"),
OpMulDot.INSTANCE);
OpMulDot.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wdedw", HexDir.NORTH_EAST), modLoc("div_cross"),
OpDivCross.INSTANCE);
OpDivCross.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wqaqw", HexDir.NORTH_EAST), modLoc("abs_len"),
OpAbsLen.INSTANCE);
OpAbsLen.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wedew", HexDir.NORTH_WEST), modLoc("pow_proj"),
OpPowProj.INSTANCE);
OpPowProj.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("ewq", HexDir.EAST), modLoc("floor"),
OpFloor.INSTANCE);
OpFloor.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qwe", HexDir.EAST), modLoc("ceil"),
OpCeil.INSTANCE);
OpCeil.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eqqqqq", HexDir.EAST), modLoc("construct_vec"),
OpConstructVec.INSTANCE);
OpConstructVec.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qeeeee", HexDir.EAST), modLoc("deconstruct_vec"),
OpDeconstructVec.INSTANCE);
OpDeconstructVec.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqaww", HexDir.NORTH_WEST), modLoc("coerce_axial"),
OpCoerceToAxial.INSTANCE);
OpCoerceToAxial.INSTANCE);
// == Logic ==
PatternRegistry.mapPattern(HexPattern.fromAngles("wdw", HexDir.NORTH_EAST), modLoc("and"),
OpBoolAnd.INSTANCE);
OpBoolAnd.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("waw", HexDir.SOUTH_EAST), modLoc("or"),
OpBoolOr.INSTANCE);
OpBoolOr.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("dwa", HexDir.NORTH_WEST), modLoc("xor"),
OpBoolXor.INSTANCE);
OpBoolXor.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("e", HexDir.SOUTH_EAST), modLoc("greater"),
new OpCompare(false, (a, b) -> a > b));
new OpCompare(false, (a, b) -> a > b));
PatternRegistry.mapPattern(HexPattern.fromAngles("q", HexDir.SOUTH_WEST), modLoc("less"),
new OpCompare(false, (a, b) -> a < b));
new OpCompare(false, (a, b) -> a < b));
PatternRegistry.mapPattern(HexPattern.fromAngles("ee", HexDir.SOUTH_EAST), modLoc("greater_eq"),
new OpCompare(true, (a, b) -> a >= b));
new OpCompare(true, (a, b) -> a >= b));
PatternRegistry.mapPattern(HexPattern.fromAngles("qq", HexDir.SOUTH_WEST), modLoc("less_eq"),
new OpCompare(true, (a, b) -> a <= b));
new OpCompare(true, (a, b) -> a <= b));
PatternRegistry.mapPattern(HexPattern.fromAngles("ad", HexDir.EAST), modLoc("equals"),
new OpEquality(false));
new OpEquality(false));
PatternRegistry.mapPattern(HexPattern.fromAngles("da", HexDir.EAST), modLoc("not_equals"),
new OpEquality(true));
new OpEquality(true));
PatternRegistry.mapPattern(HexPattern.fromAngles("dw", HexDir.NORTH_WEST), modLoc("not"),
OpBoolNot.INSTANCE);
OpBoolNot.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aw", HexDir.NORTH_EAST), modLoc("bool_coerce"),
OpCoerceToBool.INSTANCE);
OpCoerceToBool.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("awdd", HexDir.SOUTH_EAST), modLoc("if"),
OpBoolIf.INSTANCE);
OpBoolIf.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eqqq", HexDir.NORTH_WEST), modLoc("random"),
OpRandom.INSTANCE);
OpRandom.INSTANCE);
// == Advanced Math ==
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqaa", HexDir.SOUTH_EAST), modLoc("sin"),
OpSin.INSTANCE);
OpSin.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqad", HexDir.SOUTH_EAST), modLoc("cos"),
OpCos.INSTANCE);
OpCos.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wqqqqqadq", HexDir.SOUTH_WEST), modLoc("tan"),
OpTan.INSTANCE);
OpTan.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("ddeeeee", HexDir.SOUTH_EAST), modLoc("arcsin"),
OpArcSin.INSTANCE);
OpArcSin.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("adeeeee", HexDir.NORTH_EAST), modLoc("arccos"),
OpArcCos.INSTANCE);
OpArcCos.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eadeeeeew", HexDir.NORTH_EAST), modLoc("arctan"),
OpArcTan.INSTANCE);
OpArcTan.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eqaqe", HexDir.NORTH_WEST), modLoc("logarithm"),
OpLog.INSTANCE);
OpLog.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("addwaad", HexDir.NORTH_EAST), modLoc("modulo"),
OpModulo.INSTANCE);
OpModulo.INSTANCE);
// == Sets ==
PatternRegistry.mapPattern(HexPattern.fromAngles("wdweaqa", HexDir.NORTH_EAST), modLoc("and_bit"),
OpAnd.INSTANCE);
OpAnd.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("waweaqa", HexDir.SOUTH_EAST), modLoc("or_bit"),
OpOr.INSTANCE);
OpOr.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("dwaeaqa", HexDir.NORTH_WEST), modLoc("xor_bit"),
OpXor.INSTANCE);
OpXor.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("dweaqa", HexDir.NORTH_WEST), modLoc("not_bit"),
OpNot.INSTANCE);
OpNot.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aweaqa", HexDir.NORTH_EAST), modLoc("to_set"),
OpToSet.INSTANCE);
OpToSet.INSTANCE);
// == Spells ==
PatternRegistry.mapPattern(HexPattern.fromAngles("de", HexDir.NORTH_EAST), modLoc("print"),
OpPrint.INSTANCE);
OpPrint.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aawaawaa", HexDir.EAST), modLoc("explode"),
new OpExplode(false));
new OpExplode(false));
PatternRegistry.mapPattern(HexPattern.fromAngles("ddwddwdd", HexDir.EAST), modLoc("explode/fire"),
new OpExplode(true));
new OpExplode(true));
PatternRegistry.mapPattern(HexPattern.fromAngles("awqqqwaqw", HexDir.SOUTH_WEST), modLoc("add_motion"),
OpAddMotion.INSTANCE);
OpAddMotion.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("awqqqwaq", HexDir.SOUTH_WEST), modLoc("blink"),
OpBlink.INSTANCE);
OpBlink.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qaqqqqq", HexDir.EAST), modLoc("break_block"),
OpBreakBlock.INSTANCE);
OpBreakBlock.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeede", HexDir.SOUTH_WEST), modLoc("place_block"),
OpPlaceBlock.INSTANCE);
OpPlaceBlock.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("awddwqawqwawq", HexDir.EAST),
modLoc("colorize"),
OpColorize.INSTANCE);
modLoc("colorize"),
OpColorize.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aqawqadaq", HexDir.SOUTH_EAST), modLoc("create_water"),
new OpCreateFluid(false, MediaConstants.DUST_UNIT,
Items.WATER_BUCKET,
Blocks.WATER_CAULDRON.defaultBlockState()
.setValue(LayeredCauldronBlock.LEVEL, LayeredCauldronBlock.MAX_FILL_LEVEL),
Fluids.WATER));
new OpCreateFluid(false, MediaConstants.DUST_UNIT,
Items.WATER_BUCKET,
Blocks.WATER_CAULDRON.defaultBlockState()
.setValue(LayeredCauldronBlock.LEVEL, LayeredCauldronBlock.MAX_FILL_LEVEL),
Fluids.WATER));
PatternRegistry.mapPattern(HexPattern.fromAngles("dedwedade", HexDir.SOUTH_WEST),
modLoc("destroy_water"),
OpDestroyFluid.INSTANCE);
modLoc("destroy_water"),
OpDestroyFluid.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aaqawawa", HexDir.SOUTH_EAST), modLoc("ignite"),
OpIgnite.INSTANCE);
OpIgnite.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("ddedwdwd", HexDir.SOUTH_WEST), modLoc("extinguish"),
OpExtinguish.INSTANCE);
OpExtinguish.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqa", HexDir.NORTH_EAST), modLoc("conjure_block"),
new OpConjureBlock(false));
new OpConjureBlock(false));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqd", HexDir.NORTH_EAST), modLoc("conjure_light"),
new OpConjureBlock(true));
new OpConjureBlock(true));
PatternRegistry.mapPattern(HexPattern.fromAngles("wqaqwawqaqw", HexDir.NORTH_EAST), modLoc("bonemeal"),
OpTheOnlyReasonAnyoneDownloadedPsi.INSTANCE);
OpTheOnlyReasonAnyoneDownloadedPsi.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqwaeaeaeaeaea", HexDir.NORTH_WEST),
modLoc("recharge"),
OpRecharge.INSTANCE);
modLoc("recharge"),
OpRecharge.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qdqawwaww", HexDir.EAST), modLoc("erase"),
new OpErase());
new OpErase());
PatternRegistry.mapPattern(HexPattern.fromAngles("wqaqwd", HexDir.NORTH_EAST), modLoc("edify"),
OpEdifySapling.INSTANCE);
OpEdifySapling.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("adaa", HexDir.WEST), modLoc("beep"),
OpBeep.INSTANCE);
OpBeep.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("waqqqqq", HexDir.EAST), modLoc("craft/cypher"),
new OpMakePackagedSpell<>(HexItems.CYPHER, MediaConstants.CRYSTAL_UNIT));
new OpMakePackagedSpell<>(HexItems.CYPHER, MediaConstants.CRYSTAL_UNIT));
PatternRegistry.mapPattern(HexPattern.fromAngles("wwaqqqqqeaqeaeqqqeaeq", HexDir.EAST),
modLoc("craft/trinket"),
new OpMakePackagedSpell<>(HexItems.TRINKET, 5 * MediaConstants.CRYSTAL_UNIT));
modLoc("craft/trinket"),
new OpMakePackagedSpell<>(HexItems.TRINKET, 5 * MediaConstants.CRYSTAL_UNIT));
PatternRegistry.mapPattern(
HexPattern.fromAngles("wwaqqqqqeawqwqwqwqwqwwqqeadaeqqeqqeadaeqq", HexDir.EAST),
modLoc("craft/artifact"),
new OpMakePackagedSpell<>(HexItems.ARTIFACT, 10 * MediaConstants.CRYSTAL_UNIT));
HexPattern.fromAngles("wwaqqqqqeawqwqwqwqwqwwqqeadaeqqeqqeadaeqq", HexDir.EAST),
modLoc("craft/artifact"),
new OpMakePackagedSpell<>(HexItems.ARTIFACT, 10 * MediaConstants.CRYSTAL_UNIT));
PatternRegistry.mapPattern(
HexPattern.fromAngles("aqqqaqwwaqqqqqeqaqqqawwqwqwqwqwqw", HexDir.SOUTH_WEST),
modLoc("craft/battery"),
OpMakeBattery.INSTANCE,
true);
HexPattern.fromAngles("aqqqaqwwaqqqqqeqaqqqawwqwqwqwqwqw", HexDir.SOUTH_WEST),
modLoc("craft/battery"),
OpMakeBattery.INSTANCE,
true);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqaqwawaw", HexDir.NORTH_WEST),
modLoc("potion/weakness"),
new OpPotionEffect(MobEffects.WEAKNESS, MediaConstants.DUST_UNIT / 10, true, false, false));
modLoc("potion/weakness"),
new OpPotionEffect(MobEffects.WEAKNESS, MediaConstants.DUST_UNIT / 10, true, false, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqawwawawd", HexDir.WEST),
modLoc("potion/levitation"),
new OpPotionEffect(MobEffects.LEVITATION, MediaConstants.DUST_UNIT / 5, false, false, false));
modLoc("potion/levitation"),
new OpPotionEffect(MobEffects.LEVITATION, MediaConstants.DUST_UNIT / 5, false, false, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqaewawawe", HexDir.SOUTH_WEST),
modLoc("potion/wither"),
new OpPotionEffect(MobEffects.WITHER, MediaConstants.DUST_UNIT, true, false, false));
modLoc("potion/wither"),
new OpPotionEffect(MobEffects.WITHER, MediaConstants.DUST_UNIT, true, false, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqadwawaww", HexDir.SOUTH_EAST),
modLoc("potion/poison"),
new OpPotionEffect(MobEffects.POISON, MediaConstants.DUST_UNIT / 3, true, false, false));
modLoc("potion/poison"),
new OpPotionEffect(MobEffects.POISON, MediaConstants.DUST_UNIT / 3, true, false, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqadwawaw", HexDir.SOUTH_EAST),
modLoc("potion/slowness"),
new OpPotionEffect(MobEffects.MOVEMENT_SLOWDOWN, MediaConstants.DUST_UNIT / 3, true, false, false));
modLoc("potion/slowness"),
new OpPotionEffect(MobEffects.MOVEMENT_SLOWDOWN, MediaConstants.DUST_UNIT / 3, true, false, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqaawawaedd", HexDir.NORTH_WEST),
modLoc("potion/regeneration"),
new OpPotionEffect(MobEffects.REGENERATION, MediaConstants.DUST_UNIT, true, true, true), true);
modLoc("potion/regeneration"),
new OpPotionEffect(MobEffects.REGENERATION, MediaConstants.DUST_UNIT, true, true, true), true);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqaawawaeqdd", HexDir.WEST),
modLoc("potion/night_vision"),
new OpPotionEffect(MobEffects.NIGHT_VISION, MediaConstants.DUST_UNIT / 5, false, true, true), true);
modLoc("potion/night_vision"),
new OpPotionEffect(MobEffects.NIGHT_VISION, MediaConstants.DUST_UNIT / 5, false, true, true), true);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqaawawaeqqdd", HexDir.SOUTH_WEST),
modLoc("potion/absorption"),
new OpPotionEffect(MobEffects.ABSORPTION, MediaConstants.DUST_UNIT, true, true, true), true);
modLoc("potion/absorption"),
new OpPotionEffect(MobEffects.ABSORPTION, MediaConstants.DUST_UNIT, true, true, true), true);
PatternRegistry.mapPattern(HexPattern.fromAngles("qaawawaeqqqdd", HexDir.SOUTH_EAST),
modLoc("potion/haste"),
new OpPotionEffect(MobEffects.DIG_SPEED, MediaConstants.DUST_UNIT / 3, true, true, true), true);
modLoc("potion/haste"),
new OpPotionEffect(MobEffects.DIG_SPEED, MediaConstants.DUST_UNIT / 3, true, true, true), true);
PatternRegistry.mapPattern(HexPattern.fromAngles("aawawaeqqqqdd", HexDir.EAST),
modLoc("potion/strength"),
new OpPotionEffect(MobEffects.DAMAGE_BOOST, MediaConstants.DUST_UNIT / 3, true, true, true), true);
modLoc("potion/strength"),
new OpPotionEffect(MobEffects.DAMAGE_BOOST, MediaConstants.DUST_UNIT / 3, true, true, true), true);
PatternRegistry.mapPattern(HexPattern.fromAngles("waeawae", HexDir.EAST),
modLoc("sentinel/create"),
new OpCreateSentinel(false));
modLoc("sentinel/create"),
new OpCreateSentinel(false));
PatternRegistry.mapPattern(HexPattern.fromAngles("qdwdqdw", HexDir.NORTH_EAST),
modLoc("sentinel/destroy"),
OpDestroySentinel.INSTANCE);
modLoc("sentinel/destroy"),
OpDestroySentinel.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("waeawaede", HexDir.EAST),
modLoc("sentinel/get_pos"),
OpGetSentinelPos.INSTANCE);
modLoc("sentinel/get_pos"),
OpGetSentinelPos.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("waeawaedwa", HexDir.EAST),
modLoc("sentinel/wayfind"),
OpGetSentinelWayfind.INSTANCE);
modLoc("sentinel/wayfind"),
OpGetSentinelWayfind.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("waadwawdaaweewq", HexDir.EAST),
modLoc("lightning"), OpLightning.INSTANCE, true);
modLoc("lightning"), OpLightning.INSTANCE, true);
PatternRegistry.mapPattern(HexPattern.fromAngles("eawwaeawawaa", HexDir.NORTH_WEST),
modLoc("flight"), OpFlight.INSTANCE, true);
modLoc("flight"), OpFlight.INSTANCE, true);
PatternRegistry.mapPattern(HexPattern.fromAngles("eaqawqadaqd", HexDir.EAST),
modLoc("create_lava"), new OpCreateFluid(true, MediaConstants.CRYSTAL_UNIT,
Items.LAVA_BUCKET,
Blocks.LAVA_CAULDRON.defaultBlockState(),
Fluids.LAVA), true);
modLoc("create_lava"), new OpCreateFluid(true, MediaConstants.CRYSTAL_UNIT,
Items.LAVA_BUCKET,
Blocks.LAVA_CAULDRON.defaultBlockState(),
Fluids.LAVA), true);
PatternRegistry.mapPattern(
HexPattern.fromAngles("wwwqqqwwwqqeqqwwwqqwqqdqqqqqdqq", HexDir.EAST),
modLoc("teleport"), OpTeleport.INSTANCE, true);
HexPattern.fromAngles("wwwqqqwwwqqeqqwwwqqwqqdqqqqqdqq", HexDir.EAST),
modLoc("teleport"), OpTeleport.INSTANCE, true);
PatternRegistry.mapPattern(HexPattern.fromAngles("waeawaeqqqwqwqqwq", HexDir.EAST),
modLoc("sentinel/create/great"),
new OpCreateSentinel(true), true);
modLoc("sentinel/create/great"),
new OpCreateSentinel(true), true);
PatternRegistry.mapPattern(HexPattern.fromAngles("eeewwweeewwaqqddqdqd", HexDir.EAST),
modLoc("dispel_rain"),
new OpWeather(false), true);
modLoc("dispel_rain"),
new OpWeather(false), true);
PatternRegistry.mapPattern(HexPattern.fromAngles("wwweeewwweewdawdwad", HexDir.WEST),
modLoc("summon_rain"),
new OpWeather(true), true);
modLoc("summon_rain"),
new OpWeather(true), true);
PatternRegistry.mapPattern(HexPattern.fromAngles("qeqwqwqwqwqeqaeqeaqeqaeqaqded", HexDir.NORTH_EAST),
modLoc("brainsweep"),
OpBrainsweep.INSTANCE, true);
modLoc("brainsweep"),
OpBrainsweep.INSTANCE, true);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqwqqqqqaq", HexDir.WEST), modLoc("akashic/read"),
OpAkashicRead.INSTANCE);
OpAkashicRead.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeweeeeede", HexDir.EAST), modLoc("akashic/write"),
OpAkashicWrite.INSTANCE);
OpAkashicWrite.INSTANCE);
// == Meta stuff ==
@ -352,158 +353,158 @@ public class RegisterPatterns {
// http://www.toroidalsnark.net/mkss3-pix/CalderheadJMM2014.pdf
// eval being a space filling curve feels apt doesn't it
PatternRegistry.mapPattern(HexPattern.fromAngles("deaqq", HexDir.SOUTH_EAST), modLoc("eval"),
OpEval.INSTANCE);
OpEval.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aqdee", HexDir.SOUTH_WEST), modLoc("halt"),
OpHalt.INSTANCE);
OpHalt.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aqqqqq", HexDir.EAST), modLoc("read"),
OpRead.INSTANCE);
OpRead.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wawqwqwqwqwqw", HexDir.EAST),
modLoc("read/entity"), OpTheCoolerRead.INSTANCE);
modLoc("read/entity"), OpTheCoolerRead.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("deeeee", HexDir.EAST), modLoc("write"),
OpWrite.INSTANCE);
OpWrite.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wdwewewewewew", HexDir.EAST),
modLoc("write/entity"), OpTheCoolerWrite.INSTANCE);
modLoc("write/entity"), OpTheCoolerWrite.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aqqqqqe", HexDir.EAST), modLoc("readable"),
OpReadable.INSTANCE);
OpReadable.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wawqwqwqwqwqwew", HexDir.EAST),
modLoc("readable/entity"), OpTheCoolerReadable.INSTANCE);
modLoc("readable/entity"), OpTheCoolerReadable.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("deeeeeq", HexDir.EAST), modLoc("writable"),
OpWritable.INSTANCE);
OpWritable.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wdwewewewewewqw", HexDir.EAST),
modLoc("writable/entity"), OpTheCoolerWritable.INSTANCE);
modLoc("writable/entity"), OpTheCoolerWritable.INSTANCE);
// lorge boyes
PatternRegistry.mapPattern(HexPattern.fromAngles("qeewdweddw", HexDir.NORTH_EAST),
modLoc("read/local"), OpPeekLocal.INSTANCE);
modLoc("read/local"), OpPeekLocal.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("eqqwawqaaw", HexDir.NORTH_WEST),
modLoc("write/local"), OpPushLocal.INSTANCE);
modLoc("write/local"), OpPushLocal.INSTANCE);
// == Consts ==
PatternRegistry.mapPattern(HexPattern.fromAngles("d", HexDir.EAST), modLoc("const/null"),
Action.makeConstantOp(new NullIota()));
Action.makeConstantOp(new NullIota()));
PatternRegistry.mapPattern(HexPattern.fromAngles("aqae", HexDir.SOUTH_EAST), modLoc("const/true"),
Action.makeConstantOp(new BooleanIota(true)));
Action.makeConstantOp(new BooleanIota(true)));
PatternRegistry.mapPattern(HexPattern.fromAngles("dedq", HexDir.NORTH_EAST), modLoc("const/false"),
Action.makeConstantOp(new BooleanIota(false)));
Action.makeConstantOp(new BooleanIota(false)));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqea", HexDir.NORTH_WEST), modLoc("const/vec/px"),
Action.makeConstantOp(new Vec3Iota(new Vec3(1.0, 0.0, 0.0))));
Action.makeConstantOp(new Vec3Iota(new Vec3(1.0, 0.0, 0.0))));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqew", HexDir.NORTH_WEST), modLoc("const/vec/py"),
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 1.0, 0.0))));
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 1.0, 0.0))));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqed", HexDir.NORTH_WEST), modLoc("const/vec/pz"),
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, 1.0))));
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, 1.0))));
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeeqa", HexDir.SOUTH_WEST), modLoc("const/vec/nx"),
Action.makeConstantOp(new Vec3Iota(new Vec3(-1.0, 0.0, 0.0))));
Action.makeConstantOp(new Vec3Iota(new Vec3(-1.0, 0.0, 0.0))));
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeeqw", HexDir.SOUTH_WEST), modLoc("const/vec/ny"),
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, -1.0, 0.0))));
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, -1.0, 0.0))));
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeeqd", HexDir.SOUTH_WEST), modLoc("const/vec/nz"),
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, -1.0))));
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, -1.0))));
// Yep, this is what I spend the "plain hexagon" pattern on.
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqq", HexDir.NORTH_WEST), modLoc("const/vec/0"),
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, 0.0))));
Action.makeConstantOp(new Vec3Iota(new Vec3(0.0, 0.0, 0.0))));
PatternRegistry.mapPattern(HexPattern.fromAngles("qdwdq", HexDir.NORTH_EAST), modLoc("const/double/pi"),
Action.makeConstantOp(new DoubleIota(Math.PI)));
Action.makeConstantOp(new DoubleIota(Math.PI)));
PatternRegistry.mapPattern(HexPattern.fromAngles("eawae", HexDir.NORTH_WEST), modLoc("const/double/tau"),
Action.makeConstantOp(new DoubleIota(HexUtils.TAU)));
Action.makeConstantOp(new DoubleIota(HexUtils.TAU)));
// e
PatternRegistry.mapPattern(HexPattern.fromAngles("aaq", HexDir.EAST), modLoc("const/double/e"),
Action.makeConstantOp(new DoubleIota(Math.E)));
Action.makeConstantOp(new DoubleIota(Math.E)));
// == Entities ==
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqdaqa", HexDir.SOUTH_EAST), modLoc("get_entity"),
new OpGetEntityAt(e -> true));
new OpGetEntityAt(e -> true));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqdaqaawa", HexDir.SOUTH_EAST),
modLoc("get_entity/animal"),
new OpGetEntityAt(OpGetEntitiesBy::isAnimal));
modLoc("get_entity/animal"),
new OpGetEntityAt(OpGetEntitiesBy::isAnimal));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqdaqaawq", HexDir.SOUTH_EAST),
modLoc("get_entity/monster"),
new OpGetEntityAt(OpGetEntitiesBy::isMonster));
modLoc("get_entity/monster"),
new OpGetEntityAt(OpGetEntitiesBy::isMonster));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqdaqaaww", HexDir.SOUTH_EAST),
modLoc("get_entity/item"),
new OpGetEntityAt(OpGetEntitiesBy::isItem));
modLoc("get_entity/item"),
new OpGetEntityAt(OpGetEntitiesBy::isItem));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqdaqaawe", HexDir.SOUTH_EAST),
modLoc("get_entity/player"),
new OpGetEntityAt(OpGetEntitiesBy::isPlayer));
modLoc("get_entity/player"),
new OpGetEntityAt(OpGetEntitiesBy::isPlayer));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqdaqaawd", HexDir.SOUTH_EAST),
modLoc("get_entity/living"),
new OpGetEntityAt(OpGetEntitiesBy::isLiving));
modLoc("get_entity/living"),
new OpGetEntityAt(OpGetEntitiesBy::isLiving));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqwded", HexDir.SOUTH_EAST), modLoc("zone_entity"),
new OpGetEntitiesBy(e -> true, false));
new OpGetEntitiesBy(e -> true, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqwdeddwa", HexDir.SOUTH_EAST),
modLoc("zone_entity/animal"),
new OpGetEntitiesBy(OpGetEntitiesBy::isAnimal, false));
modLoc("zone_entity/animal"),
new OpGetEntitiesBy(OpGetEntitiesBy::isAnimal, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeewaqaawa", HexDir.NORTH_EAST),
modLoc("zone_entity/not_animal"),
new OpGetEntitiesBy(OpGetEntitiesBy::isAnimal, true));
modLoc("zone_entity/not_animal"),
new OpGetEntitiesBy(OpGetEntitiesBy::isAnimal, true));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqwdeddwq", HexDir.SOUTH_EAST),
modLoc("zone_entity/monster"),
new OpGetEntitiesBy(OpGetEntitiesBy::isMonster, false));
modLoc("zone_entity/monster"),
new OpGetEntitiesBy(OpGetEntitiesBy::isMonster, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeewaqaawq", HexDir.NORTH_EAST),
modLoc("zone_entity/not_monster"),
new OpGetEntitiesBy(OpGetEntitiesBy::isMonster, true));
modLoc("zone_entity/not_monster"),
new OpGetEntitiesBy(OpGetEntitiesBy::isMonster, true));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqwdeddww", HexDir.SOUTH_EAST),
modLoc("zone_entity/item"),
new OpGetEntitiesBy(OpGetEntitiesBy::isItem, false));
modLoc("zone_entity/item"),
new OpGetEntitiesBy(OpGetEntitiesBy::isItem, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeewaqaaww", HexDir.NORTH_EAST),
modLoc("zone_entity/not_item"),
new OpGetEntitiesBy(OpGetEntitiesBy::isItem, true));
modLoc("zone_entity/not_item"),
new OpGetEntitiesBy(OpGetEntitiesBy::isItem, true));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqwdeddwe", HexDir.SOUTH_EAST),
modLoc("zone_entity/player"),
new OpGetEntitiesBy(OpGetEntitiesBy::isPlayer, false));
modLoc("zone_entity/player"),
new OpGetEntitiesBy(OpGetEntitiesBy::isPlayer, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeewaqaawe", HexDir.NORTH_EAST),
modLoc("zone_entity/not_player"),
new OpGetEntitiesBy(OpGetEntitiesBy::isPlayer, true));
modLoc("zone_entity/not_player"),
new OpGetEntitiesBy(OpGetEntitiesBy::isPlayer, true));
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqqqwdeddwd", HexDir.SOUTH_EAST),
modLoc("zone_entity/living"),
new OpGetEntitiesBy(OpGetEntitiesBy::isLiving, false));
modLoc("zone_entity/living"),
new OpGetEntitiesBy(OpGetEntitiesBy::isLiving, false));
PatternRegistry.mapPattern(HexPattern.fromAngles("eeeeewaqaawd", HexDir.NORTH_EAST),
modLoc("zone_entity/not_living"),
new OpGetEntitiesBy(OpGetEntitiesBy::isLiving, true));
modLoc("zone_entity/not_living"),
new OpGetEntitiesBy(OpGetEntitiesBy::isLiving, true));
// == Lists ==
PatternRegistry.mapPattern(HexPattern.fromAngles("edqde", HexDir.SOUTH_WEST), modLoc("append"),
OpAppend.INSTANCE);
OpAppend.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qaeaq", HexDir.NORTH_WEST), modLoc("concat"),
OpConcat.INSTANCE);
OpConcat.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("deeed", HexDir.NORTH_WEST), modLoc("index"),
OpIndex.INSTANCE);
OpIndex.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("dadad", HexDir.NORTH_EAST), modLoc("for_each"),
OpForEach.INSTANCE);
OpForEach.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aqaeaq", HexDir.EAST), modLoc("list_size"),
OpListSize.INSTANCE);
OpListSize.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("adeeed", HexDir.EAST), modLoc("singleton"),
OpSingleton.INSTANCE);
OpSingleton.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqaeaae", HexDir.NORTH_EAST), modLoc("empty_list"),
OpEmptyList.INSTANCE);
OpEmptyList.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qqqaede", HexDir.EAST), modLoc("reverse_list"),
OpReverski.INSTANCE);
OpReverski.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("ewdqdwe", HexDir.SOUTH_WEST), modLoc("last_n_list"),
OpLastNToList.INSTANCE);
OpLastNToList.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qwaeawq", HexDir.NORTH_WEST), modLoc("splat"),
OpSplat.INSTANCE);
OpSplat.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("dedqde", HexDir.EAST), modLoc("index_of"),
OpIndexOf.INSTANCE);
OpIndexOf.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("edqdewaqa", HexDir.SOUTH_WEST), modLoc("list_remove"),
OpRemove.INSTANCE);
OpRemove.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("qaeaqwded", HexDir.NORTH_WEST), modLoc("slice"),
OpSlice.INSTANCE);
OpSlice.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("wqaeaqw", HexDir.NORTH_WEST),
modLoc("modify_in_place"),
OpModifyInPlace.INSTANCE);
modLoc("modify_in_place"),
OpModifyInPlace.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("ddewedd", HexDir.SOUTH_EAST), modLoc("construct"),
OpCons.INSTANCE);
OpCons.INSTANCE);
PatternRegistry.mapPattern(HexPattern.fromAngles("aaqwqaa", HexDir.SOUTH_WEST), modLoc("deconstruct"),
OpUnCons.INSTANCE);
OpUnCons.INSTANCE);
} catch (PatternRegistry.RegisterPatternException exn) {
exn.printStackTrace();

View file

@ -4,8 +4,9 @@ import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.FrameEvaluate
import at.petrak.hexcasting.api.spell.casting.eval.FrameFinishEval
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.evaluatable
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.iota.PatternIota
@ -27,14 +28,14 @@ object OpEval : Action {
// if not installed already...
// also, never make a break boundary when evaluating just one pattern
val newCont =
if (instrs.left().isPresent || (continuation is SpellContinuation.NotDone && continuation.frame is ContinuationFrame.FinishEval)) {
if (instrs.left().isPresent || (continuation is SpellContinuation.NotDone && continuation.frame is FrameFinishEval)) {
continuation
} else {
continuation.pushFrame(ContinuationFrame.FinishEval) // install a break-boundary after eval
continuation.pushFrame(FrameFinishEval) // install a break-boundary after eval
}
val instrsList = instrs.map({ SpellList.LList(0, listOf(PatternIota(it))) }, { it })
val frame = ContinuationFrame.Evaluate(instrsList)
val frame = FrameEvaluate(instrsList, true)
return OperationResult(newCont.pushFrame(frame), stack, ravenmind, listOf())
}
}

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.eval
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.iota.Iota
object OpEvalDelay : Action {

View file

@ -3,8 +3,8 @@ package at.petrak.hexcasting.common.casting.operators.eval
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.FrameForEach
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.getList
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
@ -24,7 +24,7 @@ object OpForEach : Action {
stack.removeLastOrNull()
stack.removeLastOrNull()
val frame = ContinuationFrame.ForEach(datums, instrs, null, mutableListOf())
val frame = FrameForEach(datums, instrs, null, mutableListOf())
return OperationResult(
continuation.pushFrame(frame),

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.eval
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.iota.Iota
object OpHalt : Action {

View file

@ -4,7 +4,7 @@ import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.asActionResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.getPositiveIntUnderInclusive
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.local
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.orNull

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.local
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs

View file

@ -17,7 +17,7 @@ object OpOr : ConstMediaAction {
},
{ list1 ->
val list2 = args.getList(1, argc)
list1 + list2.filter { x -> list1.none { Iota.tolerates(x, it) } }.asActionResult
(list1 + list2.filter { x -> list1.none { Iota.tolerates(x, it) } }).asActionResult
}
)
}

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.common.casting.operators
package at.petrak.hexcasting.common.casting.operators.rw
import at.petrak.hexcasting.api.spell.ConstMediaAction
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.xplat.IXplatAbstractions

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.casting.operators
package at.petrak.hexcasting.common.casting.operators.rw
import at.petrak.hexcasting.api.spell.ConstMediaAction
import at.petrak.hexcasting.api.spell.asActionResult

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.casting.operators
package at.petrak.hexcasting.common.casting.operators.rw
import at.petrak.hexcasting.api.spell.ConstMediaAction
import at.petrak.hexcasting.api.spell.casting.CastingContext

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.casting.operators
package at.petrak.hexcasting.common.casting.operators.rw
import at.petrak.hexcasting.api.spell.ConstMediaAction
import at.petrak.hexcasting.api.spell.asActionResult

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.casting.operators
package at.petrak.hexcasting.common.casting.operators.rw
import at.petrak.hexcasting.api.spell.ConstMediaAction
import at.petrak.hexcasting.api.spell.asActionResult

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.casting.operators
package at.petrak.hexcasting.common.casting.operators.rw
import at.petrak.hexcasting.api.addldata.ADIotaHolder
import at.petrak.hexcasting.api.spell.ParticleSpray
@ -10,6 +10,8 @@ import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapBadEntity
import at.petrak.hexcasting.api.spell.mishaps.MishapOthersName
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.phys.Vec3
object OpTheCoolerWrite : SpellAction {
override val argc = 2
@ -25,16 +27,25 @@ object OpTheCoolerWrite : SpellAction {
val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target)
?: throw MishapBadEntity.of(target, "iota.write")
if (!datumHolder.writeIota(datum, true))
throw MishapBadEntity.of(target, "iota.write")
// We pass null here so that even the own caster won't be allowed into a focus.
// Otherwise, you could sentinel scout to people and remotely write their names into things using a cleric circle.
val trueName = MishapOthersName.getTrueNameFromDatum(datum, null)
if (trueName != null)
throw MishapOthersName(trueName)
val burstPos = if (target is ItemEntity) {
// Special case these because the render is way above the entity
target.position().add(0.0, 3.0 / 8.0, 0.0)
} else {
target.position()
}
return Triple(
Spell(datum, datumHolder),
0,
listOf(ParticleSpray.burst(target.position(), 0.5))
listOf(ParticleSpray(burstPos, Vec3(1.0, 0.0, 0.0), 0.25, 3.14, 40))
)
}

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.casting.operators
package at.petrak.hexcasting.common.casting.operators.rw
import at.petrak.hexcasting.api.spell.ConstMediaAction
import at.petrak.hexcasting.api.spell.asActionResult

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.casting.operators
package at.petrak.hexcasting.common.casting.operators.rw
import at.petrak.hexcasting.api.addldata.ADIotaHolder
import at.petrak.hexcasting.api.spell.ParticleSpray

View file

@ -4,8 +4,8 @@ import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
@ -23,8 +23,8 @@ object OpPrint : Action {
val datum = stack[stack.lastIndex]
return OperationResult(
continuation, stack, ravenmind, listOf(
OperatorSideEffect.AttemptSpell(Spell(datum), hasCastingSound = false, awardStat = false)
)
OperatorSideEffect.AttemptSpell(Spell(datum), hasCastingSound = false, awardStat = false)
)
)
}

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.stack
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.getPositiveInt
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.stack
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.getPositiveInt
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.stack
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.getPositiveIntUnderInclusive
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.stack
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.getPositiveIntUnderInclusive
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
@ -18,7 +18,7 @@ object OpFishermanButItCopies : Action {
if (stack.size < 2)
throw MishapNotEnoughArgs(2, stack.size)
val depth = stack.getPositiveIntUnderInclusive(stack.lastIndex, stack.size - 1)
val depth = stack.getPositiveIntUnderInclusive(stack.lastIndex, stack.size - 2)
stack.removeLast()
val fish = stack.get(stack.size - 1 - depth)
stack.add(fish)

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.casting.operators.stack
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation
import at.petrak.hexcasting.api.spell.iota.DoubleIota
import at.petrak.hexcasting.api.spell.iota.Iota

View file

@ -4,7 +4,7 @@ import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.spell.iota.DoubleIota;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexSounds;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
@ -66,7 +66,7 @@ public class ItemAbacus extends Item implements IotaHolderItem {
@Override
public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, List<Component> pTooltipComponents,
TooltipFlag pIsAdvanced) {
TooltipFlag pIsAdvanced) {
IotaHolderItem.appendHoverText(this, pStack, pTooltipComponents, pIsAdvanced);
}
}

View file

@ -4,7 +4,7 @@ import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.iota.NullIota;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;

View file

@ -7,7 +7,7 @@ import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.gui.PatternTooltipComponent;
import at.petrak.hexcasting.common.entities.EntityWallScroll;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.common.misc.PatternTooltip;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@ -121,7 +121,7 @@ public class ItemScroll extends Item implements IotaHolderItem {
var ancientId = NBTHelper.getString(pStack, TAG_OP_ID);
if (ancientId != null) {
return Component.translatable(descID + ".of",
Component.translatable("hexcasting.spell." + ResourceLocation.tryParse(ancientId)));
Component.translatable("hexcasting.spell." + ResourceLocation.tryParse(ancientId)));
} else if (NBTHelper.hasCompound(pStack, TAG_PATTERN)) {
return Component.translatable(descID);
} else {
@ -137,10 +137,10 @@ public class ItemScroll extends Item implements IotaHolderItem {
if (compound != null) {
var pattern = HexPattern.fromNBT(compound);
return Optional.of(new PatternTooltip(
pattern,
NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID)
? PatternTooltipComponent.ANCIENT_BG
: PatternTooltipComponent.PRISTINE_BG));
pattern,
NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID)
? PatternTooltipComponent.ANCIENT_BG
: PatternTooltipComponent.PRISTINE_BG));
}
return Optional.empty();

View file

@ -9,7 +9,7 @@ import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.gui.PatternTooltipComponent;
import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.common.misc.PatternTooltip;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;

View file

@ -4,7 +4,7 @@ import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.spell.iota.NullIota;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
@ -42,7 +42,7 @@ public class ItemSpellbook extends Item implements IotaHolderItem {
@Override
public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip,
TooltipFlag isAdvanced) {
TooltipFlag isAdvanced) {
boolean sealed = isSealed(stack);
boolean empty = false;
if (NBTHelper.hasNumber(stack, TAG_SELECTED_PAGE)) {
@ -51,9 +51,9 @@ public class ItemSpellbook extends Item implements IotaHolderItem {
if (highest != 0) {
if (sealed) {
tooltip.add(Component.translatable("hexcasting.tooltip.spellbook.page.sealed",
Component.literal(String.valueOf(pageIdx)).withStyle(ChatFormatting.WHITE),
Component.literal(String.valueOf(highest)).withStyle(ChatFormatting.WHITE),
Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD))
Component.literal(String.valueOf(pageIdx)).withStyle(ChatFormatting.WHITE),
Component.literal(String.valueOf(highest)).withStyle(ChatFormatting.WHITE),
Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD))
.withStyle(ChatFormatting.GRAY));
} else {
tooltip.add(Component.translatable("hexcasting.tooltip.spellbook.page",
@ -76,7 +76,7 @@ public class ItemSpellbook extends Item implements IotaHolderItem {
ChatFormatting.GOLD));
} else {
tooltip.add(Component.translatable("hexcasting.tooltip.spellbook.empty.sealed",
Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD))
Component.translatable("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD))
.withStyle(ChatFormatting.GRAY));
}
} else if (!overridden) {

View file

@ -5,7 +5,7 @@ import at.petrak.hexcasting.api.spell.casting.CastingContext;
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;

View file

@ -24,6 +24,8 @@ public class HexSounds {
public static final SoundEvent FAIL_PATTERN = sound("casting.fail_pattern");
public static final SoundEvent CASTING_AMBIANCE = sound("casting.ambiance");
public static final SoundEvent ACTUALLY_CAST = sound("casting.cast");
public static final SoundEvent CAST_HERMES = sound("casting.hermes");
public static final SoundEvent CAST_THOTH = sound("casting.thoth");
public static final SoundEvent ABACUS = sound("abacus");
public static final SoundEvent ABACUS_SHAKE = sound("abacus.shake");

View file

@ -0,0 +1,47 @@
package at.petrak.hexcasting.common.lib.hex;
import at.petrak.hexcasting.api.spell.casting.sideeffects.EvalSound;
import at.petrak.hexcasting.common.lib.HexSounds;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class HexEvalSounds {
public static final Registry<EvalSound> REGISTRY = IXplatAbstractions.INSTANCE.getEvalSoundRegistry();
private static final Map<ResourceLocation, EvalSound> SOUNDS = new LinkedHashMap<>();
public static final EvalSound NOTHING = make("nothing",
new EvalSound(null, Integer.MIN_VALUE));
public static final EvalSound OPERATOR = make("operator",
new EvalSound(HexSounds.ADD_PATTERN, 0));
public static final EvalSound SPELL = make("spell",
new EvalSound(HexSounds.ACTUALLY_CAST, 1000));
public static final EvalSound MISHAP = make("mishap",
new EvalSound(HexSounds.FAIL_PATTERN, Integer.MAX_VALUE));
public static final EvalSound HERMES = make("hermes",
new EvalSound(HexSounds.CAST_HERMES, Integer.MAX_VALUE));
public static final EvalSound THOTH = make("thoth",
new EvalSound(HexSounds.CAST_THOTH, Integer.MAX_VALUE));
private static EvalSound make(String name, EvalSound sound) {
var old = SOUNDS.put(modLoc(name), sound);
if (old != null) {
throw new IllegalArgumentException("Typo? Duplicate id " + name);
}
return sound;
}
public static void registerTypes() {
BiConsumer<EvalSound, ResourceLocation> r = (type, id) -> Registry.register(REGISTRY, id, type);
for (var e : SOUNDS.entrySet()) {
r.accept(e.getValue(), e.getKey());
}
}
}

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.lib;
package at.petrak.hexcasting.common.lib.hex;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.spell.iota.*;
@ -150,16 +150,26 @@ public class HexIotaTypes {
return type.display(data);
}
public static List<FormattedCharSequence> getDisplayWithMaxWidth(CompoundTag tag, int maxWidth, Font font) {
public static FormattedCharSequence getDisplayWithMaxWidth(CompoundTag tag, int maxWidth, Font font) {
var type = getTypeFromTag(tag);
if (type == null) {
return font.split(brokenIota(), maxWidth);
return brokenIota().getVisualOrderText();
}
var data = tag.get(KEY_DATA);
if (data == null) {
return font.split(brokenIota(), maxWidth);
return brokenIota().getVisualOrderText();
}
var display = type.display(data);
var splitted = font.split(display, maxWidth - font.width("..."));
if (splitted.isEmpty())
return FormattedCharSequence.EMPTY;
else if (splitted.size() == 1)
return splitted.get(0);
else {
var first = splitted.get(0);
return FormattedCharSequence.fromPair(first,
Component.literal("...").withStyle(ChatFormatting.GRAY).getVisualOrderText());
}
return type.displayWithWidth(data, maxWidth, font);
}
public static int getColor(CompoundTag tag) {

View file

@ -0,0 +1,4 @@
/**
* Registries and such of types Hexcasting itself defines
*/
package at.petrak.hexcasting.common.lib.hex;

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.network;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.items.ItemAbacus;
import at.petrak.hexcasting.common.items.ItemSpellbook;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.lib.HexSounds;
import io.netty.buffer.ByteBuf;

View file

@ -47,8 +47,9 @@ abstract public class AbstractPatternComponent implements ICustomComponent {
@Override
public void onVariablesAvailable(UnaryOperator<IVariable> lookup) {
var patterns = this.getPatterns(lookup);
var data = PatternDrawingUtil.loadPatterns(
this.getPatterns(lookup),
patterns,
this.showStrokeOrder() ? RenderLib.DEFAULT_READABILITY_OFFSET : 0f,
this.showStrokeOrder() ? RenderLib.DEFAULT_LAST_SEGMENT_LEN_PROP : 1f);
this.hexSize = data.hexSize();

View file

@ -9,6 +9,7 @@ import at.petrak.hexcasting.api.player.FlightAbility;
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
import at.petrak.hexcasting.api.spell.casting.sideeffects.EvalSound;
import at.petrak.hexcasting.api.spell.iota.IotaType;
import at.petrak.hexcasting.common.network.IMessage;
import at.petrak.hexcasting.interop.pehkui.PehkuiInterop;
@ -124,7 +125,7 @@ public interface IXplatAbstractions {
// Blocks
<T extends BlockEntity> BlockEntityType<T> createBlockEntityType(BiFunction<BlockPos, BlockState, T> func,
Block... blocks);
Block... blocks);
boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, Fluid fluid);
@ -159,6 +160,8 @@ public interface IXplatAbstractions {
Registry<IotaType<?>> getIotaTypeRegistry();
Registry<EvalSound> getEvalSoundRegistry();
boolean isBreakingAllowed(Level world, BlockPos pos, BlockState state, Player player);
boolean isPlacingAllowed(Level world, BlockPos pos, ItemStack blockStack, Player player);

View file

@ -172,6 +172,46 @@
"emi.category.hexcasting.villager_leveling": "Trade Leveling",
"emi.category.hexcasting.villager_profession": "Villager Profession",
"text.autoconfig.hexcasting.title": "Hexcasting Config",
"text.autoconfig.hexcasting.category.common": "Common",
"text.autoconfig.hexcasting.category.client": "Client",
"text.autoconfig.hexcasting.category.server": "Server",
"text.autoconfig.hexcasting.option.common.dustMediaAmount": "Dust Media Amount",
"text.autoconfig.hexcasting.option.common.shardMediaAmount": "Shard Media Amount",
"text.autoconfig.hexcasting.option.common.chargedCrystalMediaAmount": "Charged Crystal Media Amount",
"text.autoconfig.hexcasting.option.common.mediaToHealthRate": "Media To Health Rate",
"text.autoconfig.hexcasting.option.common.dustMediaAmount.@Tooltip": "How much media a single Amethyst Dust item is worth",
"text.autoconfig.hexcasting.option.common.shardMediaAmount.@Tooltip": "How much media a single Amethyst Shard item is worth",
"text.autoconfig.hexcasting.option.common.chargedCrystalMediaAmount.@Tooltip": "How much media a single Charged Amethyst Crystal item is worth",
"text.autoconfig.hexcasting.option.common.mediaToHealthRate.@Tooltip": "How many points of media a half-heart is worth when casting from HP",
"text.autoconfig.hexcasting.option.client.ctrlTogglesOffStrokeOrder": "Ctrl Toggles Off Stroke Order",
"text.autoconfig.hexcasting.option.client.invertSpellbookScrollDirection": "Invert Spellbook Scroll Direction",
"text.autoconfig.hexcasting.option.client.invertAbacusScrollDirection": "Invert Abacus Scroll Direction",
"text.autoconfig.hexcasting.option.client.gridSnapThreshold": "Grid Snap Threshold",
"text.autoconfig.hexcasting.option.client.ctrlTogglesOffStrokeOrder.@Tooltip": "Whether the ctrl key will instead turn *off* the color gradient on patterns",
"text.autoconfig.hexcasting.option.client.invertSpellbookScrollDirection.@Tooltip": "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and vice versa",
"text.autoconfig.hexcasting.option.client.invertAbacusScrollDirection.@Tooltip": "Whether scrolling up (as opposed to down) will increase the page index of the abacus, and vice versa",
"text.autoconfig.hexcasting.option.client.gridSnapThreshold.@Tooltip": "When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 means 50% of the way (0.5-1)",
"text.autoconfig.hexcasting.option.server.opBreakHarvestLevel": "Break Harvest Level",
"text.autoconfig.hexcasting.option.server.maxRecurseDepth": "Max Recurse Depth",
"text.autoconfig.hexcasting.option.server.maxSpellCircleLength": "Max Spell Circle Length",
"text.autoconfig.hexcasting.option.server.actionDenyList": "Action Deny List",
"text.autoconfig.hexcasting.option.server.circleActionDenyList": "Circle Action Deny List",
"text.autoconfig.hexcasting.option.server.villagersOffendedByMindMurder": "Villagers Offended By Mind Murder",
"text.autoconfig.hexcasting.option.server.fewScrollTables": "Few Scroll Tables",
"text.autoconfig.hexcasting.option.server.someScrollTables": "Some Scroll Tables",
"text.autoconfig.hexcasting.option.server.manyScrollTables": "Many Scroll Tables",
"text.autoconfig.hexcasting.option.server.opBreakHarvestLevel.@Tooltip": "The harvest level of the Break Block spell.\n0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite.",
"text.autoconfig.hexcasting.option.server.maxRecurseDepth.@Tooltip": "How many times an action can recursively cast other actions",
"text.autoconfig.hexcasting.option.server.maxSpellCircleLength.@Tooltip": "The maximum number of slates in a spell circle",
"text.autoconfig.hexcasting.option.server.actionDenyList.@Tooltip": "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.",
"text.autoconfig.hexcasting.option.server.circleActionDenyList.@Tooltip": "Resource locations of disallowed actions within circles. Trying to cast one of these from a circle will result in a mishap.",
"text.autoconfig.hexcasting.option.server.villagersOffendedByMindMurder.@Tooltip": "Whether villagers should be angry at the player when other villagers are mindflayed",
"text.autoconfig.hexcasting.option.server.fewScrollTables.@Tooltip": "Loot tables that a small number of Ancient Scrolls are injected into",
"text.autoconfig.hexcasting.option.server.someScrollTables.@Tooltip": "Loot tables that a decent number of Ancient Scrolls are injected into",
"text.autoconfig.hexcasting.option.server.manyScrollTables.@Tooltip": "Loot tables that a huge number of Ancient Scrolls are injected into",
"advancement.hexcasting:root": "Hexcasting Research",
"advancement.hexcasting:root.desc": "Find and mine a concentrated form of media growing deep beneath the earth.",
"advancement.hexcasting:enlightenment": "Achieve Enlightenment",
@ -187,7 +227,7 @@
"advancement.hexcasting:lore": "Hexcasting Lore",
"advancement.hexcasting:lore.desc": "Read a Lore Fragment",
"advancement.hexcasting:lore/terabithia1": "Terabithia Steles",
"advancement.hexcasting:lore/terabithia1.desc": "Letter from Terabithia Steles to Her Father, #2",
"advancement.hexcasting:lore/terabithia1.desc": "Letter from Terabithia Steles to Her Father, #1",
"advancement.hexcasting:lore/terabithia2": "Terabithia Steles",
"advancement.hexcasting:lore/terabithia2.desc": "Letter from Terabithia Steles to Her Father, #2",
"advancement.hexcasting:lore/terabithia3": "Terabithia Steles",
@ -195,7 +235,7 @@
"advancement.hexcasting:lore/terabithia4": "Terabithia Steles",
"advancement.hexcasting:lore/terabithia4.desc": "Letter from Terabithia Steles to Her Father, #3, 2/2",
"advancement.hexcasting:lore/terabithia5": "Terabithia Steles",
"advancement.hexcasting:lore/terabithia5.desc": "Letter from Terabithia Steles to Her Father, #5",
"advancement.hexcasting:lore/terabithia5.desc": "Letter from Terabithia Steles to Her Father, #4",
"advancement.hexcasting:lore/experiment1": "Wooleye Instance Notes",
"advancement.hexcasting:lore/experiment2": "Wooleye Interview Logs",
"advancement.hexcasting:lore/inventory": "Restoration Log 72",
@ -1105,7 +1145,7 @@
"hexcasting.page.brainsweep_spell.1": "I cannot make heads or tails of this spell... To be honest, I'm not sure I want to know what it does.",
"hexcasting.entry.lore": "Lore",
"hexcasting.entry.lore.desc": "I have uncovered some letters and text not of direct relavence to my art. But, I think I may be able to divine some of the history of the world from these. Let me see...",
"hexcasting.entry.lore.desc": "I have uncovered some letters and text not of direct relevance to my art. But, I think I may be able to divine some of the history of the world from these. Let me see...",
"hexcasting.entry.lore.terabithia1": "Terabithia Steles, #1",
"hexcasting.page.lore.terabithia1.1": "$(italic)Full title: Letter from Terabithia Steles to Her Father, #1/$$(br2)Dear Papa,$(br)Every day it seems I have more reason to thank you for saving up to send me to the Grand Library. The amount I am learning is incredible! I feel I don't have the skill with words needed to express myself fully... it is wonderful to be here.",

View file

@ -43,7 +43,18 @@
"hexcasting:cast_hex"
]
},
"casting.hermes": {
"subtitle": "hexcasting.subtitles.cast",
"sounds": [
"hexcasting:hermes"
]
},
"casting.thoth": {
"subtitle": "hexcasting.subtitles.cast",
"sounds": [
"hexcasting:thoth"
]
},
"abacus": {
"subtitle": "hexcasting.subtitles.abacus",
"sounds": [
@ -58,7 +69,6 @@
"hexcasting:abacus_shake"
]
},
"spellcircle.find_block": {
"sounds": [
{
@ -83,7 +93,6 @@
],
"subtitle": "hexcasting.subtitles.spellcircle.cast"
},
"scroll.dust": {
"sounds": [
"minecraft:dig/sand1",
@ -101,7 +110,6 @@
],
"subtitle": "hexcasting.subtitles.scroll.scribble"
},
"impetus.fletcher.tick": {
"sounds": [
"minecraft:note/hat"
@ -114,7 +122,6 @@
],
"subtitle": "hexcasting.subtitles.impetus.cleric.register"
},
"lore_fragment.read": {
"sounds": [
"block/enchantment_table/enchant1",

View file

@ -78,9 +78,6 @@ dependencies {
modImplementation "at.petra-k.paucal:paucal-fabric-$minecraftVersion:$paucalVersion"
modImplementation "vazkii.patchouli:Patchouli:$minecraftVersion-$patchouliVersion-FABRIC"
modImplementation "me.zeroeightsix:fiber:$fiberVersion"
include "me.zeroeightsix:fiber:$fiberVersion"
modImplementation "dev.onyxstudios.cardinal-components-api:cardinal-components-api:$cardinalComponentsVersion"
modImplementation "com.jamieswhiteshirt:reach-entity-attributes:${entityReachVersion}"
@ -107,7 +104,7 @@ dependencies {
// *Something* is including an old version of modmenu with a broken mixin
// We can't figure out what it is
// so i'm just including a fresher version
modImplementation("com.terraformersmc:modmenu:4.1.0")
modImplementation("com.terraformersmc:modmenu:$modmenuVersion")
// i am speed
// sodium is causing frustum mixin errors so don't use it

View file

@ -2,7 +2,6 @@ fabricVersion=0.64.0+1.19.2
fabricLoaderVersion=0.14.10
# These are all included
fiberVersion=0.23.0-2
cardinalComponentsVersion=5.0.2
serializationHooksVersion=0.3.24
entityReachVersion=2.3.0
@ -12,6 +11,8 @@ gravityApiVersion=0.7.12+fabric
clothConfigVersion=8.2.88
trinketsVersion=3.4.0
modmenuVersion=4.1.1
# Optimizations
sodiumVersion=mc1.19.2-0.4.4
lithiumVersion=mc1.19.2-0.10.2

View file

@ -1,21 +1,21 @@
// 1.19.2 2022-11-09T19:48:37.741505 Tags for minecraft:item
5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/items/wooden_slabs.json
// 1.19.2 2022-11-21T19:55:21.969467688 Tags for minecraft:item
5928bad07d3872bb60f29ef4f3c885c8e1967c20 data/hexcasting/tags/items/phial_base.json
fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/items/wooden_doors.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/minecraft/tags/items/planks.json
38d781b60c5c37dc025d4c7e9ec5aa680f2a5835 data/c/tags/items/gems.json
4461ef6db41a675fd077dd833cfd0ea537e755be data/c/tags/items/amethyst_dusts.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/items/trapdoors.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/hexcasting/tags/items/edified_planks.json
20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/items/buttons.json
fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/items/doors.json
37cff4ce449b8069b59b2327d78e073fc026d348 data/minecraft/tags/items/wooden_pressure_plates.json
684c3206f38cc9cc494d5875c5e56aad004486af data/minecraft/tags/items/logs.json
24145229528668829a1bcecf18a6377ebd07ccf8 data/hexcasting/tags/items/grants_root_advancement.json
38d781b60c5c37dc025d4c7e9ec5aa680f2a5835 data/c/tags/items/gems.json
72ae9c5305aa948e78f95069eb34ecd532915fbf data/hexcasting/tags/items/staves.json
684c3206f38cc9cc494d5875c5e56aad004486af data/minecraft/tags/items/logs_that_burn.json
20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/items/wooden_buttons.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/hexcasting/tags/items/edified_planks.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/items/wooden_trapdoors.json
5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/items/slabs.json
24145229528668829a1bcecf18a6377ebd07ccf8 data/hexcasting/tags/items/grants_root_advancement.json
684c3206f38cc9cc494d5875c5e56aad004486af data/hexcasting/tags/items/edified_logs.json
20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/items/buttons.json
5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data/minecraft/tags/items/leaves.json
72ae9c5305aa948e78f95069eb34ecd532915fbf data/hexcasting/tags/items/staves.json
5928bad07d3872bb60f29ef4f3c885c8e1967c20 data/hexcasting/tags/items/phial_base.json
fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/items/doors.json
684c3206f38cc9cc494d5875c5e56aad004486af data/minecraft/tags/items/logs.json
5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/items/slabs.json
5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/items/wooden_slabs.json
4461ef6db41a675fd077dd833cfd0ea537e755be data/c/tags/items/amethyst_dusts.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/items/trapdoors.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/minecraft/tags/items/planks.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/items/wooden_trapdoors.json

View file

@ -1,39 +1,39 @@
// 1.19.2 2022-11-09T19:48:37.716082 LootTables
a39e834a389257f05d72d2fa2ea43c22a6066bb5 data/hexcasting/loot_tables/blocks/amethyst_edified_leaves.json
// 1.19.2 2022-11-21T19:55:21.965828817 LootTables
01a50f557196c705c275722015cf893e0abe6425 data/hexcasting/loot_tables/inject/scroll_loot_many.json
d97f573d03712b4d677e3a0a22ab6a000b1db060 data/hexcasting/loot_tables/blocks/impetus_rightclick.json
14b3c20c41228c7e6cc6341abe738fdb4b776ec4 data/hexcasting/loot_tables/blocks/aventurine_edified_leaves.json
dec1d3592e82f99d9e059d9c771530f103b2bda5 data/hexcasting/loot_tables/blocks/empty_directrix.json
2c42fc5d8c74c98ad15b8bd50f56541fccbef750 data/hexcasting/loot_tables/blocks/edified_tile.json
cfb39e2151725fe4f9a7269d9b5de8031ea54a44 data/hexcasting/loot_tables/blocks/directrix_redstone.json
47f8f9442a6f072f04709551eb0b997233731310 data/hexcasting/loot_tables/blocks/edified_button.json
5ab3568a18745879cf60b2febd2c650b3f8cdb52 data/hexcasting/loot_tables/blocks/edified_pressure_plate.json
4bd736b9d96bb5a0f0b18cb423566bf0ec63f530 data/hexcasting/loot_tables/blocks/scroll_paper.json
8c81bd237a36b4f3dfb3ef174f455f1edd606b74 data/hexcasting/loot_tables/blocks/edified_planks.json
6e4bc6364e7e1cc97f1ad1127608a0b95e4d156f data/hexcasting/loot_tables/blocks/stripped_edified_wood.json
e329c8ad61d61ad9be91d6ab4c36d57c05990e0c data/hexcasting/loot_tables/blocks/amethyst_dust_block.json
d640fa26a044349d1f989a8afc6af9e8f3a520ba data/hexcasting/loot_tables/blocks/ancient_scroll_paper_lantern.json
457b355c6a5e1b2ee4ddda37a39084ceef3546d7 data/hexcasting/loot_tables/blocks/stripped_edified_log.json
a3ca7f9427bd57a6033f241754d49425251cc091 data/hexcasting/loot_tables/blocks/scroll_paper_lantern.json
16498092b43c43a4a7617ba91bcfcc13b87d9a7e data/hexcasting/loot_tables/blocks/akashic_record.json
c089d3d230ae5354f2a9953f65bba77b6e26d976 data/hexcasting/loot_tables/blocks/edified_trapdoor.json
f99e241d651abe7f9234301508bc805deba179ad data/hexcasting/loot_tables/blocks/empty_impetus.json
2c42fc5d8c74c98ad15b8bd50f56541fccbef750 data/hexcasting/loot_tables/blocks/edified_tile.json
3b1e2f738c4906371a4cdecf24253ad94ae66320 data/hexcasting/loot_tables/blocks/akashic_bookshelf.json
a7a08d76b8a1b1596a0d67d422d7a0d93f3a1d2f data/hexcasting/loot_tables/inject/scroll_loot_few.json
9ee4259b51cccd4582fb2e52ab9f64e92af857bb data/hexcasting/loot_tables/blocks/edified_log.json
e17ca4b3e84c4fb6dadfee273e6040cf15724014 data/hexcasting/loot_tables/inject/amethyst_cluster.json
ac9d01324ffe7c1ea963aa7def5c177db820067f data/hexcasting/loot_tables/blocks/amethyst_tiles.json
4bd736b9d96bb5a0f0b18cb423566bf0ec63f530 data/hexcasting/loot_tables/blocks/scroll_paper.json
fd874549344d85ec2bb6edcb7fe7af62cafebba2 data/hexcasting/loot_tables/inject/scroll_loot_some.json
2a38344306b3ee7245c271f4af339544bc4abab8 data/hexcasting/loot_tables/blocks/edified_wood.json
d51eabb3875bdf6d31db635e15db10cb25e8bcc5 data/hexcasting/loot_tables/blocks/edified_panel.json
d97f573d03712b4d677e3a0a22ab6a000b1db060 data/hexcasting/loot_tables/blocks/impetus_rightclick.json
5432a6fece51aa2120ff28eb3044d43f45ac2c8c data/hexcasting/loot_tables/blocks/citrine_edified_leaves.json
201bbf7adff979ff8cb087e1798da5a2a31eed09 data/hexcasting/loot_tables/blocks/akashic_connector.json
b7f7af68760b51d0c438f5c6039f1cd7157fa452 data/hexcasting/loot_tables/blocks/ancient_scroll_paper.json
745b510161cfff804b115f566ad6b50e0cb492d1 data/hexcasting/loot_tables/blocks/slate.json
dec1d3592e82f99d9e059d9c771530f103b2bda5 data/hexcasting/loot_tables/blocks/empty_directrix.json
543b9a1b5f81ae468f08ed055b9f086d5d2c3278 data/hexcasting/loot_tables/blocks/edified_slab.json
d640fa26a044349d1f989a8afc6af9e8f3a520ba data/hexcasting/loot_tables/blocks/ancient_scroll_paper_lantern.json
a3ca7f9427bd57a6033f241754d49425251cc091 data/hexcasting/loot_tables/blocks/scroll_paper_lantern.json
2a9a51aed541bb1ede76c34271e1262fc7bcd300 data/hexcasting/loot_tables/blocks/edified_stairs.json
201bbf7adff979ff8cb087e1798da5a2a31eed09 data/hexcasting/loot_tables/blocks/akashic_connector.json
ac9d01324ffe7c1ea963aa7def5c177db820067f data/hexcasting/loot_tables/blocks/amethyst_tiles.json
e329c8ad61d61ad9be91d6ab4c36d57c05990e0c data/hexcasting/loot_tables/blocks/amethyst_dust_block.json
a7a08d76b8a1b1596a0d67d422d7a0d93f3a1d2f data/hexcasting/loot_tables/inject/scroll_loot_few.json
3b1e2f738c4906371a4cdecf24253ad94ae66320 data/hexcasting/loot_tables/blocks/akashic_bookshelf.json
5da5b504c400c052ee8b03cf88e78dc567456ef8 data/hexcasting/loot_tables/blocks/amethyst_sconce.json
5596975fb09fab7f74ec06af9f2b854cf198a775 data/hexcasting/loot_tables/blocks/slate_block.json
c8dd063aa3fe320f9f4518736d4ae97ba2c93a79 data/hexcasting/loot_tables/blocks/impetus_storedplayer.json
d21fdf6326f7a9958df22224e5e34489d63e013d data/hexcasting/loot_tables/blocks/edified_door.json
cfb39e2151725fe4f9a7269d9b5de8031ea54a44 data/hexcasting/loot_tables/blocks/directrix_redstone.json
5596975fb09fab7f74ec06af9f2b854cf198a775 data/hexcasting/loot_tables/blocks/slate_block.json
90f8f97b941408ed89d01b69e1fccf5f2a35e2bc data/hexcasting/loot_tables/blocks/impetus_look.json
a39e834a389257f05d72d2fa2ea43c22a6066bb5 data/hexcasting/loot_tables/blocks/amethyst_edified_leaves.json
e17ca4b3e84c4fb6dadfee273e6040cf15724014 data/hexcasting/loot_tables/inject/amethyst_cluster.json
f99e241d651abe7f9234301508bc805deba179ad data/hexcasting/loot_tables/blocks/empty_impetus.json
14b3c20c41228c7e6cc6341abe738fdb4b776ec4 data/hexcasting/loot_tables/blocks/aventurine_edified_leaves.json
543b9a1b5f81ae468f08ed055b9f086d5d2c3278 data/hexcasting/loot_tables/blocks/edified_slab.json
c8dd063aa3fe320f9f4518736d4ae97ba2c93a79 data/hexcasting/loot_tables/blocks/impetus_storedplayer.json
16498092b43c43a4a7617ba91bcfcc13b87d9a7e data/hexcasting/loot_tables/blocks/akashic_record.json
d51eabb3875bdf6d31db635e15db10cb25e8bcc5 data/hexcasting/loot_tables/blocks/edified_panel.json
5ab3568a18745879cf60b2febd2c650b3f8cdb52 data/hexcasting/loot_tables/blocks/edified_pressure_plate.json
457b355c6a5e1b2ee4ddda37a39084ceef3546d7 data/hexcasting/loot_tables/blocks/stripped_edified_log.json
b7f7af68760b51d0c438f5c6039f1cd7157fa452 data/hexcasting/loot_tables/blocks/ancient_scroll_paper.json
2a38344306b3ee7245c271f4af339544bc4abab8 data/hexcasting/loot_tables/blocks/edified_wood.json
9ee4259b51cccd4582fb2e52ab9f64e92af857bb data/hexcasting/loot_tables/blocks/edified_log.json
c089d3d230ae5354f2a9953f65bba77b6e26d976 data/hexcasting/loot_tables/blocks/edified_trapdoor.json
745b510161cfff804b115f566ad6b50e0cb492d1 data/hexcasting/loot_tables/blocks/slate.json
fd874549344d85ec2bb6edcb7fe7af62cafebba2 data/hexcasting/loot_tables/inject/scroll_loot_some.json

View file

@ -1,22 +1,22 @@
// 1.19.2 2022-11-09T19:48:37.743198 Tags for minecraft:block
36b54a86d2ed41c8a503f7a61817a7a9d7a94536 data/minecraft/tags/blocks/crystal_sound_blocks.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/hexcasting/tags/blocks/edified_planks.json
5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/blocks/wooden_slabs.json
// 1.19.2 2022-11-21T19:55:21.971658683 Tags for minecraft:block
20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/blocks/wooden_buttons.json
357eddf3cee6f16725bed0701d57b2ca3097d74d data/minecraft/tags/blocks/mineable/shovel.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/blocks/wooden_trapdoors.json
20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/blocks/buttons.json
5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/blocks/slabs.json
684c3206f38cc9cc494d5875c5e56aad004486af data/minecraft/tags/blocks/logs_that_burn.json
5853312830fdd8ee85e2c5b1be3dd4a6357a4971 data/minecraft/tags/blocks/mineable/pickaxe.json
f38c2a2a896388b3b87f53887609b417930abdf7 data/minecraft/tags/blocks/mineable/axe.json
5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data/minecraft/tags/blocks/mineable/hoe.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/blocks/trapdoors.json
fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/blocks/wooden_doors.json
684c3206f38cc9cc494d5875c5e56aad004486af data/minecraft/tags/blocks/logs.json
684c3206f38cc9cc494d5875c5e56aad004486af data/hexcasting/tags/blocks/edified_logs.json
5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/blocks/slabs.json
684c3206f38cc9cc494d5875c5e56aad004486af data/minecraft/tags/blocks/logs_that_burn.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/minecraft/tags/blocks/planks.json
5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data/minecraft/tags/blocks/leaves.json
37cff4ce449b8069b59b2327d78e073fc026d348 data/minecraft/tags/blocks/pressure_plates.json
37cff4ce449b8069b59b2327d78e073fc026d348 data/minecraft/tags/blocks/wooden_pressure_plates.json
20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/blocks/wooden_buttons.json
36b54a86d2ed41c8a503f7a61817a7a9d7a94536 data/minecraft/tags/blocks/crystal_sound_blocks.json
fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/blocks/doors.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/blocks/wooden_trapdoors.json
357eddf3cee6f16725bed0701d57b2ca3097d74d data/minecraft/tags/blocks/mineable/shovel.json
684c3206f38cc9cc494d5875c5e56aad004486af data/minecraft/tags/blocks/logs.json
5853312830fdd8ee85e2c5b1be3dd4a6357a4971 data/minecraft/tags/blocks/mineable/pickaxe.json
684c3206f38cc9cc494d5875c5e56aad004486af data/hexcasting/tags/blocks/edified_logs.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/minecraft/tags/blocks/planks.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/blocks/trapdoors.json
5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/blocks/wooden_slabs.json
37cff4ce449b8069b59b2327d78e073fc026d348 data/minecraft/tags/blocks/wooden_pressure_plates.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/hexcasting/tags/blocks/edified_planks.json

View file

@ -1,186 +1,186 @@
// 1.19.2 2022-11-09T19:48:37.724413 Recipes
e35c89ccc099c511c9ab321a7490d35f2e8c9353 data/hexcasting/advancements/recipes/hexcasting.creative_tab/amethyst_dust_packing.json
1754e1304908edf58a70fe8548f9d0ede22a1dd3 data/hexcasting/recipes/pride_colorizer_pansexual.json
1315f615ebc6593829bd86318d8eb45c2de68876 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_button.json
28fa66705fcd6dbfa46ec76602497441cde579ef data/hexcasting/advancements/recipes/hexcasting.creative_tab/empty_impetus.json
4ba0fcb9b3142029c36cc48b250b89b0cac3f6de data/hexcasting/recipes/akashic_connector.json
b54339a9e990419e4820491001c4cbdb7aa9fddb data/hexcasting/recipes/artifact.json
d603560d9bbe0bd3e9c0ca5cd502fe874337599e data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_light_gray.json
aa6c75e8834d47b0a144dac7b6448cbaecb7df44 data/hexcasting/recipes/pride_colorizer_aromantic.json
b9202eb55254abe6cbffc6ce73ba9dcf36a84ffe data/hexcasting/advancements/recipes/brainsweep/brainsweep/budding_amethyst.json
527f52ec902b9f456099bebe066b15533fe8cffd data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_pressure_plate.json
4cc110d5ce9831c0072cc2c4fd8f1a6196f42331 data/hexcasting/advancements/recipes/hexcasting.creative_tab/ancient_scroll_paper_lantern.json
79ebc61817f6ef529c385fe3ed3ff9edb0761f96 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_genderfluid.json
783c691f24bc4259ba5da014133763dce26ee4bd data/hexcasting/recipes/crimson_staff.json
f8e027860b2505a7217d1264c5d0b6f7feea0679 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_door.json
c86adafd19871ba67f0b7b693247c0a5bdec1020 data/hexcasting/recipes/brainsweep/impetus_storedplayer.json
36c97b8de7a0b67256e8966eca289a865cb85df5 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_bisexual.json
3de6a907c45a97e163caf043292bb693af58e453 data/hexcasting/advancements/recipes/hexcasting.creative_tab/crimson_staff.json
fccc3e05b011e1fd1a41a0bfca11876d0fb16df2 data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll_small.json
b62b3b67e6a105e1eb47d04c2ededd8d408df7b7 data/hexcasting/advancements/recipes/hexcasting.creative_tab/ancient_scroll_paper.json
04569ccadfd99f203b0485d0c3e877209290f2b3 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_pink.json
48b6d3429e3536a85f3a0e9585a7d252ae0d57a3 data/hexcasting/advancements/recipes/hexcasting.creative_tab/jeweler_hammer.json
6aa3e7825025d055a70a58acd4fd48eef0480721 data/hexcasting/recipes/edified_wood.json
b7250840982952fc23c8b32b77517744329d8d2d data/hexcasting/recipes/spellbook.json
83ec93ac94401b356fbee3d6464f52f151edeac4 data/hexcasting/advancements/recipes/hexcasting.creative_tab/spellbook.json
414d605b72164240bc308444c48ed03571cc0d61 data/hexcasting/advancements/recipes/hexcasting.creative_tab/empty_directrix.json
326925a948aeb17aabafbc25ed2562a257796d29 data/hexcasting/recipes/dye_colorizer_yellow.json
563d6b480a6ebf1c200c2ca7cd62ed305cbf9710 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_lime.json
b640608755649a8bde55a434016b14522fa6d2e0 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_wood.json
9bd09d681a608e465feb6d6a63d0b021920c7a1d data/hexcasting/recipes/brainsweep/directrix_redstone.json
cc89232d202eec019f584e8c5cc044deee76036b data/hexcasting/recipes/amethyst_sconce.json
8c49c1c022cee20fb2a44046425b48cd0e6659af data/hexcasting/advancements/recipes/hexcasting.creative_tab/birch_staff.json
bc91b7e096d8a0033916101f21fa43c06b343e86 data/hexcasting/recipes/dye_colorizer_red.json
323ccf5637e08024ae3984d1dd3585e6af0fd14c data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_demigirl.json
1f04d75a1c713d3c5ac44e62889ce834f12d6234 data/hexcasting/recipes/jeweler_hammer.json
2a1021614882392be78d22cb557e43cbbd9092ca data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_rightclick.json
04d5ceb50171bf1575b4c0145c4acbbc414a6390 data/hexcasting/advancements/recipes/hexcasting.creative_tab/cypher.json
3514bb0e92046ca12dfd10afb3c47084434f84c2 data/hexcasting/recipes/brainsweep/akashic_record.json
dc0fb37084974cf396264d046fa6708338eb0879 data/hexcasting/recipes/pride_colorizer_transgender.json
// 1.19.2 2022-11-21T19:55:21.951767357 Recipes
858dada9c41974f5aa80c66423bf371c9e176a53 data/hexcasting/recipes/pride_colorizer_demigirl.json
6c54952ecbb6899f3291fe72486e7205e6ab76cc data/hexcasting/recipes/pride_colorizer_intersex.json
9c8503715195c4cb2e2d9a1abe4f94df7bb9f4b5 data/hexcasting/advancements/recipes/hexcasting.creative_tab/stonecutting/amethyst_tiles.json
0ed898da60aa78cd526ff4ae0524359891dbd976 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_tile.json
d684142c75bee35e6035d1829e271704d4ccdff3 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_lesbian.json
c8ff04819448a3efb2c031e06045be761db6a2f1 data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll_medium.json
3c552071e6b3cfd4932b8f1e8d8b91aae8ead99d data/hexcasting/advancements/recipes/hexcasting.creative_tab/dark_oak_staff.json
dfc171097bdd8a8f280e6787ea999286deda643e data/hexcasting/advancements/recipes/hexcasting.creative_tab/focus.json
1ba5dada44ad7c008756f0e8e7adfe30e2520239 data/hexcasting/recipes/dye_colorizer_lime.json
a22233090497e1c44082b6eb16ad079d9acc8f7c data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_storedplayer.json
6641b22c79fa29fab15d414afecabd3aa7402b38 data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll_paper_lantern.json
86d3a071eaec779167ca51dafaedde0e705cfb70 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_asexual.json
07902912a9ca6f8da48ed579ec318bb760d4f8df data/hexcasting/recipes/pride_colorizer_nonbinary.json
92d5ec5ddf2b35cc59f5bfe389f80443e7ee1ff8 data/hexcasting/recipes/uuid_colorizer.json
fc0476880c79cf4458dd5b24f77fc980b02534d2 data/hexcasting/recipes/edified_button.json
6e6c73a93e0e06ff399d95e40baf4e06f3a25a0a data/hexcasting/advancements/recipes/hexcasting.creative_tab/slate_block_from_slates.json
64f509c0496204d39c38a4a64a1fbe0f84b9e5ae data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_magenta.json
4f301e8e812f409be41cfddfa74b1fb7c8034edf data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_purple.json
f0852056a692d776bf537c821f3d166c2be88bd8 data/hexcasting/recipes/spruce_staff.json
5ffea2f9ccbb855ab3f5aca9cb572f57f26619ae data/hexcasting/recipes/amethyst_dust_unpacking.json
dc2a9bf96ca9d04ea6bdeb32249322530b5e1cbf data/hexcasting/advancements/recipes/hexcasting.creative_tab/warped_staff.json
a16ce751797baf92c3dd3f125b564e789aeec260 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_planks.json
9d4594ac55f0221fff91bc0a48f54e890edd3596 data/hexcasting/recipes/dark_oak_staff.json
260f89eb21b360ea8b7fdbd23f9977d03ab57149 data/hexcasting/recipes/ancient_scroll_paper_lantern.json
8a9e7aa8d07556649768729348dff5305b84e1b9 data/hexcasting/recipes/edified_door.json
ae676c825f58eefb2bfbbd866db13dbb59deff0e data/hexcasting/recipes/brainsweep/impetus_look.json
3b83dd1c1aa1bcc58e6512bca75c3a6a3b7482b3 data/hexcasting/recipes/edified_tile.json
5902d75cd2474604f2bb1067187ba574eb1e15fc data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_wood.json
d73e5d8fec4d3f7d15888bd292f4ad9c1b37cac5 data/hexcasting/advancements/recipes/hexcasting.creative_tab/ageing_scroll_paper_lantern.json
6f5ee50706640e9be82810e22388fc7b2bce13b1 data/hexcasting/recipes/birch_staff.json
0101f5c24d8beedcc884ce87b052ad4f6884ddc4 data/hexcasting/recipes/akashic_bookshelf.json
3ae790bef91b6ae57ed7e3e792740ea059875293 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_cyan.json
63da3af421dfb38283d750eb3b9761f42e95fb91 data/hexcasting/advancements/recipes/hexcasting.creative_tab/stripped_edified_wood.json
0cb3e2e6e0be9f53811f24ad43bf711d07560210 data/hexcasting/advancements/recipes/hexcasting.creative_tab/acacia_staff.json
25df58c8b78028142c47deb060768d4fbfe2c38e data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_nonbinary.json
0859373b9e60e80f3c8b0962a3bc94903af43d36 data/hexcasting/recipes/stripped_edified_wood.json
013a4b5603757f8610709428dad8de79bd9bd590 data/hexcasting/recipes/dye_colorizer_pink.json
b7d75dcd88e5091ff44eec236531a56e82c7bd91 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_aroace.json
202e70722198141d5dd961bb087a25873e4928af data/hexcasting/recipes/edified_stairs.json
f9e4d9171ffc6a125d9899f1867398acf8037b27 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_agender.json
fa49dab810cff4f827d2662a93fc3439a8e99cba data/hexcasting/recipes/pride_colorizer_genderqueer.json
ad390fe854110e60aec4c805f7bb5fed45b4e5d1 data/hexcasting/advancements/recipes/hexcasting.creative_tab/amethyst_tiles.json
b2496e7ff3b631a148de37896eeb7dbcd2cbf04a data/hexcasting/recipes/scroll_medium.json
e687ceab424098d586f0b67a34fe65bee1f4dfca data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_blue.json
36c3ea4547b49c7553e7024192d5ddf6f2163422 data/hexcasting/recipes/scroll_paper_lantern.json
b6d6716724729f0530a524f92d7e4646455de344 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_red.json
c9c2b33afc4b5de1f10df08d901312ee1ded1c5e data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_pansexual.json
220f4dc7c8f857092bcb85b5ccf8936237ededa4 data/hexcasting/advancements/recipes/hexcasting.creative_tab/amethyst_sconce.json
1c5681b6bf354ce068c51852b51a5aba9ac2d8f9 data/hexcasting/recipes/compat/create/crushing/amethyst_shard.json
b2dc08cc62b9a36d6b034aead99e0b328b5efecb data/hexcasting/recipes/scroll_small.json
4440b41499c9c32e297dc184c39da010ff82ac5e data/hexcasting/advancements/recipes/hexcasting.creative_tab/uuid_colorizer.json
898319b3a4ee7a8d7bd7a4af0313593561ed657e data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll_paper.json
ebfa29e0a62a629afbe18681e09cc7be95a3529e data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_yellow.json
f58700261f72cf87acacf1df0f163890c8b7ae00 data/hexcasting/advancements/recipes/brainsweep/brainsweep/directrix_redstone.json
bc100b94798f0b456877b42a5fc9aee7c4f25218 data/hexcasting/recipes/dye_colorizer_magenta.json
b494dc17959c76857f25368eb845e58e4f8bca92 data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_door.json
1b210391768fede639b29ae6fc5adf2b8b4e64c6 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_brown.json
d75bc1009064769735d46e7f4f32c65d10a470e3 data/hexcasting/recipes/pride_colorizer_asexual.json
a776209b64fea520f6a2fff9f1623e7086939dd9 data/hexcasting/recipes/jungle_staff.json
6978ff90efdd067940caccdd29437d2aefd0fe1f data/hexcasting/recipes/scroll_paper.json
e91b58b8a52d0d69e13102fbf743aab8be177924 data/hexcasting/recipes/pride_colorizer_genderfluid.json
993a613fabd0ee1005bde11ebe92f8046351ba9e data/hexcasting/advancements/recipes/hexcasting.creative_tab/trinket.json
50f5bf4d8a499f87fa2211489624c11cc90a95a6 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_stairs.json
f91ab1d68c575970ef48ad499ec92057a8ee7b2e data/hexcasting/recipes/cypher.json
bb0f91c534c888d1cff8793b49986dce236c7b2d data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_white.json
cd22886924e7aaeb62e8f7da0747cc950af9dc32 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_plural.json
735a7d770f23a02dc4ae93644e7f4c44a32e313a data/hexcasting/recipes/oak_staff.json
a58f37bc66e65c1ac00ba7dbc4d9a7b902f42aad data/hexcasting/advancements/recipes/hexcasting.creative_tab/oak_staff.json
0c72527448454438308ba5a4e99452b193fad421 data/hexcasting/recipes/dye_colorizer_gray.json
17aa26ce6bc9941d1477dee99e514fd66be7f664 data/hexcasting/recipes/pride_colorizer_aroace.json
e0e49c8a9977fe2b0619179b11a4379b5b19ace9 data/hexcasting/advancements/recipes/hexcasting.creative_tab/sub_sandwich.json
437f92b83317beda07c55c122224e6740573a05e data/hexcasting/recipes/scroll.json
2aa2e5c268ae440238eaf4cea20011b0c8f81a49 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_demiboy.json
5627128775e24fb6281a0576a931cfa88a909bc0 data/hexcasting/recipes/slate_block_from_slates.json
3608f0ec056f2c5d29a9a89305218497fd2c4383 data/hexcasting/recipes/stonecutting/amethyst_tiles.json
ef5a19ab2710fd0ce836d767588fe6a54a528a48 data/hexcasting/recipes/dye_colorizer_white.json
e52dbfc2d86bb3e87ff554fc8d5f0d43b7ff334a data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_gray.json
2fa8ff79780daaa523fe9f04a8fa15c186f055c2 data/hexcasting/recipes/dye_colorizer_purple.json
65246cf025a3300dacf9235db546178e83c863e9 data/hexcasting/recipes/pride_colorizer_lesbian.json
8d6f58c45be52e22559fdbc2806ee48ab40d133c data/hexcasting/advancements/recipes/brainsweep/brainsweep/akashic_record.json
4ffed306e5f640054a6f269ae0e548388f087996 data/hexcasting/recipes/warped_staff.json
be7ceaf2b55525f06178fb09070dfeeef8da1c65 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_transgender.json
f0849d723141b9f02798d474da6594f78755dd51 data/hexcasting/recipes/amethyst_tiles.json
2b16fb3f6b4e4e31c5c507e6c0535bd12c7c63a1 data/hexcasting/recipes/dye_colorizer_brown.json
6e692bdb7e797c1d0fffb5fcc90c5a3b28e4aaff data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_aromantic.json
6479526ac6b8732814ea3feb97e877896c17f7b7 data/hexcasting/recipes/edified_trapdoor.json
85ea4913eb07d67a976891e48a32d20879f31eaa data/hexcasting/recipes/dye_colorizer_light_gray.json
a184ee70962538e4f8641c707d6dca8796ca36e7 data/hexcasting/recipes/edified_slab.json
605f921a98b5dabbd80bc762070916e7d6756df6 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_orange.json
12e1ba1ec29bf0eadf1210d2307fab35e9685085 data/hexcasting/recipes/empty_directrix.json
336465276c06fc59be003ccad3d6fc121fa438f5 data/hexcasting/recipes/edified_staff.json
db105c67babb1ffc1bcad53ed1c98d7eb2fee4b1 data/hexcasting/recipes/pride_colorizer_plural.json
aa4a00864f1b22835612fe60a4715250f3ab2126 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_panel.json
90088535c8e4d0beb0725878314c49ac8deb373b data/hexcasting/recipes/amethyst_dust_packing.json
3662834d6e0bac03aba28f0f9d9f07f511492118 data/hexcasting/recipes/lens.json
5ba498c4c19f74cbb456385bccda96d4a8d1d1cc data/hexcasting/advancements/recipes/hexcasting.creative_tab/slate_block.json
0d08dab8c9700c7b5b32ad35e7b665a2e3c2cdc7 data/hexcasting/advancements/recipes/hexcasting.creative_tab/artifact.json
13ca24f9f87a6b34f7717e5c326291079e6db96f data/hexcasting/recipes/sub_sandwich.json
045e4eeefde52c09fd5bc24b8fcbe2a4e81f8bdb data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_intersex.json
f45428f892d2064fafa29ea644eea21354e2e322 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_staff.json
f75c21d35b926a2303d60115a297c387790bbbd9 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_trapdoor.json
12d9ec588869179a8e8a1f4bce718175d57e4a71 data/create/recipes/crushing/amethyst_block.json
108421ab59fc52c69913676abda5e0a045fe1b04 data/hexcasting/recipes/pride_colorizer_gay.json
dfb42a8b723b37df5c8888bdef86a1be35f2de72 data/hexcasting/recipes/pride_colorizer_bisexual.json
13d03da2cfee5c29e5432806189e18eeefb76e11 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_gay.json
122ca20f3a77c1267e4b8c755e9cd66e56734547 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_genderqueer.json
d7f93550b7c25b963eaf34d4d2ab9d9871830983 data/hexcasting/recipes/dye_colorizer_cyan.json
c93cecd3f883e57f3cce7ad3d6aad44000ed541c data/hexcasting/recipes/ancient_scroll_paper.json
9f75d3e93ecbbbf3ed9a92b2943397e09dcae1a9 data/hexcasting/recipes/dye_colorizer_light_blue.json
62bfad9dc29406a9807ea33f866cbdfca32e7d0a data/hexcasting/advancements/recipes/hexcasting.creative_tab/amethyst_dust_unpacking.json
709232dd093e48895014957f2e4ff5a1a76da583 data/create/recipes/crushing/amethyst_cluster.json
0ee8d29cb06065a55017a8fc50576193107f958d data/hexcasting/recipes/dynamic/seal_focus.json
0b8a01eab5d4ce90974c6c53b6d397f8e9398385 data/hexcasting/recipes/slate_block.json
e3416c3e103fe206cbaa352eb5011f81ccfc6aca data/hexcasting/recipes/slate.json
ab26481b45a7f463e2225b9a04d24a1b4d84daef data/hexcasting/recipes/abacus.json
646baa3a1299b4ee296ba0763a858db30e995adb data/hexcasting/recipes/focus.json
4692127dbfe21eab57a6e33b214a3661cf3e6d0f data/hexcasting/recipes/pride_colorizer_demiboy.json
04569ccadfd99f203b0485d0c3e877209290f2b3 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_pink.json
0101f5c24d8beedcc884ce87b052ad4f6884ddc4 data/hexcasting/recipes/akashic_bookshelf.json
f58700261f72cf87acacf1df0f163890c8b7ae00 data/hexcasting/advancements/recipes/brainsweep/brainsweep/directrix_redstone.json
1b510d32bad1a51ad6795fb8e7702d34c8c8cfbe data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_green.json
b185eee3dc066959c2699284eeed8c5c5de80d33 data/hexcasting/recipes/trinket.json
a331f4ce9b8d3565cbb154af4d63279f1e2c7a41 data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_trapdoor.json
a3c7f19df257ee07f0894708b48438fdf3b14a47 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_black.json
bb42a28d7b19f8f8057630f0d2e99b371e93126a data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_light_blue.json
d323e21de69d0606d1fac03fa8820e5857e4e1f1 data/hexcasting/recipes/dynamic/seal_spellbook.json
38e7b64a4a15f1ce496f8c156d7262426f98fbcc data/hexcasting/recipes/acacia_staff.json
8715e71c2fb59ee458ce217040c9a8dd0db04789 data/hexcasting/advancements/recipes/hexcasting.creative_tab/lens.json
0efcdb6cd338f382c823e8599e298322a0080dae data/hexcasting/recipes/edified_panel.json
22ff2d626da7f5fdc1411b4df75a6fc6a0e52df7 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_slab.json
6e8ba1635146314810ce9181c83024c0c0a931f7 data/hexcasting/advancements/recipes/hexcasting.creative_tab/akashic_bookshelf.json
773860888fb2d695b775f3afb93b16f43795bcc6 data/hexcasting/recipes/brainsweep/impetus_rightclick.json
494a76b3cebcd7b0b37c3f2e655d37b3c7fb762b data/hexcasting/advancements/recipes/hexcasting.creative_tab/spruce_staff.json
768d70365c56ef1fbad089d3e3fd68548f964227 data/hexcasting/recipes/dye_colorizer_black.json
e6ba57745f6841c2dcb537ada2475e880ea25186 data/hexcasting/recipes/dye_colorizer_green.json
4bff4a59e32c6d1d99bc3a8abd16cd88c51a8e73 data/hexcasting/recipes/dye_colorizer_orange.json
7caa7a8d9f8b0859f9507376bb715bdbe4b3fb56 data/hexcasting/recipes/dye_colorizer_blue.json
b7fc41f8cfd83a0d138290251d63bb6cc04e0f9a data/hexcasting/recipes/edified_pressure_plate.json
b21f6cbf11e23eac313d68805428cc0da55edb83 data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_log.json
f0a77ba758e649d0c16a8e2d9964d18f95a544f4 data/hexcasting/advancements/recipes/hexcasting.creative_tab/slate.json
7ae2bd282afbf2f460a6bb705fe301a2a11d7835 data/hexcasting/advancements/recipes/hexcasting.creative_tab/akashic_connector.json
63d9172717dd1cbb587fc9d92fd69f47b1bb3307 data/hexcasting/recipes/brainsweep/budding_amethyst.json
da3c95902e93fe82e489ceccc84a56159329e091 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_look.json
c7d28ccf9df6fc46aa142c2e7b176cc0cb5ea62b data/hexcasting/recipes/empty_impetus.json
ae2c6392cc0ec104c4e3019e1824a1e7f811f1de data/hexcasting/advancements/recipes/hexcasting.creative_tab/abacus.json
bd3e10b3d468e48e72ad060b9eb0b9f8f4057bf1 data/hexcasting/recipes/ageing_scroll_paper_lantern.json
182c2b5dd406c80ed957e1b43d554cce1b212d28 data/hexcasting/advancements/recipes/hexcasting.creative_tab/jungle_staff.json
d73e5d8fec4d3f7d15888bd292f4ad9c1b37cac5 data/hexcasting/advancements/recipes/hexcasting.creative_tab/ageing_scroll_paper_lantern.json
b54339a9e990419e4820491001c4cbdb7aa9fddb data/hexcasting/recipes/artifact.json
c3f9cca50935f7abf141825d78b441033fc0dab8 data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll.json
ef5a19ab2710fd0ce836d767588fe6a54a528a48 data/hexcasting/recipes/dye_colorizer_white.json
768d70365c56ef1fbad089d3e3fd68548f964227 data/hexcasting/recipes/dye_colorizer_black.json
dfb42a8b723b37df5c8888bdef86a1be35f2de72 data/hexcasting/recipes/pride_colorizer_bisexual.json
d323e21de69d0606d1fac03fa8820e5857e4e1f1 data/hexcasting/recipes/dynamic/seal_spellbook.json
605f921a98b5dabbd80bc762070916e7d6756df6 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_orange.json
17aa26ce6bc9941d1477dee99e514fd66be7f664 data/hexcasting/recipes/pride_colorizer_aroace.json
6978ff90efdd067940caccdd29437d2aefd0fe1f data/hexcasting/recipes/scroll_paper.json
8d6f58c45be52e22559fdbc2806ee48ab40d133c data/hexcasting/advancements/recipes/brainsweep/brainsweep/akashic_record.json
1754e1304908edf58a70fe8548f9d0ede22a1dd3 data/hexcasting/recipes/pride_colorizer_pansexual.json
92d5ec5ddf2b35cc59f5bfe389f80443e7ee1ff8 data/hexcasting/recipes/uuid_colorizer.json
d684142c75bee35e6035d1829e271704d4ccdff3 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_lesbian.json
dfc171097bdd8a8f280e6787ea999286deda643e data/hexcasting/advancements/recipes/hexcasting.creative_tab/focus.json
e6ba57745f6841c2dcb537ada2475e880ea25186 data/hexcasting/recipes/dye_colorizer_green.json
a3c7f19df257ee07f0894708b48438fdf3b14a47 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_black.json
b9202eb55254abe6cbffc6ce73ba9dcf36a84ffe data/hexcasting/advancements/recipes/brainsweep/brainsweep/budding_amethyst.json
a776209b64fea520f6a2fff9f1623e7086939dd9 data/hexcasting/recipes/jungle_staff.json
4ffed306e5f640054a6f269ae0e548388f087996 data/hexcasting/recipes/warped_staff.json
2b16fb3f6b4e4e31c5c507e6c0535bd12c7c63a1 data/hexcasting/recipes/dye_colorizer_brown.json
f45428f892d2064fafa29ea644eea21354e2e322 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_staff.json
8715e71c2fb59ee458ce217040c9a8dd0db04789 data/hexcasting/advancements/recipes/hexcasting.creative_tab/lens.json
86d3a071eaec779167ca51dafaedde0e705cfb70 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_asexual.json
be7ceaf2b55525f06178fb09070dfeeef8da1c65 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_transgender.json
3608f0ec056f2c5d29a9a89305218497fd2c4383 data/hexcasting/recipes/stonecutting/amethyst_tiles.json
260f89eb21b360ea8b7fdbd23f9977d03ab57149 data/hexcasting/recipes/ancient_scroll_paper_lantern.json
62bfad9dc29406a9807ea33f866cbdfca32e7d0a data/hexcasting/advancements/recipes/hexcasting.creative_tab/amethyst_dust_unpacking.json
4cc110d5ce9831c0072cc2c4fd8f1a6196f42331 data/hexcasting/advancements/recipes/hexcasting.creative_tab/ancient_scroll_paper_lantern.json
1315f615ebc6593829bd86318d8eb45c2de68876 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_button.json
3514bb0e92046ca12dfd10afb3c47084434f84c2 data/hexcasting/recipes/brainsweep/akashic_record.json
b21f6cbf11e23eac313d68805428cc0da55edb83 data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_log.json
1b210391768fede639b29ae6fc5adf2b8b4e64c6 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_brown.json
ae2c6392cc0ec104c4e3019e1824a1e7f811f1de data/hexcasting/advancements/recipes/hexcasting.creative_tab/abacus.json
cd22886924e7aaeb62e8f7da0747cc950af9dc32 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_plural.json
6c54952ecbb6899f3291fe72486e7205e6ab76cc data/hexcasting/recipes/pride_colorizer_intersex.json
cc89232d202eec019f584e8c5cc044deee76036b data/hexcasting/recipes/amethyst_sconce.json
48b6d3429e3536a85f3a0e9585a7d252ae0d57a3 data/hexcasting/advancements/recipes/hexcasting.creative_tab/jeweler_hammer.json
709232dd093e48895014957f2e4ff5a1a76da583 data/create/recipes/crushing/amethyst_cluster.json
bc100b94798f0b456877b42a5fc9aee7c4f25218 data/hexcasting/recipes/dye_colorizer_magenta.json
85ea4913eb07d67a976891e48a32d20879f31eaa data/hexcasting/recipes/dye_colorizer_light_gray.json
7caa7a8d9f8b0859f9507376bb715bdbe4b3fb56 data/hexcasting/recipes/dye_colorizer_blue.json
ad390fe854110e60aec4c805f7bb5fed45b4e5d1 data/hexcasting/advancements/recipes/hexcasting.creative_tab/amethyst_tiles.json
0ed898da60aa78cd526ff4ae0524359891dbd976 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_tile.json
ebfa29e0a62a629afbe18681e09cc7be95a3529e data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_yellow.json
5ba498c4c19f74cbb456385bccda96d4a8d1d1cc data/hexcasting/advancements/recipes/hexcasting.creative_tab/slate_block.json
f8e027860b2505a7217d1264c5d0b6f7feea0679 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_door.json
2aa2e5c268ae440238eaf4cea20011b0c8f81a49 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_demiboy.json
63da3af421dfb38283d750eb3b9761f42e95fb91 data/hexcasting/advancements/recipes/hexcasting.creative_tab/stripped_edified_wood.json
c86adafd19871ba67f0b7b693247c0a5bdec1020 data/hexcasting/recipes/brainsweep/impetus_storedplayer.json
326925a948aeb17aabafbc25ed2562a257796d29 data/hexcasting/recipes/dye_colorizer_yellow.json
2a1021614882392be78d22cb557e43cbbd9092ca data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_rightclick.json
4440b41499c9c32e297dc184c39da010ff82ac5e data/hexcasting/advancements/recipes/hexcasting.creative_tab/uuid_colorizer.json
63d9172717dd1cbb587fc9d92fd69f47b1bb3307 data/hexcasting/recipes/brainsweep/budding_amethyst.json
6e6c73a93e0e06ff399d95e40baf4e06f3a25a0a data/hexcasting/advancements/recipes/hexcasting.creative_tab/slate_block_from_slates.json
3662834d6e0bac03aba28f0f9d9f07f511492118 data/hexcasting/recipes/lens.json
4ba0fcb9b3142029c36cc48b250b89b0cac3f6de data/hexcasting/recipes/akashic_connector.json
1c5681b6bf354ce068c51852b51a5aba9ac2d8f9 data/hexcasting/recipes/compat/create/crushing/amethyst_shard.json
336465276c06fc59be003ccad3d6fc121fa438f5 data/hexcasting/recipes/edified_staff.json
773860888fb2d695b775f3afb93b16f43795bcc6 data/hexcasting/recipes/brainsweep/impetus_rightclick.json
ce0cd4d73792c30dcec2eea306bff44b28cb237f data/hexcasting/recipes/pride_colorizer_agender.json
f91ab1d68c575970ef48ad499ec92057a8ee7b2e data/hexcasting/recipes/cypher.json
a331f4ce9b8d3565cbb154af4d63279f1e2c7a41 data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_trapdoor.json
4f301e8e812f409be41cfddfa74b1fb7c8034edf data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_purple.json
108421ab59fc52c69913676abda5e0a045fe1b04 data/hexcasting/recipes/pride_colorizer_gay.json
f75c21d35b926a2303d60115a297c387790bbbd9 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_trapdoor.json
3b83dd1c1aa1bcc58e6512bca75c3a6a3b7482b3 data/hexcasting/recipes/edified_tile.json
7ae2bd282afbf2f460a6bb705fe301a2a11d7835 data/hexcasting/advancements/recipes/hexcasting.creative_tab/akashic_connector.json
d603560d9bbe0bd3e9c0ca5cd502fe874337599e data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_light_gray.json
da3c95902e93fe82e489ceccc84a56159329e091 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_look.json
8c49c1c022cee20fb2a44046425b48cd0e6659af data/hexcasting/advancements/recipes/hexcasting.creative_tab/birch_staff.json
12e1ba1ec29bf0eadf1210d2307fab35e9685085 data/hexcasting/recipes/empty_directrix.json
898319b3a4ee7a8d7bd7a4af0313593561ed657e data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll_paper.json
0c72527448454438308ba5a4e99452b193fad421 data/hexcasting/recipes/dye_colorizer_gray.json
64f509c0496204d39c38a4a64a1fbe0f84b9e5ae data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_magenta.json
aa6c75e8834d47b0a144dac7b6448cbaecb7df44 data/hexcasting/recipes/pride_colorizer_aromantic.json
a16ce751797baf92c3dd3f125b564e789aeec260 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_planks.json
c8ff04819448a3efb2c031e06045be761db6a2f1 data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll_medium.json
dc2a9bf96ca9d04ea6bdeb32249322530b5e1cbf data/hexcasting/advancements/recipes/hexcasting.creative_tab/warped_staff.json
b62b3b67e6a105e1eb47d04c2ededd8d408df7b7 data/hexcasting/advancements/recipes/hexcasting.creative_tab/ancient_scroll_paper.json
1ba5dada44ad7c008756f0e8e7adfe30e2520239 data/hexcasting/recipes/dye_colorizer_lime.json
4692127dbfe21eab57a6e33b214a3661cf3e6d0f data/hexcasting/recipes/pride_colorizer_demiboy.json
b494dc17959c76857f25368eb845e58e4f8bca92 data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_door.json
36c97b8de7a0b67256e8966eca289a865cb85df5 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_bisexual.json
4bff4a59e32c6d1d99bc3a8abd16cd88c51a8e73 data/hexcasting/recipes/dye_colorizer_orange.json
1f04d75a1c713d3c5ac44e62889ce834f12d6234 data/hexcasting/recipes/jeweler_hammer.json
8a9e7aa8d07556649768729348dff5305b84e1b9 data/hexcasting/recipes/edified_door.json
e52dbfc2d86bb3e87ff554fc8d5f0d43b7ff334a data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_gray.json
b6d6716724729f0530a524f92d7e4646455de344 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_red.json
993a613fabd0ee1005bde11ebe92f8046351ba9e data/hexcasting/advancements/recipes/hexcasting.creative_tab/trinket.json
b2496e7ff3b631a148de37896eeb7dbcd2cbf04a data/hexcasting/recipes/scroll_medium.json
6e8ba1635146314810ce9181c83024c0c0a931f7 data/hexcasting/advancements/recipes/hexcasting.creative_tab/akashic_bookshelf.json
bd3e10b3d468e48e72ad060b9eb0b9f8f4057bf1 data/hexcasting/recipes/ageing_scroll_paper_lantern.json
5627128775e24fb6281a0576a931cfa88a909bc0 data/hexcasting/recipes/slate_block_from_slates.json
6aa3e7825025d055a70a58acd4fd48eef0480721 data/hexcasting/recipes/edified_wood.json
783c691f24bc4259ba5da014133763dce26ee4bd data/hexcasting/recipes/crimson_staff.json
437f92b83317beda07c55c122224e6740573a05e data/hexcasting/recipes/scroll.json
6479526ac6b8732814ea3feb97e877896c17f7b7 data/hexcasting/recipes/edified_trapdoor.json
0cb3e2e6e0be9f53811f24ad43bf711d07560210 data/hexcasting/advancements/recipes/hexcasting.creative_tab/acacia_staff.json
6641b22c79fa29fab15d414afecabd3aa7402b38 data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll_paper_lantern.json
3ae790bef91b6ae57ed7e3e792740ea059875293 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_cyan.json
c7d28ccf9df6fc46aa142c2e7b176cc0cb5ea62b data/hexcasting/recipes/empty_impetus.json
f0a77ba758e649d0c16a8e2d9964d18f95a544f4 data/hexcasting/advancements/recipes/hexcasting.creative_tab/slate.json
f9e4d9171ffc6a125d9899f1867398acf8037b27 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_agender.json
c93cecd3f883e57f3cce7ad3d6aad44000ed541c data/hexcasting/recipes/ancient_scroll_paper.json
12d9ec588869179a8e8a1f4bce718175d57e4a71 data/create/recipes/crushing/amethyst_block.json
ab26481b45a7f463e2225b9a04d24a1b4d84daef data/hexcasting/recipes/abacus.json
fccc3e05b011e1fd1a41a0bfca11876d0fb16df2 data/hexcasting/advancements/recipes/hexcasting.creative_tab/scroll_small.json
38e7b64a4a15f1ce496f8c156d7262426f98fbcc data/hexcasting/recipes/acacia_staff.json
7c7888ba95d1e2e8620a916df546a2b06b592d37 data/hexcasting/recipes/edified_planks.json
0d08dab8c9700c7b5b32ad35e7b665a2e3c2cdc7 data/hexcasting/advancements/recipes/hexcasting.creative_tab/artifact.json
0859373b9e60e80f3c8b0962a3bc94903af43d36 data/hexcasting/recipes/stripped_edified_wood.json
414d605b72164240bc308444c48ed03571cc0d61 data/hexcasting/advancements/recipes/hexcasting.creative_tab/empty_directrix.json
e687ceab424098d586f0b67a34fe65bee1f4dfca data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_blue.json
013a4b5603757f8610709428dad8de79bd9bd590 data/hexcasting/recipes/dye_colorizer_pink.json
202e70722198141d5dd961bb087a25873e4928af data/hexcasting/recipes/edified_stairs.json
6e692bdb7e797c1d0fffb5fcc90c5a3b28e4aaff data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_aromantic.json
b640608755649a8bde55a434016b14522fa6d2e0 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_wood.json
e0e49c8a9977fe2b0619179b11a4379b5b19ace9 data/hexcasting/advancements/recipes/hexcasting.creative_tab/sub_sandwich.json
b2dc08cc62b9a36d6b034aead99e0b328b5efecb data/hexcasting/recipes/scroll_small.json
e3416c3e103fe206cbaa352eb5011f81ccfc6aca data/hexcasting/recipes/slate.json
0b8a01eab5d4ce90974c6c53b6d397f8e9398385 data/hexcasting/recipes/slate_block.json
bb42a28d7b19f8f8057630f0d2e99b371e93126a data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_light_blue.json
2fa8ff79780daaa523fe9f04a8fa15c186f055c2 data/hexcasting/recipes/dye_colorizer_purple.json
dc0fb37084974cf396264d046fa6708338eb0879 data/hexcasting/recipes/pride_colorizer_transgender.json
5902d75cd2474604f2bb1067187ba574eb1e15fc data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_wood.json
07902912a9ca6f8da48ed579ec318bb760d4f8df data/hexcasting/recipes/pride_colorizer_nonbinary.json
f0852056a692d776bf537c821f3d166c2be88bd8 data/hexcasting/recipes/spruce_staff.json
b185eee3dc066959c2699284eeed8c5c5de80d33 data/hexcasting/recipes/trinket.json
65246cf025a3300dacf9235db546178e83c863e9 data/hexcasting/recipes/pride_colorizer_lesbian.json
b7d75dcd88e5091ff44eec236531a56e82c7bd91 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_aroace.json
13ca24f9f87a6b34f7717e5c326291079e6db96f data/hexcasting/recipes/sub_sandwich.json
90088535c8e4d0beb0725878314c49ac8deb373b data/hexcasting/recipes/amethyst_dust_packing.json
220f4dc7c8f857092bcb85b5ccf8936237ededa4 data/hexcasting/advancements/recipes/hexcasting.creative_tab/amethyst_sconce.json
ae676c825f58eefb2bfbbd866db13dbb59deff0e data/hexcasting/recipes/brainsweep/impetus_look.json
f0849d723141b9f02798d474da6594f78755dd51 data/hexcasting/recipes/amethyst_tiles.json
a184ee70962538e4f8641c707d6dca8796ca36e7 data/hexcasting/recipes/edified_slab.json
b7250840982952fc23c8b32b77517744329d8d2d data/hexcasting/recipes/spellbook.json
22ff2d626da7f5fdc1411b4df75a6fc6a0e52df7 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_slab.json
3de6a907c45a97e163caf043292bb693af58e453 data/hexcasting/advancements/recipes/hexcasting.creative_tab/crimson_staff.json
494a76b3cebcd7b0b37c3f2e655d37b3c7fb762b data/hexcasting/advancements/recipes/hexcasting.creative_tab/spruce_staff.json
83ec93ac94401b356fbee3d6464f52f151edeac4 data/hexcasting/advancements/recipes/hexcasting.creative_tab/spellbook.json
9d4594ac55f0221fff91bc0a48f54e890edd3596 data/hexcasting/recipes/dark_oak_staff.json
0efcdb6cd338f382c823e8599e298322a0080dae data/hexcasting/recipes/edified_panel.json
527f52ec902b9f456099bebe066b15533fe8cffd data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_pressure_plate.json
563d6b480a6ebf1c200c2ca7cd62ed305cbf9710 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_lime.json
d7f93550b7c25b963eaf34d4d2ab9d9871830983 data/hexcasting/recipes/dye_colorizer_cyan.json
9c8503715195c4cb2e2d9a1abe4f94df7bb9f4b5 data/hexcasting/advancements/recipes/hexcasting.creative_tab/stonecutting/amethyst_tiles.json
e91b58b8a52d0d69e13102fbf743aab8be177924 data/hexcasting/recipes/pride_colorizer_genderfluid.json
0ee8d29cb06065a55017a8fc50576193107f958d data/hexcasting/recipes/dynamic/seal_focus.json
b7fc41f8cfd83a0d138290251d63bb6cc04e0f9a data/hexcasting/recipes/edified_pressure_plate.json
122ca20f3a77c1267e4b8c755e9cd66e56734547 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_genderqueer.json
3c552071e6b3cfd4932b8f1e8d8b91aae8ead99d data/hexcasting/advancements/recipes/hexcasting.creative_tab/dark_oak_staff.json
a58f37bc66e65c1ac00ba7dbc4d9a7b902f42aad data/hexcasting/advancements/recipes/hexcasting.creative_tab/oak_staff.json
13d03da2cfee5c29e5432806189e18eeefb76e11 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_gay.json
fc0476880c79cf4458dd5b24f77fc980b02534d2 data/hexcasting/recipes/edified_button.json
a22233090497e1c44082b6eb16ad079d9acc8f7c data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_storedplayer.json
aa4a00864f1b22835612fe60a4715250f3ab2126 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_panel.json
6f5ee50706640e9be82810e22388fc7b2bce13b1 data/hexcasting/recipes/birch_staff.json
e35c89ccc099c511c9ab321a7490d35f2e8c9353 data/hexcasting/advancements/recipes/hexcasting.creative_tab/amethyst_dust_packing.json
9bd09d681a608e465feb6d6a63d0b021920c7a1d data/hexcasting/recipes/brainsweep/directrix_redstone.json
735a7d770f23a02dc4ae93644e7f4c44a32e313a data/hexcasting/recipes/oak_staff.json
d75bc1009064769735d46e7f4f32c65d10a470e3 data/hexcasting/recipes/pride_colorizer_asexual.json
36c3ea4547b49c7553e7024192d5ddf6f2163422 data/hexcasting/recipes/scroll_paper_lantern.json
50f5bf4d8a499f87fa2211489624c11cc90a95a6 data/hexcasting/advancements/recipes/hexcasting.creative_tab/edified_stairs.json
646baa3a1299b4ee296ba0763a858db30e995adb data/hexcasting/recipes/focus.json
db105c67babb1ffc1bcad53ed1c98d7eb2fee4b1 data/hexcasting/recipes/pride_colorizer_plural.json
bc91b7e096d8a0033916101f21fa43c06b343e86 data/hexcasting/recipes/dye_colorizer_red.json
04d5ceb50171bf1575b4c0145c4acbbc414a6390 data/hexcasting/advancements/recipes/hexcasting.creative_tab/cypher.json
323ccf5637e08024ae3984d1dd3585e6af0fd14c data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_demigirl.json
79ebc61817f6ef529c385fe3ed3ff9edb0761f96 data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_genderfluid.json
045e4eeefde52c09fd5bc24b8fcbe2a4e81f8bdb data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_intersex.json
5ffea2f9ccbb855ab3f5aca9cb572f57f26619ae data/hexcasting/recipes/amethyst_dust_unpacking.json
c9c2b33afc4b5de1f10df08d901312ee1ded1c5e data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_pansexual.json
fa49dab810cff4f827d2662a93fc3439a8e99cba data/hexcasting/recipes/pride_colorizer_genderqueer.json
25df58c8b78028142c47deb060768d4fbfe2c38e data/hexcasting/advancements/recipes/hexcasting.creative_tab/pride_colorizer_nonbinary.json
28fa66705fcd6dbfa46ec76602497441cde579ef data/hexcasting/advancements/recipes/hexcasting.creative_tab/empty_impetus.json
182c2b5dd406c80ed957e1b43d554cce1b212d28 data/hexcasting/advancements/recipes/hexcasting.creative_tab/jungle_staff.json

View file

@ -4,292 +4,192 @@ import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.misc.ScrollQuantity;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import io.github.fablabsmc.fablabs.api.fiber.v1.builder.ConfigTreeBuilder;
import io.github.fablabsmc.fablabs.api.fiber.v1.exception.ValueDeserializationException;
import io.github.fablabsmc.fablabs.api.fiber.v1.schema.type.derived.ConfigTypes;
import io.github.fablabsmc.fablabs.api.fiber.v1.serialization.FiberSerialization;
import io.github.fablabsmc.fablabs.api.fiber.v1.serialization.JanksonValueSerializer;
import io.github.fablabsmc.fablabs.api.fiber.v1.tree.ConfigTree;
import io.github.fablabsmc.fablabs.api.fiber.v1.tree.PropertyMirror;
import me.shedaniel.autoconfig.AutoConfig;
import me.shedaniel.autoconfig.ConfigData;
import me.shedaniel.autoconfig.annotation.Config;
import me.shedaniel.autoconfig.annotation.ConfigEntry;
import me.shedaniel.autoconfig.serializer.JanksonConfigSerializer;
import me.shedaniel.autoconfig.serializer.PartitioningSerializer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import java.io.*;
import java.nio.file.*;
import java.util.List;
import static at.petrak.hexcasting.api.mod.HexConfig.anyMatch;
import static at.petrak.hexcasting.api.mod.HexConfig.noneMatch;
// https://github.com/VazkiiMods/Botania/blob/1.18.x/Fabric/src/main/java/vazkii/botania/fabric/FiberBotaniaConfig.java
public class FabricHexConfig {
private static final Common COMMON = new Common();
private static final Client CLIENT = new Client();
private static final Server SERVER = new Server();
@Config(name = HexAPI.MOD_ID)
@Config.Gui.Background("minecraft:textures/block/calcite.png")
@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"})
private static void writeDefaultConfig(ConfigTree config, Path path, JanksonValueSerializer serializer) {
try (OutputStream s = new BufferedOutputStream(
Files.newOutputStream(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW))) {
FiberSerialization.serialize(config, s, serializer);
} catch (FileAlreadyExistsException ignored) {
} catch (IOException e) {
HexAPI.LOGGER.error("Error writing default config", e);
}
}
private static void setupConfig(ConfigTree config, Path p, JanksonValueSerializer serializer) {
writeDefaultConfig(config, p, serializer);
try (InputStream s = new BufferedInputStream(
Files.newInputStream(p, StandardOpenOption.READ, StandardOpenOption.CREATE))) {
FiberSerialization.deserialize(config, s, serializer);
} catch (IOException | ValueDeserializationException e) {
HexAPI.LOGGER.error("Error loading config from {}", p, e);
}
}
public class FabricHexConfig extends PartitioningSerializer.GlobalData {
@ConfigEntry.Category("common")
@ConfigEntry.Gui.TransitiveObject
private final Common common = new Common();
@ConfigEntry.Category("client")
@ConfigEntry.Gui.TransitiveObject
private final Client client = new Client();
@ConfigEntry.Category("server")
@ConfigEntry.Gui.TransitiveObject
private final Server server = new Server();
public static void setup() {
try {
Files.createDirectory(Paths.get("config"));
} catch (FileAlreadyExistsException ignored) {
} catch (IOException e) {
HexAPI.LOGGER.warn("Failed to make config dir", e);
}
var serializer = new JanksonValueSerializer(false);
var common = COMMON.configure(ConfigTree.builder());
setupConfig(common, Paths.get("config", HexAPI.MOD_ID + "-common.json5"), serializer);
HexConfig.setCommon(COMMON);
AutoConfig.register(FabricHexConfig.class, PartitioningSerializer.wrap(JanksonConfigSerializer::new));
var instance = AutoConfig.getConfigHolder(FabricHexConfig.class).getConfig();
HexConfig.setCommon(instance.common);
// We care about the client only on the *physical* client ...
if (IXplatAbstractions.INSTANCE.isPhysicalClient()) {
var client = CLIENT.configure(ConfigTree.builder());
setupConfig(client, Paths.get("config", HexAPI.MOD_ID + "-client.json5"), serializer);
HexConfig.setClient(CLIENT);
HexConfig.setClient(instance.client);
}
// but we care about the server on the *logical* server
// i believe this should Just Work without a guard? assuming we don't access it from the client ever
var server = SERVER.configure(ConfigTree.builder());
setupConfig(server, Paths.get("config", HexAPI.MOD_ID + "-server.json5"), serializer);
HexConfig.setServer(SERVER);
HexConfig.setServer(instance.server);
}
private static final class Common implements HexConfig.CommonConfigAccess {
private final PropertyMirror<Integer> dustMediaAmount = PropertyMirror.create(ConfigTypes.NATURAL);
private final PropertyMirror<Integer> shardMediaAmount = PropertyMirror.create(ConfigTypes.NATURAL);
private final PropertyMirror<Integer> chargedCrystalMediaAmount = PropertyMirror.create(ConfigTypes.NATURAL);
private final PropertyMirror<Double> mediaToHealthRate = PropertyMirror.create(
ConfigTypes.DOUBLE.withMinimum(0d));
@Config(name = "common")
private static final class Common implements HexConfig.CommonConfigAccess, ConfigData {
@ConfigEntry.Gui.Tooltip
private int dustMediaAmount = DEFAULT_DUST_MEDIA_AMOUNT;
@ConfigEntry.Gui.Tooltip
private int shardMediaAmount = DEFAULT_SHARD_MEDIA_AMOUNT;
@ConfigEntry.Gui.Tooltip
private int chargedCrystalMediaAmount = DEFAULT_CHARGED_MEDIA_AMOUNT;
@ConfigEntry.Gui.Tooltip
private double mediaToHealthRate = DEFAULT_MEDIA_TO_HEALTH_RATE;
public ConfigTree configure(ConfigTreeBuilder bob) {
bob.fork("Media Amounts")
.beginValue("dustMediaAmount", ConfigTypes.NATURAL, DEFAULT_DUST_MEDIA_AMOUNT)
.withComment("How much media a single Amethyst Dust item is worth")
.finishValue(dustMediaAmount::mirror)
.beginValue("shardMediaAmount", ConfigTypes.NATURAL, DEFAULT_SHARD_MEDIA_AMOUNT)
.withComment("How much media a single Amethyst Shard item is worth")
.finishValue(shardMediaAmount::mirror)
.beginValue("chargedCrystalMediaAmount", ConfigTypes.NATURAL, DEFAULT_CHARGED_MEDIA_AMOUNT)
.withComment("How much media a single Charged Amethyst Crystal item is worth")
.finishValue(chargedCrystalMediaAmount::mirror)
.beginValue("mediaToHealthRate", ConfigTypes.DOUBLE, DEFAULT_MEDIA_TO_HEALTH_RATE)
.withComment("How many points of media a half-heart is worth when casting from HP")
.finishValue(mediaToHealthRate::mirror)
.finishBranch();
return bob.build();
@Override
public void validatePostLoad() throws ValidationException {
this.dustMediaAmount = Math.max(this.dustMediaAmount, 0);
this.shardMediaAmount = Math.max(this.shardMediaAmount, 0);
this.chargedCrystalMediaAmount = Math.max(this.chargedCrystalMediaAmount, 0);
this.mediaToHealthRate = Math.max(this.mediaToHealthRate, 0);
}
@Override
public int dustMediaAmount() {
return dustMediaAmount.getValue();
return dustMediaAmount;
}
@Override
public int shardMediaAmount() {
return shardMediaAmount.getValue();
return shardMediaAmount;
}
@Override
public int chargedCrystalMediaAmount() {
return chargedCrystalMediaAmount.getValue();
return chargedCrystalMediaAmount;
}
@Override
public double mediaToHealthRate() {
return mediaToHealthRate.getValue();
return mediaToHealthRate;
}
}
private static final class Client implements HexConfig.ClientConfigAccess {
private final PropertyMirror<Double> patternPointSpeedMultiplier = PropertyMirror.create(
ConfigTypes.DOUBLE.withMinimum(0d));
private final PropertyMirror<Boolean> ctrlTogglesOffStrokeOrder = PropertyMirror.create(ConfigTypes.BOOLEAN);
private final PropertyMirror<Boolean> invertSpellbookScrollDirection = PropertyMirror.create(ConfigTypes.BOOLEAN);
private final PropertyMirror<Boolean> invertAbacusScrollDirection = PropertyMirror.create(ConfigTypes.BOOLEAN);
private final PropertyMirror<Double> gridSnapThreshold = PropertyMirror.create(
ConfigTypes.DOUBLE.withMinimum(0.5).withMaximum(1.0));
public ConfigTree configure(ConfigTreeBuilder bob) {
bob
.beginValue("patternPointSpeedMultiplier", ConfigTypes.DOUBLE, DEFAULT_PATTERN_POINT_SPEED_MULTIPLIER)
.withComment("How fast the point showing you the stroke order on patterns moves. Must be positive.")
.finishValue(patternPointSpeedMultiplier::mirror)
.beginValue("ctrlTogglesOffStrokeOrder", ConfigTypes.BOOLEAN, DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER)
.withComment("Whether the ctrl key will instead turn *off* the color gradient on patterns")
.finishValue(ctrlTogglesOffStrokeOrder::mirror)
.beginValue("invertSpellbookScrollDirection", ConfigTypes.BOOLEAN, DEFAULT_INVERT_SPELLBOOK_SCROLL)
.withComment("Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and vice versa")
.finishValue(invertSpellbookScrollDirection::mirror)
.beginValue("invertAbacusScrollDirection", ConfigTypes.BOOLEAN, DEFAULT_INVERT_ABACUS_SCROLL)
.withComment("Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa")
.finishValue(invertAbacusScrollDirection::mirror)
.beginValue("gridSnapThreshold", ConfigTypes.DOUBLE, DEFAULT_GRID_SNAP_THRESHOLD)
.withComment(
"When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 means 50% of the way. Valid range is 0.5 to 1.0, and may cause client crashes if set above or below those values.")
.finishValue(gridSnapThreshold::mirror);
return bob.build();
}
@Config(name = "client")
private static final class Client implements HexConfig.ClientConfigAccess, ConfigData {
@ConfigEntry.Gui.Tooltip
private boolean ctrlTogglesOffStrokeOrder = DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER;
@ConfigEntry.Gui.Tooltip
private boolean invertSpellbookScrollDirection = DEFAULT_INVERT_SPELLBOOK_SCROLL;
@ConfigEntry.Gui.Tooltip
private boolean invertAbacusScrollDirection = DEFAULT_INVERT_SPELLBOOK_SCROLL;
@ConfigEntry.Gui.Tooltip
private double gridSnapThreshold = DEFAULT_GRID_SNAP_THRESHOLD;
@Override
public double patternPointSpeedMultiplier() {
return patternPointSpeedMultiplier.getValue();
public void validatePostLoad() throws ValidationException {
this.gridSnapThreshold = Mth.clamp(this.gridSnapThreshold, 0.5, 1.0);
}
@Override
public boolean ctrlTogglesOffStrokeOrder() {
return ctrlTogglesOffStrokeOrder.getValue();
return ctrlTogglesOffStrokeOrder;
}
@Override
public boolean invertSpellbookScrollDirection() {
return invertSpellbookScrollDirection.getValue();
return invertSpellbookScrollDirection;
}
@Override
public boolean invertAbacusScrollDirection() {
return invertAbacusScrollDirection.getValue();
return invertAbacusScrollDirection;
}
@Override
public double gridSnapThreshold() {
return gridSnapThreshold.getValue();
return gridSnapThreshold;
}
}
private static final class Server implements HexConfig.ServerConfigAccess {
private final PropertyMirror<Integer> opBreakHarvestLevel = PropertyMirror.create(
ConfigTypes.INTEGER.withValidRange(0, 4, 1));
private final PropertyMirror<Integer> maxRecurseDepth = PropertyMirror.create(ConfigTypes.NATURAL);
private final PropertyMirror<Integer> maxSpellCircleLength = PropertyMirror.create(
ConfigTypes.INTEGER.withMinimum(4));
private final PropertyMirror<List<String>> actionDenyList = PropertyMirror.create(
ConfigTypes.makeList(ConfigTypes.STRING));
private final PropertyMirror<List<String>> circleActionDenyList = PropertyMirror.create(
ConfigTypes.makeList(ConfigTypes.STRING));
private final PropertyMirror<Boolean> villagersOffendedByMindMurder = PropertyMirror.create(
ConfigTypes.BOOLEAN);
private final PropertyMirror<List<String>> fewScrollTables = PropertyMirror.create(
ConfigTypes.makeList(ConfigTypes.STRING));
private final PropertyMirror<List<String>> someScrollTables = PropertyMirror.create(
ConfigTypes.makeList(ConfigTypes.STRING));
private final PropertyMirror<List<String>> manyScrollTables = PropertyMirror.create(
ConfigTypes.makeList(ConfigTypes.STRING));
@Config(name = "server")
private static final class Server implements HexConfig.ServerConfigAccess, ConfigData {
@ConfigEntry.BoundedDiscrete(min = 0, max = 4)
@ConfigEntry.Gui.Tooltip
private int opBreakHarvestLevel = DEFAULT_OP_BREAK_HARVEST_LEVEL;
@ConfigEntry.Gui.Tooltip
private int maxRecurseDepth = DEFAULT_MAX_RECURSE_DEPTH;
@ConfigEntry.Gui.Tooltip
private int maxSpellCircleLength = DEFAULT_MAX_SPELL_CIRCLE_LENGTH;
@ConfigEntry.Gui.Tooltip
private List<String> actionDenyList = List.of();
@ConfigEntry.Gui.Tooltip
private List<String> circleActionDenyList = List.of();
@ConfigEntry.Gui.Tooltip
private boolean villagersOffendedByMindMurder = DEFAULT_VILLAGERS_DISLIKE_MIND_MURDER;
public ConfigTree configure(ConfigTreeBuilder bob) {
bob.fork("Spells")
.beginValue("maxRecurseDepth", ConfigTypes.NATURAL, DEFAULT_MAX_RECURSE_DEPTH)
.withComment("How many times a spell can recursively cast other spells")
.finishValue(maxRecurseDepth::mirror)
@ConfigEntry.Gui.Tooltip
private List<String> fewScrollTables = DEFAULT_FEW_SCROLL_TABLES;
@ConfigEntry.Gui.Tooltip
private List<String> someScrollTables = DEFAULT_SOME_SCROLL_TABLES;
@ConfigEntry.Gui.Tooltip
private List<String> manyScrollTables = DEFAULT_MANY_SCROLL_TABLES;
.beginValue("opBreakHarvestLevel", ConfigTypes.NATURAL, DEFAULT_OP_BREAK_HARVEST_LEVEL)
.withComment("The harvest level of the Break Block spell.\n" +
"0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite.")
.finishValue(opBreakHarvestLevel::mirror)
.finishBranch()
.fork("Spell Circles")
.beginValue("maxSpellCircleLength", ConfigTypes.NATURAL, DEFAULT_MAX_SPELL_CIRCLE_LENGTH)
.withComment("The maximum number of slates in a spell circle. Must be at least 4.")
.finishValue(maxSpellCircleLength::mirror)
.beginValue("circleActionDenyList", ConfigTypes.makeList(ConfigTypes.STRING), List.of())
.withComment(
"Resource locations of disallowed actions within circles. Trying to cast one of these in a circle will result in a mishap.")
.finishValue(circleActionDenyList::mirror)
.finishBranch()
.beginValue("actionDenyList", ConfigTypes.makeList(ConfigTypes.STRING), List.of())
.withComment(
"Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.")
.finishValue(actionDenyList::mirror)
.beginValue("villagersOffendedByMindMurder", ConfigTypes.BOOLEAN, true)
.withComment("Should villagers take offense when you flay the mind of their fellow villagers?")
.finishValue(villagersOffendedByMindMurder::mirror)
.fork("Scrolls in Loot")
.beginValue("fewScrollTables", ConfigTypes.makeList(ConfigTypes.STRING), DEFAULT_FEW_SCROLL_TABLES)
.withComment("Which loot tables should a small number of Ancient Scrolls be injected into?")
.finishValue(fewScrollTables::mirror)
.beginValue("someScrollTables", ConfigTypes.makeList(ConfigTypes.STRING), DEFAULT_SOME_SCROLL_TABLES)
.withComment("Which loot tables should a decent number of Ancient Scrolls be injected into?")
.finishValue(someScrollTables::mirror)
.beginValue("manyScrollTables", ConfigTypes.makeList(ConfigTypes.STRING), DEFAULT_MANY_SCROLL_TABLES)
.withComment("Which loot tables should a huge number of Ancient Scrolls be injected into?")
.finishValue(manyScrollTables::mirror)
.finishBranch();
return bob.build();
@Override
public void validatePostLoad() throws ValidationException {
this.maxRecurseDepth = Math.max(this.maxRecurseDepth, 0);
this.maxSpellCircleLength = Math.max(this.maxSpellCircleLength, 4);
}
@Override
public int opBreakHarvestLevelBecauseForgeThoughtItWasAGoodIdeaToImplementHarvestTiersUsingAnHonestToGodTopoSort() {
return opBreakHarvestLevel.getValue();
return opBreakHarvestLevel;
}
@Override
public int maxRecurseDepth() {
return maxRecurseDepth.getValue();
return maxRecurseDepth;
}
@Override
public int maxSpellCircleLength() {
return maxSpellCircleLength.getValue();
return maxSpellCircleLength;
}
@Override
public boolean isActionAllowed(ResourceLocation actionID) {
return noneMatch(actionDenyList.getValue(), actionID);
return noneMatch(actionDenyList, actionID);
}
@Override
public boolean isActionAllowedInCircles(ResourceLocation actionID) {
return noneMatch(circleActionDenyList.getValue(), actionID);
return noneMatch(circleActionDenyList, actionID);
}
@Override
public boolean doVillagersTakeOffenseAtMindMurder() {
return villagersOffendedByMindMurder.getValue();
return villagersOffendedByMindMurder;
}
@Override
public ScrollQuantity scrollsForLootTable(ResourceLocation lootTable) {
if (anyMatch(fewScrollTables.getValue(), lootTable)) {
if (anyMatch(fewScrollTables, lootTable)) {
return ScrollQuantity.FEW;
} else if (anyMatch(someScrollTables.getValue(), lootTable)) {
} else if (anyMatch(someScrollTables, lootTable)) {
return ScrollQuantity.SOME;
} else if (anyMatch(manyScrollTables.getValue(), lootTable)) {
} else if (anyMatch(manyScrollTables, lootTable)) {
return ScrollQuantity.MANY;
}
return ScrollQuantity.NONE;

View file

@ -12,6 +12,7 @@ import at.petrak.hexcasting.common.entities.HexEntities
import at.petrak.hexcasting.common.items.ItemJewelerHammer
import at.petrak.hexcasting.common.items.ItemLens
import at.petrak.hexcasting.common.lib.*
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import at.petrak.hexcasting.common.loot.HexLootHandler
import at.petrak.hexcasting.common.misc.AkashicTreeGrower
import at.petrak.hexcasting.common.misc.Brainsweeping

View file

@ -1,6 +1,7 @@
package at.petrak.hexcasting.fabric.cc;
import at.petrak.hexcasting.api.addldata.ADMediaHolder;
import at.petrak.hexcasting.api.addldata.ItemDelegatingEntityIotaHolder;
import at.petrak.hexcasting.api.item.ColorizerItem;
import at.petrak.hexcasting.api.item.HexHolderItem;
import at.petrak.hexcasting.api.item.IotaHolderItem;
@ -10,6 +11,7 @@ import at.petrak.hexcasting.api.spell.iota.DoubleIota;
import at.petrak.hexcasting.common.entities.EntityWallScroll;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.fabric.cc.adimpl.*;
import dev.onyxstudios.cca.api.v3.component.ComponentFactory;
import dev.onyxstudios.cca.api.v3.component.ComponentKey;
import dev.onyxstudios.cca.api.v3.component.ComponentRegistry;
import dev.onyxstudios.cca.api.v3.entity.EntityComponentFactoryRegistry;
@ -18,11 +20,14 @@ import dev.onyxstudios.cca.api.v3.entity.RespawnCopyStrategy;
import dev.onyxstudios.cca.api.v3.item.ItemComponentFactoryRegistry;
import dev.onyxstudios.cca.api.v3.item.ItemComponentInitializer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.Items;
import java.util.function.Function;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class HexCardinalComponents implements EntityComponentInitializer, ItemComponentInitializer {
@ -59,9 +64,12 @@ public class HexCardinalComponents implements EntityComponentInitializer, ItemCo
registry.registerFor(ServerPlayer.class, HARNESS, CCHarness::new);
registry.registerFor(ServerPlayer.class, PATTERNS, CCPatterns::new);
registry.registerFor(ItemEntity.class, IOTA_HOLDER, CCEntityIotaHolder.EntityItemDelegating::new);
registry.registerFor(ItemFrame.class, IOTA_HOLDER, CCEntityIotaHolder.ItemFrameDelegating::new);
registry.registerFor(EntityWallScroll.class, IOTA_HOLDER, CCEntityIotaHolder.ScrollDelegating::new);
registry.registerFor(ItemEntity.class, IOTA_HOLDER, wrapItemEntityDelegate(
ItemDelegatingEntityIotaHolder.ToItemEntity::new));
registry.registerFor(ItemFrame.class, IOTA_HOLDER, wrapItemEntityDelegate(
ItemDelegatingEntityIotaHolder.ToItemFrame::new));
registry.registerFor(EntityWallScroll.class, IOTA_HOLDER,
wrapItemEntityDelegate(ItemDelegatingEntityIotaHolder.ToWallScroll::new));
}
@Override
@ -87,4 +95,9 @@ public class HexCardinalComponents implements EntityComponentInitializer, ItemCo
registry.register(i -> i instanceof HexHolderItem, HEX_HOLDER, CCHexHolder.ItemBased::new);
}
private <E extends Entity> ComponentFactory<E, CCEntityIotaHolder.Wrapper> wrapItemEntityDelegate(Function<E,
ItemDelegatingEntityIotaHolder> make) {
return e -> new CCEntityIotaHolder.Wrapper(make.apply(e));
}
}

View file

@ -1,18 +1,12 @@
package at.petrak.hexcasting.fabric.cc.adimpl;
import at.petrak.hexcasting.api.addldata.ItemDelegatingEntityIotaHolder;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.common.entities.EntityWallScroll;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Supplier;
public abstract class CCEntityIotaHolder implements CCIotaHolder {
@Override
public void writeToNbt(@NotNull CompoundTag tag) {
@ -24,58 +18,32 @@ public abstract class CCEntityIotaHolder implements CCIotaHolder {
// NO-OP
}
public static class ItemDelegating extends CCEntityIotaHolder {
private final Supplier<ItemStack> item;
public static class Wrapper extends CCEntityIotaHolder {
private final ItemDelegatingEntityIotaHolder inner;
public ItemDelegating(Supplier<ItemStack> stackSupplier) {
this.item = stackSupplier;
public Wrapper(ItemDelegatingEntityIotaHolder inner) {
this.inner = inner;
}
@Override
public @Nullable CompoundTag readIotaTag() {
var delegate = IXplatAbstractions.INSTANCE.findDataHolder(item.get());
return delegate == null ? null : delegate.readIotaTag();
return inner.readIotaTag();
}
@Override
public boolean writeIota(@Nullable Iota datum, boolean simulate) {
var delegate = IXplatAbstractions.INSTANCE.findDataHolder(item.get());
return delegate != null && delegate.writeIota(datum, simulate);
public boolean writeIota(@Nullable Iota iota, boolean simulate) {
return inner.writeIota(iota, simulate);
}
@Override
public @Nullable Iota readIota(ServerLevel world) {
var delegate = IXplatAbstractions.INSTANCE.findDataHolder(item.get());
return delegate == null ? null : delegate.readIota(world);
return inner.readIota(world);
}
@Override
public @Nullable Iota emptyIota() {
var delegate = IXplatAbstractions.INSTANCE.findDataHolder(item.get());
return delegate == null ? null : delegate.emptyIota();
}
}
public static class EntityItemDelegating extends ItemDelegating {
public EntityItemDelegating(ItemEntity entity) {
super(entity::getItem);
}
}
public static class ItemFrameDelegating extends ItemDelegating {
public ItemFrameDelegating(ItemFrame entity) {
super(entity::getItem);
}
}
public static class ScrollDelegating extends ItemDelegating {
public ScrollDelegating(EntityWallScroll entity) {
super(() -> entity.scroll);
}
@Override
public boolean writeIota(@Nullable Iota datum, boolean simulate) {
return false;
return inner.emptyIota();
}
}
}

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.fabric.cc.adimpl;
import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.fabric.cc.HexCardinalComponents;
import dev.onyxstudios.cca.api.v3.item.ItemComponent;
import net.minecraft.nbt.CompoundTag;

View file

@ -0,0 +1,16 @@
package at.petrak.hexcasting.fabric.interop;
import at.petrak.hexcasting.fabric.FabricHexConfig;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import me.shedaniel.autoconfig.AutoConfig;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public class ModMenuInterop implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return parent -> AutoConfig.getConfigScreen(FabricHexConfig.class, parent).get();
}
}

View file

@ -11,6 +11,7 @@ import at.petrak.hexcasting.api.player.FlightAbility;
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
import at.petrak.hexcasting.api.spell.casting.sideeffects.EvalSound;
import at.petrak.hexcasting.api.spell.iota.IotaType;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.network.IMessage;
@ -24,6 +25,7 @@ import at.petrak.hexcasting.mixin.accessor.AccessorVillager;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import at.petrak.hexcasting.xplat.IXplatTags;
import at.petrak.hexcasting.xplat.Platform;
import com.google.common.base.Suppliers;
import com.jamieswhiteshirt.reachentityattributes.ReachEntityAttributes;
import com.mojang.serialization.Lifecycle;
import net.fabricmc.api.EnvType;
@ -79,6 +81,7 @@ import virtuoel.pehkui.api.ScaleTypes;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Stream;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
@ -258,7 +261,7 @@ public class FabricXplatImpl implements IXplatAbstractions {
@Override
public <T extends BlockEntity> BlockEntityType<T> createBlockEntityType(BiFunction<BlockPos, BlockState, T> func,
Block... blocks) {
Block... blocks) {
return FabricBlockEntityTypeBuilder.create(func::apply, blocks).build();
}
@ -409,17 +412,27 @@ public class FabricXplatImpl implements IXplatAbstractions {
return namespace;
}
private static Registry<IotaType<?>> IOTA_TYPE_REGISTRY = null;
private static final Supplier<Registry<IotaType<?>>> IOTA_TYPE_REGISTRY = Suppliers.memoize(() ->
FabricRegistryBuilder.from(new DefaultedRegistry<IotaType<?>>(
HexAPI.MOD_ID + ":null", ResourceKey.createRegistryKey(modLoc("iota_type")),
Lifecycle.stable(), null))
.buildAndRegister()
);
private static final Supplier<Registry<EvalSound>> EVAL_SOUNDS_REGISTRY = Suppliers.memoize(() ->
FabricRegistryBuilder.from(new DefaultedRegistry<EvalSound>(
HexAPI.MOD_ID + ":nothing", ResourceKey.createRegistryKey(modLoc("eval_sound")),
Lifecycle.stable(), null))
.buildAndRegister()
);
@Override
public Registry<IotaType<?>> getIotaTypeRegistry() {
if (IOTA_TYPE_REGISTRY == null) {
IOTA_TYPE_REGISTRY = FabricRegistryBuilder.from(new DefaultedRegistry<IotaType<?>>(
HexAPI.MOD_ID + ":null", ResourceKey.createRegistryKey(modLoc("iota_type")),
Lifecycle.stable(), null))
.buildAndRegister();
}
return IOTA_TYPE_REGISTRY;
return IOTA_TYPE_REGISTRY.get();
}
@Override
public Registry<EvalSound> getEvalSoundRegistry() {
return EVAL_SOUNDS_REGISTRY.get();
}
@Override

View file

@ -2,7 +2,6 @@
"schemaVersion": 1,
"id": "hexcasting",
"version": "${version}",
"name": "Hex Casting",
"description": "Cast powerful Hexes on the fly by drawing patterns with a staff.",
"authors": [
@ -12,17 +11,21 @@
"homepage": "https://www.curseforge.com/minecraft/mc-mods/hexcasting",
"sources": "https://github.com/gamma-delta/HexMod"
},
"license": "MIT",
"icon": "logo.png",
"environment": "*",
"entrypoints": {
"main": [
{"adapter": "kotlin", "value": "at.petrak.hexcasting.fabric.FabricHexInitializer"}
{
"adapter": "kotlin",
"value": "at.petrak.hexcasting.fabric.FabricHexInitializer"
}
],
"client": [
{"adapter": "kotlin", "value": "at.petrak.hexcasting.fabric.FabricHexClientInitializer"}
{
"adapter": "kotlin",
"value": "at.petrak.hexcasting.fabric.FabricHexClientInitializer"
}
],
"fabric-datagen": [
"at.petrak.hexcasting.fabric.datagen.HexFabricDataGenerators"
@ -32,6 +35,9 @@
],
"emi": [
"at.petrak.hexcasting.fabric.interop.emi.HexEMIPlugin"
],
"modmenu": [
"at.petrak.hexcasting.fabric.interop.ModMenuInterop"
]
},
"mixins": [
@ -39,23 +45,20 @@
"fabricasting.mixins.json"
],
"accessWidener": "fabricasting.accesswidener",
"depends": {
"minecraft": "=1.19.2",
"java": ">=17",
"fabricloader": ">=0.14",
"fabric": ">=0.64",
"fabric-language-kotlin": ">=1.7.4+kotlin.1.6.21",
"patchouli": ">=1.19.2-77",
"paucal": "0.5.x"
"paucal": "0.5.x",
"cloth-config": "8.2.x"
},
"suggests": {
"gravitychanger": "0.7.21+fabric",
"pehkui": "3.6.0+1.14.4-1.19"
},
"custom": {
"cardinal-components": [
"hexcasting:brainswept",
@ -64,7 +67,6 @@
"hexcasting:flight",
"hexcasting:harness",
"hexcasting:patterns",
"hexcasting:colorizer",
"hexcasting:iota_holder",
"hexcasting:media_holder",

View file

@ -50,28 +50,25 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
}
public static class Client implements HexConfig.ClientConfigAccess {
private static ForgeConfigSpec.DoubleValue patternPointSpeedMultiplier;
private static ForgeConfigSpec.BooleanValue ctrlTogglesOffStrokeOrder;
private static ForgeConfigSpec.BooleanValue invertSpellbookScrollDirection;
private static ForgeConfigSpec.BooleanValue invertAbacusScrollDirection;
private static ForgeConfigSpec.DoubleValue gridSnapThreshold;
public Client(ForgeConfigSpec.Builder builder) {
patternPointSpeedMultiplier = builder.comment(
"How fast the point showing you the stroke order on patterns moves")
.defineInRange("patternPointSpeedMultiplier", DEFAULT_PATTERN_POINT_SPEED_MULTIPLIER, 0.0,
Double.POSITIVE_INFINITY);
ctrlTogglesOffStrokeOrder = builder.comment(
"Whether the ctrl key will instead turn *off* the color gradient on patterns")
.define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER);
invertSpellbookScrollDirection = builder.comment(
"Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and vice versa")
"Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " +
"vice versa")
.define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL);
invertAbacusScrollDirection = builder.comment(
"Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa")
.define("invertAbacusScrollDirection", DEFAULT_INVERT_ABACUS_SCROLL);
gridSnapThreshold = builder.comment(
"When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 means 50% of the way.")
"When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 " +
"means 50% of the way.")
.defineInRange("gridSnapThreshold", DEFAULT_GRID_SNAP_THRESHOLD, 0.5, 1.0);
}
@ -85,11 +82,6 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
return invertAbacusScrollDirection.get();
}
@Override
public double patternPointSpeedMultiplier() {
return patternPointSpeedMultiplier.get();
}
@Override
public boolean ctrlTogglesOffStrokeOrder() {
return ctrlTogglesOffStrokeOrder.get();
@ -131,7 +123,8 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
.defineInRange("maxSpellCircleLength", DEFAULT_MAX_SPELL_CIRCLE_LENGTH, 4, Integer.MAX_VALUE);
circleActionDenyList = builder.comment(
"Resource locations of disallowed actions within circles. Trying to cast one of these in a circle will result in a mishap.")
"Resource locations of disallowed actions within circles. Trying to cast one of these in a circle" +
" will result in a mishap.")
.defineList("circleActionDenyList", List.of(),
obj -> obj instanceof String s && ResourceLocation.isValidResourceLocation(s));
builder.pop();
@ -210,7 +203,8 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
// then we are in develop env AND this is being called in the new world screen (it loads datapacks for
// world generation options)
// config values don't exist yet because config is per-world on Forge, and in dev it throws an exn
// (in release it just silently returns default, which is expected behavior here, but the comment suggests
// (in release it just silently returns default, which is expected behavior here, but the comment
// suggests
// it will start throwing at some point soon.)
}
return ScrollQuantity.NONE;

View file

@ -13,6 +13,7 @@ import at.petrak.hexcasting.common.entities.HexEntities;
import at.petrak.hexcasting.common.items.ItemJewelerHammer;
import at.petrak.hexcasting.common.items.ItemLens;
import at.petrak.hexcasting.common.lib.*;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.common.loot.HexLootHandler;
import at.petrak.hexcasting.common.misc.AkashicTreeGrower;
import at.petrak.hexcasting.common.misc.Brainsweeping;
@ -131,9 +132,12 @@ public class ForgeHexInitializer {
HexComposting.setup();
HexStrippables.init();
RegisterPatterns.registerPatterns();
// Forge does not strictly require TreeGrowers to initialize during early game stages, unlike Fabric and Quilt.
// However, all launcher panic if the same resource is registered twice. But do need blocks and items to be completely initialized.
// Explicitly calling here avoids potential confusion, or reliance on tricks that may fail under compiler optimization.
// Forge does not strictly require TreeGrowers to initialize during early game stages, unlike Fabric
// and Quilt.
// However, all launcher panic if the same resource is registered twice. But do need blocks and
// items to be completely initialized.
// Explicitly calling here avoids potential confusion, or reliance on tricks that may fail under
// compiler optimization.
AkashicTreeGrower.init();
HexInterop.init();
@ -143,7 +147,8 @@ public class ForgeHexInitializer {
modBus.addListener((RegisterEvent evt) -> {
if (evt.getRegistryKey().equals(Registry.ITEM_REGISTRY)) {
CraftingHelper.register(ForgeUnsealedIngredient.ID, ForgeUnsealedIngredient.Serializer.INSTANCE);
CraftingHelper.register(ForgeModConditionalIngredient.ID, ForgeModConditionalIngredient.Serializer.INSTANCE);
CraftingHelper.register(ForgeModConditionalIngredient.ID,
ForgeModConditionalIngredient.Serializer.INSTANCE);
HexStatistics.register();
HexLootFunctions.registerSerializers((lift, id) ->
Registry.register(Registry.LOOT_FUNCTION_TYPE, id, lift));

View file

@ -1,9 +1,6 @@
package at.petrak.hexcasting.forge.cap;
import at.petrak.hexcasting.api.addldata.ADColorizer;
import at.petrak.hexcasting.api.addldata.ADHexHolder;
import at.petrak.hexcasting.api.addldata.ADIotaHolder;
import at.petrak.hexcasting.api.addldata.ADMediaHolder;
import at.petrak.hexcasting.api.addldata.*;
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus;
import at.petrak.hexcasting.api.item.ColorizerItem;
import at.petrak.hexcasting.api.item.HexHolderItem;
@ -11,21 +8,17 @@ import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.item.MediaHolderItem;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.api.spell.iota.DoubleIota;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.common.entities.EntityWallScroll;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.forge.cap.adimpl.*;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
@ -36,11 +29,8 @@ import net.minecraftforge.event.AttachCapabilitiesEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.UUID;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import java.util.function.Supplier;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
@ -84,47 +74,51 @@ public class ForgeCapabilityHandler {
if (stack.getItem() instanceof MediaHolderItem holder) {
evt.addCapability(MEDIA_STORAGE_CAP,
provide(stack, HexCapabilities.MEDIA, () -> new ItemBasedMediaHolder(holder, stack)));
provide(stack, HexCapabilities.MEDIA, () -> new CapItemMediaHolder(holder, stack)));
} else if (stack.is(HexItems.AMETHYST_DUST)) {
evt.addCapability(MEDIA_STATIC_CAP, provide(stack, HexCapabilities.MEDIA, () ->
new StaticMediaHolder(HexConfig.common()::dustMediaAmount, ADMediaHolder.AMETHYST_DUST_PRIORITY,
new CapStaticMediaHolder(HexConfig.common()::dustMediaAmount, ADMediaHolder.AMETHYST_DUST_PRIORITY,
stack)));
} else if (stack.is(Items.AMETHYST_SHARD)) {
evt.addCapability(MEDIA_STATIC_CAP, provide(stack, HexCapabilities.MEDIA, () -> new StaticMediaHolder(
evt.addCapability(MEDIA_STATIC_CAP, provide(stack, HexCapabilities.MEDIA, () -> new CapStaticMediaHolder(
HexConfig.common()::shardMediaAmount, ADMediaHolder.AMETHYST_SHARD_PRIORITY, stack)));
} else if (stack.is(HexItems.CHARGED_AMETHYST)) {
evt.addCapability(MEDIA_STATIC_CAP,
provide(stack, HexCapabilities.MEDIA, () -> new StaticMediaHolder(
provide(stack, HexCapabilities.MEDIA, () -> new CapStaticMediaHolder(
HexConfig.common()::chargedCrystalMediaAmount, ADMediaHolder.CHARGED_AMETHYST_PRIORITY, stack)));
}
if (stack.getItem() instanceof IotaHolderItem holder) {
evt.addCapability(IOTA_STORAGE_CAP,
provide(stack, HexCapabilities.IOTA, () -> new ItemBasedIotaHolder(holder, stack)));
provide(stack, HexCapabilities.IOTA, () -> new CapItemIotaHolder(holder, stack)));
} else if (stack.is(Items.PUMPKIN_PIE)) {
// haha yes
evt.addCapability(IOTA_STATIC_CAP, provide(stack, HexCapabilities.IOTA, () ->
new StaticIotaHolder((s) -> new DoubleIota(Math.PI * s.getCount()), stack)));
new CapStaticIotaHolder((s) -> new DoubleIota(Math.PI * s.getCount()), stack)));
}
if (stack.getItem() instanceof HexHolderItem holder) {
evt.addCapability(HEX_HOLDER_CAP,
provide(stack, HexCapabilities.STORED_HEX, () -> new ItemBasedHexHolder(holder, stack)));
provide(stack, HexCapabilities.STORED_HEX, () -> new CapItemHexHolder(holder, stack)));
}
if (stack.getItem() instanceof ColorizerItem colorizer) {
evt.addCapability(PIGMENT_CAP,
provide(stack, HexCapabilities.COLOR, () -> new ItemBasedColorizer(colorizer, stack)));
provide(stack, HexCapabilities.COLOR, () -> new CapItemColorizer(colorizer, stack)));
}
}
public static void attachEntityCaps(AttachCapabilitiesEvent<Entity> evt) {
if (evt.getObject() instanceof ItemEntity item) {
evt.addCapability(IOTA_STORAGE_CAP, delegateTo(item::getItem)); // Delegate to the item
} else if (evt.getObject() instanceof ItemFrame frame) {
evt.addCapability(IOTA_STORAGE_CAP, delegateTo(frame::getItem));
} else if (evt.getObject() instanceof EntityWallScroll scroll) {
evt.addCapability(IOTA_STORAGE_CAP, delegateTo(() -> scroll.scroll));
var entity = evt.getObject();
if (entity instanceof ItemEntity item) {
evt.addCapability(IOTA_STORAGE_CAP, wrapItemEntityDelegate(item,
ItemDelegatingEntityIotaHolder.ToItemEntity::new));
} else if (entity instanceof ItemFrame frame) {
evt.addCapability(IOTA_STORAGE_CAP, wrapItemEntityDelegate(frame,
ItemDelegatingEntityIotaHolder.ToItemFrame::new));
} else if (entity instanceof EntityWallScroll scroll) {
evt.addCapability(IOTA_STORAGE_CAP, wrapItemEntityDelegate(scroll,
ItemDelegatingEntityIotaHolder.ToWallScroll::new));
}
}
@ -135,22 +129,20 @@ public class ForgeCapabilityHandler {
}
}
private static ICapabilityProvider delegateTo(Supplier<ICapabilityProvider> provider) {
return new ICapabilityProvider() {
@NotNull
@Override
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
var providerInst = provider.get();
return providerInst == null ? LazyOptional.empty() : providerInst.getCapability(cap, side);
}
};
// i do not know why we need super here
private static <E extends Entity> SimpleProvider<? super CapEntityIotaHolder.Wrapper> wrapItemEntityDelegate(E entity,
Function<E, ItemDelegatingEntityIotaHolder> make) {
return provide(entity, HexCapabilities.IOTA,
() -> new CapEntityIotaHolder.Wrapper(make.apply(entity)));
}
private static <CAP> SimpleProvider<CAP> provide(Entity entity, Capability<CAP> capability, NonNullSupplier<CAP> supplier) {
private static <CAP> SimpleProvider<CAP> provide(Entity entity, Capability<CAP> capability,
NonNullSupplier<CAP> supplier) {
return provide(entity::isRemoved, capability, supplier);
}
private static <CAP> SimpleProvider<CAP> provide(BlockEntity be, Capability<CAP> capability, NonNullSupplier<CAP> supplier) {
private static <CAP> SimpleProvider<CAP> provide(BlockEntity be, Capability<CAP> capability,
NonNullSupplier<CAP> supplier) {
return provide(be::isRemoved, capability, supplier);
}
@ -179,197 +171,4 @@ public class ForgeCapabilityHandler {
}
}
private record StaticMediaHolder(Supplier<Integer> baseWorth,
int consumptionPriority,
ItemStack stack) implements ADMediaHolder {
@Override
public int getMedia() {
return baseWorth.get() * stack.getCount();
}
@Override
public int getMaxMedia() {
return getMedia();
}
@Override
public void setMedia(int media) {
// NO-OP
}
@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 withdrawMedia(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 record ItemBasedMediaHolder(MediaHolderItem holder,
ItemStack stack) implements ADMediaHolder {
@Override
public int getMedia() {
return holder.getMedia(stack);
}
@Override
public int getMaxMedia() {
return holder.getMaxMedia(stack);
}
@Override
public void setMedia(int media) {
holder.setMedia(stack, media);
}
@Override
public boolean canRecharge() {
return holder.canRecharge(stack);
}
@Override
public boolean canProvide() {
return holder.canProvideMedia(stack);
}
@Override
public int getConsumptionPriority() {
return 40;
}
@Override
public boolean canConstructBattery() {
return false;
}
@Override
public int withdrawMedia(int cost, boolean simulate) {
return holder.withdrawMedia(stack, cost, simulate);
}
@Override
public int insertMedia(int amount, boolean simulate) {
return holder.insertMedia(stack, amount, simulate);
}
}
private record StaticIotaHolder(Function<ItemStack, Iota> provider,
ItemStack stack) implements ADIotaHolder {
@Override
public @Nullable
CompoundTag readIotaTag() {
var iota = provider.apply(stack);
return iota == null ? null : HexIotaTypes.serialize(iota);
}
@Override
public @Nullable
Iota readIota(ServerLevel world) {
return provider.apply(stack);
}
@Override
public boolean writeIota(@Nullable Iota iota, boolean simulate) {
return false;
}
}
private record ItemBasedIotaHolder(IotaHolderItem holder,
ItemStack stack) implements ADIotaHolder {
@Override
public @Nullable
CompoundTag readIotaTag() {
return holder.readIotaTag(stack);
}
@Override
public @Nullable
Iota readIota(ServerLevel world) {
return holder.readIota(stack, world);
}
@Override
public @Nullable
Iota emptyIota() {
return holder.emptyIota(stack);
}
@Override
public boolean writeIota(@Nullable Iota iota, boolean simulate) {
if (!holder.canWrite(stack, iota)) {
return false;
}
if (!simulate) {
holder.writeDatum(stack, iota);
}
return true;
}
}
private record ItemBasedHexHolder(HexHolderItem holder,
ItemStack stack) implements ADHexHolder {
@Override
public boolean canDrawMediaFromInventory() {
return holder.canDrawMediaFromInventory(stack);
}
@Override
public boolean hasHex() {
return holder.hasHex(stack);
}
@Override
public @Nullable List<Iota> getHex(ServerLevel level) {
return holder.getHex(stack, level);
}
@Override
public void writeHex(List<Iota> patterns, int media) {
holder.writeHex(stack, patterns, media);
}
@Override
public void clearHex() {
holder.clearHex(stack);
}
}
private record ItemBasedColorizer(ColorizerItem holder,
ItemStack stack) implements ADColorizer {
@Override
public int color(UUID owner, float time, Vec3 position) {
return holder.color(stack, owner, time, position);
}
}
}

View file

@ -0,0 +1,39 @@
package at.petrak.hexcasting.forge.cap.adimpl;
import at.petrak.hexcasting.api.addldata.ADIotaHolder;
import at.petrak.hexcasting.api.addldata.ItemDelegatingEntityIotaHolder;
import at.petrak.hexcasting.api.spell.iota.Iota;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;
public abstract class CapEntityIotaHolder implements ADIotaHolder {
public static class Wrapper extends CapEntityIotaHolder {
private final ItemDelegatingEntityIotaHolder inner;
public Wrapper(ItemDelegatingEntityIotaHolder inner) {
this.inner = inner;
}
@Override
public @Nullable CompoundTag readIotaTag() {
return inner.readIotaTag();
}
@Override
public boolean writeIota(@Nullable Iota iota, boolean simulate) {
return inner.writeIota(iota, simulate);
}
@Override
public @Nullable Iota readIota(ServerLevel world) {
return inner.readIota(world);
}
@Override
public @Nullable Iota emptyIota() {
return inner.emptyIota();
}
}
}

View file

@ -0,0 +1,16 @@
package at.petrak.hexcasting.forge.cap.adimpl;
import at.petrak.hexcasting.api.addldata.ADColorizer;
import at.petrak.hexcasting.api.item.ColorizerItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import java.util.UUID;
public record CapItemColorizer(ColorizerItem holder,
ItemStack stack) implements ADColorizer {
@Override
public int color(UUID owner, float time, Vec3 position) {
return holder.color(stack, owner, time, position);
}
}

View file

@ -0,0 +1,39 @@
package at.petrak.hexcasting.forge.cap.adimpl;
import at.petrak.hexcasting.api.addldata.ADHexHolder;
import at.petrak.hexcasting.api.item.HexHolderItem;
import at.petrak.hexcasting.api.spell.iota.Iota;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public record CapItemHexHolder(HexHolderItem holder,
ItemStack stack) implements ADHexHolder {
@Override
public boolean canDrawMediaFromInventory() {
return holder.canDrawMediaFromInventory(stack);
}
@Override
public boolean hasHex() {
return holder.hasHex(stack);
}
@Override
public @Nullable List<Iota> getHex(ServerLevel level) {
return holder.getHex(stack, level);
}
@Override
public void writeHex(List<Iota> patterns, int media) {
holder.writeHex(stack, patterns, media);
}
@Override
public void clearHex() {
holder.clearHex(stack);
}
}

View file

@ -0,0 +1,42 @@
package at.petrak.hexcasting.forge.cap.adimpl;
import at.petrak.hexcasting.api.addldata.ADIotaHolder;
import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.spell.iota.Iota;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
public record CapItemIotaHolder(IotaHolderItem holder,
ItemStack stack) implements ADIotaHolder {
@Override
public @Nullable
CompoundTag readIotaTag() {
return holder.readIotaTag(stack);
}
@Override
public @Nullable
Iota readIota(ServerLevel world) {
return holder.readIota(stack, world);
}
@Override
public @Nullable
Iota emptyIota() {
return holder.emptyIota(stack);
}
@Override
public boolean writeIota(@Nullable Iota iota, boolean simulate) {
if (!holder.canWrite(stack, iota)) {
return false;
}
if (!simulate) {
holder.writeDatum(stack, iota);
}
return true;
}
}

View file

@ -0,0 +1,57 @@
package at.petrak.hexcasting.forge.cap.adimpl;
import at.petrak.hexcasting.api.addldata.ADMediaHolder;
import at.petrak.hexcasting.api.item.MediaHolderItem;
import net.minecraft.world.item.ItemStack;
/**
* Things that read/write media amounts from an itemstack
*/
public record CapItemMediaHolder(MediaHolderItem holder,
ItemStack stack) implements ADMediaHolder {
@Override
public int getMedia() {
return holder.getMedia(stack);
}
@Override
public int getMaxMedia() {
return holder.getMaxMedia(stack);
}
@Override
public void setMedia(int media) {
holder.setMedia(stack, media);
}
@Override
public boolean canRecharge() {
return holder.canRecharge(stack);
}
@Override
public boolean canProvide() {
return holder.canProvideMedia(stack);
}
@Override
public int getConsumptionPriority() {
return 40;
}
@Override
public boolean canConstructBattery() {
return false;
}
@Override
public int withdrawMedia(int cost, boolean simulate) {
return holder.withdrawMedia(stack, cost, simulate);
}
@Override
public int insertMedia(int amount, boolean simulate) {
return holder.insertMedia(stack, amount, simulate);
}
}

View file

@ -0,0 +1,33 @@
package at.petrak.hexcasting.forge.cap.adimpl;
import at.petrak.hexcasting.api.addldata.ADIotaHolder;
import at.petrak.hexcasting.api.spell.iota.Iota;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
public record CapStaticIotaHolder(Function<ItemStack, Iota> provider,
ItemStack stack) implements ADIotaHolder {
@Override
public @Nullable
CompoundTag readIotaTag() {
var iota = provider.apply(stack);
return iota == null ? null : HexIotaTypes.serialize(iota);
}
@Override
public @Nullable
Iota readIota(ServerLevel world) {
return provider.apply(stack);
}
@Override
public boolean writeIota(@Nullable Iota iota, boolean simulate) {
return false;
}
}

View file

@ -0,0 +1,62 @@
package at.petrak.hexcasting.forge.cap.adimpl;
import at.petrak.hexcasting.api.addldata.ADMediaHolder;
import net.minecraft.world.item.ItemStack;
import java.util.function.Supplier;
/**
* Things that always hold a constant amount of media, like amethyst
*/
public record CapStaticMediaHolder(Supplier<Integer> baseWorth,
int consumptionPriority,
ItemStack stack) implements ADMediaHolder {
@Override
public int getMedia() {
return baseWorth.get() * stack.getCount();
}
@Override
public int getMaxMedia() {
return getMedia();
}
@Override
public void setMedia(int media) {
// NO-OP
}
@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 withdrawMedia(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;
}
}

View file

@ -12,10 +12,12 @@ import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.api.spell.casting.CastingContext;
import at.petrak.hexcasting.api.spell.casting.CastingHarness;
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
import at.petrak.hexcasting.api.spell.casting.sideeffects.EvalSound;
import at.petrak.hexcasting.api.spell.iota.IotaType;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexIotaTypes;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.common.network.IMessage;
import at.petrak.hexcasting.forge.cap.CapSyncers;
import at.petrak.hexcasting.forge.cap.HexCapabilities;
@ -30,6 +32,7 @@ import at.petrak.hexcasting.mixin.accessor.AccessorVillager;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import at.petrak.hexcasting.xplat.IXplatTags;
import at.petrak.hexcasting.xplat.Platform;
import com.google.common.base.Suppliers;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
@ -83,6 +86,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
import static net.minecraftforge.fluids.capability.IFluidHandler.FluidAction.EXECUTE;
@ -317,7 +321,7 @@ public class ForgeXplatImpl implements IXplatAbstractions {
@Override
public <T extends BlockEntity> BlockEntityType<T> createBlockEntityType(BiFunction<BlockPos, BlockState, T> func,
Block... blocks) {
Block... blocks) {
return BlockEntityType.Builder.of(func::apply, blocks).build(null);
}
@ -414,16 +418,25 @@ public class ForgeXplatImpl implements IXplatAbstractions {
return namespace;
}
private static Registry<IotaType<?>> IOTA_TYPE_REGISTRY = null;
private static final Supplier<Registry<IotaType<?>>> IOTA_TYPE_REGISTRY = Suppliers.memoize(() ->
ForgeAccessorRegistry.hex$registerDefaulted(
ResourceKey.createRegistryKey(modLoc("iota_type")),
HexAPI.MOD_ID + ":null", registry -> HexIotaTypes.NULL)
);
private static final Supplier<Registry<EvalSound>> EVAL_SOUND_REGISTRY = Suppliers.memoize(() ->
ForgeAccessorRegistry.hex$registerDefaulted(
ResourceKey.createRegistryKey(modLoc("eval_sound")),
HexAPI.MOD_ID + ":nothing", registry -> HexEvalSounds.NOTHING)
);
@Override
public Registry<IotaType<?>> getIotaTypeRegistry() {
if (IOTA_TYPE_REGISTRY == null) {
IOTA_TYPE_REGISTRY = ForgeAccessorRegistry.hex$registerDefaulted(
ResourceKey.createRegistryKey(modLoc("iota_type")),
HexAPI.MOD_ID + ":null", registry -> HexIotaTypes.NULL);
}
return IOTA_TYPE_REGISTRY;
return IOTA_TYPE_REGISTRY.get();
}
@Override
public Registry<EvalSound> getEvalSoundRegistry() {
return EVAL_SOUND_REGISTRY.get();
}
@Override

View file

@ -10,7 +10,7 @@ jetbrainsAnnotationsVersion=23.0.0
minecraftVersion=1.19.2
kotlinVersion=1.7.20
modVersion=0.11.0
modVersion=0.10.1
paucalVersion=0.5.0
patchouliVersion=77