This commit is contained in:
yrsegal@gmail.com 2022-07-02 22:42:09 -04:00
commit b0accc1bfc
14 changed files with 177 additions and 42 deletions

View file

@ -36,10 +36,13 @@ public class HexConfig {
boolean invertAbacusScrollDirection();
double gridSnapThreshold();
double DEFAULT_PATTERN_POINT_SPEED_MULTIPLIER = 1;
boolean DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER = false;
boolean DEFAULT_INVERT_SPELLBOOK_SCROLL = false;
boolean DEFAULT_INVERT_ABACUS_SCROLL = false;
double DEFAULT_GRID_SNAP_THRESHOLD = 0.5;
}
public interface ServerConfigAccess {
@ -60,8 +63,10 @@ public class HexConfig {
int DEFAULT_MAX_RECURSE_DEPTH = 64;
int DEFAULT_MAX_SPELL_CIRCLE_LENGTH = 1024;
int DEFAULT_OP_BREAK_HARVEST_LEVEL = 3;
List<String> DEFAULT_FEW_SCROLL_TABLES = List.of("minecraft:chests/jungle_temple", "minecraft:chests/simple_dungeon", "minecraft:chests/village/village_cartographer");
List<String> DEFAULT_SOME_SCROLL_TABLES = List.of("minecraft:chests/bastion_treasure", "minecraft:chests/shipwreck_map");
List<String> DEFAULT_FEW_SCROLL_TABLES = List.of("minecraft:chests/jungle_temple",
"minecraft:chests/simple_dungeon", "minecraft:chests/village/village_cartographer");
List<String> DEFAULT_SOME_SCROLL_TABLES = List.of("minecraft:chests/bastion_treasure",
"minecraft:chests/shipwreck_map");
List<String> DEFAULT_MANY_SCROLL_TABLES = List.of("minecraft:chests/stronghold_library");
// We can't have default values for the break harvest level or if

View file

@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.spell.iota.*
import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
import at.petrak.hexcasting.api.utils.asTranslatedComponent
import com.mojang.datafixers.util.Either
import com.mojang.math.Vector3f
import net.minecraft.core.BlockPos
@ -242,6 +243,17 @@ fun List<Iota>.getLongOrList(idx: Int, argc: Int = 0): Either<Long, SpellList> {
)
}
fun evaluatable(datum: Iota, reverseIdx: Int): Either<HexPattern, SpellList> =
when (datum) {
is PatternIota -> Either.left(datum.pattern)
is ListIota -> Either.right(datum.list)
else -> throw MishapInvalidIota(
datum,
reverseIdx,
"hexcasting.mishap.invalid_value.evaluatable".asTranslatedComponent
)
}
fun Iota?.orNull() = this ?: NullIota()
// TODO do we make this work on lists

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.client.gui
import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.mod.HexItemTags
import at.petrak.hexcasting.api.spell.casting.ControllerInfo
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern
@ -173,7 +174,9 @@ class GuiSpellcasting constructor(
if (anchorCoord != null) {
val anchor = this.coordToPx(anchorCoord)
val mouse = Vec2(mx.toFloat(), my.toFloat())
if (anchor.distanceToSqr(mouse) >= this.hexSize() * this.hexSize()) {
if (anchor.distanceToSqr(mouse) >=
this.hexSize() * this.hexSize() * 2.0 * HexConfig.client().gridSnapThreshold()
) {
val delta = mouse.add(anchor.negated())
val angle = atan2(delta.y, delta.x)
// 0 is right, increases clockwise(?)

View file

@ -2,11 +2,13 @@ package at.petrak.hexcasting.common.casting.operators.eval
import at.petrak.hexcasting.api.spell.Action
import at.petrak.hexcasting.api.spell.OperationResult
import at.petrak.hexcasting.api.spell.SpellList
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.spell.getList
import at.petrak.hexcasting.api.spell.evaluatable
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.iota.PatternIota
object OpEval : Action {
override fun operate(
@ -15,20 +17,24 @@ object OpEval : Action {
ravenmind: Iota?,
ctx: CastingContext
): OperationResult {
val instrs = stack.getList(stack.lastIndex)
stack.removeLastOrNull()
val datum = stack.removeLast()
val instrs = evaluatable(datum, 0)
ctx.incDepth()
instrs.ifRight {
ctx.incDepth()
}
// if not installed already...
// also, never make a break boundary when evaluating just one pattern
val newCont =
if (continuation is SpellContinuation.NotDone && continuation.frame is ContinuationFrame.FinishEval) {
if (instrs.left().isPresent || (continuation is SpellContinuation.NotDone && continuation.frame is ContinuationFrame.FinishEval)) {
continuation
} else {
continuation.pushFrame(ContinuationFrame.FinishEval) // install a break-boundary after eval
}
val frame = ContinuationFrame.Evaluate(instrs)
val instrsList = instrs.map({ SpellList.LList(0, listOf(PatternIota(it))) }, { it })
val frame = ContinuationFrame.Evaluate(instrsList)
return OperationResult(newCont.pushFrame(frame), stack, ravenmind, listOf())
}
}

View file

@ -410,6 +410,7 @@
"hexcasting.mishap.invalid_value.int.positive": "a positive integer",
"hexcasting.mishap.invalid_value.int.positive.lessthan": "a positive integer less than %d",
"hexcasting.mishap.invalid_value.int.between": "an integer between %d and %d",
"hexcasting.mishap.invalid_value.evaluatable": "something evaluatable",
"hexcasting.mishap.not_enough_args": "%s expected %s or more arguments but the stack was only %s tall",
"hexcasting.mishap.too_many_close_parens": "Used Retrospection without first using Introspection",
"hexcasting.mishap.location_too_far": "%s is out of range for %s",
@ -556,7 +557,7 @@
"hexcasting.page.mishaps.incorrect_item.title": "Incorrect Item",
"hexcasting.page.mishaps.incorrect_item": "The action requires some sort of item, but the item I supplied was not suitable.$(br2)Causes brown sparks. If the offending item was in my hand, it will be flung to the floor. If it was in entity form, it will be flung in the air.",
"hexcasting.page.mishaps.incorrect_block.title": "Incorrect Block",
"hexcasting.page.mishaps.incorrect_block": "The action requires some sort of block at a target location, but the block supplied was not suitable.$(br2)Causes bright green sparks, and causes an ephemeral explosion at the given location; it will harm me and others, but will not destroy any blocks.",
"hexcasting.page.mishaps.incorrect_block": "The action requires some sort of block at a target location, but the block supplied was not suitable.$(br2)Causes bright green sparks, and causes an ephemeral explosion at the given location. The explosion doesn't seem to harm me, the world, or anything else though; it's just startling.",
"hexcasting.page.mishaps.retrospection.title": "Hasty Retrospection",
"hexcasting.page.mishaps.retrospection": "I attempted to draw $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ without first drawing $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$.$(br2)Causes orange sparks, and pushes the pattern for $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ to the stack as a pattern iota.",
"hexcasting.page.mishaps.too_deep.title": "Delve Too Deep",
@ -894,7 +895,7 @@
"hexcasting.page.readwrite.read/local": "Copy the iota out of my $(l:patterns/readwrite#hexcasting:local)$(thing)ravenmind/$, which I likely just wrote with $(l:patterns/readwrite#hexcasting:write/local)$(action)Huginn's Gambit/$.",
"hexcasting.entry.meta": "Meta-evaluation",
"hexcasting.page.meta.eval.1": "Remove a list of patterns from the stack, then cast them sequentially, as if I had drawn them myself with my $(l:items/staff)$(item)Staff/$. If an iota is escaped with $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ or $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)its ilk/$, it will be pushed to the stack. Otherwise, non-patterns will fail.",
"hexcasting.page.meta.eval.1": "Remove a pattern or list of patterns from the stack, then cast them as if I had drawn them myself with my $(l:items/staff)$(item)Staff/$ (until a $(l:patterns/meta#hexcasting:halt)$(action)Charon's Gambit/$ is encountered). If an iota is escaped with $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ or $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)its ilk/$, it will be pushed to the stack. Otherwise, non-patterns will fail.",
"hexcasting.page.meta.eval.2": "This can be $(italic)very/$ powerful in tandem with $(l:items/focus)$(item)Foci/$.$(br2)It also makes the bureaucracy of Nature a \"Turing-complete\" system, according to one esoteric scroll I found.$(br2)However, it seems there's a limit to how many times a _Hex can cast itself-- Nature doesn't look kindly on runaway spells!$(br2)In addition, with the energies of the patterns occurring without me to guide them, any mishap will cause the remaining actions to become too unstable and immediately unravel.",
"hexcasting.page.meta.for_each.1": "Remove a list of patterns and a list from the stack, then cast the given pattern over each element of the second list.",
"hexcasting.page.meta.for_each.2": "More specifically, for each element in the second list, it will:$(li)Create a new stack, with everything on the current stack plus that element$(li)Draw all the patterns in the first list$(li)Save all the iotas remaining on the stack to a list$(br)Then, after all is said and done, pushes the list of saved iotas onto the main stack.$(br2)No wonder all the practitioners of this art go mad.",

View file

@ -10,7 +10,7 @@
"type": "hexcasting:pattern",
"op_id": "hexcasting:eval",
"anchor": "hexcasting:eval",
"input": "list of patterns",
"input": "[pattern] | pattern",
"output": "many",
"text": "hexcasting.page.meta.eval.1"
},

View file

@ -0,0 +1,94 @@
{
"replace": false,
"values": [
"hexcasting:jeweler_hammer",
{
"id": "#ae2:quartz_pickaxe",
"required": false
},
{
"id": "ae2:fluix_pickaxe",
"required": false
},
{
"id": "twilightforest:ironwood_pickaxe",
"required": false
},
{
"id": "twilightforest:fiery_pickaxe",
"required": false
},
{
"id": "twilightforest:steeleaf_pickaxe",
"required": false
},
{
"id": "twilightforest:knightmetal_pickaxe",
"required": false
},
{
"id": "occultism:infused_pickaxe",
"required": false
},
{
"id": "occultism:iesnium_pickaxe",
"required": false
},
{
"id": "forbidden_arcanus:slimec_pickaxe",
"required": false
},
{
"id": "forbidden_arcanus:draco_arcanus_pickaxe",
"required": false
},
{
"id": "forbidden_arcanus:arcane_golden_pickaxe",
"required": false
},
{
"id": "forbidden_arcanus:reinforced_arcane_golden_pickaxe",
"required": false
},
{
"id": "undergarden:cloggrum_pickaxe",
"required": false
},
{
"id": "undergarden:froststeel_pickaxe",
"required": false
},
{
"id": "undergarden:utherium_pickaxe",
"required": false
},
{
"id": "undergarden:forgotten_pickaxe",
"required": false
},
{
"id": "alloyed:steel_pickaxe",
"required": false
},
{
"id": "malum:soul_stained_steel_pickaxe",
"required": false
},
{
"id": "evilcraft:vengeance_pickaxe",
"required": false
},
{
"id": "tconstruct:pickaxe",
"required": false
},
{
"id": "tconstruct:pickadze",
"required": false
},
{
"id": "thermal:flux_drill",
"required": false
}
]
}

View file

@ -87,7 +87,7 @@ dependencies {
modImplementation "dev.emi:emi:${emiVersion}"
modImplementation "maven.modrinth:fusions-gravity-api:$gravityApiVersion"
modImplementation "maven.modrinth:gravity-api:$gravityApiVersion"
modApi("com.github.Virtuoel:Pehkui:${pehkuiVersion}", {
exclude group: "net.fabricmc.fabric-api"
})

View file

@ -1,6 +0,0 @@
{
"replace": false,
"values": [
"hexcasting:jeweler_hammer"
]
}

View file

@ -130,6 +130,8 @@ public class FabricHexConfig {
private final PropertyMirror<Boolean> ctrlTogglesOffStrokeOrder = PropertyMirror.create(ConfigTypes.BOOLEAN);
private final PropertyMirror<Boolean> invertSpellbookScrollDirection = PropertyMirror.create(ConfigTypes.BOOLEAN);
private final PropertyMirror<Boolean> invertAbacusScrollDirection = PropertyMirror.create(ConfigTypes.BOOLEAN);
private final PropertyMirror<Double> gridSnapThreshold = PropertyMirror.create(
ConfigTypes.DOUBLE.withMinimum(0.5).withMaximum(1.0));
public ConfigTree configure(ConfigTreeBuilder bob) {
bob
@ -147,7 +149,12 @@ public class FabricHexConfig {
.beginValue("invertAbacusScrollDirection", ConfigTypes.BOOLEAN, DEFAULT_INVERT_ABACUS_SCROLL)
.withComment("Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa")
.finishValue(invertAbacusScrollDirection::mirror);
.finishValue(invertAbacusScrollDirection::mirror)
.beginValue("gridSnapThreshold", ConfigTypes.DOUBLE, DEFAULT_GRID_SNAP_THRESHOLD)
.withComment(
"When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 means 50% of the way.")
.finishValue(gridSnapThreshold::mirror);
return bob.build();
@ -163,6 +170,11 @@ public class FabricHexConfig {
return ctrlTogglesOffStrokeOrder.getValue();
}
@Override
public double gridSnapThreshold() {
return gridSnapThreshold.getValue();
}
@Override
public boolean invertSpellbookScrollDirection() {
return invertSpellbookScrollDirection.getValue();
@ -183,9 +195,9 @@ public class FabricHexConfig {
private final PropertyMirror<List<String>> actionDenyList = PropertyMirror.create(
ConfigTypes.makeList(ConfigTypes.STRING));
private final PropertyMirror<List<String>> circleActionDenyList = PropertyMirror.create(
ConfigTypes.makeList(ConfigTypes.STRING));
ConfigTypes.makeList(ConfigTypes.STRING));
private final PropertyMirror<Boolean> villagersOffendedByMindMurder = PropertyMirror.create(
ConfigTypes.BOOLEAN);
ConfigTypes.BOOLEAN);
private final PropertyMirror<List<String>> fewScrollTables = PropertyMirror.create(
ConfigTypes.makeList(ConfigTypes.STRING));
private final PropertyMirror<List<String>> someScrollTables = PropertyMirror.create(
@ -211,12 +223,14 @@ public class FabricHexConfig {
.finishValue(maxSpellCircleLength::mirror)
.beginValue("circleActionDenyList", ConfigTypes.makeList(ConfigTypes.STRING), List.of())
.withComment("Resource locations of disallowed actions within circles. Trying to cast one of these in a circle will result in a mishap.")
.withComment(
"Resource locations of disallowed actions within circles. Trying to cast one of these in a circle will result in a mishap.")
.finishValue(circleActionDenyList::mirror)
.finishBranch()
.beginValue("actionDenyList", ConfigTypes.makeList(ConfigTypes.STRING), List.of())
.withComment("Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.")
.withComment(
"Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.")
.finishValue(actionDenyList::mirror)
.beginValue("villagersOffendedByMindMurder", ConfigTypes.BOOLEAN, true)
@ -272,12 +286,13 @@ public class FabricHexConfig {
@Override
public ScrollQuantity scrollsForLootTable(ResourceLocation lootTable) {
if (anyMatch(fewScrollTables.getValue(), lootTable))
if (anyMatch(fewScrollTables.getValue(), lootTable)) {
return ScrollQuantity.FEW;
else if (anyMatch(someScrollTables.getValue(), lootTable))
} else if (anyMatch(someScrollTables.getValue(), lootTable)) {
return ScrollQuantity.SOME;
else if (anyMatch(manyScrollTables.getValue(), lootTable))
} else if (anyMatch(manyScrollTables.getValue(), lootTable)) {
return ScrollQuantity.MANY;
}
return ScrollQuantity.NONE;
}
}

View file

@ -49,6 +49,7 @@
"minecraft": "=1.18.2",
"java": ">=17",
"fabric-language-kotlin": ">=1.7.4+kotlin.1.6.21",
"cardinal-components": "~4.1.4",
"patchouli": ">=1.18.2-69",
"paucal": "~0.4.6"
},

View file

@ -1,6 +0,0 @@
{
"replace": false,
"values": [
"hexcasting:jeweler_hammer"
]
}

View file

@ -54,6 +54,7 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
private static ForgeConfigSpec.BooleanValue ctrlTogglesOffStrokeOrder;
private static ForgeConfigSpec.BooleanValue invertSpellbookScrollDirection;
private static ForgeConfigSpec.BooleanValue invertAbacusScrollDirection;
private static ForgeConfigSpec.DoubleValue gridSnapThreshold;
public Client(ForgeConfigSpec.Builder builder) {
patternPointSpeedMultiplier = builder.comment(
@ -69,6 +70,9 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
invertAbacusScrollDirection = builder.comment(
"Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa")
.define("invertAbacusScrollDirection", DEFAULT_INVERT_ABACUS_SCROLL);
gridSnapThreshold = builder.comment(
"When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 means 50% of the way.")
.defineInRange("gridSnapThreshold", DEFAULT_GRID_SNAP_THRESHOLD, 0.5, 1.0);
}
@Override
@ -90,6 +94,11 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
public boolean invertAbacusScrollDirection() {
return invertAbacusScrollDirection.get();
}
@Override
public double gridSnapThreshold() {
return gridSnapThreshold.get();
}
}
public static class Server implements HexConfig.ServerConfigAccess {
@ -122,9 +131,9 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
.defineInRange("maxSpellCircleLength", DEFAULT_MAX_SPELL_CIRCLE_LENGTH, 4, Integer.MAX_VALUE);
circleActionDenyList = builder.comment(
"Resource locations of disallowed actions within circles. Trying to cast one of these in a circle will result in a mishap.")
.defineList("circleActionDenyList", List.of(),
obj -> obj instanceof String s && ResourceLocation.isValidResourceLocation(s));
"Resource locations of disallowed actions within circles. Trying to cast one of these in a circle will result in a mishap.")
.defineList("circleActionDenyList", List.of(),
obj -> obj instanceof String s && ResourceLocation.isValidResourceLocation(s));
builder.pop();
actionDenyList = builder.comment(
@ -134,7 +143,7 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
villagersOffendedByMindMurder = builder.comment(
"Should villagers take offense when you flay the mind of their fellow villagers?")
.define("villagersOffendedByMindMurder", true);
.define("villagersOffendedByMindMurder", true);
builder.push("Scrolls in Loot");
@ -184,12 +193,13 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
@Override
public ScrollQuantity scrollsForLootTable(ResourceLocation lootTable) {
if (anyMatch(fewScrollTables.get(), lootTable))
if (anyMatch(fewScrollTables.get(), lootTable)) {
return ScrollQuantity.FEW;
else if (anyMatch(someScrollTables.get(), lootTable))
} else if (anyMatch(someScrollTables.get(), lootTable)) {
return ScrollQuantity.SOME;
else if (anyMatch(manyScrollTables.get(), lootTable))
} else if (anyMatch(manyScrollTables.get(), lootTable)) {
return ScrollQuantity.MANY;
}
return ScrollQuantity.NONE;
}
}

View file

@ -8,10 +8,10 @@ modName=Hex Casting
minecraftVersion=1.18.2
kotlinVersion=1.6.21
modVersion=0.9.0
modVersion=0.9.1
paucalVersion=0.4.6
patchouliVersion=69
jeiVersion=9.5.3.143
pehkuiVersion=3.3.2
pehkuiVersion=3.3.2