patterns now have innate names

currently only matters for mishaps
This commit is contained in:
yrsegal@gmail.com 2022-08-26 14:40:38 -04:00
parent 240f021194
commit 32fed35beb
16 changed files with 186 additions and 62 deletions

View file

@ -27,6 +27,7 @@ import java.util.concurrent.ConcurrentMap
*/
object PatternRegistry {
private val operatorLookup = ConcurrentHashMap<ResourceLocation, Operator>()
private val keyLookup = ConcurrentHashMap<Operator, ResourceLocation>()
private val specialHandlers: ConcurrentLinkedDeque<SpecialHandlerEntry> = ConcurrentLinkedDeque()
// Map signatures to the "preferred" direction they start in and their operator ID.
@ -48,6 +49,7 @@ object PatternRegistry {
}
this.operatorLookup[id] = operator
this.keyLookup[operator] = id
if (isPerWorld) {
this.perWorldPatternLookup[id] = PerWorldEntry(pattern, id)
} else {
@ -120,6 +122,12 @@ object PatternRegistry {
return perWorldPatterns.lookup
}
/**
* Internal use only.
*/
@JvmStatic
fun lookupPattern(op: Operator): ResourceLocation? = this.keyLookup[op]
/**
* Internal use only.
*/

View file

@ -1,8 +1,14 @@
package at.petrak.hexcasting.api.spell
import at.petrak.hexcasting.api.PatternRegistry
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.api.utils.lightPurple
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.phys.Vec3
import java.text.DecimalFormat
/**
* Manipulates the stack in some way, usually by popping some number of values off the stack
@ -40,6 +46,11 @@ interface Operator {
*/
val causesBlindDiversion: Boolean get() = this is SpellOperator
/**
* The component for displaying this pattern's name. Override for dynamic patterns.
*/
val displayName: Component get() = "hexcasting.spell.${PatternRegistry.lookupPattern(this)}".asTranslatedComponent.lightPurple
companion object {
// I see why vzakii did this: you can't raycast out to infinity!
const val MAX_DISTANCE: Double = 32.0
@ -57,6 +68,20 @@ interface Operator {
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> =
listOf(x)
}
private val DOUBLE_FORMATTER = DecimalFormat("####.####")
@JvmStatic
fun makeConstantOp(x: Double, key: ResourceLocation): Operator = object : ConstManaOperator {
override val argc: Int
get() = 0
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> =
x.asSpellResult
override val displayName: Component
get() = "hexcasting.spell.$key".asTranslatedComponent(DOUBLE_FORMATTER.format(x)).lightPurple
}
}
}

View file

@ -47,6 +47,24 @@ class CastingHarness private constructor(
*/
fun executeIota(iota: SpellDatum<*>, world: ServerLevel): ControllerInfo = executeIotas(listOf(iota), world)
private fun getOperatorForPattern(iota: SpellDatum<*>, world: ServerLevel): Operator? {
if (iota.getType() == DatumType.PATTERN)
return PatternRegistry.matchPattern(iota.payload as HexPattern, world)
return null
}
private fun getPatternForFrame(frame: ContinuationFrame): HexPattern? {
if (frame !is ContinuationFrame.Evaluate) return null
return frame.list.car.payload as? HexPattern
}
private fun getOperatorForFrame(frame: ContinuationFrame, world: ServerLevel): Operator? {
if (frame !is ContinuationFrame.Evaluate) return null
return getOperatorForPattern(frame.list.car, world)
}
/**
* Given a list of iotas, execute them in sequence.
*/
@ -63,6 +81,8 @@ class CastingHarness private constructor(
val result = try {
next.evaluate(continuation.next, world, this)
} catch (mishap: Mishap) {
val pattern = getPatternForFrame(next)
val operator = getOperatorForFrame(next, world)
CastResult(
continuation,
null,
@ -70,7 +90,7 @@ class CastingHarness private constructor(
listOf(
OperatorSideEffect.DoMishap(
mishap,
Mishap.Context(HexPattern(HexDir.WEST), null)
Mishap.Context(pattern ?: HexPattern(HexDir.WEST), operator)
)
)
)
@ -126,7 +146,7 @@ class CastingHarness private constructor(
listOf(
OperatorSideEffect.DoMishap(
mishap,
Mishap.Context(iota.payload as? HexPattern ?: HexPattern(HexDir.WEST), null)
Mishap.Context(iota.payload as? HexPattern ?: HexPattern(HexDir.WEST), getOperatorForPattern(iota, world))
)
),
)
@ -139,7 +159,7 @@ class CastingHarness private constructor(
listOf(
OperatorSideEffect.DoMishap(
MishapError(exception),
Mishap.Context(iota.payload as? HexPattern ?: HexPattern(HexDir.WEST), null)
Mishap.Context(iota.payload as? HexPattern ?: HexPattern(HexDir.WEST), getOperatorForPattern(iota, world))
)
)
)
@ -218,7 +238,7 @@ class CastingHarness private constructor(
continuation,
null,
mishap.resolutionType(ctx),
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, operatorIdPair?.second))),
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, operatorIdPair?.first))),
)
} catch (exception: Exception) {
exception.printStackTrace()
@ -229,7 +249,7 @@ class CastingHarness private constructor(
listOf(
OperatorSideEffect.DoMishap(
MishapError(exception),
Mishap.Context(newPat, operatorIdPair?.second)
Mishap.Context(newPat, operatorIdPair?.first)
)
)
)

View file

@ -2,6 +2,7 @@ package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.mod.HexItemTags
import at.petrak.hexcasting.api.spell.Operator
import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
@ -15,7 +16,6 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.Util
import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.InteractionHand
import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.LivingEntity
@ -54,8 +54,8 @@ sealed class Mishap : Throwable() {
protected fun error(stub: String, vararg args: Any): Component =
"hexcasting.mishap.$stub".asTranslatedComponent(*args)
protected fun actionName(action: ResourceLocation?): Component =
"hexcasting.spell.${action ?: "unknown"}".asTranslatedComponent.lightPurple
protected fun actionName(action: Operator?): Component =
action?.displayName ?: "hexcasting.spell.null".asTranslatedComponent.lightPurple
protected fun yeetHeldItemsTowards(ctx: CastingContext, targetPos: Vec3) {
// Knock the player's items out of their hands
@ -101,7 +101,7 @@ sealed class Mishap : Throwable() {
return ctx.world.getBlockState(pos).block.name
}
data class Context(val pattern: HexPattern, val action: ResourceLocation?)
data class Context(val pattern: HexPattern, val action: Operator?)
companion object {
fun trulyHurt(entity: LivingEntity, source: DamageSource, amount: Float) {

View file

@ -207,10 +207,6 @@ class GuiSpellcasting(
is PatternDrawState.JustStarted -> {
// Well, we never managed to get anything on the stack this go-around.
this.drawState = PatternDrawState.BetweenPatterns
if (this.patterns.isEmpty()) {
Minecraft.getInstance().setScreen(null)
Minecraft.getInstance().soundManager.stop(HexSounds.CASTING_AMBIANCE.location, null)
}
}
is PatternDrawState.Drawing -> {
val (start, _, pat) = this.drawState as PatternDrawState.Drawing

View file

@ -500,7 +500,7 @@ public class RegisterPatterns {
if (negate) {
accumulator = -accumulator;
}
return Operator.makeConstantOp(SpellDatum.make(accumulator));
return Operator.makeConstantOp(accumulator, modLoc("number"));
} else {
return null;
}
@ -536,7 +536,7 @@ public class RegisterPatterns {
return null;
}
return new OpMask(mask);
return new OpMask(mask, modLoc("mask"));
});
}
}

View file

@ -3,9 +3,13 @@ package at.petrak.hexcasting.common.casting.operators.stack
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.api.utils.lightPurple
import it.unimi.dsi.fastutil.booleans.BooleanList
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
class OpMask(val mask: BooleanList) : ConstManaOperator {
class OpMask(val mask: BooleanList, val key: ResourceLocation) : ConstManaOperator {
override val argc: Int
get() = mask.size
@ -17,4 +21,7 @@ class OpMask(val mask: BooleanList) : ConstManaOperator {
}
return out
}
override val displayName: Component
get() = "hexcasting.spell.$key".asTranslatedComponent(mask.map { if (it) '-' else 'v' }.joinToString("")).lightPurple
}

View file

@ -0,0 +1,33 @@
package at.petrak.hexcasting.interop.patchouli;
import net.minecraft.client.resources.language.I18n;
import vazkii.patchouli.api.IComponentProcessor;
import vazkii.patchouli.api.IVariable;
import vazkii.patchouli.api.IVariableProvider;
public class PatternProcessor implements IComponentProcessor {
private String translationKey;
@Override
public void setup(IVariableProvider vars) {
if (vars.has("header"))
translationKey = vars.get("header").asString();
else {
IVariable key = vars.get("op_id");
String opName = key.asString();
String prefix = "hexcasting.spell.";
boolean hasOverride = I18n.exists(prefix + "book." + opName);
translationKey = prefix + (hasOverride ? "book." : "") + opName;
}
}
@Override
public IVariable process(String key) {
if (key.equals("translation_key")) {
return IVariable.wrap(translationKey);
}
return null;
}
}

View file

@ -207,10 +207,40 @@
"hexcasting.subtitles.impetus.fletcher.tick": "Fletcher Impetus ticks",
"hexcasting.subtitles.impetus.cleric.register": "Cleric Impetus dings",
"_comment": "hexcasting.spell.book keys override the name of a pattern in the patchouli book if present",
"hexcasting.spell.book.hexcasting:get_entity_height": "Stadiometer's Prfn.",
"hexcasting.spell.book.hexcasting:get_entity/animal": "Entity Prfn.: Animal",
"hexcasting.spell.book.hexcasting:get_entity/monster": "Entity Prfn.: Monster",
"hexcasting.spell.book.hexcasting:get_entity/item": "Entity Prfn.: Item",
"hexcasting.spell.book.hexcasting:get_entity/player": "Entity Prfn.: Player",
"hexcasting.spell.book.hexcasting:get_entity/living": "Entity Prfn.: Living",
"hexcasting.spell.book.hexcasting:zone_entity": "Zone Dstl.: Any",
"hexcasting.spell.book.hexcasting:zone_entity/animal": "Zone Dstl.: Animal",
"hexcasting.spell.book.hexcasting:zone_entity/monster": "Zone Dstl.: Monster",
"hexcasting.spell.book.hexcasting:zone_entity/item": "Zone Dstl.: Item",
"hexcasting.spell.book.hexcasting:zone_entity/player": "Zone Dstl.: Player",
"hexcasting.spell.book.hexcasting:zone_entity/living": "Zone Dstl.: Living",
"hexcasting.spell.book.hexcasting:zone_entity/not_animal": "Zone Dstl.: Non-Animal",
"hexcasting.spell.book.hexcasting:zone_entity/not_monster": "Zone Dstl.: Non-Monster",
"hexcasting.spell.book.hexcasting:zone_entity/not_item": "Zone Dstl.: Non-Item",
"hexcasting.spell.book.hexcasting:zone_entity/not_player": "Zone Dstl.: Non-Player",
"hexcasting.spell.book.hexcasting:zone_entity/not_living": "Zone Dstl.: Non-Living",
"hexcasting.spell.book.hexcasting:mul_dot": "Multiplicative Dstl.",
"hexcasting.spell.book.hexcasting:div_cross": "Division Dstl.",
"hexcasting.spell.book.hexcasting:arcsin": "Inverse Sine Prfn.",
"hexcasting.spell.book.hexcasting:arccos": "Inverse Cosine Prfn.",
"hexcasting.spell.book.hexcasting:arctan": "Inverse Tangent Prfn.",
"hexcasting.spell.book.hexcasting:const/vec/x": "Vector Rfln. +X/-X",
"hexcasting.spell.book.hexcasting:const/vec/y": "Vector Rfln. +Y/-Y",
"hexcasting.spell.book.hexcasting:const/vec/z": "Vector Rfln. +Z/-Z",
"hexcasting.spell.book.hexcasting:number": "Numerical Reflection",
"hexcasting.spell.book.hexcasting:mask": "Bookkeeper's Gambit",
"hexcasting.spell.hexcasting:get_caster": "Mind's Reflection",
"hexcasting.spell.hexcasting:get_entity_pos": "Compass' Purification",
"hexcasting.spell.hexcasting:get_entity_look": "Alidade's Purification",
"hexcasting.spell.hexcasting:get_entity_height": "Stadiometer's Prfn.",
"hexcasting.spell.hexcasting:get_entity_height": "Stadiometer's Purification",
"hexcasting.spell.hexcasting:get_entity_velocity": "Pace Purification",
"hexcasting.spell.hexcasting:raycast": "Archer's Distillation",
"hexcasting.spell.hexcasting:raycast/axis": "Architect's Distillation",
@ -236,22 +266,22 @@
"hexcasting.spell.hexcasting:construct": "Speaker's Distillation",
"hexcasting.spell.hexcasting:deconstruct": "Speaker's Decomposition",
"hexcasting.spell.hexcasting:get_entity": "Entity Purification",
"hexcasting.spell.hexcasting:get_entity/animal": "Entity Prfn.: Animal",
"hexcasting.spell.hexcasting:get_entity/monster": "Entity Prfn.: Monster",
"hexcasting.spell.hexcasting:get_entity/item": "Entity Prfn.: Item",
"hexcasting.spell.hexcasting:get_entity/player": "Entity Prfn.: Player",
"hexcasting.spell.hexcasting:get_entity/living": "Entity Prfn.: Living",
"hexcasting.spell.hexcasting:zone_entity": "Zone Dstl.: Any",
"hexcasting.spell.hexcasting:zone_entity/animal": "Zone Dstl.: Animal",
"hexcasting.spell.hexcasting:zone_entity/monster": "Zone Dstl.: Monster",
"hexcasting.spell.hexcasting:zone_entity/item": "Zone Dstl.: Item",
"hexcasting.spell.hexcasting:zone_entity/player": "Zone Dstl.: Player",
"hexcasting.spell.hexcasting:zone_entity/living": "Zone Dstl.: Living",
"hexcasting.spell.hexcasting:zone_entity/not_animal": "Zone Dstl.: Non-Animal",
"hexcasting.spell.hexcasting:zone_entity/not_monster": "Zone Dstl.: Non-Monster",
"hexcasting.spell.hexcasting:zone_entity/not_item": "Zone Dstl.: Non-Item",
"hexcasting.spell.hexcasting:zone_entity/not_player": "Zone Dstl.: Non-Player",
"hexcasting.spell.hexcasting:zone_entity/not_living": "Zone Dstl.: Non-Living",
"hexcasting.spell.hexcasting:get_entity/animal": "Entity Purification: Animal",
"hexcasting.spell.hexcasting:get_entity/monster": "Entity Purification: Monster",
"hexcasting.spell.hexcasting:get_entity/item": "Entity Purification: Item",
"hexcasting.spell.hexcasting:get_entity/player": "Entity Purification: Player",
"hexcasting.spell.hexcasting:get_entity/living": "Entity Purification: Living",
"hexcasting.spell.hexcasting:zone_entity": "Zone Distillation: Any",
"hexcasting.spell.hexcasting:zone_entity/animal": "Zone Distillation: Animal",
"hexcasting.spell.hexcasting:zone_entity/monster": "Zone Distillation: Monster",
"hexcasting.spell.hexcasting:zone_entity/item": "Zone Distillation: Item",
"hexcasting.spell.hexcasting:zone_entity/player": "Zone Distillation: Player",
"hexcasting.spell.hexcasting:zone_entity/living": "Zone Distillation: Living",
"hexcasting.spell.hexcasting:zone_entity/not_animal": "Zone Distillation: Non-Animal",
"hexcasting.spell.hexcasting:zone_entity/not_monster": "Zone Distillation: Non-Monster",
"hexcasting.spell.hexcasting:zone_entity/not_item": "Zone Distillation: Non-Item",
"hexcasting.spell.hexcasting:zone_entity/not_player": "Zone Distillation: Non-Player",
"hexcasting.spell.hexcasting:zone_entity/not_living": "Zone Distillation: Non-Living",
"hexcasting.spell.hexcasting:const/null": "Nullary Reflection",
"hexcasting.spell.hexcasting:duplicate": "Gemini Decomposition",
"hexcasting.spell.hexcasting:duplicate_n": "Gemini's Gambit",
@ -261,8 +291,8 @@
"hexcasting.spell.hexcasting:swizzle": "Swindler's Gambit",
"hexcasting.spell.hexcasting:add": "Additive Distillation",
"hexcasting.spell.hexcasting:sub": "Subtractive Distillation",
"hexcasting.spell.hexcasting:mul_dot": "Multiplicative Dstl.",
"hexcasting.spell.hexcasting:div_cross": "Division Dstl.",
"hexcasting.spell.hexcasting:mul_dot": "Multiplicative Distillation",
"hexcasting.spell.hexcasting:div_cross": "Division Distillation",
"hexcasting.spell.hexcasting:abs_len": "Length Purification",
"hexcasting.spell.hexcasting:pow_proj": "Power Distillation",
"hexcasting.spell.hexcasting:construct_vec": "Vector Exaltation",
@ -289,9 +319,9 @@
"hexcasting.spell.hexcasting:sin": "Sine Purification",
"hexcasting.spell.hexcasting:cos": "Cosine Purification",
"hexcasting.spell.hexcasting:tan": "Tangent Purification",
"hexcasting.spell.hexcasting:arcsin": "Inverse Sine Prfn.",
"hexcasting.spell.hexcasting:arccos": "Inverse Cosine Prfn.",
"hexcasting.spell.hexcasting:arctan": "Inverse Tangent Prfn.",
"hexcasting.spell.hexcasting:arcsin": "Inverse Sine Purification",
"hexcasting.spell.hexcasting:arccos": "Inverse Cosine Purification",
"hexcasting.spell.hexcasting:arctan": "Inverse Tangent Purification",
"hexcasting.spell.hexcasting:random": "Entropy Reflection",
"hexcasting.spell.hexcasting:logarithm": "Logarithmic Distillation",
"hexcasting.spell.hexcasting:coerce_axial": "Axial Purification",
@ -361,16 +391,13 @@
"hexcasting.spell.hexcasting:const/vec/nx": "Vector Reflection -X",
"hexcasting.spell.hexcasting:const/vec/ny": "Vector Reflection -Y",
"hexcasting.spell.hexcasting:const/vec/nz": "Vector Reflection -Z",
"hexcasting.spell.hexcasting:const/vec/x": "Vector Rfln. +X/-X",
"hexcasting.spell.hexcasting:const/vec/y": "Vector Rfln. +Y/-Y",
"hexcasting.spell.hexcasting:const/vec/z": "Vector Rfln. +Z/-Z",
"hexcasting.spell.hexcasting:const/vec/0": "Vector Reflection Zero",
"hexcasting.spell.hexcasting:const/double/pi": "Arc's Reflection",
"hexcasting.spell.hexcasting:const/double/tau": "Circle's Reflection",
"hexcasting.spell.hexcasting:const/double/e": "Euler's Reflection",
"hexcasting.spell.hexcasting:number": "Numerical Reflection",
"hexcasting.spell.hexcasting:mask": "Bookkeeper's Gambit",
"hexcasting.spell.unknown": "Special Handler",
"hexcasting.spell.hexcasting:number": "Numerical Reflection: %s",
"hexcasting.spell.hexcasting:mask": "Bookkeeper's Gambit: %s",
"hexcasting.spell.null": "Unknown Pattern",
"hexcasting.spell.hexcasting:interop/gravity/get": "Gravitational Purification",
"hexcasting.spell.hexcasting:interop/gravity/set": "Alter Gravity",
@ -731,7 +758,6 @@
"hexcasting.page.basics_pattern.raycast/entity": "Like $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$, but instead returns the $(italic)entity/$ I am looking at. Costs a negligible amount of _media.",
"hexcasting.entry.numbers": "Number Literals",
"hexcasting.page.numbers.1.header": "Numerical Reflection",
"hexcasting.page.numbers.1": "Irritatingly, there is no easy way to draw numbers. Here is the method Nature deigned to give us.",
"hexcasting.page.numbers.2": "First, I draw one of the two shapes shown on the other page. Next, the $(italic)angles/$ following will modify a running count starting at 0.$(li)Forward: Add 1$(li)Left: Add 5$(li)Right: Add 10$(li)Sharp Left: Multiply by 2$(li)Sharp Right: Divide by 2.$(br)The clockwise version of the pattern, on the right of the other page, will negate the value at the very end. (The left-hand counter-clockwise version keeps the number positive).$(p)Once I finish drawing, the number's pushed to the top of the stack.",
"hexcasting.page.numbers.example.10.header": "Example 1",
@ -805,7 +831,6 @@
"hexcasting.page.stackmanip.splat": "Remove the list at the top of the stack, then push its contents to the stack.",
"hexcasting.page.stackmanip.duplicate": "Duplicates the top iota of the stack.",
"hexcasting.page.stackmanip.duplicate_n": "Removes the number at the top of the stack, then copies the top iota of the stack that number of times. (A count of 2 results in two of the iota on the stack, not three.)",
"hexcasting.page.stackmanip.mask.header": "Bookkeeper's Gambits",
"hexcasting.page.stackmanip.mask.1": "An infinite family of actions that keep or remove elements at the top of the stack based on the sequence of dips and lines.",
"hexcasting.page.stackmanip.mask.2": "Assuming that I draw a Bookkeeper's Gambit pattern left-to-right, the number of iotas the action will require is determined by the horizontal distance covered by the pattern. From deepest in the stack to shallowest, a flat line will keep the iota, whereas a triangle dipping down will remove it.$(br2)If my stack contains $(italic)0, 1, 2/$ from deepest to shallowest, drawing the first pattern opposite will give me $(italic)1/$, the second will give me $(italic)0/$, and the third will give me $(italic)0, 2/$ (the 0 at the bottom is left untouched).",
"hexcasting.page.stackmanip.swizzle.1": "Rearranges the top elements of the stack based on the given numerical code, which is the index of the permutation wanted. Costs an amount of media that starts negligible and scales up as the numerical code does.",

View file

@ -8,7 +8,7 @@
"pages": [
{
"type": "hexcasting:manual_pattern",
"header": "hexcasting.spell.hexcasting:const/vec/x",
"op_id": "hexcasting:const/vec/x",
"anchor": "hexcasting:const/vec/x",
"input": "",
"output": "vector",
@ -28,7 +28,7 @@
},
{
"type": "hexcasting:manual_pattern",
"header": "hexcasting.spell.hexcasting:const/vec/y",
"op_id": "hexcasting:const/vec/y",
"anchor": "hexcasting:const/vec/y",
"input": "",
"output": "vector",
@ -48,7 +48,7 @@
},
{
"type": "hexcasting:manual_pattern",
"header": "hexcasting.spell.hexcasting:const/vec/z",
"op_id": "hexcasting:const/vec/z",
"anchor": "hexcasting:const/vec/z",
"input": "",
"output": "vector",

View file

@ -8,7 +8,7 @@
"pages": [
{
"type": "hexcasting:manual_pattern",
"header": "hexcasting.page.numbers.1.header",
"op_id": "hexcasting:number",
"anchor": "Numbers",
"input": "",
"output": "number",

View file

@ -68,8 +68,8 @@
},
{
"type": "hexcasting:manual_pattern",
"header": "hexcasting.page.stackmanip.mask.header",
"anchor": "Numbers",
"op_id": "hexcasting:mask",
"anchor": "hexcasting:mask",
"input": "many",
"output": "many",
"text": "hexcasting.page.stackmanip.mask.1",

View file

@ -1,8 +1,9 @@
{
"processor": "at.petrak.hexcasting.interop.patchouli.PatternProcessor",
"components": [
{
"type": "patchouli:header",
"text": "#header",
"text": "#translation_key",
"x": -1,
"y": -1
},

View file

@ -1,8 +1,9 @@
{
"processor": "at.petrak.hexcasting.interop.patchouli.PatternProcessor",
"components": [
{
"type": "patchouli:header",
"text": "#header",
"text": "#translation_key",
"x": -1,
"y": -1
},

View file

@ -1,8 +1,9 @@
{
"processor": "at.petrak.hexcasting.interop.patchouli.PatternProcessor",
"components": [
{
"type": "patchouli:header",
"text": "hexcasting.spell.#op_id#",
"text": "#translation_key",
"x": -1,
"y": -1
},

View file

@ -104,15 +104,15 @@ def parse_style(sty):
return "", Style("base", None)
if sty in types:
return "", Style(types[sty], True)
if sty in colors:
if sty in colors:
return "", Style("color", colors[sty])
if sty.startswith("#") and len(sty) in [4, 7]:
return "", Style("color", sty[1:])
# TODO more style parse
raise ValueError("Unknown style: " + sty)
def localize(i18n, string):
return i18n.get(string, string) if i18n else string
def localize(i18n, string, default=None):
return i18n.get(string, default if default else string) if i18n else string
format_re = re.compile(r"\$\(([^)]*)\)")
def format_string(root_data, string):
@ -144,7 +144,7 @@ def format_string(root_data, string):
text_nodes.append(extra_text + string[last_end:])
first_node, *text_nodes = text_nodes
# parse
# parse
style_stack = [FormatTree(Style("base", True), []), FormatTree(Style("para", {}), [first_node])]
for style, text in zip(styles, text_nodes):
tmp_stylestack = []
@ -174,6 +174,11 @@ def format_string(root_data, string):
test_root = {"i18n": {}, "macros": default_macros, "resource_dir": "Common/src/main/resources", "modid": "hexcasting"}
test_str = "Write the given iota to my $(l:patterns/readwrite#hexcasting:write/local)$(#490)local$().$(br)The $(l:patterns/readwrite#hexcasting:write/local)$(#490)local$() is a lot like a $(l:items/focus)$(#b0b)Focus$(). It's cleared when I stop casting a Hex, starts with $(l:casting/influences)$(#490)Null$() in it, and is preserved between casts of $(l:patterns/meta#hexcasting:for_each)$(#fc77be)Thoth's Gambit$(). "
def localize_pattern(root_data, op_id):
return localize(root_data["i18n"], "hexcasting.spell.book." + op_id,
localize(root_data["i18n"], "hexcasting.spell." + op_id))
def do_localize(root_data, obj, *names):
for name in names:
if name in obj:
@ -204,10 +209,12 @@ def resolve_pattern(root_data, page):
if "pattern_reg" not in root_data:
root_data["pattern_reg"] = fetch_patterns(root_data)
page["op"] = [root_data["pattern_reg"][page["op_id"]]]
page["name"] = localize(root_data["i18n"], "hexcasting.spell." + page["op_id"])
page["name"] = localize_pattern(root_data, page["op_id"])
def fixup_pattern(do_sig, root_data, page):
patterns = page["patterns"]
if "op_id" in page:
page["header"] = localize_pattern(root_data, page["op_id"])
if not isinstance(patterns, list): patterns = [patterns]
if do_sig:
inp = page.get("input", None) or ""
@ -261,7 +268,7 @@ def parse_entry(root_data, entry_path, ent_name):
if isinstance(page, str):
page = {"type": "patchouli:text", "text": page}
data["pages"][i] = page
do_localize(root_data, page, "title", "header")
do_format(root_data, page, "text")
if page["type"] in page_types:
@ -473,7 +480,7 @@ def write_page(out, pageid, page):
with out.pair_tag("code"): out.text(i)
out.text(".")
if "text" in page: write_block(out, page["text"])
elif ty == "hexcasting:brainsweep":
elif ty == "hexcasting:brainsweep":
with out.pair_tag("blockquote", clazz="crafting-info"):
out.text(f"Depicted in the book: A mind-flaying recipe producing the ")
with out.pair_tag("code"): out.text(page["output_name"])