this does not compile even a little bit but i'm pushing so i'm not anxious having code on my HD

This commit is contained in:
petrak@ 2023-01-20 13:27:35 -06:00
parent 7748cf7387
commit 5d8b7a61eb
271 changed files with 1900 additions and 1656 deletions

View file

@ -2,8 +2,8 @@ Hello, intrepid Github reader!
The "flavor text" words for things in this mod and the internal names are different. (Sorry.) The "flavor text" words for things in this mod and the internal names are different. (Sorry.)
- A "Hex" is a `Cast`, cast through a [`CastingHarness`](api/spell/casting/CastingHarness.kt) - A "Hex" is a `Cast`, cast through a [`CastingHarness`](api/casting/eval/CastingHarness.kt)
- A "Pattern" is a [`HexPattern`](api/spell/math/HexPattern.kt) - A "Pattern" is a [`HexPattern`](api/casting/math/HexPattern.kt)
- An "Action" is an [`Operator`](api/spell/Action.kt) - An "Action" is an [`Operator`](api/casting/Action.kt)
- An action that pushes a spell is a [`Spell`](api/spell/SpellAction.kt) - An action that pushes a spell is a [`Spell`](api/casting/SpellAction.kt)

View file

@ -1,6 +1,11 @@
package at.petrak.hexcasting.api; package at.petrak.hexcasting.api;
import at.petrak.hexcasting.api.casting.ActionRegistryEntry;
import at.petrak.hexcasting.api.casting.SpecialHandler;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -22,6 +27,26 @@ public interface HexAPI {
} }
}); });
/**
* Return the localization key for the given action.
* <p>
* Note we're allowed to have action <em>resource keys</em> on the client, just no actual actions.
* <p>
* Special handlers should be calling {@link SpecialHandler#getName()}
*/
default String getActionI18nKey(ResourceKey<ActionRegistryEntry> action) {
return "hexcasting.spell.%s".formatted(action.location());
}
default String getActionI18nKey(ResourceLocation action) {
return "hexcasting.spell.%s".formatted(action.toString());
}
default Component getActionI18(ResourceLocation key, boolean isGreat) {
return Component.translatable(getActionI18nKey(key))
.withStyle(isGreat ? ChatFormatting.GOLD : ChatFormatting.LIGHT_PURPLE);
}
static HexAPI instance() { static HexAPI instance() {
return INSTANCE.get(); return INSTANCE.get();
} }

View file

@ -1,324 +0,0 @@
package at.petrak.hexcasting.api;
import at.petrak.hexcasting.api.spell.Action;
import at.petrak.hexcasting.api.spell.math.EulerPathFinder;
import at.petrak.hexcasting.api.spell.math.HexDir;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidPattern;
import com.mojang.datafixers.util.Pair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.saveddata.SavedData;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
public class PatternRegistry {
private static final ConcurrentMap<ResourceLocation, Action> actionLookup = new ConcurrentHashMap<>();
private static final ConcurrentMap<Action, ResourceLocation> keyLookup = new ConcurrentHashMap<>();
private static final ConcurrentLinkedDeque<SpecialHandlerEntry> specialHandlers = new ConcurrentLinkedDeque<>();
// Map signatures to the "preferred" direction they start in and their operator ID.
private static final ConcurrentMap<String, RegularEntry> regularPatternLookup =
new ConcurrentHashMap<>();
private static final ConcurrentMap<ResourceLocation, PerWorldEntry> perWorldPatternLookup =
new ConcurrentHashMap<>();
public static void mapPattern(HexPattern pattern, ResourceLocation id,
Action action) throws RegisterPatternException {
mapPattern(pattern, id, action, false);
}
/**
* Associate a given angle signature with a SpellOperator.
*/
public static void mapPattern(HexPattern pattern, ResourceLocation id, Action action,
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));
}
actionLookup.put(id, action);
keyLookup.put(action, id);
if (isPerWorld) {
perWorldPatternLookup.put(id, new PerWorldEntry(pattern, id));
} else {
regularPatternLookup.put(pattern.anglesSignature(), new RegularEntry(pattern.getStartDir(), id));
}
}
/**
* Add a special handler, to take an arbitrary pattern and return whatever kind of operator you like.
*/
public static void addSpecialHandler(SpecialHandlerEntry handler) {
specialHandlers.add(handler);
}
/**
* Add a special handler, to take an arbitrary pattern and return whatever kind of operator you like.
*/
public static void addSpecialHandler(ResourceLocation id, SpecialHandler handler) {
addSpecialHandler(new SpecialHandlerEntry(id, handler));
}
/**
* Internal use only.
*/
public static Action matchPattern(HexPattern pat, ServerLevel overworld) throws MishapInvalidPattern {
return matchPatternAndID(pat, overworld).getFirst();
}
/**
* Internal use only.
*/
public static Pair<Action, ResourceLocation> matchPatternAndID(HexPattern pat,
ServerLevel overworld) throws MishapInvalidPattern {
// Pipeline:
// patterns are registered here every time the game boots
// when we try to look
for (var handler : specialHandlers) {
var op = handler.handler.handlePattern(pat);
if (op != null) {
return new Pair<>(op, handler.id);
}
}
// Is it global?
var sig = pat.anglesSignature();
if (regularPatternLookup.containsKey(sig)) {
var it = regularPatternLookup.get(sig);
if (!actionLookup.containsKey(it.opId)) {
throw new MishapInvalidPattern();
}
var op = actionLookup.get(it.opId);
return new Pair<>(op, it.opId);
}
// Look it up in the world?
var ds = overworld.getDataStorage();
Save perWorldPatterns =
ds.computeIfAbsent(Save::load, () -> Save.create(overworld.getSeed()), TAG_SAVED_DATA);
perWorldPatterns.fillMissingEntries(overworld.getSeed());
if (perWorldPatterns.lookup.containsKey(sig)) {
var it = perWorldPatterns.lookup.get(sig);
return new Pair<>(actionLookup.get(it.getFirst()), it.getFirst());
}
throw new MishapInvalidPattern();
}
/**
* Internal use only.
*/
@Nullable
public static Action lookupPatternByShape(HexPattern pat) {
// Pipeline:
// patterns are registered here every time the game boots
// when we try to look
for (var handler : specialHandlers) {
var op = handler.handler.handlePattern(pat);
if (op != null) {
return op;
}
}
// Is it global?
var sig = pat.anglesSignature();
if (regularPatternLookup.containsKey(sig)) {
var it = regularPatternLookup.get(sig);
if (!actionLookup.containsKey(it.opId)) {
return null;
}
return actionLookup.get(it.opId);
}
// Currently, there's no way to look up the name of a Great Spell, as the client is unaware of the correct
// mapping.
// TODO: add code to match any pattern in the shape of a Great Spell to its operator.
// var ds = overworld.getDataStorage();
// Save perWorldPatterns =
// ds.computeIfAbsent(Save::load, () -> Save.create(overworld.getSeed()), TAG_SAVED_DATA);
// perWorldPatterns.fillMissingEntries(overworld.getSeed());
// if (perWorldPatterns.lookup.containsKey(sig)) {
// var it = perWorldPatterns.lookup.get(sig);
// return new Pair<>(actionLookup.get(it.getFirst()), it.getFirst());
// }
return null;
}
/**
* Internal use only.
* <p>
* Map of signatures to (op id, canonical start dir)
*/
public static Map<String, Pair<ResourceLocation, HexDir>> getPerWorldPatterns(ServerLevel overworld) {
var ds = overworld.getDataStorage();
Save perWorldPatterns =
ds.computeIfAbsent(Save::load, () -> Save.create(overworld.getSeed()), TAG_SAVED_DATA);
return perWorldPatterns.lookup;
}
public static ResourceLocation lookupPattern(Action action) {
return keyLookup.get(action);
}
/**
* Internal use only.
*/
public static PatternEntry lookupPattern(ResourceLocation opId) {
if (perWorldPatternLookup.containsKey(opId)) {
var it = perWorldPatternLookup.get(opId);
return new PatternEntry(it.prototype, actionLookup.get(it.opId), true);
}
for (var kv : regularPatternLookup.entrySet()) {
var sig = kv.getKey();
var entry = kv.getValue();
if (entry.opId.equals(opId)) {
var pattern = HexPattern.fromAngles(sig, entry.preferredStart);
return new PatternEntry(pattern, actionLookup.get(entry.opId), false);
}
}
throw new IllegalArgumentException("could not find a pattern for " + opId);
}
/**
* Internal use only.
*/
public static Set<ResourceLocation> getAllPerWorldPatternNames() {
return perWorldPatternLookup.keySet();
}
public record SpecialHandlerEntry(ResourceLocation id, SpecialHandler handler) {
}
public static class RegisterPatternException extends Exception {
public RegisterPatternException(String msg, Object... formats) {
super(String.format(msg, formats));
}
}
private record RegularEntry(HexDir preferredStart, ResourceLocation opId) {
}
private record PerWorldEntry(HexPattern prototype, ResourceLocation opId) {
}
// Fake class we pretend to use internally
public record PatternEntry(HexPattern prototype, Action action, boolean isPerWorld) {
}
/**
* 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";
// Maps hex signatures to (op ids, canonical start dir)
private Map<String, Pair<ResourceLocation, HexDir>> lookup;
private boolean missingEntries;
public Save(Map<String, Pair<ResourceLocation, HexDir>> lookup, boolean missingEntries) {
this.lookup = lookup;
this.missingEntries = missingEntries;
}
public Save(Map<String, Pair<ResourceLocation, HexDir>> lookup) {
this(lookup, missingEntries(lookup));
}
private static boolean missingEntries(Map<String, Pair<ResourceLocation, HexDir>> lookup) {
var allIds = lookup.values().stream().map(Pair::getFirst).collect(Collectors.toSet());
return perWorldPatternLookup.values().stream().anyMatch(it -> allIds.contains(it.opId));
}
private void fillMissingEntries(long seed) {
if (missingEntries) {
var doneAny = false;
var allIds = lookup.values().stream().map(Pair::getFirst).collect(Collectors.toSet());
for (var entry : perWorldPatternLookup.values()) {
if (!allIds.contains(entry.opId)) {
scrungle(lookup, entry.prototype, entry.opId, seed);
doneAny = true;
}
}
if (doneAny) {
setDirty();
missingEntries = false;
}
}
}
@Override
public CompoundTag save(CompoundTag tag) {
this.lookup.forEach((sig, rhs) -> {
var entry = new CompoundTag();
entry.putString(TAG_OP_ID, rhs.getFirst().toString());
entry.putInt(TAG_START_DIR, rhs.getSecond().ordinal());
tag.put(sig, entry);
});
return tag;
}
private static Save load(CompoundTag tag) {
var map = new HashMap<String, Pair<ResourceLocation, HexDir>>();
var allIds = new HashSet<ResourceLocation>();
for (var sig : tag.getAllKeys()) {
var entry = tag.getCompound(sig);
var opId = ResourceLocation.tryParse(entry.getString(TAG_OP_ID));
allIds.add(opId);
var startDir = HexDir.values()[entry.getInt(TAG_START_DIR)];
map.put(sig, new Pair<>(opId, startDir));
}
var missingEntries = perWorldPatternLookup.values().stream().anyMatch(it -> allIds.contains(it.opId));
return new Save(map, missingEntries);
}
private static void scrungle(Map<String, Pair<ResourceLocation, HexDir>> lookup, HexPattern prototype,
ResourceLocation opId, long seed) {
var scrungled = EulerPathFinder.findAltDrawing(prototype, seed, it -> {
var sig = it.anglesSignature();
return !lookup.containsKey(sig) &&
!regularPatternLookup.containsKey(sig)
&& specialHandlers.stream().noneMatch(handler -> handler.handler.handlePattern(it) != null);
});
lookup.put(scrungled.anglesSignature(), new Pair<>(opId, scrungled.getStartDir()));
}
public static Save create(long seed) {
var map = new HashMap<String, Pair<ResourceLocation, HexDir>>();
PatternRegistry.perWorldPatternLookup.values().forEach(it -> scrungle(map, it.prototype, it.opId, seed));
var save = new Save(map);
save.setDirty();
return save;
}
}
public static final String TAG_SAVED_DATA = "hex.per-world-patterns";
public static String getPatternCountInfo() {
return String.format(
"Loaded %d regular patterns, " +
"%d per-world patterns, and " +
"%d special handlers.", regularPatternLookup.size(), perWorldPatternLookup.size(),
specialHandlers.size());
}
}

View file

@ -1,17 +0,0 @@
package at.petrak.hexcasting.api;
import at.petrak.hexcasting.api.spell.Action;
import at.petrak.hexcasting.api.spell.math.HexPattern;
import org.jetbrains.annotations.Nullable;
/**
* Special handling of a pattern. Before checking any of the normal angle-signature based patterns,
* a given pattern is run by all of these special handlers patterns. If none of them return non-null,
* then its signature is checked.
* <p>
* In the base mod, this is used for number patterns and Bookkeeper's Gambit.
*/
@FunctionalInterface
public interface SpecialHandler {
@Nullable Action handlePattern(HexPattern pattern);
}

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.addldata; package at.petrak.hexcasting.api.addldata;
import at.petrak.hexcasting.api.spell.iota.Iota; import at.petrak.hexcasting.api.casting.iota.Iota;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View file

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

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.addldata; package at.petrak.hexcasting.api.addldata;
import at.petrak.hexcasting.api.spell.iota.Iota; import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.common.entities.EntityWallScroll; import at.petrak.hexcasting.common.entities.EntityWallScroll;
import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.block.circle; package at.petrak.hexcasting.api.block.circle;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.block.circle; package at.petrak.hexcasting.api.block.circle;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;

View file

@ -4,11 +4,11 @@ import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.misc.FrozenColorizer; import at.petrak.hexcasting.api.misc.FrozenColorizer;
import at.petrak.hexcasting.api.misc.MediaConstants; import at.petrak.hexcasting.api.misc.MediaConstants;
import at.petrak.hexcasting.api.mod.HexConfig; import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.api.spell.ParticleSpray; import at.petrak.hexcasting.api.casting.ParticleSpray;
import at.petrak.hexcasting.api.spell.casting.CastingContext; import at.petrak.hexcasting.api.casting.eval.CastingContext;
import at.petrak.hexcasting.api.spell.casting.CastingHarness; import at.petrak.hexcasting.api.casting.eval.CastingHarness;
import at.petrak.hexcasting.api.spell.casting.SpellCircleContext; import at.petrak.hexcasting.api.casting.eval.SpellCircleContext;
import at.petrak.hexcasting.api.spell.iota.PatternIota; import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.api.utils.MediaHelper; import at.petrak.hexcasting.api.utils.MediaHelper;
import at.petrak.hexcasting.common.items.magic.ItemCreativeUnlocker; import at.petrak.hexcasting.common.items.magic.ItemCreativeUnlocker;
import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.common.lib.HexItems;

View file

@ -1,9 +1,8 @@
package at.petrak.hexcasting.api.spell package at.petrak.hexcasting.api.casting
import at.petrak.hexcasting.api.PatternRegistry import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.api.utils.lightPurple import at.petrak.hexcasting.api.utils.lightPurple
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
@ -15,6 +14,12 @@ import java.text.DecimalFormat
* Manipulates the stack in some way, usually by popping some number of values off the stack * Manipulates the stack in some way, usually by popping some number of values off the stack
* and pushing one new value. * and pushing one new value.
* For a more "traditional" pop arguments, push return experience, see [ConstMediaAction]. * For a more "traditional" pop arguments, push return experience, see [ConstMediaAction].
*
* Instances of this can exist on the client, but they should NEVER be used there. They only
* exist on the client because Minecraft's registry system demands they do; any information
* the client needs about them is stored elsewhere. (For example, their canonical stroke order
* is stored in [ActionRegistryEntry], and their localization key is gotten from the resource key
* via [at.petrak.hexcasting.api.HexAPI.getActionI18nKey].)
*/ */
interface Action { interface Action {
/** /**
@ -53,7 +58,9 @@ interface Action {
/** /**
* The component for displaying this pattern's name. Override for dynamic patterns. * The component for displaying this pattern's name. Override for dynamic patterns.
*/ */
val displayName: Component get() = "hexcasting.spell.${PatternRegistry.lookupPattern(this)}".asTranslatedComponent.lightPurple fun getDisplayName(resLoc: ResourceLocation): Component {
return "hexcasting.spell.${resLoc.toString()}".asTranslatedComponent.lightPurple
}
companion object { companion object {
// I see why vzakii did this: you can't raycast out to infinity! // I see why vzakii did this: you can't raycast out to infinity!
@ -73,7 +80,7 @@ interface Action {
listOf(x) listOf(x)
} }
private val DOUBLE_FORMATTER = DecimalFormat("####.####") public val DOUBLE_FORMATTER = DecimalFormat("####.####")
@JvmStatic @JvmStatic
fun makeConstantOp(x: Double, key: ResourceLocation): Action = object : ConstMediaAction { fun makeConstantOp(x: Double, key: ResourceLocation): Action = object : ConstMediaAction {
@ -83,8 +90,9 @@ interface Action {
override fun execute(args: List<Iota>, ctx: CastingContext): List<Iota> = override fun execute(args: List<Iota>, ctx: CastingContext): List<Iota> =
x.asActionResult x.asActionResult
override val displayName: Component override fun getDisplayName(resLoc: ResourceLocation): Component {
get() = "hexcasting.spell.$key".asTranslatedComponent(DOUBLE_FORMATTER.format(x)).lightPurple return "hexcasting.spell.$key".asTranslatedComponent(DOUBLE_FORMATTER.format(x)).lightPurple
}
} }
} }
} }

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.spell; package at.petrak.hexcasting.api.casting;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
/** /**
* A bit of wrapper information around an action to go in the registry. * A bit of wrapper information around an action to go in the registry.

View file

@ -1,10 +1,10 @@
package at.petrak.hexcasting.api.spell package at.petrak.hexcasting.api.casting
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.sideeffects.OperatorSideEffect import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs
/** /**
* A SimpleOperator that always costs the same amount of media. * A SimpleOperator that always costs the same amount of media.

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell package at.petrak.hexcasting.api.casting
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.sideeffects.OperatorSideEffect import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
/** /**
* What happens when an operator is through? * What happens when an operator is through?

View file

@ -1,11 +1,11 @@
@file:JvmName("OperatorUtils") @file:JvmName("OperatorUtils")
package at.petrak.hexcasting.api.spell package at.petrak.hexcasting.api.casting
import at.petrak.hexcasting.api.spell.iota.* import at.petrak.hexcasting.api.casting.iota.*
import at.petrak.hexcasting.api.spell.math.HexPattern import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import com.mojang.datafixers.util.Either import com.mojang.datafixers.util.Either
import com.mojang.math.Vector3f import com.mojang.math.Vector3f

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell package at.petrak.hexcasting.api.casting
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.common.network.MsgCastParticleAck import at.petrak.hexcasting.common.network.MsgCastParticleAck

View file

@ -0,0 +1,56 @@
package at.petrak.hexcasting.api.casting;
import net.minecraft.resources.ResourceKey;
/**
* Possible things we find when trying to match a pattern's shape.
*/
public abstract sealed class PatternShapeMatch {
/**
* I've never met that pattern in my life
*/
public static final class Nothing extends PatternShapeMatch {
}
/**
* The shape exactly matches a pattern that isn't altered per world
*/
public static final class Normal extends PatternShapeMatch {
public final ResourceKey<ActionRegistryEntry> key;
public Normal(ResourceKey<ActionRegistryEntry> key) {
this.key = key;
}
}
/**
* The pattern is the right <em>shape</em> to be one of the per-world patterns.
* <p>
* On the server, {@link PerWorld#certain} means whether this is an exact match, or if it's just the
* right shape. (In other words it should only actually be casted if it is true.)
* <p>
* On the client, it is always false.
*/
public static final class PerWorld extends PatternShapeMatch {
public final ResourceKey<ActionRegistryEntry> key;
public final boolean certain;
public PerWorld(ResourceKey<ActionRegistryEntry> key, boolean certain) {
this.key = key;
this.certain = certain;
}
}
/**
* The shape matches a special handler
*/
public static final class Special extends PatternShapeMatch {
public final ResourceKey<SpecialHandler.Factory<?>> key;
public final SpecialHandler handler;
public Special(ResourceKey<SpecialHandler.Factory<?>> key, SpecialHandler handler) {
this.key = key;
this.handler = handler;
}
}
}

View file

@ -0,0 +1,7 @@
package at.petrak.hexcasting.api.casting
import at.petrak.hexcasting.api.casting.eval.CastingContext
interface RenderedSpell {
fun cast(ctx: CastingContext)
}

View file

@ -0,0 +1,40 @@
package at.petrak.hexcasting.api.casting;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
/**
* Special handling of a pattern. Before checking any of the normal angle-signature based patterns,
* a given pattern is run by all of these special handlers patterns. If none of them return non-null,
* then its signature is checked.
* <p>
* In the base mod, this is used for number patterns and Bookkeeper's Gambit.
* <p>
* There's a separation between the special handlers and their factories so we never have to use
* {@link Action} instances on the client. We can have SpecialHandlers on the client though because they're just
* wrappers.
*/
public abstract class SpecialHandler {
/**
* Convert this to an action, for modification of the stack and state.
* <p>
* This is called on the SERVER-SIDE ONLY.
*/
public abstract Action act();
/**
* Get the name of this handler.
*/
public abstract Component getName();
/**
* Given a pattern, possibly make up the special handler from it.
* <p>
* This is what goes in the registry! Think of it like BlockEntityType vs BlockEntity.
*/
@FunctionalInterface
public interface Factory<T extends SpecialHandler> {
@Nullable T tryMatch(HexPattern pattern);
}
}

View file

@ -1,10 +1,10 @@
package at.petrak.hexcasting.api.spell package at.petrak.hexcasting.api.casting
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.casting.eval.SpellContinuation import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.spell.casting.sideeffects.OperatorSideEffect import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs
interface SpellAction : Action { interface SpellAction : Action {
val argc: Int val argc: Int

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.spell package at.petrak.hexcasting.api.casting
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
/** /**
* Restricted interface for functional lists. * Restricted interface for functional lists.

View file

@ -1,12 +1,12 @@
package at.petrak.hexcasting.api.spell.casting package at.petrak.hexcasting.api.casting.eval
import at.petrak.hexcasting.api.HexAPI.modLoc import at.petrak.hexcasting.api.HexAPI.modLoc
import at.petrak.hexcasting.api.misc.DiscoveryHandlers import at.petrak.hexcasting.api.misc.DiscoveryHandlers
import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.spell.Action import at.petrak.hexcasting.api.casting.Action
import at.petrak.hexcasting.api.spell.mishaps.MishapEntityTooFarAway import at.petrak.hexcasting.api.casting.mishaps.MishapEntityTooFarAway
import at.petrak.hexcasting.api.spell.mishaps.MishapEvalTooDeep import at.petrak.hexcasting.api.casting.mishaps.MishapEvalTooDeep
import at.petrak.hexcasting.api.spell.mishaps.MishapLocationTooFarAway import at.petrak.hexcasting.api.casting.mishaps.MishapLocationTooFarAway
import at.petrak.hexcasting.api.utils.otherHand import at.petrak.hexcasting.api.utils.otherHand
import at.petrak.hexcasting.common.items.magic.ItemCreativeUnlocker import at.petrak.hexcasting.common.items.magic.ItemCreativeUnlocker
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions

View file

@ -1,30 +1,31 @@
package at.petrak.hexcasting.api.spell.casting package at.petrak.hexcasting.api.casting.eval
import at.petrak.hexcasting.api.PatternRegistry import at.petrak.hexcasting.api.HexAPI
import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus
import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.casting.PatternShapeMatch
import at.petrak.hexcasting.api.casting.PatternShapeMatch.*
import at.petrak.hexcasting.api.casting.SpellList
import at.petrak.hexcasting.api.casting.eval.sideeffects.EvalSound
import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect
import at.petrak.hexcasting.api.casting.eval.vm.FrameEvaluate
import at.petrak.hexcasting.api.casting.eval.vm.FunctionalData
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.iota.ListIota
import at.petrak.hexcasting.api.casting.iota.PatternIota
import at.petrak.hexcasting.api.casting.math.HexDir
import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.casting.mishaps.*
import at.petrak.hexcasting.api.misc.DiscoveryHandlers import at.petrak.hexcasting.api.misc.DiscoveryHandlers
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.misc.HexDamageSources
import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.mod.HexStatistics import at.petrak.hexcasting.api.mod.HexStatistics
import at.petrak.hexcasting.api.mod.HexTags import at.petrak.hexcasting.api.mod.HexTags
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
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.api.utils.*
import at.petrak.hexcasting.common.casting.PatternRegistryManifest
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import at.petrak.hexcasting.xplat.IXplatAbstractions import at.petrak.hexcasting.xplat.IXplatAbstractions
@ -32,7 +33,6 @@ import net.minecraft.ChatFormatting
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.sounds.SoundSource import net.minecraft.sounds.SoundSource
import net.minecraft.util.Mth import net.minecraft.util.Mth
@ -43,7 +43,10 @@ import kotlin.math.min
/** /**
* Keeps track of a player casting a spell on the server. * Keeps track of a player casting a spell on the server.
* It's stored as NBT on the wand. * It's stored as NBT on the player.
*
* TODO oh god this entire class needs a gigantic refactor. why are there like 6 different entrypoints for casting
* a pattern. oh god.
*/ */
class CastingHarness private constructor( class CastingHarness private constructor(
var stack: MutableList<Iota>, var stack: MutableList<Iota>,
@ -66,7 +69,7 @@ class CastingHarness private constructor(
*/ */
fun executeIota(iota: Iota, world: ServerLevel): ControllerInfo = executeIotas(listOf(iota), world) fun executeIota(iota: Iota, world: ServerLevel): ControllerInfo = executeIotas(listOf(iota), world)
private fun displayPattern(escapeNext: Boolean, parenCount: Int, iotaRepresentation: Component) { private fun displayPatternDebug(escapeNext: Boolean, parenCount: Int, iotaRepresentation: Component) {
if (this.ctx.debugPatterns) { if (this.ctx.debugPatterns) {
val display = " ".repeat(parenCount).asTextComponent val display = " ".repeat(parenCount).asTextComponent
if (escapeNext) if (escapeNext)
@ -77,24 +80,6 @@ class CastingHarness private constructor(
} }
} }
private fun getOperatorForPattern(iota: Iota, world: ServerLevel): Action? {
if (iota is PatternIota)
return PatternRegistry.matchPattern(iota.pattern, world)
return null
}
private fun getPatternForFrame(frame: ContinuationFrame): HexPattern? {
if (frame !is FrameEvaluate) return null
return (frame.list.car as? PatternIota)?.pattern
}
private fun getOperatorForFrame(frame: ContinuationFrame, world: ServerLevel): Action? {
if (frame !is FrameEvaluate) return null
return getOperatorForPattern(frame.list.car, world)
}
/** /**
* Given a list of iotas, execute them in sequence. * Given a list of iotas, execute them in sequence.
*/ */
@ -109,28 +94,9 @@ class CastingHarness private constructor(
// Take the top of the continuation stack... // Take the top of the continuation stack...
val next = continuation.frame val next = continuation.frame
// ...and execute it. // ...and execute it.
val result = try { // TODO there used to be error checking code here; I'm pretty sure any and all mishaps should already
next.evaluate(continuation.next, world, this) // get caught and folded into CastResult by evaluate.
} catch (mishap: Mishap) { val result = next.evaluate(continuation.next, world, this)
val pattern = getPatternForFrame(next)
val operator = try {
getOperatorForFrame(next, world)
} catch (e: Throwable) {
null
}
CastResult(
continuation,
null,
mishap.resolutionType(ctx),
listOf(
OperatorSideEffect.DoMishap(
mishap,
Mishap.Context(pattern ?: HexPattern(HexDir.WEST), operator)
)
),
HexEvalSounds.MISHAP,
)
}
// Then write all pertinent data back to the harness for the next iteration. // Then write all pertinent data back to the harness for the next iteration.
if (result.newData != null) { if (result.newData != null) {
this.applyFunctionalData(result.newData) this.applyFunctionalData(result.newData)
@ -172,11 +138,35 @@ class CastingHarness private constructor(
) )
} }
/**
* this DOES NOT THROW THINGS
*/
@Throws()
fun getUpdate(iota: Iota, world: ServerLevel, continuation: SpellContinuation): CastResult { fun getUpdate(iota: Iota, world: ServerLevel, continuation: SpellContinuation): CastResult {
try { try {
// TODO we can have a special intro/retro sound // TODO we can have a special intro/retro sound
this.handleParentheses(iota)?.let { (data, resolutionType) -> // ALSO TODO need to add reader macro-style things
return@getUpdate CastResult(continuation, data, resolutionType, listOf(), HexEvalSounds.OPERATOR) try {
this.handleParentheses(iota)?.let { (data, resolutionType) ->
return@getUpdate CastResult(continuation, data, resolutionType, listOf(), HexEvalSounds.OPERATOR)
}
} catch (e: MishapTooManyCloseParens) {
// This is ridiculous and needs to be fixed
return CastResult(
continuation,
null,
ResolvedPatternType.ERRORED,
listOf(
OperatorSideEffect.DoMishap(
e,
Mishap.Context(
(iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST),
HexAPI.instance().getActionI18(HexAPI.modLoc("retrospection"), false)
)
)
),
HexEvalSounds.MISHAP
)
} }
if (iota is PatternIota) { if (iota is PatternIota) {
@ -195,35 +185,9 @@ class CastingHarness private constructor(
HexEvalSounds.MISHAP HexEvalSounds.MISHAP
) )
} }
} catch (mishap: Mishap) {
val operator = try {
getOperatorForPattern(iota, world)
} catch (e: Throwable) {
null
}
return CastResult(
continuation,
null,
mishap.resolutionType(ctx),
listOf(
OperatorSideEffect.DoMishap(
mishap,
Mishap.Context(
(iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST),
operator
)
)
),
HexEvalSounds.MISHAP
)
} catch (exception: Exception) { } catch (exception: Exception) {
// This means something very bad has happened // This means something very bad has happened
exception.printStackTrace() exception.printStackTrace()
val operator = try {
getOperatorForPattern(iota, world)
} catch (e: Throwable) {
null
}
return CastResult( return CastResult(
continuation, continuation,
null, null,
@ -233,7 +197,7 @@ class CastingHarness private constructor(
MishapError(exception), MishapError(exception),
Mishap.Context( Mishap.Context(
(iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST), (iota as? PatternIota)?.pattern ?: HexPattern(HexDir.WEST),
operator null
) )
) )
), ),
@ -247,32 +211,51 @@ class CastingHarness private constructor(
* handle it functionally. * handle it functionally.
*/ */
fun updateWithPattern(newPat: HexPattern, world: ServerLevel, continuation: SpellContinuation): CastResult { fun updateWithPattern(newPat: HexPattern, world: ServerLevel, continuation: SpellContinuation): CastResult {
var actionIdPair: Pair<Action, ResourceLocation>? = null var castedName: Component? = null
try { try {
// Don't catch this one // Don't catch this one
val mojangPair = PatternRegistry.matchPatternAndID(newPat, world) val lookup = PatternRegistryManifest.matchPattern(newPat, world, false)
actionIdPair = mojangPair.first to mojangPair.second val actionNamePair = when (lookup) {
is Normal -> {
val action = IXplatAbstractions.INSTANCE.actionRegistry.get(lookup.key)
val i18n = HexAPI.instance().getActionI18nKey(lookup.key)
action!!.action to i18n.asTranslatedComponent.lightPurple
}
if (this.ctx.spellCircle == null && !HexConfig.server().isActionAllowed(actionIdPair.second)) { is PerWorld -> {
throw MishapDisallowedSpell() // it will always be exact match here.
} else if (this.ctx.spellCircle != null // TODO add non-exact checking as a hint to the player?
&& !HexConfig.server().isActionAllowedInCircles(actionIdPair.second) val action = IXplatAbstractions.INSTANCE.actionRegistry.get(lookup.key)
) { val i18n = HexAPI.instance().getActionI18nKey(lookup.key)
throw MishapDisallowedSpell("disallowed_circle") // what the hey let's make great spells golden
action!!.action to i18n.asTranslatedComponent.gold
}
is Special -> {
lookup.handler.act() to lookup.handler.name
}
is PatternShapeMatch.Nothing -> throw MishapInvalidPattern()
else -> throw IllegalStateException()
} }
castedName = actionNamePair.second
val action = actionNamePair.first
val pattern = actionIdPair.first // TODO: the config denylist should be handled per VM type.
// I just removed it for now, should re-add it...
val unenlightened = pattern.isGreat && !ctx.isCasterEnlightened // TODO need to check for enlightenment on VM
val requiresAndFailedEnlightenment = action.isGreat && !ctx.isCasterEnlightened
val sideEffects = mutableListOf<OperatorSideEffect>() val sideEffects = mutableListOf<OperatorSideEffect>()
var stack2: List<Iota>? = null var stack2: List<Iota>? = null
var cont2 = continuation var cont2 = continuation
var ravenmind2: Iota? = null var ravenmind2: Iota? = null
if (!unenlightened || pattern.alwaysProcessGreatSpell) { if (!requiresAndFailedEnlightenment || action.alwaysProcessGreatSpell) {
displayPattern(false, 0, pattern.displayName) displayPatternDebug(false, 0, castedName)
val result = pattern.operate( val result = action.operate(
continuation, continuation,
this.stack.toMutableList(), this.stack.toMutableList(),
this.ravenmind, this.ravenmind,
@ -285,8 +268,8 @@ class CastingHarness private constructor(
sideEffects.addAll(result.sideEffects) sideEffects.addAll(result.sideEffects)
} }
if (unenlightened) { if (requiresAndFailedEnlightenment) {
sideEffects.add(OperatorSideEffect.RequiredEnlightenment(pattern.causesBlindDiversion)) sideEffects.add(OperatorSideEffect.RequiredEnlightenment(action.causesBlindDiversion))
} }
// Stick a poofy particle effect at the caster position // Stick a poofy particle effect at the caster position
@ -311,6 +294,7 @@ class CastingHarness private constructor(
hereFd hereFd
} }
// TODO again this should be per VM
var soundType = if (this.ctx.source == CastingContext.CastSource.STAFF) { var soundType = if (this.ctx.source == CastingContext.CastSource.STAFF) {
HexEvalSounds.OPERATOR HexEvalSounds.OPERATOR
} else { } else {
@ -342,7 +326,7 @@ class CastingHarness private constructor(
continuation, continuation,
null, null,
mishap.resolutionType(ctx), mishap.resolutionType(ctx),
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, actionIdPair?.first))), listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, castedName))),
HexEvalSounds.MISHAP HexEvalSounds.MISHAP
) )
} }
@ -394,6 +378,7 @@ class CastingHarness private constructor(
* Return a non-null value if we handled this in some sort of parenthesey way, * Return a non-null value if we handled this in some sort of parenthesey way,
* either escaping it onto the stack or changing the parenthese-handling state. * either escaping it onto the stack or changing the parenthese-handling state.
*/ */
@Throws(MishapTooManyCloseParens::class)
private fun handleParentheses(iota: Iota): Pair<FunctionalData, ResolvedPatternType>? { private fun handleParentheses(iota: Iota): Pair<FunctionalData, ResolvedPatternType>? {
val sig = (iota as? PatternIota)?.pattern?.anglesSignature() val sig = (iota as? PatternIota)?.pattern?.anglesSignature()
@ -497,7 +482,7 @@ class CastingHarness private constructor(
.copy() .copy()
.withStyle(if (out.second == ResolvedPatternType.ESCAPED) ChatFormatting.YELLOW else ChatFormatting.AQUA) .withStyle(if (out.second == ResolvedPatternType.ESCAPED) ChatFormatting.YELLOW else ChatFormatting.AQUA)
} else iota.display() } else iota.display()
displayPattern(this.escapeNext, displayDepth, display) displayPatternDebug(this.escapeNext, displayDepth, display)
} }
return out return out
} }

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.casting package at.petrak.hexcasting.api.casting.eval
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.api.spell.casting package at.petrak.hexcasting.api.casting.eval
import at.petrak.hexcasting.api.spell.math.HexCoord import at.petrak.hexcasting.api.casting.math.HexCoord
import at.petrak.hexcasting.api.spell.math.HexPattern import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.api.utils.NBTBuilder
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import java.util.* import java.util.*

View file

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

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.api.spell.casting; package at.petrak.hexcasting.api.casting.eval;
import at.petrak.hexcasting.api.spell.math.HexDir; import at.petrak.hexcasting.api.casting.math.HexDir;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
public final class SpecialPatterns { public final class SpecialPatterns {
public static final HexPattern INTROSPECTION = HexPattern.fromAngles("qqq", HexDir.WEST); public static final HexPattern INTROSPECTION = HexPattern.fromAngles("qqq", HexDir.WEST);

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.casting package at.petrak.hexcasting.api.casting.eval
import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.api.utils.NBTBuilder
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.casting.sideeffects; package at.petrak.hexcasting.api.casting.eval.sideeffects;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View file

@ -1,13 +1,13 @@
package at.petrak.hexcasting.api.spell.casting.sideeffects package at.petrak.hexcasting.api.casting.eval.sideeffects
import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus
import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.casting.RenderedSpell
import at.petrak.hexcasting.api.casting.eval.CastingHarness
import at.petrak.hexcasting.api.casting.mishaps.Mishap
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.mod.HexStatistics 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.api.utils.asTranslatedComponent
import at.petrak.hexcasting.common.lib.HexItems import at.petrak.hexcasting.common.lib.HexItems
import net.minecraft.Util import net.minecraft.Util
@ -69,7 +69,7 @@ sealed class OperatorSideEffect {
data class DoMishap(val mishap: Mishap, val errorCtx: Mishap.Context) : OperatorSideEffect() { data class DoMishap(val mishap: Mishap, val errorCtx: Mishap.Context) : OperatorSideEffect() {
override fun performEffect(harness: CastingHarness): Boolean { override fun performEffect(harness: CastingHarness): Boolean {
val msg = mishap.errorMessage(harness.ctx, errorCtx); val msg = mishap.errorMessageWithName(harness.ctx, errorCtx);
if (harness.ctx.spellCircle != null) { if (harness.ctx.spellCircle != null) {
val tile = harness.ctx.world.getBlockEntity(harness.ctx.spellCircle.impetusPos) val tile = harness.ctx.world.getBlockEntity(harness.ctx.spellCircle.impetusPos)
if (tile is BlockEntityAbstractImpetus) { if (tile is BlockEntityAbstractImpetus) {

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.casting.eval package at.petrak.hexcasting.api.casting.eval.vm
import at.petrak.hexcasting.api.spell.SpellList import at.petrak.hexcasting.api.casting.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingHarness import at.petrak.hexcasting.api.casting.eval.CastingHarness
import at.petrak.hexcasting.api.spell.casting.CastingHarness.CastResult import at.petrak.hexcasting.api.casting.eval.CastingHarness.CastResult
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.utils.getList import at.petrak.hexcasting.api.utils.getList
import at.petrak.hexcasting.api.utils.hasList import at.petrak.hexcasting.api.utils.hasList
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes import at.petrak.hexcasting.common.lib.hex.HexIotaTypes

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.casting.eval package at.petrak.hexcasting.api.casting.eval.vm
import at.petrak.hexcasting.api.spell.SpellList import at.petrak.hexcasting.api.casting.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingHarness import at.petrak.hexcasting.api.casting.eval.CastingHarness
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.api.utils.serializeToNBT import at.petrak.hexcasting.api.utils.serializeToNBT
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexEvalSounds

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.casting.eval package at.petrak.hexcasting.api.casting.eval.vm
import at.petrak.hexcasting.api.spell.casting.CastingHarness import at.petrak.hexcasting.api.casting.eval.CastingHarness
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel

View file

@ -1,10 +1,10 @@
package at.petrak.hexcasting.api.spell.casting.eval package at.petrak.hexcasting.api.casting.eval.vm
import at.petrak.hexcasting.api.spell.SpellList import at.petrak.hexcasting.api.casting.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingHarness import at.petrak.hexcasting.api.casting.eval.CastingHarness
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.iota.ListIota import at.petrak.hexcasting.api.casting.iota.ListIota
import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.api.utils.serializeToNBT import at.petrak.hexcasting.api.utils.serializeToNBT
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexEvalSounds

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.spell.casting.eval package at.petrak.hexcasting.api.casting.eval.vm
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
/** /**
* A change to the data in a CastHarness after a pattern is drawn. * A change to the data in a CastHarness after a pattern is drawn.

View file

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

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.iota; package at.petrak.hexcasting.api.casting.iota;
import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.iota; package at.petrak.hexcasting.api.casting.iota;
import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.iota; package at.petrak.hexcasting.api.casting.iota;
import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.iota; package at.petrak.hexcasting.api.casting.iota;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;

View file

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

View file

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

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.spell.iota; package at.petrak.hexcasting.api.casting.iota;
import at.petrak.hexcasting.api.spell.SpellList; import at.petrak.hexcasting.api.casting.SpellList;
import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.iota; package at.petrak.hexcasting.api.casting.iota;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.spell.iota; package at.petrak.hexcasting.api.casting.iota;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.iota; package at.petrak.hexcasting.api.casting.iota;
import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.math package at.petrak.hexcasting.api.casting.math
import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.HexAPI
import java.util.* import java.util.*

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.math package at.petrak.hexcasting.api.casting.math
enum class HexAngle { enum class HexAngle {
FORWARD, RIGHT, RIGHT_BACK, BACK, LEFT_BACK, LEFT; FORWARD, RIGHT, RIGHT_BACK, BACK, LEFT_BACK, LEFT;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.math package at.petrak.hexcasting.api.casting.math
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.math package at.petrak.hexcasting.api.casting.math
import at.petrak.hexcasting.api.utils.getSafe import at.petrak.hexcasting.api.utils.getSafe

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.api.spell.math package at.petrak.hexcasting.api.casting.math
import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.api.utils.NBTBuilder
import at.petrak.hexcasting.api.utils.coordToPx import at.petrak.hexcasting.api.utils.coordToPx

View file

@ -1,13 +1,12 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.mod.HexTags import at.petrak.hexcasting.api.mod.HexTags
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.api.utils.lightPurple import at.petrak.hexcasting.api.utils.lightPurple
import at.petrak.hexcasting.common.lib.HexItems import at.petrak.hexcasting.common.lib.HexItems
@ -41,7 +40,18 @@ abstract class Mishap : Throwable() {
*/ */
abstract fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<Iota>) abstract fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<Iota>)
abstract fun errorMessage(ctx: CastingContext, errorCtx: Context): Component abstract protected fun errorMessage(ctx: CastingContext, errorCtx: Context): Component
/**
* Every error message should be prefixed with the name of the action...
*/
public fun errorMessageWithName(ctx: CastingContext, errorCtx: Context): Component {
return if (errorCtx.name != null) {
errorCtx.name.copy().append(": ").append(this.errorMessage(ctx, errorCtx))
} else {
this.errorMessage(ctx, errorCtx)
}
}
// Useful helper functions // Useful helper functions
@ -54,8 +64,8 @@ abstract class Mishap : Throwable() {
protected fun error(stub: String, vararg args: Any): Component = protected fun error(stub: String, vararg args: Any): Component =
"hexcasting.mishap.$stub".asTranslatedComponent(*args) "hexcasting.mishap.$stub".asTranslatedComponent(*args)
protected fun actionName(action: Action?): Component = protected fun actionName(name: Component?): Component =
action?.displayName ?: "hexcasting.spell.null".asTranslatedComponent.lightPurple name ?: "hexcasting.spell.null".asTranslatedComponent.lightPurple
protected fun yeetHeldItemsTowards(ctx: CastingContext, targetPos: Vec3) { protected fun yeetHeldItemsTowards(ctx: CastingContext, targetPos: Vec3) {
// Knock the player's items out of their hands // Knock the player's items out of their hands
@ -101,7 +111,7 @@ abstract class Mishap : Throwable() {
return ctx.world.getBlockState(pos).block.name return ctx.world.getBlockState(pos).block.name
} }
data class Context(val pattern: HexPattern, val action: Action?) data class Context(val pattern: HexPattern, val name: Component?)
companion object { companion object {
fun trulyHurt(entity: LivingEntity, source: DamageSource, amount: Float) { fun trulyHurt(entity: LivingEntity, source: DamageSource, amount: Float) {

View file

@ -1,10 +1,10 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.misc.HexDamageSources
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import net.minecraft.world.entity.Mob import net.minecraft.world.entity.Mob
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component

View file

@ -1,10 +1,10 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.misc.HexDamageSources
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.world.entity.Mob import net.minecraft.world.entity.Mob
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.utils.aqua import at.petrak.hexcasting.api.utils.aqua
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
@ -19,7 +19,7 @@ class MishapBadEntity(val entity: Entity, val wanted: Component) : Mishap() {
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
error("bad_entity", actionName(errorCtx.action), wanted, entity.displayName.plainCopy().aqua) error("bad_entity", wanted, entity.displayName.plainCopy().aqua)
companion object { companion object {
@JvmStatic @JvmStatic

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
@ -17,9 +17,9 @@ class MishapBadItem(val item: ItemEntity, val wanted: Component) : Mishap() {
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = if (item.item.isEmpty) override fun errorMessage(ctx: CastingContext, errorCtx: Context) = if (item.item.isEmpty)
error("no_item", actionName(errorCtx.action), wanted) error("no_item", wanted)
else else
error("bad_item", actionName(errorCtx.action), wanted, item.item.count, item.item.displayName) error("bad_item", wanted, item.item.count, item.item.displayName)
companion object { companion object {
@JvmStatic @JvmStatic

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.InteractionHand import net.minecraft.world.InteractionHand
@ -18,9 +18,9 @@ class MishapBadOffhandItem(val item: ItemStack, val hand: InteractionHand, val w
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = if (item.isEmpty) override fun errorMessage(ctx: CastingContext, errorCtx: Context) = if (item.isEmpty)
error("no_item.offhand", actionName(errorCtx.action), wanted) error("no_item.offhand", wanted)
else else
error("bad_item.offhand", actionName(errorCtx.action), wanted, item.count, item.displayName) error("bad_item.offhand", wanted, item.count, item.displayName)
companion object { companion object {
@JvmStatic @JvmStatic

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapDisallowedSpell(val type: String = "disallowed") : Mishap() { class MishapDisallowedSpell(val type: String = "disallowed") : Mishap() {
@ -17,5 +17,5 @@ class MishapDisallowedSpell(val type: String = "disallowed") : Mishap() {
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
error(type, actionName(errorCtx.action)) error(type)
} }

View file

@ -1,12 +1,12 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.misc.HexDamageSources
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.iota.DoubleIota import at.petrak.hexcasting.api.casting.iota.DoubleIota
import at.petrak.hexcasting.api.spell.iota.GarbageIota import at.petrak.hexcasting.api.casting.iota.GarbageIota
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.iota.Vec3Iota import at.petrak.hexcasting.api.casting.iota.Vec3Iota
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
@ -17,5 +17,5 @@ class MishapEntityTooFarAway(val entity: Entity) : Mishap() {
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component = override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component =
error("entity_too_far", entity.displayName, actionName(errorCtx.action)) error("entity_too_far", entity.displayName)
} }

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapError(val exception: Exception) : Mishap() { class MishapError(val exception: Exception) : Mishap() {
@ -14,5 +14,5 @@ class MishapError(val exception: Exception) : Mishap() {
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
error("unknown", actionName(errorCtx.action), exception) error("unknown", exception)
} }

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapEvalTooDeep : Mishap() { class MishapEvalTooDeep : Mishap() {

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.utils.aqua import at.petrak.hexcasting.api.utils.aqua
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
@ -16,5 +16,5 @@ class MishapImmuneEntity(val entity: Entity) : Mishap() {
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
error("immune_entity", actionName(errorCtx.action), entity.displayName.plainCopy().aqua) error("immune_entity", entity.displayName.plainCopy().aqua)
} }

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.GarbageIota
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.GarbageIota
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
@ -27,7 +27,7 @@ class MishapInvalidIota(
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
error( error(
"invalid_value", actionName(errorCtx.action), expected, reverseIdx, "invalid_value", expected, reverseIdx,
perpetrator.display() perpetrator.display()
) )

View file

@ -1,10 +1,10 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.spell.iota.GarbageIota import at.petrak.hexcasting.api.casting.iota.GarbageIota
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapInvalidPattern : Mishap() { class MishapInvalidPattern : Mishap() {

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
/** /**

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.GarbageIota
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.GarbageIota
import at.petrak.hexcasting.api.spell.iota.Iota
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
@ -18,7 +18,7 @@ class MishapLocationInWrongDimension(val properDimension: ResourceLocation) : Mi
override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component = override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component =
error( error(
"wrong_dimension", actionName(errorCtx.action!!), properDimension.toString(), "wrong_dimension", properDimension.toString(),
ctx.world.dimension().location().toString() ctx.world.dimension().location().toString()
) )
} }

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.iota.Vec3Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.iota.Vec3Iota
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
@ -17,5 +17,5 @@ class MishapLocationTooFarAway(val location: Vec3, val type: String = "too_far")
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component = override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component =
error("location_$type", Vec3Iota.display(location), actionName(errorCtx.action)) error("location_$type", Vec3Iota.display(location))
} }

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
@ -31,5 +31,5 @@ class MishapNoSpellCircle : Mishap() {
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
error("no_spell_circle", actionName(errorCtx.action)) error("no_spell_circle")
} }

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.casting.iota.GarbageIota
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.GarbageIota
import at.petrak.hexcasting.api.spell.iota.Iota
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapNotEnoughArgs(val expected: Int, val got: Int) : Mishap() { class MishapNotEnoughArgs(val expected: Int, val got: Int) : Mishap() {
@ -16,7 +16,7 @@ class MishapNotEnoughArgs(val expected: Int, val got: Int) : Mishap() {
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
if (got == 0) if (got == 0)
error("no_args", actionName(errorCtx.action), expected) error("no_args", expected)
else else
error("not_enough_args", actionName(errorCtx.action), expected, got) error("not_enough_args", expected, got)
} }

View file

@ -1,10 +1,10 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.iota.EntityIota import at.petrak.hexcasting.api.casting.iota.EntityIota
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.iota.ListIota import at.petrak.hexcasting.api.casting.iota.ListIota
import net.minecraft.world.effect.MobEffectInstance import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.misc.HexDamageSources
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapShameOnYou() : Mishap() { class MishapShameOnYou() : Mishap() {

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.iota.PatternIota import at.petrak.hexcasting.api.casting.iota.PatternIota
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapTooManyCloseParens : Mishap() { class MishapTooManyCloseParens : Mishap() {

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.casting.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
/** /**

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.item; package at.petrak.hexcasting.api.item;
import at.petrak.hexcasting.api.spell.iota.Iota; import at.petrak.hexcasting.api.casting.iota.Iota;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.item; package at.petrak.hexcasting.api.item;
import at.petrak.hexcasting.api.spell.iota.Iota; import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.ClientTickCounter; import at.petrak.hexcasting.client.ClientTickCounter;
@ -27,7 +27,7 @@ import java.util.List;
public interface IotaHolderItem { public interface IotaHolderItem {
/** /**
* If this key is set on the item, we ignore the rest of the item and render this as if it were of the * If this key is set on the item, we ignore the rest of the item and render this as if it were of the
* {@link at.petrak.hexcasting.api.spell.iota.IotaType IotaType} given by the resource location. * {@link at.petrak.hexcasting.api.casting.iota.IotaType IotaType} given by the resource location.
* <p> * <p>
* This is not useful to the player at all. * This is not useful to the player at all.
*/ */

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.misc; package at.petrak.hexcasting.api.misc;
import at.petrak.hexcasting.api.addldata.ADMediaHolder; import at.petrak.hexcasting.api.addldata.ADMediaHolder;
import at.petrak.hexcasting.api.spell.casting.CastingContext; import at.petrak.hexcasting.api.casting.eval.CastingContext;
import at.petrak.hexcasting.api.spell.casting.CastingHarness; import at.petrak.hexcasting.api.casting.eval.CastingHarness;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.api.mod; package at.petrak.hexcasting.api.mod;
import at.petrak.hexcasting.api.spell.ActionRegistryEntry; import at.petrak.hexcasting.api.casting.ActionRegistryEntry;
import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;

View file

@ -1,7 +0,0 @@
package at.petrak.hexcasting.api.spell
import at.petrak.hexcasting.api.spell.casting.CastingContext
interface RenderedSpell {
fun cast(ctx: CastingContext)
}

View file

@ -2,9 +2,9 @@
package at.petrak.hexcasting.api.utils package at.petrak.hexcasting.api.utils
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.iota.ListIota import at.petrak.hexcasting.api.casting.iota.ListIota
import at.petrak.hexcasting.api.spell.math.HexCoord import at.petrak.hexcasting.api.casting.math.HexCoord
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.nbt.* import net.minecraft.nbt.*

View file

@ -1,28 +1,29 @@
package at.petrak.hexcasting.api.utils; package at.petrak.hexcasting.api.utils;
import at.petrak.hexcasting.api.PatternRegistry; import at.petrak.hexcasting.common.casting.PatternRegistryManifest;
import at.petrak.hexcasting.api.spell.casting.SpecialPatterns; import at.petrak.hexcasting.api.casting.eval.SpecialPatterns;
import at.petrak.hexcasting.api.spell.iota.PatternIota; import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
public class PatternNameHelper { public class PatternNameHelper {
public static Component representationForPattern(HexPattern pattern) { public static Component representationForPattern(HexPattern pattern) {
if (pattern.sigsEqual(SpecialPatterns.CONSIDERATION)) { if (pattern.sigsEqual(SpecialPatterns.CONSIDERATION)) {
return Component.translatable("hexcasting.spell.hexcasting:escape").withStyle(ChatFormatting.LIGHT_PURPLE); return Component.translatable("hexcasting.spell.hexcasting:escape").withStyle(ChatFormatting.LIGHT_PURPLE);
} else if (pattern.sigsEqual(SpecialPatterns.INTROSPECTION)) { } else if (pattern.sigsEqual(SpecialPatterns.INTROSPECTION)) {
return Component.translatable("hexcasting.spell.hexcasting:open_paren").withStyle(ChatFormatting.LIGHT_PURPLE); return Component.translatable("hexcasting.spell.hexcasting:open_paren").withStyle(ChatFormatting.LIGHT_PURPLE);
} else if (pattern.sigsEqual(SpecialPatterns.RETROSPECTION)) { } else if (pattern.sigsEqual(SpecialPatterns.RETROSPECTION)) {
return Component.translatable("hexcasting.spell.hexcasting:close_paren").withStyle(ChatFormatting.LIGHT_PURPLE); return Component.translatable("hexcasting.spell.hexcasting:close_paren").withStyle(ChatFormatting.LIGHT_PURPLE);
} }
var action = PatternRegistry.lookupPatternByShape(pattern); var action = PatternRegistryManifest.lookupPatternByShape(pattern);
if (action != null) { if (action != null) {
return action.getDisplayName(); return action.getDisplayName();
} }
return new PatternIota(pattern).display(); // TODO: this should be merged into iota.display once Great Spells can be identified by name return new PatternIota(pattern).display(); // TODO: this should be merged into iota.display once Great Spells
} // can be identified by name
}
} }

View file

@ -0,0 +1,4 @@
package at.petrak.hexcasting.client;
public class PatternShapeMatcher {
}

View file

@ -3,7 +3,7 @@
package at.petrak.hexcasting.client package at.petrak.hexcasting.client
import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.spell.math.HexPattern import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.utils.TAU import at.petrak.hexcasting.api.utils.TAU
import at.petrak.hexcasting.api.utils.getValue import at.petrak.hexcasting.api.utils.getValue
import at.petrak.hexcasting.api.utils.setValue import at.petrak.hexcasting.api.utils.setValue

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.client.be; package at.petrak.hexcasting.client.be;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.client.RenderLib; import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf; import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf; import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf;

View file

@ -3,13 +3,13 @@ package at.petrak.hexcasting.client.gui
import at.petrak.hexcasting.api.misc.DiscoveryHandlers import at.petrak.hexcasting.api.misc.DiscoveryHandlers
import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.mod.HexTags import at.petrak.hexcasting.api.mod.HexTags
import at.petrak.hexcasting.api.spell.casting.ControllerInfo import at.petrak.hexcasting.api.casting.eval.ControllerInfo
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern import at.petrak.hexcasting.api.casting.eval.ResolvedPattern
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternType import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType
import at.petrak.hexcasting.api.spell.math.HexAngle import at.petrak.hexcasting.api.casting.math.HexAngle
import at.petrak.hexcasting.api.spell.math.HexCoord import at.petrak.hexcasting.api.casting.math.HexCoord
import at.petrak.hexcasting.api.spell.math.HexDir import at.petrak.hexcasting.api.casting.math.HexDir
import at.petrak.hexcasting.api.spell.math.HexPattern import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.utils.asTranslatedComponent import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.client.* import at.petrak.hexcasting.client.*
import at.petrak.hexcasting.client.ktxt.accumulatedScroll import at.petrak.hexcasting.client.ktxt.accumulatedScroll

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.client.gui; package at.petrak.hexcasting.client.gui;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.client.RenderLib; import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.common.misc.PatternTooltip; import at.petrak.hexcasting.common.misc.PatternTooltip;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.blocks.akashic; package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.annotations.SoftImplement; import at.petrak.hexcasting.annotations.SoftImplement;
import at.petrak.hexcasting.api.spell.iota.PatternIota; import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.common.items.ItemScroll; import at.petrak.hexcasting.common.items.ItemScroll;
import at.petrak.hexcasting.common.lib.HexSounds; import at.petrak.hexcasting.common.lib.HexSounds;
import at.petrak.hexcasting.xplat.IForgeLikeBlock; import at.petrak.hexcasting.xplat.IForgeLikeBlock;

View file

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

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.common.blocks.akashic; package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.api.block.HexBlockEntity; import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.spell.iota.Iota; import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexBlockEntities; import at.petrak.hexcasting.common.lib.HexBlockEntities;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.blocks.circles; package at.petrak.hexcasting.common.blocks.circles;
import at.petrak.hexcasting.api.block.circle.BlockCircleComponent; import at.petrak.hexcasting.api.block.circle.BlockCircleComponent;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.blocks.circles; package at.petrak.hexcasting.common.blocks.circles;
import at.petrak.hexcasting.api.block.HexBlockEntity; import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexBlockEntities; import at.petrak.hexcasting.common.lib.HexBlockEntities;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;

View file

@ -2,8 +2,8 @@ package at.petrak.hexcasting.common.blocks.circles;
import at.petrak.hexcasting.annotations.SoftImplement; import at.petrak.hexcasting.annotations.SoftImplement;
import at.petrak.hexcasting.api.block.circle.BlockCircleComponent; import at.petrak.hexcasting.api.block.circle.BlockCircleComponent;
import at.petrak.hexcasting.api.spell.iota.PatternIota; import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.common.lib.HexItems; import at.petrak.hexcasting.common.lib.HexItems;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.blocks.circles.directrix; package at.petrak.hexcasting.common.blocks.circles.directrix;
import at.petrak.hexcasting.api.block.circle.BlockCircleComponent; import at.petrak.hexcasting.api.block.circle.BlockCircleComponent;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.blocks.circles.directrix; package at.petrak.hexcasting.common.blocks.circles.directrix;
import at.petrak.hexcasting.api.block.circle.BlockCircleComponent; import at.petrak.hexcasting.api.block.circle.BlockCircleComponent;
import at.petrak.hexcasting.api.spell.math.HexPattern; import at.petrak.hexcasting.api.casting.math.HexPattern;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.core.particles.DustParticleOptions;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.blocks.circles.impetuses; package at.petrak.hexcasting.common.blocks.circles.impetuses;
import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus; import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.api.spell.iota.EntityIota; import at.petrak.hexcasting.api.casting.iota.EntityIota;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityStoredPlayerImpetus; import at.petrak.hexcasting.common.blocks.entity.BlockEntityStoredPlayerImpetus;
import at.petrak.hexcasting.common.lib.HexSounds; import at.petrak.hexcasting.common.lib.HexSounds;
import at.petrak.hexcasting.xplat.IXplatAbstractions; import at.petrak.hexcasting.xplat.IXplatAbstractions;

View file

@ -0,0 +1,200 @@
package at.petrak.hexcasting.common.casting;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.casting.ActionRegistryEntry;
import at.petrak.hexcasting.api.casting.PatternShapeMatch;
import at.petrak.hexcasting.api.casting.SpecialHandler;
import at.petrak.hexcasting.api.casting.math.EulerPathFinder;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import com.mojang.datafixers.util.Pair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.saveddata.SavedData;
import org.apache.commons.lang3.NotImplementedException;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
// Now an internal-only class used to do final processing on the registered stuff
public class PatternRegistryManifest {
// Map actions to their entry except for the per-world ones. Client and server side
public static final ConcurrentMap<String, ResourceKey<ActionRegistryEntry>> NORMAL_ACTION_LOOKUP =
new ConcurrentHashMap<>();
// On the server side, where we know such things, the jumbled patterns
//
// SERVER SIDE ONLY
public static final ConcurrentMap<String, ResourceKey<ActionRegistryEntry>> PER_WORLD_ACTION_LOOKUP =
new ConcurrentHashMap<>();
/**
* Process the registry!
* <p>
* Pass null for the OW to signal we're on the client
*/
public static void processRegistry(@Nullable ServerLevel overworld) {
ScrungledPatternsSave perWorldPatterns = null;
if (overworld != null) {
var ds = overworld.getDataStorage();
perWorldPatterns = ds.computeIfAbsent(ScrungledPatternsSave::load,
ScrungledPatternsSave::create,
TAG_SAVED_DATA);
}
var postCalculationNeeders = new ArrayList<ResourceKey<ActionRegistryEntry>>();
var registry = IXplatAbstractions.INSTANCE.getActionRegistry();
for (var key : registry.registryKeySet()) {
var entry = registry.get(key);
if (registry.getHolderOrThrow(key).is(HexTags.Actions.PER_WORLD_PATTERN)) {
// Then we need to create this only on the server, gulp
if (perWorldPatterns != null) {
var precalced = perWorldPatterns.lookup.get(entry.prototype().anglesSignature());
if (precalced == null) {
postCalculationNeeders.add(key);
perWorldPatterns.setDirty();
}
} else {
// We're on the client, TODO implement the client guessing code
}
} else {
NORMAL_ACTION_LOOKUP.put(entry.prototype().anglesSignature(), key);
}
}
if (perWorldPatterns != null) {
for (var postNeederKey : postCalculationNeeders) {
var entry = registry.get(postNeederKey);
var scrungledSig = scrunglePattern(entry.prototype(), overworld.getSeed());
PER_WORLD_ACTION_LOOKUP.put(scrungledSig, postNeederKey);
}
}
HexAPI.LOGGER.info(("We're on the %s! Loaded %d regular actions, %d per-world actions, and %d special " +
"handlers").formatted(
(overworld == null) ? "client" : "server", NORMAL_ACTION_LOOKUP.size(), PER_WORLD_ACTION_LOOKUP.size(),
IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry().size()
));
}
/**
* Try to match this pattern to a special handler. If one is found, return both the handler and its key.
*/
@Nullable
public static Pair<SpecialHandler, ResourceKey<SpecialHandler.Factory<?>>> matchPatternToSpecialHandler(HexPattern pat) {
var registry = IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry();
for (var key : registry.registryKeySet()) {
var factory = registry.get(key);
var handler = factory.tryMatch(pat);
if (handler != null) {
return Pair.of(handler, key);
}
}
return null;
}
/**
* Try to match this pattern to an action, whether via a normal pattern, a per-world pattern, or the machinations
* of a special handler.
*
* @param checkForAlternateStrokeOrders if this is true, will check if the pattern given is an erroneous stroke
* order
* for a per-world pattern.
*/
public static PatternShapeMatch matchPattern(HexPattern pat, ServerLevel overworld,
boolean checkForAlternateStrokeOrders) {
// I am PURPOSELY checking normal actions before special handlers
// This way we don't get a repeat of the phial number literal incident
var sig = pat.anglesSignature();
if (NORMAL_ACTION_LOOKUP.containsKey(sig)) {
var key = NORMAL_ACTION_LOOKUP.get(sig);
return new PatternShapeMatch.Normal(key);
}
// Look it up in the world?
var ds = overworld.getDataStorage();
ScrungledPatternsSave perWorldPatterns =
ds.computeIfAbsent(ScrungledPatternsSave::load, ScrungledPatternsSave::create,
TAG_SAVED_DATA);
if (perWorldPatterns.lookup.containsKey(sig)) {
var key = perWorldPatterns.lookup.get(sig);
return new PatternShapeMatch.PerWorld(key, true);
}
if (checkForAlternateStrokeOrders) {
throw new NotImplementedException("checking for alternate stroke orders is NYI sorry");
}
var shMatch = matchPatternToSpecialHandler(pat);
if (shMatch != null) {
return new PatternShapeMatch.Special(shMatch.getSecond(), shMatch.getFirst());
}
return new PatternShapeMatch.Nothing();
}
/**
* 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 ScrungledPatternsSave extends SavedData {
// Maps scrungled signatures to their keys.
private final Map<String, ResourceKey<ActionRegistryEntry>> lookup;
public ScrungledPatternsSave(Map<String, ResourceKey<ActionRegistryEntry>> lookup) {
this.lookup = lookup;
}
@Override
public CompoundTag save(CompoundTag tag) {
this.lookup.forEach((sig, key) -> tag.putString(sig, key.location().toString()));
return tag;
}
private static ScrungledPatternsSave load(CompoundTag tag) {
var registryKey = IXplatAbstractions.INSTANCE.getActionRegistry().key();
var map = new HashMap<String, ResourceKey<ActionRegistryEntry>>();
for (var sig : tag.getAllKeys()) {
var keyStr = tag.getString(sig);
var key = ResourceKey.create(registryKey, new ResourceLocation(keyStr));
map.put(sig, key);
}
return new ScrungledPatternsSave(map);
}
public static ScrungledPatternsSave create() {
var save = new ScrungledPatternsSave(new HashMap<>());
return save;
}
}
public static final String DATA_VERSION = "0.1.0";
public static final String TAG_SAVED_DATA = "hexcasting.per-world-patterns." + DATA_VERSION;
/**
* Find a valid alternate drawing for this pattern that won't collide with anything pre-existing
*/
private static String scrunglePattern(HexPattern prototype, long seed) {
var scrungled = EulerPathFinder.findAltDrawing(prototype, seed, it -> {
var sig = it.anglesSignature();
return !NORMAL_ACTION_LOOKUP.containsKey(sig);
});
return scrungled.anglesSignature();
}
}

View file

@ -1,13 +1,13 @@
package at.petrak.hexcasting.common.casting.operators package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.misc.MediaConstants import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.spell.Action import at.petrak.hexcasting.api.casting.Action
import at.petrak.hexcasting.api.spell.ConstMediaAction import at.petrak.hexcasting.api.casting.ConstMediaAction
import at.petrak.hexcasting.api.spell.asActionResult import at.petrak.hexcasting.api.casting.asActionResult
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.getVec3 import at.petrak.hexcasting.api.casting.getVec3
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.iota.NullIota import at.petrak.hexcasting.api.casting.iota.NullIota
import net.minecraft.world.level.ClipContext import net.minecraft.world.level.ClipContext
import net.minecraft.world.phys.HitResult import net.minecraft.world.phys.HitResult
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3

View file

@ -1,13 +1,13 @@
package at.petrak.hexcasting.common.casting.operators package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.misc.MediaConstants import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.spell.Action import at.petrak.hexcasting.api.casting.Action
import at.petrak.hexcasting.api.spell.ConstMediaAction import at.petrak.hexcasting.api.casting.ConstMediaAction
import at.petrak.hexcasting.api.spell.asActionResult import at.petrak.hexcasting.api.casting.asActionResult
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.casting.eval.CastingContext
import at.petrak.hexcasting.api.spell.getVec3 import at.petrak.hexcasting.api.casting.getVec3
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.spell.iota.NullIota import at.petrak.hexcasting.api.casting.iota.NullIota
import net.minecraft.world.level.ClipContext import net.minecraft.world.level.ClipContext
import net.minecraft.world.phys.HitResult import net.minecraft.world.phys.HitResult
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3

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