Merge remote-tracking branch 'origin/main' into eval/cc

This commit is contained in:
Alwinfy 2022-11-22 00:31:38 -05:00
commit 1da56cd2dc
No known key found for this signature in database
GPG key ID: 2CCB99445F0C949E
126 changed files with 1946 additions and 1511 deletions

0
Common/logs/latest.log Normal file
View file

View file

@ -34,7 +34,7 @@ public class PatternRegistry {
new ConcurrentHashMap<>();
public static void mapPattern(HexPattern pattern, ResourceLocation id,
Action action) throws RegisterPatternException {
Action action) throws RegisterPatternException {
mapPattern(pattern, id, action, false);
}
@ -42,7 +42,7 @@ public class PatternRegistry {
* Associate a given angle signature with a SpellOperator.
*/
public static void mapPattern(HexPattern pattern, ResourceLocation id, Action action,
boolean isPerWorld) throws RegisterPatternException {
boolean isPerWorld) throws RegisterPatternException {
if (actionLookup.containsKey(id)) {
throw new RegisterPatternException("The operator with id `%s` was already registered to: %s", id,
actionLookup.get(id));
@ -83,7 +83,7 @@ public class PatternRegistry {
* Internal use only.
*/
public static Pair<Action, ResourceLocation> matchPatternAndID(HexPattern pat,
ServerLevel overworld) throws MishapInvalidPattern {
ServerLevel overworld) throws MishapInvalidPattern {
// Pipeline:
// patterns are registered here every time the game boots
// when we try to look
@ -232,13 +232,13 @@ public class PatternRegistry {
/**
* Maps angle sigs to resource locations and their preferred start dir so we can look them up in the main registry
* Save this on the world in case the random algorithm changes.
*/
public static class Save extends SavedData {
private static final String TAG_OP_ID = "op_id";
private static final String TAG_START_DIR = "start_dir";
// TODO: this is slightly weird that we save it *on* the world
// might it be better to recalculate it every time the world loads?
// Maps hex signatures to (op ids, canonical start dir)
private Map<String, Pair<ResourceLocation, HexDir>> lookup;
private boolean missingEntries;
@ -279,7 +279,7 @@ public class PatternRegistry {
public CompoundTag save(CompoundTag tag) {
this.lookup.forEach((sig, rhs) -> {
var entry = new CompoundTag();
entry.putString(TAG_OP_ID, sig.toString());
entry.putString(TAG_OP_ID, rhs.getFirst().toString());
entry.putInt(TAG_START_DIR, rhs.getSecond().ordinal());
tag.put(sig, entry);
});

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;
@ -86,12 +86,18 @@ public interface IotaHolderItem {
return HexIotaTypes.getColor(tag);
}
/**
* Write {@code null} to indicate erasing
*/
boolean canWrite(ItemStack stack, @Nullable Iota iota);
/**
* Write {@code null} to indicate erasing
*/
void writeDatum(ItemStack stack, @Nullable Iota iota);
static void appendHoverText(IotaHolderItem self, ItemStack stack, List<Component> components,
TooltipFlag flag) {
TooltipFlag flag) {
var datumTag = self.readIotaTag(stack);
if (datumTag != null) {
var cmp = HexIotaTypes.getDisplay(datumTag);

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
@ -20,7 +26,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
@ -76,13 +83,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)
}
@ -92,10 +99,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
@ -115,7 +123,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.
@ -124,8 +132,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) {
@ -147,23 +169,24 @@ 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 if (iota is ContinuationIota) {
ctx.incDepth()
CastResult(
iota.continuation,
return CastResult(
iota.continuation!!,
null,
ResolvedPatternType.EVALUATED,
listOf(),
EvalSound.GENERIC
HexEvalSounds.HERMES
)
} else {
CastResult(
return CastResult(
continuation,
null,
ResolvedPatternType.INVALID, // Should never matter
@ -173,7 +196,7 @@ class CastingHarness private constructor(
Mishap.Context(HexPattern(HexDir.WEST), null)
)
),
EvalSound.MISHAP
HexEvalSounds.MISHAP
)
}
} catch (mishap: Mishap) {
@ -190,7 +213,7 @@ class CastingHarness private constructor(
)
)
),
EvalSound.MISHAP
HexEvalSounds.MISHAP
)
} catch (exception: Exception) {
// This means something very bad has happened
@ -208,7 +231,7 @@ class CastingHarness private constructor(
)
)
),
EvalSound.MISHAP
HexEvalSounds.MISHAP
)
}
}
@ -282,20 +305,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(
@ -312,7 +337,7 @@ class CastingHarness private constructor(
null,
mishap.resolutionType(ctx),
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, actionIdPair?.first))),
EvalSound.MISHAP
HexEvalSounds.MISHAP
)
}
}
@ -320,7 +345,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) {
@ -328,14 +353,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(
@ -392,6 +409,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()
@ -401,6 +419,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--
@ -425,6 +444,7 @@ class CastingHarness private constructor(
) to ResolvedPatternType.ESCAPED
}
}
else -> {
val newParens = this.parenthesized.toMutableList()
newParens.add(iota)
@ -448,14 +468,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
import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.api.utils.getList

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,8 +1,8 @@
package at.petrak.hexcasting.api.spell.iota;
import at.petrak.hexcasting.api.spell.casting.SpellContinuation;
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation;
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.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

@ -10,14 +10,16 @@ import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.be.BlockEntityAkashicBookshelfRenderer;
import at.petrak.hexcasting.client.be.BlockEntitySlateRenderer;
import at.petrak.hexcasting.client.entity.WallScrollRenderer;
import at.petrak.hexcasting.client.particles.ConjureParticle;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf;
import at.petrak.hexcasting.common.entities.HexEntities;
import at.petrak.hexcasting.common.items.*;
import at.petrak.hexcasting.common.items.magic.ItemMediaBattery;
import at.petrak.hexcasting.common.items.magic.ItemPackagedHex;
import at.petrak.hexcasting.common.lib.*;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import at.petrak.hexcasting.common.lib.HexBlocks;
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;
import net.minecraft.ChatFormatting;
@ -107,11 +109,19 @@ public class RegisterClientStuff {
x.registerEntityRenderer(HexEntities.WALL_SCROLL, WallScrollRenderer::new);
// for (var tex : new ResourceLocation[]{
// PatternTooltipComponent.PRISTINE_BG,
// PatternTooltipComponent.ANCIENT_BG,
// PatternTooltipComponent.SLATE_BG
// }) {
// Minecraft.getInstance().getTextureManager().bindForSetup(tex);
// }
addScryingLensStuff();
}
public static void registerColorProviders(BiConsumer<ItemColor, Item> itemColorRegistry,
BiConsumer<BlockColor, Block> blockColorRegistry) {
BiConsumer<BlockColor, Block> blockColorRegistry) {
itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.FOCUS::getColor), HexItems.FOCUS);
itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.SPELLBOOK::getColor), HexItems.SPELLBOOK);
@ -315,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 {
@ -324,7 +335,7 @@ public class RegisterClientStuff {
int z = pos.getZ();
boolean descending = true;
RailShape shape = state.getValue(PoweredRailBlock.SHAPE);
switch(shape) {
switch (shape) {
case NORTH_SOUTH:
if (travelPositive) {
++z;
@ -407,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;
}
@ -443,14 +455,6 @@ public class RegisterClientStuff {
});
}
public static void registerParticles() {
// rip particle man
IClientXplatAbstractions.INSTANCE.registerParticleType(HexParticles.LIGHT_PARTICLE,
ConjureParticle.Provider::new);
IClientXplatAbstractions.INSTANCE.registerParticleType(HexParticles.CONJURE_PARTICLE,
ConjureParticle.Provider::new);
}
public static void registerBlockEntityRenderers(@NotNull BlockEntityRendererRegisterererer registerer) {
registerer.registerBlockEntityRenderer(HexBlockEntities.SLATE_TILE, BlockEntitySlateRenderer::new);
registerer.registerBlockEntityRenderer(HexBlockEntities.AKASHIC_BOOKSHELF_TILE,
@ -460,6 +464,6 @@ public class RegisterClientStuff {
@FunctionalInterface
public interface BlockEntityRendererRegisterererer {
<T extends BlockEntity> void registerBlockEntityRenderer(BlockEntityType<T> type,
BlockEntityRendererProvider<? super T> berp);
BlockEntityRendererProvider<? super T> berp);
}
}

View file

@ -8,7 +8,6 @@ import at.petrak.hexcasting.api.utils.TAU
import at.petrak.hexcasting.api.utils.getValue
import at.petrak.hexcasting.api.utils.setValue
import at.petrak.hexcasting.api.utils.weakMapped
import at.petrak.hexcasting.client.gui.GuiSpellcasting
import at.petrak.hexcasting.common.recipe.ingredient.VillagerIngredient
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.DefaultVertexFormat
@ -31,19 +30,25 @@ import net.minecraft.world.entity.npc.VillagerProfession
import net.minecraft.world.entity.npc.VillagerType
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.levelgen.XoroshiroRandomSource
import net.minecraft.world.level.levelgen.synth.PerlinNoise
import net.minecraft.world.level.levelgen.SingleThreadedRandomSource
import net.minecraft.world.level.levelgen.synth.SimplexNoise
import net.minecraft.world.phys.Vec2
import kotlin.math.abs
import kotlin.math.min
import kotlin.math.roundToInt
import kotlin.math.sin
/**
* Source of perlin noise
*/
val NOISE: PerlinNoise = PerlinNoise.create(XoroshiroRandomSource(9001L), listOf(0, 1, 2, 3, 4))
val NOISE: SimplexNoise = SimplexNoise(SingleThreadedRandomSource(9001L))
val CAP_THETA: Float = 18f
// see the test; perlin noise seems to output almost exclusively between -0.5 and 0.5
// i could probably impl this "properly" with some kind of exponent but it's faster and easier to divide
fun getNoise(x: Double, y: Double, z: Double): Double =
NOISE.getValue(x * 0.6, y * 0.6, z * 0.6) / 2.0
// how many degrees are between each triangle on the smooth caps of the lines
const val CAP_THETA = 180f / 10f
const val DEFAULT_READABILITY_OFFSET = 0.2f
const val DEFAULT_LAST_SEGMENT_LEN_PROP = 0.8f
/**
* Draw a sequence of linePoints spanning the given points.
@ -79,7 +84,7 @@ fun drawLineSeq(
val n = points.size
val joinAngles = FloatArray(n)
val joinOffsets = FloatArray(n)
for (i in 2..n - 1) {
for (i in 2 until n) {
val p0 = points[i - 2];
val p1 = points[i - 1];
val p2 = points[i];
@ -95,8 +100,11 @@ fun drawLineSeq(
fun vertex(color: BlockPos, pos: Vec2) =
buf.vertex(mat, pos.x, pos.y, z).color(color.x, color.y, color.z, a).endVertex()
for ((i, pair) in points.zipWithNext().withIndex()) {
val (p1, p2) = pair
buf.begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION_COLOR)
for (i in 0 until points.size - 1) {
val p1 = points[i]
val p2 = points[i + 1]
// https://github.com/not-fl3/macroquad/blob/master/src/shapes.rs#L163
// GuiComponent::innerFill line 52
// fedor have useful variable names challenge (99% can't beat)
@ -110,16 +118,32 @@ fun drawLineSeq(
val color2 = color((i + 1f) / n)
val jlow = joinOffsets[i]
val jhigh = joinOffsets[i + 1]
buf.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR)
vertex(color1, p1.add(tangent.scale(Math.max(0f, jlow))).add(normal))
// Draw the line segment as a hexagon, sort of
// I can't imagine what the hell alwinfy is up to but this is implementing what TRIANGLE_FAN does
// using normal triangles so we can send the entire segment to the buffer at once
val p1Down = p1.add(tangent.scale(Math.max(0f, jlow))).add(normal)
val p1Up = p1.add(tangent.scale(Math.max(0f, -jlow))).add(normal.negated())
val p2Down = p2.add(tangent.scale(Math.max(0f, jhigh)).negated()).add(normal)
val p2Up = p2.add(tangent.scale(Math.max(0f, -jhigh)).negated()).add(normal.negated())
vertex(color1, p1Down)
vertex(color1, p1)
vertex(color1, p1.add(tangent.scale(Math.max(0f, -jlow))).add(normal.negated()))
vertex(color2, p2.add(tangent.scale(Math.max(0f, -jhigh)).negated()).add(normal.negated()))
vertex(color1, p1Up)
vertex(color1, p1Down)
vertex(color1, p1Up)
vertex(color2, p2Up)
vertex(color1, p1Down)
vertex(color2, p2Up)
vertex(color2, p2)
vertex(color2, p2.add(tangent.scale(Math.max(0f, jhigh)).negated()).add(normal))
tess.end()
vertex(color1, p1Down)
vertex(color2, p2)
vertex(color2, p2Down)
if (i > 0) {
// Draw the connector to the next line segment
val sangle = joinAngles[i]
val angle = Math.abs(sangle)
val rnormal = normal.negated()
@ -127,22 +151,35 @@ fun drawLineSeq(
if (joinSteps < 1) {
continue
}
buf.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR)
buf.vertex(mat, p1.x, p1.y, z).color(color1.x, color1.y, color1.z, a).endVertex()
if (sangle < 0) {
for (j in 0..joinSteps) {
var prevVert = Vec2(p1.x - rnormal.x, p1.y - rnormal.y)
for (j in 1..joinSteps) {
val fan = rotate(rnormal, -sangle * (j.toFloat() / joinSteps))
buf.vertex(mat, p1.x - fan.x, p1.y - fan.y, z).color(color1.x, color1.y, color1.z, a).endVertex()
val fanShift = Vec2(p1.x - fan.x, p1.y - fan.y)
vertex(color1, p1)
vertex(color1, prevVert)
vertex(color1, fanShift)
prevVert = fanShift
}
} else {
for (j in joinSteps downTo 0) {
val startFan = rotate(normal, -sangle)
var prevVert = Vec2(p1.x - startFan.x, p1.y - startFan.y)
for (j in joinSteps - 1 downTo 0) {
val fan = rotate(normal, -sangle * (j.toFloat() / joinSteps))
buf.vertex(mat, p1.x - fan.x, p1.y - fan.y, z).color(color1.x, color1.y, color1.z, a).endVertex()
val fanShift = Vec2(p1.x - fan.x, p1.y - fan.y)
vertex(color1, p1)
vertex(color1, prevVert)
vertex(color1, fanShift)
prevVert = fanShift
}
}
tess.end()
}
}
tess.end()
fun drawCaps(color: BlockPos, point: Vec2, prev: Vec2) {
val tangent = point.add(prev.negated()).normalized().scale(0.5f * width)
val normal = Vec2(-tangent.y, tangent.x)
@ -166,9 +203,9 @@ fun rotate(vec: Vec2, theta: Float): Vec2 {
}
/**
* * Draw a hex pattern from the given list of non-zappy points (as in, do the *style* of drawing it,
* * you have to do the conversion yourself.)
* */
* Draw a hex pattern from the given list of non-zappy points (as in, do the *style* of drawing it,
* you have to do the conversion yourself.)
*/
fun drawPatternFromPoints(
mat: Matrix4f,
points: List<Vec2>,
@ -177,8 +214,11 @@ fun drawPatternFromPoints(
tail: Int,
head: Int,
flowIrregular: Float,
readabilityOffset: Float,
lastSegmentLenProportion: Float,
seed: Double
) {
val zappyPts = makeZappy(points, dupIndices, 10f, 2.5f, 0.1f, flowIrregular)
val zappyPts = makeZappy(points, dupIndices, 10, 2.5f, 0.1f, flowIrregular, readabilityOffset, lastSegmentLenProportion, seed)
val nodes = if (drawLast) {
points
} else {
@ -199,16 +239,6 @@ fun drawPatternFromPoints(
}
}
fun makeZappy(
points: List<Vec2>,
dupIndices: Set<Int>?,
hops: Float,
variance: Float,
speed: Float,
flowIrregular: Float
) =
makeZappy(points, dupIndices, hops.toInt(), variance, speed, flowIrregular, 0.2f)
/**
* Split up a sequence of linePoints with a lightning effect
* @param hops: rough number of points to subdivide each segment into
@ -216,17 +246,18 @@ fun makeZappy(
*/
fun makeZappy(
barePoints: List<Vec2>, dupIndices: Set<Int>?, hops: Int, variance: Float, speed: Float, flowIrregular: Float,
readabilityOffset: Float
readabilityOffset: Float, lastSegmentLenProportion: Float, seed: Double
): List<Vec2> {
// Nothing in, nothing out
if (barePoints.isEmpty()) {
return emptyList()
}
fun zappify(points: List<Vec2>): List<Vec2> {
fun zappify(points: List<Vec2>, truncateLast: Boolean): List<Vec2> {
val scaleVariance = { it: Double -> 1.0.coerceAtMost(8 * (0.5 - abs(0.5 - it))) }
val zSeed = ClientTickCounter.getTotal().toDouble() * speed
// Create our output list of zap points
val zappyPts = mutableListOf(points[0])
val zappyPts = ArrayList<Vec2>(points.size * hops)
zappyPts.add(points[0])
// For each segment in the original...
for ((i, pair) in points.zipWithNext().withIndex()) {
val (src, target) = pair
@ -236,30 +267,40 @@ fun makeZappy(
// Compute how big the radius of variance should be
val maxVariance = hopDist * variance
for (j in 1..hops) {
// for a list of length n, there will be n-1 pairs,
// and so the last index will be (n-1)-1
val maxJ = if (truncateLast && i == points.size - 2) {
(lastSegmentLenProportion * hops.toFloat()).roundToInt()
} else hops
for (j in 1..maxJ) {
val progress = j.toDouble() / (hops + 1)
// Add the next hop...
val pos = src.add(delta.scale(progress.toFloat()))
// as well as some random variance...
// (We use i, j (segment #, subsegment #) as seeds for the Perlin noise,
// and zSeed (i.e. time elapsed) to perturb the shape gradually over time)
val minorPerturb = NOISE.getValue(i.toDouble(), j.toDouble(), sin(zSeed)) * flowIrregular
val theta = (3 * NOISE.getValue(
i.toDouble() + j.toDouble() / (hops + 1) + minorPerturb - zSeed,
val minorPerturb = getNoise(i.toDouble(), j.toDouble(), sin(zSeed)) * flowIrregular
val theta = (3 * getNoise(
i + progress + minorPerturb - zSeed,
1337.0,
0.0
seed
) * TAU).toFloat()
val r = (NOISE.getValue(
i.toDouble() + j.toDouble() / (hops + 1) - zSeed,
val r = (getNoise(
i + progress - zSeed,
69420.0,
0.0
seed
) * maxVariance * scaleVariance(progress)).toFloat()
val randomHop = Vec2(r * Mth.cos(theta), r * Mth.sin(theta))
// Then record the new location.
zappyPts.add(pos.add(randomHop))
if (j == hops) {
// Finally, we hit the destination, add that too
// but we might not hit the destination if we want to stop short
zappyPts.add(target)
}
}
// Finally, we hit the destination, add that too
zappyPts.add(target)
}
return zappyPts
}
@ -277,16 +318,16 @@ fun makeZappy(
}
if (i == barePoints.size - 2) {
daisyChain.add(tail)
points.addAll(zappify(daisyChain))
points.addAll(zappify(daisyChain, true))
} else if (dupIndices.contains(i + 1)) {
daisyChain.add(tail.add(tangent.negated()))
points.addAll(zappify(daisyChain))
points.addAll(zappify(daisyChain, false))
daisyChain.clear()
}
}
points
} else {
zappify(barePoints)
zappify(barePoints, true)
}
}

View file

@ -22,7 +22,7 @@ public class BlockEntityAkashicBookshelfRenderer implements BlockEntityRenderer<
@Override
public void render(BlockEntityAkashicBookshelf tile, float pPartialTick, PoseStack ps,
MultiBufferSource buffer, int light, int overlay) {
MultiBufferSource buffer, int light, int overlay) {
HexPattern pattern = tile.getPattern();
if (pattern == null) {
return;
@ -73,7 +73,9 @@ public class BlockEntityAkashicBookshelfRenderer implements BlockEntityRenderer<
lines2.set(j, new Vec2(-v.x, v.y));
}
var zappy = RenderLib.makeZappy(lines2, RenderLib.findDupIndices(pattern.positions()), 10f, 0.5f, 0f, 0f);
var stupidHash = tile.getBlockPos().hashCode();
var zappy = RenderLib.makeZappy(lines2, RenderLib.findDupIndices(pattern.positions()), 10, 0.5f, 0f, 0f, 0f,
1f, stupidHash);
int outer = 0xff_d2c8c8;
int inner = 0xc8_322b33;

View file

@ -22,7 +22,7 @@ public class BlockEntitySlateRenderer implements BlockEntityRenderer<BlockEntity
@Override
public void render(BlockEntitySlate tile, float pPartialTick, PoseStack ps,
MultiBufferSource buffer, int light, int overlay) {
MultiBufferSource buffer, int light, int overlay) {
if (tile.pattern == null) {
return;
}
@ -84,7 +84,11 @@ public class BlockEntitySlateRenderer implements BlockEntityRenderer<BlockEntity
}
var isLit = bs.getValue(BlockSlate.ENERGIZED);
var zappy = RenderLib.makeZappy(lines2, RenderLib.findDupIndices(tile.pattern.positions()), 10f, isLit ? 2.5f : 0.5f, isLit ? 0.1f : 0f, 0.2f);
var variance = isLit ? 2.5f : 0.5f;
var speed = isLit ? 0.1f : 0f;
var stupidHash = tile.getBlockPos().hashCode();
var zappy = RenderLib.makeZappy(lines2, RenderLib.findDupIndices(tile.pattern.positions()),
10, variance, speed, 0.2f, 0f, 1f, stupidHash);
int outer = isLit ? 0xff_64c8ff : 0xff_d2c8c8;
int inner = isLit ? RenderLib.screenCol(outer) : 0xc8_322b33;

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.client.entity;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.common.entities.EntityWallScroll;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
@ -38,7 +39,7 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
// I do as the PaintingRenderer guides
@Override
public void render(EntityWallScroll wallScroll, float yaw, float partialTicks, PoseStack ps,
MultiBufferSource bufSource, int packedLight) {
MultiBufferSource bufSource, int packedLight) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
@ -157,8 +158,8 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
}
private static void vertex(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts, float x, float y,
float z, float u,
float v, float nx, float ny, float nz) {
float z, float u,
float v, float nx, float ny, float nz) {
verts.vertex(mat, x, y, z)
.color(0xffffffff)
.uv(u, v).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(light)
@ -166,82 +167,136 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
.endVertex();
}
private static void vertexCol(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts, int col, float x,
float y) {
verts.vertex(mat, -x, y, 0)
private static void vertexCol(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts, int col, Vec2 pos) {
verts.vertex(mat, -pos.x, pos.y, 0)
.color(col)
.uv(0, 0).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(light)
.normal(normal, 0, 0, 1)
.endVertex();
}
private static void theCoolerDrawLineSeq(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts,
List<Vec2> points, float width, int color
private static void theCoolerDrawLineSeq(Matrix4f mat, Matrix3f normalMat, int light, VertexConsumer verts,
List<Vec2> points, float width, int color
) {
if (points.size() <= 1) {
return;
}
float prevXHi, prevYHi, prevXLo, prevYLo;
{
var p1 = points.get(0);
var p2 = points.get(1);
var dx = p2.x - p1.x;
var dy = p2.y - p1.y;
var nx = -dy;
var ny = dx;
var tlen = Mth.sqrt(nx * nx + ny * ny) / (width * 0.5f);
var tx = nx / tlen;
var ty = ny / tlen;
prevXHi = p1.x - tx;
prevYHi = p1.y - ty;
prevXLo = p1.x + tx;
prevYLo = p1.y + ty;
// TODO: abstract some of this out with RenderLib to stop WET code
var joinAngles = new float[points.size()];
var joinOffsets = new float[points.size()];
for (int i = 2; i < points.size(); i++) {
var p0 = points.get(i - 2);
var p1 = points.get(i - 1);
var p2 = points.get(i);
var prev = p1.add(p0.negated());
var next = p2.add(p1.negated());
var angle = (float) Mth.atan2(
prev.x * next.y - prev.y * next.x,
prev.x * next.x + prev.y * next.y);
joinAngles[i - 1] = angle;
var clamp = Math.min(prev.length(), next.length()) / (width * 0.5f);
joinOffsets[i - 1] = Mth.clamp(Mth.sin(angle) / (1 + Mth.cos(angle)), -clamp, clamp);
}
for (var i = 0; i < points.size() - 1; i++) {
var p1 = points.get(i);
var p2 = points.get(i + 1);
var dx = p2.x - p1.x;
var dy = p2.y - p1.y;
var nx = -dy;
var ny = dx;
var tlen = Mth.sqrt(nx * nx + ny * ny) / (width * 0.5f);
var tx = nx / tlen;
var ty = ny / tlen;
var tangent = p2.add(p1.negated()).normalized().scale(width * 0.5f);
var normal = new Vec2(-tangent.y, tangent.x);
var xHi = p2.x - tx;
var yHi = p2.y - ty;
var xLo = p2.x + tx;
var yLo = p2.y + ty;
vertexCol(mat, normal, light, verts, color, prevXHi, prevYHi);
vertexCol(mat, normal, light, verts, color, prevXLo, prevYLo);
vertexCol(mat, normal, light, verts, color, xLo, yLo);
vertexCol(mat, normal, light, verts, color, xHi, yHi);
var jlow = joinOffsets[i];
var jhigh = joinOffsets[i + 1];
prevXHi = xHi;
prevYHi = yHi;
prevXLo = xLo;
prevYLo = yLo;
var p1Down = p1.add(tangent.scale(Math.max(0f, jlow))).add(normal);
var p1Up = p1.add(tangent.scale(Math.max(0f, -jlow))).add(normal.negated());
var p2Down = p2.add(tangent.scale(Math.max(0f, jhigh)).negated()).add(normal);
var p2Up = p2.add(tangent.scale(Math.max(0f, -jhigh)).negated()).add(normal.negated());
// Draw the chamfer hexagon as two trapezoids
// the points are in different orders to keep clockwise
vertexCol(mat, normalMat, light, verts, color, p1);
vertexCol(mat, normalMat, light, verts, color, p2);
vertexCol(mat, normalMat, light, verts, color, p2Up);
vertexCol(mat, normalMat, light, verts, color, p1Up);
vertexCol(mat, normalMat, light, verts, color, p1);
vertexCol(mat, normalMat, light, verts, color, p1Down);
vertexCol(mat, normalMat, light, verts, color, p2Down);
vertexCol(mat, normalMat, light, verts, color, p2);
if (i > 0) {
var sangle = joinAngles[i];
var angle = Math.abs(sangle);
var rnormal = normal.negated();
var joinSteps = Mth.ceil(angle * 180 / (RenderLib.CAP_THETA * Mth.PI));
if (joinSteps < 1) continue;
if (sangle < 0) {
var prevVert = new Vec2(p1.x - rnormal.x, p1.y - rnormal.y);
for (var j = 1; j <= joinSteps; j++) {
var fan = RenderLib.rotate(rnormal, -sangle * ((float) j / joinSteps));
var fanShift = new Vec2(p1.x - fan.x, p1.y - fan.y);
vertexCol(mat, normalMat, light, verts, color, p1);
vertexCol(mat, normalMat, light, verts, color, p1);
vertexCol(mat, normalMat, light, verts, color, fanShift);
vertexCol(mat, normalMat, light, verts, color, prevVert);
prevVert = fanShift;
}
} else {
var startFan = RenderLib.rotate(normal, -sangle);
var prevVert = new Vec2(p1.x - startFan.x, p1.y - startFan.y);
for (var j = joinSteps - 1; j >= 0; j--) {
var fan = RenderLib.rotate(normal, -sangle * ((float) j / joinSteps));
var fanShift = new Vec2(p1.x - fan.x, p1.y - fan.y);
vertexCol(mat, normalMat, light, verts, color, p1);
vertexCol(mat, normalMat, light, verts, color, p1);
vertexCol(mat, normalMat, light, verts, color, fanShift);
vertexCol(mat, normalMat, light, verts, color, prevVert);
prevVert = fanShift;
}
}
}
}
for (var pair : new Vec2[][]{
{points.get(0), points.get(1)},
{points.get(points.size() - 1), points.get(points.size() - 2)}
}) {
var point = pair[0];
var prev = pair[1];
var tangent = point.add(prev.negated()).normalized().scale(0.5f * width);
var normal = new Vec2(-tangent.y, tangent.x);
var joinSteps = Mth.ceil(180f / RenderLib.CAP_THETA);
for (int j = joinSteps; j > 0; j--) {
var fan0 = RenderLib.rotate(normal, -Mth.PI * ((float) j / joinSteps));
var fan1 = RenderLib.rotate(normal, -Mth.PI * ((float) (j - 1) / joinSteps));
vertexCol(mat, normalMat, light, verts, color, point);
vertexCol(mat, normalMat, light, verts, color, point);
vertexCol(mat, normalMat, light, verts, color, point.add(fan1));
vertexCol(mat, normalMat, light, verts, color, point.add(fan0));
}
}
}
private static void theCoolerDrawSpot(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts,
Vec2 point, float radius, int color) {
Vec2 point, float radius, int color) {
var fracOfCircle = 6;
for (int i = 0; i < fracOfCircle; i++) {
// We do need rects, irritatingly
// so we do fake triangles
vertexCol(mat, normal, light, verts, color, point.x, point.y);
vertexCol(mat, normal, light, verts, color, point.x, point.y);
vertexCol(mat, normal, light, verts, color, point);
vertexCol(mat, normal, light, verts, color, point);
for (int j = 0; j <= 1; j++) {
var theta = (i - j) / (float) fracOfCircle * Mth.TWO_PI;
var rx = Mth.cos(theta) * radius + point.x;
var ry = Mth.sin(theta) * radius + point.y;
vertexCol(mat, normal, light, verts, color, rx, ry);
vertexCol(mat, normal, light, verts, color, new Vec2(rx, ry));
}
}
}

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(
@ -234,6 +234,7 @@ class GuiSpellcasting constructor(
// Well, we never managed to get anything on the stack this go-around.
this.drawState = PatternDrawState.BetweenPatterns
}
is PatternDrawState.Drawing -> {
val (start, _, pat) = this.drawState as PatternDrawState.Drawing
this.drawState = PatternDrawState.BetweenPatterns
@ -325,7 +326,8 @@ class GuiSpellcasting constructor(
}
RenderSystem.defaultBlendFunc()
for ((pat, origin, valid) in this.patterns) {
for ((idx, elts) in this.patterns.withIndex()) {
val (pat, origin, valid) = elts
drawPatternFromPoints(
mat,
pat.toLines(
@ -336,7 +338,10 @@ class GuiSpellcasting constructor(
true,
valid.color or (0xC8 shl 24),
valid.fadeColor or (0xC8 shl 24),
if (valid.success) 0.2f else 0.9f
if (valid.success) 0.2f else 0.9f,
DEFAULT_READABILITY_OFFSET,
1f,
idx.toDouble()
)
}
@ -358,7 +363,17 @@ class GuiSpellcasting constructor(
}
points.add(mousePos)
drawPatternFromPoints(mat, points, dupIndices, false, 0xff_64c8ff_u.toInt(), 0xff_fecbe6_u.toInt(), 0.1f)
// Use the size of the patterns as the seed so that way when this one is added the zappies don't jump
drawPatternFromPoints(mat,
points,
dupIndices,
false,
0xff_64c8ff_u.toInt(),
0xff_fecbe6_u.toInt(),
0.1f,
DEFAULT_READABILITY_OFFSET,
1f,
this.patterns.size.toDouble())
}
RenderSystem.enableDepthTest()
@ -368,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
@ -400,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()
}
@ -464,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

@ -5,9 +5,9 @@ import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.common.misc.PatternTooltip;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.math.Matrix4f;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.entity.ItemRenderer;
@ -19,17 +19,20 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.stream.Collectors;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
// https://github.com/VazkiiMods/Botania/blob/95bd2d3fbc857b7c102687554e1d1b112f8af436/Xplat/src/main/java/vazkii/botania/client/gui/ManaBarTooltipComponent.java
// yoink
public class PatternTooltipComponent implements ClientTooltipComponent {
public static final ResourceLocation PRISTINE_BG = new ResourceLocation(
"hexcasting:textures/gui/scroll.png");
public static final ResourceLocation ANCIENT_BG = new ResourceLocation(
"hexcasting:textures/gui/scroll_ancient.png");
public static final ResourceLocation SLATE_BG = new ResourceLocation(
"hexcasting:textures/gui/slate.png");
private static final float SIZE = 72f;
/**
* @see PatternTooltip the associated data for this
*/
public class PatternTooltipComponent implements ClientTooltipComponent {
public static final ResourceLocation PRISTINE_BG = modLoc("textures/gui/scroll.png");
public static final ResourceLocation ANCIENT_BG = modLoc("textures/gui/scroll_ancient.png");
public static final ResourceLocation SLATE_BG = modLoc("textures/gui/slate.png");
private static final float RENDER_SIZE = 128f;
private final HexPattern pattern;
private final List<Vec2> zappyPoints;
@ -41,10 +44,13 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
this.pattern = tt.pattern();
this.background = tt.background();
var pair = RenderLib.getCenteredPattern(pattern, SIZE, SIZE, 8f);
var pair = RenderLib.getCenteredPattern(pattern, RENDER_SIZE, RENDER_SIZE, 16f);
this.scale = pair.getFirst();
var dots = pair.getSecond();
this.zappyPoints = RenderLib.makeZappy(dots, RenderLib.findDupIndices(pattern.positions()), 10f, 0.8f, 0f, 0f);
this.zappyPoints = RenderLib.makeZappy(
dots, RenderLib.findDupIndices(pattern.positions()),
10, 0.8f, 0f, 0f, RenderLib.DEFAULT_READABILITY_OFFSET, RenderLib.DEFAULT_LAST_SEGMENT_LEN_PROP,
0.0);
this.pathfinderDots = dots.stream().distinct().collect(Collectors.toList());
}
@ -58,7 +64,7 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
@Override
public void renderImage(Font font, int mouseX, int mouseY, PoseStack ps, ItemRenderer pItemRenderer,
int pBlitOffset) {
int pBlitOffset) {
var width = this.getWidth(font);
var height = this.getHeight();
@ -66,7 +72,7 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
ps.pushPose();
ps.translate(mouseX, mouseY, 500);
RenderSystem.enableBlend();
renderBG(ps, this.background);
renderBG(ps, this.background, pBlitOffset);
// renderText happens *before* renderImage for some asinine reason
// RenderSystem.disableBlend();
@ -82,9 +88,9 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
var outer = 0xff_d2c8c8;
var innerLight = 0xc8_aba2a2;
var innerDark = 0xc8_322b33;
RenderLib.drawLineSeq(mat, this.zappyPoints, 5f, 0,
RenderLib.drawLineSeq(mat, this.zappyPoints, 6f, 0,
outer, outer);
RenderLib.drawLineSeq(mat, this.zappyPoints, 2f, 0,
RenderLib.drawLineSeq(mat, this.zappyPoints, 6f * 0.4f, 0,
innerDark, innerLight);
RenderLib.drawSpot(mat, this.zappyPoints.get(0), 2.5f, 1f, 0.1f, 0.15f, 0.6f);
@ -95,31 +101,22 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
ps.popPose();
}
private static void renderBG(PoseStack ps, ResourceLocation background) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
private static void renderBG(PoseStack ps, ResourceLocation background, int blitOffset) {
RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
RenderSystem.setShaderTexture(0, background);
// i wish i liked mobius front enough ot get to the TIS puzzles
BufferBuilder buffer = Tesselator.getInstance().getBuilder();
Matrix4f neo = ps.last().pose();
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
buffer.vertex(neo, 0, 0, 0.0F).uv(0.0F, 0.0F).endVertex();
buffer.vertex(neo, 0, SIZE, 0.0F).uv(0.0F, 1.0f).endVertex();
buffer.vertex(neo, SIZE, SIZE, 0.0F).uv(1.0F, 1.0f).endVertex();
buffer.vertex(neo, SIZE, 0, 0.0F).uv(1.0F, 0.0F).endVertex();
BufferUploader.draw(buffer.end());
// x y blitoffset sw sh w h ... ?
// parchment doesn't have this mapped
GuiComponent.blit(ps, 0, 0, blitOffset, 0f, 0f, (int) RENDER_SIZE, (int) RENDER_SIZE, (int) RENDER_SIZE,
(int) RENDER_SIZE);
}
@Override
public int getWidth(Font pFont) {
return (int) SIZE;
return (int) RENDER_SIZE;
}
@Override
public int getHeight() {
return (int) SIZE;
return (int) RENDER_SIZE;
}
}

View file

@ -27,7 +27,7 @@ public class ConjureParticle extends TextureSheetParticle {
private final boolean light;
ConjureParticle(ClientLevel pLevel, double x, double y, double z, double dx, double dy, double dz,
SpriteSet pSprites, int color, boolean light) {
SpriteSet pSprites, int color, boolean light) {
super(pLevel, x, y, z, dx, dy, dz);
this.light = light;
this.quadSize *= light ? 0.9f : 0.75f;
@ -86,10 +86,10 @@ public class ConjureParticle extends TextureSheetParticle {
@Nullable
@Override
public Particle createParticle(ConjureParticleOptions type, ClientLevel level,
double pX, double pY, double pZ,
double pXSpeed, double pYSpeed, double pZSpeed) {
double pX, double pY, double pZ,
double pXSpeed, double pYSpeed, double pZSpeed) {
return new ConjureParticle(level, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, this.sprite, type.color(),
type.isLight());
type.isLight());
}
}
@ -113,7 +113,7 @@ public class ConjureParticle extends TextureSheetParticle {
public void end(Tesselator tess) {
tess.end();
IClientXplatAbstractions.INSTANCE.restoreLastFilter(
Minecraft.getInstance().getTextureManager().getTexture(TextureAtlas.LOCATION_PARTICLES)
Minecraft.getInstance().getTextureManager().getTexture(TextureAtlas.LOCATION_PARTICLES)
);
RenderSystem.disableBlend();
RenderSystem.depthMask(true);

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

@ -28,6 +28,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;
@ -95,7 +96,7 @@ public class RegisterPatterns {
new OpTwiddling(2, new int[]{1, 0}));
PatternRegistry.mapPattern(HexPattern.fromAngles("aaeaa", HexDir.EAST), modLoc("rotate"),
new OpTwiddling(3, new int[]{1, 2, 0}));
PatternRegistry.mapPattern(HexPattern.fromAngles("ddqdd", HexDir.NORTH_EAST), modLoc("rotate-reverse"),
PatternRegistry.mapPattern(HexPattern.fromAngles("ddqdd", HexDir.NORTH_EAST), modLoc("rotate_reverse"),
new OpTwiddling(3, new int[]{2, 0, 1}));
PatternRegistry.mapPattern(HexPattern.fromAngles("aadaa", HexDir.EAST), modLoc("duplicate"),
new OpTwiddling(1, new int[]{0, 0}));

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
@ -36,14 +37,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(it)) }, { it })
val frame = ContinuationFrame.Evaluate(instrsList)
val frame = FrameEvaluate(instrsList, true)
return OperationResult(newCont.pushFrame(frame), stack, ravenmind, listOf())
}
}

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.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.ContinuationFrame
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.ContinuationIota

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

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

@ -53,7 +53,7 @@ public class EntityWallScroll extends HangingEntity {
}
public EntityWallScroll(Level world, BlockPos pos, Direction dir, ItemStack scroll, boolean showStrokeOrder,
int blockSize) {
int blockSize) {
super(HexEntities.WALL_SCROLL, world, pos);
this.setDirection(dir);
this.blockSize = blockSize;
@ -72,8 +72,10 @@ public class EntityWallScroll extends HangingEntity {
var pair = RenderLib.getCenteredPattern(pattern, 128f / 3 * blockSize, 128f / 3 * blockSize,
16f / 3 * blockSize);
var dots = pair.getSecond();
var readOffset = this.getShowsStrokeOrder() ? RenderLib.DEFAULT_READABILITY_OFFSET : 0f;
var lastProp = this.getShowsStrokeOrder() ? RenderLib.DEFAULT_LAST_SEGMENT_LEN_PROP : 1f;
this.zappyPoints = RenderLib.makeZappy(dots, RenderLib.findDupIndices(pattern.positions()), 10, 0.4f,
0f, 0f, this.getShowsStrokeOrder() ? 0.2f : 0f);
0f, 0f, readOffset, lastProp, this.getId());
}
this.isAncient = NBTHelper.hasString(scroll, ItemScroll.TAG_OP_ID);
@ -158,7 +160,7 @@ public class EntityWallScroll extends HangingEntity {
}
public void readSpawnData(BlockPos pos, Direction dir, ItemStack scrollItem,
boolean showsStrokeOrder, int blockSize) {
boolean showsStrokeOrder, int blockSize) {
this.pos = pos;
this.scroll = scrollItem;
this.blockSize = blockSize;
@ -201,7 +203,7 @@ public class EntityWallScroll extends HangingEntity {
@Override
public void lerpTo(double pX, double pY, double pZ, float pYaw, float pPitch, int pPosRotationIncrements,
boolean pTeleport) {
boolean pTeleport) {
BlockPos blockpos = this.pos.offset(pX - this.getX(), pY - this.getY(), pZ - this.getZ());
this.setPos(blockpos.getX(), blockpos.getY(), blockpos.getZ());
}

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;
@ -63,7 +63,7 @@ public class ItemFocus 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

@ -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;
@ -138,8 +138,9 @@ public class ItemScroll extends Item implements IotaHolderItem {
var pattern = HexPattern.fromNBT(compound);
return Optional.of(new PatternTooltip(
pattern,
NBTHelper.hasString(stack,
ItemScroll.TAG_OP_ID) ? PatternTooltipComponent.ANCIENT_BG : PatternTooltipComponent.PRISTINE_BG));
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;
@ -86,7 +86,10 @@ public class ItemSlate extends BlockItem implements IotaHolderItem {
@Override
public boolean canWrite(ItemStack stack, Iota datum) {
return datum instanceof PatternIota && !NBTHelper.hasCompound(stack, BlockEntitySlate.TAG_PATTERN);
var isWritten = NBTHelper.hasCompound(stack, "BlockEntityTag")
&& stack.getTag().getCompound("BlockEntityTag").contains(BlockEntitySlate.TAG_PATTERN);
return (datum instanceof PatternIota && !isWritten)
|| (datum == null && isWritten);
}
@Override

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

@ -1,6 +1,9 @@
package at.petrak.hexcasting.common.lib;
import at.petrak.hexcasting.client.particles.ConjureParticle;
import at.petrak.hexcasting.common.particles.ConjureParticleOptions;
import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.client.particle.SpriteSet;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.resources.ResourceLocation;
@ -8,6 +11,7 @@ import net.minecraft.resources.ResourceLocation;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
@ -21,9 +25,9 @@ public class HexParticles {
private static final Map<ResourceLocation, ParticleType<?>> PARTICLES = new LinkedHashMap<>();
public static final ConjureParticleOptions.Type CONJURE_PARTICLE = register(
"conjure_block_particle", new ConjureParticleOptions.Type(false));
"conjure_block_particle", new ConjureParticleOptions.Type(false));
public static final ConjureParticleOptions.Type LIGHT_PARTICLE = register(
"conjure_light_particle", new ConjureParticleOptions.Type(false));
"conjure_light_particle", new ConjureParticleOptions.Type(false));
private static <O extends ParticleOptions, T extends ParticleType<O>> T register(String id, T particle) {
var old = PARTICLES.put(modLoc(id), particle);
@ -32,4 +36,15 @@ public class HexParticles {
}
return particle;
}
public static class FactoryHandler {
public interface Consumer {
<T extends ParticleOptions> void register(ParticleType<T> type, Function<SpriteSet, ParticleProvider<T>> constructor);
}
public static void registerFactories(Consumer consumer) {
consumer.register(CONJURE_PARTICLE, ConjureParticle.Provider::new);
consumer.register(LIGHT_PARTICLE, ConjureParticle.Provider::new);
}
}
}

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

@ -6,6 +6,8 @@ import net.minecraft.world.inventory.tooltip.TooltipComponent;
/**
* Used for displaying patterns on the tooltips for scrolls and slates.
*
* @see at.petrak.hexcasting.client.gui.PatternTooltipComponent the client-side renderer for this
*/
public record PatternTooltip(HexPattern pattern, ResourceLocation background) implements TooltipComponent {
}

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

@ -2,6 +2,7 @@ package at.petrak.hexcasting.interop.patchouli;
import at.petrak.hexcasting.api.spell.math.HexCoord;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.interop.utils.PatternDrawingUtil;
import at.petrak.hexcasting.interop.utils.PatternEntry;
import com.mojang.blaze3d.vertex.PoseStack;
@ -22,7 +23,7 @@ abstract public class AbstractPatternComponent implements ICustomComponent {
protected transient float hexSize;
private transient List<PatternEntry> patterns;
private transient List<Vec2> pathfinderDots;
private transient List<Vec2> zappyPoints;
/**
* Pass -1, -1 to center it.
@ -39,17 +40,21 @@ abstract public class AbstractPatternComponent implements ICustomComponent {
@Override
public void render(PoseStack poseStack, IComponentRenderContext ctx, float partialTicks, int mouseX, int mouseY) {
PatternDrawingUtil.drawPattern(poseStack, this.x, this.y, this.patterns, this.pathfinderDots,
this.showStrokeOrder(), ctx.getTicksInBook(),
PatternDrawingUtil.drawPattern(poseStack, this.x, this.y, this.patterns, this.zappyPoints,
this.showStrokeOrder(),
0xff_d2c8c8, 0xc8_aba2a2, 0xc8_322b33, 0x80_d1cccc);
}
@Override
public void onVariablesAvailable(UnaryOperator<IVariable> lookup) {
var data = PatternDrawingUtil.loadPatterns(this.getPatterns(lookup));
var patterns = this.getPatterns(lookup);
var data = PatternDrawingUtil.loadPatterns(
patterns,
this.showStrokeOrder() ? RenderLib.DEFAULT_READABILITY_OFFSET : 0f,
this.showStrokeOrder() ? RenderLib.DEFAULT_LAST_SEGMENT_LEN_PROP : 1f);
this.hexSize = data.hexSize();
this.patterns = data.patterns();
this.pathfinderDots = data.pathfinderDots();
this.zappyPoints = data.pathfinderDots();
}
protected static class RawPattern {

View file

@ -19,7 +19,8 @@ import java.util.List;
public final class PatternDrawingUtil {
public static void drawPattern(PoseStack poseStack, int x, int y, List<PatternEntry> patterns, List<Vec2> dots,
boolean strokeOrder, long animTicks, int outer, int innerLight, int innerDark, int dotColor) {
boolean strokeOrder, int outer, int innerLight, int innerDark,
int dotColor) {
poseStack.pushPose();
poseStack.translate(x, y, 1);
var mat = poseStack.last().pose();
@ -59,7 +60,8 @@ public final class PatternDrawingUtil {
poseStack.popPose();
}
public static PatternRenderingData loadPatterns(List<Pair<HexPattern, HexCoord>> patterns) {
public static PatternRenderingData loadPatterns(List<Pair<HexPattern, HexCoord>> patterns,
float readabilityOffset, float lastLineLenProp) {
var patternEntries = new ArrayList<PatternEntry>(patterns.size());
var fakeScale = 1;
@ -103,12 +105,13 @@ public final class PatternDrawingUtil {
var realCom = HexUtils.findCenter(seenRealPoints);
// and NOW for real!
for (var pat : patternEntries) {
for (int i = 0; i < patternEntries.size(); i++) {
PatternEntry pat = patternEntries.get(i);
var localOrigin = HexUtils.coordToPx(pat.origin(), hexSize, realCom.negated());
var points = pat.pattern().toLines(hexSize, localOrigin);
pat.zappyPoints()
.addAll(RenderLib.makeZappy(points, RenderLib.findDupIndices(pat.pattern().positions()), 10f, 0.8f, 0f,
0f));
.addAll(RenderLib.makeZappy(points, RenderLib.findDupIndices(pat.pattern().positions()), 10, 0.8f, 0f,
0f, readabilityOffset, lastLineLenProp, i));
}
var pathfinderDots = seenCoords.stream()

View file

@ -2,14 +2,10 @@ package at.petrak.hexcasting.xplat;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.common.network.IMessage;
import net.minecraft.client.particle.ParticleProvider;
import net.minecraft.client.particle.SpriteSet;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.item.ItemPropertyFunction;
import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
@ -17,7 +13,6 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import java.util.ServiceLoader;
import java.util.function.Function;
import java.util.stream.Collectors;
public interface IClientXplatAbstractions {
@ -29,9 +24,6 @@ public interface IClientXplatAbstractions {
<T extends Entity> void registerEntityRenderer(EntityType<? extends T> type, EntityRendererProvider<T> renderer);
<T extends ParticleOptions> void registerParticleType(ParticleType<T> type,
Function<SpriteSet, ParticleProvider<T>> factory);
void registerItemProperty(Item item, ResourceLocation id, ItemPropertyFunction func);
// On Forge, these are already exposed; on Farbc we do a mixin
@ -46,7 +38,7 @@ public interface IClientXplatAbstractions {
if (providers.size() != 1) {
var names = providers.stream().map(p -> p.type().getName()).collect(Collectors.joining(",", "[", "]"));
throw new IllegalStateException(
"There should be exactly one IClientXplatAbstractions implementation on the classpath. Found: " + names);
"There should be exactly one IClientXplatAbstractions implementation on the classpath. Found: " + names);
} else {
var provider = providers.get(0);
HexAPI.LOGGER.debug("Instantiating client xplat impl: " + provider.type().getName());

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

@ -173,6 +173,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",
@ -188,7 +228,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",
@ -196,7 +236,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",
@ -271,7 +311,7 @@
"hexcasting.spell.book.hexcasting:const/vec/x": "Vector Rfln. +X/-X",
"hexcasting.spell.book.hexcasting:const/vec/y": "Vector Rfln. +Y/-Y",
"hexcasting.spell.book.hexcasting:const/vec/z": "Vector Rfln. +Z/-Z",
"hexcasting.spell.book.hexcasting:write/entity": "Chronicler's Prfn.",
"hexcasting.spell.book.hexcasting:read/entity": "Chronicler's Prfn.",
"hexcasting.spell.book.hexcasting:number": "Numerical Reflection",
"hexcasting.spell.book.hexcasting:mask": "Bookkeeper's Gambit",
@ -337,12 +377,17 @@
"hexcasting.spell.hexcasting:zone_entity/not_player": "Zone Distillation: Non-Player",
"hexcasting.spell.hexcasting:zone_entity/not_living": "Zone Distillation: Non-Living",
"hexcasting.spell.hexcasting:duplicate": "Gemini Decomposition",
"hexcasting.spell.hexcasting:duplicate_n": "Gemini's Gambit",
"hexcasting.spell.hexcasting:over": "Dioscuri's Gambit",
"hexcasting.spell.hexcasting:stack_len": "Flock's Reflection",
"hexcasting.spell.hexcasting:swap": "Jester's Gambit",
"hexcasting.spell.hexcasting:rotate": "Rotation Gambit",
"hexcasting.spell.hexcasting:rotate_reverse": "Rotation Gambit II",
"hexcasting.spell.hexcasting:duplicate": "Gemini Decomposition",
"hexcasting.spell.hexcasting:over": "Prospector's Gambit",
"hexcasting.spell.hexcasting:tuck": "Undertaker's Gambit",
"hexcasting.spell.hexcasting:2dup": "Dioscuri Gambit",
"hexcasting.spell.hexcasting:duplicate_n": "Gemini Gambit",
"hexcasting.spell.hexcasting:stack_len": "Flock's Reflection",
"hexcasting.spell.hexcasting:fisherman": "Fisherman's Gambit",
"hexcasting.spell.hexcasting:fisherman/copy": "Fisherman's Gambit II",
"hexcasting.spell.hexcasting:swizzle": "Swindler's Gambit",
"hexcasting.spell.hexcasting:and_bit": "Intersection Distillation",
@ -899,10 +944,15 @@
"hexcasting.page.stackmanip.pseudo-novice": "Removes the first iota from the stack.",
"hexcasting.page.stackmanip.duplicate": "Duplicates the top iota of the stack.",
"hexcasting.page.stackmanip.swap": "Swaps the top two iotas of the stack.",
"hexcasting.page.stackmanip.rotate": "Yanks the iota third from the top of the stack to the top. [0, 1, 2] becomes [1, 2, 0].",
"hexcasting.page.stackmanip.over": "Duplicates the iota second from the top to the top. [0, 1] becomes [0, 1, 0].",
"hexcasting.page.stackmanip.rotate": "Yanks the iota third from the top of the stack to the top. [0, 1, 2] becomes [1, 2, 0].",
"hexcasting.page.stackmanip.rotate_reverse": "Yanks the top iota to the third position. [0, 1, 2] becomes [2, 0, 1].",
"hexcasting.page.stackmanip.over": "Copy the second-to-last iota of the stack to the top. [0, 1] becomes [0, 1, 0].",
"hexcasting.page.stackmanip.tuck": "Copy the top iota of the stack, then put it under the second iota. [0, 1] becomes [1, 0, 1].",
"hexcasting.page.stackmanip.2dup": "Copy the top two iotas of the stack. [0, 1] becomes [0, 1, 0, 1].",
"hexcasting.page.stackmanip.duplicate_n": "Removes the number at the top of the stack, then copies the top iota of the stack that number of times. (A count of 2 results in two of the iota on the stack, not three.)",
"hexcasting.page.stackmanip.fisherman": "Grabs the element in the stack indexed by the number and brings it to the top.",
"hexcasting.page.stackmanip.fisherman/copy": "Like $(action)Fisherman's Gambit/$, but instead of moving the iota, copies it.",
"hexcasting.page.stackmanip.stack_len": "Pushes the size of the stack as a number to the top of the stack. (For example, a stack of [0, 1] will become [0, 1, 2].)",
"hexcasting.page.stackmanip.last_n_list": "Remove $(italic)num/$ elements from the stack, then add them to a list at the top of the stack.",
"hexcasting.page.stackmanip.splat": "Remove the list at the top of the stack, then push its contents to the stack.",
@ -1099,7 +1149,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

@ -270,7 +270,7 @@
"hexcasting.spell.book.hexcasting:const/vec/x": "向量之精思,+X/-X型",
"hexcasting.spell.book.hexcasting:const/vec/y": "向量之精思,+Y/-Y型",
"hexcasting.spell.book.hexcasting:const/vec/z": "向量之精思,+Z/-Z型",
"hexcasting.spell.book.hexcasting:write/entity": "编年史家之策略",
"hexcasting.spell.book.hexcasting:read/entity": "编年史家之纯化",
"hexcasting.spell.book.hexcasting:number": "数字之精思",
"hexcasting.spell.book.hexcasting:mask": "簿记员之策略",
@ -336,12 +336,17 @@
"hexcasting.spell.hexcasting:zone_entity/not_player": "区域之馏化:非玩家",
"hexcasting.spell.hexcasting:zone_entity/not_living": "区域之馏化:非生物",
"hexcasting.spell.hexcasting:duplicate": "双子之分解",
"hexcasting.spell.hexcasting:duplicate_n": "双子之策略",
"hexcasting.spell.hexcasting:over": "狄俄斯库里之策略",
"hexcasting.spell.hexcasting:stack_len": "群体之精思",
"hexcasting.spell.hexcasting:swap": "弄臣之策略",
"hexcasting.spell.hexcasting:rotate": "轮换之策略",
"hexcasting.spell.hexcasting:rotate_reverse": "轮换之策略,第二型",
"hexcasting.spell.hexcasting:duplicate": "双子之分解",
"hexcasting.spell.hexcasting:over": "勘探者之策略",
"hexcasting.spell.hexcasting:tuck": "送葬者之策略",
"hexcasting.spell.hexcasting:2dup": "狄俄斯库里之策略",
"hexcasting.spell.hexcasting:duplicate_n": "双子之策略",
"hexcasting.spell.hexcasting:stack_len": "群体之精思",
"hexcasting.spell.hexcasting:fisherman": "渔夫之策略",
"hexcasting.spell.hexcasting:fisherman/copy": "渔夫之策略,第二型",
"hexcasting.spell.hexcasting:swizzle": "骗徒之策略",
"hexcasting.spell.hexcasting:and_bit": "交叉之馏化",
@ -897,10 +902,15 @@
"hexcasting.page.stackmanip.pseudo-novice": "移除栈顶的 iota。",
"hexcasting.page.stackmanip.duplicate": "复制栈顶的 iota。",
"hexcasting.page.stackmanip.swap": "交换栈顶两个 iota 的位置。",
"hexcasting.page.stackmanip.rotate": "将栈顶往下第三元素拉至栈顶。[0, 1, 2] 变为 [1, 2, 0]。",
"hexcasting.page.stackmanip.over": "将栈顶往下第二元素复制至栈顶。[0, 1] 变为 [0, 1, 0]。",
"hexcasting.page.stackmanip.rotate": "将栈顶往下第三元素拉至栈顶。[0, 1, 2] 变为 [1, 2, 0]。",
"hexcasting.page.stackmanip.rotate_reverse": "将栈顶元素沉至栈顶往下第三位处。[0, 1, 2] 变为 [2, 0, 1]。",
"hexcasting.page.stackmanip.over": "将栈顶往下第二元素复制至栈顶。[0, 1] 变为 [0, 1, 0]。",
"hexcasting.page.stackmanip.tuck": "将栈底元素复制至栈顶往下第二元素下方。[0, 1] 变为 [1, 0, 1]。",
"hexcasting.page.stackmanip.2dup": "复制栈顶的两个 iota。[0, 1] 变为 [0, 1, 0, 1]。",
"hexcasting.page.stackmanip.duplicate_n": "移除栈顶的数,然后将现在的栈顶元素复制该数次。(若所给数为 2则栈顶会有两个同一元素。",
"hexcasting.page.stackmanip.fisherman": "提出下标为所给数的元素并将其置于栈顶。",
"hexcasting.page.stackmanip.fisherman/copy": "与$(action)渔夫之策略/$类似,但会复制 iota 而非将其提出。",
"hexcasting.page.stackmanip.stack_len": "以数的形式压入栈中元素的个数。(例如,一个形如 [0, 1] 的栈会变为 [0, 1, 2]。)",
"hexcasting.page.stackmanip.last_n_list": "移除$(italic)所给数/$个元素,然后压入一个由其组成的列表。",
"hexcasting.page.stackmanip.splat": "移除栈顶的列表,然后依次压入其元素。",

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

@ -36,7 +36,7 @@
"type": "hexcasting:pattern",
"op_id": "hexcasting:write/entity",
"anchor": "hexcasting:write/entity",
"input": "any, entity",
"input": "entity, any",
"output": "",
"text": "hexcasting.page.readwrite.write/entity"
},

View file

@ -22,14 +22,6 @@
}
]
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:duplicate",
"anchor": "hexcasting:duplicate",
"input": "any",
"output": "any, any",
"text": "hexcasting.page.stackmanip.duplicate"
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:swap",
@ -46,6 +38,22 @@
"output": "any, any, any",
"text": "hexcasting.page.stackmanip.rotate"
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:rotate_reverse",
"anchor": "hexcasting:rotate_reverse",
"input": "any, any, any",
"output": "any, any, any",
"text": "hexcasting.page.stackmanip.rotate_reverse"
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:duplicate",
"anchor": "hexcasting:duplicate",
"input": "any",
"output": "any, any",
"text": "hexcasting.page.stackmanip.duplicate"
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:over",
@ -54,6 +62,14 @@
"output": "any, any, any",
"text": "hexcasting.page.stackmanip.over"
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:tuck",
"anchor": "hexcasting:tuck",
"input": "any, any",
"output": "any, any, any",
"text": "hexcasting.page.stackmanip.tuck"
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:duplicate_n",
@ -72,11 +88,11 @@
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:stack_len",
"anchor": "hexcasting:stack_len",
"input": "",
"output": "num",
"text": "hexcasting.page.stackmanip.stack_len"
"op_id": "hexcasting:fisherman/copy",
"anchor": "hexcasting:fisherman/copy",
"input": "num",
"output": "any",
"text": "hexcasting.page.stackmanip.fisherman/copy"
},
{
"type": "hexcasting:manual_pattern",
@ -89,12 +105,14 @@
{
"startdir": "SOUTH_EAST",
"signature": "aeea"
}, {
},
{
"startdir": "EAST",
"signature": "eada",
"q": 1,
"r": 2
}, {
},
{
"startdir": "SOUTH_EAST",
"signature": "ae",
"q": 2,
@ -119,6 +137,14 @@
"text": "hexcasting.page.stackmanip.swizzle.2",
"link_text": "hexcasting.page.stackmanip.swizzle.link",
"url": "https://github.com/gamma-delta/HexMod/wiki/Table-of-Lehmer-Codes-for-Swindler's-Gambit"
},
{
"type": "hexcasting:pattern",
"op_id": "hexcasting:stack_len",
"anchor": "hexcasting:stack_len",
"input": "",
"output": "num",
"text": "hexcasting.page.stackmanip.stack_len"
}
]
}

View file

@ -0,0 +1,39 @@
import net.minecraft.world.level.levelgen.SingleThreadedRandomSource;
import net.minecraft.world.level.levelgen.synth.PerlinNoise;
import net.minecraft.world.level.levelgen.synth.SimplexNoise;
import org.junit.jupiter.api.Test;
import java.util.List;
public class WhatRangeDoTheNoisesOutputAnywaysTest {
@Test
public void test() {
var perlin = PerlinNoise.create(new SingleThreadedRandomSource(12345), List.of(0, 1, 2, 3, 4));
var simplex = new SimplexNoise(new SingleThreadedRandomSource(12345));
System.out.println("Perlin:");
for (int i = 0; i < 20; i++) {
System.out.printf(" %f%n", perlin.getValue(i / 10.0, 69420.0, 1337.0));
}
System.out.println("Simplex:");
for (int i = 0; i < 20; i++) {
System.out.printf(" %f%n", simplex.getValue(i / 10.0, 69420.0, 1337.0));
}
}
@Test
public void perlinBounds() {
var perlin = PerlinNoise.create(new SingleThreadedRandomSource(12345), List.of(0, 1, 2, 3, 4));
var min = Double.POSITIVE_INFINITY;
var max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < 10000; i++) {
var it = perlin.getValue(i / 10.0, 12345.0, 7604.0);
min = Math.min(min, it);
max = Math.max(max, it);
}
System.out.printf("Min: %f\nMax: %f\n", min, max);
}
}

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

@ -5,15 +5,22 @@ import at.petrak.hexcasting.client.HexAdditionalRenderers
import at.petrak.hexcasting.client.RegisterClientStuff
import at.petrak.hexcasting.client.ShiftScrollListener
import at.petrak.hexcasting.client.gui.PatternTooltipComponent
import at.petrak.hexcasting.common.lib.HexParticles
import at.petrak.hexcasting.fabric.event.MouseScrollCallback
import at.petrak.hexcasting.fabric.network.FabricPacketHandler
import at.petrak.hexcasting.interop.HexInterop
import net.fabricmc.api.ClientModInitializer
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry
import net.fabricmc.fabric.api.client.rendering.v1.*
import net.minecraft.client.particle.ParticleProvider
import net.minecraft.client.particle.SpriteSet
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.core.particles.ParticleOptions
import net.minecraft.core.particles.ParticleType
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityType
import java.util.function.Function
object FabricHexClientInitializer : ClientModInitializer {
override fun onInitializeClient() {
@ -33,13 +40,19 @@ object FabricHexClientInitializer : ClientModInitializer {
MouseScrollCallback.EVENT.register(ShiftScrollListener::onScrollInGameplay)
RegisterClientStuff.init()
RegisterClientStuff.registerParticles()
HexParticles.FactoryHandler.registerFactories(object : HexParticles.FactoryHandler.Consumer {
override fun <T : ParticleOptions?> register(type: ParticleType<T>, constructor: Function<SpriteSet, ParticleProvider<T>>) {
ParticleFactoryRegistry.getInstance().register(type, constructor::apply)
}
})
// how ergonomic
RegisterClientStuff.registerBlockEntityRenderers(object :
RegisterClientStuff.BlockEntityRendererRegisterererer {
RegisterClientStuff.BlockEntityRendererRegisterererer {
override fun <T : BlockEntity> registerBlockEntityRenderer(
type: BlockEntityType<T>,
berp: BlockEntityRendererProvider<in T>
type: BlockEntityType<T>,
berp: BlockEntityRendererProvider<in T>
) {
BlockEntityRendererRegistry.register(type, berp)
}
@ -47,7 +60,7 @@ object FabricHexClientInitializer : ClientModInitializer {
HexInterop.clientInit()
RegisterClientStuff.registerColorProviders(
{ colorizer, item -> ColorProviderRegistry.ITEM.register(colorizer, item) },
{ colorizer, block -> ColorProviderRegistry.BLOCK.register(colorizer, block) })
{ colorizer, item -> ColorProviderRegistry.ITEM.register(colorizer, item) },
{ colorizer, block -> ColorProviderRegistry.BLOCK.register(colorizer, block) })
}
}

Some files were not shown because too many files have changed in this diff Show more