From e6253263e07aad70e5c7069d96958394c3aee7a8 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Mon, 5 Feb 2024 23:27:06 +1000 Subject: [PATCH 01/39] Fix #585, Power Distillation should mishap when taking the square root of a negative number --- .../hexcasting/common/casting/arithmetic/DoubleArithmetic.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt index 57917c2279..a111f9958d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt @@ -57,7 +57,7 @@ object DoubleArithmetic : Arithmetic { MUL -> make2 { a, b -> a * b } DIV -> make2 { a, b -> if (b == 0.0) throw MishapDivideByZero.of(a, b) else a / b } ABS -> make1 { a -> abs(a) } - POW -> make2 { a, b -> a.pow(b) } + POW -> make2 { a, b -> if (a < 0 && !DoubleIota.tolerates(floor(b), b)) throw MishapDivideByZero.of(a, b, "power_neg") else a.pow(b) } FLOOR -> make1 { a -> floor(a) } CEIL -> make1 { a -> ceil(a) } SIN -> make1 { a -> sin(a) } From 1559d70d4f069d948a5202e432d1d70d0ee870a3 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Mon, 5 Feb 2024 23:59:50 +1000 Subject: [PATCH 02/39] Fix #551, White Sun's Zeniths at level 0 gives a high regen for free. --- .../hexcasting/common/casting/actions/spells/OpPotionEffect.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt index cea6c99faf..6f7dc5a05e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt @@ -24,7 +24,7 @@ class OpPotionEffect( val target = args.getLivingEntityButNotArmorStand(0, argc) val duration = args.getPositiveDouble(1, argc) val potency = if (this.allowPotency) - args.getPositiveDoubleUnderInclusive(2, 127.0, argc) + args.getDoubleBetween(2, 1.0, 127.0, argc) else 1.0 env.assertEntityInRange(target) From e8dfa94f93ed3c5ce3a8035fcb63f1acb2685627 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Tue, 6 Feb 2024 00:29:54 +1000 Subject: [PATCH 03/39] Fixed #545 (Cannot read null from empty scrolls/slates) by defaulting all readable items to read NullIota() if no iota contained. Fixed behaviour of OpRead and similar if no IotaHolder found. --- .../api/casting/mishaps/MishapBadOffhandItem.kt | 6 +++--- .../at/petrak/hexcasting/api/item/IotaHolderItem.java | 5 ++--- .../petrak/hexcasting/common/casting/actions/rw/OpRead.kt | 3 +-- .../hexcasting/common/casting/actions/rw/OpReadable.kt | 4 ++-- .../hexcasting/common/casting/actions/rw/OpWrite.kt | 8 ++++---- .../petrak/hexcasting/common/items/storage/ItemFocus.java | 6 ------ .../hexcasting/common/items/storage/ItemSpellbook.java | 7 ------- 7 files changed, 12 insertions(+), 27 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt index 1de584503c..2e7ad8df9d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt @@ -9,7 +9,7 @@ import net.minecraft.world.InteractionHand import net.minecraft.world.item.DyeColor import net.minecraft.world.item.ItemStack -class MishapBadOffhandItem(val item: ItemStack, val hand: InteractionHand?, val wanted: Component) : Mishap() { +class MishapBadOffhandItem(val item: ItemStack?, val hand: InteractionHand?, val wanted: Component) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BROWN) @@ -17,14 +17,14 @@ class MishapBadOffhandItem(val item: ItemStack, val hand: InteractionHand?, val env.mishapEnvironment.dropHeldItems() } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item.isEmpty) + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item?.isEmpty != false) error("no_item.offhand", wanted) else error("bad_item.offhand", wanted, item.count, item.displayName) companion object { @JvmStatic - fun of(item: ItemStack, hand: InteractionHand?, stub: String, vararg args: Any): MishapBadOffhandItem { + fun of(item: ItemStack?, hand: InteractionHand?, stub: String, vararg args: Any): MishapBadOffhandItem { return MishapBadOffhandItem(item, hand, "hexcasting.mishap.bad_item.$stub".asTranslatedComponent(*args)) } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java index 46f4074fc8..c9cca3d607 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java @@ -2,6 +2,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; +import at.petrak.hexcasting.api.casting.iota.NullIota; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.client.ClientTickCounter; @@ -54,12 +55,10 @@ default Iota readIota(ItemStack stack, ServerLevel world) { /** * What is this considered to contain when nothing can be read? - *

- * TODO i'm not sure what this isCastable for */ @Nullable default Iota emptyIota(ItemStack stack) { - return null; + return new NullIota(); } default int getColor(ItemStack stack) { diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt index fceb1a1af1..4dd0e04dfc 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt @@ -3,7 +3,6 @@ package at.petrak.hexcasting.common.casting.actions.rw import at.petrak.hexcasting.api.casting.castables.ConstMediaAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota -import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.api.casting.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.xplat.IXplatAbstractions @@ -14,7 +13,7 @@ object OpRead : ConstMediaAction { val (handStack, hand) = env.getHeldItemToOperateOn { val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) dataHolder != null && (dataHolder.readIota(env.world) != null || dataHolder.emptyIota() != null) - } ?: return listOf(NullIota()) + } ?: throw MishapBadOffhandItem.of(null, null, "iota.read") val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) ?: throw MishapBadOffhandItem.of(handStack, hand, "iota.read") diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpReadable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpReadable.kt index 8b4cee8524..d368b9d87b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpReadable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpReadable.kt @@ -17,9 +17,9 @@ object OpReadable : ConstMediaAction { val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) ?: return false.asActionResult + // If the datum contains no iota, return whether it has a default empty iota. datumHolder.readIota(env.world) - ?: datumHolder.emptyIota() - ?: return false.asActionResult + ?: return (datumHolder.emptyIota() != null).asActionResult return true.asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt index 211f74a30f..d26a27b49a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt @@ -20,17 +20,17 @@ object OpWrite : SpellAction { ): SpellAction.Result { val datum = args[0] - val (handStack, hand) = env.getHeldItemToOperateOn { + val (handStack) = env.getHeldItemToOperateOn { val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) datumHolder != null && datumHolder.writeIota(datum, true) - } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), null, "iota.write") // TODO: hack + } ?: throw MishapBadOffhandItem.of(null, "iota.write") val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) - ?: throw MishapBadOffhandItem.of(handStack, hand, "iota.write") + ?: throw MishapBadOffhandItem.of(handStack, "iota.write") if (!datumHolder.writeIota(datum, true)) - throw MishapBadOffhandItem.of(handStack, hand, "iota.readonly", datum.display()) + throw MishapBadOffhandItem.of(handStack, "iota.readonly", datum.display()) val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer) if (trueName != null) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java index 27c6a8c8ee..4a3cd6b631 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java @@ -2,7 +2,6 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; -import at.petrak.hexcasting.api.casting.iota.NullIota; import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.item.VariantItem; import at.petrak.hexcasting.api.utils.NBTHelper; @@ -44,11 +43,6 @@ public String getDescriptionId(ItemStack stack) { return super.getDescriptionId(stack) + (NBTHelper.getBoolean(stack, TAG_SEALED) ? ".sealed" : ""); } - @Override - public @Nullable Iota emptyIota(ItemStack stack) { - return new NullIota(); - } - @Override public boolean canWrite(ItemStack stack, Iota datum) { return datum == null || !NBTHelper.getBoolean(stack, TAG_SEALED); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java index 2b2eb98d77..fc6b85854e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java @@ -2,7 +2,6 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; -import at.petrak.hexcasting.api.casting.iota.NullIota; import at.petrak.hexcasting.api.item.IotaHolderItem; import at.petrak.hexcasting.api.item.VariantItem; import at.petrak.hexcasting.api.utils.NBTHelper; @@ -129,12 +128,6 @@ CompoundTag readIotaTag(ItemStack stack) { } } - @Override - public @Nullable - Iota emptyIota(ItemStack stack) { - return new NullIota(); - } - @Override public boolean canWrite(ItemStack stack, Iota datum) { return datum == null || !isSealed(stack); From 17b8966a0a8d80ec841201bb4fbe68151a99c912 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Tue, 6 Feb 2024 16:23:26 +1000 Subject: [PATCH 04/39] Fixed #541, allow MediaHolderItems to specify their consumptionPriority. --- .../java/at/petrak/hexcasting/api/item/MediaHolderItem.java | 5 +++++ .../at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java | 2 +- .../hexcasting/forge/cap/adimpl/CapItemMediaHolder.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/MediaHolderItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/MediaHolderItem.java index 51dad5b8ff..a4aa3cfc0a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/MediaHolderItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/MediaHolderItem.java @@ -1,5 +1,6 @@ package at.petrak.hexcasting.api.item; +import at.petrak.hexcasting.api.addldata.ADMediaHolder; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; @@ -59,4 +60,8 @@ default long insertMedia(ItemStack stack, long amount, boolean simulate) { } return inserting; } + + default int getConsumptionPriority(ItemStack stack) { + return ADMediaHolder.BATTERY_PRIORITY; + } } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java index 539c5e5edd..b4ff6ed091 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCMediaHolder.java @@ -51,7 +51,7 @@ public boolean canProvide() { @Override public int getConsumptionPriority() { - return ADMediaHolder.BATTERY_PRIORITY; + return this.mediaHolder.getConsumptionPriority(this.stack); } @Override diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemMediaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemMediaHolder.java index b595891118..7f84f1d154 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemMediaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemMediaHolder.java @@ -37,7 +37,7 @@ public boolean canProvide() { @Override public int getConsumptionPriority() { - return ADMediaHolder.BATTERY_PRIORITY; + return holder.getConsumptionPriority(stack); } @Override From 242c20dca3de257554d60bdd6041af48c549efb0 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Tue, 6 Feb 2024 16:34:44 +1000 Subject: [PATCH 05/39] Fixed #515 --- .../main/resources/assets/hexcasting/lang/en_us.flatten.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 index 7c3b965478..cd5888eda8 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 @@ -1145,7 +1145,7 @@ "hexcasting.crafting.desc": "$(italic)We have a saying in our field: \"Magic isn't\". It doesn't \"just work,\" it doesn't respond to your thoughts, you can't throw fireballs or create a roast dinner from thin air or turn a bunch of muggers into frogs and snails./$", - "phials.1": "I find it quite ... irritating, how Nature refuses to give me change for my work. If all I have on hand is $(l:items/amethyst)$(item)Charged Amethyst/$, even the tiniest $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Purification/$ will consume the entire crystal, wasting the remaining _media.$(br2)Fortunately, it seems I've found a way to somewhat allay this problem.", + "phials.1": "I find it quite ... irritating, how Nature refuses to give me change for my work. If all I have on hand is $(l:items/amethyst)$(item)Charged Amethyst/$, even the tiniest $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$ will consume the entire crystal, wasting the remaining _media.$(br2)Fortunately, it seems I've found a way to somewhat allay this problem.", "phials.2": "I've found old scrolls describing a $(item)Glass Bottle/$ infused with _media. When casting _Hexes, my spells would then draw _media out of the phial. The liquid form of the _media would let me take exact change, so to speak; nothing would be wasted. It's quite like the internal battery of a $(l:items/hexcasting)$(item)Trinket/$, or similar; I can even $(l:patterns/spells/hexcasting#hexcasting:recharge)$(action)Recharge/$ them in the same manner.", "phials.3": "Unfortunately, the art of actually $(italic)making/$ the things seems to have been lost to time. I've found a $(l:patterns/great_spells/make_battery#hexcasting:craft/battery)$(thing)hint at the pattern used to craft it/$, but the technique is irritatingly elusive, and I can't seem to do it successfully. I suspect I will figure it out with study and practice, though. For now, I will simply deal with the wasted _media...$(br2)But I won't settle for it forever.", "phials.desc": "$(italic)Drink the milk./$", From 96598b80aeaaaa7518c0b37539018deae4a62bd0 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Tue, 6 Feb 2024 17:56:03 +1000 Subject: [PATCH 06/39] Mostly implement accepted solution for #545 (no reading from things with nothing in them), remove references to Hands in places where they aren't needed. --- .../api/casting/mishaps/MishapBadOffhandItem.kt | 6 +++--- .../petrak/hexcasting/api/item/IotaHolderItem.java | 2 +- .../hexcasting/common/casting/actions/rw/OpRead.kt | 14 ++++++++++---- .../common/casting/actions/rw/OpWrite.kt | 7 ++++++- .../common/casting/actions/spells/OpColorize.kt | 5 ++--- .../casting/actions/spells/OpCycleVariant.kt | 6 +++--- .../common/casting/actions/spells/OpErase.kt | 6 +++--- .../common/casting/actions/spells/OpMakeBattery.kt | 4 +--- .../casting/actions/spells/OpMakePackagedSpell.kt | 8 ++++---- .../common/casting/actions/spells/OpPlaceBlock.kt | 8 ++++---- .../common/casting/actions/spells/OpRecharge.kt | 5 ++--- 11 files changed, 39 insertions(+), 32 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt index 2e7ad8df9d..7d1410a550 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt @@ -9,7 +9,7 @@ import net.minecraft.world.InteractionHand import net.minecraft.world.item.DyeColor import net.minecraft.world.item.ItemStack -class MishapBadOffhandItem(val item: ItemStack?, val hand: InteractionHand?, val wanted: Component) : Mishap() { +class MishapBadOffhandItem(val item: ItemStack?, val wanted: Component) : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = dyeColor(DyeColor.BROWN) @@ -24,8 +24,8 @@ class MishapBadOffhandItem(val item: ItemStack?, val hand: InteractionHand?, val companion object { @JvmStatic - fun of(item: ItemStack?, hand: InteractionHand?, stub: String, vararg args: Any): MishapBadOffhandItem { - return MishapBadOffhandItem(item, hand, "hexcasting.mishap.bad_item.$stub".asTranslatedComponent(*args)) + fun of(item: ItemStack?, stub: String, vararg args: Any): MishapBadOffhandItem { + return MishapBadOffhandItem(item, "hexcasting.mishap.bad_item.$stub".asTranslatedComponent(*args)) } } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java index c9cca3d607..cb58c3280a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java @@ -58,7 +58,7 @@ default Iota readIota(ItemStack stack, ServerLevel world) { */ @Nullable default Iota emptyIota(ItemStack stack) { - return new NullIota(); + return null; } default int getColor(ItemStack stack) { diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt index 4dd0e04dfc..51791b6d26 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt @@ -10,17 +10,23 @@ object OpRead : ConstMediaAction { override val argc = 0 override fun execute(args: List, env: CastingEnvironment): List { - val (handStack, hand) = env.getHeldItemToOperateOn { + val (handStack) = env.getHeldItemToOperateOn { val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) dataHolder != null && (dataHolder.readIota(env.world) != null || dataHolder.emptyIota() != null) - } ?: throw MishapBadOffhandItem.of(null, null, "iota.read") + } + // If there are no data holders that are readable, find a data holder that isn't readable + // so that the error message is more helpful. + ?: env.getHeldItemToOperateOn { + val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) + dataHolder != null + } ?: throw MishapBadOffhandItem.of(null, "iota.read") val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) - ?: throw MishapBadOffhandItem.of(handStack, hand, "iota.read") + ?: throw MishapBadOffhandItem.of(handStack, "iota.read") val datum = datumHolder.readIota(env.world) ?: datumHolder.emptyIota() - ?: throw MishapBadOffhandItem.of(handStack, hand, "iota.read") + ?: throw MishapBadOffhandItem.of(handStack, "iota.read") return listOf(datum) } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt index d26a27b49a..317dbc0453 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt @@ -9,7 +9,6 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.casting.mishaps.MishapOthersName import at.petrak.hexcasting.xplat.IXplatAbstractions import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.item.ItemStack // we make this a spell cause imo it's a little ... anticlimactic for it to just make no noise object OpWrite : SpellAction { @@ -24,6 +23,12 @@ object OpWrite : SpellAction { val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) datumHolder != null && datumHolder.writeIota(datum, true) + } + // If there are no data holders that are writeable, find a data holder that isn't writeable + // so that the error message is more helpful. + ?: env.getHeldItemToOperateOn { + val dataHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) + dataHolder != null } ?: throw MishapBadOffhandItem.of(null, "iota.write") val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpColorize.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpColorize.kt index d4cdff836b..ba4c407c4a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpColorize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpColorize.kt @@ -18,13 +18,12 @@ object OpColorize : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val (handStack, hand) = env.getHeldItemToOperateOn(IXplatAbstractions.INSTANCE::isPigment) - ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, null, "colorizer") // TODO: hack + val (handStack) = env.getHeldItemToOperateOn(IXplatAbstractions.INSTANCE::isPigment) + ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, "colorizer") // TODO: hack if (!IXplatAbstractions.INSTANCE.isPigment(handStack)) { throw MishapBadOffhandItem.of( handStack, - hand, "colorizer" ) } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCycleVariant.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCycleVariant.kt index 557f29e27c..e49e6e70af 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCycleVariant.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpCycleVariant.kt @@ -13,12 +13,12 @@ object OpCycleVariant : SpellAction { override val argc = 0 override fun execute(args: List, env: CastingEnvironment): SpellAction.Result { - val (handStack, hand) = env.getHeldItemToOperateOn { + val (handStack) = env.getHeldItemToOperateOn { IXplatAbstractions.INSTANCE.findVariantHolder(it) != null - } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), null, "variant") // TODO: hack + } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "variant") // TODO: hack val variantHolder = IXplatAbstractions.INSTANCE.findVariantHolder(handStack) - ?: throw MishapBadOffhandItem.of(handStack, hand, "variant") + ?: throw MishapBadOffhandItem.of(handStack, "variant") return SpellAction.Result( Spell(variantHolder), diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpErase.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpErase.kt index f1c810ccfb..85fc913276 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpErase.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpErase.kt @@ -16,13 +16,13 @@ object OpErase : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val (handStack, hand) = env.getHeldItemToOperateOn { + val (handStack) = env.getHeldItemToOperateOn { val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(it) val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(it) (hexHolder?.hasHex() == true) || (datumHolder?.writeIota(null, true) == true) - } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), null, "eraseable") // TODO: hack + } ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "eraseable") // TODO: hack val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(handStack) val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) @@ -30,7 +30,7 @@ object OpErase : SpellAction { if ((hexHolder?.hasHex() != true) && (datumHolder?.writeIota(null, true) != true) ) { - throw MishapBadOffhandItem.of(handStack, hand, "eraseable") + throw MishapBadOffhandItem.of(handStack, "eraseable") } return SpellAction.Result( diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt index 7b60cf4769..5e86b23504 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakeBattery.kt @@ -29,19 +29,17 @@ object OpMakeBattery : SpellAction { val entity = args.getItemEntity(0, argc) val (handStack, hand) = env.getHeldItemToOperateOn { it.`is`(HexTags.Items.PHIAL_BASE) } - ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), null, "bottle") // TODO: hack + ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "bottle") // TODO: hack if (!handStack.`is`(HexTags.Items.PHIAL_BASE)) { throw MishapBadOffhandItem.of( handStack, - hand, "bottle" ) } if (handStack.count != 1) { throw MishapBadOffhandItem.of( handStack, - hand, "only_one" ) } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt index 8101af64b7..2601a70696 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpMakePackagedSpell.kt @@ -28,17 +28,17 @@ class OpMakePackagedSpell(val itemType: T, val cost: Long) val entity = args.getItemEntity(0, argc) val patterns = args.getList(1, argc).toList() - val (handStack, hand) = env.getHeldItemToOperateOn { + val (handStack) = env.getHeldItemToOperateOn { val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(it) it.`is`(itemType) && hexHolder != null && !hexHolder.hasHex() } - ?: throw MishapBadOffhandItem(ItemStack.EMPTY.copy(), null, itemType.description) // TODO: hack + ?: throw MishapBadOffhandItem(ItemStack.EMPTY.copy(), itemType.description) // TODO: hack val hexHolder = IXplatAbstractions.INSTANCE.findHexHolder(handStack) if (!handStack.`is`(itemType)) { - throw MishapBadOffhandItem(handStack, hand, itemType.description) + throw MishapBadOffhandItem(handStack, itemType.description) } else if (hexHolder == null || hexHolder.hasHex()) { - throw MishapBadOffhandItem.of(handStack, hand, "iota.write") + throw MishapBadOffhandItem.of(handStack, "iota.write") } env.assertEntityInRange(entity) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPlaceBlock.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPlaceBlock.kt index dcbe77844a..e71a3df9bd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPlaceBlock.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPlaceBlock.kt @@ -39,9 +39,9 @@ object OpPlaceBlock : SpellAction { Vec3.atCenterOf(pos), env.castingEntity?.direction ?: Direction.NORTH, pos, false ) val itemUseCtx = env - .getHeldItemToOperateOn { it.item is BlockItem } - ?.stack?.let { UseOnContext(env.world, env.castingEntity as? ServerPlayer, env.castingHand, it, blockHit) } - ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, env.castingHand, "placeable") + .queryForMatchingStack { it.item is BlockItem } + ?.let { UseOnContext(env.world, env.castingEntity as? ServerPlayer, env.castingHand, it, blockHit) } + ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY, "placeable") val placeContext = BlockPlaceContext(itemUseCtx) val worldState = env.world.getBlockState(pos) @@ -64,7 +64,7 @@ object OpPlaceBlock : SpellAction { ) val bstate = env.world.getBlockState(pos) - val placeeStack = env.getHeldItemToOperateOn { it.item is BlockItem }?.stack + val placeeStack = env.queryForMatchingStack { it.item is BlockItem } if (placeeStack != null) { if (!IXplatAbstractions.INSTANCE.isPlacingAllowed(env.world, pos, placeeStack, caster as? ServerPlayer)) return diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt index 675dc4996f..0b7fcb6dfd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpRecharge.kt @@ -23,18 +23,17 @@ object OpRecharge : SpellAction { ): SpellAction.Result { val entity = args.getItemEntity(0, argc) - val (handStack, hand) = env.getHeldItemToOperateOn { + val (handStack) = env.getHeldItemToOperateOn { val media = IXplatAbstractions.INSTANCE.findMediaHolder(it) media != null && media.canRecharge() && media.insertMedia(-1, true) != 0L } - ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), null, "rechargable") // TODO: hack + ?: throw MishapBadOffhandItem.of(ItemStack.EMPTY.copy(), "rechargable") // TODO: hack val media = IXplatAbstractions.INSTANCE.findMediaHolder(handStack) if (media == null || !media.canRecharge()) throw MishapBadOffhandItem.of( handStack, - hand, "rechargable" ) From a18d9a42e3a1a333f576d3a245d36a2c4bb05818 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Tue, 6 Feb 2024 18:10:13 +1000 Subject: [PATCH 07/39] fix OpWritable for items that only accept specific types of iotas by adding a writeable() method to IotaHolderItem. --- .../petrak/hexcasting/api/addldata/ADIotaHolder.java | 5 +++++ .../api/addldata/ItemDelegatingEntityIotaHolder.java | 6 ++++++ .../at/petrak/hexcasting/api/item/IotaHolderItem.java | 6 +++++- .../hexcasting/common/casting/actions/rw/OpWritable.kt | 3 +-- .../hexcasting/common/items/storage/ItemAbacus.java | 5 +++++ .../hexcasting/common/items/storage/ItemFocus.java | 5 +++++ .../hexcasting/common/items/storage/ItemScroll.java | 5 +++++ .../hexcasting/common/items/storage/ItemSlate.java | 5 +++++ .../hexcasting/common/items/storage/ItemSpellbook.java | 5 +++++ .../common/items/storage/ItemThoughtKnot.java | 5 +++++ .../fabric/cc/adimpl/CCEntityIotaHolder.java | 5 +++++ .../hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java | 10 ++++++++++ .../forge/cap/adimpl/CapEntityIotaHolder.java | 5 +++++ .../hexcasting/forge/cap/adimpl/CapItemIotaHolder.java | 5 +++++ .../forge/cap/adimpl/CapStaticIotaHolder.java | 5 +++++ 15 files changed, 77 insertions(+), 3 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java index 45e3e404f2..7b8fcc1c95 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADIotaHolder.java @@ -29,4 +29,9 @@ default Iota emptyIota() { * @return if the writing succeeded/would succeed */ boolean writeIota(@Nullable Iota iota, boolean simulate); + + /** + * @return whether it is possible to write to this IotaHolder + */ + boolean writeable(); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java index 390ce0dc9f..5af67a99ab 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java @@ -29,6 +29,12 @@ public ItemDelegatingEntityIotaHolder(Supplier stackSupplier, Consume return delegate == null ? null : delegate.readIotaTag(); } + @Override + public boolean writeable() { + var delegate = IXplatAbstractions.INSTANCE.findDataHolder(this.stackSupplier.get()); + return delegate != null && delegate.writeable(); + } + @Override public boolean writeIota(@Nullable Iota datum, boolean simulate) { var stacc = this.stackSupplier.get(); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java index cb58c3280a..c312383129 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/item/IotaHolderItem.java @@ -2,7 +2,6 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; -import at.petrak.hexcasting.api.casting.iota.NullIota; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.client.ClientTickCounter; @@ -86,6 +85,11 @@ default int getColor(ItemStack stack) { return IotaType.getColor(tag); } + /** + * @return whether it is possible to write to this IotaHolder + */ + boolean writeable(ItemStack stack); + /** * Write {@code null} to indicate erasing */ diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWritable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWritable.kt index 6912f7f692..f0a3d0da10 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWritable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWritable.kt @@ -4,7 +4,6 @@ import at.petrak.hexcasting.api.casting.asActionResult import at.petrak.hexcasting.api.casting.castables.ConstMediaAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.Iota -import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.xplat.IXplatAbstractions object OpWritable : ConstMediaAction { @@ -18,7 +17,7 @@ object OpWritable : ConstMediaAction { } ?: return false.asActionResult val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(handStack) ?: return false.asActionResult - val success = datumHolder.writeIota(NullIota(), true) + val success = datumHolder.writeable() return success.asActionResult } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java index 3ecb220bf0..ad8527581f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemAbacus.java @@ -33,6 +33,11 @@ CompoundTag readIotaTag(ItemStack stack) { return IotaType.serialize(datum); } + @Override + public boolean writeable(ItemStack stack) { + return false; + } + @Override public boolean canWrite(ItemStack stack, Iota datum) { return false; diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java index 4a3cd6b631..bc3af022b1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java @@ -43,6 +43,11 @@ public String getDescriptionId(ItemStack stack) { return super.getDescriptionId(stack) + (NBTHelper.getBoolean(stack, TAG_SEALED) ? ".sealed" : ""); } + @Override + public boolean writeable(ItemStack stack) { + return !NBTHelper.getBoolean(stack, TAG_SEALED); + } + @Override public boolean canWrite(ItemStack stack, Iota datum) { return datum == null || !NBTHelper.getBoolean(stack, TAG_SEALED); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemScroll.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemScroll.java index 4ed6093a46..96241ea367 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemScroll.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemScroll.java @@ -63,6 +63,11 @@ CompoundTag readIotaTag(ItemStack stack) { return out; } + @Override + public boolean writeable(ItemStack stack) { + return true; + } + @Override public boolean canWrite(ItemStack stack, Iota datum) { return datum instanceof PatternIota || datum == null; diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSlate.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSlate.java index 3821a83e99..6ad6f5b51b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSlate.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSlate.java @@ -84,6 +84,11 @@ CompoundTag readIotaTag(ItemStack stack) { return out; } + @Override + public boolean writeable(ItemStack stack) { + return true; + } + @Override public boolean canWrite(ItemStack stack, Iota datum) { return datum instanceof PatternIota || datum == null; diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java index fc6b85854e..b7521f7619 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemSpellbook.java @@ -128,6 +128,11 @@ CompoundTag readIotaTag(ItemStack stack) { } } + @Override + public boolean writeable(ItemStack stack) { + return !isSealed(stack); + } + @Override public boolean canWrite(ItemStack stack, Iota datum) { return datum == null || !isSealed(stack); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java index 518917b0b9..da1a2631fc 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java @@ -32,6 +32,11 @@ public ItemThoughtKnot(Properties properties) { return NBTHelper.getCompound(stack, TAG_DATA); } + @Override + public boolean writeable(ItemStack stack) { + return !NBTHelper.contains(stack, TAG_DATA); + } + @Override public boolean canWrite(ItemStack stack, @Nullable Iota iota) { return iota != null && !NBTHelper.contains(stack, TAG_DATA); diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCEntityIotaHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCEntityIotaHolder.java index ae794ad913..81998b9e69 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCEntityIotaHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCEntityIotaHolder.java @@ -31,6 +31,11 @@ public Wrapper(ItemDelegatingEntityIotaHolder inner) { return inner.readIotaTag(); } + @Override + public boolean writeable() { + return inner.writeable(); + } + @Override public boolean writeIota(@Nullable Iota iota, boolean simulate) { return inner.writeIota(iota, simulate); diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java index c0f8993ff9..10e9566594 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/cc/adimpl/CCItemIotaHolder.java @@ -32,6 +32,11 @@ public ItemBased(ItemStack stack) { return this.iotaHolder.readIotaTag(this.stack); } + @Override + public boolean writeable() { + return this.iotaHolder.writeable(this.stack); + } + @Override public boolean writeIota(@Nullable Iota iota, boolean simulate) { var canWrite = this.iotaHolder.canWrite(this.stack, iota); @@ -59,6 +64,11 @@ public Static(ItemStack stack, Function provider) { return iota == null ? null : IotaType.serialize(iota); } + @Override + public boolean writeable() { + return false; + } + @Override public boolean writeIota(@Nullable Iota datum, boolean simulate) { return false; diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapEntityIotaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapEntityIotaHolder.java index 8ad61fd00a..a8623e6249 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapEntityIotaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapEntityIotaHolder.java @@ -21,6 +21,11 @@ public Wrapper(ItemDelegatingEntityIotaHolder inner) { return inner.readIotaTag(); } + @Override + public boolean writeable() { + return inner.writeable(); + } + @Override public boolean writeIota(@Nullable Iota iota, boolean simulate) { return inner.writeIota(iota, simulate); diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemIotaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemIotaHolder.java index a1937c0ce3..29caaeb0d0 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemIotaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapItemIotaHolder.java @@ -39,4 +39,9 @@ public boolean writeIota(@Nullable Iota iota, boolean simulate) { } return true; } + + @Override + public boolean writeable() { + return holder.writeable(stack); + } } diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticIotaHolder.java b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticIotaHolder.java index 1eb438a191..f94cd93455 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticIotaHolder.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/cap/adimpl/CapStaticIotaHolder.java @@ -26,6 +26,11 @@ Iota readIota(ServerLevel world) { return provider.apply(stack); } + @Override + public boolean writeable() { + return false; + } + @Override public boolean writeIota(@Nullable Iota iota, boolean simulate) { return false; From e73b2af3b99f9ef4638d09890db128b7819294e8 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Tue, 6 Feb 2024 20:11:01 +1000 Subject: [PATCH 08/39] refactor some unnecessary slowdown points found (repeatedly sending packets unnecessarily, getting names of patterns for every cast and only using if a mishap occurs) --- .../api/casting/eval/CastingEnvironment.java | 14 +++++++++ .../eval/CastingEnvironmentComponent.java | 8 +++++ .../api/casting/eval/env/StaffCastEnv.java | 29 +++++++++++++++---- .../api/casting/eval/vm/CastingVM.kt | 2 ++ .../api/casting/iota/PatternIota.java | 9 +++--- 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java index 00789ac469..d1b3122189 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java @@ -2,6 +2,7 @@ import at.petrak.hexcasting.api.casting.ParticleSpray; import at.petrak.hexcasting.api.casting.PatternShapeMatch; +import at.petrak.hexcasting.api.casting.eval.vm.CastingImage; import at.petrak.hexcasting.api.casting.mishaps.Mishap; import at.petrak.hexcasting.api.casting.mishaps.MishapBadLocation; import at.petrak.hexcasting.api.casting.mishaps.MishapDisallowedSpell; @@ -66,6 +67,7 @@ public final void triggerCreateEvent() { protected Map, @NotNull CastingEnvironmentComponent> componentMap = new HashMap<>(); private final List postExecutions = new ArrayList<>(); + private final List postCasts = new ArrayList<>(); private final List extractMedias = new ArrayList<>(); private final List isVecInRanges = new ArrayList<>(); private final List hasEditPermissionsAts = new ArrayList<>(); @@ -111,6 +113,8 @@ public void addExtension(@NotNull T exte componentMap.put(extension.getKey(), extension); if (extension instanceof PostExecution postExecution) postExecutions.add(postExecution); + if (extension instanceof PostCast postCast) + postCasts.add(postCast); if (extension instanceof ExtractMedia extractMedia) extractMedias.add(extractMedia); if (extension instanceof IsVecInRange isVecInRange) @@ -126,6 +130,8 @@ public void removeExtension(@NotNull CastingEnvironmentComponent.Key key) { if (extension instanceof PostExecution postExecution) postExecutions.remove(postExecution); + if (extension instanceof PostCast postCast) + postCasts.remove(postCast); if (extension instanceof ExtractMedia extractMedia) extractMedias.remove(extractMedia); if (extension instanceof IsVecInRange isVecInRange) @@ -178,6 +184,14 @@ public void postExecution(CastResult result) { postExecutionComponent.onPostExecution(result); } + /** + * Do things after the whole cast is finished (i.e. every pattern to be executed has been executed). + */ + public void postCast(CastingImage image) { + for (var postCastComponent : postCasts) + postCastComponent.onPostCast(image); + } + public abstract Vec3 mishapSprayPos(); /** diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironmentComponent.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironmentComponent.java index fd8de3da7b..5cae9e9f41 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironmentComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironmentComponent.java @@ -1,5 +1,6 @@ package at.petrak.hexcasting.api.casting.eval; +import at.petrak.hexcasting.api.casting.eval.vm.CastingImage; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; @@ -15,6 +16,13 @@ interface PostExecution extends CastingEnvironmentComponent { void onPostExecution(CastResult result); } + interface PostCast extends CastingEnvironmentComponent { + /** + * Do things after the whole cast is finished (i.e. every pattern to be executed has been executed). + */ + void onPostCast(CastingImage image); + } + interface ExtractMedia extends CastingEnvironmentComponent { /** * Receives the cost that is being extracted, should return the diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java index 9b63ece8de..6fbfa7bcf6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java @@ -5,8 +5,10 @@ import at.petrak.hexcasting.api.casting.eval.CastResult; import at.petrak.hexcasting.api.casting.eval.ExecutionClientView; import at.petrak.hexcasting.api.casting.eval.ResolvedPattern; +import at.petrak.hexcasting.api.casting.eval.vm.CastingImage; import at.petrak.hexcasting.api.casting.iota.PatternIota; import at.petrak.hexcasting.api.casting.math.HexCoord; +import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.api.mod.HexStatistics; import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.common.msgs.*; @@ -19,10 +21,14 @@ import java.util.HashSet; import java.util.List; +import java.util.Set; public class StaffCastEnv extends PlayerBasedCastEnv { private final InteractionHand castingHand; + private final Set castPatterns = new HashSet<>(); + private int soundsPlayed = 0; + public StaffCastEnv(ServerPlayer caster, InteractionHand castingHand) { super(caster, castingHand); @@ -35,22 +41,33 @@ public void postExecution(CastResult result) { super.postExecution(result); if (result.component1() instanceof PatternIota patternIota) { - var packet = new MsgNewSpiralPatternsS2C( - this.caster.getUUID(), List.of(patternIota.getPattern()), Integer.MAX_VALUE - ); - IXplatAbstractions.INSTANCE.sendPacketToPlayer(this.caster, packet); - IXplatAbstractions.INSTANCE.sendPacketTracking(this.caster, packet); + castPatterns.add(patternIota.getPattern()); } // we always want to play this sound one at a time var sound = result.getSound().sound(); - if (sound != null) { + if (soundsPlayed < 100 && sound != null) { // TODO: Make configurable var soundPos = this.caster.position(); this.world.playSound(null, soundPos.x, soundPos.y, soundPos.z, sound, SoundSource.PLAYERS, 1f, 1f); + soundsPlayed++; } } + @Override + public void postCast(CastingImage image) { + super.postCast(image); + + var packet = new MsgNewSpiralPatternsS2C( + this.caster.getUUID(), castPatterns.stream().toList(), Integer.MAX_VALUE + ); + IXplatAbstractions.INSTANCE.sendPacketToPlayer(this.caster, packet); + IXplatAbstractions.INSTANCE.sendPacketTracking(this.caster, packet); + + castPatterns.clear(); + soundsPlayed = 0; + } + @Override public long extractMediaEnvironment(long cost) { if (this.caster.isCreative()) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index d2cdfbdb04..dbbc4865a9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -71,6 +71,8 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { val (stackDescs, ravenmind) = generateDescs() val isStackClear = image.stack.isEmpty() && image.parenCount == 0 && !image.escapeNext && ravenmind == null + + this.env.postCast(image) return ExecutionClientView(isStackClear, lastResolutionType, stackDescs, ravenmind) } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java index 6a3ec539d1..3cde42fc4b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Objects; +import java.util.function.Supplier; import static at.petrak.hexcasting.api.utils.HexUtils.isOfTag; @@ -67,7 +68,7 @@ public boolean toleratesOther(Iota that) { @Override public @NotNull CastResult execute(CastingVM vm, ServerLevel world, SpellContinuation continuation) { - @Nullable Component castedName = null; + Supplier<@Nullable Component> castedName = () -> null; try { var lookup = PatternRegistryManifest.matchPattern(this.getPattern(), vm.getEnv(), false); vm.getEnv().precheckAction(lookup); @@ -85,7 +86,7 @@ public boolean toleratesOther(Iota that) { var reqsEnlightenment = isOfTag(IXplatAbstractions.INSTANCE.getActionRegistry(), key, HexTags.Actions.REQUIRES_ENLIGHTENMENT); - castedName = HexAPI.instance().getActionI18n(key, reqsEnlightenment); + castedName = () -> HexAPI.instance().getActionI18n(key, reqsEnlightenment); action = Objects.requireNonNull(IXplatAbstractions.INSTANCE.getActionRegistry().get(key)).action(); if (reqsEnlightenment && !vm.getEnv().isEnlightened()) { @@ -93,7 +94,7 @@ public boolean toleratesOther(Iota that) { throw new MishapUnenlightened(); } } else if (lookup instanceof PatternShapeMatch.Special special) { - castedName = special.handler.getName(); + castedName = special.handler::getName; action = special.handler.act(); } else if (lookup instanceof PatternShapeMatch.Nothing) { throw new MishapInvalidPattern(); @@ -127,7 +128,7 @@ public boolean toleratesOther(Iota that) { this, continuation, null, - List.of(new OperatorSideEffect.DoMishap(mishap, new Mishap.Context(this.getPattern(), castedName))), + List.of(new OperatorSideEffect.DoMishap(mishap, new Mishap.Context(this.getPattern(), castedName.get()))), mishap.resolutionType(vm.getEnv()), HexEvalSounds.MISHAP); } From 58cb3b77566244d104924dcc38a411055168830e Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Tue, 6 Feb 2024 20:57:03 +1000 Subject: [PATCH 09/39] refactor moar, increase the default max op count since it is now fast enough for that to be fine. --- .../hexcasting/api/casting/eval/vm/CastingVM.kt | 16 ++++++++-------- .../hexcasting/api/casting/iota/PatternIota.java | 2 +- .../hexcasting/api/casting/math/HexPattern.kt | 4 ++-- .../at/petrak/hexcasting/api/mod/HexConfig.java | 2 +- .../common/casting/PatternRegistryManifest.java | 15 +++++++++++---- 5 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index dbbc4865a9..5ff591bf8d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -158,7 +158,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { */ @Throws(MishapTooManyCloseParens::class) private fun handleParentheses(iota: Iota): Pair? { - val sig = (iota as? PatternIota)?.pattern?.anglesSignature() + val sig = (iota as? PatternIota)?.pattern?.angles var displayDepth = this.image.parenCount @@ -173,13 +173,13 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { } else { when (sig) { - SpecialPatterns.CONSIDERATION.anglesSignature() -> { + SpecialPatterns.CONSIDERATION.angles -> { this.image.copy( escapeNext = true, ) to ResolvedPatternType.EVALUATED } - SpecialPatterns.EVANITION.anglesSignature() -> { + SpecialPatterns.EVANITION.angles -> { val newParens = this.image.parenthesized.toMutableList() val last = newParens.removeLastOrNull() val newParenCount = this.image.parenCount + if (last == null || last.escaped || last.iota !is PatternIota) 0 else when (last.iota.pattern) { @@ -190,7 +190,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { this.image.copy(parenthesized = newParens, parenCount = newParenCount) to if (last == null) ResolvedPatternType.ERRORED else ResolvedPatternType.UNDONE } - SpecialPatterns.INTROSPECTION.anglesSignature() -> { + SpecialPatterns.INTROSPECTION.angles -> { // we have escaped the parens onto the stack; we just also record our count. val newParens = this.image.parenthesized.toMutableList() newParens.add(ParenthesizedIota(iota, false)) @@ -200,7 +200,7 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { ) to if (this.image.parenCount == 0) ResolvedPatternType.EVALUATED else ResolvedPatternType.ESCAPED } - SpecialPatterns.RETROSPECTION.anglesSignature() -> { + SpecialPatterns.RETROSPECTION.angles -> { val newParenCount = this.image.parenCount - 1 displayDepth-- if (newParenCount == 0) { @@ -243,19 +243,19 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { ) to ResolvedPatternType.ESCAPED } else { when (sig) { - SpecialPatterns.CONSIDERATION.anglesSignature() -> { + SpecialPatterns.CONSIDERATION.angles -> { this.image.copy( escapeNext = true ) to ResolvedPatternType.EVALUATED } - SpecialPatterns.INTROSPECTION.anglesSignature() -> { + SpecialPatterns.INTROSPECTION.angles -> { this.image.copy( parenCount = this.image.parenCount + 1 ) to ResolvedPatternType.EVALUATED } - SpecialPatterns.RETROSPECTION.anglesSignature() -> { + SpecialPatterns.RETROSPECTION.angles -> { throw MishapTooManyCloseParens() } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java index 3cde42fc4b..6b52868ad6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/PatternIota.java @@ -58,7 +58,7 @@ public boolean isTruthy() { public boolean toleratesOther(Iota that) { return typesMatch(this, that) && that instanceof PatternIota piota - && this.getPattern().anglesSignature().equals(piota.getPattern().anglesSignature()); + && this.getPattern().getAngles().equals(piota.getPattern().getAngles()); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt index 096d0340df..6b6c587ea0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexPattern.kt @@ -11,7 +11,7 @@ import net.minecraft.world.phys.Vec2 /** * Sequence of angles to define a pattern traced. */ -data class HexPattern(public val startDir: HexDir, public val angles: MutableList = arrayListOf()) { +data class HexPattern(val startDir: HexDir, val angles: MutableList = arrayListOf()) { /** * @return True if it successfully appended, false if not. */ @@ -113,7 +113,7 @@ data class HexPattern(public val startDir: HexDir, public val angles: MutableLis fun toLines(hexSize: Float, origin: Vec2): List = this.positions().map { coordToPx(it, hexSize, origin) } - fun sigsEqual(that: HexPattern) = this.anglesSignature() == that.anglesSignature() + fun sigsEqual(that: HexPattern) = this.angles == that.angles override fun toString(): String = buildString { append("HexPattern[") diff --git a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java index be86acef10..c7a56ff432 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java @@ -69,7 +69,7 @@ public interface ServerConfigAccess { // fun fact, although dimension keys are a RegistryHolder, they aren't a registry, so i can't do tags boolean canTeleportInThisDimension(ResourceKey dimension); - int DEFAULT_MAX_OP_COUNT = 1_000_000; + int DEFAULT_MAX_OP_COUNT = 2_000_000; int DEFAULT_MAX_SPELL_CIRCLE_LENGTH = 1024; int DEFAULT_OP_BREAK_HARVEST_LEVEL = 3; diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/PatternRegistryManifest.java b/Common/src/main/java/at/petrak/hexcasting/common/casting/PatternRegistryManifest.java index c2a8122de3..c15ad6488f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/PatternRegistryManifest.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/PatternRegistryManifest.java @@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.casting.PatternShapeMatch; import at.petrak.hexcasting.api.casting.castables.SpecialHandler; import at.petrak.hexcasting.api.casting.eval.CastingEnvironment; +import at.petrak.hexcasting.api.casting.math.HexAngle; import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.api.mod.HexTags; import at.petrak.hexcasting.api.utils.HexUtils; @@ -16,12 +17,13 @@ import org.apache.commons.lang3.NotImplementedException; import org.jetbrains.annotations.Nullable; +import java.util.List; 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 { - private static final ConcurrentMap> NORMAL_ACTION_LOOKUP = + private static final ConcurrentMap, ResourceKey> NORMAL_ACTION_LOOKUP = new ConcurrentHashMap<>(); /** @@ -42,8 +44,11 @@ public static void processRegistry(@Nullable ServerLevel overworld) { var registry = IXplatAbstractions.INSTANCE.getActionRegistry(); for (var key : registry.registryKeySet()) { var entry = registry.get(key); + if (entry == null) + continue; + if (!HexUtils.isOfTag(registry, key, HexTags.Actions.PER_WORLD_PATTERN)) { - NORMAL_ACTION_LOOKUP.put(entry.prototype().anglesSignature(), key); + NORMAL_ACTION_LOOKUP.put(entry.prototype().getAngles(), key); } else { perWorldActionCount++; } @@ -64,6 +69,8 @@ public static Pair>> match var registry = IXplatAbstractions.INSTANCE.getSpecialHandlerRegistry(); for (var key : registry.registryKeySet()) { var factory = registry.get(key); + if (factory == null) + continue; var handler = factory.tryMatch(pat,environment); if (handler != null) { return Pair.of(handler, key); @@ -84,7 +91,7 @@ public static PatternShapeMatch matchPattern(HexPattern pat, CastingEnvironment 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(); + var sig = pat.getAngles(); if (NORMAL_ACTION_LOOKUP.containsKey(sig)) { var key = NORMAL_ACTION_LOOKUP.get(sig); return new PatternShapeMatch.Normal(key); @@ -92,7 +99,7 @@ public static PatternShapeMatch matchPattern(HexPattern pat, CastingEnvironment // Look it up in the world? var perWorldPatterns = ScrungledPatternsSave.open(environment.getWorld().getServer().overworld()); - var entry = perWorldPatterns.lookup(sig); + var entry = perWorldPatterns.lookup(pat.anglesSignature()); if (entry != null) { return new PatternShapeMatch.PerWorld(entry.key(), true); } From 7ac3d0d0ce203e5c79aa02b58a35a08a7bc2d657 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Tue, 6 Feb 2024 21:24:41 +1000 Subject: [PATCH 10/39] Fix #608, advancements based on amount of media spent no longer triggering. --- .../api/advancements/MinMaxLongs.java | 85 +++++++++++++++++++ .../api/advancements/SpendMediaTrigger.java | 16 ++-- .../casting/eval/env/PlayerBasedCastEnv.java | 5 ++ .../hexcasting/datagen/HexAdvancements.java | 9 +- 4 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 Common/src/main/java/at/petrak/hexcasting/api/advancements/MinMaxLongs.java diff --git a/Common/src/main/java/at/petrak/hexcasting/api/advancements/MinMaxLongs.java b/Common/src/main/java/at/petrak/hexcasting/api/advancements/MinMaxLongs.java new file mode 100644 index 0000000000..0be502c86e --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/api/advancements/MinMaxLongs.java @@ -0,0 +1,85 @@ +package at.petrak.hexcasting.api.advancements; + +import com.google.gson.JsonElement; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.BuiltInExceptionProvider; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.advancements.critereon.MinMaxBounds; +import net.minecraft.util.GsonHelper; + +import javax.annotation.Nullable; +import java.util.Objects; +import java.util.function.Function; + +public class MinMaxLongs extends MinMaxBounds { + public static final MinMaxLongs ANY = new MinMaxLongs(null, null); + @Nullable + private final Long minSq; + @Nullable + private final Long maxSq; + + private static MinMaxLongs create(StringReader reader, @Nullable Long min, @Nullable Long max) throws CommandSyntaxException { + if (min != null && max != null && min > max) { + throw ERROR_SWAPPED.createWithContext(reader); + } else { + return new MinMaxLongs(min, max); + } + } + + @Nullable + private static Long squareOpt(@Nullable Long l) { + return l == null ? null : l * l; + } + + private MinMaxLongs(@Nullable Long min, @Nullable Long max) { + super(min, max); + this.minSq = squareOpt(min); + this.maxSq = squareOpt(max); + } + + public static MinMaxLongs exactly(long l) { + return new MinMaxLongs(l, l); + } + + public static MinMaxLongs between(long min, long max) { + return new MinMaxLongs(min, max); + } + + public static MinMaxLongs atLeast(long min) { + return new MinMaxLongs(min, null); + } + + public static MinMaxLongs atMost(long max) { + return new MinMaxLongs(null, max); + } + + public boolean matches(long l) { + if (this.min != null && this.min > l) { + return false; + } else { + return this.max == null || this.max >= l; + } + } + + public boolean matchesSqr(long l) { + if (this.minSq != null && this.minSq > l) { + return false; + } else { + return this.maxSq == null || this.maxSq >= l; + } + } + + public static MinMaxLongs fromJson(@Nullable JsonElement json) { + return fromJson(json, ANY, GsonHelper::convertToLong, MinMaxLongs::new); + } + + public static MinMaxLongs fromReader(StringReader reader) throws CommandSyntaxException { + return fromReader(reader, (l) -> l); + } + + public static MinMaxLongs fromReader(StringReader reader, Function map) throws CommandSyntaxException { + BuiltInExceptionProvider builtInExceptions = CommandSyntaxException.BUILT_IN_EXCEPTIONS; + Objects.requireNonNull(builtInExceptions); + return fromReader(reader, MinMaxLongs::create, Long::parseLong, builtInExceptions::readerInvalidInt, map); + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/advancements/SpendMediaTrigger.java b/Common/src/main/java/at/petrak/hexcasting/api/advancements/SpendMediaTrigger.java index aa12d472cf..d610807f59 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/advancements/SpendMediaTrigger.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/advancements/SpendMediaTrigger.java @@ -20,20 +20,20 @@ public ResourceLocation getId() { protected Instance createInstance(JsonObject json, ContextAwarePredicate predicate, DeserializationContext context) { return new Instance(predicate, - MinMaxBounds.Ints.fromJson(json.get(TAG_MEDIA_SPENT)), - MinMaxBounds.Ints.fromJson(json.get(TAG_MEDIA_WASTED))); + MinMaxLongs.fromJson(json.get(TAG_MEDIA_SPENT)), + MinMaxLongs.fromJson(json.get(TAG_MEDIA_WASTED))); } - public void trigger(ServerPlayer player, int mediaSpent, int mediaWasted) { + public void trigger(ServerPlayer player, long mediaSpent, long mediaWasted) { super.trigger(player, inst -> inst.test(mediaSpent, mediaWasted)); } public static class Instance extends AbstractCriterionTriggerInstance { - protected final MinMaxBounds.Ints mediaSpent; - protected final MinMaxBounds.Ints mediaWasted; + protected final MinMaxLongs mediaSpent; + protected final MinMaxLongs mediaWasted; - public Instance(ContextAwarePredicate predicate, MinMaxBounds.Ints mediaSpent, - MinMaxBounds.Ints mediaWasted) { + public Instance(ContextAwarePredicate predicate, MinMaxLongs mediaSpent, + MinMaxLongs mediaWasted) { super(SpendMediaTrigger.ID, predicate); this.mediaSpent = mediaSpent; this.mediaWasted = mediaWasted; @@ -56,7 +56,7 @@ public JsonObject serializeToJson(SerializationContext ctx) { return json; } - private boolean test(int mediaSpentIn, int mediaWastedIn) { + private boolean test(long mediaSpentIn, long mediaWastedIn) { return this.mediaSpent.matches(mediaSpentIn) && this.mediaWasted.matches(mediaWastedIn); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java index 9932ba7b3c..c137930071 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java @@ -223,6 +223,11 @@ protected long extractMediaFromInventory(long costLeft, boolean allowOvercast) { } this.caster.awardStat(HexStatistics.MEDIA_USED, (int) (startCost - costLeft)); + HexAdvancementTriggers.SPEND_MEDIA_TRIGGER.trigger( + this.caster, + startCost - costLeft, + costLeft < 0 ? -costLeft : 0 + ); return costLeft; } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/HexAdvancements.java b/Common/src/main/java/at/petrak/hexcasting/datagen/HexAdvancements.java index 19956a7db8..28012e0da5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/HexAdvancements.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/HexAdvancements.java @@ -2,6 +2,7 @@ import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.advancements.FailToCastGreatSpellTrigger; +import at.petrak.hexcasting.api.advancements.MinMaxLongs; import at.petrak.hexcasting.api.advancements.OvercastTrigger; import at.petrak.hexcasting.api.advancements.SpendMediaTrigger; import at.petrak.hexcasting.api.misc.MediaConstants; @@ -57,15 +58,15 @@ public void generate(HolderLookup.Provider provider, Consumer consu .display(simpleDisplay(Items.GLISTERING_MELON_SLICE, "wasteful_cast", FrameType.TASK)) .parent(root) .addCriterion("waste_amt", new SpendMediaTrigger.Instance(ContextAwarePredicate.ANY, - MinMaxBounds.Ints.ANY, - MinMaxBounds.Ints.atLeast((int) (89 * MediaConstants.DUST_UNIT / 10)))) + MinMaxLongs.ANY, + MinMaxLongs.atLeast(89 * MediaConstants.DUST_UNIT / 10))) .save(consumer, prefix("aaa_wasteful_cast")); Advancement.Builder.advancement() .display(simpleDisplay(HexItems.CHARGED_AMETHYST, "big_cast", FrameType.TASK)) .parent(root) .addCriterion("cast_amt", new SpendMediaTrigger.Instance(ContextAwarePredicate.ANY, - MinMaxBounds.Ints.atLeast((int) (64 * MediaConstants.CRYSTAL_UNIT)), - MinMaxBounds.Ints.ANY)) + MinMaxLongs.atLeast(64 * MediaConstants.CRYSTAL_UNIT), + MinMaxLongs.ANY)) .save(consumer, prefix("aab_big_cast")); var impotence = Advancement.Builder.advancement() From 2e9172950a531c1b870777f3ea5549637745f217 Mon Sep 17 00:00:00 2001 From: Talia-12 Date: Thu, 8 Feb 2024 23:51:35 +1000 Subject: [PATCH 11/39] turns out there's still a bunch of lag with a loop that actually does things --- .../src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java index c7a56ff432..be86acef10 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java @@ -69,7 +69,7 @@ public interface ServerConfigAccess { // fun fact, although dimension keys are a RegistryHolder, they aren't a registry, so i can't do tags boolean canTeleportInThisDimension(ResourceKey dimension); - int DEFAULT_MAX_OP_COUNT = 2_000_000; + int DEFAULT_MAX_OP_COUNT = 1_000_000; int DEFAULT_MAX_SPELL_CIRCLE_LENGTH = 1024; int DEFAULT_OP_BREAK_HARVEST_LEVEL = 3; From 61fb791be66c9bbeb7264a68c289b68811b4b811 Mon Sep 17 00:00:00 2001 From: object-Object Date: Sat, 13 Jul 2024 13:21:30 -0400 Subject: [PATCH 12/39] Remove gradle clean step --- .github/workflows/pr.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index fadca52244..6a6de9e7f9 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -19,14 +19,11 @@ jobs: distribution: temurin java-version: "17.0.1" - uses: gradle/actions/setup-gradle@v3 - - - name: Clean - run: | - chmod +x gradlew - ./gradlew clean - name: Build - run: ./gradlew build + run: | + chmod +x gradlew + ./gradlew build - name: Run Datagen run: ./gradlew runAllDatagen From 6fdb3447eb58f2e051db9839422aa0b8b72e4a01 Mon Sep 17 00:00:00 2001 From: object-Object Date: Sat, 13 Jul 2024 13:43:23 -0400 Subject: [PATCH 13/39] Use nick-fields/retry action to work around intermittent ForgeGradle asset download failures --- .github/workflows/pr.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 6a6de9e7f9..e4e5a10143 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -25,8 +25,14 @@ jobs: chmod +x gradlew ./gradlew build + # ForgeGradle datagen asset download often fails (see #692) + # so just allow it to automatically retry a few times - name: Run Datagen - run: ./gradlew runAllDatagen + uses: nick-fields/retry@v3 + with: + timeout_minutes: 10 + max_attempts: 3 + command: ./gradlew runAllDatagen - name: Check Datagen run: | From b7336bebd74718c747c9a5c542aa7de196f082bb Mon Sep 17 00:00:00 2001 From: ChuijkYahus <94828194+ChuijkYahus@users.noreply.github.com> Date: Wed, 17 Jul 2024 03:36:41 +0800 Subject: [PATCH 14/39] update --- .../resources/assets/hexcasting/lang/zh_cn.flatten.json5 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Common/src/main/resources/assets/hexcasting/lang/zh_cn.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/zh_cn.flatten.json5 index e0ab7bf18e..da3abb9df5 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/zh_cn.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/zh_cn.flatten.json5 @@ -890,6 +890,11 @@ cos: "%s的余弦", }, + invalid_operator_args: { + one: "在栈下标为%d处获取到意外iota:%s", + many: "在栈下标为%2$d到%3$d处获取到意外iota:%4$s", + }, + no_akashic_record: "%s处无阿卡夏记录", disallowed: "已被服务器管理员禁用于施法", disallowed_circle: "已被服务器管理员禁用于法术环", From 353ad0a386d9ca1d6c3e174619811d792cba3ac8 Mon Sep 17 00:00:00 2001 From: Ledinec Date: Fri, 19 Jul 2024 01:13:25 +0400 Subject: [PATCH 15/39] Fixed spelling mistakes, mostly replaced all occurencies of english words among translation, added new translations, translated spells, translated the spells naming --- .../hexcasting/lang/ru_ru.flatten.json5 | 1250 ++++++++--------- 1 file changed, 625 insertions(+), 625 deletions(-) diff --git a/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 index 3f2c4240a7..2dfc5aaca8 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 @@ -1,7 +1,7 @@ // A work in progress { "item.hexcasting": { - book: "Hex Notebook", + book: "Рунный блокнот", staff: { oak: "Дубовый Посох", @@ -10,19 +10,19 @@ jungle: "Посох из Тропического дерева", acacia: "Посох из Акации", dark_oak: "Посох из Тёмного Дуба", - crimson: "Crimson Посох", - warped: "Warped Посох", + crimson: "Багровый Посох", + warped: "Искаженный Посох", mangrove: "Посох из Мангровых зарослей", cherry: "Вишнёвый Посох", bamboo: "Бамбуковый Посох", - edified: "Edified Посох", - quenched: "Quenched Shard Посох", - mindsplice: "Mindsplice Посох", + edified: "Посох Созидания", + quenched: "Погашенный Посох", + mindsplice: "Посох Разума", }, amethyst_dust: "Аметистовая Пыль", charged_amethyst: "Заряженный Аметист", - quenched_allay_shard: "Осколок Quenched Allay", + quenched_allay_shard: "Осколок Погашенного Сплава", scroll_small: { "": "Малый Свиток", @@ -43,20 +43,20 @@ }, focus: { - "": "Фокус", - sealed: "Запечатанный фокус", + "": "Талисман", + sealed: "Запечатанный Талисман", }, - thought_knot: "Узел-Мыслей", + thought_knot: "Узел Мыслей", spellbook: "Книга заклинаний", - cypher: "Cypher", - trinket: "Безделушка", + cypher: "Побрякушка", + trinket: "Штуковина", artifact: "Артефакт", - battery: "Сосуд Media", - lens: "Аметистовая линза", - abacus: "Abacus", + battery: "Сосуд мысли", + lens: "Линза прозрения", + abacus: "Рунные счеты", jeweler_hammer: "Ювелирный Молоток", - sub_sandwich: "ЗубоДробительный Сендвич", + sub_sandwich: "ЗубоДробительный бутерброд", dye_colorizer_: { white: "Белый Пигмент", @@ -96,18 +96,18 @@ transgender: "Transgender Pigment", }, - uuid_colorizer: "Soulglimmer Pigment", - default_colorizer: "Vacant Pigment", + uuid_colorizer: "Пигмент Души", + default_colorizer: "Чистый Пигмент", creative_unlocker: { "": "Медиакуб", - for_emphasis: "Безгроничные MEDIA", + for_emphasis: "Безграничные мысли", tooltip: "Потребляйте, чтобы разблокировать все знания %s.", mod_name: "Hexcasting", }, lore_fragment: { - "": "Фрагмент Лора", + "": "Фрагмент истории", all: "Кажется, я постиг все, что может предложить этот мир.", }, }, @@ -123,7 +123,7 @@ directrix: { empty: "Empty Directrix", redstone: "Mason Directrix", - boolean: "??? Directrix", + boolean: "Boolean Directrix", }, impetus: { @@ -134,9 +134,9 @@ }, akashic_: { - record: "Akashic Record", - bookshelf: "Akashic Bookshelf", - connector: "Akashic Ligature", + record: "Запись Акаши", + bookshelf: "Акаши Книжная Полка", + connector: "Лигатура Акаши", }, slate: { @@ -147,66 +147,66 @@ slate_: { block: "Блок Скрижалей", - tiles: "Slate Tiles", - bricks: "Кирпечи из Скрижалей", + tiles: "Плитка из Скражалей", + bricks: "Кирпичи из Скрижалей", bricks_small: "Маленькие кирпичи из Скрижалей", - pillar: "Slate Pillar", + pillar: "Колонна из Скрижалей", }, amethyst_: { dust_block: "Блок Аметистовой Пыли", - tiles: "Amethyst Tiles", + tiles: "Аметистовая плитка", bricks: "Аметистовые Кирпечи", - bricks_small: "Маленькие Аметистовые Кирпечи", - pillar: "Amethyst Pillar", + bricks_small: "Маленькие Аметистовые Кирпичи", + pillar: "Аметистовая колонна", }, slate_amethyst_: { - tiles: "Slate & Amethyst Tiles", - bricks: "Slate & Amethyst Bricks", - bricks_small: "Small Slate & Amethyst Bricks", - pillar: "Slate & Amethyst Pillar", + tiles: "Сланцево-аметистовые плитки", + bricks: "Сланцево-аметистовые кирпичи", + bricks_small: "Малые сланцево-аметистовые кирпичи", + pillar: "Сланцево-аметистовая колонна", }, scroll_paper: "Бумага для свитков", ancient_scroll_paper: "Древняя бумага для свитков", scroll_paper_lantern: "Бумажный Фонарь", ancient_scroll_paper_lantern: "Древний Бумажный Фонарь", - amethyst_sconce: "Amethyst Sconce", + amethyst_sconce: "Аметистовый Подсвечник", edified_: { - log: "Edified Log", - log_amethyst: "Amethyst Edified Log", - log_aventurine: "Aventurine Edified Log", - log_citrine: "Citrine Edified Log", - log_purple: "Purple Edified Log", - wood: "Edified Древесина", - planks: "Edified Доски", - panel: "Edified Panel", - tile: "Edified Tile", - door: "Edified Дверь", - trapdoor: "Edified Люк", - stairs: "Edified Лестница", - slab: "Edified Полу Блок", - button: "Edified Кнопка", - pressure_plate: "Edified Нажимная Плита", - fence: "Edified Ограда", - fence_gate: "Edified Ворота", + log: "Бревно Созидания", + log_amethyst: "Аметистовое Бревно Созидания", + log_aventurine: "Авантюриновое Бревно Созидания", + log_citrine: "Цитриновое Бревно Созидания", + log_purple: "Фиолетовое Бревно Созидания", + wood: "Древесина Созидания", + planks: "Доски Созидания", + panel: "Panel Созидания", + tile: "Плитка Созидания", + door: "Дверь Созидания", + trapdoor: "Люк Созидания", + stairs: "Лестница Созидания", + slab: "Полу Блок Созидания", + button: "Кнопка Созидания", + pressure_plate: "Нажимная Плита Созидания", + fence: "Ограда Созидания", + fence_gate: "Ворота Созидания", }, - stripped_edified_log: "Stripped Edified Log", - stripped_edified_wood: "Stripped Edified Wood", + stripped_edified_log: "Обтесанное Бревно Созидания", + stripped_edified_wood: "Обтесанная Древесина Созидания", - amethyst_edified_leaves: "Amethyst Edified Leaves", - aventurine_edified_leaves: "Aventurine Edified Leaves", - citrine_edified_leaves: "Citrine Edified Leaves", + amethyst_edified_leaves: "Аметистовые Листья Созидания", + aventurine_edified_leaves: "Авентюриновые Листья Созидания", + citrine_edified_leaves: "Цитриновые Листья Созидания", - quenched_allay: "Quenched Allay", + quenched_allay: "Погашенный Сплав", quenched_allay_: { - tiles: "Quenched Allay Tiles", - bricks: "Quenched Allay Bricks", - bricks_small: "Small Quenched Allay Bricks", + tiles: "Плитка из Погашенного Сплава", + bricks: "Кирпичи из Погашенного Сплава", + bricks_small: "Малые Кирпичи из Погашенного Сплава", }, }, @@ -220,9 +220,9 @@ }, "tag.hexcasting": { - staves: "Hex Staves", - edified_logs: "Edified Брёвна", - edified_planks: "Edified Доски", + staves: "Посохи", + edified_logs: "Брёвна Созидани", + edified_planks: "Доски Созидания", phial_base: "Пустой Сосуд", }, @@ -235,11 +235,11 @@ }, "emi.category.hexcasting": { - brainsweep: "Flay Mind", - "craft.battery": "Craft Phial", - edify: "Edify Sapling", - villager_leveling: "Trade Leveling", - villager_profession: "Villager Profession", + brainsweep: "Очистка Разума", + "craft.battery": "Создать пузырь мыслей", + edify: "Саженец Созидания", + villager_leveling: "Уровень Торговли", + villager_profession: "Профессия Жителя", }, "text.autoconfig.hexcasting": { @@ -254,32 +254,32 @@ option: { common: { dustMediaAmount: { - "": "Dust Media Amount", - "@Tooltip": "Сколько стоит один предмет из Аметистовой пыли.", + "": "Количество Мысли в Пыли", + "@Tooltip": "Сколько мысли вмещает предмет из Аметистовой пыли.", }, shardMediaAmount: { - "": "Shard Media Amount", - "@Tooltip": "Сколько Media стоит один осколок аметиста", + "": "Количество Мысли в Осколке", + "@Tooltip": "Сколько мысли вмещает осколок аметиста", }, chargedCrystalMediaAmount: { - "": "Charged Crystal Media Amount", + "": "Количество Мысли в Заряженном Кристалле Аметиста", "@Tooltip": "Сколько Media стоит один заряженный кристалл аметиста", }, mediaToHealthRate: { - "": "Влияние Media на уровень Здоровья", - "@Tooltip": "Сколько Media стоит половинка сердца при кастинге за HP", + "": "Влияние Мысли на уровень Здоровья", + "@Tooltip": "Сколько мысли стоит половинка сердца при использовании магии за жизни", }, cypherCooldown: { - "": "Время восстановления Cypher", - "@Tooltip": "Время восстановления Сypher в тиках", + "": "Время восстановления Побрякушки", + "@Tooltip": "Время восстановления Побрякушки в тиках", }, trinketCooldown: { - "": "Время восстановления Trinket", - "@Tooltip": "Время восстановления Безделушки в тиках", + "": "Время восстановления Штуковины", + "@Tooltip": "Время восстановления Штуковины в тиках", }, artifactCooldown: { - "": "Время восстановления Artifact", - "@Tooltip": "Время восстановления Artifact в тиках", + "": "Время восстановления Артефакта", + "@Tooltip": "Время восстановления Артефакта в тиках", }, }, @@ -346,32 +346,32 @@ "advancement.hexcasting:": { root: { - "": "Hexcasting Research", - desc: "Найдите и добудте концентрированную форму Media, растущих глубоко под землей.", + "": "Изучение рунных заклинаний", + desc: "Найдите и добудте концентрированную форму мыслей, растущих глубоко под землей.", }, enlightenment: { - "": "Achieve Enlightenment", - desc: "Разрушьте внутренний барьер, израсходовав почти все свое здоровье, кастуя заклинание.", + "": "Прорицание", + desc: "Разрушьте внутренний барьер, израсходовав почти все свое здоровье за заклинание.", }, wasteful_cast: { - "": "Waste Not...", - desc: "Растрачивать впустую большое количество Media при касте заклинания.", + "": "Кто аметистами посорит...", + desc: "Потратить впустую большое количество мысли при использовании заклинания.", }, big_cast: { - "": "... Want Not", - desc: "Произнесение одного-единственного заклинания требует поистине огромного количества Media.", + "": "... тот нужду пожнет", + desc: "Произнесение одного-единственного заклинания требует поистине огромного количества Мысли.", }, y_u_no_cast_angy: { - "": "Blind Diversion", - desc: "Попробовать произнести заклинание из свитка, но потерпите неудачу.", + "": "Первый блин комом", + desc: "Попробовать произнести заклинание из свитка, но потерпеть неудачу.", }, opened_eyes: { - "": "Opened Eyes", + "": "Открытие", desc: "Пусть природа заберет частичку твоего разума в качестве платы за колдовство. Что может случиться, если ты позволишь ей сделать больше?", }, lore: { - "": "Hexcasting Lore", - desc: "Прочитать Lore Fragment", + "": "История Рунных Заклинаний", + desc: "Прочитать фрагмент истории", }, "lore/": { cardamom1: { @@ -401,14 +401,14 @@ }, "stat.hexcasting": { - media_used: "Media потребляемые (в виде пыли)", - media_overcasted: "Media Overcast (в виде пыли)", - patterns_drawn: "Нарисованные Patterns", - spells_cast: "Каст Заклинаний", + media_used: "Мысли потребляемые (в виде пыли)", + media_overcasted: "Переиспользовано мысли (в виде пыли)", + patterns_drawn: "Рун нарисовано", + spells_cast: "Заклинаний использовано", }, "death.attack.hexcasting": { - overcast: "%s' его разум превратился в энергию", + overcast: "Разум %s был полноценно поглощён как оплата заклинания.", shame: "Позор %s!", }, @@ -416,20 +416,20 @@ recalc: "Recalculated patterns", pats: { - listing: "Паттрены в этом мире:", - all: "Отдал все %d scrolls в %s", + listing: "Руны в этом мире:", + all: "Отдал все %d свитки в %s", "specific.success": "Отдал %s с id %s за %s", }, brainsweep: { "": "Brainswept %s", "fail.badtype": "%s это не моб", - "fail.already": "%s он уже пуст", + "fail.already": "%s уже пуст", }, }, hexcasting: { - "pattern.unknown": "Unknown pattern resource location %s", + "pattern.unknown": "Неизвестная руна %s", debug: { media_withdrawn: "%s - Media withdrawn: %s", @@ -442,8 +442,8 @@ // TODO: post-eigengrau make these less anticlimactic message: { - cant_overcast: "Для этого заклинания требовалось больше Media, чем у меня было... Мне следует еще раз проверить свои расчеты.", - cant_great_spell: "Заклинание каким-то образом не сработало... неужели я недостаточно искусен?", + cant_overcast: "Для этого заклинания требовалось больше мысли, чем у меня было... Мне следует еще раз проверить свои расчеты.", + cant_great_spell: "Заклинание каким-то образом не сработало... неужели у меня не хватает знаний?", }, tooltip: { @@ -470,13 +470,13 @@ }, circle: { - no_exit: "Поток Media не смог найти выхода в %s", - many_exits: "У потока Media было слишком много выходов в %s", - no_closure: "Поток Media не сможет вернуться к прежнему impetus на %s", + no_exit: "Поток мысли не смог найти выхода в %s", + many_exits: "У потока мысли было слишком много выходов в %s", + no_closure: "Поток мысли не сможет вернуться к прежнему impetus на %s", }, lens: { - "pattern.invalid": "Недопустимый Pattern", + "pattern.invalid": "Неизвестная руна", bee: { "": "%s bees", single: "%s bee", @@ -488,7 +488,7 @@ akashic: { "bookshelf.location": "Запись на %s", "record.count": { - "": "%s iotas хранящиеся", + "": "%s йоты хранящиеся", single: "%s iota хранящаяся", }, }, @@ -500,60 +500,60 @@ product: "Лишенное разума Тело", }, - media: "%d пыль", + media: "%d пыли", media_amount: "Содержит: %s (%s)", "media_amount.advanced": "Содержит: %s/%s (%s)", list_contents: "[%s]", - null_iota: "Null", + null_iota: "Ничто", jump_iota: "[Jump]", - pattern_iota: "HexPattern(%s)", - boolean_true: "True", - boolean_false: "False", + pattern_iota: "Руна(%s)", + boolean_true: "Истина", + boolean_false: "Ложь", }, // ^ tooltip spelldata: { onitem: "Содержит: %s", anything: "Что-либо", - unknown: "Сломанная iota", - "entity.whoknows": "Неизвестное entity", - "akashic.nopos": "Владелец записи не знает ни о каких iota здесь (это ошибка)", + unknown: "Сломанная йота", + "entity.whoknows": "Неизвестная сущность", + "akashic.nopos": "Владелец записи не знает ни о каких йота здесь (это ошибка)", }, subtitles: { casting: { pattern: { - start: "Начальный pattern", + start: "Начальная руна", add_segment: "Добавление строки", }, cast: { - normal: "Action hums", + normal: "Действие жужжит", spell: "Заклинание гремит", - hermes: "Hermes' twangs", - thoth: "Thoth's twangs", + hermes: "Гермес стрекочит", + thoth: "Тот стрекочит", }, }, ambiance: "Hex grid hums", - "staff.reset": "Сброс каста", + "staff.reset": "Сброс заклинания", abacus: { - "": "Abacus clicks", - shake: "Abacus shakes", - }, - "spellcircle.add_pattern": "Spell circle crackles", - "spellcircle.fail": "Spell circle fizzles out", - "scroll.dust": "Scroll covers with dust", - "scroll.scribble": "Scroll is scribbled", - "impetus.fletcher.tick": "Fletcher Impetus ticks", - "impetus.redstone.register": "Cleric Impetus dings", - "lore_fragment.read": "Read lore fragment", - "flight.ambience": "Player flies", - "flight.finish": "Flight ends", + "": "Счеты щелкают", + shake: "Счеты трещат", + }, + "spellcircle.add_pattern": "Заклинание круга трещит", + "spellcircle.fail": "Заклинание круга громко трещит", + "scroll.dust": "Свиток покрывается аметистовой пылью", + "scroll.scribble": "Свиток расписан", + "impetus.fletcher.tick": "Fletcher Impetus кликает", + "impetus.redstone.register": "Cleric Impetus звенит", + "lore_fragment.read": "Прочтен фрагмент истории", + "flight.ambience": "Игрок летит", + "flight.finish": "Полет окончился", }, attributes: { - grid_zoom: "Размер сетки каста", + grid_zoom: "Размер сетки заклинания", // TODO: the +1 is kind of janky scry_sight: "Магический взгляд", }, @@ -563,93 +563,93 @@ action: { "hexcasting:": { "const/": { - "null": "Nullary Reflection", - "true": "True Reflection", - "false": "False Reflection", + "null": "Отражение ничта", + "true": "Отражение истины", + "false": "Отражение лжи", "vec/": { - px: "Vector Reflection +X", - py: "Vector Reflection +Y", - pz: "Vector Reflection +Z", - nx: "Vector Reflection -X", - ny: "Vector Reflection -Y", - nz: "Vector Reflection -Z", - "0": "Vector Reflection Zero", + px: "Отражение Вектора +X", + py: "Отражение Вектора +Y", + pz: "Отражение Вектора +Z", + nx: "Отражение Вектора -X", + ny: "Отражение Вектора -Y", + nz: "Отражение Вектора -Z", + "0": "Отражение Вектора 0", }, "double/": { - pi: "Arc's Reflection", - tau: "Circle's Reflection", - "e": "Euler's Reflection", + pi: "Отражение арки", + tau: "Отражение круга", + "e": "Отражение Эйлера", }, }, - get_caster: "Mind's Reflection", - "entity_pos/eye": "Compass' Purification", - "entity_pos/foot": "Compass' Purification II", - get_entity_look: "Alidade's Purification", - get_entity_height: "Stadiometer's Purification", - get_entity_velocity: "Pace Purification", - raycast: "Archer's Distillation", - "raycast/axis": "Architect's Distillation", - "raycast/entity": "Scout's Distillation", + get_caster: "Отражение Нарцисса", + "entity_pos/eye": "Преобразование глаз", + "entity_pos/foot": "Преобразование ног", + get_entity_look: "Преобразование Взгляда", + get_entity_height: "Преобразование Высот", + get_entity_velocity: "Преобразование Скорости", + raycast: "Объединение Луча", + "raycast/axis": "Объединение Стороны", + "raycast/entity": "Объединение Сущности", "circle/": { - impetus_pos: "Waystone Reflection", - impetus_dir: "Lodestone Reflection", - "bounds/min": "Lesser Fold Reflection", - "bounds/max": "Greater Fold Reflection", - }, - - append: "Integration Distillation", - unappend: "Derivation Distillation", - index: "Selection Distillation", - singleton: "Single's Purification", - empty_list: "Vacant Reflection", - reverse: "Retrograde Purification", - last_n_list: "Flock's Gambit", - splat: "Flock's Disintegration", - index_of: "Locator's Distillation", - remove_from: "Excisor's Distillation", - slice: "Selection Exaltation", - replace: "Surgeon's Exaltation", - construct: "Speaker's Distillation", - deconstruct: "Speaker's Decomposition", + impetus_pos: "Отражение Путевого Камня", + impetus_dir: "Взгляд Путевого Камня", + "bounds/min": "Отражение меньшей стопки", + "bounds/max": "Отражение большей стопки", + }, + + append: "Объединение Вступления", + unappend: "Объединение Вывода", + index: "Объединение Выборки", + singleton: "Одиночное Преображение", + empty_list: "Отражение Чистоты", + reverse: "Обратное Преображение", + last_n_list: "Гамбит Группы", + splat: "Распад Группы", + index_of: "Объединение Искателя", + remove_from: "Возвышение Удаления", + slice: "Возвышение Выборки", + replace: "Возвышение Хирурга", + construct: "Объединение Динамика", + deconstruct: "Распад Динамика", - get_entity: "Entity Purification", + get_entity: "Сущностное Преображение", "get_entity/": { - animal: "Entity Purification: Animal", - monster: "Entity Purification: Monster", - item: "Entity Purification: Item", - player: "Entity Purification: Player", - living: "Entity Purification: Living", + animal: "Сущностное Преображение: Животное", + monster: "Сущностное Преображение: Монстр", + item: "Сущностное Преображение: Предмет", + player: "Сущностное Преображение: Игрок", + living: "Сущностное Преображение: Живое", }, - zone_entity: "Zone Distillation: Any", + zone_entity: "Объединение Области: Любое", "zone_entity/": { - animal: "Zone Distillation: Animal", - monster: "Zone Distillation: Monster", - item: "Zone Distillation: Item", - player: "Zone Distillation: Player", - living: "Zone Distillation: Living", - not_animal: "Zone Distillation: Non-Animal", - not_monster: "Zone Distillation: Non-Monster", - not_item: "Zone Distillation: Non-Item", - not_player: "Zone Distillation: Non-Player", - not_living: "Zone Distillation: Non-Living", - }, - - swap: "Jester's Gambit", - rotate: "Rotation Gambit", - rotate_reverse: "Rotation Gambit II", - duplicate: "Gemini Decomposition", - over: "Prospector's Gambit", + animal: "Объединение Области: Животное", + monster: "Объединение Области: Монстр", + item: "Объединение Области: Предмет", + player: "Объединение Области: Игрок", + living: "Объединение Области: Живое", + not_animal: "Объединение Области: Не-Животное", + not_monster: "Объединение Области: Не-Монстр", + not_item: "Объединение Области: Не-Предмет", + not_player: "Объединение Области: Не-Игрок", + not_living: "Объединение Области: Не-Живое", + }, + + swap: "Гамбит Шута", + rotate: "Гамбит Поворота", + rotate_reverse: "Гамбит Поворота II", + duplicate: "Разбор Близнецов", + over: "Гамбит Старателя", tuck: "Undertaker's Gambit", - "2dup": "Dioscuri Gambit", - duplicate_n: "Gemini Gambit", - stack_len: "Flock's Reflection", - fisherman: "Fisherman's Gambit", - "fisherman/copy": "Fisherman's Gambit II", + "2dup": "Гамбит Дубля", + duplicate_n: "Гамбит Близнецов", + stack_len: "Отражение Группы", + fisherman: "Гамбит Рыбака", + "fisherman/copy": "Гамбит Рыбака II", swizzle: "Swindler's Gambit", unique: "Uniqueness Purification", @@ -657,209 +657,209 @@ or: "Disjunction Distillation", xor: "Exclusion Distillation", - greater: "Maximus Distillation", - less: "Minimus Distillation", - greater_eq: "Maximus Distillation II", - less_eq: "Minimus Distillation II", - equals: "Equality Distillation", - not_equals: "Inequality Distillation", - not: "Negation Purification", - bool_coerce: "Augur's Purification", - if: "Augur's Exaltation", + greater: "Объединение Максимум", + less: "Объединение Минимум", + greater_eq: "Объединение Максимум II", + less_eq: "Объединение Минимум II", + equals: "Объединение Равенства", + not_equals: "Объединение Неравенства", + not: "Объединение Отрицания", + bool_coerce: "Преображение Прорицателя", + if: "Возвышение Прорицателя", - add: "Additive Distillation", - sub: "Subtractive Distillation", - mul: "Multiplicative Distillation", - div: "Division Distillation", - abs: "Length Purification", - pow: "Power Distillation", - floor: "Floor Purification", - ceil: "Ceiling Purification", - modulo: "Modulus Distillation", - construct_vec: "Vector Exaltation", - deconstruct_vec: "Vector Disintegration", - sin: "Sine Purification", - cos: "Cosine Purification", - tan: "Tangent Purification", - arcsin: "Inverse Sine Purification", - arccos: "Inverse Cosine Purification", - arctan: "Inverse Tangent Purification", - arctan2: "Inverse Tangent Purification II", - random: "Entropy Reflection", - logarithm: "Logarithmic Distillation", - coerce_axial: "Axial Purification", + add: "Суммирующее Объединение", + sub: "Вычитающее Объединение", + mul: "Умножающее Объединение", + div: "Делящее Объединение", + abs: "Преображение к Абсолюту", + pow: "Объединение Экспоненты", + floor: "Преображение к полу", + ceil: "Преображение к потолку", + modulo: "Модульное Объединение", + construct_vec: "Векторное Возвышение", + deconstruct_vec: "Векторный Распад", + sin: "Преображение к Синусу", + cos: "Преображение к Косинусу", + tan: "Преображение к Тангенсу", + arcsin: " Преображение к Арксинусу", + arccos: "Преображение к Арккосинусу", + arctan: "Преображение к Арктангенсу", + arctan2: "Преображение к Арктангенсу II", + random: "Отражение Случая", + logarithm: "Логаритмическое Объединение", + coerce_axial: "Преображение к Стороне", - read: "Scribe's Reflection", - "read/entity": "Chronicler's Purification", + read: "Отражение Писаря", + "read/entity": "Преобразование Летописца", "read/local": "Muninn's Reflection", - write: "Scribe's Gambit", - "write/entity": "Chronicler's Gambit", + write: "Гамбит Писаря", + "write/entity": "Гамбит Летописца", "write/local": "Huginn's Gambit", - readable: "Auditor's Reflection", - "readable/entity": "Auditor's Purification", - writable: "Assessor's Reflection", - "writable/entity": "Assessor's Purification", - "akashic/read": "Akasha's Distillation", - "akashic/write": "Akasha's Gambit", - - print: "Reveal", - beep: "Make Note", - explode: "Explosion", - "explode/fire": "Fireball", - add_motion: "Impulse", - blink: "Blink", - break_block: "Break Block", - place_block: "Place Block", - - "craft/cypher": "Craft Cypher", - "craft/trinket": "Craft Trinket", - "craft/artifact": "Craft Artifact", - "craft/battery": "Craft Phial", - - recharge: "Recharge Item", - erase: "Erase Item", - create_water: "Create Water", - destroy_water: "Destroy Liquid", - ignite: "Ignite Block", - extinguish: "Extinguish Area", - conjure_block: "Conjure Block", - conjure_light: "Conjure Light", - bonemeal: "Overgrow", - edify: "Edify Sapling", - colorize: "Internalize Pigment", + readable: "Отражение Ревизора", + "readable/entity": "Преображение Ревизора", + writable: "Отражение Заседателя", + "writable/entity": "Преображение Заседателя", + "akashic/read": "Объединение Акаши", + "akashic/write": "Гамбит Акаши", + + print: "Раскрытие", + beep: "Издать Ноту", + explode: "Взрыв", + "explode/fire": "Огненный шар", + add_motion: "Импульс", + blink: "Перенос", + break_block: "Сломать Блок", + place_block: "Поставить Блок", + + "craft/cypher": "Создать Побрякушку", + "craft/trinket": "Создрать Штуковину", + "craft/artifact": "Создрать Артефакт", + "craft/battery": "Создать Сосуд Мыслей", + + recharge: "Зарядить Предмет", + erase: "Очистить Предмет", + create_water: "Создать Воду", + destroy_water: "Испарить Жидкость", + ignite: "Поджечь Блок", + extinguish: "Потушить Область", + conjure_block: "Магический Барьер", + conjure_light: "Магический Свет", + bonemeal: "Ускорить Рост", + edify: "Созидать Саженец", + colorize: "Использовать Пигмент", "sentinel/": { - create: "Summon Sentinel", - "create/great": "Summon Greater Sentinel", - destroy: "Banish Sentinel", - get_pos: "Locate Sentinel", - wayfind: "Wayfind Sentinel", + create: "Призвать Часового", + "create/great": "Призвать Великого Часового", + destroy: "Уничтожить Часового", + get_pos: "Место Часового", + wayfind: "Путь к Часовому", }, "potion/": { - weakness: "White Sun's Nadir", - levitation: "Blue Sun's Nadir", - wither: "Black Sun's Nadir", - poison: "Red Sun's Nadir", - slowness: "Green Sun's Nadir", + weakness: "Надир Белого Солнца", + levitation: "Надир Синего Солнца", + wither: "Надир Черного Солнца", + poison: "Надир Красного Солнца", + slowness: "Надир Зеленого Солнца", - regeneration: "White Sun's Zenith", - night_vision: "Blue Sun's Zenith", - absorption: "Black Sun's Zenith", - haste: "Red Sun's Zenith", - strength: "Green Sun's Zenith", + regeneration: "Зенит Белого Солнца", + night_vision: "Зенит Синего Солнца", + absorption: "Зенит Черного Солнца", + haste: "Зенит Красного Солнца", + strength: "Зенит Зеленого Солнца", }, flight: "Altiora", - "flight/range": "Anchorite's Flight", - "flight/time": "Wayfarer's Flight", - - lightning: "Summon Lightning", - summon_rain: "Summon Rain", - dispel_rain: "Dispel Rain", - create_lava: "Create Lava", - "teleport/great": "Greater Teleport", - brainsweep: "Flay Mind", - - eval: "Hermes' Gambit", - "eval/cc": "Iris' Gambit", - for_each: "Thoth's Gambit", - halt: "Charon's Gambit", + "flight/range": "Anchorite Полет", + "flight/time": "Wayfarer Полет", + + lightning: "Громовержец", + summon_rain: "Призвать дождь", + dispel_rain: "Прогнать дождь", + create_lava: "Создать лаву", + "teleport/great": "Великое Перемещение", + brainsweep: "Очистка разума", + + eval: "Гамбит Гермеса", + "eval/cc": "Гамбит Ириса", + for_each: "Гамбит Тота", + halt: "Гамбит Чарона", "interop/": { "gravity/": { - get: "Gravitational Purification", - set: "Alter Gravity", + get: "Отражение Гравитации", + set: "Изменить Гравитацию", }, "pehkui/": { - get: "Gulliver's Purification", - set: "Alter Scale", + get: "Отражение Гуливера", + set: "Изменить Размер", }, }, }, // hexcasting.action.book.[resloc] override the name of that pattern in the patchi book, for abbreviations "book.hexcasting:": { - get_entity_height: "Stadiometer's Prfn.", + get_entity_height: "Высот Преобр.", "get_entity/": { - animal: "Entity Prfn.: Животное", - monster: "Entity Prfn.: Монстр", - item: "Entity Prfn.: Предмет", - player: "Entity Prfn.: Игрок", - living: "Entity Prfn.: Живое", + animal: "Преобр Сущн.: Животное", + monster: "Преобр Сущн.: Монстр", + item: "Преобр Сущн.: Предмет", + player: "Преобр Сущн.: Игрок", + living: "Преобр Сущн.: Живое", }, - zone_entity: "Zone Dstl.: Any", + zone_entity: "Объед. Обл.: Any", "zone_entity/": { - animal: "Zone Dstl.: Животное", - monster: "Zone Dstl.: Монстр", - item: "Zone Dstl.: Предмет", - player: "Zone Dstl.: Игрок", - living: "Zone Dstl.: Живое", - not_animal: "Zone Dstl.: Не Животное", - not_monster: "Zone Dstl.: Не Монстр", - not_item: "Zone Dstl.: Не Предмет", - not_player: "Zone Dstl.: Не Игрок", - not_living: "Zone Dstl.: Не Живое", - }, - - mul: "Multiplicative Dstl.", - div: "Division Dstl.", - arcsin: "Inverse Sine Prfn.", - arccos: "Inverse Cosine Prfn.", - arctan: "Inverse Tangent Prfn.", - arctan2: "Inverse Tan. Prfn. II", + animal: "Объед. Обл.: Животное", + monster: "Объед. Обл.: Монстр", + item: "Объед. Обл.: Предмет", + player: "Объед. Обл.: Игрок", + living: "Объед. Обл.: Живое", + not_animal: "Объед. Обл.: Не Животное", + not_monster: "Объед. Обл.: Не Монстр", + not_item: "Объед. Обл.: Не Предмет", + not_player: "Объед. Обл.: Не Игрок", + not_living: "Объед. Обл.: Не Живое", + }, + + mul: "Умножение", + div: "Деление", + arcsin: "Обратный синус", + arccos: "Обратный косинус", + arctan: "Обратный тангенс", + arctan2: "Обратный тангенс II", "const/vec/": { - x: "Vector Rfln. +X/-X", - y: "Vector Rfln. +Y/-Y", - z: "Vector Rfln. +Z/-Z", + x: "Отражение Вектора +X/-X", + y: "Отражение Вектора +Y/-Y", + z: "Отражение Вектора +Z/-Z", }, - "read/entity": "Chronicler's Prfn.", - bool_to_number: "Numerologist's Prfn.", - number: "Numerical Reflection", - mask: "Bookkeeper's Gambit", + "read/entity": "Преображение Летописца", + bool_to_number: "Нумерологист", + number: "Численное Отражение", + mask: "Гамбит Библиотекаря", }, }, // ^ action "special.hexcasting:": { - number: "Numerical Reflection: %s", - mask: "Bookkeeper's Gambit: %s", + number: "Численное Отражение: %s", + mask: "Гамбит Библиотекаря: %s", }, "rawhook.hexcasting:": { - open_paren: "Introspection", - close_paren: "Retrospection", - escape: "Consideration", - undo: "Evanition", + open_paren: "Интроспекция", + close_paren: "Ретроспектива", + escape: "Рассмотрение", + undo: "Исчезновение", }, "iota.hexcasting:": { - "null": "Null", - double: "Number", - boolean: "Boolean", - entity: "Entity", - list: "List", - pattern: "Pattern", - garbage: "Garbage", - vec3: "Vector", + "null": "Ничто", + double: "Число", + boolean: "Истина/Ложь", + entity: "Сущность", + list: "Список", + pattern: "Руна", + garbage: "Мусор", + vec3: "Вектор", }, mishap: { "": "%s: %s", - invalid_pattern: "Этот Pattern не связан ни с каким действием", + invalid_pattern: "Эта руна не связана ни с каким действием", unescaped: "Ожидалось, что он оценит паттерн, но вместо этого он оценил %s", not_enough_args: "ожидалось %s или больше аргументов, но высота стека была всего %s", no_args: "ожидалось %s или больше аргументов, но стек был пуст", - too_many_close_parens: "Сначала я не прибегал к самоанализу", + too_many_close_parens: "Слишком много рун закрытий", wrong_dimension: "не удается увидеть %s из %s", entity_too_far: "%s находится вне диапазона", @@ -876,8 +876,8 @@ divide_by_zero: { divide: "Попытался разделить %s на %s", - project: "Попытался спроецировать %s на %s", - exponent: "Попытался увеличить значение %s до значения %s", + project: "Попытался спроецировать %s на %s", + exponent: "Попытался возвести %s в степень %s", logarithm: "Попытался получить логарифм %s в виде базового значения %s", zero: { @@ -890,7 +890,7 @@ cos: "косинус %s", }, - no_akashic_record: "Нет Akashic Record на %s", + no_akashic_record: "Нет Записи Акаши на %s", disallowed: "был запрещен администраторами сервера", disallowed_circle: "был запрещен в кругах заклинаний администраторами сервера", invalid_spell_datum_type: "Пытался использовать значение недопустимого типа в качестве параметра для написания: %s (класс %s). Это ошибка в настройках.", @@ -902,18 +902,18 @@ class: { double: "число", - boolean: "a boolean", + boolean: "логика", vector: "вектор", list: "список", widget: "действие", - pattern: "pattern", + pattern: "руна", entity: { - "": "entity", - item: "предмет entity", + "": "сущность", + item: "предмет-сущность", player: "игрок", villager: "житель", - living: "живое entity", + living: "живая сущность", }, unknown: "(неизвестно, это ошибка)", @@ -921,12 +921,12 @@ numvec: "число или вектор", numlist: "целое число или список", - "list.pattern": "список patterns", + "list.pattern": "список рун", double: { positive: { - "": "a positive number", - less: "a positive number less than %d", + "": "положительное число", + less: "положительное число меньше %d", "less.equal": "положительное число, меньшее или равное %d", }, between: "число между %d и %d", @@ -942,8 +942,8 @@ between: "целое число между %d и %d", }, - evaluatable: "something evaluatable", - bool_commute: "boolean - 0 или 1", + evaluatable: "нечто исполняемое", + bool_commute: "Логика - 0 или 1", }, location: { @@ -959,14 +959,14 @@ offhand: "нужен %s в другой руке но получил %dx %s", iota: { - "": "место для хранения iotas", - read: "место, откуда можно читать iotas", - write: "место, куда можно записывать iotas", + "": "место для хранения йоты", + read: "место, откуда можно читать йоты", + write: "место, куда можно записывать йоты", readonly: "место, которое будет принимать %s", }, - media: "предмет, содержащий Media", - media_for_battery: "необработанный Media предмет", + media: "предмет, содержащий мысли", + media_for_battery: "необработанный мысли предмет", only_one: "ровно один предмет", eraseable: "предмет, поддающийся стиранию", bottle: "стеклянная бутылочка", @@ -982,35 +982,35 @@ }, "circle.bool_directrix": { - no_bool: "значение iota, обнаруженное в %s, было %s, а не bool", + no_bool: "значение йоты, обнаруженное в %s, было %s, а не bool", empty_stack: "стек был пуст в момент %s", }, }, // ^ mishap circles: { - no_exit: "Поток Media в %s не смог найти выход", - many_exits: "Поток Media в %s имел слишком много выходов", + no_exit: "Поток мысли в %s не смог найти выход", + many_exits: "Поток мысли в %s имел слишком много выходов", }, // === Patchi stuff! === - landing: "Кажется, я открыл новый метод магических искусств, при котором человек рисует странные и дикие узоры на шестиугольной сетке. \ + landing: "Кажется, я открыл новый метод магических искусств, при котором человек рисует странные и дикие руны на шестиугольной сетке. \ Это меня восхищает. Я решил начать вести дневник своих мыслей и открытий.\ $(br2)$(l:https://forum.petra-k.at/index.php)Ссылка на форум/$", category: { basics: { "": "Приступая к работе", - desc: "Практикующие это искусство разыгрывали свои так называемые _Hexes рисуя странные узоры в воздухе с помощью $(l:items/staff)$(item)Staff/$ -- \ - или создавая $(l:items/hexcasting)$(item)могущественные магические предметы/$ что бы кастовать с их помощью. \ + desc: "Практикующие это искусство разыгрывали свои так называемые Заклинания рисуя странные руны в воздухе с помощью $(l:items/staff)$(item)Staff/$ -- \ + или создавая $(l:items/hexcasting)$(item)могущественные магические предметы/$ что бы исполнять руны с их помощью. \ Как я мог бы сделать то же самое?", }, casting: { "": "Hex Casting", - desc: "Я начал понимать, как старые мастера создавали свои _Hexes! Это немного сложно, \ + desc: "Я начал понимать, как старые мастера создавали свои Заклинания! Это немного сложно, \ но я уверен, что смогу с этим разобраться. Давайте посмотрим...", }, items: { @@ -1038,92 +1038,92 @@ }, patterns: { - "": "Patterns", - desc: "Список всех обнаруженных мной patterns, а также то, что они делают.", + "": "Руны", + desc: "Список всех обнаруженных мной руны, а также то, что они делают.", }, spells: { - "": "Заклинания", - desc: "Patterns и действия, которые оказывают магическое воздействие на окружающий мир.", + "": "Продвинутые Руны", + desc: "Руны, которые оказывают магическое воздействие на окружающий мир.", }, great_spells: { - "": "Великие Заклинания", - desc: "Заклинания, перечисленные здесь, предположительно обладают легендарной сложностью и силой. \ + "": "Великие Руны", + desc: "Руны, перечисленные здесь, предположительно обладают легендарной сложностью и силой. \ Похоже, что они использовались очень редко (как утверждается в текстах, на то есть веские причины). \ - Хотя, возможно, это просто бредни вымерших традиционалистов - закономерность есть закономерность.$(br2)\ + Хотя, возможно, это просто бредни давно умерших стариков.$(br2)\ Что может пойти не так?", }, }, // ^ categories entry: { - media: "Media", + media: "Мысли", geodes: "Жеоды", couldnt_cast: "Разочарование", start_to_see: "ЧТО Я ВИДЕЛ!", - "101": "Hex Casting 101", + "101": "Рунные заклинания: начало", vectors: "Учебник по векторам", mishaps: "Неудачи", stack: "Стек", naming: "Наименование", influences: "Влияние", - mishaps2: "Просвещёные неудачи", + mishaps2: "Просвещённые неудачи", amethyst: "Аметист", - staff: "Staves", - lens: "Магическая линза", + staff: "Посох", + lens: "Линза Прозрения", jeweler_hammer: "Ювелирный молоток", - thought_knot: "Thought-Knot", + thought_knot: "Узел мысли", focus: "Focus", - abacus: "Abacus", + abacus: "Cчеты", spellbook: "Книга Заклинаний", scroll: "Свитки", - slate: "Slates", + slate: "Плитки", // why is this called "hexcasting"? - hexcasting: "Предметы для Каста Заклинаний", - phials: "Сосуд Media", + hexcasting: "Предметы для Заклинаний", + phials: "Сосуд мысли", pigments: "Пигмент", - edified: "Edified Деревья", + edified: "Деревья Созидания", decoration: "Декоративные Блоки", the_work: "Работа", - brainsweeping: "On The Flaying of Minds", + brainsweeping: "Об очистке разума", spellcircles: "Круги Заклинаний", impetus: "Impeti", directrix: "Directrices", - akashiclib: "Akashic Libraries", + akashiclib: "Библиотеки Акаши", quenching_allays: "Quenching Allays", fanciful_staves: "Fanciful Staves", // and the actions readers_guide: "Как Читать Этот Раздел", // ops - basics_pattern: "Базовые Patterns", + basics_pattern: "Базовые руны", numbers: "Числа в Рунах", math: "Математика", advanced_math: "Продвинутая математика", - sets: "Sets", + sets: "Множества", consts: "Константы", stackmanip: "Манипулирование стеком", logic: "Логические операторы", - entities: "Entities", + entities: "Сущности", lists: "Манипулирование списками", patterns_as_iotas: "Escaping Patterns", readwrite: "Чтение и Запись", meta: "Meta-Evaluation", - circle_patterns: "Patterns для Кругов Заклинаний", - akashic_patterns: "Akashic Patterns", + circle_patterns: "Руны для Кругов Заклинаний", + akashic_patterns: "Руны Акаши", // spells itempicking: "Работа с Предметами", basic_spell: "Базовые заклинания", blockworks: "Манипулирование блоками", - nadirs: "Nadirs", - hexcasting_spell: "Создание Кастующих Предметов", - sentinels: "Sentinels", + nadirs: "Надир", + hexcasting_spell: "Создание Исполняющих Предметов", + sentinels: "Часовые", // internalize pigment uses the action name flights: "Полет", @@ -1155,34 +1155,34 @@ page: { media: { - "1": "_Media - это форма психической энергии, внешняя по отношению к разуму. Все живые существа, думая о чем-либо, вырабатывают незначительные количества _media; после того, как мысль закончена, средства массовой информации попадают в окружающую среду.$(br2)Искуство casting _Hexes заключается в манипуляции _media чтобы они выполняли ваши требования.", - "2": "_Media могут оказывать влияние на другие media-- силой и типом влияния можно манипулировать, используя _media в виде шаблонов.$(p)Знатоки искусства использовали концентрированный сгусток _media на конце палочки: размахивая им в воздухе в определенных конфигурациях, они могли манипулировать достаточным количеством _media с достаточной точностью, чтобы влиять на сам мир в форме _Hex.", - "3": "К сожалению, даже полностью разумное существо (предположительно, такое, как я) может генерировать лишь незначительное количество _media. Было бы совершенно непрактично пытаться использовать свои собственные мозговые способности для каста Hexes.$(br2)Но легенда гласит, что существуют подземные отложения, где _media медленно накапливается, превращаясь в кристаллические формы.$(p)Если бы я только мог найти что-нибудь из этого...", + "1": "Мысли - это форма психической энергии, внешняя по отношению к разуму. Все живые существа, думая о чем-либо, вырабатывают незначительное количество Мысли; после того, как мысль закончена, средства массовой информации попадают в окружающую среду.$(br2)Искуство Рунных Заклинаний заключается в манипуляции _мыслями чтобы они выполняли ваши требования.", + "2": "Мысли могут оказывать влияние на другие мысли-- силой и типом влияния можно манипулировать, используя Мысли в виде шаблонов.$(p)Знатоки искусства использовали концентрированный сгусток Мысли на конце палочки: размахивая им в воздухе в определенных конфигурациях, они могли манипулировать достаточным количеством Мысли с достаточной точностью, чтобы влиять на сам мир в форме _Рун.", + "3": "К сожалению, даже полностью разумное существо (предположительно, такое, как я) может генерировать лишь незначительное количество Мысли. Было бы совершенно непрактично пытаться использовать свои собственные силы для использование _Рун.$(br2)Но легенда гласит, что существуют подземные отложения, где Мысли медленно накапливаются, превращаясь в кристаллические формы.$(p)Если бы я только мог найти что-нибудь из этого...", }, geodes: { - "1": "Aга! Занимаясь добычей полезных ископаемых глубоко под землей, я обнаружил огромную жеоду, резонирующую с энергией - энергией, которая давила на мой череп и мои мысли. И теперь я держу это давление в своей руке, в твердой форме. Это $(italic)должно/$ быть тем местом, о котором говорится в легендах, где скапливается _media.$(br2)Эти $(l:items/amethyst)$(item)кристаллы аметиста/$ должны быть $(l:items/amethyst)$(thing)удобной, затвердевшей формой _Media/$.", + "1": "Aга! Занимаясь добычей полезных ископаемых глубоко под землей, я обнаружил огромную жеоду, резонирующую с энергией - энергией, которая давила на мой череп и мои мысли. И теперь я держу это давление в своей руке, в твердой форме. Это $(italic)должно/$ быть тем местом, о котором говорится в легендах, где скапливается Мысли.$(br2)Эти $(l:items/amethyst)$(item)кристаллы аметиста/$ должны быть $(l:items/amethyst)$(thing)удобной, затвердевшей формой Мысли/$.", "2": "Похоже, что в дополнение к $(l:items/amethyst)$(item)аметистовым осколкам/$ Я уже видел в прошлом, что из этих кристаллов также могут выпадать частицы порошкообразной $(l:items/amethyst)$(item)аметистовой пыли/$, а также эти $(l:items/amethyst)$(item) Заряженные кристаллы аметиста/$. Похоже, у меня будет больше шансов найти заряженные кристаллы аметиста $(l:items/amethyst)$(item)/$ если я воспользуюсь киркой с зачарованием Удачи.", - "3": "Когда я впитываю красоту кристалла, я чувствую, как в моем сознании стремительно вспыхивают связи. Как будто _media витающие в воздухе, проникают в меня, наполняют меня силой, проясняют меня... Это чудесное чувство.$(br2)Наконец-то мое изучение тайн начинает обретать какой-то смысл!$(p)Позвольте мне еще раз перечитать эти старые легенды, теперь, когда я знаю, на что смотрю.", + "3": "Когда я впитываю красоту кристалла, я чувствую, как в моем сознании стремительно вспыхивают связи. Как будто Мысли витающие в воздухе, проникают в меня, наполняют меня силой, проясняют меня... Это чудесное чувство.$(br2)Наконец-то мое изучение тайн начинает обретать какой-то смысл!$(p)Позвольте мне еще раз перечитать эти старые легенды, теперь, когда я знаю, на что смотрю.", }, couldnt_cast: { - "1": "Аргх! Почему он не позволяет мне произнести заклинание?!$(br2)Свиток, который я нашел, свидетельствует о его подлинности. Я могу $(italic)почувствовать/$ iкак он жужжит в свитке - схема верна, или настолько верна, насколько это возможно. Это заклинание $(italic)прямо здесь/$.$(p)Но мне кажется, что это происходит по другую сторону какой-то тонкой мембраны. Я вызвал это - оно попыталось проявиться - но оно $(italic)НЕ СМОГЛО/$.", + "1": "Аргх! Почему он не позволяет мне произнести заклинание?!$(br2)Свиток, который я нашел, казалось бы корректен. Я могу $(italic)почувствовать/$ как он трещит в свитке - схема верна, или настолько верна, насколько это возможно. Это заклинание $(italic)должно было сработать/$.$(p)Но мне кажется, что это происходит по другую сторону какой-то тонкой мембраны. Я вызвал это - оно попыталось проявиться - но оно $(italic)не смогло/$.", "2": "Мне показалось, что барьер, возможно, совсем немного ослаб от силы, которую я приложил к заклинанию; и все же, несмотря на мои величайшие усилия - мою глубочайшую сосредоточенность, мой тончайший аметист, мои самые точные рисунки, - он отказывается преодолевать барьер. Это сводит с ума.$(p)$(italic)На этом/$ мои занятия тайнами заканчиваются? Проклят бессилием, обречен потерять свои законные силы?$(br2)Я должен сделать глубокий вдох. Я должен поразмышлять над тем, что я узнал, даже если это было не так уж много...", - "3": "..После тщательного обдумывания... Я обнаружил перемену в себе.$(p)Кажется... вместо $(l:items/amethyst)$(item)аметиста/$, я получил возможность творить заклинания, используя свой собственный разум и жизненную энергию - точно так, как я читал в древних легендах.$(p)Я не уверен, почему я могу это сделать сейчас. Это просто ... бремя истины-знания- было всегда, и теперь я это вижу. Я знаю это. Я терплю это.$(br2)К счастью, я тоже чувствую свои пределы - я бы потратил на свое здоровье примерно два $(l:items/amethyst)$(item)заряженных аметиста/$'на сумму _media в самом расцвете сил.", + "3": "..После тщательного обдумывания... Я обнаружил перемену в себе.$(p)Кажется... вместо $(l:items/amethyst)$(item)аметиста/$, я получил возможность творить заклинания, используя свой собственный разум и жизненную энергию - точно так, как я читал в древних легендах.$(p)Я не уверен, почему я могу это сделать сейчас. Это просто ... бремя истины-знания- было всегда, и теперь я это вижу. Я знаю это. Я терплю это.$(br2)К счастью, я тоже чувствую свои пределы - я бы потратил на свое здоровье примерно два $(l:items/amethyst)$(item)заряженных аметиста/$'на сумму Мысли в самом расцвете сил.", "4": "Я содрогаюсь даже при мысли об этом - до сих пор я сохранял свой разум в основном нетронутым во время учебы. Но факт в том, что я являюсь одной из сторон хрупкой связи.$(p)Я связан с какой-то другой стороной - стороной, границы которой сузились из-за этой травмы. Место, где простые действия создают вечную славу.$(p)Неужели это так неправильно - хотеть этого для себя?", }, start_to_see: { "1": "Тексты не лгали. Природа взяла свое.", - "2": "Это... это было... $(p)...это была одна из $(italic)худших/$ вещей, с которыми я $(italic)когда-либо/$ сталкивался. Я предложил свой план Природе и получил в ответ искреннюю улыбку и ощущение разрыва - частичка меня самого откалывается, как аметистовая пыль под дождем.$(p)Мне повезло, что у меня $(italic)сохранился/$, не говоря уже о том, что у меня хватило ума написать это - я должен объявить вопрос закрытым, перепроверить свои математические выкладки, прежде чем ставить еще какие-либо _Hexes, и никогда больше не допускать подобной ошибки.", + "2": "Это... это было... $(p)...это была одна из $(italic)худших/$ вещей, с которыми я $(italic)когда-либо/$ сталкивался. Я предложил свой план Природе и получил в ответ искреннюю улыбку и ощущение разрыва - частичка меня самого откалывается, как аметистовая пыль под дождем.$(p)Мне повезло, что у меня $(italic)сохранился/$, не говоря уже о том, что у меня хватило ума написать это - я должен объявить вопрос закрытым, перепроверить свои математические выкладки, прежде чем ставить еще какие-либо Заклинания, и никогда больше не допускать подобной ошибки.", "3": "..Но.$(br2)Но на краткий миг эта часть меня... она $(italic)увидела/$... $(l:greatwork/the_work)$(thing)что-то/$. Какое-то место. (Такие различия, казалось, не имели значения перед лицом... того, что.)$(p)И... мембранный барьер-кожная граница, отделяющая меня от царства необузданных мыслей-потоков-света-энергии. Я помню - я видел - думал- вспоминал - чувствовал - барьер расплывался по краям, совсем чуть-чуть.$(p)Я хотел $(italic)покончить с этим./$", "4": "Я не должен был этого делать. Я $(italic)знаю/$Я не должен был. Это опасно. Это слишком опасно. Для этого требовалась сила... Мне пришлось бы $(italic)одним ударом оказаться на волосок от смерти/$.$(br2)Но я... так $(italic)близко/$.$(p)$(italic)Это/$ кульминация моего творчества. Это и есть $(#54398a)Просветление/$ Которого я так долго добивался. $(br2)Я хочу больше. Мне нужно увидеть это снова. Я $(italic)will/$ увижу это.$(p)Что значит мой смертный разум против бессмертной славы?", }, casting: { overview: { - "1": "Я считаю, что всегда полезно начинать с правильного шага. Итак, я собрал patterns для _Hex которые вызовут небольшой всплеск в той позиции, на которую я смотрю. Я полагаю, что изучение внутренней работы этого _Hex будет весьма поучительным.", + "1": "Я считаю, что всегда полезно начинать с правильного шага. Итак, я собрал руны которые вызовут небольшой всплеск в той позиции, на которую я смотрю. Я полагаю, что изучение внутренней работы этого заклинания будет весьма поучительным.", }, grid: { @@ -1190,154 +1190,154 @@ Применив $(thing)$(k:use)/$ держа его в руке, передо мной появится шестиугольная сетка из точек. \ Затем я могу щелкнуть, перетащить от точки к точке и отпустить, чтобы нарисовать узор.$(br2)\ Как только я отправляю шаблон, он выполняется (смотрите следующую главу).", - "2": "Нажатие кнопки $(thing)$(k:escape)/$ сохраняет и закрывает сетку; когда я в следующий раз использую свой посох, все мои patterns и iotas по-прежнему будут там.$(br2)\ - Если я захочу сбросить свое состояние кастинга, я могу сделать это присев, открывая сетку.", + "2": "Нажатие кнопки $(thing)$(k:escape)/$ сохраняет и закрывает сетку; когда я в следующий раз использую свой посох, все мои руны и йоты по-прежнему будут там.$(br2)\ + Если я захочу сбросить свое состояние заклинания, я могу сделать это присев, открывая сетку.", }, "patterns&actions": { - "1": "$(thing)Patterns/$ это пути, проложенные по сетке _media. Я считаю, что шестикратная симметрия узоров - это то, что дало название моему искусству.$(br2)\ - $(thing)Действия/$, между тем, - это то, что $(italic)делают/$ patterns.", - "2": "Разница подобна разнице между $(italic)словами /$ и $(italic)значениями/$. \ + "1": "$(thing)Руны/$ это пути, проложенные по сетке Мысли. Я считаю, что симметрия узоров в шестиугольниках - это то, что дало название моему искусству.$(br2)\ + $(thing)Действия/$, между тем, - это то, что $(italic)делают/$ руны.", + "2": "Разница подобна разнице между $(italic)словами /$ и их $(italic)значениями/$. \ Любое сочетание букв образует слово, но большинство из них ничего не означают. \ - Аналогично, любая закорючка, пропущенная через _media технически является pattern, но большинство из них ничего не сделают.", + Аналогично, любая закорючка, пропущенная через Мысли технически является руной, но большинство из них ничего не сделают.", "3": "Действия чем-то напоминают команды к правилам великой системы, управляющей Вселенной (которые, как я видел, в некоторых текстах олицетворяются как \"Природа.\"). \ Они склонны делать одну из нескольких вещей:\ - $(li)Соберите некоторую информацию о мире, например, определите местоположение - entity.\ + $(li)Соберите некоторую информацию о мире, например, определите местоположение - сущность.\ $(li)Манипулируйте собранной информацией, например, находите расстояние между двумя позициями.\ $(li)Произведите какое-нибудь магическое воздействие на мир, например, вызовите молнию или взрыв.$(br)\ Эти последние виды действий называются \"Заклинаниями.\", и, как правило, являются тем, что привлекает людей к искусству.", - "4": "Таким образом, _Hex - это последовательность допустимых patterns, представленных Природе в определенной последовательности. \ - Природа интерпретирует каждый из этих patterns по отдельности и, если понимает, изменяет мир в соответствии с моими прихотями. \ - (Или каковы, по его мнению, мои прихоти.)", - "5": "Хотя некоторые действия могут быть выполнены легко, некоторые требуют оплаты в виде _media. \ + "4": "Таким образом, _Заклинания - это последовательность допустимых рун, представленных Природе в определенной последовательности. \ + Природа интерпретирует каждую руну по отдельности и, если понимает, изменяет мир в соответствии с моими прихотями. \ + (Или каковы, по её мнению, мои прихоти.)", + "5": "Хотя некоторые действия могут быть выполнены легко, некоторые требуют оплаты в виде Мысли. \ Я верю, что концентрированная ментальная энергия используется как своего рода аргумент для Природы, убеждающий ее в том, что она действительно должна сделать то, о чем я прошу. \ Большинство заклинаний требуют такого рода оплаты, но некоторые действия, не связанные с заклинаниями, тоже требуют такой оплаты.$(br2)\ Я записал стоимость каждого действия, если таковая имелась, на соответствующих страницах.", }, iotas: { - "1": "The \"nouns\" in Nature's language are called $(thing)iotas/$. \ - На самом базовом уровне Hex casting - это искусство манипулирования iotas.$(br2)\ - Iotas бывают самых разных типов:\ + "1": "В языке природы \"существительные\" названы $(thing)йоты/$. \ + На самом базовом уровне Рунная магия - это искусство манипулирования йотами.$(br2)\ + Йоты бывают самых разных типов:\ $(li)Числа.\ $(li)Векторы - это набор из трех чисел, представляющих положение, движение или направление.\ - $(li)Booleans или \"bools\" представляющие абстрактное значение True или False(1 или 0)\ - $(li)Entities - подобные мне, цыплятам и мини-тележкам.", - "2": "$(li)Influences - своеобразные типы йоты, которые, по-видимому, представляют собой абстрактные идеи.\ - $(li)Patterns - используемые для создания магических предметов и поистине умопомрачительных трюков, таких как $(italic)заклинания которые накладывают другие заклинания/$.\ + $(li)Логические значения абстрактное значение Истина или Ложь (1 или 0)\ + $(li)Сущности - подобные мне, цыплятам, лодкам и лежащим на земле аметистам.", + "2": "$(li)Влияния - своеобразные типы йот, которые, по-видимому, представляют собой абстрактные идеи.\ + $(li)Руны - используемые для создания магических предметов и поистине умопомрачительных трюков, таких как $(italic)заклинания, что манипулируют другими заклинаниями/$.\ $(li)Список - несколько вышеперечисленных типов вместе", - "3": "Как правило, я предоставляю iotas для действий. \ + "3": "Как правило, я предоставляю йоты для действий. \ Например, возьмем $(l:patterns/spells/basic#hexcasting:explode)$(action)Взрыв/$. \ - Для этого заклинания требуется числовая iota, указывающая на силу, и векторная iota, указывающая на местоположение.$(br2)\ - Или возьмите $(l:patterns/basic#hexcasting:get_pos)$(action)Compass Purification/$. \ - При этом берется iota entity и преобразуется в векторную iota, представляющую положение этого entity.", + Для этого заклинания требуется числовая йота, указывающая на силу, и векторная йота0, указывающая на местоположение.$(br2)\ + Или возьмите $(l:patterns/basic#hexcasting:get_pos)$(action)/$. \ + При этом берется йота сущности и преобразуется в вектор йота, представляющую положение этого сущности.", }, }, // Casting "101": { - "1": "Кастовать _Hex довольно сложно - неудивительно, что это искусство было утрачено со временем! Мне придется внимательно перечитать свои записи.$(br2)Я могу запустить _Hex нажав $(k:use) держа в руке $(l:items/staff)$(item)Staff/$ - это приведет к появлению передо мной шестиугольной сетки из точек. Затем я могу щелкать и перетаскивать от точки к точке, чтобы рисовать узоры в _media сетки; завершение создания узора приведет к выполнению соответствующего действия (подробнее об этом позже).", - "2": "Как только я нарисую достаточно узоров, чтобы произнести заклинание, сетка исчезнет, когда будет выпущен сохраненный мной _media. Удерживая $(k:sneak) при использовании моего $(l:items/staff)$(item)staff/$ вы также очистите сетку.$(br2)Итак, как же работают patterns? Вкратце:$(li)$(italic)Patterns/$ выполняет...$(li)$(italic)Действия/$, которыми манипулируют...$(li)$(l:casting/stack)$(italic)Стек/$, который представляет собой список из...$(li)$(italic)Iotas/$, которые являются просто единицами информации.", - "3": "Во-первых, $(thing)patterns/$. Они важны - это то, что я использую для манипулирования _media вокруг меня. Определенные паттерны, будучи нарисованными, вызовут выполнение оределённых действий. Действие - это то, что на самом деле творит чудеса; все шаблоны определенным образом влияют на _media и когда эти влияния в конечном итоге приводят к чему-то полезному, мы называем это действием.$(br2)_Media может быть непостоянной: если я нарисую неверный pattern, я получу некоторый $(l:casting/influences)$(action)мусор/$ результат где-нибудь в моем стеке (читайте дальше...)", + "1": "Исполнение рунных заклинаний немного сложный процесс, неудивительно, что это искусство было забыто. Мне придется внимательно перечитать свои записи.$(br2)Я могу начать писать Руну нажав $(k:use) держа в руке $(l:items/staff)$(item)Посох/$ - это приведет к появлению передо мной шестиугольной сетки из точек. Затем я могу щелкать и перетаскивать от точки к точке, чтобы рисовать руны сетки; завершение создания узора приведет к выполнению соответствующего действия (подробнее об этом позже).", + "2": "Как только я нарисую достаточно рун, чтобы произнести заклинание, сетка исчезнет, когда будут выпущены сохраненные мною мысли. Удерживая $(k:sneak) при использовании моего $(l:items/staff)$(item)посоха/$ вы также очистите сетку.$(br2)Итак, как же работают руны? Вкратце:$(italic)Руны/$ выполняют $(italic)Действия/$, которые манипулируют...$(l:casting/stack)$(italic)Стэком/$, который представляет собой список из...$(italic)Йоты/$, которые являются просто единицами информации.", + "3": "Во-первых, $(thing)Руны/$. Они важны - это то, что я использую для манипулирования мысли вокруг меня. Определенные паттерны, будучи нарисованными, вызовут выполнение оределённых действий. Действия - это то, что на самом деле творит чудеса; все шаблоны определенным образом влияют на мысли и когда эти влияния в конечном итоге приводят к чему-то полезному, мы называем это действием.$(br2)Мысли могут быть непостоянными: если я нарисую неверную руну, я получу некоторый $(l:casting/influences)$(action)мусор/$ как результат где-нибудь в моем стеке (читайте дальше...)", "4.header": "Вот пример", - "4": "Интересно отметить, что $(italic)угол/$ pattern похоже, вообще не имеет значения. Оба этих паттерна выполняют действие, называемое $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$, например.", - "5": "_Hex приводится в действие путем последовательного выполнения (допустимых) действий. Каждое действие может выполнять одну из нескольких задач:$(li)Собирать некоторую информацию об окружающей среде, оставляя ее на вершине стека;$(li)манипулировать собранной информацией (например, складывать два числа); или$(li)выполнять какой-либо магический эффект, например вызывать молнию или взрыв. (Эти действия называются \"заклинания\")$(p)Когда я начинаю использовать _Hex, создается пустой стек. Действия управляют вершиной этого стека.", - "6": "Например, $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$ создаст iota представляющую $(italic)меня/$, заклинателя, и добавит ее в начало стека. $(l:patterns/basics#hexcasting:entity_pos/eye)$(action)Compass Purification/$ возьмет iota расположенную на вершине стека, если она представляет entity, и преобразует ее в iota представляющую местоположение этого объекта.$(br2)Таким образом, рисование этих patterns в таком порядке привело бы к тому, что в стеке появилась бы iota представляющая мою позицию.", - "7": "$(thing)Iotas/$ может представлять вещи, такие как я сам или мое положение, но есть несколько других типов, с которыми я могу манипулировать с помощью $(thing)Actions/$. Вот подробный список:$(li)Числа (которые некоторые легенды называют \"дублями\");$(li)Векторы, коллекция из трех чисел, представляющих положение, движение или направление в мире;$(li)Булевы значения или \"bools\" в сокращении, представляющие абстрактное Истина или Ложь,", - "8": "$(li)Entities, подобные мне, курицам и вагонеткам;$(li)Influences, особые типы иоты, которые кажутся представлять абстрактные идеи;$(li)Сами узоры, используемые для создания магических предметов и поистине поразительных подвигов, таких как $(italic)заклинания, которые произносят другие заклинания/$; и$(li)Список нескольких из вышеперечисленного, собранных в одну иоту.", - "9": "Конечно, бесплатного обеда не бывает. Все заклинания и определенные другие действия требуют _media в качестве оплаты.$(br2)Наилучшее, что я могу понять, _Hex - это нечто вроде плана действий, представленного Природе - в этой аналогии _media используется для предоставления аргументов в поддержку этого плана, чтобы Природа приняла ваш план и осуществила его.", - "10": "Помимо этого, кажется, что никто не проводил серьезных исследований о том, насколько $(italic)много/$ стоит конкретный кусок $(l:items/amethyst)$(item)аметиста/$. По моим лучшим оценкам, $(l:items/amethyst)$(item)Осколок Аметиста/$ стоит примерно пять кусков $(l:items/amethyst)$(item)Аметистовой Пыли/$, а $(l:items/amethyst)$(item)Заряженный Аметистовый Кристалл/$ - примерно десять.$(br2)Странно, что кажется, никакая другая форма $(l:items/amethyst)$(item)аметиста/$ не подходит для использования при создании _Hex. Я подозреваю, что целые блоки или кристаллы слишком прочны, чтобы легко распутываться в _media.", - "11": "Также стоит отметить, что каждое действие немедленно потребляет необходимую _media, а не все сразу, когда _Hex завершается. Кроме того, действие всегда потребляет целые предметы - действие, которое требует только столько _media, сколько стоит одна $(l:items/amethyst)$(item)Аметистовая Пыль/$, потребует целый $(l:items/amethyst)$(item)Заряженный Аметистовый Кристалл/$, если это единственное, что есть в моем инвентаре.$(br2)Таким образом, может быть хорошей идеей взять пыль для колдовства тоже - не тратьте зря, не будет желания...", - "12": "Я также должен быть осторожен, чтобы убедиться, что у меня действительно достаточно Аметиста в инвентаре - некоторые старые тексты говорят, что Природа с удовольствием использует собственный разум в качестве оплаты. Они описывают это чувство как ужасное, но странно эйфорическое, \"[...] искрящееся растворение в свет и энергию...\" Возможно, поэтому все старые практикующие искусство сходили с ума. Я не могу представить, что сжигать кусочки своего разума ради силы - $(italic)здорово/$.", - "13": "Maybe something's changed, though. In my experiments, I've never managed to do it; if I run out of _media, the spell will simply fail to cast, as if some barrier is blocking it from harming me. $(br2)It would be interesting to get to the bottom of that mystery, but for now I suppose it'll keep me safe.", - "14": "I have also found an amusing tidbit on why so many practitioners of magic in general seem to go mad, which I may like as some light and flavorful reading not canonical to my world.$(br2)$(italic)Content Warning: some body horror and suggestive elements./$", + "4": "Интересно отметить, что $(italic)угол/$ руны похоже, вообще не имеет значения, самое главное это начальная точка руны и градус на который вы поворачиваете линию. Оба этих паттерна выполняют действие, называемое $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$, например.", + "5": "_Заклинание приводится в действие путем последовательного выполнения (допустимых) действий. Каждое действие может выполнять одну из нескольких задач:$(li)Собирать некоторую информацию об окружающей среде, оставляя ее на вершине стека;$(li)манипулировать собранной информацией (например, складывать два числа); или$(li)выполнять какой-либо магический эффект, например вызывать молнию или взрыв. (Эти действия называются \"заклинания\")$(p)Когда я начинаю использовать посох, создается пустой стек. Действия управляют вершиной этого стека.", + "6": "Например, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$ создаст iota представляющую $(italic)меня/$, заклинателя, и добавит ее в начало стека. $(l:patterns/basics#hexcasting:entity_pos/eye)$(action)Преобразование глаз/$ возьмет iota расположенную на вершине стека, если она представляет сущность, и преобразует ее в iota представляющую местоположение этого объекта.$(br2)Таким образом, рисование этих рун в таком порядке привело бы к тому, что в стеке появилась бы iota представляющая мою позицию.", + "7": "$(thing)Йоты/$ может представлять вещи, такие как я сам или мое положение, но есть несколько других типов, с которыми я могу манипулировать с помощью $(thing)Действия/$. Вот подробный список:$(li)Числа (которые некоторые легенды называют \"double\");$(li)Векторы, коллекция из трех чисел, представляющих положение, движение или направление в мире;$(li) Логические значения или \"bools\" в сокращении, представляющие абстрактное Истина или Ложь,", + "8": "$(li)Сущности, подобные мне, курицам и вагонеткам;$(li)Influences, особые типы иоты, которые кажутся представлять абстрактные идеи;$(li)Сами руны, используемые для создания магических предметов и поистине поразительных подвигов, таких как $(italic)заклинания, которые произносят другие заклинания/$; и$(li)Список нескольких из вышеперечисленного, собранных в одну iota.", + "9": "Конечно, бесплатный сыр только в мышеловке. Все заклинания и определенные другие действия требуют Мысли в качестве оплаты.$(br2)Как я могу понять, _Рунные заклинания - это нечто вроде плана действий, представленного Природе - в этой аналогии Мысли используются для убеждения, чтобы Природа приняла план и осуществила его.", + "10": "Помимо этого, кажется, что никто не проводил серьезных исследований о том, насколько $(italic)много/$ стоит конкретный кусок $(l:items/amethyst)$(item)аметиста/$. По моим лучшим оценкам, $(l:items/amethyst)$(item)Осколок Аметиста/$ стоит примерно пять кусков $(l:items/amethyst)$(item)Аметистовой Пыли/$, а $(l:items/amethyst)$(item)Заряженный Кристалл Аметиста/$ - примерно десять.$(br2)Странно, что кажется, никакая другая форма $(l:items/amethyst)$(item)аметиста/$ не подходит для использования при создании _Рунных заклинаний. Я подозреваю, что целые блоки или кристаллы слишком прочны, чтобы легко распутываться в Мысли.", + "11": "Также стоит отметить, что каждое действие немедленно потребляет необходимые Мысли, а не все сразу, когда Заклинание завершается. Кроме того, действие всегда потребляет целые предметы - действие, которое требует только столько Мысли, сколько стоит одна $(l:items/amethyst)$(item)Аметистовая Пыль/$, потребует целый $(l:items/amethyst)$(item)Заряженный Аметистовый Кристалл/$, если это единственное, что есть в моем инвентаре.$(br2)Таким образом, может быть хорошей идеей взять пыль для колдовства тоже - не тратьте зря, не будет желания...", + "12": "Я также должен быть осторожен, чтобы убедиться, что у меня действительно достаточно Аметиста в инвентаре - некоторые старые тексты говорят, что Природа с удовольствием использует разум в качестве оплаты. Они описывают это чувство как ужасное, но странно эйфорическое, \"[...] искрящееся растворение в свет и энергию...\" Возможно, поэтому все старые практикующие искусство сходили с ума. Я не могу представить, каково $(italic)сжигать кусочки своего разума ради силы/$.", + "13": "Но кажется что-то не так, в ходе моих экспериментов мне ещё не доводилось достить такого. Когда у меня кончается аметист заклинание просто обрывается! Будто бы некоторый барьер останавливает меня, спасает.$(br2)Мне интересно разгадать эту тайну, пока что я защищёен от этого.", + "14": "Я нашел некоторую информацию о том почему многие маги сходят с ума, неканоническое чтиво что я мог бы счесть крайне страшным.$(br2)$(italic)Предупреждение: элементы ужасных изощрений с телом./$", "14.link_text": "Goblin Punch", - "15": "Наконец, кажется, что заклинания имеют максимальную дальность воздействия, около 32 блоков от моего положения. Попытка воздействовать на что-либо за пределами этого приведет к неудаче заклинания.$(br2)Несмотря на это, если у меня есть ссылка на игрока, я могу воздействовать на него откуда угодно. Однако это применимо только к прямому воздействию на них; я не могу использовать это для воздействия на мир вокруг них, если они за пределами моего диапазона.$(br)Мне следует быть осторожным, когда даю такую ссылку. В то время как дружелюбные _Hexcasters могут использовать их с большим эффектом и пользой, мне страшно думать, что мог бы сделать кто-то злонамеренный с этим.", + "15": "Наконец, кажется, что заклинания имеют максимальную дальность воздействия, около 32 блоков от моего положения. Попытка воздействовать на что-либо за пределами этого приведет к неудаче заклинания.$(br2)Несмотря на это, если у меня есть истинное имя игрока, я могу воздействовать на него откуда угодно. Однако это применимо только к прямому воздействию на них; я не могу использовать это для воздействия на мир вокруг них, если они за пределами моего диапазона.$(br)Мне следует быть крайне осторожным и не давать никому свое истинное имя. В то время как дружелюбные Рунные маги могут использовать их с большим эффектом и пользой, мне страшно думать, что мог бы сделать кто-то злонамеренный с этим...", }, vectors: { "1": "Похоже, мне придется быть искусным с векторами, если я собираюсь добиться успеха в своих исследованиях. Я собрал здесь некоторые ресурсы по векторам, если обнаружу, что не знаю, как с ними работать.$(br2)Прежде всего, просветительское видео по этой теме.", "1.link_text": "3blue1brown", - "2": "Кроме того, кажется, что маги, которые манипулировали $(thing)Энергией Пси/$ (так называемые \"мастера заклинаний\"), несмотря на их плохой вкус в названиях, имели некоторые довольно эффективные уроки по векторам для своих последователей. Я позволил себе разместить ссылку на один из их текстов на следующей странице.$(br2)Похоже, что они использовали другой язык для своего колдовства:$(li)\"Кусок Заклинани\" было их название для действия;$(li)\"Фокус\" было их название для заклинания; и$(li)\"Оператор\" было их название для не-заклинательного действия.", + "2": "Кроме того, кажется, что маги, которые манипулировали $(thing)Псиэнергией/$ (так называемые \"мастера заклинаний\"), несмотря на их плохой вкус в названиях, имели некоторые довольно эффективные уроки по векторам для своих последователей. Я позволил себе разместить ссылку на один из их текстов на следующей странице.$(br2)Похоже, что они использовали другой язык для своего колдовства:$(li)\"Кусок Заклинани\" было их название для действия;$(li)\"Талисман\" было их название для заклинания; и$(li)\"Оператор\" было их название для не-заклинательного действия.", "3": "Ссылка Сдесь.", "3.link_text": "Psi Codex", }, mishaps: { - "1": "К сожалению, я не (пока что) совершенное существо. Иногда я допускаю ошибки в своих исследованиях и произношении _Hexes; например, неправильное нарисование узора или попытка вызвать действие с неправильными иотами. И Природа обычно не смотрит благосклонно на мои ошибки - вызывая то, что называется $(italic)несчастье/$.", - "2": "Узор, вызывающий несчастье, будет светиться красным на моей сетке. В зависимости от типа ошибки, я также могу ожидать определенного вредного эффекта и обильного разбрызгивания красного и разноцветных искр, поскольку неправильно обработанная _media сворачивается в свет определенного цвета.", + "1": "К сожалению, я не (пока что) совершенное существо. Иногда я допускаю ошибки в своих исследованиях и произношении Заклинания; например, неправильное нарисование узора или попытка вызвать действие с неправильными иотами. И Природа обычно не смотрит благосклонно на мои ошибки - вызывая то, что называется $(italic)несчастье/$.", + "2": "Узор, вызывающий несчастье, будет светиться красным на моей сетке. В зависимости от типа ошибки, я также могу ожидать определенного вредного эффекта и обильного разбрызгивания красного и разноцветных искр, поскольку неправильно обработанная Мысли сворачивается в свет определенного цвета.", "3": "К счастью, хотя плохие последствия несчастий, безусловно, $(italic)раздражающие/$, ни одно из них не является особенно разрушительным в долгосрочной перспективе. Нечего лучше делать, чем смахнуть пыль с себя и попробовать снова... но все равно я должен стремиться к лучшему.$(br2)Ниже приведен список несчастий, который я составил.", - "invalid_pattern.title": "Invalid Pattern", + "invalid_pattern.title": "Некорретная руна", invalid_pattern: "Нарисованный узор не связан ни с одним действием.$(br2)Вызывает желтые искры, и $(l:casting/influences)$(action)Мусор/$ будет помещен в верхнюю часть моего стека.", - "not_enough_iotas.title": "Not Enough Iotas", - not_enough_iotas: "Для действия требовалось больше иот, чем было в стеке.$(br2)Вызывает светло-серые искры, и столько $(l:casting/influences)$(action)Мусора/$, сколько потребовалось бы для заполнения количества аргументов, будет добавлено.", + "not_enough_iotas.title": "Недостаточно Йот", + not_enough_iotas: "Для действия требовалось больше йот, чем было в стеке.$(br2)Вызывает светло-серые искры, и столько $(l:casting/influences)$(action)Мусора/$, сколько потребовалось бы для заполнения количества аргументов, будет добавлено.", - "incorrect_iota.title": "Incorrect Iota", + "incorrect_iota.title": "Неверный тип Йота", incorrect_iota: "Выполненное действие ожидало иоту определенного типа в качестве аргумента, но получило что-то недопустимое. Если несколько иот недопустимы, сообщение об ошибке будет указывать только на ошибку в самом глубоком уровне стека.$(br2)Вызывает темно-серые искры, и недопустимый иот будет заменен на $(l:casting/influences)$(action)Мусор/$.", - "vector_out_of_range.title": "Vector Out of Ambit", + "vector_out_of_range.title": "Дальняя позиция", vector_out_of_range: "Действие пыталось воздействовать на мир в точке, находящейся за пределами моего диапазона.$(br2)Вызывает пурпурные искры, и предметы в моих руках будут вырваны и брошены в направлении нарушающего места.", - "entity_out_of_range.title": "Entity Out of Ambit", + "entity_out_of_range.title": "Сущность далеко", entity_out_of_range: "Действие пыталось воздействовать на существо, находящееся за пределами моего диапазона.$(br2)Вызывает розовые искры, и предметы в моих руках будут вырваны и брошены в направлении нарушающего существо.", - "entity_immune.title": "Entity is Immune", + "entity_immune.title": "Существо неизменяемо", entity_immune: "Действие пыталось воздействовать на существо, которое не может быть изменено этим.$(br2)Вызывает синие искры, и предметы в моих руках будут вырваны и брошены в направлении нарушающего существо.", - "math_error.title": "Mathematical Error", + "math_error.title": "Математический парадокс", math_error: "Действие совершило что-то оскорбительное для законов математики, например, деление на ноль.$(br2)Вызывает красные искры, добавляет $(l:casting/influences)$(action)Мусор/$ в мой стек, и мой разум будет истощен, украв половину оставшейся у меня энергии. Похоже, что Природа возмущается подобными операциями и делит $(italic)меня/$ в ответ.", - "incorrect_item.title": "Incorrect Item", + "incorrect_item.title": "Неправильный предмет", incorrect_item: "Действие требует какого-то предмета, но предоставленный мной предмет не подходит.$(br2)Вызывает коричневые искры. Если нарушающий предмет был в моей руке, он будет брошен на пол. Если это было существо, оно будет брошено в воздух.", - "incorrect_block.title": "Incorrect Block", - incorrect_block: "Действие требует наличия определенного блока в целевом месте, но предоставленный блок не подходит.$(br2)Вызывает яркие зеленые искры и создает мимолетный взрыв в указанном месте. Однако этот взрыв, кажется, не наносит вреда ни мне, ни миру, ни чему-либо еще; он просто пугающий.", + "incorrect_block.title": "Неправильный блок", + incorrect_block: "Действие требует наличия определенного блока в целевом месте, но предоставленный блок не подходит.$(br2)Вызывает яркие зеленые искры и создает мимолетный взрыв в указанном месте. Однако этот взрыв, кажется, не наносит вреда ни мне, ни миру, ни чему-либо еще;просто пугалка.", "retrospection.title": "Hasty Retrospection", - retrospection: "Я попытался нарисовать $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Ретроспекция/$ без предварительного рисования $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Интроспекция/$.$(br2)Вызывает оранжевые искры и помещает шаблон для $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Ретроспекция/$ в стек как шаблон иота.", + retrospection: "Я попытался нарисовать $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Ретроспектива/$ без предварительного рисования $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Интроспекция/$.$(br2)Вызывает оранжевые искры и помещает шаблон для $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Ретроспектива/$ в стек как шаблон иота.", "too_deep.title": "Delve Too Deep", too_deep: "Оценено слишком много заклинаний с метаоценкой от одного заклинания.$(br2)Вызывает темно-синие искры и лишает меня всего воздуха.", - "true_name.title": "Transgress Other", - true_name: "Я попытался $(l:patterns/readwrite#hexcasting:write)$(action)сохранить ссылку/$ на другого игрока на постоянный носитель.$(br2)Вызывает черные искры и лишает меня зрения примерно на одну минуту.", + "true_name.title": "Нарушение Законов", + true_name: "Я попытался $(l:patterns/readwrite#hexcasting:write)$(action)сохранить истинное имя/$ другого игрока на постоянный носитель.$(br2)Вызывает черные искры и лишает меня зрения примерно на одну минуту.", - "disabled.title": "Disallowed Action", + "disabled.title": "Запрещенное действие", disabled: "Я попытался выполнить действие, которое было запрещено администратором сервера.$(br2)Вызывает черные искры.", - "other.title": "Catastrophic Failure", - other: "Ошибка в моде вызвала иоту недопустимого типа или иным образом привела к сбою заклинания. $(l:https://github.com/gamma-delta/HexMod/issues)Пожалуйста, откройте отчет об ошибке!/$$(br2)Вызывает черные искры.", + "other.title": "Катастрофическая ошибка", + other: "Ошибка в моде вызвала iota недопустимого типа или иным образом привела к сбою заклинания. $(l:https://github.com/gamma-delta/HexMod/issues)Пожалуйста, откройте отчет об ошибке!/$$(br2)Вызывает черные искры.", }, stack: { - "1": "Стек $(thing)Stack/$, также известный как \"LIFO\", является концепцией, заимствованной из информатики. Вкратце, это коллекция вещей, спроектированная так, что вы можете взаимодействовать только с последней использованной вещью.$(br2)Представьте стопку тарелок, где новые тарелки добавляются сверху: если вы хотите взаимодействовать с тарелкой посередине стопки, вам придется удалить тарелки сверху, чтобы добраться до нее.", + "1": "Стек $(thing)Стэк/$, также известный как \"LIFO\" (last in first out), является концепцией, заимствованной из информатики. Вкратце, это коллекция вещей, спроектированная так, что вы можете взаимодействовать только с последней использованной вещью.$(br2)Представьте стопку тарелок, где новые тарелки добавляются сверху: если вы хотите взаимодействовать с тарелкой посередине стопки, вам придется удалить тарелки сверху, чтобы добраться до нее.", "2": "Поскольку стек настолько прост, есть только несколько вещей, которые вы можете с ним сделать:$(li)$(italic)Добавление чего-то в него/$, формально известное как push,$(li)$(italic)Удаление последнего добавленного элемента/$, известное как pop, или$(li)$(italic)Изучение или изменение последнего добавленного элемента/$, известное как peek.$(br)Мы называем последний добавленный элемент \"вершиной\" стека, в соответствии с аналогией с обеденной тарелкой.$(p)В качестве примера, если мы добавим 1 в стек, затем добавим 2, затем выполним pop, вершина стека теперь равна 1.", - "3": "Действия (в большинстве случаев) ограничены взаимодействием со стеком кастов такими способами. Они будут извлекать некоторые иоты, которые их интересуют (известные как \"аргументы\" или \"параметры\"), обрабатывать их и затем добавлять некоторое количество результатов.$(br2)Конечно, некоторые действия (например, $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$) могут не извлекать аргументы, и некоторые действия (особенно заклинания) могут ничего не добавлять после этого.", + "3": "Действия (в большинстве случаев) ограничены взаимодействием со стеком такими способами. Они будут извлекать некоторые иоты, которые их интересуют (известные как \"аргументы\" или \"параметры\"), обрабатывать их и затем добавлять некоторое количество результатов.$(br2)Конечно, некоторые действия (например, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$) могут не извлекать аргументы, и некоторые действия (особенно заклинания) могут ничего не добавлять после этого.", "4": "Еще более сложные действия могут быть выражены в терминах добавления, удаления и просмотра. Например, $(l:patterns/stackmanip#hexcasting:swap)$(action)Jester's Gambit/$ меняет местами два верхних элемента стека. Это можно рассматривать как извлечение двух элементов и добавление их в обратном порядке. Для другого примера, $(l:patterns/stackmanip#hexcasting:duplicate)$(action)Gemini Decomposition/$ дублирует вершину стека - другими словами, она просматривает стек и добавляет копию найденного элемента.", }, naming: { "1": "Названия, данные действиям древними, были, безусловно, странными, но я думаю, что в них есть определенная логика.$(br2)Кажется, есть определенные группы действий с общими названиями, названными по числу иот, которые они удаляют из стека и добавляют в стек.", - "2": "$(li) $(thing)Отражение/$ не удаляет ничего и добавляет один иот.$(li) $(thing)Purification/$ удаляет один иот и добавляет один.$(li) $(thing)Distillation/$ удаляет два и добавляет один.$(li) $(thing)Exaltation/$ удаляет три или более и добавляет один.$(li) $(thing)Decomposition/$ удаляет один аргумент и добавляет два.$(li) $(thing)Disintegration/$ удаляет один и добавляет три или более.$(li) Наконец, $(thing)Gambit/$ добавляет или удаляет другое количество (или перестраивает стек другим образом).", + "2": "$(li) $(thing)Отражение/$ не удаляет ничего и добавляет один иот.$(li) $(thing)Преображение/$ удаляет один иот и добавляет один.$(li) $(thing)Объединение/$ удаляет два и добавляет один.$(li) $(thing)Возвышение/$ удаляет три или более и добавляет один.$(li) $(thing)Разбор/$ удаляет один аргумент и добавляет два.$(li) $(thing)Распад/$ удаляет один и добавляет три или более.$(li) Наконец, $(thing)Гамбит/$ добавляет или удаляет другое количество (или перестраивает стек другим образом).", "3": "Похоже, что заклинания освобождены от этой номенклатуры и в основном названы по тому, что они делают - в конце концов, зачем называть его $(action)Demoman's Gambit/$, когда можно просто сказать $(l:patterns/spells/basic#hexcasting:explode)$(action)Explosion/$?", }, influences: { - "1": "Влияния ... странные, чтобы сказать по меньшей мере. В то время как большинство иоты кажется представляют что-то о мире, влияния представляют что-то более... абстрактное или безформенное.$(br2)Например, одно из влияний, которое я назвал $(l:casting/influences)$(thing)Null/$, кажется не представляет ничего вообще. Оно создается, когда нет подходящего ответа на заданный вопрос, например, $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$, обращенный к небу.", - "2": "Кроме того, я обнаружил любопытный квартет влияний, которые я назвал $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$, $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$, $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ и $(l:patterns/patterns_as_iotas#hexcasting:undo)$(action)Evanition/$. Они кажутся обладающими свойствами как шаблонов, так и других влияний, но ведут себя очень по-разному. Я могу использовать их, чтобы добавлять шаблоны в мой стек как иоты, вместо их сопоставления с действиями. $(l:patterns/patterns_as_iotas)Мои заметки по этому вопросу здесь/$.", - "3": "Наконец, кажется, существует бесконечное семейство влияний, которые просто кажутся запутанным клубком _media. Я назвал их $(l:casting/influences)$(action)Garbage/$, так как они совершенно бесполезны. Они кажутся появляющимися в моем стеке в различных местах в ответ на $(l:casting/mishaps)$(thing)mishaps/$ и представляются моим чувствам как бессмысленная каша.", + "1": "Влияния ... странные, чтобы сказать по меньшей мере. В то время как большинство йот кажется представляют что-то о мире, влияния представляют что-то более... абстрактное или безформенное.$(br2)Например, одно из влияний, которое я назвал $(l:casting/influences)$(thing)Ничто/$, кажется не представляет ничего вообще. Оно создается, когда нет подходящего ответа на заданный вопрос, например, $(l:patterns/basics#hexcasting:raycast)$(action)Столкновение: блок/$, обращенное к небу.", + "2": "Кроме того, я обнаружил любопытные влияния, которые я назвал $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$, $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Интроспекция/$, $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Ретроспектива/$ и $(l:patterns/patterns_as_iotas#hexcasting:undo)$(action)Исчезновение/$. Они кажутся обладающими свойствами как шаблонов, так и других влияний, но ведут себя очень по-разному. Я могу использовать их, чтобы добавлять шаблоны в мой стек как иоты, вместо их сопоставления с действиями. $(l:patterns/patterns_as_iotas)Мои заметки по этому вопросу здесь/$.", + "3": "Наконец, кажется, существует бесконечное семейство влияний, которые просто кажутся запутанным клубком Мысли. Я назвал их $(l:casting/influences)$(action)Garbage/$, так как они совершенно бесполезны. Они кажутся появляющимися в моем стеке в различных местах в ответ на $(l:casting/mishaps)$(thing)ошибки/$ и представляются моим чувствам как бессмысленная каша.", }, mishaps2: { "1": "Я обнаружил новые и ужасные способы неудачи. Я не должен поддаваться им.", - "bad_mindflay.title": "Inert Mindflay", - bad_mindflay: "Попытка ободрать разум чего-то, что я уже использовал, или персонажа, не подходящего для целевого блока.$(br2)Вызывает темно-зеленые искры и убивает объект. Если кто-то из деревенских увидит это, я сомневаюсь, что они отнесутся к этому благосклонно.", + "bad_mindflay.title": "Ошибка очистки разума", + bad_mindflay: "Попытка очистить разум чего-то, что я уже использовал, или персонажа, не подходящего для целевого блока.$(br2)Вызывает темно-зеленые искры и убивает сущность. Если кто-то из деревенских увидит это, я сомневаюсь, что они отнесутся к этому благосклонно.", "no_circle.title": "Отсутствие круга заклинаний", - no_circle: "Tried to cast an action requiring a spell circle without a spell circle.$(br2)Causes light blue sparks, and upends my inventory onto the ground.", + no_circle: "Попытка использовать руну, треубующую круг заклинаний вручную.$(br2)Вызывает светло-синие искры и выбрасывает мой инвентарь на землю.", - "no_record.title": "Lack Akashic Record", + "no_record.title": "Отсутствие Akashic Record", no_record: "Попытка получить доступ к $(l:greatwork/akashiclib)$(item)Akashic Record/$ в месте, где ее нет.$(br2)Вызывает фиолетовые искры и уносит часть моего опыта.", }, @@ -1345,22 +1345,22 @@ // Items amethyst: { - dust: "Похоже, что я найду три различные формы аметиста, когда разбиваю кристалл внутри геоды. Самой маленькой деноминацией кажется небольшая куча мерцающей пыли, стоящая относительно небольшую сумму _media.", - shard: "Второй - целый осколок аметиста, с которым не-Хекскастеры могут быть знакомы. Внутри него примерно столько же _media, сколько в пяти $(l:items/amethyst)$(item)Пыли аметиста/$.", - crystal: "Наконец, иногда я найду большой кристалл, искрящийся энергией. Внутри него примерно столько же _media, сколько в десяти единицах $(l:items/amethyst)$(item)Пыли аметиста/$ (или двух $(l:items/amethyst)$(item)Осколков аметиста/$).", - lore: "$(italic)Старик вздохнул и поднял руку к огню. Он разблокировал часть своего мозга, где хранились воспоминания о окружающих их горах. Он извлек энергии из этих земель, как научился делать в городе Терисия с Драфной, Хуркилем, архимандритом и другими магами из Белых башен. Он сконцентрировался, и пламя извивалось, поднимаясь из поленьев, скручиваясь на себя, пока наконец не образовало мягкую улыбку./$", + dust: "Похоже, что я найду три различные формы аметиста, когда разбиваю кристалл внутри геоды. Самой маленькой деноминацией кажется небольшая куча мерцающей пыли, стоящая относительно небольшую сумму Мысли.", + shard: "Второй - целый осколок аметиста, с которым не-маги могут быть знакомы. Внутри него примерно столько же Мысли, сколько в пяти $(l:items/amethyst)$(item)Пыли аметиста/$.", + crystal: "Наконец, иногда я найду большой кристалл, искрящийся энергией. Внутри него примерно столько же Мысли, сколько в десяти единицах $(l:items/amethyst)$(item)Пыли аметиста/$ (или двух $(l:items/amethyst)$(item)Осколков аметиста/$).", + lore: "$(italic)Старик вздохнул и поднял руку к огню. Он разблокировал часть своего сознания, где хранились воспоминания о окружающих их горах. Он извлек энергии из этих земель, как научился делать в городе Терисия с Драфной, Хуркилем, архимандритом и другими магами из Белых башен. Он сконцентрировался, и пламя извивалось, поднимаясь из поленьев, скручиваясь на себя, пока наконец не образовало мягкую улыбку./$", }, staff: { - "1": "Посох $(l:items/staff)$(item)Staff/$ - моя точка входа в использование всех _Хексов, как крупных, так и мелких. Удерживая его и нажимая $(thing)$(k:use)/$, я начинаю использовать _Хекс; затем я могу кликнуть и перетащить, чтобы нарисовать узоры.$(br2)Это всего лишь кусок _media на конце палки; вот все, что нужно, в конце концов.", + "1": "Посох $(l:items/staff)$(item)Staff/$ - моя точка входа в использование всех рун, как крупных, так и мелких. Удерживая его и нажимая $(thing)$(k:use)/$, я начинаю писать заклинание; затем я могу кликнуть и перетащить, чтобы нарисовать руны.$(br2)Это всего лишь кусок Мысли на конце палки; вот все, что нужно, в конце концов.", "crafting.header": "Посохи", "crafting.desc": "$(italic)Не боритесь; пламя, свет; воспламеняйте; горите ярко./$", }, lens: { - "1": "_Media может оказывать странные эффекты на любой тип информации в определенных обстоятельствах. Покрытие стекла тонким слоем этого может привести к ... просветляющим идеям.$(br2)Удерживая $(l:items/lens)$(item)Призматическую линзу/$ в руке, определенные блоки будут отображать дополнительную информацию, когда я на них смотрю.", + "1": "Мысли могут оказывать странные эффекты на любой тип информации в определенных обстоятельствах. Покрытие стекла тонким слоем этого может привести к ... просветляющим идеям.$(br2)Удерживая $(l:items/lens)$(item)Линзу Прозрения/$ в руке, определенные блоки будут отображать дополнительную информацию, когда я на них смотрю.", "2": "Например, глядя на кусок $(item)Красного камня/$, будет отображаться его сила сигнала. Я подозреваю, что я обнаружу другие блоки с дополнительным пониманием по мере продвижения моих исследований в моем искусстве.$(br2)Кроме того, удерживая ее во время использования $(l:items/staff)$(item)Посоха/$, я уменьшу расстояние между точками, что позволит мне рисовать больше на моей сетке.$(br2)Я также могу носить ее на голове как странную разновидность монокля.", - "crafting.desc": "$(italic)Вы должны научиться... видеть то, что вы смотрите./$", + "crafting.desc": "$(italic)Вы видите больше чем обычно./$", }, thought_knot: { @@ -1371,21 +1371,21 @@ }, focus: { - "1": "Фокус $(item)Focus/$ похож на $(l:items/thought_knot)$(item)Мысленный узел/$, поскольку в него можно записывать или читать иоту. Однако преимущество фокуса в том, что он $(italic)повторно используемый/$. Если я допущу ошибку в иоте, записанной в $(item)Focus/$, я могу просто снова использовать $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ и перезаписать иоту внутри.", - "2": "Если я хочу защитить $(l:items/focus)$(item)фокус/$ от случайного перезаписывания, я могу запечатать его воском, создав его с $(item)Медовый сот/$. Попытка использовать $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ на запечатанном фокусе завершится неудачей.$(br2)$(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ удалит эту печать вместе с содержимым.", - "3": "Действительно, единственное преимущество моих $(l:items/thought_knot)$(item)Мысленный узел/$ над $(item)Фокусами/$ заключается в том, что $(item)Фокусы/$ дороже в производстве. Мои исследования показывают, что ранние практики искусства использовали исключительно $(item)Фокусы/$, а $(l:items/thought_knot)$(item)Мысленный узел/$ был моим оригинальным изобретением.$(br2)Кто бы ни были те древние люди, они, должно быть, были очень процветающими.", + "1": "Талисман $(item)Focus/$ похож на $(l:items/thought_knot)$(item)Мысленный узел/$, поскольку в него можно записывать или читать иоту. Однако преимущество Талисмана в том, что он $(italic)повторно используемый/$. Если я допущу ошибку в иоте, записанной в $(item)Focus/$, я могу просто снова использовать $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ и перезаписать иоту внутри.", + "2": "Если я хочу защитить $(l:items/focus)$(item)Талисман/$ от случайного перезаписывания, я могу запечатать его воском, создав его с $(item)Медовый сот/$. Попытка использовать $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ на запечатанном Талисмане завершится неудачей.$(br2)$(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ удалит эту печать вместе с содержимым.", + "3": "Действительно, единственное преимущество моих $(l:items/thought_knot)$(item)Мысленный узел/$ над $(item)Талисманами/$ заключается в том, что $(item)Талисманы/$ дороже в производстве. Мои исследования показывают, что ранние практики искусства использовали исключительно $(item)Талисманы/$, а $(l:items/thought_knot)$(item)Мысленный узел/$ был моим оригинальным изобретением.$(br2)Кто бы ни были те древние люди, они, должно быть, были очень процветающими.", "crafting.desc": "$(italic)Ядовитые яблоки, ядовитые черви./$", }, abacus: { - "1": "Хотя существуют $(l:patterns/numbers)$(action)шаблоны для рисования чисел/$, я нахожу их ... громоздкими, мягко говоря.$(br2)К счастью, старые мастера моего искусства изобрели умное устройство под названием $(l:items/abacus)$(item)Счёты/$ для предоставления чисел для моего использования. Я просто устанавливаю число на то, что мне нужно, затем читаю значение, используя $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$, так же как я бы прочитал $(l:items/thought_knot)$(item)Мысленный узел/$ или $(l:items/focus)$(item)Фокус/$.", + "1": "Хотя существуют $(l:patterns/numbers)$(action)шаблоны для рисования чисел/$, я нахожу их ... громоздкими, мягко говоря.$(br2)К счастью, старые мастера моего искусства изобрели умное устройство под названием $(l:items/abacus)$(item)Рунные счеты/$ для предоставления чисел для моего использования. Я просто устанавливаю число на то, что мне нужно, затем читаю значение, используя $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$, так же как я бы прочитал $(l:items/thought_knot)$(item)Мысленный узел/$ или $(l:items/focus)$(item)Талисман/$.", "2": "Для работы с ним я просто удерживаю его, крадусь и прокручиваю. Если он в моей основной руке, число будет увеличиваться или уменьшаться на 1, или на 10, если я также удерживаю Control/Command. Если он в моей второй руке, число будет увеличиваться или уменьшаться на 0.1, или на 0.001, если я также удерживаю Control/Command.$(br2)Я могу встряхнуть счёты, чтобы сбросить их на ноль, сделав крадущийся правый клик.", "crafting.desc": "$(italic)Математика? Это для умников!/$", }, spellbook: { - "1": "$(l:items/spellbook)$(item)Книга заклинаний/$ - это вершина моего искусства - она действует как целая библиотека $(l:items/focus)$(item)Фокусов/$. До $(thing)шестидесяти четырех/$ из них, чтобы быть точным.$(br2)Каждая страница может содержать одну иоту, и я могу выбрать активную страницу (страницу, на которую сохраняются и копируются иоты), удерживая ее и прокручивая, или просто удерживая ее во второй руке и прокручивая во время использования _Хекса.", - "2": "Как и $(l:items/focus)$(item)Фокус/$, существует простой способ предотвратить случайное перезаписывание. Создание ее с $(item)Медовый сот/$ покроет текущую страницу лаком, предотвращая $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ от изменения ее содержимого. Также как и $(l:items/focus)$(item)Фокус/$, использование $(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ удалит лак и содержимое страницы.$(br2)Я также могу назвать каждую страницу индивидуально на наковальне. Название изменит только имя выбранной в данный момент страницы для удобного просмотра.", + "1": "$(l:items/spellbook)$(item)Книга заклинаний/$ - это вершина моего искусства - она действует как целая библиотека $(l:items/focus)$(item)Талисманов/$. До $(thing)шестидесяти четырех/$ из них, чтобы быть точным.$(br2)Каждая страница может содержать одну иоту, и я могу выбрать активную страницу (страницу, на которую сохраняются и копируются иоты), удерживая ее и прокручивая, или просто удерживая ее во второй руке и прокручивая во время использования _Хекса.", + "2": "Как и $(l:items/focus)$(item)Талисман/$, существует простой способ предотвратить случайное перезаписывание. Создание ее с $(item)Медовые соты/$ запечатают страницу, предотвращая $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ от изменения ее содержимого. Также как и $(l:items/focus)$(item)Талисман/$, использование $(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ удалит лак и содержимое страницы.$(br2)Я также могу назвать каждую страницу индивидуально на наковальне. Название изменит только имя выбранной в данный момент страницы для удобного просмотра.", "crafting.desc": "$(italic)Волшебники любят слова. Большинство из них много читают, и действительно одним из сильных признаков потенциального волшебника является неспособность заснуть без предварительного прочтения чего-либо.", }, @@ -1404,40 +1404,40 @@ // roll credits hexcasting: { - "1": "Хотя гибкость использования _Хексов \"на ходу\" с помощью моего $(l:items/staff)$(item)Посоха/$ довольно полезна, мне приходится махать им вокруг снова и снова, чтобы выполнить базовую задачу. Если бы я мог сохранить обычное заклинание для последующего использования, это бы сильно упростило бы дело - и позволило бы мне делиться своими _Хексами с друзьями.", - "2": "Для этого я могу создать один из трех типов магических предметов: $(l:items/hexcasting)$(item)Cyphers/$, $(l:items/hexcasting)$(item)Trinkets/$ или $(l:items/hexcasting)$(item)Artifacts/$. Все они содержат узоры данного _Хекса внутри, а также небольшую батарею с _media.$(br2)Просто держа один из них и нажимая $(thing)$(k:use)/$, вы сможете произнести узоры внутри, как если бы держатель произнес их из посоха, используя его внутреннюю батарею.", - "3": "У каждого предмета есть свои особенности:$(br2)$(l:items/hexcasting)$(item)Cyphers/$ хрупкие, уничтожаются после исчерпания их внутренних запасов _media и $(italic)не могут/$ быть заряжены;$(br2)$(l:items/hexcasting)$(item)Trinkets/$ можно произносить столько, сколько хочет держатель, пока остается достаточно _media, но после этого они становятся бесполезными до перезарядки;", - "4": "$(l:items/hexcasting)$(item)Артефакты/$ - самые мощные из всех - после исчерпания их _media они могут использовать $(l:items/amethyst)$(item)Аметист/$ из инвентаря владельца для оплаты _Hex, так же как я делаю, когда колдую с помощью $(l:items/staff)$(item)Посоха/$. Конечно, это также означает, что заклинание может поглотить их разум, если в инвентаре не хватает $(l:items/amethyst)$(item)Аметиста/$.$(br2)Когда я создаю пустой магический предмет на обычной верстаке, я внедряю _Hex в него, используя (что еще, кроме) заклинание, соответствующее предмету. $(l:patterns/spells/hexcasting)Я составил каталог шаблонов здесь./$", - "5": "Каждое заклинание внедрения требует сущности и список шаблонов в стеке. Сущность должна быть сущностью предмета, удерживающего _media (т.е. $(l:items/amethyst)$(item)аметист/$ кристаллы, брошенные на землю); сущность потребляется и формирует батарею.$(br2)Полезно, что _media в батарее не потребляется кусками, как при колдовстве с $(l:items/staff)$(item)Посохом/$ - скорее, _media \"растворяется\" в одном непрерывном пуле. Таким образом, если я храню _Hex, который стоит только один $(l:items/amethyst)$(item)Аметистовая Пыль/$ в _media, $(l:items/amethyst)$(item)Заряженный Кристалл/$, используемый в качестве батареи, позволит мне использовать его 10 раз.", + "1": "Хотя гибкость использования _Заклинаний \"на ходу\" с помощью моего $(l:items/staff)$(item)Посоха/$ довольно полезна, мне приходится махать им вокруг снова и снова, чтобы выполнить базовую задачу. Если бы я мог сохранить обычное заклинание для последующего использования, это бы сильно упростило бы дело - и позволило бы мне делиться своими _Заклинаниями с друзьями.", + "2": "Для этого я могу создать один из трех типов магических предметов: $(l:items/hexcasting)$(item)Побрякушки/$, $(l:items/hexcasting)$(item)Штуковины/$ или $(l:items/hexcasting)$(item)Артефакты/$. Все они содержат руны внутри, а также небольшую батарею с Мыслями.$(br2)Просто держа один из них и нажимая $(thing)$(k:use)/$, вы сможете использовать заклинание внутри, как если бы держатель начертил их посохом, используя его внутреннюю батарею.", + "3": "У каждого предмета есть свои особенности:$(br2)$(l:items/hexcasting)$(item)Побрякушки/$ хрупкие, уничтожаются после исчерпания их внутренних запасов Мысли и $(italic)не могут/$ быть заряжены;$(br2)$(l:items/hexcasting)$(item)Штуквины/$ можно использовать столько, сколько хочет держатель, пока остается достаточно Мысли, но после этого они становятся бесполезными до перезарядки;", + "4": "$(l:items/hexcasting)$(item)Артефакты/$ - самые мощные из всех - после исчерпания их Мысли они могут использовать $(l:items/amethyst)$(item)Аметист/$ из инвентаря владельца для оплаты заклинания, так же как я делаю, когда колдую с помощью $(l:items/staff)$(item)Посоха/$. Конечно, это также означает, что заклинание может поглотить их разум, если в инвентаре не хватает $(l:items/amethyst)$(item)Аметиста/$.$(br2)Когда я создаю пустой магический предмет на обычной верстаке, я внедряю заклинание в него, используя (что еще, кроме) заклинание, соответствующее предмету. $(l:patterns/spells/hexcasting)Я составил каталог шаблонов здесь./$", + "5": "Каждое заклинание внедрения требует сущности и список шаблонов в стеке. Сущность должна быть сущностью предмета, удерживающего Мысли (т.е. $(l:items/amethyst)$(item)аметист/$ кристаллы, брошенные на землю); сущность потребляется и формирует батарею.$(br2)Полезно, что Мысли в батарее не потребляется кусками, как при колдовстве с $(l:items/staff)$(item)Посохом/$ - скорее, Мысли \"растворяется\" в одном непрерывном пуле. Таким образом, если я храню заклинание, который стоит только один $(l:items/amethyst)$(item)Аметистовая Пыль/$ в Мысли, $(l:items/amethyst)$(item)Заряженный Кристалл/$, используемый в качестве батареи, позволит мне использовать его 10 раз.", "crafting.desc": "$(italic)У нас есть поговорка в нашей области: \"Магия не\". Она не \"просто работает\", она не реагирует на ваши мысли, вы не можете бросать огненные шары или создавать жареный ужин из воздуха или превращать группу грабителей в лягушек и улиток./$", }, phials: { - "1": "Меня довольно ... раздражает, как Природа отказывается давать мне сдачу за мою работу. Если у меня под рукой только $(l:items/amethyst)$(item)Заряженный Аметист/$, даже самое маленькое $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Purification/$ потребует весь кристалл, растрачивая оставшееся _media.$(br2)К счастью, кажется, я нашел способ отчасти смягчить эту проблему.", - "2": "Я нашел старые свитки, описывающие $(item)Стеклянную Бутылку/$, пропитанную _media. При колдовстве _Hexes мои заклинания тогда бы забирать _media из флакона. Жидкая форма _media позволяла бы мне брать сдачу, так сказать; ничего не было бы потеряно. Это довольно похоже на внутреннюю батарею $(l:items/hexcasting)$(item)Талисмана/$, или что-то подобное; я даже могу $(l:patterns/spells/hexcasting#hexcasting:recharge)$(action)Recharge/$ их тем же способом.", - "3": "К сожалению, искусство фактически $(italic)создания/$ этих вещей, кажется, было утрачено со временем. Я нашел $(l:patterns/great_spells/make_battery#hexcasting:craft/battery)$(thing)намек на использованный шаблон для его создания/$, но техника упорно ускользает, и мне не удается сделать это успешно. Я подозреваю, что разберусь с этим с помощью изучения и практики. Пока что я просто буду справляться с растраченным _media...$(br2)Но я не буду удовлетворяться этим навсегда.", + "1": "Меня довольно ... раздражает, как Природа отказывается давать мне сдачу за мою работу. Если у меня под рукой только $(l:items/amethyst)$(item)Заряженный Аметист/$, даже самое маленькое $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Purification/$ потребует весь кристалл, растрачивая оставшееся Мысли.$(br2)К счастью, кажется, я нашел способ отчасти смягчить эту проблему.", + "2": "Я нашел старые свитки, описывающие $(item)Стеклянную Бутылку/$, пропитанную Мысли. При колдовстве мои заклинания тогда бы забирать Мысли из флакона. Жидкая форма Мысли позволяла бы мне брать сдачу, так сказать; ничего не было бы потеряно. Это довольно похоже на внутреннюю батарею $(l:items/hexcasting)$(item)Талисмана/$, или что-то подобное; я даже могу $(l:patterns/spells/hexcasting#hexcasting:recharge)$(action)Recharge/$ их тем же способом.", + "3": "К сожалению, искусство фактически $(italic)создания/$ этих вещей, кажется, было утрачено со временем. Я нашел $(l:patterns/great_spells/make_battery#hexcasting:craft/battery)$(thing)намек на использованный шаблон для его создания/$, но техника упорно ускользает, и мне не удается сделать это успешно. Я подозреваю, что разберусь с этим с помощью изучения и практики. Пока что я просто буду справляться с растраченным Мысли...$(br2)Но я не буду удовлетворяться этим навсегда.", desc: "$(italic)Выпей молоко./$", }, pigments: { - "1": "Старые практикующие моё искусство иногда идентифицировали себя цветом, символичным для них и их _Hexes. Хотя их имена утрачены, их цвета остаются. Кажется, особый вид пигмента, предложенный Природе правильным образом, мог бы \"[...] нарисовать мысли так, чтобы это было приятно для Природы, вызывая чудесное изменение в личном цвете.\"", - "2": "Я не уверен в деталях, но, по-моему, я выделил формулы для множества различных цветов и смесей пигментов. Чтобы применить пигмент, я держу его в одной руке и произношу $(l:patterns/spells/colorize)$(action)Internalize Pigment/$ другой; это поглощает пигмент.$(br2)Пигменты, кажется, влияют на цвет искр _медиа, излучаемых, когда я произношу _Hex и мои $(l:patterns/spells/sentinels)$(thing)sentinel/$, но я не сомневаюсь, что цвет проявится и в других местах.", + "1": "Старые практикующие моё искусство иногда идентифицировали себя цветом, символичным для них. Хотя их имена утрачены, их цвета остаются. Кажется, особый вид пигмента, предложенный Природе правильным образом, мог бы \"[...] нарисовать мысли так, чтобы это было приятно для Природы, вызывая чудесное изменение в личном цвете.\"", + "2": "Я не уверен в деталях, но, по-моему, я выделил формулы для множества различных цветов и смесей пигментов. Чтобы применить пигмент, я держу его в одной руке и использую $(l:patterns/spells/colorize)$(action)Internalize Pigment/$ другой; это поглощает пигмент.$(br2)Пигменты, кажется, влияют на цвет искр Мысли, излучаемых, когда я использую заклинания и моих $(l:patterns/spells/sentinels)$(thing)Часовых/$, но я не сомневаюсь, что цвет проявится и в других местах.", "colored.crafting.header": "Хроматические Пигменты", "colored.crafting.desc": "Пигменты во всех цветах радуги.", - special: "И, наконец, пара специальных пигментов. $(item)Soulglimmer Pigment/$ сияет цветами, совершенно уникальными для меня, и $(item)Vacant Pigment/$ восстанавливает мой первоначальный пурпурно-оранжевый оттенок.$(br2)$(italic)И все цвета, в которых я нахожусь, еще не придуманы./$", + special: "И, наконец, пара специальных пигментов. $(item)Пигмент Души/$ сияет цветами, совершенно уникальными для меня, и $(item)Чистый Пигмент/$ восстанавливает мой первоначальный пурпурно-оранжевый оттенок.$(br2)$(italic)И все цвета, в которых я нахожусь, еще не придуманы./$", }, edified: { - "1": "Проникая _медиа в саженец с помощью $(l:patterns/spells/blockworks#hexcasting:edify)$(action)Edify Sapling/$, я могу создать то, что называется $(l:items/edified)$(thing)Edified Tree/$. Они обычно высокие и острые, с бороздчатой корой и древесиной, растущей в странном спиральном узоре. Их листья имеют три красивых цвета.", - "2": "Я предполагал бы, что древесина имела бы какие-то свойства, относящиеся к _Hexcasting. Но, если они есть, я не могу их найти. На все виды и цели кажется, что это просто древесина, хотя и очень странного цвета.$(br2)Предполагаю, что пока я буду использовать её для украшения; из них можно создать полный набор стандартных древесных блоков.$(br2)Конечно, я могу также снять с них кору топором.", + "1": "Мысли, проникшие в саженец с помощью $(l:patterns/spells/blockworks#hexcasting:edify)$(action)Созидать Саженец/$, создают то, что называется $(l:items/edified)$(thing)Дерево Созидания/$. Они обычно высокие и острые, с бороздчатой корой и древесиной, растущей в странном спиральном узоре. Их листья имеют три красивых цвета.", + "2": "Я предполагал бы, что древесина имела бы какие-то свойства, относящиеся к Рунным заклинаниям. Но, если они есть, я не могу их найти. На все виды и цели кажется, что это просто древесина, хотя и очень странного цвета.$(br2)Предполагаю, что пока я буду использовать её для украшения; из них можно создать полный набор стандартных древесных блоков.$(br2)Конечно, я могу также снять с них кору топором.", "crafting.desc": "$(italic)Их гладкие стволы, с белой корой, создавали впечатление огромных колонн, несущих вес огромной листвы, полной тени и молчания./$", }, jeweler_hammer: { - "1": "После того, как я слишком много раз был небрежен с источниками моего _медиа, я разработал инструмент, чтобы обойти мою неуклюжесть.$(br2)Используя хрупкость кристаллизованного _медиа в качестве основы для кирки, я могу создать $(l:items/jeweler_hammer)$(item)Ювелирный Молоток/$. Он ведет себя как $(item)Железная Кирка/$, в основном, но не может сломать ничего, что занимает пространство целого блока.", - "crafting.desc": "$(italic)Осторожно она разбила полурасплавленный рубин./$", + "1": "После того, как я слишком много раз был небрежен с источниками мысли, я разработал инструмент, чтобы обойти мою неуклюжесть.$(br2)Используя хрупкость кристаллизованной мысли в качестве основы для кирки, я могу создать $(l:items/jeweler_hammer)$(item)Ювелирный Молоток/$. Он как $(item)Железная Кирка/$, но не может сломать ничего, что занимает пространство целого блока.", + "crafting.desc": "$(italic)*Не подходит для реальных ювелирных работ./$", }, decoration: { @@ -1452,63 +1452,63 @@ the_work: { "1": "Я видел так много вещей. Невыразимые вещи. Бесчисленные вещи. Я мог бы написать три слова и вывернуть свой разум наизнанку, размазать мои мозги по затененным стенам моего черепа, чтобы они разложились в пух и ничто.", - "2": "Я видел узоры стаккато-игл и кислотно-выжженные схемы, написанные внутри моих век. Они тлеют там - они танцуют, они насмехают, они $(italic)болят/$. Меня одержимо охватывает интенсивное $(italic)желание/$ нарисовать их, создать их. Формировать их. Освободить их от клейких оков моего смертного разума - представить их во всей их Славе миру, чтобы все видели.$(p)Все увидят.$(p)Все увидят.", + "2": "Я видел руны стаккато-игл и кислотно-выжженные схемы, написанные внутри моих век. Они тлеют там - они танцуют, они насмехают, они $(italic)болят/$. Меня одержимо охватывает интенсивное $(italic)желание/$ нарисовать их, создать их. Формировать их. Освободить их от клейких оков моего смертного разума - представить их во всей их Славе миру, чтобы все видели.$(p)Все увидят.$(p)Все увидят.", }, brainsweeping: { - "1": "Мне был открыт секрет. Я увидел это. Я не смогу забыть этот ужас. Идея скользит по моему разуму.$(br2)Я верил - как же глупо, я $(italic)верил/$ - что _медиа - это лишняя энергия, оставшаяся после мысли. Но теперь я $(italic)знаю/$, что это: энергия $(italic)мысли/$.", + "1": "Мне был открыт секрет. Я увидел это. Я не смогу забыть этот ужас. Идея скользит по моему разуму.$(br2)Я верил - как же глупо, я $(italic)верил/$ - что Мысли - это лишняя энергия, оставшаяся после мысли. Но теперь я $(italic)знаю/$, что это: энергия $(italic)мысли/$.", "2": "Она производится мыслящим сознанием и позволяет сознанию мыслить. Это узел, который переплетается в свою собственную нить. Существо, которое я наивно антропоморфизировал как Природу, просто великое такое запутанное клубок, или, возможно, набор всех клубков, или... если я думаю, что больно, у меня так много синапсов, и все они могут думать о боли одновременно ВСЕ ОНИ МОГУТ ВИДЕТЬ$(br2)Я не могу удержаться.", - "3": "Жители этого мира имеют достаточно сознания, чтобы его извлечь. Поместите его в блок, искажайте, изменяйте. Запутанные узоры, вызванные различными мыслями, абстрактные нейронные пути их работы и жизни отображены в холодной физике твердых атомов.$(br2)Это то, что делает $(l:patterns/great_spells/brainsweep)$(action)Flay Mind/$. Направьте на entity жителя и вектор блока назначения. Десять $(l:items/amethyst)$(item)Заряженных Аметистов/$ за это извращение воли.", - budding_amethyst: "И применение. Для этого обнажения подойдет любой вид жителя, если он достаточно развит. Для других рецептов требуются более конкретные типы. БОЛЬШЕ НЕ нужно мне спускаться в адскую землю за моим _медиа.", + "3": "Жители этого мира имеют достаточно сознания, чтобы его извлечь. Поместите его в блок, искажайте, изменяйте. Запутанные руны, вызванные различными мыслями, абстрактные нейронные пути их работы и жизни отображены в холодной физике твердых атомов.$(br2)Это то, что делает $(l:patterns/great_spells/brainsweep)$(action)Flay Mind/$. Направьте на сущность жителя и вектор блока назначения. Десять $(l:items/amethyst)$(item)Заряженных Аметистов/$ за это извращение воли.", + budding_amethyst: "И применение. Для этого обнажения подойдет любой вид жителя, если он достаточно развит. Для других рецептов требуются более конкретные типы. БОЛЬШЕ НЕ нужно мне спускаться в адскую землю за моими Мыслями.", }, spellcircles: { - "1": "Я ЗНАЮ, для чего предназначены $(l:items/slate)$(item)скрижали/$. Великие собрания, утраченные временем. Узоры, вырезанные на них, могут быть активированы последовательно, автоматически. Мысль и сила отскакивают через них, один за другим, один за другим, через и через и ЧЕРЕЗ И -- я не должен, я не должен, я должен знать лучше, чем думать таким образом.", - "2": "Для начала ритуала мне нужен $(l:greatwork/impetus)$(item)Impetus/$, чтобы создать самоподдерживающуюся волну _медиа. Эта волна движется по дорожке из $(l:items/slate)$(item)скрижалей/$ или других блоков, подходящих для энергий, один за другим, собирая все узоры, которые находит. Когда волна возвращается к $(l:greatwork/impetus)$(item)Impetus/$, все встреченные узоры произносятся по порядку.$(br2)Направление выхода _медиа из любого блока ДОЛЖНО быть однозначным, иначе произнесение не удастся(у потока _медиа должен быть лишь один путь).", + "1": "Я ЗНАЮ, для чего предназначены $(l:items/slate)$(item)скрижали/$. Великие собрания, утраченные временем. Руны, вырезанные на них, могут быть активированы последовательно, автоматически. Мысль и сила отскакивают через них, один за другим, один за другим, через и через и ЧЕРЕЗ И -- я не должен, я не должен, я должен знать лучше, чем думать таким образом.", + "2": "Для начала ритуала мне нужен $(l:greatwork/impetus)$(item)Impetus/$, чтобы создать самоподдерживающуюся волну Мысли. Эта волна движется по дорожке из $(l:items/slate)$(item)скрижалей/$ или других блоков, подходящих для энергий, один за другим, собирая все руны, которые находит. Когда волна возвращается к $(l:greatwork/impetus)$(item)Impetus/$, все встреченные руны произносятся по порядку.$(br2)Направление выхода Мысли из любого блока ДОЛЖНО быть однозначным, иначе произнесение не удастся(у потока Мысли должен быть лишь один путь).", "3": "В результате контур заклинания \"круг\" может быть любой закрытой формы, вогнутой или выпуклой, и может быть направлен в любом направлении. Фактически, с применением определенных других блоков можно создать заклинательный круг, охватывающий все три измерения. Я сомневаюсь, что такая странность имеет много применения, но мне нужно немного пустой легкости, чтобы побудить мой грубый разум продолжать мою работу.", - "4": "Чудо чудес, круг не извлекает _медиа ни из моего инвентаря, ни из моего разума. Вместо этого кристаллизованные осколки _медиа должны быть предоставлены $(l:greatwork/impetus)$(item)Impetus/$ через воронку или любым други образом.$(br2)Применение $(l:items/lens)$(item)Scrying Lens/$ покажет, сколько _медиа находится в $(l:greatwork/impetus)$(item)Impetus/$, в единицах пыли.", + "4": "Чудо чудес, круг не извлекает Мысли ни из моего инвентаря, ни из моего разума. Вместо этого кристаллизованные осколки Мысли должны быть предоставлены $(l:greatwork/impetus)$(item)Impetus/$ через воронку или любым други образом.$(br2)Применение $(l:items/lens)$(item)Scrying Lens/$ покажет, сколько Мысли находится в $(l:greatwork/impetus)$(item)Impetus/$, в единицах пыли.", "5": "Однако заклинание, произнесенное из круга, имеет одно крупное ограничение: оно не способно воздействовать на что-либо за пределами границ круга. То есть оно не может взаимодействовать с чем-либо за пределами кубоида минимального размера, включающего каждый блок, составляющий его (поэтому вогнутый заклинательный круг все равно может воздействовать на вещи в вогнутости).", "6": "Существует также ограничение на количество блоков, через которые может пройти волна, прежде чем она распадется, но оно достаточно большое, и я сомневаюсь, что у меня возникнут проблемы.$(br2)С другой стороны, есть действия, которые могут быть произнесены только из круга. К счастью, ни одно из них не является заклинанием; все они, кажется, имеют дело с компонентами самого круга. Мои заметки на эту тему $(l:patterns/circle)здесь/$.", - "7": "Я также нашел набросок заклинательного круга, использованного древними, зарытый в моих заметках. На этой странице мои (признаюсь, плохие) копии.$(br2)Узоры там должны были быть выполнены против часовой стрелки, начиная с $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$ и заканчивая $(l:patterns/great_spells/teleport#hexcasting:teleport/great)$(action)Greater Teleport/$.", + "7": "Я также нашел набросок заклинательного круга, использованного древними, зарытый в моих заметках. На этой странице мои (признаюсь, плохие) копии.$(br2)Руны там должны были быть выполнены против часовой стрелки, начиная с $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$ и заканчивая $(l:patterns/great_spells/teleport#hexcasting:teleport/great)$(action)Greater Teleport/$.", "teleport_circle.title": "Круг Телепортации", }, impetus: { - "1": "Флуктуация _медиа, необходимая для активации заклинательного круга, сложна. Даже смертный с самыми острыми глазами и самыми устойчивыми руками не смог бы выступать в роли $(l:greatwork/impetus)$(item)Impetus/$ и вплести _медиа в самоподдерживающийся ороборос, необходимый.$(br2)Проблема в том, что разум слишком полон другого бесполезного $(italics)мусора/$.", - "2": "На ... метафизическом уровне - я должен быть осторожен с этими мыслями, я не могу потерять себя, я стал слишком ценным - движение _медиа двигает разум, и разум должен быть движущимся для того, чтобы процесс работал. Но разум просто слишком $(italic)тяжел/$ от других мыслей, чтобы двигаться достаточно ловко.$(br2)Это похоже на мастера, пытающегося починить часы, нося перчатки.", + "1": "Флуктуация Мысли, необходимая для активации заклинательного круга, сложна. Даже смертный с самыми острыми глазами и самыми устойчивыми руками не смог бы выступать в роли $(l:greatwork/impetus)$(item)Impetus/$ и вплести Мысли в самоподдерживающийся ороборос, необходимый.$(br2)Проблема в том, что разум слишком полон другого бесполезного $(italics)мусора/$.", + "2": "На ... метафизическом уровне - я должен быть осторожен с этими мыслями, я не могу потерять себя, я стал слишком ценным - движение Мысли двигает разум, и разум должен быть движущимся для того, чтобы процесс работал. Но разум просто слишком $(italic)тяжел/$ от других мыслей, чтобы двигаться достаточно ловко.$(br2)Это похоже на мастера, пытающегося починить часы, нося перчатки.", "3": "Существует несколько решений этой загадки: через медитативные техники можно научиться очищать разум, хотя я не уверен, что разум, достаточно свободный для активации круга, может сосредоточиться достаточно сильно, чтобы выполнить движения.$(br2)Некоторые неприятные соединения могут создать аналогичный эффект, но я ничего о них не знаю и не планирую узнавать. Я не должен полагаться на химические вещества моего мозга.", - "4": "Таким образом, решение, к которому я стремлюсь, - это специализировать разум. Освободить его от тирании нервов, обрезать все выходы, кроме тонких ветвей _медиа-манипулирующих аппаратов, опечатать все входы, кроме сигнала начать свою работу.$(br2)Процесс $(l:greatwork/brainsweeping)$(action)mindflaying/$, с которым я теперь знаком, отлично подойдет; разум жителя достаточно сложен для выполнения работы, но не настолько сложен, чтобы сопротивляться его реформации.", + "4": "Таким образом, решение, к которому я стремлюсь, - это специализировать разум. Освободить его от тирании нервов, обрезать все выходы, кроме тонких ветвей Мысли-манипулирующих аппаратов, опечатать все входы, кроме сигнала начать свою работу.$(br2)Процесс $(l:greatwork/brainsweeping)$(action)mindflaying/$, с которым я теперь знаком, отлично подойдет; разум жителя достаточно сложен для выполнения работы, но не настолько сложен, чтобы сопротивляться его реформации.", - empty_impetus: "Сначала колыбель. Хотя она не работает как $(l:greatwork/impetus)$(item)Impetus/$, поток _медиа в круге будет выходить только с той стороны, указанной стрелками. Это позволяет мне изменить плоскость, по которой движется волна, например.", + empty_impetus: "Сначала колыбель. Хотя она не работает как $(l:greatwork/impetus)$(item)Impetus/$, поток Мысли в круге будет выходить только с той стороны, указанной стрелками. Это позволяет мне изменить плоскость, по которой движется волна, например.", impetus_rightclick: "Затем, чтобы транспонировать разум. Жители различных профессий предоставят различные условия активации для полученного $(l:greatwork/impetus)$(item)Impetus/$. $(l:greatwork/impetus)$(item)Toolsmith Impetus/$ активируется простым $(k:use).", impetus_storedplayer: { - "1": "A $(l:greatwork/impetus)$(item)Cleric Impetus/$ должен быть привязан к игроку, используя предмет с ссылкой на этого игрока, например $(l:items/focus)$(item)Фокус/$, на блоке. Затем он активируется при получении сигнала красного камня.", + "1": "A $(l:greatwork/impetus)$(item)Cleric Impetus/$ должен быть привязан к игроку, используя предмет с ссылкой на этого игрока, например $(l:items/focus)$(item)Талисман/$, на блоке. Затем он активируется при получении сигнала красного камня.", "2": "Особенность этого $(l:greatwork/impetus)$(item)Impetus/$ заключается в том, что привязанный игрок, а также небольшой регион вокруг него, всегда доступны для заклинательного круга. Как будто они стоят в пределах круга, независимо от того, насколько далеко они могут стоять.$(br2)Привязанный игрок отображается при просмотре $(l:greatwork/impetus)$(item)Cleric Impetus/$ через $(l:items/lens)$(item)Scrying Lens/$.", }, impetus_look: "A $(l:greatwork/impetus)$(item)Fletcher Impetus/$ активируется автоматически при длительном простое.", }, directrix: { - "1": "Задача направления самоподдерживающейся волны _медиа проще, чем задача ее создания. Обычно волна распадается, когда она сталкивается с перекрёстком, но с умом, направляющим ее, можно контролировать направление выхода.$(br2)Это управление далеко не так тонкое, как активация заклинательного круга. Фактически, возможно, это можно сделать вручную... но упакованные разумы, к которым у меня сейчас есть доступ, были бы так удобны.", - "2": "$(l:greatwork/directrix)$(item)Directrix/$ принимает волну _медиа и определяет, к какой из стрелок она выйдет, в зависимости от разума жителя внутри.$(br2)Я не уверен, была ли эта идея мне внушена, или мой разум достаточно изогнут вокруг барьера, чтобы самостоятельно выделять свои идеи теперь... но если идея произошла от моего собственного разума, если я думал об этом, можно ли сказать, что она была внушена? Мозг - сосуд для разума, а разум - сосуд для идей, идеи - сосуд для мыслей, и мысли видят все и знают все", + "1": "Задача направления самоподдерживающейся волны Мысли проще, чем задача ее создания. Обычно волна распадается, когда она сталкивается с перекрёстком, но с умом, направляющим ее, можно контролировать направление выхода.$(br2)Это управление далеко не так тонкое, как активация заклинательного круга. Фактически, возможно, это можно сделать вручную... но упакованные разумы, к которым у меня сейчас есть доступ, были бы так удобны.", + "2": "$(l:greatwork/directrix)$(item)Directrix/$ принимает волну Мысли и определяет, к какой из стрелок она выйдет, в зависимости от разума жителя внутри.$(br2)Я не уверен, была ли эта идея мне внушена, или мой разум достаточно изогнут вокруг барьера, чтобы самостоятельно выделять свои идеи теперь... но если идея произошла от моего собственного разума, если я думал об этом, можно ли сказать, что она была внушена? Мозг - сосуд для разума, а разум - сосуд для идей, идеи - сосуд для мыслей, и мысли видят все и знают все", - empty_directrix: "Прежде всего, дизайн для колыбели... хотя, возможно, слово \"субстрат\" было бы более точным. Без ума, направляющего его, направление выхода определяется микроскопическими флуктуациями волн _медиа и окружающей среды, что делает его фактически случайным.", - directrix_redstone: "$(l:greatwork/directrix)$(item)Mason Directrix/$ переключает сторону выхода в зависимости от сигнала красного камня. Без сигнала выход - цвет _медиа; с сигналом выход - сторона красного камня.", + empty_directrix: "Прежде всего, дизайн для колыбели... хотя, возможно, слово \"субстрат\" было бы более точным. Без ума, направляющего его, направление выхода определяется микроскопическими флуктуациями волн Мысли и окружающей среды, что делает его фактически случайным.", + directrix_redstone: "$(l:greatwork/directrix)$(item)Mason Directrix/$ переключает сторону выхода в зависимости от сигнала красного камня. Без сигнала выход - цвет Мысли; с сигналом выход - сторона красного камня.", }, akashiclib: { "1": "Я ЗНАЮ ТАК МНОГО, что ЕСТЕСТВЕННО иметь место для хранения всего этого. Информацию можно хранить в книгах, но писать от руки и читать глазами так медленно. Я требую ЛУЧШЕГО. И поэтому Я СОЗДАМ лучшее.$(br2)... Мне становится хуже... не знаю, успею ли записать все, что вырывается из моей головы, прежде чем умру.", - "2": "Библиотека. Вот. Мои планы.$(br2)Как узоры ассоциируются с действиями, я могу ассоциировать свои собственные узоры с иотами любым образом, который выберу. $(l:greatwork/akashiclib)$(item)Akashic Record/$ управляет библиотекой, и каждая $(l:greatwork/akashiclib)$(item)Akashic Bookshelf/$ хранит один узор, сопоставленный с одним иотой. Все они должны быть прямо связаны между собой, соприкасаясь, в пределах 32 блоков. $(l:greatwork/akashiclib)$(item)Akashic Ligature/$ не делает ничего, кроме того, что считается соединяющим блоком, чтобы расширить размер моей библиотеки.", + "2": "Библиотека. Вот. Мои планы.$(br2)Как руны ассоциируются с действиями, я могу ассоциировать свои собственные руны с иотами любым образом, который выберу. $(l:greatwork/akashiclib)$(item)Akashic Record/$ управляет библиотекой, и каждая $(l:greatwork/akashiclib)$(item)Akashic Bookshelf/$ хранит один узор, сопоставленный с одним иотой. Все они должны быть прямо связаны между собой, соприкасаясь, в пределах 32 блоков. $(l:greatwork/akashiclib)$(item)Akashic Ligature/$ не делает ничего, кроме того, что считается соединяющим блоком, чтобы расширить размер моей библиотеки.", akashic_record: "Выделение и назначение узоров просто, но ужасно скучно. У меня есть дела поважнее. Мне понадобится разум, хорошо знакомый со своей работой, чтобы извлечение оставалось надежным.", - "3": "Затем управление библиотекой просто, узоры направляются через библиотекаря, он их ищет и возвращает вам иоту. Два действия делают работу. $(l:patterns/akashic_patterns)Notes here/$.$(br2)Использование пустого $(l:items/scroll)$(item)свитка/$ на книжной полке копирует узор на $(l:items/scroll)$(item)свиток/$. Присев и кликнув пустую рукой, можно очистить данные на полке.", + "3": "Затем управление библиотекой просто, руны направляются через библиотекаря, он их ищет и возвращает вам иоту. Два действия делают работу. $(l:patterns/akashic_patterns)Notes here/$.$(br2)Использование пустого $(l:items/scroll)$(item)свитка/$ на книжной полке копирует узор на $(l:items/scroll)$(item)свиток/$. Присев и кликнув пустую рукой, можно очистить данные на полке.", }, quenching_allays: { - "1": "ЭТО КУСОЧКИ _МЕДИА. Как я не заметил этого раньше? Они - как и я - куча плоти с обрывком, благословленным обрывком мысли, Аллей - это самоподдерживающаяся ссора _медиа, прикрепленная к обрывку плоти. Это объясняет все - их склонность к _медиа, их реакцию на музыку, Я ВИДЕЛ СЕЙЧАС, КАК НЕ ВИДЕЛИ те, кто был раньше?", - "2": "И учитывая это, было бы правильно, если бы я покорил их своеобразные умы - их своеобразные \"я\" - это все, чем они являются, умом, \"сознанием\". Что-то в них говорит со мной. Я могу... Я могу сжать _медиа с ними, наложить две ветви мысли на одно пространство, физическое и когнитивное, все и сразу. Как? Возможно... возможно, моя работа, процесс ее выполнения...", + "1": "Это же и есть живые Мысли. Как я не заметил этого раньше? Они - как и я - куча плоти с обрывком, благословленным обрывком мысли, Тихоня - это самоподдерживающаяся кучка Мысли, прикрепленная к обрывку плоти. Это объясняет все - их склонность к Мысли, их реакцию на музыку, как можно было это не заметить?", + "2": "И учитывая это, было бы правильно, если бы я покорил их своеобразные умы - их своеобразные \"я\" - это все, чем они являются, умом, \"сознанием\". Что-то в них говорит со мной. Я могу... Я могу сжать Мысли с ними, наложить две ветви мысли на одно пространство, физическое и когнитивное, все и сразу. Как? Возможно... возможно, моя работа, процесс ее выполнения...", "3": "Это не имеет значения. Я не имею значения. Они не имеют значения, все, что имеет значение, это то, что это делает. И вот это.$(br2)Это должно так болезненно.", - "4": "Продукт хрупок. Разбив его, вы раскалываете его на кусочки, и $(thing)зачерование Удачи/$ увеличивает выход... если я хочу сам блок, мне нужно легкое прикосновение.$(br2)Полученные осколки стоят втрое дороже $(l:items/amethyst)$(item)Заряженного Аметистового Кристалла/$ за штуку. Сам блок стоит четыре осколка.", - "5": "Они непостоянны, кажется, что они изгибаются и мигают под моими пальцами, и, дав им пример в другой форме _медиа, их можно заставить принять его форму, в эквивалентном обмене _медиа.", + "4": "Продукт хрупок. Разбив его, вы раскалываете его на кусочки, и $(thing)зачарование Удачи/$ увеличивает выход... если я хочу сам блок, мне нужно легкое прикосновение.$(br2)Полученные осколки стоят втрое дороже $(l:items/amethyst)$(item)Заряженного Аметистового Кристалла/$ за штуку. Сам блок стоит четыре осколка.", + "5": "Они непостоянны, кажется, что они изгибаются и мигают под моими пальцами, и, дав им пример в другой форме Мысли, их можно заставить принять его форму, в эквивалентном обмене Мысли.", }, @@ -1520,25 +1520,25 @@ "1": "Я разделил все найденные мной действительные руны на разделы в зависимости от их функций. Я также записал порядок хода рун, если мне удалось найти его в своих исследованиях, начиная руну с отмеченной красной точкой.$(br2)Если действие выполняется несколькими рунами, как это бывает в некоторых случаях, я буду писать их все рядом.", "2": "Однако для некоторых рун я $(italic)не смог/$ найти порядок хода, только форму. Я предполагаю, что порядок рисования их где-то существует, спрятанный в древних библиотеках и подземельях мира.$(br2)В таких случаях я просто рисую руну без информации о порядке ее рисования.", "3": "Я также указываю типы иот, которые действие потребляет или изменяет, символ \"\u2192\", и типы иот, которые действие создает.$(p)Например, \"$(n)вектор, число/$ \u2192 $(n)вектор/$\" означает, что действие удалит вектор и число из верхней части стека, а затем добавит вектор; или, другими словами, удалит число из стека, а затем изменит вектор в верхней части стека. (Число должно быть на верхушке стека, с вектором прямо под ним.)", - "4": "\"\u2192 $(n)entity/$\" означает, что оно просто добавит entity. \"$(n)entity, вектор/$ \u2192\" означает, что оно удалит entity и вектор, и ничего не добавит.$(br2)Наконец, если я нахожу, что маленькая точка, обозначающая порядок хода, слишком медленная или запутанная, я могу нажать $(thing)Control/Command/$, чтобы отобразить градиент, где начало руны самое темное, а конец самое светлое. Это также работает на свитках и при произнесении заклинаний!", + "4": "\"\u2192 $(n)сущность/$\" означает, что оно просто добавит сущность. \"$(n)сущность, вектор/$ \u2192\" означает, что оно удалит сущность и вектор, и ничего не добавит.$(br2)Наконец, если я нахожу, что маленькая точка, обозначающая порядок хода, слишком медленная или запутанная, я могу нажать $(thing)Control/Command/$, чтобы отобразить градиент, где начало руны самое темное, а конец самое светлое. Это также работает на свитках и при произнесении заклинаний!", }, basics_pattern: { - get_caster: "Добавляет меня, как entity в стек.", - "entity_pos/eye": "Преобразует entity в стеке в позицию ее глаз. Вероятно, мне следует использовать это на себе.", + get_caster: "Добавляет меня, как сущность в стек.", + "entity_pos/eye": "Преобразует сущность в стеке в позицию ее глаз. Вероятно, мне следует использовать это на себе.", "entity_pos/foot": "Преобразует сущность в стеке в позицию, в которой она стоит.", get_entity_look: "Преобразует сущность в стеке в направление, в котором она смотрит, как вектор.", print: "Отображает верхнюю йоту стека.", raycast: { - "1": "Комбинирует два вектора (позицию и направление взгляда). -Если я стою в позиции и смотрю в направлении, на какой блок я смотрю? Стоимость незначительного количества _media.", - "2": "Если ничего не попадает, векторы объединятся в $(l:casting/influences)$(thing)Null/$.$(br2)Общая последовательность шаблонов, так называемая \"raycast mantra,\" состоит из $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$, $(l:patterns/basics#hexcasting:entity_pos/eye)$(action)Compass Purification/$, $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$, $(l:patterns/basics#hexcasting:get_entity_look)$(action)Alidade Purification/$, $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$. Вместе они возвращают векторную позицию блока, на который я смотрю.", + "1": "Комбинирует два вектора (позицию и направление взгляда). -Если я стою в позиции и смотрю в направлении, на какой блок я смотрю? Стоимость незначительного количества Мысли.", + "2": "Если ничего не попадает, векторы объединятся в $(l:casting/influences)$(thing)Null/$.$(br2)Общая последовательность шаблонов, так называемая \"raycast mantra,\" состоит из $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$, $(l:patterns/basics#hexcasting:entity_pos/eye)$(action)Compass Purification/$, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$, $(l:patterns/basics#hexcasting:get_entity_look)$(action)Пробразование Взгляда/$, $(l:patterns/basics#hexcasting:raycast)$(action)Объединение Луча/$. Вместе они возвращают векторную позицию блока, на который я смотрю.", }, "raycast/axis": { - "1": "Подобно $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$, но вместо этого возвращает вектор, представляющий ответ на вопрос: С какой $(italic)стороны/$ блока я смотрю? Стоимость незначительного количества _media.", + "1": "Подобно $(l:patterns/basics#hexcasting:raycast)$(action)Объединению Луча/$, но вместо этого возвращает вектор, представляющий ответ на вопрос: С какой $(italic)стороны/$ блока я смотрю? Стоит незначительное количество Мысли.", "2": "Если говорить подробней, он возвращает $(italic)нормальный вектор/$ ударенной поверхности или единичный вектор, указывающий перпендикулярно к поверхности.$(li)Если я смотрю на пол, он вернет (0, 1, 0).$(li)Если я смотрю на южную грань блока, он вернет (0, 0, 1).", }, - "raycast/entity": "Подобно $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$, но вместо этого возвращает $(italic)entity/$, на которую я смотрю. Стоимость незначительного количества _media.", - get_entity_height: "Преобразует entity в стеке в ее высоту.", + "raycast/entity": "Подобно $(l:patterns/basics#hexcasting:raycast)$(action)Объединению Луча/$, но вместо этого возвращает $(italic)сущность/$, на которую я смотрю. Стоимость незначительного количества Мысли.", + get_entity_height: "Преобразует сущность на стеке в ее высоту.", get_entity_velocity: "Преобразует сущность в стеке в направление, в котором она движется, со скоростью этого движения в качестве величины этого направления.", }, @@ -1619,14 +1619,14 @@ }, "consts.const/": { - "null": "Добавляет $(l:casting/influences)$(thing)Null/$ в верхнюю часть стека.", - "true": "Добавляет $(thing)True/$ в верхнюю часть стека.", - "false": "Добавляет $(thing)False/$ в верхнюю часть стека.", + "null": "Добавляет $(l:casting/influences)$(thing)Ничто/$ в верхнюю часть стека.", + "true": "Добавляет $(thing)Истину/$ в верхнюю часть стека.", + "false": "Добавляет $(thing)Ложь/$ в верхнюю часть стека.", "vec/": { - x: "Левый контр-часовой шаблон добавляет [1, 0, 0] в стек; правый по часовой стрелке шаблон добавляет [-1, 0, 0].", - y: "Левый контр-часовой шаблон добавляет [0, 1, 0] в стек; правый по часовой стрелке шаблон добавляет [0, -1, 0].", - z: "Левый контр-часовой шаблон добавляет [0, 0, 1]; правый по часовой стрелке шаблон добавляет [0, 0, -1].", + x: "Левый противочасовой шаблон добавляет [1, 0, 0] в стек; правый по часовой стрелке шаблон добавляет [-1, 0, 0].", + y: "Левый противочасовой шаблон добавляет [0, 1, 0] в стек; правый по часовой стрелке шаблон добавляет [0, -1, 0].", + z: "Левый противочасовой шаблон добавляет [0, 0, 1]; правый по часовой стрелке шаблон добавляет [0, 0, -1].", "0": "Добавляет [0, 0, 0] в стек.", }, @@ -1638,8 +1638,8 @@ }, stackmanip: { - "pseudo-novice.title": "Novice's Gambit", - "pseudo-novice": "Удаляет первую йоту из стека.$(br2)Это кажется особым случаем $(l:patterns/stackmanip#hexcasting:mask)$(action)Bookkeeper's Gambit/$.", + "pseudo-novice.title": "Гамбит Новичка", + "pseudo-novice": "Удаляет первую йоту из стека.$(br2)Это кажется особым случаем $(l:patterns/stackmanip#hexcasting:mask)$(action)Гамбита Библиотекаря/$.", swap: "Меняет местами две верхних йоты в стеке.", rotate: "Вытаскивает третью йоту сверху стека и перемещает его наверх. [0, 1, 2] становится [1, 2, 0].", @@ -1651,11 +1651,11 @@ stack_len: "Помещает размер стека в виде числа наверху стека. (Например, стек [0, 1] станет [0, 1, 2].)", duplicate_n: "Удаляет число в верхней части стека, затем копирует верхнюю йоту столько раз, сколько указано этим числом. (При значении 2 в стеке будет две йоты, а не три.)", fisherman: "Берет элемент в стеке с указанным индексом и перемещает его наверх. Если число отрицательное, то перемещает верхний элемент стека на указанное количество позиций вниз.", - "fisherman/copy": "Подобно $(l:patterns/stackmanip#hexcasting:fisherman)$(action)Fisherman's Gambit/$, но вместо перемещения йота, копирует его.", + "fisherman/copy": "Подобно $(l:patterns/stackmanip#hexcasting:fisherman)$(action)Гамбиту РЫбака/$, но вместо перемещения йота, копирует его.", mask: { "1": "Бесконечное семейство действий, которые сохраняют или удаляют элементы на вершине стека, основываясь на последовательности погружений и линий.", - "2": "Предполагая, что я рисую шаблон - Bookkeeper's Gambit слева направо, количество йотов, необходимых для действия, определяется горизонтальным расстоянием, пройденным шаблоном. От самого глубокого в стеке до самого поверхностного, плоская линия сохранит йот, в то время как треугольник, опускающийся вниз, удалит его.$(br2)Если мой стек содержит $(italic)0, 1, 2/$ от самого глубокого к поверхностному, рисование первого шаблона в противоположную сторону даст мне $(italic)1/$, второй даст $(italic)0/$, а третий даст $(italic)0, 2/$ (нуль внизу остается нетронутым).", + "2": "Предполагая, что я рисую шаблон - Гамбита Библиотекаря слева направо, количество йотов, необходимых для действия, определяется горизонтальным расстоянием, пройденным шаблоном. От самого глубокого в стеке до самого поверхностного, плоская линия сохранит йот, в то время как треугольник, опускающийся вниз, удалит его.$(br2)Если мой стек содержит $(italic)0, 1, 2/$ от самого глубокого к поверхностному, рисование первого шаблона в противоположную сторону даст мне $(italic)1/$, второй даст $(italic)0/$, а третий даст $(italic)0, 2/$ (нуль внизу остается нетронутым).", }, swizzle: { @@ -1666,23 +1666,23 @@ }, logic: { - bool_coerce: "Преобразует аргумент в логическое значение. Число $(thing)0/$, $(l:casting/influences)$(thing)Null/$ и пустой список становятся False; всё остальное становится True.", - bool_to_number: "Преобразует логическое значение в число; True становится $(thing)1/$, а False становится $(thing)0/$.", - not: "Если аргумент равен True, вернёт False; если он равен False, вернёт True.", - or: "Возвращает True, если хотя бы один из аргументов равен True; в противном случае возвращает False.", - and: "Возвращает True, если оба аргумента равны True; в противном случае возвращает False.", - xor: "Возвращает True, если ровно один из аргументов равен True; в противном случае возвращает False.", - if: "Если первый аргумент равен True, сохраняет второй и отбрасывает третий; в противном случае отбрасывает второй и сохраняет третий.", - equals: "Если первый аргумент равен второму (с небольшим допуском), возвращает True. В противном случае возвращает False.", - not_equals: "Если первый аргумент не равен второму (с учетом небольшого допуска), возвращает True. В противном случае возвращает False.", - greater: "Если первый аргумент больше второго, возвращает True. В противном случае возвращает False.", - less: "Если первый аргумент меньше второго, возвращает True. В противном случае возвращает False.", - greater_eq: "Если первый аргумент больше или равен второму, возвращает True. В противном случае возвращает False.", - less_eq: "Если первый аргумент меньше или равен второму, возвращает True. В противном случае возвращает False.", + bool_coerce: "Преобразует аргумент в логическое значение. Число $(thing)0/$, $(l:casting/influences)$(thing)Null/$ и пустой список становятся Ложь; всё остальное становится Истина.", + bool_to_number: "Преобразует логическое значение в число; Истина становится $(thing)1/$, а Ложь становится $(thing)0/$.", + not: "Если аргумент равен Истина, вернёт Ложь; если он равен Ложь, вернёт Истина.", + or: "Возвращает Истина, если хотя бы один из аргументов равен Истина; в противном случае возвращает Ложь.", + and: "Возвращает Истина, если оба аргумента равны Истина; в противном случае возвращает Ложь.", + xor: "Возвращает Истина, если ровно один из аргументов равен Истина; в противном случае возвращает Ложь.", + if: "Если первый аргумент равен Истина, сохраняет второй и отбрасывает третий; в противном случае отбрасывает второй и сохраняет третий.", + equals: "Если первый аргумент равен второму (с небольшим допуском), возвращает Истина. В противном случае возвращает Ложь.", + not_equals: "Если первый аргумент не равен второму (с учетом небольшого допуска), возвращает Истина. В противном случае возвращает Ложь.", + greater: "Если первый аргумент больше второго, возвращает Истина. В противном случае возвращает Ложь.", + less: "Если первый аргумент меньше второго, возвращает Истина. В противном случае возвращает Ложь.", + greater_eq: "Если первый аргумент больше или равен второму, возвращает Истина. В противном случае возвращает Ложь.", + less_eq: "Если первый аргумент меньше или равен второму, возвращает Истина. В противном случае возвращает Ложь.", }, entities: { - get_entity: "Преобразует позицию в стеке в entity на этом месте (или $(l:casting/influences)$(thing)Null/$, если ее там нет).", + get_entity: "Преобразует позицию в стеке в сущность на этом месте (или $(l:casting/influences)$(thing)Null/$, если ее там нет).", "get_entity/": { animal: "Преобразует позицию в стеке в животное на этом месте (или $(l:casting/influences)$(thing)Null/$, если его там нет).", monster: "Преобразует позицию в стеке в монстра на этом месте (или $(l:casting/influences)$(thing)Null/$, если его там нет).", @@ -1691,18 +1691,18 @@ living: "Преобразует позицию в стеке в живое существо на этом месте (или $(l:casting/influences)$(thing)Null/$, если его там нет).", }, - zone_entity: "Берёт позицию и радиус в стеке и объедините их в список всех entity, находящихся в заданном радиусе от позиции.", + zone_entity: "Берёт позицию и радиус в стеке и объедините их в список всех сущность, находящихся в заданном радиусе от позиции.", "zone_entity/": { animal: "Берёт позицию и радиус в стеке и объедините их в список животных, находящихся в заданном радиусе от позиции.", - not_animal: "Берёт позицию и радиус в стеке и объедините их в список entity, не являющихся животными, находящихся в заданном радиусе от позиции.", + not_animal: "Берёт позицию и радиус в стеке и объедините их в список сущность, не являющихся животными, находящихся в заданном радиусе от позиции.", monster: "Берёт позицию и радиус в стеке и объедините их в список монстров, находящихся в заданном радиусе от позиции.", - not_monster: "Берёт позицию и радиус в стеке и объедините их в список entity, не являющихся монстрами, находящихся в заданном радиусе от позиции.", + not_monster: "Берёт позицию и радиус в стеке и объедините их в список сущность, не являющихся монстрами, находящихся в заданном радиусе от позиции.", item: "Берёт позицию и радиус в стеке и объедините их в список выброшенных предметов, находящихся в заданном радиусе от позиции.", - not_item: "Берёт позицию и радиус в стеке и объедините их в список entity, не являющихся предметами, находящихся в заданном радиусе от позиции.", + not_item: "Берёт позицию и радиус в стеке и объедините их в список сущность, не являющихся предметами, находящихся в заданном радиусе от позиции.", player: "Берёт позицию и радиус в стеке и объедините их в список игроков, находящихся в заданном радиусе от позиции.", - not_player: "Берёт позицию и радиус в стеке и объедините их в список entity, не являющихся игроками, находящихся в заданном радиусе от позиции.", - living: "Берёт позицию и радиус в стеке и объедините их в список живых entity, находящихся в заданном радиусе от позиции.", - not_living: "Берёт позицию и радиус в стеке и объедините их в список entity, не являющихся живыми, находящихся в заданном радиусе от позиции.", + not_player: "Берёт позицию и радиус в стеке и объедините их в список сущность, не являющихся игроками, находящихся в заданном радиусе от позиции.", + living: "Берёт позицию и радиус в стеке и объедините их в список живых сущность, находящихся в заданном радиусе от позиции.", + not_living: "Берёт позицию и радиус в стеке и объедините их в список сущность, не являющихся живыми, находящихся в заданном радиусе от позиции.", }, }, @@ -1741,38 +1741,38 @@ }, readwrite: { - "1": "Этот раздел касается хранения $(thing)йот/$ в более постоянной среде. Почти любой йот может быть сохранен на подходящем предмете, таком как $(l:items/focus)$(item)Фокус/$ или $(l:items/spellbook)$(item)Книга заклинаний/$), и позже снова прочитан. Некоторые предметы, такие как $(l:items/abacus)$(item)Счеты/$, могут быть только прочитаны.$(br2)Йоты обычно читаются и записываются с другой руки, но также возможно читать и писать с помощью предмета, когда он находится на земле как предмет-сущность или в рамке предмета.", + "1": "Этот раздел касается хранения $(thing)йот/$ в более постоянной среде. Почти любой йот может быть сохранен на подходящем предмете, таком как $(l:items/focus)$(item)Талисман/$ или $(l:items/spellbook)$(item)Книга заклинаний/$), и позже снова прочитан. Некоторые предметы, такие как $(l:items/abacus)$(item)Счеты/$, могут быть только прочитаны.$(br2)Йоты обычно читаются и записываются с другой руки, но также возможно читать и писать с помощью предмета, когда он находится на земле как предмет-сущность или в рамке предмета.", "2": "Возможно, есть и другие сущности, с которыми я могу взаимодействовать подобным образом. Например, со $(l:items/scroll)$(item)Свитка/$, висящего на стене, можно считывать его узор.$(br2)Однако, похоже, я не могу сохранить ссылку на другого игрока, только на себя. Я полагаю, что ссылка на сущность похожа на идею Истинного Имени; возможно, Природа помогает сохранить наши Имена от рук наших врагов. Если я хочу, чтобы у друга было мое Имя, я могу сделать для него $(l:items/focus)$(item)Focus/$ и самостоятельно записать себя на него.", read: "Копирует йоту, хранящуюся в предмете в моей другой руке, и добавляет её в стек.", write: "Извлекает верхнюю йоту из стека и помещает ее в предмет в другой руке.", "read/entity": "Подобно $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$, но йота считывается из сущности, а не из моей руки.", "write/entity": "Подобно $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Gambit/$, но йота записывается на сущность, а не в предмет в руке.$(br2)Интересно, кажется, что я не могу записать свое собственное Имя с помощью этого заклинания. Я чувствую, что могу оказаться в опасности, если бы мог это сделать.", - readable: "Если предмет в моей другой руке содержит йоту, которую я могу прочитать, возвращается True. В противном случае возвращается False.", - "readable/entity": "Подобно $(l:patterns/readwrite#hexcasting:readable)$(action)Auditor's Reflection/$, но проверяется читаемость entity, а не моя вторая рука.", - writable: "Если я могу сохранить йоту в предмете, который держу в другой руке, возвращается True. В противном случае возвращается False.", - "writable/entity": "Подобно $(l:patterns/readwrite#hexcasting:writable)$(action)Assessor's Reflection/$, но проверяется возможность записи на Entity.", - "local.title": "The Ravenmind", - local: "Предметы - не единственное место, где я могу хранить информацию. Я также могу хранить эту информацию в _медиа _Хекса, подобно стеку, но отдельно. В текстах это именуется $(l:patterns/readwrite#hexcasting:local)$(thing)ravenmind/$. Он содержит одну йоту, подобно $(l:items/focus)$(item)Фокусу/$. Он сохраняется между итерациями $(l:patterns/meta#hexcasting:for_each)$(action)Thoth's Gambit/$, но длится только до тех пор, пока действует _Хекс, частью которого он является. Как только я прекращу кастовать, значение будет потеряно.", - "write/local": "Удаляет верхнюю йоту из стека и сохраняет его в мой $(l:patterns/readwrite#hexcasting:local)$(thing)ravenmind/$, храня его там до тех пор, пока я не прекращу заклинание _Хекса.", - "read/local": "Копирует йоту из моего $(l:patterns/readwrite#hexcasting:local)$(thing)ravenmind/$, который я, только что записал с помощью $(l:patterns/readwrite#hexcasting:write/local)$(action)Huginn's Gambit/$.", + readable: "Если предмет в моей другой руке содержит йоту, которую я могу прочитать, возвращается Истина. В противном случае возвращается Ложь.", + "readable/entity": "Подобно $(l:patterns/readwrite#hexcasting:readable)$(action)Отражение Ревизора/$, но проверяется читаемость сущности, а не моя вторая рука.", + writable: "Если я могу сохранить йоту в предмете, который держу в другой руке, возвращается Истина. В противном случае возвращается Ложь.", + "writable/entity": "Подобно $(l:patterns/readwrite#hexcasting:writable)$(action)Отражению Заседателя/$, но проверяется возможность записи на сущность.", + "local.title": "Разум", + local: "Предметы - не единственное место, где я могу хранить информацию. Я также могу хранить эту информацию в Мысли, подобно стеку, но отдельно. В текстах это именуется $(l:patterns/readwrite#hexcasting:local)$(thing)Разум/$. Он содержит одну йоту, подобно $(l:items/focus)$(item)Талисману/$. Он сохраняется между итерациями $(l:patterns/meta#hexcasting:for_each)$(action)Гамбита Тота/$, но длится только до тех пор, пока действует заклинание, частью которого он является. Как только я прекращу писать руны, значение будет потеряно.", + "write/local": "Удаляет верхнюю йоту из стека и сохраняет его в мой $(l:patterns/readwrite#hexcasting:local)$(thing)Разум Ворона/$, храня его там до тех пор, пока я не прекращу заклинание.", + "read/local": "Копирует йоту из моего $(l:patterns/readwrite#hexcasting:local)$(thing)Разума/$, который я, только что записал с помощью $(l:patterns/readwrite#hexcasting:write/local)$(action)Huginn's Gambit/$.", }, meta: { - "eval.1": "Уберает паттерн или список паттернов из стека, затем кастует их, как если бы я сам их нарисовал, с помощью моего $(l:items/staff)$(item)Посоха/$ (пока не встретится $(l:patterns/meta#hexcasting:halt)$(action)Charon's Gambit/$). Если йота была выведена с помощью $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ или $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)its ilk/$, она будет перемещена в стек. В противном случае непаттерны будут провалены.", - "eval.2": "Это может быть $(italic)очень/$ мощным в сочетании с $(l:items/focus)$(item)Фокусами/$.$(br2)Это также делает бюрократию Природы \"Тьюриг-Полной\" системой, согласно одному эзотерическому свитку, который я нашел.$(br2)Однако, кажется, есть ограничение на количество раз, которое _Хекс может сам себя использовать - Природа не благосклонно относится к беглым заклинаниям!$(br2)Кроме того, с энергией шаблонов, происходящей без моего управления, любое недоразумение приведет к тому, что оставшиеся действия станут слишком нестабильными и немедленно разваливаются.", + "eval.1": "Убирает паттерн или список паттернов из стека, затем кастует их, как если бы я сам их нарисовал, с помощью моего $(l:items/staff)$(item)Посоха/$ (пока не встретится $(l:patterns/meta#hexcasting:halt)$(action)Charon's Gambit/$). Если йота была выведена с помощью $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ или $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)its ilk/$, она будет перемещена в стек. В противном случае непаттерны будут провалены.", + "eval.2": "Это может быть $(italic)очень/$ мощным в сочетании с $(l:items/focus)$(item)Талисманами/$.$(br2)Это также делает бюрократию Природы \"Тьюриг-Полной\" системой, согласно одному эзотерическому свитку, который я нашел.$(br2)Однако, кажется, есть ограничение на количество раз, которое _Хекс может сам себя использовать - Природа не благосклонно относится к беглым заклинаниям!$(br2)Кроме того, с энергией шаблонов, происходящей без моего управления, любое недоразумение приведет к тому, что оставшиеся действия станут слишком нестабильными и немедленно разваливаются.", "for_each.1": "Извлеките из стека список шаблонов и список, а затем проведите по каждому элементу второго списка заданный шаблон.", "for_each.2": "Более конкретно, для каждого элемента во втором списке будет:$(li) Создать новый стек со всем, что есть на текущем стеке плюс этот элемент$(li) Нарисовать все шаблоны из первого списка$(li) Сохранить все иоты, оставшиеся на стеке, в список$(br) Затем, после того, как все будет сделано, поместить список сохраненных иотов на основной стек.$(br2) Неудивительно, что все практикующие этого искусства сходят с ума.", - "halt.1": "Этот паттерн принудительно останавливает _Hex. Сам по себе он практически бесполезен, так как я могу просто перестать писать шаблоны или положить посох.", - "halt.2": "Но когда это сочетается с $(l:patterns/meta#hexcasting:eval)$(action)Hermes'/$ или $(l:patterns/meta#hexcasting:for_each)$(action)Thoth's Gambits/$, это становится $(italics)гораздо/$ более интересным. Эти шаблоны служат для 'содержания' этого прекращения, и вместо того, чтобы завершить весь _Хекс, эти ходы завершаются вместо этого. Это можно использовать, чтобы $(l:patterns/meta#hexcasting:for_each)$(action)Thoth's Gambit/$ не действовал на каждую йоту, которая ему дана. Побег от безумия, так сказать.", + "halt.1": "Этот паттерн принудительно останавливает заклинание. Сам по себе он практически бесполезен, так как я могу просто перестать писать шаблоны или положить посох.", + "halt.2": "Но когда это сочетается с $(l:patterns/meta#hexcasting:eval)$(action)Гамбитом Гермеса/$ или $(l:patterns/meta#hexcasting:for_each)$(action)Гамбит Тота/$, это становится $(italics)гораздо/$ более интересным. Эти шаблоны служат для 'содержания' этого прекращения, и вместо того, чтобы завершить вcё заклинание, эти части завершаются вместо этого. Это можно использовать, чтобы $(l:patterns/meta#hexcasting:for_each)$(action)Гамбит Тота/$ не действовал на каждую йоту, которая ему дана. Побег от безумия, так сказать.", - "eval/cc.1": "Вызывает паттерн или список паттернов из стека точно так же, как Hermes' Gambit/$, за исключением того, что в стек предварительно помещается уникальная йота \"Jump\".", + "eval/cc.1": "Вызывает паттерн или список паттернов из стека точно так же, как Гамбит Гермеса, за исключением того, что в стек предварительно помещается уникальная йота \"Jump\".", "eval/cc.2": "Когда \"Jump\"-йота выполняется, она пропускает остальные паттерны и переходит непосредственно к концу списка паттернов. $(p)Хотя это может показаться излишним, учитывая существование $(l:patterns/meta#hexcasting:halt)$(action)Charon's Gambit/$, это позволяет вам выходить из $(italic)вложенных/$ $(l:patterns/meta#hexcasting:eval)$(action)Hermes'/$ вызовов контролируемым образом, тогда как Charon позволяет вам выйти только из одного.$(p)The \"Jump\" йота, очевидно, останется в стеке даже после завершения выполнения... лучше не думать о последствиях этого.", }, circle_patterns: { - disclaimer: "!Предуприждение! все эти патерны должны быть кастованы с помощью $(l:greatwork/spellcircles)$(item)Магическова Круга/$; попытка каста с помощью $(l:items/staff)$(item)Посоха/$ приведёт к весьма впечатляющему провалу.", + disclaimer: "Предупреждение! все эти патерны должны быть использованы с помощью $(l:greatwork/spellcircles)$(item)Магического Круга/$; попытка каста с помощью $(l:items/staff)$(item)Посоха/$ приведёт к весьма впечатляющему провалу.", "circle/impetus_pos": "Возвращает позицию $(l:greatwork/impetus)$(item)Impetus/$ этого круга заклинаний.", "circle/impetus_dir": "Возвращает направление, в котором смотрит $(l:greatwork/impetus)$(item)Impetus/$ этого круга заклинаний, в виде единичного вектора.", @@ -1800,11 +1800,11 @@ "explode.fire.1": "Удаляет верхние вектор и число из стека, затем создаёт огненный-взрыв в указанном месте с заданной мощностью.", "explode.fire.2": "Стоит одну $(l:items/amethyst)$(item)аметистовую пыль/$, плюс примерно 3 дополнительных $(l:items/amethyst)$(item)аметистовых пыли/$ за каждую единицу мощности взрыва. В остальном то же самое, что и $(l:patterns/spells/basic#hexcasting:explode)$(action)Взрыв/$, за исключением наличия огня.", - add_motion: "Поглощает Entity и вектор из стека, затем придает импульс указаннму entity в указанном направлении. Сила импульса определяется длиной вектора.$(br)Стоимость в единицах $(l:items/amethyst)$(item)аметистовой пыли/$, равная квадрату длины вектора, плюс одна за каждый импульс, кроме первого, направленного на сущность.", - blink: "Поглощает Entity и вектор из стека, затем телепортирует указанное entity вдоль её вектора обзора на указанное расстояние.$(br)Стоимость примерно одного $(l:items/amethyst)$(item)аметистового осколка/$ за каждые два пройденных блока.", + add_motion: "Поглощает Сущность и вектор из стека, затем придает импульс указанной сущности в указанном направлении. Сила импульса определяется длиной вектора.$(br)Стоимость в единицах $(l:items/amethyst)$(item)аметистовой пыли/$, равная квадрату длины вектора, плюс одна за каждый импульс, кроме первого, направленного на сущность.", + blink: "Поглощает Сущность и вектор из стека, затем телепортирует указанную сущность вдоль её вектора обзора на указанное расстояние.$(br)Стоимость примерно одного $(l:items/amethyst)$(item)аметистового осколка/$ за каждые два пройденных блока.", "beep.1": "Поглощает вектор и два числа из стека. Играет на $(thing)инструменте/$, определенном первым числом, в указанном месте, с $(thing)нотой/$, определенной вторым числом.", - "beep.2": "Похоже, что есть 16 различных $(thing)инструментов/$ и 25 различных $(thing)нот/$. Оба параметра индексируются начиная с нуля.$(br2)Похоже, что это те же инструменты, которые я могу создать с помощью $(item)нотного блока/$, хотя причина присвоения каждому инструменту своего номера мне неизвестна.$(br2)В любом случае, я могу найти необходимые мне числа, осматривая $(item)нотный блок/$ через $(l:items/lens)$(item)Амметистовую Линзу/$.", + "beep.2": "Похоже, что есть 16 различных $(thing)инструментов/$ и 25 различных $(thing)нот/$. Оба параметра индексируются начиная с нуля.$(br2)Похоже, что это те же инструменты, которые я могу создать с помощью $(item)нотного блока/$, хотя причина присвоения каждому инструменту своего номера мне неизвестна.$(br2)В любом случае, я могу найти необходимые мне числа, осматривая $(item)нотный блок/$ через $(l:items/lens)$(item)Линзу Прозрения/$.", }, blockworks: { @@ -1815,14 +1815,14 @@ conjure_block: "Создаёт прозрачный, но прочный блок, который сверкает моим пигментом в указанном месте. Стоит примерно одну $(l:items/amethyst)$(item)Аметистовую Пыль/$.", conjure_light: "Создаёт магический свет, мягко светящийся моим пигментом в указанном месте. Стоит примерно одну $(l:items/amethyst)$(item)Аметистовую Пыль/$.", bonemeal: "Побуждает растения или саженцы в указанном месте к росту, как если бы к ним была применена $(item)Костная Мука/$. Стоит немного больше, чем одна $(l:items/amethyst)$(item)Аметистовая Пыль/$.", - edify: "Принудительно насыщает саженец _media на целевой позиции, заставляя его вырасти в $(l:items/edified)$(thing)Edified Tree/$. Стоит примерно примерно как один $(l:items/amethyst)$(item)заряженный аметист/$.", + edify: "Принудительно насыщает саженец Мысли на целевой позиции, заставляя его вырасти в $(l:items/edified)$(thing)Edified Tree/$. Стоит примерно примерно как один $(l:items/amethyst)$(item)заряженный аметист/$.", ignite: "Зажигает огонь на указанном местоположением, как если бы был применен $(item)огненный заряд/$. Стоит примерно одну $(l:items/amethyst)$(item)аметистовую пыль/$.", extinguish: "Тушит блоки в большой области. Стоит примерно шесть $(l:items/amethyst)$(item)аметистовых пылинок/$.", }, nadirs: { - "1": "Вся эта группа заклинаний накладывает отрицательный эффект зелья на entity. Все они принимают entity - получателя, и одно или два числа: первое - это длительность, а второе, если присутствует, - это сила (начиная с 1).$(br2)У каждого из них есть \"базовая стоимость\"; фактическая стоимость равна этой базовой стоимости, умноженной на квадрат силы.", - "2": "Согласно некоторым легендам, эти заклинания и их собратья, $(l:patterns/great_spells/zeniths)$(action)Zeniths/$, были \"[...] вдохновлены миром, близким к этому, где могущественные волшебники собирали магию из земли и устраивали дуэли насмерть. К сожалению, многое было потеряно в переводе...\"$(br2)Возможно, в этом и причина их странных названий.", + "1": "Вся эта группа заклинаний накладывает отрицательный эффект зелья на сущность. Все они принимают сущность - получателя, и одно или два числа: первое - это длительность, а второе, если присутствует, - это сила (начиная с 1).$(br2)У каждого из них есть \"базовая стоимость\"; фактическая стоимость равна этой базовой стоимости, умноженной на квадрат силы.", + "2": "Согласно некоторым легендам, эти заклинания и их собратья, $(l:patterns/great_spells/zeniths)$(action)Зениты/$, были \"[...] вдохновлены миром, близким к этому, где могущественные волшебники собирали магию из земли и устраивали дуэли насмерть. К сожалению, многое было потеряно в переводе...\"$(br2)Возможно, в этом и причина их странных названий.", "potion/weakness": "Накладывает $(thing)Слабость/$. Базовая стоимость - одна $(l:items/amethyst)$(item)аметистовая пыль/$ за 10 секунд.", "potion/levitation": "Накладывает $(thing)Левитацию/$. Базовая стоимость - одна $(l:items/amethyst)$(item)аметистовая пыль/$ за 5 секунд.", @@ -1832,36 +1832,36 @@ }, hexcasting_spell: { - basics: "Эти три заклинания создают $(l:items/hexcasting)$(thing)предмет, который кастуют _Hex./$$(br)Все они требуют, чтобы я держал соответсвующий пустой предмет в своей второй руке и нуждаются в двух вещах: списке шаблонов для произнесения и entity, представляющей собой сброшенный стак $(l:items/amethyst)$(item)аметиста/$ для формирования батареи предмета.$(br2)Смотрите $(l:items/hexcasting)эту запись/$ для получения дополнительной информации.", + basics: "Эти три заклинания создают $(l:items/hexcasting)$(thing)предмет, который кастуют заклинания./$$(br)Все они требуют, чтобы я держал соответсвующий пустой предмет в своей второй руке и нуждаются в двух вещах: списке шаблонов для произнесения и сущность, представляющую собой сброшенный стак $(l:items/amethyst)$(item)аметиста/$ для формирования батареи предмета.$(br2)Смотрите $(l:items/hexcasting)эту запись/$ для получения дополнительной информации.", "craft/cypher": "Стоит примерно 1 $(l:items/amethyst)$(item)Заряженный Аметист/$.", "craft/trinket": "Стоит примерно 5 $(l:items/amethyst)$(item)Заряженных Аметистов/$.", "craft/artifact": "Стоит примерно 10 $(l:items/amethyst)$(item)Заряженных Аметистов/$.", - "recharge.1": "Перезарядить предмет, содержащий _media, в моей второй руке. Стоит примерно 1 $(l:items/amethyst)$(item)Аметистовый Осколок/$.", - "recharge.2": "Это заклинание применяется похожим образом на заклинание создания батареи-media; Ему требуется Entity, представляющая собой сброшенную стопку $(l:items/amethyst)$(item)аметиста/$, оно перезаряжает батарею _media предмета в моей другой руке.", + "recharge.1": "Перезарядить предмет, содержащий Мысли, в моей второй руке. Стоит примерно 1 $(l:items/amethyst)$(item)Аметистовый Осколок/$.", + "recharge.2": "Это заклинание применяется похожим образом на заклинание создания батареи-media; Ему требуется Сущность, представляющая собой сброшенную стопку $(l:items/amethyst)$(item)аметиста/$, оно перезаряжает батарею Мысли предмета в моей другой руке.", - "erase.1": "Очищает предмет от содержащигося в нём _Hex, в моей другой руке. Стоит примерно 1 $(l:items/amethyst)$(item)Аметистовую Пыль/$.", - "erase.2": "Это заклинание также аннулирует всю _media, хранящуюся внутри предмета, возвращая её обратно в Природу и возвращая предмет к идеально чистому состоянию. Таким образом, я могу повторно использовать $(l:items/hexcasting)$(item)Талисманы/$, в которые я поместил ошибочное заклинание.$(br2)Оно также способно очистить $(l:items/focus)$(item)Фокус/$ или $(l:items/spellbook)$(item)Книгу заклинаний/$.", + "erase.1": "Очищает предмет от содержащегося в нём заклинания, в моей другой руке. Стоит примерно 1 $(l:items/amethyst)$(item)Аметистовую Пыль/$.", + "erase.2": "Это заклинание также аннулирует всю Мысли, хранящуюся внутри предмета, возвращая её обратно в Природу и возвращая предмет к идеально чистому состоянию. Таким образом, я могу повторно использовать $(l:items/hexcasting)$(item)Талисманы/$, в которые я поместил ошибочное заклинание.$(br2)Оно также способно очистить $(l:items/focus)$(item)Талисман/$ или $(l:items/spellbook)$(item)Книгу заклинаний/$.", }, sentinels: { - "1": "$(italic)Итак, вперед! Теперь все в порядке./$$(br2)$(l:patterns/spells/sentinels)$(thing)Sentinel/$ - это таинственная сила, которую я могу призвать для помощи в произнесении _Hexes, подобно знакомому или духу-хранителю. Для меня он выглядит как вращающаяся геометрическая форма, но он невидим для всех остальных.", - "2": "У него несколько интересных свойств:$(li)По-видимому, он не является осязаемым; никто не может его коснуться.$(li)Только мои _Hexes могут взаимодействовать с ним.$(li)После призыва он остается на месте до изгнания.", + "1": "$(italic)Итак, вперед! Теперь все в порядке./$$(br2)$(l:patterns/spells/sentinels)$(thing)Sentinel/$ - это таинственная сила, которую я могу призвать для помощи в произнесении заклинаний, подобно знакомому или духу-хранителю. Для меня он выглядит как вращающаяся геометрическая форма, но он невидим для всех остальных.", + "2": "У него несколько интересных свойств:$(li)По-видимому, он не является осязаемым; никто не может его коснуться.$(li)Только мои заклинания могут взаимодействовать с ним.$(li)После призыва он остается на месте до изгнания.", "sentinel/create": "Призывает моего $(l:patterns/spells/sentinels)$(thing)sentinel/$ на указанной позиции. Стоит примерно 1 $(l:items/amethyst)$(item)аметистовую пыль/$.", - "sentinel/destroy": "Изгоняет моего $(l:patterns/spells/sentinels)$(thing)sentinel/$ из мира. Стоимость незначительна в _media.", - "sentinel/get_pos": "Добавляет позицию моего $(l:patterns/spells/sentinels)$(thing)sentinel/$ в стек, или $(l:casting/influences)$(thing)Null/$, если он не призван. Стоимость незначительна в _media.", - "sentinel/wayfind": "Преобразует вектор-позиции на вершине стека в единичный вектор, указывающий от этой позиции к моему $(l:patterns/spells/sentinels)$(thing)sentinel/$, или $(l:casting/influences)$(thing)Null/$, если он не призван. Стоимость незначительна в _media.", + "sentinel/destroy": "Изгоняет моего $(l:patterns/spells/sentinels)$(thing)sentinel/$ из мира. Стоимость незначительна в Мысли.", + "sentinel/get_pos": "Добавляет позицию моего $(l:patterns/spells/sentinels)$(thing)sentinel/$ в стек, или $(l:casting/influences)$(thing)Null/$, если он не призван. Стоимость незначительна в Мысли.", + "sentinel/wayfind": "Преобразует вектор-позиции на вершине стека в единичный вектор, указывающий от этой позиции к моему $(l:patterns/spells/sentinels)$(thing)sentinel/$, или $(l:casting/influences)$(thing)Null/$, если он не призван. Стоимость незначительна в Мысли.", }, colorize: "Для произнесения этого заклинания мне необходимо держать в другой руке $(l:items/pigments)$(item)Пигмент/$. Когда я это делаю, он поглощает краситель и навсегда изменяет окраску моего разума (по крайней мере, до тех пор, пока я снова не произнесу заклинание). Стоит примерно одну $(l:items/amethyst)$(item)аметистую пыль/$.", flights: { - "1": "Хотя кажется, что истинный, безграничный полет находится за пределами моего понимания, я тем не менее нашел некоторые способы удержания в воздухе, каждый со своими недостатками.$(br2)Все формы производят избыток _media; по мере приближения к концу заклинания, искры пропитываются большим количеством красного и черного.", - "2": "Конечно, существуют и другие формы полета. Например, комбинация $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ и $(l:patterns/spells/nadirs#hexcasting:potion/levitation)$(action)Blue Sun's Nadir/$ использовалась с древности для своего рода полета.$(br2)Я также слышал о тонкой мембране, носимой на спине, которая позволяет скользить по воздуху. Из моих исследований я полагаю, что Великое заклинание $(l:patterns/great_spells/altiora)$(action)Altiora/$ может быть использовано для имитации этого.", + "1": "Хотя кажется, что истинный, безграничный полет находится за пределами моего понимания, я тем не менее нашел некоторые способы удержания в воздухе, каждый со своими недостатками.$(br2)Все формы производят избыток Мысли; по мере приближения к концу заклинания, искры пропитываются большим количеством красного и черного.", + "2": "Конечно, существуют и другие формы полета. Например, комбинация $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Импульс/$ и $(l:patterns/spells/nadirs#hexcasting:potion/levitation)$(action)Blue Sun's Nadir/$ использовалась с древности для своего рода полета.$(br2)Я также слышал о тонкой мембране, носимой на спине, которая позволяет скользить по воздуху. Из моих исследований я полагаю, что Великое заклинание $(l:patterns/great_spells/altiora)$(action)Altiora/$ может быть использовано для имитации этого.", "range.1": "Полет, ограниченный по дальности.", - "range.2": "Второй аргумент - горизонтальный радиус, в метрах, в пределах которого заклинание стабильно. Перемещение за пределы этого радиуса приведет к окончанию заклинания и к падению на землю. Однако, пока я остаюсь в пределах безопасной зоны, заклинание длится бесконечно. Дополнительное мерцание _media обозначает точку происхождения безопасной зоны. $(br2)Стоит примерно 1 $(l:items/amethyst)$(item)аметистовую пыль/$ за метр безопасности.", + "range.2": "Второй аргумент - горизонтальный радиус, в метрах, в пределах которого заклинание стабильно. Перемещение за пределы этого радиуса приведет к окончанию заклинания и к падению на землю. Однако, пока я остаюсь в пределах безопасной зоны, заклинание длится бесконечно. Дополнительное мерцание Мысли обозначает точку происхождения безопасной зоны. $(br2)Стоит примерно 1 $(l:items/amethyst)$(item)аметистовую пыль/$ за метр безопасности.", "time.1": "Полет, ограниченный по продолжительности.", "time.2": "Второй аргумент - это количество времени в секундах, в течение которого заклинание стабильно. По истечении этого времени заклинание завершается. $(br2)Это относительно дорогое заклинание, примерно 1 $(l:items/amethyst)$(item)Заряженный Аметист/$ за секунду полета; я считаю, что оно лучше всего подходит для путешествий.", @@ -1879,32 +1879,32 @@ }, altiora: { - "1": "Вызывает вокруг тебя сноп _media в форме крыльев, наделенных достаточным количеством вещества, чтобы обеспечить скольжение по воздуху.", + "1": "Вызывает вокруг тебя сноп Мысли в форме крыльев, наделенных достаточным количеством вещества, чтобы обеспечить скольжение по воздуху.", "2": "Их использование идентично использованию $(item)Елитр/$; цель(которой должен быть игрок) поднимается в воздух, после нажатие $(k:jump) приводит в действие крылья. Крылья хрупкие и ломаются при соприкосновении с любой поверхностью. Для более длительных полетов можно использовать $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ или (для самых отважных) $(item)Феерверки/$.$(br2)Стоит около одного $(l:items/amethyst)$(item)Заряженного Аметиста/$.", }, "teleport/great": { "1": "Гораздо мощнее, чем $(l:patterns/spells/basic#hexcasting:blink)$(action)Blink/$, это заклинание позволяет мне телепортироваться практически в любое место на всей планете! Похоже, что есть ограничение, но оно $(italic)гораздо/$ больше, чем обычный радиус влияния, к которому я привык.", - "2": "Entity будет телепортировано по заданному вектору, который является смещением от его текущего положения. Независимо от расстояния, это всегда стоит около десяти $(l:items/amethyst)$(item)Заряженных Аметистов/$.$(br2)Перенос не идеален, и кажется, что при телепортации чего-то такого сложного, как игрок, их инвентарь не $(italic)всегда/$ остается прикрепленным и склонен разлетаться повсюду на месте назначения. Кроме того, цель будет насильственно удалена от всего неживого, на чем они едут или сидят... но я прочитал кое-какие обрывки, которые предполагают, что животные могут пойти вместе в путь, так сказать.", + "2": "Сущность будет телепортирована по заданному вектору, который является смещением от его текущего положения. Независимо от расстояния, это всегда стоит около десяти $(l:items/amethyst)$(item)Заряженных Аметистов/$.$(br2)Перенос не идеален, и кажется, что при телепортации чего-то такого сложного, как игрок, их инвентарь не $(italic)всегда/$ остается прикрепленным и склонен разлетаться повсюду на месте назначения. Кроме того, цель будет насильственно удалена от всего неживого, на чем они едут или сидят... но я прочитал кое-какие обрывки, которые предполагают, что животные могут пойти вместе в путь, так сказать.", }, zeniths: { - "1": "Это семейство заклинаний наделяют существо положительными еффектами, оно схожо с аналогичным $(l:patterns/spells/nadirs)$(action)Nadirs/$. Однако их затраты на _media увеличиваются с $(italic)кубом/$ мощности.", + "1": "Это семейство заклинаний наделяют существо положительными еффектами, оно схожо с $(l:patterns/spells/nadirs)$(action)Надир/$. Однако их затраты на Мысли увеличиваются с $(italic)кубом/$ мощности.", "potion/regeneration": "Дарует $(thing)Регенерацию/$. Базовая стоимость - одна $(l:items/amethyst)$(item)Аметистовая Пыль/$ в секунду.", "potion/night_vision": "Дарует $(thing)Ночное Зрение/$. Базовая стоимость - одна $(l:items/amethyst)$(item)Аметистовая пыль/$ за каждые 5 секунд.", - "potion/absorption": "Дарует $(thing)absorption/$. Базовая стоимость - одна $(l:items/amethyst)$(item)Аметистовая Пыль/$ в секунду.", - "potion/haste": "Дарует $(thing)Haste/$. Базовая стоимость - одна $(l:items/amethyst)$(item)Аметистовая Пыль/$ за каждые 3 секунды.", + "potion/absorption": "Дарует $(thing)Поглощение/$. Базовая стоимость - одна $(l:items/amethyst)$(item)Аметистовая Пыль/$ в секунду.", + "potion/haste": "Дарует $(thing)Спешку/$. Базовая стоимость - одна $(l:items/amethyst)$(item)Аметистовая Пыль/$ за каждые 3 секунды.", "potion/strength": "Дарует $(thing)Силу/$. Базовая стоимость - одна $(l:items/amethyst)$(item)Аметистовая Пыль/$ за каждые 3 секунды.", }, greater_sentinel: { - "1": "Призывает более мощную версию моего $(l:patterns/spells/sentinels)$(thing)Sentinel/$. Стоит около двух $(l:items/amethyst)$(item)Аметистовых Пылей/$.", - "2": "Более сильный $(l:patterns/spells/sentinels)$(thing)Sentinel/$ действует как обычный, которого я могу призвать без использования Великово Заклинания. Однако диапазон, в котором мои заклинания могут работать, расширяется до небольшого региона вокруг моего более мощного $(l:patterns/spells/sentinels)$(thing)sentinel/$, примерно 16 блоков. Другими словами, независимо от того, где я нахожусь в мире, я могу взаимодействовать с вещами вокруг моего $(l:patterns/spells/sentinels)$(thing)sentinel/$.", + "1": "Призывает более мощную версию моего $(l:patterns/spells/sentinels)$(thing)Часового/$. Стоит около двух $(l:items/amethyst)$(item)Аметистовых Пылей/$.", + "2": "Более сильный $(l:patterns/spells/sentinels)$(thing)Часовой/$ действует как обычный, которого я могу призвать без использования Великого Заклинания. Однако диапазон, в котором мои заклинания могут работать, расширяется до небольшого региона вокруг моего более мощного $(l:patterns/spells/sentinels)$(thing)Часового/$, примерно 16 блоков. Другими словами, независимо от того, где я нахожусь в мире, я могу взаимодействовать с вещами вокруг моего $(l:patterns/spells/sentinels)$(thing)Часового/$.", }, make_battery: { - "1": "Наполняет бутылку _media для получения $(l:items/phials)$(item)Флакона/$.", + "1": "Наполняет бутыль Мыслью для получения $(l:items/phials)$(item)Сосуда Мысли/$.", "2": "Подобно заклинаниям для $(l:patterns/spells/hexcasting)$(action)Создания Магических Предметов/$, мне нужно держать $(item)Стеклянную Бутылку/$ в другой руке и предоставить заклинанию выброшенный стак $(l:items/amethyst)$(item)Аметиста/$. Посмотрите $(l:items/phials)эту страницу/$ для получения дополнительной информации.$(br2)Стоит около одного $(l:items/amethyst)$(item)Заряженного Аметиста/$.", }, @@ -1913,14 +1913,14 @@ lore: { cardamom1: { - "1": "$(italic)Full title: Letter from Cardamom Steles to Her Father, #1/$$(br2)Dear Papa,$(br)Every day it seems I have more reason to thank you for saving up to send me to the Grand Library. The amount I am learning is incredible! I feel I don't have the skill with words needed to express myself fully... it is wonderful to be here.", - "2": "I sit in the main dome as I write this. It's maintained by the Hexcasting Corps; they have some sort of peculiar mechanism at the top that captures the stray thought energy as it leaks out from the desks and desks of hard-working students, as I understand it. One of my friends in the dormitory, Amanita, is studying the subject, and oh how she loves to explain it to me at length, although I confess I do not understand it very well.", - "3": "Так, как я понимаю, наши процессы мышления - нематериальные механизмы, с помощью которых я двигаю своим пером, а вы читаете это письмо - не совершенно эффективны. Небольшое количество этой энергии высвобождается в окружающую среду, подобно тому, как ось повозки нагревается на ощупь после того, как она крутится некоторое время. Эта лишняя энергия называется \"media\". Лишняя media одного человека ничтожна, но сотни мыслящих людей в главном куполе имеют своего рода мультипликативный эффект, и в сочетании с каким-то изобретательным механизмом, она может быть превращена в своего рода фиолетовый кристалл.", - "4": "Но достаточно об учебе. Сегодня я вернулся с моей первой экспедиции с Геологическим корпусом! Прошу прощения, что не отправил письмо перед отъездом; дата подкралась ко мне незаметно. Мы отправились в трещину на востоке от Гранда и провели ночь в походе под скалой и почвой. Конечно, мы держались в хорошо освещенных и хорошо проторенных участках пещеры, и, честно говоря, скорее всего, там было безопаснее, чем на поверхности ночью, но как же мне было страшно!", + "1": "$(italic)Письмо Кардамом Стайлз её Отцу, #1/$$(br2)Дорогой папа,$(br)каждый день я нахожу новые причины поблагодарить тебя за отправление меня в Великую Библиотеку. Невероятно то сколько нового я узнаю! Мне кажется что нет таких слов чтобы описать то как я себя чувствую... здесь прекрасно!", + "2": "Я пишу это находясь в основном куполе. Он поддерживается Рунными ???; у них есть некоторый механизм на верху, который захватывает мимолетную энергию мысли, которая вылетает с учебных мест трудящихся студентов, как я понимаю. Моя подруга Аманита изучает эту тему и она очень любит объяснять мне всё что может, но честно признаться я сама не до конца понимаю что она говорит.", + "3": "Как я понимаю, наши процессы мышления - нематериальные механизмы, с помощью которых я двигаю своим пером, а вы читаете это письмо - не совершенно эффективны. Небольшое количество этой энергии высвобождается в окружающую среду, подобно тому, как ось повозки нагревается на ощупь после того, как она крутится некоторое время. Эта лишняя энергия называется \"Мысли\". Лишние Мысли одного человека ничтожна, но сотни мыслящих людей в главном куполе имеют своего рода накопительный эффект, и в сочетании с каким-то изобретательным механизмом, она может быть превращена в своего рода фиолетовый кристалл.", + "4": "Но достаточно об учебе. Сегодня я вернулась с моей первой экспедиции с Геологическим корпусом! Прошу прощения, что не отправил письмо перед отъездом; дата подкралась ко мне незаметно. Мы отправились в трещину на востоке от Гранда и провели ночь в походе под скалой и почвой. Конечно, мы держались в хорошо освещенных и хорошо проторенных участках пещеры, и, честно говоря, скорее всего, там было безопаснее, чем на поверхности ночью, но как же мне было страшно!", "5": "К счастью, ночь прошла без происшествий, и мы продолжили двигаться глубже в пещеру для изучения местных жил руды. Мы искали следы жил фиолетового кристалла по имени \"аметист\", который, как говорят, встречается в небольших количествах глубоко в скале. К сожалению, мы ничего не нашли и вернулись на освещенную солнцем поверхность с пустыми руками.", "6": "Придя к этому, описание этого \"аметиста\" я теперь понимаю, тесно соответствует тем кристаллам среды, о которых говорит Аманита. Представьте, если бы эти кусочки мысли возникали естественным образом под землей! Я не могу представить, почему это могло бы произойти, однако...", - "7": "Как студент, у меня есть право отправить одно письмо по Akashic почте каждые три месяца бесплатно. К сожалению, вы знаете, насколько пусты мои кошельки... поэтому боюсь, что это предложение - единственный способ связаться с вами. Конечно, я буду очень благодарен, если вы сможете найти деньги, чтобы отправить ответное письмо, но, кажется, наши коммуникации могут быть ограничены. Мне жаль, что нам придется быть отрезанными друг от друга, но навыки, которые я здесь приобрету, более чем окупят это. Представьте, я буду первым членом нашей семьи, который станет кем-то, кроме фермера!", - "8": "Так что, предполагаю, я напишу снова через три месяца.$(br2)Ваш,$(br)-- Кардамон Стелес", + "7": "Как студент, у меня есть право отправить одно письмо по почте Акаши каждые три месяца бесплатно. К сожалению, вы знаете, насколько пусты мои кошельки... поэтому боюсь, что это предложение - единственный способ связаться с вами. Конечно, я буду очень благодарен, если вы сможете найти деньги, чтобы отправить ответное письмо, но, кажется, наши коммуникации могут быть ограничены. Мне жаль, что нам придется быть отрезанными друг от друга, но навыки, которые я здесь приобрету, более чем окупят это. Представьте, я буду первым членом нашей семьи, который станет кем-то, кроме фермера!", + "8": "Так что, предполагаю, я напишу снова через три месяца.$(br2)Ваша,$(br)-- Кардамом Стайлз", }, cardamom2: { @@ -1975,7 +1975,7 @@ "3": "I am more lucid today. Maybe. I cannot tell anymore. I cannot even say I am tired anymore; at some point the constant companion of exhaustion left me, even as something else came to prick at my eyes. I can't sense the fatigue. But it's there.$(br2)My bones are fragile. My joints are rough and sharp.", "4": "Sometimes why I am here comes back to me. I remember being too loud about something I knew ... I remember a very bright room where I was told things. I remember my thoughts freezing into glass, shattered, melted and recrystallized over and over and over and over and over with a purpose behind them to make me forget worse than that to keep me alive while killing me, my self, the iota of ME being meaningless because there would be no observer just a body but I tricked them I did it somehow", "5": "they thought they broke me beyond the point of pulling the wool over my eyes but i was awake enough and am awake enough to feel PAIN$(br2)I do not sleep but when i wake up I cannot rub the crust off of my eyes because it would cut my skin and I do not want to see the purple glints inside", - "6": "They do not kill me, because my husband has my focus, and he would know if I died. But he is no Hexcaster and could not find me with his mediocre skill. i am out of ambit$(br2)it h urts to think. quite literally. the thoughts are so wasteful now the leftover striates directly onto the million microcrystals", + "6": "They do not kill me, because my husband has my focus, and he would know if I died. But he is no Hexcaster and could not find me with his mediocre skill. i am out of ambit$(br2)it hurts to think. quite literally. the thoughts are so wasteful now the leftover striates directly onto the million microcrystals", "7": "i remember the doctors in the bright room forcing me to inhale something like sand but sharper and it hurt so much. At first just the physical pain of mucous membranes trying to absorb shatterglass but then they got their fingernails into my stimulus-response and they could do it with a word$(br2)i remember camping out and seeing the corps setting up their circle all around a village and the ground under my feet rumbling", "8": "drift out of time. Sometimes I believe I see visions of the future, because they seem to make sense but cannot happen now because I know i will be here until forever because the white room men said so. i see myself toppling over and my skull cracking open into halves and inside will be spears of not-amethyst dripping with blood piercing the wrinkled three pounds of fat and meat dreaming that it is a butterfly", "9": "i hope my students are alright. why do i think that? waste. they told me i'm a waste, they couldn't be content with destroying me they had to make me feel like I deserved it the whole time, too. No sticks or stones to break my bones, just words to hurt me. if they released me no one would believe me because my body is inspectable fully i just look like one more addicted to overcasting$(br2)But they locked me up insted and i dont know if it's a mercy", @@ -2004,7 +2004,7 @@ // ^ lore interop: { - "1": "Искусство _Hexcasting универсально. Если я обнаружу, что мой мир был $(italic)изменен/$ определенными другими силами, возможно, что я смогу использовать _Hexcasting в гармонии и сочетании с ними.", + "1": "Искусство написания рун универсально. Если я обнаружу, что мой мир был $(italic)изменен/$ определенными другими силами, возможно, что я смогу использовать руны в гармонии и сочетании с ними.", "2": "Я должен помнить, однако, что Природа, кажется, уделила меньше внимания при создании этих аспектов моего искусства; странное поведение и ошибки можно ожидать. Я уверен, что разработчик мода сделает все возможное, чтобы их исправить, но я должен помнить, что это для нее менее важное занятие.$(br2)Мне также может показаться, что есть явные нарушения баланса в затратах и эффектах взаимодействующих сил. В таком случае, предполагаю, мне придется быть ответственным и воздерживаться от их использования.", "3": "Наконец, если я обнаружу, что меня заинтересовали легенды и истории этого мира, я не думаю, что какие-либо заметки, составленные во время изучения этих взаимодействий, следует рассматривать как что-то более серьезное, чем легкие пустяки.", @@ -2016,7 +2016,7 @@ pehkui: { "1": "Я обнаружил способы изменения размера сущностей и запроса, насколько они больше или меньше обычного.", - get: "Получите масштаб сущности как пропорцию их нормального размера. Для большинства сущностей это будет 1.", + get: "Получите масштаб сущности как отношение к их нормальному размеру. Для большинства сущностей это будет 1.", set: "Установите масштаб сущности, передавая пропорцию их нормального размера. Стоимость около 1 $(item)Осколка Аметиста/$.", }, }, From da4a0ca4593cd46282f7df71aeb68bf3716565eb Mon Sep 17 00:00:00 2001 From: Ledinec Date: Sat, 20 Jul 2024 20:48:12 +0400 Subject: [PATCH 16/39] Translate Impetus, Directrix --- .../hexcasting/lang/ru_ru.flatten.json5 | 266 +++++++++--------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 index 2dfc5aaca8..4542efba8a 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 @@ -121,16 +121,16 @@ conjured_block: "Магический Блок", directrix: { - empty: "Empty Directrix", - redstone: "Mason Directrix", - boolean: "Boolean Directrix", + empty: "Пустой Направитель", + redstone: "Направитель Каменщика", + boolean: "Логический Направитель", }, impetus: { - empty: "Empty Impetus", - rightclick: "Toolsmith Impetus", - look: "Fletcher Impetus", - redstone: "Cleric Impetus", + empty: "Пустой Инициатор", + rightclick: "Инициатор Инструментальщика", + look: "Инициатор Лучника", + redstone: "Инициатор Священника", }, akashic_: { @@ -227,11 +227,11 @@ }, "tag.item.hexcasting": { - brainswept_circle_components: "Brainswept Circle Components", - directrices: "Directrices", + brainswept_circle_components: "Компоненты Круга Очистки Разума", + directrices: "Направители", grants_root_advancement: "Grants Rood Advancement", - impeti: "Impeti", - seal_materials: "Seal Materials", + impeti: "Инициаторы", + seal_materials: "Запечатанные материалы", }, "emi.category.hexcasting": { @@ -375,23 +375,23 @@ }, "lore/": { cardamom1: { - "": "Cardamom Steles #1", + "": "Кардамом Стайлз #1", desc: "Письмо Кардамон Стайлз своему отцу, #1", }, cardamom2: { - "": "Cardamom Steles #2", + "": "Кардамом Стайлз #2", desc: "Письмо Кардамон Стайлз своему отцу, #2", }, cardamom3: { - "": "Cardamom Steles #3", + "": "Кардамом Стайлз #3", desc: "Письмо Кардамон Стайлз своему отцу, #3, 1/2", }, cardamom4: { - "": "Cardamom Steles #3 pt2", + "": "Кардамом Стайлз #3 pt2", desc: "Письмо Кардамон Стайлз своему отцу, #3, 2/2", }, cardamom5: { - "": "Cardamom Steles #4", + "": "Кардамом Стайлз #4", desc: "Письмо Кардамон Стайлз своему отцу, #4", }, experiment1: "Wooleye Instance Notes", @@ -472,7 +472,7 @@ circle: { no_exit: "Поток мысли не смог найти выхода в %s", many_exits: "У потока мысли было слишком много выходов в %s", - no_closure: "Поток мысли не сможет вернуться к прежнему impetus на %s", + no_closure: "Поток мысли не сможет вернуться к прежнему Инициатору на %s", }, lens: { @@ -545,8 +545,8 @@ "spellcircle.fail": "Заклинание круга громко трещит", "scroll.dust": "Свиток покрывается аметистовой пылью", "scroll.scribble": "Свиток расписан", - "impetus.fletcher.tick": "Fletcher Impetus кликает", - "impetus.redstone.register": "Cleric Impetus звенит", + "impetus.fletcher.tick": "Инициатор Лучника кликает", + "impetus.redstone.register": "Инициатор Священника звенит", "lore_fragment.read": "Прочтен фрагмент истории", "flight.ambience": "Игрок летит", "flight.finish": "Полет окончился", @@ -585,11 +585,11 @@ }, get_caster: "Отражение Нарцисса", - "entity_pos/eye": "Преобразование глаз", - "entity_pos/foot": "Преобразование ног", - get_entity_look: "Преобразование Взгляда", - get_entity_height: "Преобразование Высот", - get_entity_velocity: "Преобразование Скорости", + "entity_pos/eye": "Преображение глаз", + "entity_pos/foot": "Преображение ног", + get_entity_look: "Преображение Взгляда", + get_entity_height: "Преображение Высот", + get_entity_velocity: "Преображение Скорости", raycast: "Объединение Луча", "raycast/axis": "Объединение Стороны", "raycast/entity": "Объединение Сущности", @@ -644,18 +644,18 @@ rotate_reverse: "Гамбит Поворота II", duplicate: "Разбор Близнецов", over: "Гамбит Старателя", - tuck: "Undertaker's Gambit", + tuck: "Гамбит Гробовщика", "2dup": "Гамбит Дубля", duplicate_n: "Гамбит Близнецов", stack_len: "Отражение Группы", fisherman: "Гамбит Рыбака", "fisherman/copy": "Гамбит Рыбака II", - swizzle: "Swindler's Gambit", + swizzle: "Гамбит Мошенника", - unique: "Uniqueness Purification", - and: "Conjunction Distillation", - or: "Disjunction Distillation", - xor: "Exclusion Distillation", + unique: "Преображение Уникальности", + and: "Объединение Совпадения", + or: "Объединение Дизъюнкции", + xor: "Объединение Исключения", greater: "Объединение Максимум", less: "Объединение Минимум", @@ -690,12 +690,12 @@ coerce_axial: "Преображение к Стороне", read: "Отражение Писаря", - "read/entity": "Преобразование Летописца", - "read/local": "Muninn's Reflection", + "read/entity": "Преображение Летописца", + "read/local": "Отражение Мунин", write: "Гамбит Писаря", "write/entity": "Гамбит Летописца", - "write/local": "Huginn's Gambit", + "write/local": "Гамбит Хугин", readable: "Отражение Ревизора", "readable/entity": "Преображение Ревизора", @@ -752,9 +752,9 @@ strength: "Зенит Зеленого Солнца", }, - flight: "Altiora", - "flight/range": "Anchorite Полет", - "flight/time": "Wayfarer Полет", + flight: "Альтиора", + "flight/range": "Дальность Полета", + "flight/time": "Время Полета", lightning: "Громовержец", summon_rain: "Призвать дождь", @@ -766,7 +766,7 @@ eval: "Гамбит Гермеса", "eval/cc": "Гамбит Ириса", for_each: "Гамбит Тота", - halt: "Гамбит Чарона", + halt: "Гамбит Харона", "interop/": { "gravity/": { @@ -1092,11 +1092,11 @@ the_work: "Работа", brainsweeping: "Об очистке разума", spellcircles: "Круги Заклинаний", - impetus: "Impeti", - directrix: "Directrices", + impetus: "Инициатор", + directrix: "Направитель", akashiclib: "Библиотеки Акаши", - quenching_allays: "Quenching Allays", - fanciful_staves: "Fanciful Staves", + quenching_allays: "Погашенные Тихони", + fanciful_staves: "Красивые Посохи", // and the actions readers_guide: "Как Читать Этот Раздел", @@ -1132,11 +1132,11 @@ zeniths: "Зенит", lore: { - cardamom1: "Cardamom Steles, #1", - cardamom2: "Cardamom Steles, #2", - cardamom3: "Cardamom Steles, #3", - cardamom4: "Cardamom Steles, #4", - cardamom5: "Cardamom Steles, #5", + cardamom1: "Кардамом Стайлз, #1", + cardamom2: "Кардамом Стайлз, #2", + cardamom3: "Кардамом Стайлз, #3", + cardamom4: "Кардамом Стайлз, #4", + cardamom5: "Кардамом Стайлз, #5", experiment1: "Wooleye Instance Notes", experiment2: "Wooleye Interview Logs", inventory: "Журнал восстановления #72", @@ -1156,8 +1156,8 @@ page: { media: { "1": "Мысли - это форма психической энергии, внешняя по отношению к разуму. Все живые существа, думая о чем-либо, вырабатывают незначительное количество Мысли; после того, как мысль закончена, средства массовой информации попадают в окружающую среду.$(br2)Искуство Рунных Заклинаний заключается в манипуляции _мыслями чтобы они выполняли ваши требования.", - "2": "Мысли могут оказывать влияние на другие мысли-- силой и типом влияния можно манипулировать, используя Мысли в виде шаблонов.$(p)Знатоки искусства использовали концентрированный сгусток Мысли на конце палочки: размахивая им в воздухе в определенных конфигурациях, они могли манипулировать достаточным количеством Мысли с достаточной точностью, чтобы влиять на сам мир в форме _Рун.", - "3": "К сожалению, даже полностью разумное существо (предположительно, такое, как я) может генерировать лишь незначительное количество Мысли. Было бы совершенно непрактично пытаться использовать свои собственные силы для использование _Рун.$(br2)Но легенда гласит, что существуют подземные отложения, где Мысли медленно накапливаются, превращаясь в кристаллические формы.$(p)Если бы я только мог найти что-нибудь из этого...", + "2": "Мысли могут оказывать влияние на другие мысли-- силой и типом влияния можно манипулировать, используя Мысли в виде шаблонов.$(p)Знатоки искусства использовали концентрированный сгусток Мысли на конце палочки: размахивая им в воздухе в определенных конфигурациях, они могли манипулировать достаточным количеством Мысли с достаточной точностью, чтобы влиять на сам мир в форме Рун.", + "3": "К сожалению, даже полностью разумное существо (предположительно, такое, как я) может генерировать лишь незначительное количество Мысли. Было бы совершенно непрактично пытаться использовать свои собственные силы для использование Рун.$(br2)Но легенда гласит, что существуют подземные отложения, где Мысли медленно накапливаются, превращаясь в кристаллические формы.$(p)Если бы я только мог найти что-нибудь из этого...", }, geodes: { @@ -1188,13 +1188,13 @@ grid: { "1": "Как правило, я предоставляю свои шаблоны природе с помощью моего $(l:items/staff)$(item)Staff/$. \ Применив $(thing)$(k:use)/$ держа его в руке, передо мной появится шестиугольная сетка из точек. \ - Затем я могу щелкнуть, перетащить от точки к точке и отпустить, чтобы нарисовать узор.$(br2)\ + Затем я могу щелкнуть, перетащить от точки к точке и отпустить, чтобы нарисовать руну.$(br2)\ Как только я отправляю шаблон, он выполняется (смотрите следующую главу).", "2": "Нажатие кнопки $(thing)$(k:escape)/$ сохраняет и закрывает сетку; когда я в следующий раз использую свой посох, все мои руны и йоты по-прежнему будут там.$(br2)\ Если я захочу сбросить свое состояние заклинания, я могу сделать это присев, открывая сетку.", }, "patterns&actions": { - "1": "$(thing)Руны/$ это пути, проложенные по сетке Мысли. Я считаю, что симметрия узоров в шестиугольниках - это то, что дало название моему искусству.$(br2)\ + "1": "$(thing)Руны/$ это пути, проложенные по сетке Мысли. Я считаю, что симметрия рун в шестиугольниках - это то, что дало название моему искусству.$(br2)\ $(thing)Действия/$, между тем, - это то, что $(italic)делают/$ руны.", "2": "Разница подобна разнице между $(italic)словами /$ и их $(italic)значениями/$. \ Любое сочетание букв образует слово, но большинство из них ничего не означают. \ @@ -1205,7 +1205,7 @@ $(li)Манипулируйте собранной информацией, например, находите расстояние между двумя позициями.\ $(li)Произведите какое-нибудь магическое воздействие на мир, например, вызовите молнию или взрыв.$(br)\ Эти последние виды действий называются \"Заклинаниями.\", и, как правило, являются тем, что привлекает людей к искусству.", - "4": "Таким образом, _Заклинания - это последовательность допустимых рун, представленных Природе в определенной последовательности. \ + "4": "Таким образом, Заклинания - это последовательность допустимых рун, представленных Природе в определенной последовательности. \ Природа интерпретирует каждую руну по отдельности и, если понимает, изменяет мир в соответствии с моими прихотями. \ (Или каковы, по её мнению, мои прихоти.)", "5": "Хотя некоторые действия могут быть выполнены легко, некоторые требуют оплаты в виде Мысли. \ @@ -1234,17 +1234,17 @@ // Casting "101": { - "1": "Исполнение рунных заклинаний немного сложный процесс, неудивительно, что это искусство было забыто. Мне придется внимательно перечитать свои записи.$(br2)Я могу начать писать Руну нажав $(k:use) держа в руке $(l:items/staff)$(item)Посох/$ - это приведет к появлению передо мной шестиугольной сетки из точек. Затем я могу щелкать и перетаскивать от точки к точке, чтобы рисовать руны сетки; завершение создания узора приведет к выполнению соответствующего действия (подробнее об этом позже).", + "1": "Исполнение рунных заклинаний немного сложный процесс, неудивительно, что это искусство было забыто. Мне придется внимательно перечитать свои записи.$(br2)Я могу начать писать Руну нажав $(k:use) держа в руке $(l:items/staff)$(item)Посох/$ - это приведет к появлению передо мной шестиугольной сетки из точек. Затем я могу щелкать и перетаскивать от точки к точке, чтобы рисовать руны сетки; завершение создания руны приведет к выполнению соответствующего действия (подробнее об этом позже).", "2": "Как только я нарисую достаточно рун, чтобы произнести заклинание, сетка исчезнет, когда будут выпущены сохраненные мною мысли. Удерживая $(k:sneak) при использовании моего $(l:items/staff)$(item)посоха/$ вы также очистите сетку.$(br2)Итак, как же работают руны? Вкратце:$(italic)Руны/$ выполняют $(italic)Действия/$, которые манипулируют...$(l:casting/stack)$(italic)Стэком/$, который представляет собой список из...$(italic)Йоты/$, которые являются просто единицами информации.", "3": "Во-первых, $(thing)Руны/$. Они важны - это то, что я использую для манипулирования мысли вокруг меня. Определенные паттерны, будучи нарисованными, вызовут выполнение оределённых действий. Действия - это то, что на самом деле творит чудеса; все шаблоны определенным образом влияют на мысли и когда эти влияния в конечном итоге приводят к чему-то полезному, мы называем это действием.$(br2)Мысли могут быть непостоянными: если я нарисую неверную руну, я получу некоторый $(l:casting/influences)$(action)мусор/$ как результат где-нибудь в моем стеке (читайте дальше...)", "4.header": "Вот пример", "4": "Интересно отметить, что $(italic)угол/$ руны похоже, вообще не имеет значения, самое главное это начальная точка руны и градус на который вы поворачиваете линию. Оба этих паттерна выполняют действие, называемое $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$, например.", - "5": "_Заклинание приводится в действие путем последовательного выполнения (допустимых) действий. Каждое действие может выполнять одну из нескольких задач:$(li)Собирать некоторую информацию об окружающей среде, оставляя ее на вершине стека;$(li)манипулировать собранной информацией (например, складывать два числа); или$(li)выполнять какой-либо магический эффект, например вызывать молнию или взрыв. (Эти действия называются \"заклинания\")$(p)Когда я начинаю использовать посох, создается пустой стек. Действия управляют вершиной этого стека.", - "6": "Например, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$ создаст iota представляющую $(italic)меня/$, заклинателя, и добавит ее в начало стека. $(l:patterns/basics#hexcasting:entity_pos/eye)$(action)Преобразование глаз/$ возьмет iota расположенную на вершине стека, если она представляет сущность, и преобразует ее в iota представляющую местоположение этого объекта.$(br2)Таким образом, рисование этих рун в таком порядке привело бы к тому, что в стеке появилась бы iota представляющая мою позицию.", + "5": "Заклинание приводится в действие путем последовательного выполнения (допустимых) действий. Каждое действие может выполнять одну из нескольких задач:$(li)Собирать некоторую информацию об окружающей среде, оставляя ее на вершине стека;$(li)манипулировать собранной информацией (например, складывать два числа); или$(li)выполнять какой-либо магический эффект, например вызывать молнию или взрыв. (Эти действия называются \"заклинания\")$(p)Когда я начинаю использовать посох, создается пустой стек. Действия управляют вершиной этого стека.", + "6": "Например, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$ создаст йота представляющую $(italic)меня/$, заклинателя, и добавит ее в начало стека. $(l:patterns/basics#hexcasting:entity_pos/eye)$(action)Преображение глаз/$ возьмет йота расположенную на вершине стека, если она представляет сущность, и преобразует ее в йота представляющую местоположение этого объекта.$(br2)Таким образом, рисование этих рун в таком порядке привело бы к тому, что в стеке появилась бы йота представляющая мою позицию.", "7": "$(thing)Йоты/$ может представлять вещи, такие как я сам или мое положение, но есть несколько других типов, с которыми я могу манипулировать с помощью $(thing)Действия/$. Вот подробный список:$(li)Числа (которые некоторые легенды называют \"double\");$(li)Векторы, коллекция из трех чисел, представляющих положение, движение или направление в мире;$(li) Логические значения или \"bools\" в сокращении, представляющие абстрактное Истина или Ложь,", - "8": "$(li)Сущности, подобные мне, курицам и вагонеткам;$(li)Influences, особые типы иоты, которые кажутся представлять абстрактные идеи;$(li)Сами руны, используемые для создания магических предметов и поистине поразительных подвигов, таких как $(italic)заклинания, которые произносят другие заклинания/$; и$(li)Список нескольких из вышеперечисленного, собранных в одну iota.", - "9": "Конечно, бесплатный сыр только в мышеловке. Все заклинания и определенные другие действия требуют Мысли в качестве оплаты.$(br2)Как я могу понять, _Рунные заклинания - это нечто вроде плана действий, представленного Природе - в этой аналогии Мысли используются для убеждения, чтобы Природа приняла план и осуществила его.", - "10": "Помимо этого, кажется, что никто не проводил серьезных исследований о том, насколько $(italic)много/$ стоит конкретный кусок $(l:items/amethyst)$(item)аметиста/$. По моим лучшим оценкам, $(l:items/amethyst)$(item)Осколок Аметиста/$ стоит примерно пять кусков $(l:items/amethyst)$(item)Аметистовой Пыли/$, а $(l:items/amethyst)$(item)Заряженный Кристалл Аметиста/$ - примерно десять.$(br2)Странно, что кажется, никакая другая форма $(l:items/amethyst)$(item)аметиста/$ не подходит для использования при создании _Рунных заклинаний. Я подозреваю, что целые блоки или кристаллы слишком прочны, чтобы легко распутываться в Мысли.", + "8": "$(li)Сущности, подобные мне, курицам и вагонеткам;$(li)Influences, особые типы иоты, которые кажутся представлять абстрактные идеи;$(li)Сами руны, используемые для создания магических предметов и поистине поразительных подвигов, таких как $(italic)заклинания, которые произносят другие заклинания/$; и$(li)Список нескольких из вышеперечисленного, собранных в одну йота.", + "9": "Конечно, бесплатный сыр только в мышеловке. Все заклинания и определенные другие действия требуют Мысли в качестве оплаты.$(br2)Как я могу понять, Рунные заклинания - это нечто вроде плана действий, представленного Природе - в этой аналогии Мысли используются для убеждения, чтобы Природа приняла план и осуществила его.", + "10": "Помимо этого, кажется, что никто не проводил серьезных исследований о том, насколько $(italic)много/$ стоит конкретный кусок $(l:items/amethyst)$(item)аметиста/$. По моим лучшим оценкам, $(l:items/amethyst)$(item)Осколок Аметиста/$ стоит примерно пять кусков $(l:items/amethyst)$(item)Аметистовой Пыли/$, а $(l:items/amethyst)$(item)Заряженный Кристалл Аметиста/$ - примерно десять.$(br2)Странно, что кажется, никакая другая форма $(l:items/amethyst)$(item)аметиста/$ не подходит для использования при создании Рунных заклинаний. Я подозреваю, что целые блоки или кристаллы слишком прочны, чтобы легко распутываться в Мысли.", "11": "Также стоит отметить, что каждое действие немедленно потребляет необходимые Мысли, а не все сразу, когда Заклинание завершается. Кроме того, действие всегда потребляет целые предметы - действие, которое требует только столько Мысли, сколько стоит одна $(l:items/amethyst)$(item)Аметистовая Пыль/$, потребует целый $(l:items/amethyst)$(item)Заряженный Аметистовый Кристалл/$, если это единственное, что есть в моем инвентаре.$(br2)Таким образом, может быть хорошей идеей взять пыль для колдовства тоже - не тратьте зря, не будет желания...", "12": "Я также должен быть осторожен, чтобы убедиться, что у меня действительно достаточно Аметиста в инвентаре - некоторые старые тексты говорят, что Природа с удовольствием использует разум в качестве оплаты. Они описывают это чувство как ужасное, но странно эйфорическое, \"[...] искрящееся растворение в свет и энергию...\" Возможно, поэтому все старые практикующие искусство сходили с ума. Я не могу представить, каково $(italic)сжигать кусочки своего разума ради силы/$.", "13": "Но кажется что-то не так, в ходе моих экспериментов мне ещё не доводилось достить такого. Когда у меня кончается аметист заклинание просто обрывается! Будто бы некоторый барьер останавливает меня, спасает.$(br2)Мне интересно разгадать эту тайну, пока что я защищёен от этого.", @@ -1262,12 +1262,12 @@ }, mishaps: { - "1": "К сожалению, я не (пока что) совершенное существо. Иногда я допускаю ошибки в своих исследованиях и произношении Заклинания; например, неправильное нарисование узора или попытка вызвать действие с неправильными иотами. И Природа обычно не смотрит благосклонно на мои ошибки - вызывая то, что называется $(italic)несчастье/$.", - "2": "Узор, вызывающий несчастье, будет светиться красным на моей сетке. В зависимости от типа ошибки, я также могу ожидать определенного вредного эффекта и обильного разбрызгивания красного и разноцветных искр, поскольку неправильно обработанная Мысли сворачивается в свет определенного цвета.", + "1": "К сожалению, я не (пока что) совершенное существо. Иногда я допускаю ошибки в своих исследованиях и произношении Заклинания; например, неправильное нарисование руны или попытка вызвать действие с неправильными иотами. И Природа обычно не смотрит благосклонно на мои ошибки - вызывая то, что называется $(italic)несчастье/$.", + "2": "Некорректная руна будет светиться красным на моей сетке. В зависимости от типа ошибки, я также могу ожидать определенного вредного эффекта и обильного разбрызгивания красного и разноцветных искр, поскольку неправильно обработанная Мысли сворачивается в свет определенного цвета.", "3": "К счастью, хотя плохие последствия несчастий, безусловно, $(italic)раздражающие/$, ни одно из них не является особенно разрушительным в долгосрочной перспективе. Нечего лучше делать, чем смахнуть пыль с себя и попробовать снова... но все равно я должен стремиться к лучшему.$(br2)Ниже приведен список несчастий, который я составил.", "invalid_pattern.title": "Некорретная руна", - invalid_pattern: "Нарисованный узор не связан ни с одним действием.$(br2)Вызывает желтые искры, и $(l:casting/influences)$(action)Мусор/$ будет помещен в верхнюю часть моего стека.", + invalid_pattern: "Руна не связана ни с одним действием.$(br2)Вызывает желтые искры, и $(l:casting/influences)$(action)Мусор/$ будет помещен в верхнюю часть моего стека.", "not_enough_iotas.title": "Недостаточно Йот", not_enough_iotas: "Для действия требовалось больше йот, чем было в стеке.$(br2)Вызывает светло-серые искры, и столько $(l:casting/influences)$(action)Мусора/$, сколько потребовалось бы для заполнения количества аргументов, будет добавлено.", @@ -1313,13 +1313,13 @@ "1": "Стек $(thing)Стэк/$, также известный как \"LIFO\" (last in first out), является концепцией, заимствованной из информатики. Вкратце, это коллекция вещей, спроектированная так, что вы можете взаимодействовать только с последней использованной вещью.$(br2)Представьте стопку тарелок, где новые тарелки добавляются сверху: если вы хотите взаимодействовать с тарелкой посередине стопки, вам придется удалить тарелки сверху, чтобы добраться до нее.", "2": "Поскольку стек настолько прост, есть только несколько вещей, которые вы можете с ним сделать:$(li)$(italic)Добавление чего-то в него/$, формально известное как push,$(li)$(italic)Удаление последнего добавленного элемента/$, известное как pop, или$(li)$(italic)Изучение или изменение последнего добавленного элемента/$, известное как peek.$(br)Мы называем последний добавленный элемент \"вершиной\" стека, в соответствии с аналогией с обеденной тарелкой.$(p)В качестве примера, если мы добавим 1 в стек, затем добавим 2, затем выполним pop, вершина стека теперь равна 1.", "3": "Действия (в большинстве случаев) ограничены взаимодействием со стеком такими способами. Они будут извлекать некоторые иоты, которые их интересуют (известные как \"аргументы\" или \"параметры\"), обрабатывать их и затем добавлять некоторое количество результатов.$(br2)Конечно, некоторые действия (например, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$) могут не извлекать аргументы, и некоторые действия (особенно заклинания) могут ничего не добавлять после этого.", - "4": "Еще более сложные действия могут быть выражены в терминах добавления, удаления и просмотра. Например, $(l:patterns/stackmanip#hexcasting:swap)$(action)Jester's Gambit/$ меняет местами два верхних элемента стека. Это можно рассматривать как извлечение двух элементов и добавление их в обратном порядке. Для другого примера, $(l:patterns/stackmanip#hexcasting:duplicate)$(action)Gemini Decomposition/$ дублирует вершину стека - другими словами, она просматривает стек и добавляет копию найденного элемента.", + "4": "Еще более сложные действия могут быть выражены в терминах добавления, удаления и просмотра. Например, $(l:patterns/stackmanip#hexcasting:swap)$(action)Гамбит Шута/$ меняет местами два верхних элемента стека. Это можно рассматривать как извлечение двух элементов и добавление их в обратном порядке. Для другого примера, $(l:patterns/stackmanip#hexcasting:duplicate)$(action)Разбор Близнецов/$ дублирует вершину стека - другими словами, она просматривает стек и добавляет копию найденного элемента.", }, naming: { "1": "Названия, данные действиям древними, были, безусловно, странными, но я думаю, что в них есть определенная логика.$(br2)Кажется, есть определенные группы действий с общими названиями, названными по числу иот, которые они удаляют из стека и добавляют в стек.", "2": "$(li) $(thing)Отражение/$ не удаляет ничего и добавляет один иот.$(li) $(thing)Преображение/$ удаляет один иот и добавляет один.$(li) $(thing)Объединение/$ удаляет два и добавляет один.$(li) $(thing)Возвышение/$ удаляет три или более и добавляет один.$(li) $(thing)Разбор/$ удаляет один аргумент и добавляет два.$(li) $(thing)Распад/$ удаляет один и добавляет три или более.$(li) Наконец, $(thing)Гамбит/$ добавляет или удаляет другое количество (или перестраивает стек другим образом).", - "3": "Похоже, что заклинания освобождены от этой номенклатуры и в основном названы по тому, что они делают - в конце концов, зачем называть его $(action)Demoman's Gambit/$, когда можно просто сказать $(l:patterns/spells/basic#hexcasting:explode)$(action)Explosion/$?", + "3": "Похоже, что заклинания освобождены от этой номенклатуры и в основном названы по тому, что они делают - в конце концов, зачем называть его $(action)Гамбит Демона/$, когда можно просто сказать $(l:patterns/spells/basic#hexcasting:explode)$(action)Взрыв/$?", }, influences: { @@ -1337,15 +1337,15 @@ "no_circle.title": "Отсутствие круга заклинаний", no_circle: "Попытка использовать руну, треубующую круг заклинаний вручную.$(br2)Вызывает светло-синие искры и выбрасывает мой инвентарь на землю.", - "no_record.title": "Отсутствие Akashic Record", - no_record: "Попытка получить доступ к $(l:greatwork/akashiclib)$(item)Akashic Record/$ в месте, где ее нет.$(br2)Вызывает фиолетовые искры и уносит часть моего опыта.", + "no_record.title": "Отсутствие Записи Акаши", + no_record: "Попытка получить доступ к $(l:greatwork/akashiclib)$(item)Записи Акаши/$ в месте, где ее нет.$(br2)Вызывает фиолетовые искры и уносит часть моего опыта.", }, // Items amethyst: { - dust: "Похоже, что я найду три различные формы аметиста, когда разбиваю кристалл внутри геоды. Самой маленькой деноминацией кажется небольшая куча мерцающей пыли, стоящая относительно небольшую сумму Мысли.", + dust: "Похоже, что я найду три различные формы аметиста, когда разбиваю кристалл внутри жеоды. Самой маленькой деноминацией кажется небольшая куча мерцающей пыли, стоящая относительно небольшую сумму Мысли.", shard: "Второй - целый осколок аметиста, с которым не-маги могут быть знакомы. Внутри него примерно столько же Мысли, сколько в пяти $(l:items/amethyst)$(item)Пыли аметиста/$.", crystal: "Наконец, иногда я найду большой кристалл, искрящийся энергией. Внутри него примерно столько же Мысли, сколько в десяти единицах $(l:items/amethyst)$(item)Пыли аметиста/$ (или двух $(l:items/amethyst)$(item)Осколков аметиста/$).", lore: "$(italic)Старик вздохнул и поднял руку к огню. Он разблокировал часть своего сознания, где хранились воспоминания о окружающих их горах. Он извлек энергии из этих земель, как научился делать в городе Терисия с Драфной, Хуркилем, архимандритом и другими магами из Белых башен. Он сконцентрировался, и пламя извивалось, поднимаясь из поленьев, скручиваясь на себя, пока наконец не образовало мягкую улыбку./$", @@ -1365,41 +1365,41 @@ thought_knot: { "1": "Забывчивые часто завязывают кусок нити вокруг пальца, чтобы им помнить что-то важное. Я верю, что эта идея может быть полезной в моем искусстве. Особенно завязанный кусок нити должен быть способен устойчиво удерживать одну иоту, независимо от моего стека.$(br2)Я назову свое изобретение $(item)Мысленный узел/$.", - "2": "При создании он не хранит никакой иоты. Использование $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$, удерживая $(item)Мысленный узел/$ в другой руке, удалит верх стека и сохранит его в $(item)Мысленный узел/$. Использование $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$ скопирует любую иоту из $(item)Мысленный узел/$ и добавит ее в стек.$(br2)Как только $(item)Мысленный узел/$ будет записан, нить неразрывно запутывается; иоту можно прочитать любое количество раз, но нет способа стереть или перезаписать ее. К счастью, они не дорогие.", - "3": "Кроме того, если я сохраню сущность в $(item)Мысленный узел/$ и попытаюсь вспомнить ее после того, как ссылочная сущность умерла или исчезла, $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$ добавит $(l:casting/influences)$(thing)Null/$ в стек вместо нее.", + "2": "При создании он не хранит никакой иоты. Использование $(l:patterns/readwrite#hexcasting:write)$(action)Гамбит Писаря/$, удерживая $(item)Мысленный узел/$ в другой руке, удалит верх стека и сохранит его в $(item)Мысленный узел/$. Использование $(l:patterns/readwrite#hexcasting:read)$(action)Отражение Писаря/$ скопирует любую иоту из $(item)Мысленный узел/$ и добавит ее в стек.$(br2)Как только $(item)Мысленный узел/$ будет записан, нить неразрывно запутывается; иоту можно прочитать любое количество раз, но нет способа стереть или перезаписать ее. К счастью, они не дорогие.", + "3": "Кроме того, если я сохраню сущность в $(item)Мысленный узел/$ и попытаюсь вспомнить ее после того, как ссылочная сущность умерла или исчезла, $(l:patterns/readwrite#hexcasting:read)$(action)Отражение Писаря/$ добавит $(l:casting/influences)$(thing)Ничто/$ в стек вместо нее.", "crafting.desc": "$(italic)Как бы вы почувствовали, если бы кто-то увидел вас с табличкой, на которой написано: \"Я красив и привлекателен\"?/$", }, focus: { - "1": "Талисман $(item)Focus/$ похож на $(l:items/thought_knot)$(item)Мысленный узел/$, поскольку в него можно записывать или читать иоту. Однако преимущество Талисмана в том, что он $(italic)повторно используемый/$. Если я допущу ошибку в иоте, записанной в $(item)Focus/$, я могу просто снова использовать $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ и перезаписать иоту внутри.", - "2": "Если я хочу защитить $(l:items/focus)$(item)Талисман/$ от случайного перезаписывания, я могу запечатать его воском, создав его с $(item)Медовый сот/$. Попытка использовать $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ на запечатанном Талисмане завершится неудачей.$(br2)$(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ удалит эту печать вместе с содержимым.", + "1": "Талисман $(item)Focus/$ похож на $(l:items/thought_knot)$(item)Мысленный узел/$, поскольку в него можно записывать или читать иоту. Однако преимущество Талисмана в том, что он $(italic)повторно используемый/$. Если я допущу ошибку в иоте, записанной в $(item)Focus/$, я могу просто снова использовать $(l:patterns/readwrite#hexcasting:write)$(action)Гамбит Писаря/$ и перезаписать иоту внутри.", + "2": "Если я хочу защитить $(l:items/focus)$(item)Талисман/$ от случайного перезаписывания, я могу запечатать его воском, создав его с $(item)Медовый сот/$. Попытка использовать $(l:patterns/readwrite#hexcasting:write)$(action)Гамбит Писаря/$ на запечатанном Талисмане завершится неудачей.$(br2)$(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Очистить предмет/$ удалит эту печать вместе с содержимым.", "3": "Действительно, единственное преимущество моих $(l:items/thought_knot)$(item)Мысленный узел/$ над $(item)Талисманами/$ заключается в том, что $(item)Талисманы/$ дороже в производстве. Мои исследования показывают, что ранние практики искусства использовали исключительно $(item)Талисманы/$, а $(l:items/thought_knot)$(item)Мысленный узел/$ был моим оригинальным изобретением.$(br2)Кто бы ни были те древние люди, они, должно быть, были очень процветающими.", "crafting.desc": "$(italic)Ядовитые яблоки, ядовитые черви./$", }, abacus: { - "1": "Хотя существуют $(l:patterns/numbers)$(action)шаблоны для рисования чисел/$, я нахожу их ... громоздкими, мягко говоря.$(br2)К счастью, старые мастера моего искусства изобрели умное устройство под названием $(l:items/abacus)$(item)Рунные счеты/$ для предоставления чисел для моего использования. Я просто устанавливаю число на то, что мне нужно, затем читаю значение, используя $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$, так же как я бы прочитал $(l:items/thought_knot)$(item)Мысленный узел/$ или $(l:items/focus)$(item)Талисман/$.", + "1": "Хотя существуют $(l:patterns/numbers)$(action)шаблоны для рисования чисел/$, я нахожу их ... громоздкими, мягко говоря.$(br2)К счастью, старые мастера моего искусства изобрели умное устройство под названием $(l:items/abacus)$(item)Рунные счеты/$ для предоставления чисел для моего использования. Я просто устанавливаю число на то, что мне нужно, затем читаю значение, используя $(l:patterns/readwrite#hexcasting:read)$(action)Отражение Писаря/$, так же как я бы прочитал $(l:items/thought_knot)$(item)Мысленный узел/$ или $(l:items/focus)$(item)Талисман/$.", "2": "Для работы с ним я просто удерживаю его, крадусь и прокручиваю. Если он в моей основной руке, число будет увеличиваться или уменьшаться на 1, или на 10, если я также удерживаю Control/Command. Если он в моей второй руке, число будет увеличиваться или уменьшаться на 0.1, или на 0.001, если я также удерживаю Control/Command.$(br2)Я могу встряхнуть счёты, чтобы сбросить их на ноль, сделав крадущийся правый клик.", "crafting.desc": "$(italic)Математика? Это для умников!/$", }, spellbook: { "1": "$(l:items/spellbook)$(item)Книга заклинаний/$ - это вершина моего искусства - она действует как целая библиотека $(l:items/focus)$(item)Талисманов/$. До $(thing)шестидесяти четырех/$ из них, чтобы быть точным.$(br2)Каждая страница может содержать одну иоту, и я могу выбрать активную страницу (страницу, на которую сохраняются и копируются иоты), удерживая ее и прокручивая, или просто удерживая ее во второй руке и прокручивая во время использования _Хекса.", - "2": "Как и $(l:items/focus)$(item)Талисман/$, существует простой способ предотвратить случайное перезаписывание. Создание ее с $(item)Медовые соты/$ запечатают страницу, предотвращая $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ от изменения ее содержимого. Также как и $(l:items/focus)$(item)Талисман/$, использование $(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ удалит лак и содержимое страницы.$(br2)Я также могу назвать каждую страницу индивидуально на наковальне. Название изменит только имя выбранной в данный момент страницы для удобного просмотра.", + "2": "Как и $(l:items/focus)$(item)Талисман/$, существует простой способ предотвратить случайное перезаписывание. Создание ее с $(item)Медовые соты/$ запечатают страницу, предотвращая $(l:patterns/readwrite#hexcasting:write)$(action)Гамбит Писаря/$ от изменения ее содержимого. Также как и $(l:items/focus)$(item)Талисман/$, использование $(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ удалит лак и содержимое страницы.$(br2)Я также могу назвать каждую страницу индивидуально на наковальне. Название изменит только имя выбранной в данный момент страницы для удобного просмотра.", "crafting.desc": "$(italic)Волшебники любят слова. Большинство из них много читают, и действительно одним из сильных признаков потенциального волшебника является неспособность заснуть без предварительного прочтения чего-либо.", }, scroll: { - "1": "$(l:items/scroll)$(item)Свиток/$ - удобный способ делиться узором с другими. Я могу скопировать узор на него с помощью $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$, после чего он будет отображаться в подсказке.$(br2)Я также могу разместить их на стене как украшение или поучение, как картину, в размерах от 1x1 до 3x3 блоков. Использование $(l:items/amethyst)$(item)Пыли аметиста/$ на таком свитке заставит его отображать порядок линий.", + "1": "$(l:items/scroll)$(item)Свиток/$ - удобный способ делиться руной с другими. Я могу скопировать руну на него с помощью $(l:patterns/readwrite#hexcasting:write)$(action)Гамбит Писаря/$, после чего он будет отображаться в подсказке.$(br2)Я также могу разместить их на стене как украшение или поучение, как картину, в размерах от 1x1 до 3x3 блоков. Использование $(l:items/amethyst)$(item)Пыли аметиста/$ на таком свитке заставит его отображать порядок линий.", "2": "Кроме того, я также могу найти так называемые $(l:items/scroll)$(item)Древние свитки/$ в подземельях и крепостях мира. Они содержат порядок линий $(thing)Великих заклинаний/$, могущественных магий, о которых ходят слухи, будто они слишком мощны для рук и умов смертных...$(br2)Если эти \"смертные\" не могли их произносить, я не уверен, что они заслуживают знать их.", "crafting.desc": "$(italic)Я пишу на чистом белом пергаменте острым пером и кровью моих учеников, предвидя их секреты./$", }, slate: { - "1": "$(l:items/slate)$(item)Скрижали/$ похожи на $(l:items/scroll)$(item)Свитки/$; Я могу скопировать на них узор и разместить их в мире, чтобы отобразить узор.$(br2)Однако я читал смутные рассказы о великих собраниях $(l:items/slate)$(item)Скрижалей/$, используемых для создания $(l:greatwork/spellcircles)$(thing)великих ритуалов/$ более мощных, чем может обработать $(l:items/staff)$(item)Посох/$.", + "1": "$(l:items/slate)$(item)Скрижали/$ похожи на $(l:items/scroll)$(item)Свитки/$; Я могу скопировать на них руну и разместить их в мире, чтобы отобразить руну.$(br2)Однако я читал смутные рассказы о великих собраниях $(l:items/slate)$(item)Скрижалей/$, используемых для создания $(l:greatwork/spellcircles)$(thing)великих ритуалов/$ более мощных, чем может обработать $(l:items/staff)$(item)Посох/$.", "2": "Возможно, эти знания будут раскрыты мне со временем. Но пока, я полагаю, что они служат живописным элементом декора.$(br2)По крайней мере, их можно разместить на любой стороне блока, в отличие от $(l:items/scroll)$(item)Свитков/$.", "crafting.desc": "$(italic)Это буква \"а.\" Выучи ее./$", - "3": "Я также знаю о других типах $(l:items/slate)$(item)Скрижалей/$, скрижалях, которые не содержат узоров, но кажется, что они инкрустированы другими... странными... странностями. Мне больно думать о них, словно мои мысли изгибаются вокруг их дизайнов, следуя их путям, изгибаясь и переплетаясь сквозь их лабиринтные глубины, через и через и через канализируемые и обрабатываемые и--$(br2)... Я чуть не потерял себя. Может быть, стоит отложить изучение их.", + "3": "Я также знаю о других типах $(l:items/slate)$(item)Скрижалей/$, скрижалях, которые не содержат рун, но кажется, что они инкрустированы другими... странными... странностями. Мне больно думать о них, словно мои мысли изгибаются вокруг их дизайнов, следуя их путям, изгибаясь и переплетаясь сквозь их лабиринтные глубины, через и через и через канализируемые и обрабатываемые и--$(br2)... Я чуть не потерял себя. Может быть, стоит отложить изучение их.", }, // roll credits @@ -1413,7 +1413,7 @@ }, phials: { - "1": "Меня довольно ... раздражает, как Природа отказывается давать мне сдачу за мою работу. Если у меня под рукой только $(l:items/amethyst)$(item)Заряженный Аметист/$, даже самое маленькое $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Purification/$ потребует весь кристалл, растрачивая оставшееся Мысли.$(br2)К счастью, кажется, я нашел способ отчасти смягчить эту проблему.", + "1": "Меня довольно ... раздражает, как Природа отказывается давать мне сдачу за мою работу. Если у меня под рукой только $(l:items/amethyst)$(item)Заряженный Аметист/$, даже самое маленькое $(l:patterns/basics#hexcasting:raycast)$(action)Преображение Луча/$ потребует весь кристалл, растрачивая оставшееся Мысли.$(br2)К счастью, кажется, я нашел способ отчасти смягчить эту проблему.", "2": "Я нашел старые свитки, описывающие $(item)Стеклянную Бутылку/$, пропитанную Мысли. При колдовстве мои заклинания тогда бы забирать Мысли из флакона. Жидкая форма Мысли позволяла бы мне брать сдачу, так сказать; ничего не было бы потеряно. Это довольно похоже на внутреннюю батарею $(l:items/hexcasting)$(item)Талисмана/$, или что-то подобное; я даже могу $(l:patterns/spells/hexcasting#hexcasting:recharge)$(action)Recharge/$ их тем же способом.", "3": "К сожалению, искусство фактически $(italic)создания/$ этих вещей, кажется, было утрачено со временем. Я нашел $(l:patterns/great_spells/make_battery#hexcasting:craft/battery)$(thing)намек на использованный шаблон для его создания/$, но техника упорно ускользает, и мне не удается сделать это успешно. Я подозреваю, что разберусь с этим с помощью изучения и практики. Пока что я просто буду справляться с растраченным Мысли...$(br2)Но я не буду удовлетворяться этим навсегда.", desc: "$(italic)Выпей молоко./$", @@ -1430,7 +1430,7 @@ }, edified: { - "1": "Мысли, проникшие в саженец с помощью $(l:patterns/spells/blockworks#hexcasting:edify)$(action)Созидать Саженец/$, создают то, что называется $(l:items/edified)$(thing)Дерево Созидания/$. Они обычно высокие и острые, с бороздчатой корой и древесиной, растущей в странном спиральном узоре. Их листья имеют три красивых цвета.", + "1": "Мысли, наполнившие саженец с помощью $(l:patterns/spells/blockworks#hexcasting:edify)$(action)Созидать Саженец/$, создают то, что называется $(l:items/edified)$(thing)Дерево Созидания/$. Они обычно высокие и острые, с бороздчатой корой и древесиной, растущей в странном спиральном узоре. Их листья имеют три красивых цвета.", "2": "Я предполагал бы, что древесина имела бы какие-то свойства, относящиеся к Рунным заклинаниям. Но, если они есть, я не могу их найти. На все виды и цели кажется, что это просто древесина, хотя и очень странного цвета.$(br2)Предполагаю, что пока я буду использовать её для украшения; из них можно создать полный набор стандартных древесных блоков.$(br2)Конечно, я могу также снять с них кору топором.", "crafting.desc": "$(italic)Их гладкие стволы, с белой корой, создавали впечатление огромных колонн, несущих вес огромной листвы, полной тени и молчания./$", }, @@ -1464,43 +1464,43 @@ spellcircles: { "1": "Я ЗНАЮ, для чего предназначены $(l:items/slate)$(item)скрижали/$. Великие собрания, утраченные временем. Руны, вырезанные на них, могут быть активированы последовательно, автоматически. Мысль и сила отскакивают через них, один за другим, один за другим, через и через и ЧЕРЕЗ И -- я не должен, я не должен, я должен знать лучше, чем думать таким образом.", - "2": "Для начала ритуала мне нужен $(l:greatwork/impetus)$(item)Impetus/$, чтобы создать самоподдерживающуюся волну Мысли. Эта волна движется по дорожке из $(l:items/slate)$(item)скрижалей/$ или других блоков, подходящих для энергий, один за другим, собирая все руны, которые находит. Когда волна возвращается к $(l:greatwork/impetus)$(item)Impetus/$, все встреченные руны произносятся по порядку.$(br2)Направление выхода Мысли из любого блока ДОЛЖНО быть однозначным, иначе произнесение не удастся(у потока Мысли должен быть лишь один путь).", + "2": "Для начала ритуала мне нужен $(l:greatwork/impetus)$(item)Инициатор/$, чтобы создать самоподдерживающуюся волну Мысли. Эта волна движется по дорожке из $(l:items/slate)$(item)скрижалей/$ или других блоков, подходящих для энергий, один за другим, собирая все руны, которые находит. Когда волна возвращается к $(l:greatwork/impetus)$(item)Инициатору/$, все встреченные руны произносятся по порядку.$(br2)Направление выхода Мысли из любого блока ДОЛЖНО быть однозначным, иначе произнесение не удастся(у потока Мысли должен быть лишь один путь).", "3": "В результате контур заклинания \"круг\" может быть любой закрытой формы, вогнутой или выпуклой, и может быть направлен в любом направлении. Фактически, с применением определенных других блоков можно создать заклинательный круг, охватывающий все три измерения. Я сомневаюсь, что такая странность имеет много применения, но мне нужно немного пустой легкости, чтобы побудить мой грубый разум продолжать мою работу.", - "4": "Чудо чудес, круг не извлекает Мысли ни из моего инвентаря, ни из моего разума. Вместо этого кристаллизованные осколки Мысли должны быть предоставлены $(l:greatwork/impetus)$(item)Impetus/$ через воронку или любым други образом.$(br2)Применение $(l:items/lens)$(item)Scrying Lens/$ покажет, сколько Мысли находится в $(l:greatwork/impetus)$(item)Impetus/$, в единицах пыли.", + "4": "Чудо чудес, круг не извлекает Мысли ни из моего инвентаря, ни из моего разума. Вместо этого кристаллизованные осколки Мысли должны быть предоставлены $(l:greatwork/impetus)$(item)Инициатору/$ через воронку или любым други образом.$(br2)Применение $(l:items/lens)$(item)Линзы Прозрения/$ покажет, сколько Мысли находится в $(l:greatwork/impetus)$(item)Инициаторе/$, в единицах пыли.", "5": "Однако заклинание, произнесенное из круга, имеет одно крупное ограничение: оно не способно воздействовать на что-либо за пределами границ круга. То есть оно не может взаимодействовать с чем-либо за пределами кубоида минимального размера, включающего каждый блок, составляющий его (поэтому вогнутый заклинательный круг все равно может воздействовать на вещи в вогнутости).", "6": "Существует также ограничение на количество блоков, через которые может пройти волна, прежде чем она распадется, но оно достаточно большое, и я сомневаюсь, что у меня возникнут проблемы.$(br2)С другой стороны, есть действия, которые могут быть произнесены только из круга. К счастью, ни одно из них не является заклинанием; все они, кажется, имеют дело с компонентами самого круга. Мои заметки на эту тему $(l:patterns/circle)здесь/$.", - "7": "Я также нашел набросок заклинательного круга, использованного древними, зарытый в моих заметках. На этой странице мои (признаюсь, плохие) копии.$(br2)Руны там должны были быть выполнены против часовой стрелки, начиная с $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$ и заканчивая $(l:patterns/great_spells/teleport#hexcasting:teleport/great)$(action)Greater Teleport/$.", + "7": "Я также нашел набросок заклинательного круга, использованного древними, зарытый в моих заметках. На этой странице мои (признаюсь, плохие) копии.$(br2)Руны там должны были быть выполнены против часовой стрелки, начиная с $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$ и заканчивая $(l:patterns/great_spells/teleport#hexcasting:teleport/great)$(action)Великим Перемещением/$.", "teleport_circle.title": "Круг Телепортации", }, impetus: { - "1": "Флуктуация Мысли, необходимая для активации заклинательного круга, сложна. Даже смертный с самыми острыми глазами и самыми устойчивыми руками не смог бы выступать в роли $(l:greatwork/impetus)$(item)Impetus/$ и вплести Мысли в самоподдерживающийся ороборос, необходимый.$(br2)Проблема в том, что разум слишком полон другого бесполезного $(italics)мусора/$.", - "2": "На ... метафизическом уровне - я должен быть осторожен с этими мыслями, я не могу потерять себя, я стал слишком ценным - движение Мысли двигает разум, и разум должен быть движущимся для того, чтобы процесс работал. Но разум просто слишком $(italic)тяжел/$ от других мыслей, чтобы двигаться достаточно ловко.$(br2)Это похоже на мастера, пытающегося починить часы, нося перчатки.", + "1": "Флуктуация Мысли, необходимая для активации заклинательного круга, сложна. Даже смертный с самыми острыми глазами и самыми устойчивыми руками не смог бы выступать в роли $(l:greatwork/impetus)$(item)Инициатор/$ и вплести Мысли в самоподдерживающегося уробороса, необходимого для исполнения.$(br2)Проблема в том, что разум слишком полон другого бесполезного $(italics)мусора/$.", + "2": "На ... метафизическом уровне - я должен быть осторожен с этими мыслями, я не могу потерять себя, я стал слишком ценным - движение Мысли двигают разум, и разум должен быть движущимся для того, чтобы процесс работал. Но разум просто слишком $(italic)тяжел/$ от других мыслей, чтобы двигаться достаточно ловко.$(br2)Это похоже на мастера, пытающегося починить часы, нося перчатки.", "3": "Существует несколько решений этой загадки: через медитативные техники можно научиться очищать разум, хотя я не уверен, что разум, достаточно свободный для активации круга, может сосредоточиться достаточно сильно, чтобы выполнить движения.$(br2)Некоторые неприятные соединения могут создать аналогичный эффект, но я ничего о них не знаю и не планирую узнавать. Я не должен полагаться на химические вещества моего мозга.", - "4": "Таким образом, решение, к которому я стремлюсь, - это специализировать разум. Освободить его от тирании нервов, обрезать все выходы, кроме тонких ветвей Мысли-манипулирующих аппаратов, опечатать все входы, кроме сигнала начать свою работу.$(br2)Процесс $(l:greatwork/brainsweeping)$(action)mindflaying/$, с которым я теперь знаком, отлично подойдет; разум жителя достаточно сложен для выполнения работы, но не настолько сложен, чтобы сопротивляться его реформации.", + "4": "Таким образом, решение, к которому я стремлюсь, - это специализировать разум. Освободить его от тирании нервов, обрезать все выходы, кроме тонких ветвей Мысли-манипулирующих аппаратов, опечатать все входы, кроме сигнала начать свою работу.$(br2)Процесс $(l:greatwork/brainsweeping)$(action)Очистки Разума/$, с которым я теперь знаком, отлично подойдет; разум жителя достаточно сложен для выполнения работы, но не настолько сложен, чтобы сопротивляться его реформации.", - empty_impetus: "Сначала колыбель. Хотя она не работает как $(l:greatwork/impetus)$(item)Impetus/$, поток Мысли в круге будет выходить только с той стороны, указанной стрелками. Это позволяет мне изменить плоскость, по которой движется волна, например.", - impetus_rightclick: "Затем, чтобы транспонировать разум. Жители различных профессий предоставят различные условия активации для полученного $(l:greatwork/impetus)$(item)Impetus/$. $(l:greatwork/impetus)$(item)Toolsmith Impetus/$ активируется простым $(k:use).", + empty_impetus: "Сначала колыбель. Хотя она не работает как $(l:greatwork/impetus)$(item)Инициатор/$, поток Мысли в круге будет выходить только с той стороны, указанной стрелками. Это позволяет мне изменить плоскость, по которой движется волна, например.", + impetus_rightclick: "Затем, чтобы транспонировать разум. Жители различных профессий предоставят различные условия активации для полученного $(l:greatwork/impetus)$(item)Инициаора/$. $(l:greatwork/impetus)$(item)Инициатор Инструментальщки/$ активируется простым $(k:use).", impetus_storedplayer: { - "1": "A $(l:greatwork/impetus)$(item)Cleric Impetus/$ должен быть привязан к игроку, используя предмет с ссылкой на этого игрока, например $(l:items/focus)$(item)Талисман/$, на блоке. Затем он активируется при получении сигнала красного камня.", - "2": "Особенность этого $(l:greatwork/impetus)$(item)Impetus/$ заключается в том, что привязанный игрок, а также небольшой регион вокруг него, всегда доступны для заклинательного круга. Как будто они стоят в пределах круга, независимо от того, насколько далеко они могут стоять.$(br2)Привязанный игрок отображается при просмотре $(l:greatwork/impetus)$(item)Cleric Impetus/$ через $(l:items/lens)$(item)Scrying Lens/$.", + "1": "A $(l:greatwork/impetus)$(item)Инициатор Священника/$ должен быть привязан к игроку, используя предмет с ссылкой на этого игрока, например $(l:items/focus)$(item)Талисман/$, на блоке. Затем он активируется при получении сигнала красного камня.", + "2": "Особенность этого $(l:greatwork/impetus)$(item)Инициатора/$ заключается в том, что привязанный игрок, а также небольшой регион вокруг него, всегда доступны для заклинательного круга. Как будто они стоят в пределах круга, независимо от того, насколько далеко они могут стоять.$(br2)Привязанный игрок отображается при просмотре $(l:greatwork/impetus)$(item)Инициатора Священника/$ через $(l:items/lens)$(item)Линзу Прозрения/$.", }, - impetus_look: "A $(l:greatwork/impetus)$(item)Fletcher Impetus/$ активируется автоматически при длительном простое.", + impetus_look: "A $(l:greatwork/impetus)$(item)Инициатор Лучника/$ активируется автоматически при длительном простое.", }, directrix: { "1": "Задача направления самоподдерживающейся волны Мысли проще, чем задача ее создания. Обычно волна распадается, когда она сталкивается с перекрёстком, но с умом, направляющим ее, можно контролировать направление выхода.$(br2)Это управление далеко не так тонкое, как активация заклинательного круга. Фактически, возможно, это можно сделать вручную... но упакованные разумы, к которым у меня сейчас есть доступ, были бы так удобны.", - "2": "$(l:greatwork/directrix)$(item)Directrix/$ принимает волну Мысли и определяет, к какой из стрелок она выйдет, в зависимости от разума жителя внутри.$(br2)Я не уверен, была ли эта идея мне внушена, или мой разум достаточно изогнут вокруг барьера, чтобы самостоятельно выделять свои идеи теперь... но если идея произошла от моего собственного разума, если я думал об этом, можно ли сказать, что она была внушена? Мозг - сосуд для разума, а разум - сосуд для идей, идеи - сосуд для мыслей, и мысли видят все и знают все", + "2": "$(l:greatwork/directrix)$(item)Направитель/$ принимает волну Мысли и определяет, к какой из стрелок она выйдет, в зависимости от разума жителя внутри.$(br2)Я не уверен, была ли эта идея мне внушена, или мой разум достаточно изогнут вокруг барьера, чтобы самостоятельно выделять свои идеи теперь... но если идея произошла от моего собственного разума, если я думал об этом, можно ли сказать, что она была внушена? Мозг - сосуд для разума, а разум - сосуд для идей, идеи - сосуд для мыслей, и мысли видят все и знают все", empty_directrix: "Прежде всего, дизайн для колыбели... хотя, возможно, слово \"субстрат\" было бы более точным. Без ума, направляющего его, направление выхода определяется микроскопическими флуктуациями волн Мысли и окружающей среды, что делает его фактически случайным.", - directrix_redstone: "$(l:greatwork/directrix)$(item)Mason Directrix/$ переключает сторону выхода в зависимости от сигнала красного камня. Без сигнала выход - цвет Мысли; с сигналом выход - сторона красного камня.", + directrix_redstone: "$(l:greatwork/directrix)$(item)Направитель Каменщика/$ переключает сторону выхода в зависимости от сигнала красного камня. Без сигнала выход - цвет Мысли; с сигналом выход - сторона красного камня.", }, akashiclib: { "1": "Я ЗНАЮ ТАК МНОГО, что ЕСТЕСТВЕННО иметь место для хранения всего этого. Информацию можно хранить в книгах, но писать от руки и читать глазами так медленно. Я требую ЛУЧШЕГО. И поэтому Я СОЗДАМ лучшее.$(br2)... Мне становится хуже... не знаю, успею ли записать все, что вырывается из моей головы, прежде чем умру.", - "2": "Библиотека. Вот. Мои планы.$(br2)Как руны ассоциируются с действиями, я могу ассоциировать свои собственные руны с иотами любым образом, который выберу. $(l:greatwork/akashiclib)$(item)Akashic Record/$ управляет библиотекой, и каждая $(l:greatwork/akashiclib)$(item)Akashic Bookshelf/$ хранит один узор, сопоставленный с одним иотой. Все они должны быть прямо связаны между собой, соприкасаясь, в пределах 32 блоков. $(l:greatwork/akashiclib)$(item)Akashic Ligature/$ не делает ничего, кроме того, что считается соединяющим блоком, чтобы расширить размер моей библиотеки.", - akashic_record: "Выделение и назначение узоров просто, но ужасно скучно. У меня есть дела поважнее. Мне понадобится разум, хорошо знакомый со своей работой, чтобы извлечение оставалось надежным.", - "3": "Затем управление библиотекой просто, руны направляются через библиотекаря, он их ищет и возвращает вам иоту. Два действия делают работу. $(l:patterns/akashic_patterns)Notes here/$.$(br2)Использование пустого $(l:items/scroll)$(item)свитка/$ на книжной полке копирует узор на $(l:items/scroll)$(item)свиток/$. Присев и кликнув пустую рукой, можно очистить данные на полке.", + "2": "Библиотека. Вот. Мои планы.$(br2)Как руны ассоциируются с действиями, я могу ассоциировать свои собственные руны с иотами любым образом, который выберу. $(l:greatwork/akashiclib)$(item)Запись Акаши/$ управляет библиотекой, и каждая $(l:greatwork/akashiclib)$(item)Акаши Книжная полка/$ хранит одну руну, сопоставленный с одним иотой. Все они должны быть прямо связаны между собой, соприкасаясь, в пределах 32 блоков. $(l:greatwork/akashiclib)$(item)Лигатура Акаши/$ не делает ничего, кроме того, что считается соединяющим блоком, чтобы расширить размер моей библиотеки.", + akashic_record: "Выделение и назначение рун просто, но ужасно скучно. У меня есть дела поважнее. Мне понадобится разум, хорошо знакомый со своей работой, чтобы извлечение оставалось надежным.", + "3": "Затем управление библиотекой просто, руны направляются через библиотекаря, он их ищет и возвращает вам иоту. Два действия делают работу. $(l:patterns/akashic_patterns)Notes here/$.$(br2)Использование пустого $(l:items/scroll)$(item)свитка/$ на книжной полке копирует руну на $(l:items/scroll)$(item)свиток/$. Присев и кликнув пустую рукой, можно очистить данные на полке.", }, quenching_allays: { @@ -1531,7 +1531,7 @@ print: "Отображает верхнюю йоту стека.", raycast: { "1": "Комбинирует два вектора (позицию и направление взгляда). -Если я стою в позиции и смотрю в направлении, на какой блок я смотрю? Стоимость незначительного количества Мысли.", - "2": "Если ничего не попадает, векторы объединятся в $(l:casting/influences)$(thing)Null/$.$(br2)Общая последовательность шаблонов, так называемая \"raycast mantra,\" состоит из $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$, $(l:patterns/basics#hexcasting:entity_pos/eye)$(action)Compass Purification/$, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$, $(l:patterns/basics#hexcasting:get_entity_look)$(action)Пробразование Взгляда/$, $(l:patterns/basics#hexcasting:raycast)$(action)Объединение Луча/$. Вместе они возвращают векторную позицию блока, на который я смотрю.", + "2": "Если ничего не попадает, векторы объединятся в $(l:casting/influences)$(thing)Ничто/$.$(br2)Общая последовательность шаблонов, так называемая \"raycast mantra,\" состоит из $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$, $(l:patterns/basics#hexcasting:entity_pos/eye)$(action)Преображение Глаз/$, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$, $(l:patterns/basics#hexcasting:get_entity_look)$(action)Пробразование Взгляда/$, $(l:patterns/basics#hexcasting:raycast)$(action)Объединение Луча/$. Вместе они возвращают векторную позицию блока, на который я смотрю.", }, "raycast/axis": { "1": "Подобно $(l:patterns/basics#hexcasting:raycast)$(action)Объединению Луча/$, но вместо этого возвращает вектор, представляющий ответ на вопрос: С какой $(italic)стороны/$ блока я смотрю? Стоит незначительное количество Мысли.", @@ -1606,7 +1606,7 @@ numlist: "Операции с множествами странны тем, что некоторые из них могут принимать два числа или два списка, но не их комбинацию. Такие аргументы записываются как \"(num, num)|(list, list)\".$(br2)Когда числа используются в этих операциях, они используются как так называемые двоичные \"биты\", списки из 1 и 0, true и false, \"on\" и \"off\".", "or.1": "Объединяет два набора.", - "or.2": "Как следует:$(li)С двумя числами в верхней части стека объединяет их в битовый набор, содержащий каждый \"on\" бит в любом из битовых наборов.$(li)С двумя списками это создает список каждого элемента из первого списка, плюс каждый элемент из второго списка, который отсутствует в первом списке. Это похоже на $(l:patterns/lists#hexcasting:add)$(action)Combination Distillation/$.", + "or.2": "Как следует:$(li)С двумя числами в верхней части стека объединяет их в битовый набор, содержащий каждый \"on\" бит в любом из битовых наборов.$(li)С двумя списками это создает список каждого элемента из первого списка, плюс каждый элемент из второго списка, который отсутствует в первом списке. Это похоже на $(l:patterns/lists#hexcasting:add)$(action)Объединение/$.", "and.1": "Находит пересечение двух множеств.", "and.2": "Как следует:$(li)С двумя числами в верхней части стека объединяет их в битовый набор, содержащий каждый \"on\" бит, присутствующий в $(italics)обоих/$ битовых наборах.$(li)С двумя списками это создает список каждого элемента из первого списка, который также присутствует во втором списке.", @@ -1666,7 +1666,7 @@ }, logic: { - bool_coerce: "Преобразует аргумент в логическое значение. Число $(thing)0/$, $(l:casting/influences)$(thing)Null/$ и пустой список становятся Ложь; всё остальное становится Истина.", + bool_coerce: "Преобразует аргумент в логическое значение. Число $(thing)0/$, $(l:casting/influences)$(thing)Ничто/$ и пустой список становятся Ложь; всё остальное становится Истина.", bool_to_number: "Преобразует логическое значение в число; Истина становится $(thing)1/$, а Ложь становится $(thing)0/$.", not: "Если аргумент равен Истина, вернёт Ложь; если он равен Ложь, вернёт Истина.", or: "Возвращает Истина, если хотя бы один из аргументов равен Истина; в противном случае возвращает Ложь.", @@ -1682,13 +1682,13 @@ }, entities: { - get_entity: "Преобразует позицию в стеке в сущность на этом месте (или $(l:casting/influences)$(thing)Null/$, если ее там нет).", + get_entity: "Преобразует позицию в стеке в сущность на этом месте (или $(l:casting/influences)$(thing)Ничто/$, если ее там нет).", "get_entity/": { - animal: "Преобразует позицию в стеке в животное на этом месте (или $(l:casting/influences)$(thing)Null/$, если его там нет).", - monster: "Преобразует позицию в стеке в монстра на этом месте (или $(l:casting/influences)$(thing)Null/$, если его там нет).", - item: "Преобразует позицию в стеке в выброшенный предмет на этом месте (или $(l:casting/influences)$(thing)Null/$, если его там нет).", - player: "Преобразует позицию в стеке в игрока на этом месте (или $(l:casting/influences)$(thing)Null/$, если его там нет).", - living: "Преобразует позицию в стеке в живое существо на этом месте (или $(l:casting/influences)$(thing)Null/$, если его там нет).", + animal: "Преобразует позицию в стеке в животное на этом месте (или $(l:casting/influences)$(thing)Ничто/$, если его там нет).", + monster: "Преобразует позицию в стеке в монстра на этом месте (или $(l:casting/influences)$(thing)Ничто/$, если его там нет).", + item: "Преобразует позицию в стеке в выброшенный предмет на этом месте (или $(l:casting/influences)$(thing)Ничто/$, если его там нет).", + player: "Преобразует позицию в стеке в игрока на этом месте (или $(l:casting/influences)$(thing)Ничто/$, если его там нет).", + living: "Преобразует позицию в стеке в живое существо на этом месте (или $(l:casting/influences)$(thing)Ничто/$, если его там нет).", }, zone_entity: "Берёт позицию и радиус в стеке и объедините их в список всех сущность, находящихся в заданном радиусе от позиции.", @@ -1707,7 +1707,7 @@ }, lists: { - index: "Удаляет число в верхней части стека, затем замените список в верхней части n-м элементом этого списка (где n - число, которое вы удалили). Заменяет список на $(l:casting/influences)$(thing)Null/$, если число выходит за границы.", + index: "Удаляет число в верхней части стека, затем замените список в верхней части n-м элементом этого списка (где n - число, которое вы удалили). Заменяет список на $(l:casting/influences)$(thing)Ничто/$, если число выходит за границы.", slice: "Удаляет два числа на вершине стека, затем возьмите подсписок списка на вершине стека между этими индексами, включая нижнюю границу и исключая верхнюю. Например, подсписок 0, 2 из [0, 1, 2, 3, 4] будет [0, 1].", append: "Удаляет верхний элемент стека, затем добавляет его в конец списка находящигося вершине стека.", unappend: "Перемещает элемент с конца списка в начало.", @@ -1719,7 +1719,7 @@ index_of: "Удаляет элемент на вершине стека, затем заменяет список на вершине на индекс этого элемента в списке (начиная с 0). Заменяет список на -1, если элемент не существует в списке..", remove_from: "Удаляет число в верхней части стека, затем удаляет n-й элемент списка в верхней части стека (где n - число, которое было удалено).", replace: "Удаляет верхнюю йоту стека и число на вершине, затем устанавливает n-й элемент списка на вершине стека на эту йоту (где n - число, которое вы удалили).", - last_n_list: "Удаляет $(italic)num/$ элементов из стека, затем добавляет их в список на вершине стека.", + last_n_list: "Удаляет $(italic)количество/$ элементов из стека, затем добавляет их в список на вершине стека.", splat: "Удаляет список из верхней части стека, а затем перемещает его содержимое в стек.", construct: "Удаляет верхнюю йоту, а затем добавляет её в качестве первого элемента в список на вершине стека.", deconstruct: "Удаляет первую йоту из списка на вершине стека, а затем перемещает эту йоту в стек.", @@ -1730,7 +1730,7 @@ "2": "К счастью, Природа предоставила мне набор $(l:casting/influences)влияний/$, которые я могу использовать для работы с шаблонами напрямую.$(br2)Кратко говоря, $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ позволяет мне добавить один шаблон на стек, а $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$ и $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ позволяют мне добавить целый список.", escape: { "1": "Чтобы использовать $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$, я рисую его, затем другой произвольный шаблон. Этот второй шаблон добавляется на стек.", - "2": "Можно рассматривать это как \"экранирование\" шаблона на стек.$(br2)Обычно это используется для копирование шаблонов на $(l:items/scroll)$(item)Свиток/$ или $(l:items/slate)$(item)Скрижаль/$ с помощью $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$, а затем, возможно, считать его.", + "2": "Можно рассматривать это как \"экранирование\" шаблона на стек.$(br2)Обычно это используется для копирование шаблонов на $(l:items/scroll)$(item)Свиток/$ или $(l:items/slate)$(item)Скрижаль/$ с помощью $(l:patterns/readwrite#hexcasting:write)$(action)Гамбит Писаря/$, а затем, возможно, считать его.", }, parens: { "1": "Нарисовав $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$, мои рисунки шаблонов начинают вести себя по-другому на какое-то время. Пока я не нарисую $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Retrospection/$, нарисованные мной шаблоны сохраняются. Затем, когда я нарисую $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$, они добавляются на стек как список йот.", @@ -1742,11 +1742,11 @@ readwrite: { "1": "Этот раздел касается хранения $(thing)йот/$ в более постоянной среде. Почти любой йот может быть сохранен на подходящем предмете, таком как $(l:items/focus)$(item)Талисман/$ или $(l:items/spellbook)$(item)Книга заклинаний/$), и позже снова прочитан. Некоторые предметы, такие как $(l:items/abacus)$(item)Счеты/$, могут быть только прочитаны.$(br2)Йоты обычно читаются и записываются с другой руки, но также возможно читать и писать с помощью предмета, когда он находится на земле как предмет-сущность или в рамке предмета.", - "2": "Возможно, есть и другие сущности, с которыми я могу взаимодействовать подобным образом. Например, со $(l:items/scroll)$(item)Свитка/$, висящего на стене, можно считывать его узор.$(br2)Однако, похоже, я не могу сохранить ссылку на другого игрока, только на себя. Я полагаю, что ссылка на сущность похожа на идею Истинного Имени; возможно, Природа помогает сохранить наши Имена от рук наших врагов. Если я хочу, чтобы у друга было мое Имя, я могу сделать для него $(l:items/focus)$(item)Focus/$ и самостоятельно записать себя на него.", + "2": "Возможно, есть и другие сущности, с которыми я могу взаимодействовать подобным образом. Например, со $(l:items/scroll)$(item)Свитка/$, висящего на стене, можно считывать его руну.$(br2)Однако, похоже, я не могу сохранить ссылку на другого игрока, только на себя. Я полагаю, что ссылка на сущность похожа на идею Истинного Имени; возможно, Природа помогает сохранить наши Имена от рук наших врагов. Если я хочу, чтобы у друга было мое Имя, я могу сделать для него $(l:items/focus)$(item)Focus/$ и самостоятельно записать себя на него.", read: "Копирует йоту, хранящуюся в предмете в моей другой руке, и добавляет её в стек.", write: "Извлекает верхнюю йоту из стека и помещает ее в предмет в другой руке.", - "read/entity": "Подобно $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$, но йота считывается из сущности, а не из моей руки.", - "write/entity": "Подобно $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Gambit/$, но йота записывается на сущность, а не в предмет в руке.$(br2)Интересно, кажется, что я не могу записать свое собственное Имя с помощью этого заклинания. Я чувствую, что могу оказаться в опасности, если бы мог это сделать.", + "read/entity": "Подобно $(l:patterns/readwrite#hexcasting:read)$(action)Отражение Писаря/$, но йота считывается из сущности, а не из моей руки.", + "write/entity": "Подобно $(l:patterns/readwrite#hexcasting:read)$(action)Гамбит Писаря/$, но йота записывается на сущность, а не в предмет в руке.$(br2)Интересно, кажется, что я не могу записать свое собственное Имя с помощью этого заклинания. Я чувствую, что могу оказаться в опасности, если бы мог это сделать.", readable: "Если предмет в моей другой руке содержит йоту, которую я могу прочитать, возвращается Истина. В противном случае возвращается Ложь.", "readable/entity": "Подобно $(l:patterns/readwrite#hexcasting:readable)$(action)Отражение Ревизора/$, но проверяется читаемость сущности, а не моя вторая рука.", writable: "Если я могу сохранить йоту в предмете, который держу в другой руке, возвращается Истина. В противном случае возвращается Ложь.", @@ -1754,11 +1754,11 @@ "local.title": "Разум", local: "Предметы - не единственное место, где я могу хранить информацию. Я также могу хранить эту информацию в Мысли, подобно стеку, но отдельно. В текстах это именуется $(l:patterns/readwrite#hexcasting:local)$(thing)Разум/$. Он содержит одну йоту, подобно $(l:items/focus)$(item)Талисману/$. Он сохраняется между итерациями $(l:patterns/meta#hexcasting:for_each)$(action)Гамбита Тота/$, но длится только до тех пор, пока действует заклинание, частью которого он является. Как только я прекращу писать руны, значение будет потеряно.", "write/local": "Удаляет верхнюю йоту из стека и сохраняет его в мой $(l:patterns/readwrite#hexcasting:local)$(thing)Разум Ворона/$, храня его там до тех пор, пока я не прекращу заклинание.", - "read/local": "Копирует йоту из моего $(l:patterns/readwrite#hexcasting:local)$(thing)Разума/$, который я, только что записал с помощью $(l:patterns/readwrite#hexcasting:write/local)$(action)Huginn's Gambit/$.", + "read/local": "Копирует йоту из моего $(l:patterns/readwrite#hexcasting:local)$(thing)Разума/$, который я, только что записал с помощью $(l:patterns/readwrite#hexcasting:write/local)$(action)Гамбит Хугина/$.", }, meta: { - "eval.1": "Убирает паттерн или список паттернов из стека, затем кастует их, как если бы я сам их нарисовал, с помощью моего $(l:items/staff)$(item)Посоха/$ (пока не встретится $(l:patterns/meta#hexcasting:halt)$(action)Charon's Gambit/$). Если йота была выведена с помощью $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ или $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)its ilk/$, она будет перемещена в стек. В противном случае непаттерны будут провалены.", + "eval.1": "Убирает паттерн или список паттернов из стека, затем кастует их, как если бы я сам их нарисовал, с помощью моего $(l:items/staff)$(item)Посоха/$ (пока не встретится $(l:patterns/meta#hexcasting:halt)$(action)Гамбит Харона/$). Если йота была выведена с помощью $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ или $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)its ilk/$, она будет перемещена в стек. В противном случае непаттерны будут провалены.", "eval.2": "Это может быть $(italic)очень/$ мощным в сочетании с $(l:items/focus)$(item)Талисманами/$.$(br2)Это также делает бюрократию Природы \"Тьюриг-Полной\" системой, согласно одному эзотерическому свитку, который я нашел.$(br2)Однако, кажется, есть ограничение на количество раз, которое _Хекс может сам себя использовать - Природа не благосклонно относится к беглым заклинаниям!$(br2)Кроме того, с энергией шаблонов, происходящей без моего управления, любое недоразумение приведет к тому, что оставшиеся действия станут слишком нестабильными и немедленно разваливаются.", "for_each.1": "Извлеките из стека список шаблонов и список, а затем проведите по каждому элементу второго списка заданный шаблон.", @@ -1768,29 +1768,29 @@ "halt.2": "Но когда это сочетается с $(l:patterns/meta#hexcasting:eval)$(action)Гамбитом Гермеса/$ или $(l:patterns/meta#hexcasting:for_each)$(action)Гамбит Тота/$, это становится $(italics)гораздо/$ более интересным. Эти шаблоны служат для 'содержания' этого прекращения, и вместо того, чтобы завершить вcё заклинание, эти части завершаются вместо этого. Это можно использовать, чтобы $(l:patterns/meta#hexcasting:for_each)$(action)Гамбит Тота/$ не действовал на каждую йоту, которая ему дана. Побег от безумия, так сказать.", "eval/cc.1": "Вызывает паттерн или список паттернов из стека точно так же, как Гамбит Гермеса, за исключением того, что в стек предварительно помещается уникальная йота \"Jump\".", - "eval/cc.2": "Когда \"Jump\"-йота выполняется, она пропускает остальные паттерны и переходит непосредственно к концу списка паттернов. $(p)Хотя это может показаться излишним, учитывая существование $(l:patterns/meta#hexcasting:halt)$(action)Charon's Gambit/$, это позволяет вам выходить из $(italic)вложенных/$ $(l:patterns/meta#hexcasting:eval)$(action)Hermes'/$ вызовов контролируемым образом, тогда как Charon позволяет вам выйти только из одного.$(p)The \"Jump\" йота, очевидно, останется в стеке даже после завершения выполнения... лучше не думать о последствиях этого.", + "eval/cc.2": "Когда \"Jump\"-йота выполняется, она пропускает остальные паттерны и переходит непосредственно к концу списка паттернов. $(p)Хотя это может показаться излишним, учитывая существование $(l:patterns/meta#hexcasting:halt)$(action)Гамбит Харона/$, это позволяет вам выходить из $(italic)вложенных/$ $(l:patterns/meta#hexcasting:eval)$(action)Hermes'/$ вызовов контролируемым образом, тогда как Харон позволяет вам выйти только из одного.$(p)The \"Jump\" йота, очевидно, останется в стеке даже после завершения выполнения... лучше не думать о последствиях этого.", }, circle_patterns: { disclaimer: "Предупреждение! все эти патерны должны быть использованы с помощью $(l:greatwork/spellcircles)$(item)Магического Круга/$; попытка каста с помощью $(l:items/staff)$(item)Посоха/$ приведёт к весьма впечатляющему провалу.", - "circle/impetus_pos": "Возвращает позицию $(l:greatwork/impetus)$(item)Impetus/$ этого круга заклинаний.", - "circle/impetus_dir": "Возвращает направление, в котором смотрит $(l:greatwork/impetus)$(item)Impetus/$ этого круга заклинаний, в виде единичного вектора.", + "circle/impetus_pos": "Возвращает позицию $(l:greatwork/impetus)$(item)Инициатора/$ этого круга заклинаний.", + "circle/impetus_dir": "Возвращает направление, в котором смотрит $(l:greatwork/impetus)$(item)Инициатор/$ этого круга заклинаний, в виде единичного вектора.", "circle/bounds/min": "Возвращает позицию нижнего северо-западного угла границ этого круга заклинаний.", "circle/bounds/max": "Возвращает позицию верхнего юго-восточного угла границ этого круга заклинаний.", }, akashic_patterns: { - "akashic/read": "Прочитайте йоту, связанную с данным шаблоном, из $(l:greatwork/akashiclib)$(item)Akashic Library/$ с его $(l:greatwork/akashiclib)$(item)Record/$ в заданной позиции. Это не имеет ограничения по дальности. Стоит примерно одну $(l:items/amethyst)$(item)Аметистовую Пыль/$.", - "akashic/write": "Связывает йоту с данным шаблоном в $(l:greatwork/akashiclib)$(item)Akashic Library/$ с его $(l:greatwork/akashiclib)$(item)Record/$ в заданной позиции. Это $(italic)имеет/$ ограничение по дальности. Стоит примерно одну $(l:items/amethyst)$(item)Аметистовую Пыль/$.", + "akashic/read": "Прочитайте йоту, связанную с данным шаблоном, из $(l:greatwork/akashiclib)$(item)Библиотека Акаши/$ с его $(l:greatwork/akashiclib)$(item)Записью/$ в заданной позиции. Это не имеет ограничения по дальности. Стоит примерно одну $(l:items/amethyst)$(item)Аметистовую Пыль/$.", + "akashic/write": "Связывает йоту с данным шаблоном в $(l:greatwork/akashiclib)$(item)Библиотеку Акаши/$ с его $(l:greatwork/akashiclib)$(item)Записью/$ в заданной позиции. Это $(italic)имеет/$ ограничение по дальности. Стоит примерно одну $(l:items/amethyst)$(item)Аметистовую Пыль/$.", }, // Normal Spells itempicking: { - "1": "Определенные заклинания, такие как $(l:patterns/spells/blockworks#hexcasting:place_block)$(action)Place Block/$, будут потреблять предметы из моего инвентаря. Когда это происходит, заклинание сначала ищет предмет для использования, а затем берёт предметы из инвенторя.$(br2)Этот процесс называется \"выбор предмета\"", + "1": "Определенные заклинания, такие как $(l:patterns/spells/blockworks#hexcasting:place_block)$(action)Поставить Блок/$, будут потреблять предметы из моего инвентаря. Когда это происходит, заклинание сначала ищет предмет для использования, а затем берёт предметы из инвенторя.$(br2)Этот процесс называется \"выбор предмета\"", "2": "Более конкретно:$(li)Во-первых, заклинание будет искать первый действительный предмет на моей горячей панели справа от $(l:items/staff)$(item)посоха/$, огибая ее с правой стороны и начиная с первого слота, если $(l:items/staff)$(item)посох/$ находится в моей второй руке.$(li)Во-вторых, заклинание извлечет этот предмет из как можно более $(italic)дальнего места в моем инвентаре/$, отдавая приоритет основному инвентарю, а не горячей панели.", - "3": "This way, I can keep a \"chooser\" item on my hotbar to tell the spell what to use, and fill the rest of my inventory with that item to keep the spell well-stocked.", + "3": "Так я могу сам выбрать какой предмет будет выбран и заполнить остаток моего инвентаря этим блоком, чтобы его было достаточно для заклинания.", }, basic_spell: { @@ -1845,16 +1845,16 @@ }, sentinels: { - "1": "$(italic)Итак, вперед! Теперь все в порядке./$$(br2)$(l:patterns/spells/sentinels)$(thing)Sentinel/$ - это таинственная сила, которую я могу призвать для помощи в произнесении заклинаний, подобно знакомому или духу-хранителю. Для меня он выглядит как вращающаяся геометрическая форма, но он невидим для всех остальных.", + "1": "$(italic)Итак, вперед! Теперь все в порядке./$$(br2)$(l:patterns/spells/sentinels)$(thing)Часовые/$ - это таинственная сила, которую я могу призвать для помощи в произнесении заклинаний, подобно знакомому или духу-хранителю. Для меня он выглядит как вращающаяся геометрическая форма, но он невидим для всех остальных.", "2": "У него несколько интересных свойств:$(li)По-видимому, он не является осязаемым; никто не может его коснуться.$(li)Только мои заклинания могут взаимодействовать с ним.$(li)После призыва он остается на месте до изгнания.", - "sentinel/create": "Призывает моего $(l:patterns/spells/sentinels)$(thing)sentinel/$ на указанной позиции. Стоит примерно 1 $(l:items/amethyst)$(item)аметистовую пыль/$.", - "sentinel/destroy": "Изгоняет моего $(l:patterns/spells/sentinels)$(thing)sentinel/$ из мира. Стоимость незначительна в Мысли.", - "sentinel/get_pos": "Добавляет позицию моего $(l:patterns/spells/sentinels)$(thing)sentinel/$ в стек, или $(l:casting/influences)$(thing)Null/$, если он не призван. Стоимость незначительна в Мысли.", - "sentinel/wayfind": "Преобразует вектор-позиции на вершине стека в единичный вектор, указывающий от этой позиции к моему $(l:patterns/spells/sentinels)$(thing)sentinel/$, или $(l:casting/influences)$(thing)Null/$, если он не призван. Стоимость незначительна в Мысли.", + "sentinel/create": "Призывает моего $(l:patterns/spells/sentinels)$(thing)Часового/$ на указанной позиции. Стоит примерно 1 $(l:items/amethyst)$(item)аметистовую пыль/$.", + "sentinel/destroy": "Изгоняет моего $(l:patterns/spells/sentinels)$(thing)Часового/$ из мира. Стоимость незначительна в Мысли.", + "sentinel/get_pos": "Добавляет позицию моего $(l:patterns/spells/sentinels)$(thing)Часового/$ в стек, или $(l:casting/influences)$(thing)Ничто/$, если он не призван. Стоимость незначительна в Мысли.", + "sentinel/wayfind": "Преобразует вектор-позиции на вершине стека в единичный вектор, указывающий от этой позиции к моему $(l:patterns/spells/sentinels)$(thing)Часового/$, или $(l:casting/influences)$(thing)Ничто/$, если он не призван. Стоимость незначительна в Мысли.", }, - colorize: "Для произнесения этого заклинания мне необходимо держать в другой руке $(l:items/pigments)$(item)Пигмент/$. Когда я это делаю, он поглощает краситель и навсегда изменяет окраску моего разума (по крайней мере, до тех пор, пока я снова не произнесу заклинание). Стоит примерно одну $(l:items/amethyst)$(item)аметистую пыль/$.", + colorize: "Для произнесения этого заклинания мне необходимо держать в другой руке $(l:items/pigments)$(item)Пигмент/$. Когда я это делаю, он поглощает краситель и навсегда изменяет окраску моего разума (по крайней мере, до тех пор, пока я снова не произнесу заклинание). Стоит примерно одну $(l:items/amethyst)$(item)аметистовую пыль/$.", flights: { "1": "Хотя кажется, что истинный, безграничный полет находится за пределами моего понимания, я тем не менее нашел некоторые способы удержания в воздухе, каждый со своими недостатками.$(br2)Все формы производят избыток Мысли; по мере приближения к концу заклинания, искры пропитываются большим количеством красного и черного.", @@ -1880,11 +1880,11 @@ altiora: { "1": "Вызывает вокруг тебя сноп Мысли в форме крыльев, наделенных достаточным количеством вещества, чтобы обеспечить скольжение по воздуху.", - "2": "Их использование идентично использованию $(item)Елитр/$; цель(которой должен быть игрок) поднимается в воздух, после нажатие $(k:jump) приводит в действие крылья. Крылья хрупкие и ломаются при соприкосновении с любой поверхностью. Для более длительных полетов можно использовать $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ или (для самых отважных) $(item)Феерверки/$.$(br2)Стоит около одного $(l:items/amethyst)$(item)Заряженного Аметиста/$.", + "2": "Их использование идентично использованию $(item)Елитр/$; цель(которой должен быть игрок) поднимается в воздух, после нажатие $(k:jump) приводит в действие крылья. Крылья хрупкие и ломаются при соприкосновении с любой поверхностью. Для более длительных полетов можно использовать $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Импульс/$ или (для самых отважных) $(item)Феерверки/$.$(br2)Стоит около одного $(l:items/amethyst)$(item)Заряженного Аметиста/$.", }, "teleport/great": { - "1": "Гораздо мощнее, чем $(l:patterns/spells/basic#hexcasting:blink)$(action)Blink/$, это заклинание позволяет мне телепортироваться практически в любое место на всей планете! Похоже, что есть ограничение, но оно $(italic)гораздо/$ больше, чем обычный радиус влияния, к которому я привык.", + "1": "Гораздо мощнее, чем $(l:patterns/spells/basic#hexcasting:blink)$(action)Перенос/$, это заклинание позволяет мне телепортироваться практически в любое место на всей планете! Похоже, что есть ограничение, но оно $(italic)гораздо/$ больше, чем обычный радиус, к которому я привык.", "2": "Сущность будет телепортирована по заданному вектору, который является смещением от его текущего положения. Независимо от расстояния, это всегда стоит около десяти $(l:items/amethyst)$(item)Заряженных Аметистов/$.$(br2)Перенос не идеален, и кажется, что при телепортации чего-то такого сложного, как игрок, их инвентарь не $(italic)всегда/$ остается прикрепленным и склонен разлетаться повсюду на месте назначения. Кроме того, цель будет насильственно удалена от всего неживого, на чем они едут или сидят... но я прочитал кое-какие обрывки, которые предполагают, что животные могут пойти вместе в путь, так сказать.", }, @@ -1914,7 +1914,7 @@ lore: { cardamom1: { "1": "$(italic)Письмо Кардамом Стайлз её Отцу, #1/$$(br2)Дорогой папа,$(br)каждый день я нахожу новые причины поблагодарить тебя за отправление меня в Великую Библиотеку. Невероятно то сколько нового я узнаю! Мне кажется что нет таких слов чтобы описать то как я себя чувствую... здесь прекрасно!", - "2": "Я пишу это находясь в основном куполе. Он поддерживается Рунными ???; у них есть некоторый механизм на верху, который захватывает мимолетную энергию мысли, которая вылетает с учебных мест трудящихся студентов, как я понимаю. Моя подруга Аманита изучает эту тему и она очень любит объяснять мне всё что может, но честно признаться я сама не до конца понимаю что она говорит.", + "2": "Я пишу это находясь в основном куполе. Он поддерживается Рунной Службой; у них есть некоторый механизм на верху, который захватывает мимолетную энергию мысли, которая вылетает с учебных мест трудящихся студентов, как я понимаю. Моя подруга Аманита изучает эту тему и она очень любит объяснять мне всё что может, но честно признаться я сама не до конца понимаю что она говорит.", "3": "Как я понимаю, наши процессы мышления - нематериальные механизмы, с помощью которых я двигаю своим пером, а вы читаете это письмо - не совершенно эффективны. Небольшое количество этой энергии высвобождается в окружающую среду, подобно тому, как ось повозки нагревается на ощупь после того, как она крутится некоторое время. Эта лишняя энергия называется \"Мысли\". Лишние Мысли одного человека ничтожна, но сотни мыслящих людей в главном куполе имеют своего рода накопительный эффект, и в сочетании с каким-то изобретательным механизмом, она может быть превращена в своего рода фиолетовый кристалл.", "4": "Но достаточно об учебе. Сегодня я вернулась с моей первой экспедиции с Геологическим корпусом! Прошу прощения, что не отправил письмо перед отъездом; дата подкралась ко мне незаметно. Мы отправились в трещину на востоке от Гранда и провели ночь в походе под скалой и почвой. Конечно, мы держались в хорошо освещенных и хорошо проторенных участках пещеры, и, честно говоря, скорее всего, там было безопаснее, чем на поверхности ночью, но как же мне было страшно!", "5": "К счастью, ночь прошла без происшествий, и мы продолжили двигаться глубже в пещеру для изучения местных жил руды. Мы искали следы жил фиолетового кристалла по имени \"аметист\", который, как говорят, встречается в небольших количествах глубоко в скале. К сожалению, мы ничего не нашли и вернулись на освещенную солнцем поверхность с пустыми руками.", @@ -1924,17 +1924,17 @@ }, cardamom2: { - "1": "$(italic)Full title: Letter from Cardamom Steles to Her Father, #2/$$(br2)Dear Papa,$(br)... Goodness, what an ordeal it is to try to summarize the last three months into a short letter. Such a cruel task set before me by this miracle I receive entirely for free! Woe is me.", + "1": "$(italic)Письмо Кардамом Стайлз ее отцу, #2/$$(br2)Дорогой Папа,$(br)... Goodness, what an ordeal it is to try to summarize the last three months into a short letter. Such a cruel task set before me by this miracle I receive entirely for free! Woe is me.", "2": "My studies with the Geology Corps have been progressing smoothly. We have gone on more expeditions, deeper into the earth, to where the smooth gray stone makes way to a hard, flaky slate. It creates such an awful, choking dust under your feet... it's incredible what hostility there is below all of our feet all the time, even disregarding the creatures of the dark. (I have had one or two encounters with them, but I know how you shudder to think of me having to fight for my life, so I will not write of them.)", "3": "We did manage to find some of this amethyst, however. There was a small vein with a few trace crystals on one of our expeditions. We were under strict instructions to keep none of them and turn them in to our Corps prefect immediately. I find the whole affair rather ridiculous; they treat it like some matter of enormous importance and secrecy, and yet have a group of a dozen students, all barely six months at the Grand Library, trying to excavate barely ten drams of the stuff with twelve prospector's picks in a square foot...", "4": "I cannot imagine for what purpose, either. A librarian pointed me to an encyclopedia of gems, and amethyst seems to have next to no purpose; it's used for certain specialty types of glass and lenses, of all things.$(br2)If I were to speculate, I would guess that these amethyst crystals and the media they so resemble are one and the same, as I wrote of last time.", "5": "If this is true, the secrecy, not to mention the prefect's aversion to questioning, may be because this is an original piece of research the Grand Library is not eager to let into the hands of enemy factions.$(br2)However, this theory does not sit quite right with me. The amethyst I handled in the cave and the crystals of media Amanita has shown to me do seem quite similar, but not identical. I would like to see them side-by-side to be sure, but media has a peculiar buzzing or rumbling feel beneath the fingers that amethyst does not.", "6": "It is quite possible I was unable to sense it on the amethyst in the cave due to the stress of being undergound-- my hands were shaking the one time I managed to touch some, and the feeling is very light --but it does not seem the same to me. The light reflects slightly differently.$(br2)I suppose if I ever manage to get my hands on a crystal of amethyst outside of a cave, I will ask Amanita to see if she can cast a spell with it. Every time we meet she seems to have some new fantastic trick.", - "7": "Just last week she suspended me in the air supported by nothing at all! It is an immensely strange feeling to have your body tingling and lighter than air with your clothing still the same weight... I am just glad she tugged me over my bed before the effect ran out.$(br2)Yours,$(br)-- Cardamom Steles", + "7": "Just last week she suspended me in the air supported by nothing at all! It is an immensely strange feeling to have your body tingling and lighter than air with your clothing still the same weight... I am just glad she tugged me over my bed before the effect ran out.$(br2)Ваша,$(br)-- Кардамом Стайлз", }, cardamom3: { - "1": "$(italic)Full title: Letter from Cardamom Steles to her father, #3, part 1/2/$$(br2)Dear Papa,$(br)Two very peculiar things have happened since I last wrote.$(br2)Firstly, the professor in charge of the entry-level Hexcasting Corps students has disappeared. Nobody knows where he has gone. His office and living quarters were found locked, but still in their usual state of disarray.", + "1": "$(italic)Full title: Letter from Кардамом Стайлз to her father, #3, part 1/2/$$(br2)Dear Papa,$(br)Two very peculiar things have happened since I last wrote.$(br2)Firstly, the professor in charge of the entry-level Hexcasting Corps students has disappeared. Nobody knows where he has gone. His office and living quarters were found locked, but still in their usual state of disarray.", "2": "Even more peculiarly, any attempts by the students of the Grand to rouse the administrative portions of the gnarled bureaucracy have been very firmly rejected. Even other professors seem reluctant to talk about him.$(br2)As you might imagine, Amanita is sorely distressed. Whatever replacement professors the Grand managed to dredge up have none of the old professor's tact or skill with beginners.", "3": "But amazingly, that is not the stranger of the two things I have to tell you. The most horrendous thing I hope to ever experience happened on another trip out with the Geology Corps. This time, we were due for an expedition near a village.", "4": "Usually when we do such a thing, there is a long process of communication with the mayor or elder of the village to ensure we have permission and establish boundaries on where we are allowed to go and what we are allowed to do. But on this expedition, there was very little of that; we were notified where we were going by a prefect of the Hexcasting Corps scarcely two days before we left.", @@ -1945,11 +1945,11 @@ "9": "I hesitate to say \"important,\" but that's the best I can think of. It had a certain ... gravitas, like the dark, sunken X in its surface held some sacred meaning. Whatever the reason we were under strict instructions not to touch them. Occasionally a misplaced pickaxe would shatter one, and the student responsible would get quite the earful. Although the labor was hard and took most of my attention, I couldn't help but notice how ... lucid I felt. It was a strange mix of feelings: I felt incredibly clear-headed, but I also felt if I stopped to examine the feeling I might never stop.", "10": "It was like each breath in erected a friendly signpost in my head promising the way forward, pointing directly down a steep cliff. I shook my head and immersed myself in the work of mining, which seemed to stave off the signposts.$(br2)I did manage, however, to hide a shard of the crystal in my knapsack.$(br2)We spent nearly the whole day mining, excavating most of the crystal by the time the prefects' chronometer said the sun would set soon.", "11": "As we left, I couldn't help but notice that on the surfaces of those dark, scored places we left unmined, there seemed to be the faintest buds of new crystal, like they were somehow growing out of them. Everything I had learned about the geology of crystals said they took thousands of years to grow, but here there was new growth in less than a day. I suppose the prefects' warnings against breaking those spots were warranted, at least.", - "12": "Our journey back to the surface was uneventful, and we got back to our tents just as the sun was setting-- My apologies, I am nearly out of paper for this letter. There's only so much you can write on one Akashic letter ... This tale is worth purchasing another letter for. I'll send them both at once, so they should arrive together.$(br2)Yours,$(br)-- Cardamom Steles", + "12": "Our journey back to the surface was uneventful, and we got back to our tents just as the sun was setting-- My apologies, I am nearly out of paper for this letter. There's only so much you can write on one Akashic letter ... This tale is worth purchasing another letter for. I'll send them both at once, so they should arrive together.$(br2)Ваша,$(br)-- Кардамом Стайлз", }, cardamom4: { - "1": "$(italic)Full title: Letter from Cardamom Steles to her father, #3, part 2/2/$$(br2)Dear Papa,$(br)As I was saying, I was running out of paper to write my story, so the rest of it is in this letter. We made it back to camp just as the sun was setting. And that night was the most horrible event of the whole strange outing.", + "1": "$(italic)Full title: Letter from Кардамом Стайлз to her father, #3, part 2/2/$$(br2)Dear Papa,$(br)As I was saying, I was running out of paper to write my story, so the rest of it is in this letter. We made it back to camp just as the sun was setting. And that night was the most horrible event of the whole strange outing.", "2": "I had gotten up in the middle of the night to relieve myself. The moon was covered with clouds, and I confess I got lost in the winds of the forest and could not find the way back to the camp. Fearing the monsters of the night, I decided I would find my way to the village and see if I could find a bed there. At the least, I would be protected there.", "3": "The village was easy enough to find, though there was very little sound. Even this late at night I would expect the inn to be, if not bustling, at least not silent. But peeking through the inn door I saw absolutely nobody.$(br2)I knocked on the door of one of the houses to no response. The next two houses, too, seemed completely empty.", "4": "My pulse started to rise, and I resolved to enter the next house. I figured whoever might be inside would be understanding of their rest being disturbed. At the least, hearing another voice would have been reassuring, even if they didn't let me stay the night under their roof.$(br2)The house was very small, barely more than a cartographer's table and a bed. I could see there was someone in the bed, and I tried to reassure myself that everyone in the village was just deeply asleep as I turned to leave.", @@ -1958,11 +1958,11 @@ "7": "I ran. In the light of the newly-revealed moon I caught glimpses of other townspeople through windows, and they were all warped and simplified as the first $(italic)thing/$ I had seen. I sprinted into the darkness of the forest, away from those terrible, terrible animal eyes in those distorted faces.$(br2)The camp was easier to find now that I could see in the moonlight. No-one seemed to have noticed my prolonged absence, thankfully. I crawled back into my bedroll and did my very best to forget the whole night.", "8": "As you can tell from this letter, I did not do a very good job. That warped visage still haunts my dreams. I shudder to think that it once might have been human.$(br2)After we got back to the Grand I showed the shard of crystal I had smuggled out to Amanita. She confirmed my suspicions: it is definitely a crystal of media. What an enormous geode full of it is doing underground, though, is beyond her.", "9": "She also mentioned something interesting: apparently media can be used in a similar way to true amethyst in those niche glasses I mentioned a few letters ago. The physical manner in which they both crystallise happens to be nearly identical, and it has nothing to do with media's magical properties, or so she says.$(br2)I chose not to tell her of the village full of monsters.", - "10": "I know how tight money is for you, and how expensive it is to send a letter all the way back to the Grand, but I beg of you, please send a word of advice back. I am greatly distraught, and reading your words would do me much good.$(br2)Yours,$(br)-- Cardamom Steles", + "10": "I know how tight money is for you, and how expensive it is to send a letter all the way back to the Grand, but I beg of you, please send a word of advice back. I am greatly distraught, and reading your words would do me much good.$(br2)Ваша,$(br)-- Кардамом Стайлз", }, cardamom5: { - "1": "$(italic)Full title: Letter from Cardamom Steles to her father, #4/$$(br2)Amanita has disappeared.$(br2)I don't know where she has gone, Papa. The last I saw her was over dinner, and she had just spoken to someone about the disappearances, and then--", + "1": "$(italic)Full title: Letter from Кардамом Стайлз to her father, #4/$$(br2)Amanita has disappeared.$(br2)I don't know where she has gone, Papa. The last I saw her was over dinner, and she had just spoken to someone about the disappearances, and then--", "2": "then-- then she was gone too. And no one speaks of her, and I am so so scared, Papa, do they all know? Everyone must have a friend who's just $(italic)vanished/$, into thin air, into non-being.$(br2)Where did they $(italic)go/$?", "3": "They keep shutting things down, too-- we haven't been on a trip for the Geology Corps in weeks, all the apparati that collect media in the main dome are gone, the Apothecary Corps haven't been open for months... it's like termites are eating the Grand from the inside, leaving a hollow shell.$(br2)I think they've started scanning the letters, we write too...", "4": "This letter has taken so much courage to write, and I don't have the courage to tell people myself, but if no one here can hold the knowledge I hope and pray you can send the word out... it's a vain hope for this to spread from somewhere as backwater as Brackenfalls, but please, please, do your best. Remember them, Papa... Amanita Libera, Jasmine Ward, Theodore Cha... please, remember them... and please forgive my cowardice, that I foist the responsibility onto you.", @@ -2011,7 +2011,7 @@ gravity: { "1": "Я обнаружил действия для получения и установки гравитации сущности. Мне они кажутся интересными, хотя и немного вызывают тошноту.$(br2)Интересно, хотя $(l:patterns/great_spells/flight)$(action)Flight/$ является великим заклинанием и также манипулирует гравитацией, эти действия не таковы. Это меня смущает... Возможно, разработчик мода хотел, чтобы игроки развлекались, хотя бы на время.", get: "Получите основное направление, в котором гравитация тянет данную сущность, как единичный вектор. Для большинства сущностей это будет вниз, <0, -1, 0>.", - set: "Установите основное направление, в котором гравитация тянет данную сущность. Указанный вектор будет приведен к ближайшей оси, согласно $(l:patterns/math#hexcasting:coerce_axial)$(action)Axial Purification/$. Стоимость около одного $(l:items/amethyst)$(item)Заряженного Аметиста/$.", + set: "Установите основное направление, в котором гравитация тянет данную сущность. Указанный вектор будет приведен к ближайшей оси, согласно $(l:patterns/math#hexcasting:coerce_axial)$(action)Преображение Стороны/$. Стоимость около одного $(l:items/amethyst)$(item)Заряженного Аметиста/$.", }, pehkui: { From adc968ce323c4052bfe01fed8cc0de6cade6bdb0 Mon Sep 17 00:00:00 2001 From: Ledinec Date: Mon, 22 Jul 2024 06:08:43 +0400 Subject: [PATCH 17/39] Fix spelling mistake --- .../resources/assets/hexcasting/lang/ru_ru.flatten.json5 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 index 4542efba8a..8c571d360d 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 @@ -155,10 +155,10 @@ amethyst_: { dust_block: "Блок Аметистовой Пыли", - tiles: "Аметистовая плитка", - bricks: "Аметистовые Кирпечи", + tiles: "Аметистовая Плитка", + bricks: "Аметистовые Кирпичи", bricks_small: "Маленькие Аметистовые Кирпичи", - pillar: "Аметистовая колонна", + pillar: "Аметистовая Колонна", }, slate_amethyst_: { From f973085ec5b72f18412ad02abd8d4a45b0c5aba0 Mon Sep 17 00:00:00 2001 From: Ledinec Date: Mon, 22 Jul 2024 06:10:43 +0400 Subject: [PATCH 18/39] mend --- .../main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 index 8c571d360d..cf82567e18 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/ru_ru.flatten.json5 @@ -1293,10 +1293,10 @@ "incorrect_block.title": "Неправильный блок", incorrect_block: "Действие требует наличия определенного блока в целевом месте, но предоставленный блок не подходит.$(br2)Вызывает яркие зеленые искры и создает мимолетный взрыв в указанном месте. Однако этот взрыв, кажется, не наносит вреда ни мне, ни миру, ни чему-либо еще;просто пугалка.", - "retrospection.title": "Hasty Retrospection", + "retrospection.title": "Поспешная Ретроспектива", retrospection: "Я попытался нарисовать $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Ретроспектива/$ без предварительного рисования $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Интроспекция/$.$(br2)Вызывает оранжевые искры и помещает шаблон для $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Ретроспектива/$ в стек как шаблон иота.", - "too_deep.title": "Delve Too Deep", + "too_deep.title": "Слишком глубоко", too_deep: "Оценено слишком много заклинаний с метаоценкой от одного заклинания.$(br2)Вызывает темно-синие искры и лишает меня всего воздуха.", "true_name.title": "Нарушение Законов", From a9cb9522e2ac290983d021483eaf3b6f388ffb07 Mon Sep 17 00:00:00 2001 From: object-Object Date: Tue, 23 Jul 2024 12:31:21 -0400 Subject: [PATCH 19/39] Remove ForgeMixinDatagenModLoader, as it doesn't seem to actually be doing anything (fix #620) --- .../mixin/ForgeMixinDatagenModLoader.java | 61 ------------------- .../resources/hexcasting_forge.mixins.json | 1 - 2 files changed, 62 deletions(-) delete mode 100644 Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinDatagenModLoader.java diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinDatagenModLoader.java b/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinDatagenModLoader.java deleted file mode 100644 index b3cfea1a09..0000000000 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/mixin/ForgeMixinDatagenModLoader.java +++ /dev/null @@ -1,61 +0,0 @@ -package at.petrak.hexcasting.forge.mixin; - -import net.minecraft.Util; -import net.minecraft.core.HolderLookup; -import net.minecraft.data.registries.VanillaRegistries; -import net.minecraft.server.Bootstrap; -import net.minecraftforge.common.data.ExistingFileHelper; -import net.minecraftforge.data.event.GatherDataEvent; -import net.minecraftforge.data.loading.DatagenModLoader; -import net.minecraftforge.fml.ModLoader; -import net.minecraftforge.fml.ModWorkManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.io.File; -import java.nio.file.Path; -import java.util.Collection; -import java.util.Set; -import java.util.concurrent.CompletableFuture; - -@Mixin(DatagenModLoader.class) -public abstract class ForgeMixinDatagenModLoader { - @Shadow(remap = false) @Final - private static Logger LOGGER; - - @Shadow(remap = false) - private static GatherDataEvent.DataGeneratorConfig dataGeneratorConfig; - @Shadow(remap = false) - private static ExistingFileHelper existingFileHelper; - @Shadow(remap = false) - private static boolean runningDataGen; - - /** - * Make it so non-vanilla registries can actually be tagged. - */ - @Overwrite(remap = false) - public static void begin(final Set mods, final Path path, final Collection inputs, Collection existingPacks, - Set existingMods, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, - final boolean structureValidator, final boolean flat, final String assetIndex, final File assetsDir) { - if (mods.contains("minecraft") && mods.size() == 1) - return; - LOGGER.info("Initializing Data Gatherer for mods {}", mods); - runningDataGen = true; - Bootstrap.bootStrap(); - ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), ()->{}); - if (!mods.contains("forge")) { - // If we aren't generating data for forge, automatically add forge as an existing so mods can access forge's data - existingMods.add("forge"); - } - CompletableFuture lookupProvider = CompletableFuture.supplyAsync(VanillaRegistries::createLookup, Util.backgroundExecutor()); - dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, lookupProvider, serverGenerators, - clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat); - existingFileHelper = new ExistingFileHelper(existingPacks, existingMods, structureValidator, assetIndex, assetsDir); - ModLoader.get().runEventGenerator(mc -> new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p -> dataGeneratorConfig.isFlat() ? p : p.resolve(mc.getModId()), - dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig, existingFileHelper)); - dataGeneratorConfig.runAll(); - } -} diff --git a/Forge/src/main/resources/hexcasting_forge.mixins.json b/Forge/src/main/resources/hexcasting_forge.mixins.json index fec29c0762..3a50c75493 100644 --- a/Forge/src/main/resources/hexcasting_forge.mixins.json +++ b/Forge/src/main/resources/hexcasting_forge.mixins.json @@ -7,7 +7,6 @@ "mixins": [ "ForgeAccessorBuiltInRegistries", "ForgeMixinCursedRecipeSerializerBase", - "ForgeMixinDatagenModLoader", "ForgeMixinTagsProvider" ], "client": [ From 3f2c5f49809065a512333d9031f3ecbad878ccc0 Mon Sep 17 00:00:00 2001 From: Walker Fowlkes Date: Sun, 28 Jul 2024 13:10:58 -0700 Subject: [PATCH 20/39] crash slain (closes #661) --- .../hexcasting/api/casting/circles/CircleExecutionState.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java index 7918d90812..f95fa84f01 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java @@ -237,6 +237,9 @@ public boolean tick(BlockEntityAbstractImpetus impetus) { var ctrl = executor.acceptControlFlow(this.currentImage, env, this.enteredFrom, this.currentPos, executorBlockState, world); + if (env.getImpetus() == null) + return false; //the impetus got removed during the cast and no longer exists in the world. stop casting + if (ctrl instanceof ICircleComponent.ControlFlow.Stop) { // acceptControlFlow should have already posted the error halt = true; From f670ad566fbc1ae80d6606ce68678addefb6d3ce Mon Sep 17 00:00:00 2001 From: SamsTheNerd Date: Fri, 2 Aug 2024 12:24:07 -0400 Subject: [PATCH 21/39] make focus and thought knot re-use some writeable checks --- .../at/petrak/hexcasting/common/items/storage/ItemFocus.java | 2 +- .../petrak/hexcasting/common/items/storage/ItemThoughtKnot.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java index bc3af022b1..424eccadc3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java @@ -50,7 +50,7 @@ public boolean writeable(ItemStack stack) { @Override public boolean canWrite(ItemStack stack, Iota datum) { - return datum == null || !NBTHelper.getBoolean(stack, TAG_SEALED); + return datum == null || !isSealed(stack); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java index da1a2631fc..9e867cc250 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemThoughtKnot.java @@ -39,7 +39,7 @@ public boolean writeable(ItemStack stack) { @Override public boolean canWrite(ItemStack stack, @Nullable Iota iota) { - return iota != null && !NBTHelper.contains(stack, TAG_DATA); + return iota != null && writeable(stack); } @Override From ffcc37df4441199a573876ae86c221a92d18f9ef Mon Sep 17 00:00:00 2001 From: SamsTheNerd Date: Fri, 2 Aug 2024 12:25:56 -0400 Subject: [PATCH 22/39] switch power_neg to exponent. translation is close enough imo? --- .../hexcasting/common/casting/arithmetic/DoubleArithmetic.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt index a111f9958d..07da240b2a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt @@ -57,7 +57,7 @@ object DoubleArithmetic : Arithmetic { MUL -> make2 { a, b -> a * b } DIV -> make2 { a, b -> if (b == 0.0) throw MishapDivideByZero.of(a, b) else a / b } ABS -> make1 { a -> abs(a) } - POW -> make2 { a, b -> if (a < 0 && !DoubleIota.tolerates(floor(b), b)) throw MishapDivideByZero.of(a, b, "power_neg") else a.pow(b) } + POW -> make2 { a, b -> if (a < 0 && !DoubleIota.tolerates(floor(b), b)) throw MishapDivideByZero.of(a, b, "exponent") else a.pow(b) } FLOOR -> make1 { a -> floor(a) } CEIL -> make1 { a -> ceil(a) } SIN -> make1 { a -> sin(a) } From 5f7410fc3d007bb9a52f07b4fb93c8615c1f2f28 Mon Sep 17 00:00:00 2001 From: "[object Object]" Date: Mon, 12 Aug 2024 17:18:57 -0400 Subject: [PATCH 23/39] Add comments and refactor some code to improve clarity --- .../hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt | 6 +++--- .../common/casting/arithmetic/DoubleArithmetic.kt | 1 + .../petrak/hexcasting/common/items/storage/ItemFocus.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt index 7d1410a550..d35104dab4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapBadOffhandItem.kt @@ -17,10 +17,10 @@ class MishapBadOffhandItem(val item: ItemStack?, val wanted: Component) : Mishap env.mishapEnvironment.dropHeldItems() } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item?.isEmpty != false) - error("no_item.offhand", wanted) - else + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item?.isEmpty == false) error("bad_item.offhand", wanted, item.count, item.displayName) + else + error("no_item.offhand", wanted) companion object { @JvmStatic diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt index 07da240b2a..075a17a76f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/arithmetic/DoubleArithmetic.kt @@ -57,6 +57,7 @@ object DoubleArithmetic : Arithmetic { MUL -> make2 { a, b -> a * b } DIV -> make2 { a, b -> if (b == 0.0) throw MishapDivideByZero.of(a, b) else a / b } ABS -> make1 { a -> abs(a) } + // throw MishapDivideByZero if raising a negative number to a fractional power (ie. sqrt(-1) etc) POW -> make2 { a, b -> if (a < 0 && !DoubleIota.tolerates(floor(b), b)) throw MishapDivideByZero.of(a, b, "exponent") else a.pow(b) } FLOOR -> make1 { a -> floor(a) } CEIL -> make1 { a -> ceil(a) } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java index 424eccadc3..8d08c9923f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/storage/ItemFocus.java @@ -45,7 +45,7 @@ public String getDescriptionId(ItemStack stack) { @Override public boolean writeable(ItemStack stack) { - return !NBTHelper.getBoolean(stack, TAG_SEALED); + return !isSealed(stack); } @Override From 0681c820f36fda780b5c5551945fdbf4ee6286c7 Mon Sep 17 00:00:00 2001 From: Skye Date: Wed, 14 Aug 2024 23:27:21 +0900 Subject: [PATCH 24/39] Make Break Block check for permission fixes FallingColors/HexMod#678 --- .../common/casting/actions/spells/OpBreakBlock.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBreakBlock.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBreakBlock.kt index 93d1301977..6031adb0b7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBreakBlock.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBreakBlock.kt @@ -10,6 +10,7 @@ import at.petrak.hexcasting.api.misc.MediaConstants import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.xplat.IXplatAbstractions import net.minecraft.core.BlockPos +import net.minecraft.server.level.ServerPlayer import net.minecraft.world.phys.Vec3 object OpBreakBlock : SpellAction { @@ -40,6 +41,12 @@ object OpBreakBlock : SpellAction { !blockstate.isAir && blockstate.getDestroySpeed(env.world, pos) >= 0f // fix being able to break bedrock &c && IXplatAbstractions.INSTANCE.isCorrectTierForDrops(tier, blockstate) + && IXplatAbstractions.INSTANCE.isBreakingAllowed( + env.world, + pos, + blockstate, + env.castingEntity as? ServerPlayer + ) ) { env.world.destroyBlock(pos, true, env.castingEntity) } From cf432c0809fffb9464b57e200d1b6c5bb3a678dd Mon Sep 17 00:00:00 2001 From: Skye Date: Thu, 15 Aug 2024 21:09:05 +0900 Subject: [PATCH 25/39] Fixes Empty Impetus not accepting pulses from the back. Fixes #656 --- .../hexcasting/common/blocks/circles/BlockEmptyImpetus.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEmptyImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEmptyImpetus.java index 07adca100d..2cac9c79f1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEmptyImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEmptyImpetus.java @@ -38,7 +38,7 @@ public ControlFlow acceptControlFlow(CastingImage imageIn, CircleCastEnv env, Di @Override public boolean canEnterFromDirection(Direction enterDir, BlockPos pos, BlockState bs, ServerLevel world) { - return enterDir != bs.getValue(FACING); + return enterDir != bs.getValue(FACING).getOpposite(); } @Override From 54f7dcc1d5cddb7581c84f84e2c01b9959fd78fc Mon Sep 17 00:00:00 2001 From: Skye Date: Mon, 19 Aug 2024 04:43:19 +0000 Subject: [PATCH 26/39] Allow for playerless block raycasts --- .../actions/raycast/OpBlockAxisRaycast.kt | 3 +-- .../casting/actions/raycast/OpBlockRaycast.kt | 4 ++-- .../hexcasting/mixin/MixinClipContext.java | 20 +++++++++++++++++++ Common/src/main/resources/hexplat.mixins.json | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 Common/src/main/java/at/petrak/hexcasting/mixin/MixinClipContext.java diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockAxisRaycast.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockAxisRaycast.kt index 6e066638d6..2aa68ecf28 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockAxisRaycast.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockAxisRaycast.kt @@ -8,12 +8,10 @@ import at.petrak.hexcasting.api.casting.getVec3 import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.api.misc.MediaConstants -import net.minecraft.world.entity.Entity import net.minecraft.world.level.ClipContext import net.minecraft.world.phys.HitResult import net.minecraft.world.phys.Vec3 -@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") object OpBlockAxisRaycast : ConstMediaAction { override val argc = 2 override val mediaCost: Long = MediaConstants.DUST_UNIT / 100 @@ -29,6 +27,7 @@ object OpBlockAxisRaycast : ConstMediaAction { Action.raycastEnd(origin, look), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, + @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") env.castingEntity ) ) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockRaycast.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockRaycast.kt index 1fce74df5a..33a2e990eb 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockRaycast.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/raycast/OpBlockRaycast.kt @@ -8,7 +8,6 @@ import at.petrak.hexcasting.api.casting.getVec3 import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.api.misc.MediaConstants -import net.minecraft.world.entity.Entity import net.minecraft.world.level.ClipContext import net.minecraft.world.phys.HitResult import net.minecraft.world.phys.Vec3 @@ -28,7 +27,8 @@ object OpBlockRaycast : ConstMediaAction { Action.raycastEnd(origin, look), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, - env.castingEntity as Entity + @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") + env.castingEntity ) ) diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinClipContext.java b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinClipContext.java new file mode 100644 index 0000000000..22dadc7c9d --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinClipContext.java @@ -0,0 +1,20 @@ +package at.petrak.hexcasting.mixin; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.phys.shapes.CollisionContext; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ClipContext.class) +public class MixinClipContext { + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/shapes/CollisionContext;of(Lnet/minecraft/world/entity/Entity;)Lnet/minecraft/world/phys/shapes/CollisionContext;")) + private CollisionContext allowNullEntity(Entity entity) { + if (entity == null) { + return CollisionContext.empty(); + } else { + return CollisionContext.of(entity); + } + } +} \ No newline at end of file diff --git a/Common/src/main/resources/hexplat.mixins.json b/Common/src/main/resources/hexplat.mixins.json index 1d2ac13000..3619793359 100644 --- a/Common/src/main/resources/hexplat.mixins.json +++ b/Common/src/main/resources/hexplat.mixins.json @@ -6,6 +6,7 @@ "package": "at.petrak.hexcasting.mixin", "mixins": [ "MixinAbstractVillager", + "MixinClipContext", "MixinMob", "MixinRaider", "MixinVillager", From 5f434ed672da998e19f240087493738a93e8d22e Mon Sep 17 00:00:00 2001 From: navarchus Date: Mon, 19 Aug 2024 23:00:54 -0400 Subject: [PATCH 27/39] Prevent crashes due to unbounded growth of a few items. Add configurable setting for max number of iotas on the stack, default is 2048 iotas. --- .../hexcasting/damage_type/stack_size.json | 5 ++ .../hexcasting/api/casting/ActionUtils.kt | 17 +++++ .../api/casting/eval/vm/CastingImage.kt | 18 ++++- .../api/casting/mishaps/MishapStackSize.kt | 23 ++++++ .../petrak/hexcasting/api/mod/HexConfig.java | 3 + .../hexcasting/common/lib/HexDamageTypes.java | 19 +++-- .../datagen/tag/HexDamageTypeTagProvider.java | 7 ++ .../hexcasting/lang/en_us.flatten.json5 | 1 + .../hexcasting/fabric/FabricHexConfig.java | 6 ++ .../hexcasting/forge/ForgeHexConfig.java | 75 +++++++++++-------- 10 files changed, 135 insertions(+), 39 deletions(-) create mode 100644 Common/src/generated/resources/data/hexcasting/damage_type/stack_size.json create mode 100644 Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt diff --git a/Common/src/generated/resources/data/hexcasting/damage_type/stack_size.json b/Common/src/generated/resources/data/hexcasting/damage_type/stack_size.json new file mode 100644 index 0000000000..0cfbe8c15e --- /dev/null +++ b/Common/src/generated/resources/data/hexcasting/damage_type/stack_size.json @@ -0,0 +1,5 @@ +{ + "exhaustion": 0.0, + "message_id": "hexcasting.stack_size", + "scaling": "when_caused_by_living_non_player" +} \ No newline at end of file diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt index 26f39da2f3..c2fffdddb5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt @@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.casting.iota.* import at.petrak.hexcasting.api.casting.math.HexPattern import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs +import at.petrak.hexcasting.api.casting.mishaps.MishapShameOnYou import at.petrak.hexcasting.api.utils.asTranslatedComponent import com.mojang.datafixers.util.Either import net.minecraft.core.BlockPos @@ -22,6 +23,22 @@ import kotlin.math.abs import kotlin.math.roundToInt import kotlin.math.roundToLong +fun List.getIotaListSize(): Int{ + val work = mutableListOf() + work.addAll(this) + var size = 0 + while (work.isNotEmpty()) { + val iota = work.removeLast() + val subiotas = iota.subIotas() + if (subiotas != null) { + work.addAll(subiotas) + } + size += iota.size() + } + + return size +} + fun List.getDouble(idx: Int, argc: Int = 0): Double { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is DoubleIota) { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt index 3ffd771bcd..5ffcaf0b8a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt @@ -12,6 +12,10 @@ import net.minecraft.nbt.ListTag import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.Entity +import at.petrak.hexcasting.api.casting.getIotaListSize +import at.petrak.hexcasting.api.casting.mishaps.MishapStackSize +import at.petrak.hexcasting.api.mod.HexConfig + /** * The state of a casting VM, containing the stack and all @@ -26,6 +30,13 @@ data class CastingImage private constructor( val userData: CompoundTag ) { + init { + val size = stack.getIotaListSize() + if (size > HexConfig.common().stackIotaLimit()) { + throw MishapStackSize() + } + } + constructor() : this(listOf(), 0, listOf(), false, 0, CompoundTag()) data class ParenthesizedIota(val iota: Iota, val escaped: Boolean) { @@ -113,7 +124,12 @@ data class CastingImage private constructor( val parenEscapedTag = parenTag.getByteArray(TAG_ESCAPED) for ((subtag, isEscapedByte) in parenIotasTag.zipWithDefault(parenEscapedTag) { _ -> 0 }) { - parenthesized.add(ParenthesizedIota(IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world), isEscapedByte != 0.toByte())) + parenthesized.add( + ParenthesizedIota( + IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world), + isEscapedByte != 0.toByte() + ) + ) } val parenCount = tag.getInt(TAG_PAREN_COUNT) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt new file mode 100644 index 0000000000..f97016ddec --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt @@ -0,0 +1,23 @@ +package at.petrak.hexcasting.api.casting.mishaps + +import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.pigment.FrozenPigment +import at.petrak.hexcasting.common.lib.HexDamageTypes +import net.minecraft.world.item.DyeColor + +class MishapStackSize() : Mishap() { + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BROWN) + + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + val caster = env.castingEntity + if (caster != null) { + // FIXME: handle null caster case + trulyHurt(caster, caster.damageSources().source(HexDamageTypes.STACK_SIZE), 2f) + } + } + + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("stack_size") +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java index 105994f61d..1aff751988 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java @@ -36,6 +36,9 @@ public interface CommonConfigAccess { int DEFAULT_TRINKET_COOLDOWN = 5; int DEFAULT_ARTIFACT_COOLDOWN = 3; + int DEFAUlT_STACK_IOTA_LIMIT = 2048; + + int stackIotaLimit(); } public interface ClientConfigAccess { diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java index d9f5ad2111..bde8a14ce3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java @@ -11,18 +11,25 @@ public class HexDamageTypes { public static final ResourceKey OVERCAST = ResourceKey.create(Registries.DAMAGE_TYPE, modLoc("overcast")); public static final ResourceKey SHAME_ON_YOU = ResourceKey.create(Registries.DAMAGE_TYPE, modLoc("shame")); + public static final ResourceKey STACK_SIZE = ResourceKey.create(Registries.DAMAGE_TYPE, modLoc("stack_size")); public static void bootstrap(BootstapContext ctx) { ctx.register(OVERCAST, new DamageType( - "hexcasting.overcast", - DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, - 0f + "hexcasting.overcast", + DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, + 0f )); ctx.register(SHAME_ON_YOU, new DamageType( - "hexcasting.shame", - DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, - 0f + "hexcasting.shame", + DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, + 0f + )); + + ctx.register(STACK_SIZE, new DamageType( + "hexcasting.stack_size", + DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, + 0f )); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java index 82eb35e7e2..693f02f98c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java @@ -31,6 +31,13 @@ protected void addTags(@NotNull HolderLookup.Provider provider) { DamageTypeTags.BYPASSES_INVULNERABILITY, DamageTypeTags.BYPASSES_SHIELD ); + + add(HexDamageTypes.STACK_SIZE, + DamageTypeTags.BYPASSES_ARMOR, + DamageTypeTags.BYPASSES_EFFECTS, + DamageTypeTags.BYPASSES_INVULNERABILITY, + DamageTypeTags.BYPASSES_SHIELD + ); } @SafeVarargs diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 index 470c006c0d..0b4258249d 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 @@ -901,6 +901,7 @@ invalid_spell_datum_type: "Tried to use a value of invalid type as a SpellDatum: %s (class %s). This is a bug in the mod.", unknown: "threw an exception (%s). This is a bug in the mod.", shame: "Shame on you!", + stack_size: "My mind was too small to contain the breadth of this spell.", invalid_value: { "": "expected %s at index %s of the stack, but got %s", diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java index 7622e7cf8f..d28df2ef64 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java @@ -77,6 +77,9 @@ public static final class Common implements HexConfig.CommonConfigAccess, Config @ConfigEntry.Gui.Tooltip private int artifactCooldown = DEFAULT_ARTIFACT_COOLDOWN; + @ConfigEntry.Gui.Tooltip + private int stackIotaLimit = DEFAUlT_STACK_IOTA_LIMIT; + @Override public void validatePostLoad() throws ValidationException { @@ -120,6 +123,9 @@ public int trinketCooldown() { public int artifactCooldown() { return artifactCooldown; } + + @Override + public int stackIotaLimit() { return stackIotaLimit;} } @Config(name = "client") diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java index 507d1fece7..038afd9795 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java @@ -20,26 +20,34 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess { private static ForgeConfigSpec.IntValue trinketCooldown; private static ForgeConfigSpec.IntValue artifactCooldown; + private static ForgeConfigSpec.IntValue stackIotaLimit; + public ForgeHexConfig(ForgeConfigSpec.Builder builder) { builder.push("Media Amounts"); dustMediaAmount = builder.comment("How much media a single Amethyst Dust item is worth") - .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); shardMediaAmount = builder.comment("How much media a single Amethyst Shard item is worth") - .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); chargedCrystalMediaAmount = builder.comment("How much media a single Charged Amethyst Crystal item is worth") - .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); mediaToHealthRate = builder.comment("How many points of media a half-heart is worth when casting from HP") - .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); + .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); builder.pop(); builder.push("Cooldowns"); cypherCooldown = builder.comment("Cooldown in ticks of a cypher") - .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); trinketCooldown = builder.comment("Cooldown in ticks of a trinket") - .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); artifactCooldown = builder.comment("Cooldown in ticks of a artifact") - .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); + builder.pop(); + + builder.push("Stack Limitations"); + stackIotaLimit = builder.comment("Max limit of iotas allowed on the stack") + .defineInRange("stackIotaLimit", DEFAUlT_STACK_IOTA_LIMIT, 0, Integer.MAX_VALUE); builder.pop(); + } @Override @@ -77,6 +85,9 @@ public int artifactCooldown() { return artifactCooldown.get(); } + @Override + public int stackIotaLimit() { return stackIotaLimit.get(); } + public static class Client implements HexConfig.ClientConfigAccess { private static ForgeConfigSpec.BooleanValue ctrlTogglesOffStrokeOrder; private static ForgeConfigSpec.BooleanValue invertSpellbookScrollDirection; @@ -85,19 +96,19 @@ public static class Client implements HexConfig.ClientConfigAccess { public Client(ForgeConfigSpec.Builder builder) { ctrlTogglesOffStrokeOrder = builder.comment( - "Whether the ctrl key will instead turn *off* the color gradient on patterns") - .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); + "Whether the ctrl key will instead turn *off* the color gradient on patterns") + .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); invertSpellbookScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + - "vice versa") - .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); + "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + + "vice versa") + .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); invertAbacusScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa") - .define("invertAbacusScrollDirection", DEFAULT_INVERT_ABACUS_SCROLL); + "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); + "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 @@ -144,38 +155,38 @@ public static class Server implements HexConfig.ServerConfigAccess { public Server(ForgeConfigSpec.Builder builder) { builder.push("Spells"); maxOpCount = builder.comment("The maximum number of actions that can be executed in one tick, to avoid " + - "hanging the server.") - .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); + "hanging the server.") + .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); opBreakHarvestLevel = builder.comment( - "The harvest level of the Break Block spell.", - "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." + "The harvest level of the Break Block spell.", + "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." ).defineInRange("opBreakHarvestLevel", DEFAULT_OP_BREAK_HARVEST_LEVEL, 0, 4); builder.pop(); builder.push("Spell Circles"); maxSpellCircleLength = builder.comment("The maximum number of slates in a spell circle") - .defineInRange("maxSpellCircleLength", DEFAULT_MAX_SPELL_CIRCLE_LENGTH, 4, Integer.MAX_VALUE); + .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. For example: hexcasting:get_caster will prevent Mind's Reflection.") - .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); + "Resource locations of disallowed actions within circles. Trying to cast one of these in a circle" + + " will result in a mishap. For example: hexcasting:get_caster will prevent Mind's Reflection.") + .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); builder.pop(); actionDenyList = builder.comment( - "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") - .defineList("actionDenyList", List.of(), Server::isValidReslocArg); + "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") + .defineList("actionDenyList", List.of(), Server::isValidReslocArg); villagersOffendedByMindMurder = builder.comment( - "Should villagers take offense when you flay the mind of their fellow villagers?") - .define("villagersOffendedByMindMurder", true); + "Should villagers take offense when you flay the mind of their fellow villagers?") + .define("villagersOffendedByMindMurder", true); tpDimDenyList = builder.comment("Resource locations of dimensions you can't Blink or Greater Teleport in.") - .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); + .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); doesTrueNameHaveAmbit = builder.comment( - "when false makes player reference iotas behave as normal entity reference iotas") - .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); + "when false makes player reference iotas behave as normal entity reference iotas") + .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); } @Override From 7ec296ce5fb59d74b2e86ce0c68e6c6a1078c357 Mon Sep 17 00:00:00 2001 From: Toby Vestal Date: Tue, 20 Aug 2024 16:07:28 -0400 Subject: [PATCH 28/39] Address comments in discord, scale back changes to mishaps and revert formatting --- .../hexcasting/damage_type/stack_size.json | 5 -- .../hexcasting/api/casting/ActionUtils.kt | 17 ----- .../api/casting/eval/vm/CastingImage.kt | 17 +---- .../api/casting/eval/vm/CastingVM.kt | 14 +++- .../api/casting/mishaps/MishapStackSize.kt | 13 ++-- .../petrak/hexcasting/api/mod/HexConfig.java | 3 - .../hexcasting/common/lib/HexDamageTypes.java | 7 -- .../datagen/tag/HexDamageTypeTagProvider.java | 6 -- .../hexcasting/fabric/FabricHexConfig.java | 4 -- .../hexcasting/forge/ForgeHexConfig.java | 72 +++++++++---------- 10 files changed, 51 insertions(+), 107 deletions(-) delete mode 100644 Common/src/generated/resources/data/hexcasting/damage_type/stack_size.json diff --git a/Common/src/generated/resources/data/hexcasting/damage_type/stack_size.json b/Common/src/generated/resources/data/hexcasting/damage_type/stack_size.json deleted file mode 100644 index 0cfbe8c15e..0000000000 --- a/Common/src/generated/resources/data/hexcasting/damage_type/stack_size.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "exhaustion": 0.0, - "message_id": "hexcasting.stack_size", - "scaling": "when_caused_by_living_non_player" -} \ No newline at end of file diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt index c2fffdddb5..26f39da2f3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt @@ -6,7 +6,6 @@ import at.petrak.hexcasting.api.casting.iota.* import at.petrak.hexcasting.api.casting.math.HexPattern import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs -import at.petrak.hexcasting.api.casting.mishaps.MishapShameOnYou import at.petrak.hexcasting.api.utils.asTranslatedComponent import com.mojang.datafixers.util.Either import net.minecraft.core.BlockPos @@ -23,22 +22,6 @@ import kotlin.math.abs import kotlin.math.roundToInt import kotlin.math.roundToLong -fun List.getIotaListSize(): Int{ - val work = mutableListOf() - work.addAll(this) - var size = 0 - while (work.isNotEmpty()) { - val iota = work.removeLast() - val subiotas = iota.subIotas() - if (subiotas != null) { - work.addAll(subiotas) - } - size += iota.size() - } - - return size -} - fun List.getDouble(idx: Int, argc: Int = 0): Double { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is DoubleIota) { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt index 5ffcaf0b8a..15667309d5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt @@ -12,10 +12,6 @@ import net.minecraft.nbt.ListTag import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.Entity -import at.petrak.hexcasting.api.casting.getIotaListSize -import at.petrak.hexcasting.api.casting.mishaps.MishapStackSize -import at.petrak.hexcasting.api.mod.HexConfig - /** * The state of a casting VM, containing the stack and all @@ -30,12 +26,6 @@ data class CastingImage private constructor( val userData: CompoundTag ) { - init { - val size = stack.getIotaListSize() - if (size > HexConfig.common().stackIotaLimit()) { - throw MishapStackSize() - } - } constructor() : this(listOf(), 0, listOf(), false, 0, CompoundTag()) @@ -124,12 +114,7 @@ data class CastingImage private constructor( val parenEscapedTag = parenTag.getByteArray(TAG_ESCAPED) for ((subtag, isEscapedByte) in parenIotasTag.zipWithDefault(parenEscapedTag) { _ -> 0 }) { - parenthesized.add( - ParenthesizedIota( - IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world), - isEscapedByte != 0.toByte() - ) - ) + parenthesized.add(ParenthesizedIota(IotaType.deserialize(subtag.downcast(CompoundTag.TYPE), world), isEscapedByte != 0.toByte())) } val parenCount = tag.getInt(TAG_PAREN_COUNT) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index 849a43ba20..7de56bd08f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -8,6 +8,7 @@ import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect import at.petrak.hexcasting.api.casting.eval.vm.CastingImage.ParenthesizedIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.IotaType +import at.petrak.hexcasting.api.casting.iota.IotaType.isTooLargeToSerialize import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.casting.iota.PatternIota import at.petrak.hexcasting.api.casting.math.HexDir @@ -53,12 +54,19 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { val image2 = next.evaluate(continuation.next, world, this) // Then write all pertinent data back to the harness for the next iteration. if (image2.newData != null) { - this.image = image2.newData + if (isTooLargeToSerialize(image2.newData.stack)){ + // Ugly cast, probably need to rethink location + (image2.sideEffects as MutableList).add(OperatorSideEffect.DoMishap(MishapStackSize(), Mishap.Context(null, null))) + lastResolutionType = ResolvedPatternType.ERRORED + }else { + continuation = image2.continuation + lastResolutionType = image2.resolutionType + this.image = image2.newData + } } + this.env.postExecution(image2) - continuation = image2.continuation - lastResolutionType = image2.resolutionType try { performSideEffects(info, image2.sideEffects) } catch (e: Exception) { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt index f97016ddec..571e39bcd9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt @@ -1,6 +1,8 @@ package at.petrak.hexcasting.api.casting.mishaps import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType +import at.petrak.hexcasting.api.casting.iota.GarbageIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.pigment.FrozenPigment import at.petrak.hexcasting.common.lib.HexDamageTypes @@ -8,14 +10,13 @@ import net.minecraft.world.item.DyeColor class MishapStackSize() : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.BROWN) + dyeColor(DyeColor.BLACK) + + override fun resolutionType(ctx: CastingEnvironment) = ResolvedPatternType.ERRORED override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { - val caster = env.castingEntity - if (caster != null) { - // FIXME: handle null caster case - trulyHurt(caster, caster.damageSources().source(HexDamageTypes.STACK_SIZE), 2f) - } + stack.clear() + stack.add(GarbageIota()) } override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = diff --git a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java index 1aff751988..105994f61d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexConfig.java @@ -36,9 +36,6 @@ public interface CommonConfigAccess { int DEFAULT_TRINKET_COOLDOWN = 5; int DEFAULT_ARTIFACT_COOLDOWN = 3; - int DEFAUlT_STACK_IOTA_LIMIT = 2048; - - int stackIotaLimit(); } public interface ClientConfigAccess { diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java index bde8a14ce3..80121e15a0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java @@ -11,7 +11,6 @@ public class HexDamageTypes { public static final ResourceKey OVERCAST = ResourceKey.create(Registries.DAMAGE_TYPE, modLoc("overcast")); public static final ResourceKey SHAME_ON_YOU = ResourceKey.create(Registries.DAMAGE_TYPE, modLoc("shame")); - public static final ResourceKey STACK_SIZE = ResourceKey.create(Registries.DAMAGE_TYPE, modLoc("stack_size")); public static void bootstrap(BootstapContext ctx) { ctx.register(OVERCAST, new DamageType( @@ -25,11 +24,5 @@ public static void bootstrap(BootstapContext ctx) { DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, 0f )); - - ctx.register(STACK_SIZE, new DamageType( - "hexcasting.stack_size", - DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, - 0f - )); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java index 693f02f98c..de891b315d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java @@ -32,12 +32,6 @@ protected void addTags(@NotNull HolderLookup.Provider provider) { DamageTypeTags.BYPASSES_SHIELD ); - add(HexDamageTypes.STACK_SIZE, - DamageTypeTags.BYPASSES_ARMOR, - DamageTypeTags.BYPASSES_EFFECTS, - DamageTypeTags.BYPASSES_INVULNERABILITY, - DamageTypeTags.BYPASSES_SHIELD - ); } @SafeVarargs diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java index d28df2ef64..fecf1a5397 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java @@ -77,8 +77,6 @@ public static final class Common implements HexConfig.CommonConfigAccess, Config @ConfigEntry.Gui.Tooltip private int artifactCooldown = DEFAULT_ARTIFACT_COOLDOWN; - @ConfigEntry.Gui.Tooltip - private int stackIotaLimit = DEFAUlT_STACK_IOTA_LIMIT; @Override @@ -124,8 +122,6 @@ public int artifactCooldown() { return artifactCooldown; } - @Override - public int stackIotaLimit() { return stackIotaLimit;} } @Config(name = "client") diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java index 038afd9795..6ad3203365 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java @@ -25,27 +25,22 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess { public ForgeHexConfig(ForgeConfigSpec.Builder builder) { builder.push("Media Amounts"); dustMediaAmount = builder.comment("How much media a single Amethyst Dust item is worth") - .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); shardMediaAmount = builder.comment("How much media a single Amethyst Shard item is worth") - .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); chargedCrystalMediaAmount = builder.comment("How much media a single Charged Amethyst Crystal item is worth") - .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); mediaToHealthRate = builder.comment("How many points of media a half-heart is worth when casting from HP") - .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); + .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); builder.pop(); builder.push("Cooldowns"); cypherCooldown = builder.comment("Cooldown in ticks of a cypher") - .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); trinketCooldown = builder.comment("Cooldown in ticks of a trinket") - .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); artifactCooldown = builder.comment("Cooldown in ticks of a artifact") - .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); - builder.pop(); - - builder.push("Stack Limitations"); - stackIotaLimit = builder.comment("Max limit of iotas allowed on the stack") - .defineInRange("stackIotaLimit", DEFAUlT_STACK_IOTA_LIMIT, 0, Integer.MAX_VALUE); + .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); builder.pop(); } @@ -85,9 +80,6 @@ public int artifactCooldown() { return artifactCooldown.get(); } - @Override - public int stackIotaLimit() { return stackIotaLimit.get(); } - public static class Client implements HexConfig.ClientConfigAccess { private static ForgeConfigSpec.BooleanValue ctrlTogglesOffStrokeOrder; private static ForgeConfigSpec.BooleanValue invertSpellbookScrollDirection; @@ -96,19 +88,19 @@ public static class Client implements HexConfig.ClientConfigAccess { public Client(ForgeConfigSpec.Builder builder) { ctrlTogglesOffStrokeOrder = builder.comment( - "Whether the ctrl key will instead turn *off* the color gradient on patterns") - .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); + "Whether the ctrl key will instead turn *off* the color gradient on patterns") + .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); invertSpellbookScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + - "vice versa") - .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); + "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + + "vice versa") + .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); invertAbacusScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa") - .define("invertAbacusScrollDirection", DEFAULT_INVERT_ABACUS_SCROLL); + "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); + "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 @@ -155,38 +147,38 @@ public static class Server implements HexConfig.ServerConfigAccess { public Server(ForgeConfigSpec.Builder builder) { builder.push("Spells"); maxOpCount = builder.comment("The maximum number of actions that can be executed in one tick, to avoid " + - "hanging the server.") - .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); + "hanging the server.") + .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); opBreakHarvestLevel = builder.comment( - "The harvest level of the Break Block spell.", - "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." + "The harvest level of the Break Block spell.", + "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." ).defineInRange("opBreakHarvestLevel", DEFAULT_OP_BREAK_HARVEST_LEVEL, 0, 4); builder.pop(); builder.push("Spell Circles"); maxSpellCircleLength = builder.comment("The maximum number of slates in a spell circle") - .defineInRange("maxSpellCircleLength", DEFAULT_MAX_SPELL_CIRCLE_LENGTH, 4, Integer.MAX_VALUE); + .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. For example: hexcasting:get_caster will prevent Mind's Reflection.") - .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); + "Resource locations of disallowed actions within circles. Trying to cast one of these in a circle" + + " will result in a mishap. For example: hexcasting:get_caster will prevent Mind's Reflection.") + .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); builder.pop(); actionDenyList = builder.comment( - "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") - .defineList("actionDenyList", List.of(), Server::isValidReslocArg); + "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") + .defineList("actionDenyList", List.of(), Server::isValidReslocArg); villagersOffendedByMindMurder = builder.comment( - "Should villagers take offense when you flay the mind of their fellow villagers?") - .define("villagersOffendedByMindMurder", true); + "Should villagers take offense when you flay the mind of their fellow villagers?") + .define("villagersOffendedByMindMurder", true); tpDimDenyList = builder.comment("Resource locations of dimensions you can't Blink or Greater Teleport in.") - .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); + .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); doesTrueNameHaveAmbit = builder.comment( - "when false makes player reference iotas behave as normal entity reference iotas") - .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); + "when false makes player reference iotas behave as normal entity reference iotas") + .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); } @Override From 765ed926e15b9bafda1fdcfc6945859d9ced708a Mon Sep 17 00:00:00 2001 From: Toby Vestal Date: Tue, 20 Aug 2024 16:14:07 -0400 Subject: [PATCH 29/39] formatting revert 2 --- .../api/casting/eval/vm/CastingImage.kt | 1 - .../hexcasting/common/lib/HexDamageTypes.java | 12 ++-- .../datagen/tag/HexDamageTypeTagProvider.java | 1 - .../hexcasting/fabric/FabricHexConfig.java | 2 - .../hexcasting/forge/ForgeHexConfig.java | 69 +++++++++---------- 5 files changed, 39 insertions(+), 46 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt index 15667309d5..3ffd771bcd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingImage.kt @@ -26,7 +26,6 @@ data class CastingImage private constructor( val userData: CompoundTag ) { - constructor() : this(listOf(), 0, listOf(), false, 0, CompoundTag()) data class ParenthesizedIota(val iota: Iota, val escaped: Boolean) { diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java index 80121e15a0..d9f5ad2111 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexDamageTypes.java @@ -14,15 +14,15 @@ public class HexDamageTypes { public static void bootstrap(BootstapContext ctx) { ctx.register(OVERCAST, new DamageType( - "hexcasting.overcast", - DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, - 0f + "hexcasting.overcast", + DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, + 0f )); ctx.register(SHAME_ON_YOU, new DamageType( - "hexcasting.shame", - DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, - 0f + "hexcasting.shame", + DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, + 0f )); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java index de891b315d..82eb35e7e2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java @@ -31,7 +31,6 @@ protected void addTags(@NotNull HolderLookup.Provider provider) { DamageTypeTags.BYPASSES_INVULNERABILITY, DamageTypeTags.BYPASSES_SHIELD ); - } @SafeVarargs diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java index fecf1a5397..7622e7cf8f 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexConfig.java @@ -78,7 +78,6 @@ public static final class Common implements HexConfig.CommonConfigAccess, Config private int artifactCooldown = DEFAULT_ARTIFACT_COOLDOWN; - @Override public void validatePostLoad() throws ValidationException { this.dustMediaAmount = Math.max(this.dustMediaAmount, 0); @@ -121,7 +120,6 @@ public int trinketCooldown() { public int artifactCooldown() { return artifactCooldown; } - } @Config(name = "client") diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java index 6ad3203365..d3471fdd97 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java @@ -20,29 +20,26 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess { private static ForgeConfigSpec.IntValue trinketCooldown; private static ForgeConfigSpec.IntValue artifactCooldown; - private static ForgeConfigSpec.IntValue stackIotaLimit; - public ForgeHexConfig(ForgeConfigSpec.Builder builder) { builder.push("Media Amounts"); dustMediaAmount = builder.comment("How much media a single Amethyst Dust item is worth") - .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); shardMediaAmount = builder.comment("How much media a single Amethyst Shard item is worth") - .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); chargedCrystalMediaAmount = builder.comment("How much media a single Charged Amethyst Crystal item is worth") - .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); mediaToHealthRate = builder.comment("How many points of media a half-heart is worth when casting from HP") - .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); + .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); builder.pop(); builder.push("Cooldowns"); cypherCooldown = builder.comment("Cooldown in ticks of a cypher") - .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); trinketCooldown = builder.comment("Cooldown in ticks of a trinket") - .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); artifactCooldown = builder.comment("Cooldown in ticks of a artifact") - .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); builder.pop(); - } @Override @@ -88,19 +85,19 @@ public static class Client implements HexConfig.ClientConfigAccess { public Client(ForgeConfigSpec.Builder builder) { ctrlTogglesOffStrokeOrder = builder.comment( - "Whether the ctrl key will instead turn *off* the color gradient on patterns") - .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); + "Whether the ctrl key will instead turn *off* the color gradient on patterns") + .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); invertSpellbookScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + - "vice versa") - .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); + "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + + "vice versa") + .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); invertAbacusScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa") - .define("invertAbacusScrollDirection", DEFAULT_INVERT_ABACUS_SCROLL); + "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); + "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 @@ -147,38 +144,38 @@ public static class Server implements HexConfig.ServerConfigAccess { public Server(ForgeConfigSpec.Builder builder) { builder.push("Spells"); maxOpCount = builder.comment("The maximum number of actions that can be executed in one tick, to avoid " + - "hanging the server.") - .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); + "hanging the server.") + .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); opBreakHarvestLevel = builder.comment( - "The harvest level of the Break Block spell.", - "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." + "The harvest level of the Break Block spell.", + "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." ).defineInRange("opBreakHarvestLevel", DEFAULT_OP_BREAK_HARVEST_LEVEL, 0, 4); builder.pop(); builder.push("Spell Circles"); maxSpellCircleLength = builder.comment("The maximum number of slates in a spell circle") - .defineInRange("maxSpellCircleLength", DEFAULT_MAX_SPELL_CIRCLE_LENGTH, 4, Integer.MAX_VALUE); + .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. For example: hexcasting:get_caster will prevent Mind's Reflection.") - .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); + "Resource locations of disallowed actions within circles. Trying to cast one of these in a circle" + + " will result in a mishap. For example: hexcasting:get_caster will prevent Mind's Reflection.") + .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); builder.pop(); actionDenyList = builder.comment( - "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") - .defineList("actionDenyList", List.of(), Server::isValidReslocArg); + "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") + .defineList("actionDenyList", List.of(), Server::isValidReslocArg); villagersOffendedByMindMurder = builder.comment( - "Should villagers take offense when you flay the mind of their fellow villagers?") - .define("villagersOffendedByMindMurder", true); + "Should villagers take offense when you flay the mind of their fellow villagers?") + .define("villagersOffendedByMindMurder", true); tpDimDenyList = builder.comment("Resource locations of dimensions you can't Blink or Greater Teleport in.") - .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); + .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); doesTrueNameHaveAmbit = builder.comment( - "when false makes player reference iotas behave as normal entity reference iotas") - .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); + "when false makes player reference iotas behave as normal entity reference iotas") + .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); } @Override @@ -225,4 +222,4 @@ private static boolean isValidReslocArg(Object o) { return o instanceof String s && ResourceLocation.isValidResourceLocation(s); } } -} +} \ No newline at end of file From 9600a8f0306cd8387bf8f7c13f1e827a5054d1fe Mon Sep 17 00:00:00 2001 From: Toby Vestal Date: Tue, 20 Aug 2024 16:55:10 -0400 Subject: [PATCH 30/39] copy result instead of casting to mutable list --- .../api/casting/eval/vm/CastingVM.kt | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index 7de56bd08f..34ad0cddde 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -51,22 +51,30 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { // ...and execute it. // TODO there used to be error checking code here; I'm pretty sure any and all mishaps should already // get caught and folded into CastResult by evaluate. - val image2 = next.evaluate(continuation.next, world, this) + val image2 = next.evaluate(continuation.next, world, this).let { result -> + // if stack is unable to be serialized, have the result be an error + if (result.newData != null && isTooLargeToSerialize(result.newData.stack)) { + result.copy( + newData = null, + sideEffects = result.sideEffects + OperatorSideEffect.DoMishap(MishapStackSize(), Mishap.Context(null, null)), + resolutionType = ResolvedPatternType.ERRORED, + sound = HexEvalSounds.MISHAP, + ) + } else { + result + } + } + // Then write all pertinent data back to the harness for the next iteration. if (image2.newData != null) { - if (isTooLargeToSerialize(image2.newData.stack)){ - // Ugly cast, probably need to rethink location - (image2.sideEffects as MutableList).add(OperatorSideEffect.DoMishap(MishapStackSize(), Mishap.Context(null, null))) - lastResolutionType = ResolvedPatternType.ERRORED - }else { - continuation = image2.continuation - lastResolutionType = image2.resolutionType - this.image = image2.newData - } + this.image = image2.newData } this.env.postExecution(image2) + continuation = image2.continuation + lastResolutionType = image2.resolutionType + try { performSideEffects(info, image2.sideEffects) } catch (e: Exception) { From bafcbdd314c2e5393b0dbf8368789089ea652feb Mon Sep 17 00:00:00 2001 From: Toby Vestal Date: Tue, 20 Aug 2024 17:10:01 -0400 Subject: [PATCH 31/39] addressed comments --- .../api/casting/eval/vm/CastingVM.kt | 7 +- .../hexcasting/lang/en_us.flatten.json5 | 2 +- .../hexcasting/forge/ForgeHexConfig.java | 66 +++++++++---------- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt index 34ad0cddde..8c605d9fb2 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/CastingVM.kt @@ -8,7 +8,6 @@ import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect import at.petrak.hexcasting.api.casting.eval.vm.CastingImage.ParenthesizedIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.IotaType -import at.petrak.hexcasting.api.casting.iota.IotaType.isTooLargeToSerialize import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.casting.iota.PatternIota import at.petrak.hexcasting.api.casting.math.HexDir @@ -53,10 +52,10 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { // get caught and folded into CastResult by evaluate. val image2 = next.evaluate(continuation.next, world, this).let { result -> // if stack is unable to be serialized, have the result be an error - if (result.newData != null && isTooLargeToSerialize(result.newData.stack)) { + if (result.newData != null && IotaType.isTooLargeToSerialize(result.newData.stack)) { result.copy( newData = null, - sideEffects = result.sideEffects + OperatorSideEffect.DoMishap(MishapStackSize(), Mishap.Context(null, null)), + sideEffects = listOf(OperatorSideEffect.DoMishap(MishapStackSize(), Mishap.Context(null, null))), resolutionType = ResolvedPatternType.ERRORED, sound = HexEvalSounds.MISHAP, ) @@ -69,12 +68,10 @@ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { if (image2.newData != null) { this.image = image2.newData } - this.env.postExecution(image2) continuation = image2.continuation lastResolutionType = image2.resolutionType - try { performSideEffects(info, image2.sideEffects) } catch (e: Exception) { diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 index 0b4258249d..a9e89263b4 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 @@ -901,7 +901,7 @@ invalid_spell_datum_type: "Tried to use a value of invalid type as a SpellDatum: %s (class %s). This is a bug in the mod.", unknown: "threw an exception (%s). This is a bug in the mod.", shame: "Shame on you!", - stack_size: "My mind was too small to contain the breadth of this spell.", + stack_size: "Exceeded stack size limit", invalid_value: { "": "expected %s at index %s of the stack, but got %s", diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java index d3471fdd97..507d1fece7 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexConfig.java @@ -23,22 +23,22 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess { public ForgeHexConfig(ForgeConfigSpec.Builder builder) { builder.push("Media Amounts"); dustMediaAmount = builder.comment("How much media a single Amethyst Dust item is worth") - .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("dustMediaAmount", DEFAULT_DUST_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); shardMediaAmount = builder.comment("How much media a single Amethyst Shard item is worth") - .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("shardMediaAmount", DEFAULT_SHARD_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); chargedCrystalMediaAmount = builder.comment("How much media a single Charged Amethyst Crystal item is worth") - .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); + .defineInRange("chargedCrystalMediaAmount", DEFAULT_CHARGED_MEDIA_AMOUNT, 0, Integer.MAX_VALUE); mediaToHealthRate = builder.comment("How many points of media a half-heart is worth when casting from HP") - .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); + .defineInRange("mediaToHealthRate", DEFAULT_MEDIA_TO_HEALTH_RATE, 0.0, Double.POSITIVE_INFINITY); builder.pop(); builder.push("Cooldowns"); cypherCooldown = builder.comment("Cooldown in ticks of a cypher") - .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("cypherCooldown", DEFAULT_CYPHER_COOLDOWN, 0, Integer.MAX_VALUE); trinketCooldown = builder.comment("Cooldown in ticks of a trinket") - .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("trinketCooldown", DEFAULT_TRINKET_COOLDOWN, 0, Integer.MAX_VALUE); artifactCooldown = builder.comment("Cooldown in ticks of a artifact") - .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); + .defineInRange("artifactCooldown", DEFAULT_ARTIFACT_COOLDOWN, 0, Integer.MAX_VALUE); builder.pop(); } @@ -85,19 +85,19 @@ public static class Client implements HexConfig.ClientConfigAccess { public Client(ForgeConfigSpec.Builder builder) { ctrlTogglesOffStrokeOrder = builder.comment( - "Whether the ctrl key will instead turn *off* the color gradient on patterns") - .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); + "Whether the ctrl key will instead turn *off* the color gradient on patterns") + .define("ctrlTogglesOffStrokeOrder", DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER); invertSpellbookScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + - "vice versa") - .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); + "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and " + + "vice versa") + .define("invertSpellbookScrollDirection", DEFAULT_INVERT_SPELLBOOK_SCROLL); invertAbacusScrollDirection = builder.comment( - "Whether scrolling up (as opposed to down) will increase the value of the abacus, and vice versa") - .define("invertAbacusScrollDirection", DEFAULT_INVERT_ABACUS_SCROLL); + "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); + "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 @@ -144,38 +144,38 @@ public static class Server implements HexConfig.ServerConfigAccess { public Server(ForgeConfigSpec.Builder builder) { builder.push("Spells"); maxOpCount = builder.comment("The maximum number of actions that can be executed in one tick, to avoid " + - "hanging the server.") - .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); + "hanging the server.") + .defineInRange("maxOpCount", DEFAULT_MAX_OP_COUNT, 0, Integer.MAX_VALUE); opBreakHarvestLevel = builder.comment( - "The harvest level of the Break Block spell.", - "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." + "The harvest level of the Break Block spell.", + "0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite." ).defineInRange("opBreakHarvestLevel", DEFAULT_OP_BREAK_HARVEST_LEVEL, 0, 4); builder.pop(); builder.push("Spell Circles"); maxSpellCircleLength = builder.comment("The maximum number of slates in a spell circle") - .defineInRange("maxSpellCircleLength", DEFAULT_MAX_SPELL_CIRCLE_LENGTH, 4, Integer.MAX_VALUE); + .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. For example: hexcasting:get_caster will prevent Mind's Reflection.") - .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); + "Resource locations of disallowed actions within circles. Trying to cast one of these in a circle" + + " will result in a mishap. For example: hexcasting:get_caster will prevent Mind's Reflection.") + .defineList("circleActionDenyList", List.of(), Server::isValidReslocArg); builder.pop(); actionDenyList = builder.comment( - "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") - .defineList("actionDenyList", List.of(), Server::isValidReslocArg); + "Resource locations of disallowed actions. Trying to cast one of these will result in a mishap.") + .defineList("actionDenyList", List.of(), Server::isValidReslocArg); villagersOffendedByMindMurder = builder.comment( - "Should villagers take offense when you flay the mind of their fellow villagers?") - .define("villagersOffendedByMindMurder", true); + "Should villagers take offense when you flay the mind of their fellow villagers?") + .define("villagersOffendedByMindMurder", true); tpDimDenyList = builder.comment("Resource locations of dimensions you can't Blink or Greater Teleport in.") - .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); + .defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg); doesTrueNameHaveAmbit = builder.comment( - "when false makes player reference iotas behave as normal entity reference iotas") - .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); + "when false makes player reference iotas behave as normal entity reference iotas") + .define("doesTrueNameHaveAmbit", DEFAULT_TRUE_NAME_HAS_AMBIT); } @Override @@ -222,4 +222,4 @@ private static boolean isValidReslocArg(Object o) { return o instanceof String s && ResourceLocation.isValidResourceLocation(s); } } -} \ No newline at end of file +} From 4d837ccb1fc4b90dd77b7317e3ca2626810f153d Mon Sep 17 00:00:00 2001 From: Toby Vestal Date: Tue, 20 Aug 2024 17:15:18 -0400 Subject: [PATCH 32/39] Update Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 Co-authored-by: [object Object] --- .../main/resources/assets/hexcasting/lang/en_us.flatten.json5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 index a9e89263b4..9188928801 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 @@ -901,7 +901,7 @@ invalid_spell_datum_type: "Tried to use a value of invalid type as a SpellDatum: %s (class %s). This is a bug in the mod.", unknown: "threw an exception (%s). This is a bug in the mod.", shame: "Shame on you!", - stack_size: "Exceeded stack size limit", + stack_size: "Exceeded the size limit of the stack", invalid_value: { "": "expected %s at index %s of the stack, but got %s", From 56859d8b245398ab5edd8be20a49267e78248484 Mon Sep 17 00:00:00 2001 From: object-Object Date: Tue, 20 Aug 2024 19:17:58 -0400 Subject: [PATCH 33/39] Remove unnecessary MixinClipContext mixin (see comments of #719) --- .../hexcasting/mixin/MixinClipContext.java | 20 ------------------- Common/src/main/resources/hexplat.mixins.json | 1 - 2 files changed, 21 deletions(-) delete mode 100644 Common/src/main/java/at/petrak/hexcasting/mixin/MixinClipContext.java diff --git a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinClipContext.java b/Common/src/main/java/at/petrak/hexcasting/mixin/MixinClipContext.java deleted file mode 100644 index 22dadc7c9d..0000000000 --- a/Common/src/main/java/at/petrak/hexcasting/mixin/MixinClipContext.java +++ /dev/null @@ -1,20 +0,0 @@ -package at.petrak.hexcasting.mixin; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.ClipContext; -import net.minecraft.world.phys.shapes.CollisionContext; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(ClipContext.class) -public class MixinClipContext { - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/phys/shapes/CollisionContext;of(Lnet/minecraft/world/entity/Entity;)Lnet/minecraft/world/phys/shapes/CollisionContext;")) - private CollisionContext allowNullEntity(Entity entity) { - if (entity == null) { - return CollisionContext.empty(); - } else { - return CollisionContext.of(entity); - } - } -} \ No newline at end of file diff --git a/Common/src/main/resources/hexplat.mixins.json b/Common/src/main/resources/hexplat.mixins.json index 3619793359..1d2ac13000 100644 --- a/Common/src/main/resources/hexplat.mixins.json +++ b/Common/src/main/resources/hexplat.mixins.json @@ -6,7 +6,6 @@ "package": "at.petrak.hexcasting.mixin", "mixins": [ "MixinAbstractVillager", - "MixinClipContext", "MixinMob", "MixinRaider", "MixinVillager", From 4b965305f45a75056d6b7ce80ceae7a1b7aeaee4 Mon Sep 17 00:00:00 2001 From: Skye Date: Mon, 19 Aug 2024 06:54:48 +0000 Subject: [PATCH 34/39] Don't try to getStoredPlayer on client --- .../circles/impetuses/BlockEntityRedstoneImpetus.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java index c46b7aeedf..b776d156ce 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java @@ -40,9 +40,11 @@ public BlockEntityRedstoneImpetus(BlockPos pWorldPosition, BlockState pBlockStat protected @Nullable GameProfile getPlayerName() { - Player player = getStoredPlayer(); - if (player != null) { - return player.getGameProfile(); + if (this.level instanceof ServerLevel) { + Player player = getStoredPlayer(); + if (player != null) { + return player.getGameProfile(); + } } return this.storedPlayerProfile; From 44e28dcf602083f93befe3bf9de0259f4026325a Mon Sep 17 00:00:00 2001 From: object-Object Date: Wed, 21 Aug 2024 13:28:55 -0400 Subject: [PATCH 35/39] Add step to upload build artifacts --- .github/workflows/pr.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e4e5a10143..65faa334d7 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -39,6 +39,14 @@ jobs: git add --intent-to-add . git diff --name-only --exit-code -- ":!:*/src/generated/resources/.cache/*" + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + path: | + Common/build/libs/*.jar + Forge/build/libs/*.jar + Fabric/build/libs/*.jar + hexdoc: uses: hexdoc-dev/hexdoc/.github/workflows/hexdoc.yml@main permissions: From d573eb5569935a2681a2998937a1fe74e86ecbc0 Mon Sep 17 00:00:00 2001 From: object-Object Date: Wed, 21 Aug 2024 13:37:08 -0400 Subject: [PATCH 36/39] Trigger Gradle build on pushes to the default branch so the cache stays up to date --- .github/workflows/pr.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 65faa334d7..f46da44336 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,6 +6,9 @@ name: Build pull request on: pull_request: workflow_dispatch: + # trigger on pushes to the default branch (main) to keep the cache up to date + push: + branches: main jobs: build: @@ -48,6 +51,8 @@ jobs: Fabric/build/libs/*.jar hexdoc: + # don't bother running the docs build when pushing to main - nothing necessary to cache here + if: github.event_name != 'push' uses: hexdoc-dev/hexdoc/.github/workflows/hexdoc.yml@main permissions: contents: write From b880aa86177e894419e386aa803df855f0dc5d7d Mon Sep 17 00:00:00 2001 From: object-Object Date: Wed, 21 Aug 2024 15:21:23 -0400 Subject: [PATCH 37/39] Flatten build artifact structure and add artifact name --- .github/workflows/pr.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f46da44336..276bf89fdc 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -30,25 +30,28 @@ jobs: # ForgeGradle datagen asset download often fails (see #692) # so just allow it to automatically retry a few times - - name: Run Datagen + - name: Run datagen uses: nick-fields/retry@v3 with: timeout_minutes: 10 max_attempts: 3 command: ./gradlew runAllDatagen - - name: Check Datagen + - name: Check datagen run: | git add --intent-to-add . git diff --name-only --exit-code -- ":!:*/src/generated/resources/.cache/*" - - name: Upload Artifacts + - name: Prepare artifacts for upload + run: | + mkdir -p dist + cp {Common,Forge,Fabric}/build/libs/*.jar dist + + - name: Upload artifacts uses: actions/upload-artifact@v4 with: - path: | - Common/build/libs/*.jar - Forge/build/libs/*.jar - Fabric/build/libs/*.jar + name: mod-build + path: dist hexdoc: # don't bother running the docs build when pushing to main - nothing necessary to cache here From 9fdef827e125bd05805bebb6fd546ea3f00e4892 Mon Sep 17 00:00:00 2001 From: object-Object Date: Wed, 21 Aug 2024 15:35:42 -0400 Subject: [PATCH 38/39] Try running build and datagen in parallel --- .github/workflows/pr.yml | 43 ++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 276bf89fdc..a7b57c0fa8 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -10,6 +10,9 @@ on: push: branches: main +env: + JAVA_VERSION: '17.0.1' + jobs: build: runs-on: ubuntu-latest @@ -20,7 +23,7 @@ jobs: - uses: actions/setup-java@v4 with: distribution: temurin - java-version: "17.0.1" + java-version: ${{ env.JAVA_VERSION }} - uses: gradle/actions/setup-gradle@v3 - name: Build @@ -28,6 +31,29 @@ jobs: chmod +x gradlew ./gradlew build + - name: Prepare artifacts for upload + run: | + mkdir -p dist + cp {Common,Forge,Fabric}/build/libs/*.jar dist + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: mod-build + path: dist + + datagen: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: ${{ env.JAVA_VERSION }} + - uses: gradle/actions/setup-gradle@v3 + # ForgeGradle datagen asset download often fails (see #692) # so just allow it to automatically retry a few times - name: Run datagen @@ -35,24 +61,15 @@ jobs: with: timeout_minutes: 10 max_attempts: 3 - command: ./gradlew runAllDatagen + command: | + chmod +x gradlew + ./gradlew runAllDatagen - name: Check datagen run: | git add --intent-to-add . git diff --name-only --exit-code -- ":!:*/src/generated/resources/.cache/*" - - name: Prepare artifacts for upload - run: | - mkdir -p dist - cp {Common,Forge,Fabric}/build/libs/*.jar dist - - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: mod-build - path: dist - hexdoc: # don't bother running the docs build when pushing to main - nothing necessary to cache here if: github.event_name != 'push' From ca02f95a634a3d3414cde7c724b6f7ea8af0ae70 Mon Sep 17 00:00:00 2001 From: object-Object Date: Wed, 21 Aug 2024 15:47:51 -0400 Subject: [PATCH 39/39] Add 30-day retention period to mod-build artifact --- .github/workflows/pr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index a7b57c0fa8..2600ad5068 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -41,6 +41,7 @@ jobs: with: name: mod-build path: dist + retention-days: 30 datagen: runs-on: ubuntu-latest