diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index fadca52244..2600ad5068 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -6,6 +6,12 @@ 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 + +env: + JAVA_VERSION: '17.0.1' jobs: build: @@ -17,26 +23,57 @@ 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: Clean + + - name: Build run: | chmod +x gradlew - ./gradlew clean + ./gradlew build - - name: Build - run: ./gradlew build + - name: Prepare artifacts for upload + run: | + mkdir -p dist + cp {Common,Forge,Fabric}/build/libs/*.jar dist - - name: Run Datagen - run: ./gradlew runAllDatagen + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: mod-build + path: dist + retention-days: 30 + + 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 + uses: nick-fields/retry@v3 + with: + timeout_minutes: 10 + max_attempts: 3 + command: | + chmod +x gradlew + ./gradlew runAllDatagen - - name: Check Datagen + - name: Check datagen run: | git add --intent-to-add . git diff --name-only --exit-code -- ":!:*/src/generated/resources/.cache/*" 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 diff --git a/Common/src/main/resources/data/hexcasting/damage_type/overcast.json b/Common/src/generated/resources/data/hexcasting/damage_type/overcast.json similarity index 81% rename from Common/src/main/resources/data/hexcasting/damage_type/overcast.json rename to Common/src/generated/resources/data/hexcasting/damage_type/overcast.json index cc59d47153..012582c4b2 100644 --- a/Common/src/main/resources/data/hexcasting/damage_type/overcast.json +++ b/Common/src/generated/resources/data/hexcasting/damage_type/overcast.json @@ -1,5 +1,5 @@ { - "exhaustion": 0, + "exhaustion": 0.0, "message_id": "hexcasting.overcast", "scaling": "when_caused_by_living_non_player" } \ No newline at end of file diff --git a/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_armor.json b/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_armor.json new file mode 100644 index 0000000000..4209c89aa3 --- /dev/null +++ b/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_armor.json @@ -0,0 +1,5 @@ +{ + "values": [ + "hexcasting:overcast" + ] +} \ No newline at end of file diff --git a/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_effects.json b/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_effects.json new file mode 100644 index 0000000000..4209c89aa3 --- /dev/null +++ b/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_effects.json @@ -0,0 +1,5 @@ +{ + "values": [ + "hexcasting:overcast" + ] +} \ No newline at end of file diff --git a/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_shield.json b/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_shield.json new file mode 100644 index 0000000000..4209c89aa3 --- /dev/null +++ b/Common/src/generated/resources/data/minecraft/tags/damage_type/bypasses_shield.json @@ -0,0 +1,5 @@ +{ + "values": [ + "hexcasting:overcast" + ] +} \ No newline at end of file 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..3c74745928 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 @@ -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.utils.HexUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.Nullable; @@ -14,7 +15,7 @@ public interface ADIotaHolder { default Iota readIota(ServerLevel world) { var tag = readIotaTag(); if (tag != null) { - return IotaType.deserialize(tag, world); + return HexUtils.deserializeWithCodec(tag, Iota.getCodec(world)); } else { return null; } @@ -29,4 +30,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/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/ActionUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt index 26f39da2f3..2610cd2219 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 @@ -4,11 +4,13 @@ package at.petrak.hexcasting.api.casting import at.petrak.hexcasting.api.casting.iota.* import at.petrak.hexcasting.api.casting.math.HexPattern +import at.petrak.hexcasting.api.casting.mishaps.MishapEntityNotFound import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota import at.petrak.hexcasting.api.casting.mishaps.MishapNotEnoughArgs import at.petrak.hexcasting.api.utils.asTranslatedComponent import com.mojang.datafixers.util.Either import net.minecraft.core.BlockPos +import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Entity import net.minecraft.world.entity.LivingEntity @@ -32,10 +34,10 @@ fun List.getDouble(idx: Int, argc: Int = 0): Double { } } -fun List.getEntity(idx: Int, argc: Int = 0): Entity { +fun List.getEntity(idx: Int, argc: Int = 0, world: ServerLevel): Entity { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - return x.entity + return x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) } else { throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity") } @@ -79,40 +81,40 @@ fun List.getBool(idx: Int, argc: Int = 0): Boolean { // Helpers -fun List.getItemEntity(idx: Int, argc: Int = 0): ItemEntity { +fun List.getItemEntity(idx: Int, argc: Int = 0, world: ServerLevel): ItemEntity { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - val e = x.entity + val e = x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) if (e is ItemEntity) return e } throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.item") } -fun List.getPlayer(idx: Int, argc: Int = 0): ServerPlayer { +fun List.getPlayer(idx: Int, argc: Int = 0, world: ServerLevel): ServerPlayer { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - val e = x.entity + val e = x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) if (e is ServerPlayer) return e } throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.player") } -fun List.getMob(idx: Int, argc: Int = 0): Mob { +fun List.getMob(idx: Int, argc: Int = 0, world: ServerLevel): Mob { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - val e = x.entity + val e = x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) if (e is Mob) return e } throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.mob") } -fun List.getLivingEntityButNotArmorStand(idx: Int, argc: Int = 0): LivingEntity { +fun List.getLivingEntityButNotArmorStand(idx: Int, argc: Int = 0, world: ServerLevel): LivingEntity { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is EntityIota) { - val e = x.entity + val e = x.getEntity(world)?: throw MishapEntityNotFound(x, if (argc == 0) idx else argc - (idx + 1)) if (e is LivingEntity && e !is ArmorStand) return e } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt index 2e76c18c76..d4684c0f08 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/SpellList.kt @@ -1,6 +1,9 @@ package at.petrak.hexcasting.api.casting import at.petrak.hexcasting.api.casting.iota.Iota +import com.mojang.serialization.Codec +import net.minecraft.server.level.ServerLevel +import java.util.Collections /** * Restricted interface for functional lists. @@ -90,4 +93,12 @@ sealed class SpellList : Iterable { return car } } + + companion object { + @JvmStatic + fun getCodec(): Codec = Iota.getCodec().listOf().xmap(SpellList::LList, SpellList::toMutableList) + + @JvmStatic + fun getCodec(world: ServerLevel): Codec = Iota.getCodec(world).listOf().xmap(SpellList::LList, SpellList::toMutableList) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/OperationAction.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/OperationAction.kt index c2c5b06ee3..1e9a39f80f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/OperationAction.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/castables/OperationAction.kt @@ -18,7 +18,7 @@ data class OperationAction(val pattern: HexPattern) : Action { return try { HexArithmetics.getEngine().run(pattern, env, image, continuation) } catch (e: NoOperatorCandidatesException) { - throw MishapInvalidOperatorArgs(e.args, e.pattern) + throw MishapInvalidOperatorArgs(e.args) } } } \ No newline at end of file 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; 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 d1f447cf85..4b668bddea 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; @@ -10,6 +11,7 @@ import at.petrak.hexcasting.api.pigment.FrozenPigment; import at.petrak.hexcasting.api.utils.HexUtils; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; @@ -27,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Predicate; @@ -42,21 +45,30 @@ public abstract class CastingEnvironment { /** * Stores all listeners that should be notified whenever a CastingEnvironment is initialised. */ - private static final List> createEventListeners = new ArrayList<>(); + private static final List> createEventListeners = new ArrayList<>(); /** * Add a listener that will be called whenever a new CastingEnvironment is created. */ - public static void addCreateEventListener(Consumer listener) { + public static void addCreateEventListener(BiConsumer listener) { createEventListeners.add(listener); } + /** + * Add a listener that will be called whenever a new CastingEnvironment is created (legacy). + * @deprecated replaced by {@link #addCreateEventListener(BiConsumer)} + */ + @Deprecated(since = "0.11.0-pre-660") + public static void addCreateEventListener(Consumer listener) { + createEventListeners.add((env, data) -> {listener.accept(env);}); + } + private boolean createEventTriggered = false; - public final void triggerCreateEvent() { + public final void triggerCreateEvent(CompoundTag userData) { if (!createEventTriggered) { for (var listener : createEventListeners) - listener.accept(this); + listener.accept(this, userData); createEventTriggered = true; } } @@ -66,6 +78,8 @@ 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 preMediaExtract = new ArrayList<>(); private final List postMediaExtract = new ArrayList<>(); @@ -113,6 +127,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) if (extension instanceof ExtractMedia.Pre pre) { preMediaExtract.add(pre); @@ -132,6 +148,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) if (extension instanceof ExtractMedia.Pre pre) { preMediaExtract.remove(pre); @@ -188,6 +206,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(); /** @@ -214,7 +240,7 @@ public boolean isEnlightened() { public long extractMedia(long cost) { for (var extractMediaComponent : preMediaExtract) cost = extractMediaComponent.onExtractMedia(cost); - cost = extractMediaEnvironment(cost); + cost = extractMediaEnvironment(cost); for (var extractMediaComponent : postMediaExtract) cost = extractMediaComponent.onExtractMedia(cost); return cost; 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 c5aac3eacc..faee1de0ba 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/ResolvedPattern.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt index 6108850727..99941a1d6b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/ResolvedPattern.kt @@ -3,11 +3,26 @@ package at.petrak.hexcasting.api.casting.eval import at.petrak.hexcasting.api.casting.math.HexCoord import at.petrak.hexcasting.api.casting.math.HexPattern import at.petrak.hexcasting.api.utils.NBTBuilder +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.nbt.CompoundTag import java.util.* data class ResolvedPattern(val pattern: HexPattern, val origin: HexCoord, var type: ResolvedPatternType) { + constructor(pattern: HexPattern, originQ: Int, originR: Int, type: ResolvedPatternType) : this( + pattern, + HexCoord(originQ, originR), + type + ) + + val originQ: Int + get() = origin.q + + val originR: Int + get() = origin.r + + @Deprecated("Use the CODEC instead.") fun serializeToNBT() = NBTBuilder { "Pattern" %= pattern.serializeToNBT() "OriginQ" %= origin.q @@ -16,6 +31,19 @@ data class ResolvedPattern(val pattern: HexPattern, val origin: HexCoord, var ty } companion object { + @JvmField + val CODEC: Codec = RecordCodecBuilder.create { + it.group( + HexPattern.CODEC.fieldOf("Pattern").forGetter(ResolvedPattern::pattern), + Codec.INT.fieldOf("OriginQ").forGetter(ResolvedPattern::originQ), + Codec.INT.fieldOf("OriginR").forGetter(ResolvedPattern::originR), + Codec.STRING.fieldOf("Valid") + .xmap(ResolvedPatternType::fromString) { type -> type.name.lowercase(Locale.ROOT) } + .forGetter(ResolvedPattern::type) + ).apply(it, ::ResolvedPattern) + } + + @Deprecated("Use the CODEC instead.") @JvmStatic fun fromNBT(tag: CompoundTag): ResolvedPattern { val pattern = HexPattern.fromNBT(tag.getCompound("Pattern")) 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/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 8cbd8d51e6..caa000676e 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 @@ -24,7 +24,7 @@ import net.minecraft.server.level.ServerLevel */ class CastingVM(var image: CastingImage, val env: CastingEnvironment) { init { - env.triggerCreateEvent() + env.triggerCreateEvent(image.userData) } /** @@ -50,7 +50,20 @@ 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 && IotaType.isTooLargeToSerialize(result.newData.stack)) { + result.copy( + newData = null, + sideEffects = listOf(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) { this.image = image2.newData @@ -76,6 +89,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) } @@ -161,7 +176,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 @@ -176,13 +191,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) { @@ -193,7 +208,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)) @@ -203,7 +218,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) { @@ -246,19 +261,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/eval/vm/ContinuationFrame.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt index 8000ec09aa..364657567b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/ContinuationFrame.kt @@ -1,13 +1,17 @@ package at.petrak.hexcasting.api.casting.eval.vm -import at.petrak.hexcasting.api.casting.SpellList +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.utils.deserializeWithCodec import at.petrak.hexcasting.common.lib.hex.HexContinuationTypes +import com.google.common.base.Suppliers +import com.mojang.serialization.Codec +import com.mojang.serialization.MapCodec import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.Tag -import net.minecraft.resources.ResourceLocation +import net.minecraft.nbt.NbtOps import net.minecraft.server.level.ServerLevel +import java.util.function.Supplier /** * A single frame of evaluation during the execution of a spell. @@ -50,59 +54,59 @@ interface ContinuationFrame { val type: Type<*> interface Type { - fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): U? + fun getCodec(): Codec + + fun getCodec(world: ServerLevel): Codec + + @Deprecated( + "Use the CODEC instead.", + replaceWith = ReplaceWith("tag.deserializeWithCodec(getCodec())") + ) + fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): U? = + tag.deserializeWithCodec(getCodec()) } companion object { + @JvmStatic + fun getCodec(): Codec = + HexContinuationTypes.REGISTRY.byNameCodec().dispatchMap( + HexContinuationTypes.KEY_TYPE, + ContinuationFrame::type + ) { continuationType -> + continuationType.getCodec().fieldOf(HexContinuationTypes.KEY_DATA).codec() + }.codec() + + @JvmStatic + fun getCodec(world: ServerLevel): Codec = + HexContinuationTypes.REGISTRY.byNameCodec().dispatchMap( + HexContinuationTypes.KEY_TYPE, + ContinuationFrame::type + ) { continuationType -> + continuationType.getCodec(world).fieldOf(HexContinuationTypes.KEY_DATA).codec() + }.codec() + /** * Takes a tag containing the ContinuationFrame.Type resourcelocation and the serialized continuation frame, and returns * the deserialized continuation frame. */ + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("tag.deserializeWithCodec(ContinuationFrame.getCodec(world))") + ) @JvmStatic - fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame { - val type = getTypeFromTag(tag) ?: return FrameEvaluate(SpellList.LList(0, listOf()), false) - - return (tag.get(HexContinuationTypes.KEY_DATA) as? CompoundTag)?.let { type.deserializeFromNBT(it, world) } - ?: FrameEvaluate(SpellList.LList(0, listOf()), false) - } + fun fromNBT(tag: CompoundTag, world: ServerLevel): ContinuationFrame = + getCodec(world).parse(NbtOps.INSTANCE, tag).resultOrPartial(HexAPI.LOGGER::error).orElseThrow() /** * Takes a continuation frame and serializes it along with its type. */ + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("serializeWithCodec(ContinuationFrame.getCodec())") + ) @JvmStatic - fun toNBT(frame: ContinuationFrame): CompoundTag { - val type = frame.type - val typeId = HexContinuationTypes.REGISTRY.getKey(type) - ?: throw IllegalStateException( - "Tried to serialize an unregistered continuation type. Continuation: " + frame - + " ; Type" + type.javaClass.typeName) - - val data = frame.serializeToNBT() - - val out = CompoundTag() - out.putString(HexContinuationTypes.KEY_TYPE, typeId.toString()) - out.put(HexContinuationTypes.KEY_DATA, data) - return out - } - - /** - * This method attempts to find the type from the `type` key. - * See [ContinuationFrame.serializeToNBT] for the storage format. - * - * @return `null` if it cannot get the type. - */ - private fun getTypeFromTag(tag: CompoundTag): Type<*>? { - if (!tag.contains(HexContinuationTypes.KEY_TYPE, Tag.TAG_STRING.toInt())) { - return null - } - - val typeKey = tag.getString(HexContinuationTypes.KEY_TYPE) - if (!ResourceLocation.isValidResourceLocation(typeKey)) { - return null - } - - val typeLoc = ResourceLocation(typeKey) - return HexContinuationTypes.REGISTRY[typeLoc] - } + fun toNBT(frame: ContinuationFrame): CompoundTag = + getCodec().encodeStart(NbtOps.INSTANCE, frame).resultOrPartial(HexAPI.LOGGER::error) + .orElseThrow() as CompoundTag } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt index 141148dfdc..1405aa7f05 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameEvaluate.kt @@ -1,16 +1,18 @@ package at.petrak.hexcasting.api.casting.eval.vm +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.SpellList import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota -import at.petrak.hexcasting.api.utils.NBTBuilder -import at.petrak.hexcasting.api.utils.getList -import at.petrak.hexcasting.api.utils.serializeToNBT +import at.petrak.hexcasting.api.utils.* import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexIotaTypes +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel @@ -44,14 +46,24 @@ data class FrameEvaluate(val list: SpellList, val isMetacasting: Boolean) : Cont } } else { // If there are no patterns (e.g. empty Hermes), just return OK. - CastResult(ListIota(list), continuation, null, listOf(), ResolvedPatternType.EVALUATED, HexEvalSounds.HERMES) + CastResult( + ListIota(list), + continuation, + null, + listOf(), + ResolvedPatternType.EVALUATED, + HexEvalSounds.HERMES + ) } } - override fun serializeToNBT() = NBTBuilder { - "patterns" %= list.serializeToNBT() - "isMetacasting" %= isMetacasting - } + @Deprecated( + "Use the CODEC instead.", + replaceWith = ReplaceWith("serializeWithCodec(FrameEvaluate.TYPE.getCodec())") + ) + override fun serializeToNBT() = + TYPE.getCodec().encodeStart(NbtOps.INSTANCE, this).resultOrPartial(HexAPI.LOGGER::error) + .orElseThrow() as CompoundTag override fun size() = list.size() @@ -60,15 +72,19 @@ data class FrameEvaluate(val list: SpellList, val isMetacasting: Boolean) : Cont companion object { @JvmField val TYPE: ContinuationFrame.Type = object : ContinuationFrame.Type { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameEvaluate { - return FrameEvaluate( - HexIotaTypes.LIST.deserialize( - tag.getList("patterns", Tag.TAG_COMPOUND), - world - )!!.list, - tag.getBoolean("isMetacasting")) + override fun getCodec(): Codec = RecordCodecBuilder.create { + it.group( + SpellList.getCodec().fieldOf("patterns").forGetter(FrameEvaluate::list), + Codec.BOOL.fieldOf("isMetacasting").forGetter(FrameEvaluate::isMetacasting) + ).apply(it, ::FrameEvaluate) } + override fun getCodec(world: ServerLevel): Codec = RecordCodecBuilder.create { + it.group( + SpellList.getCodec(world).fieldOf("patterns").forGetter(FrameEvaluate::list), + Codec.BOOL.fieldOf("isMetacasting").forGetter(FrameEvaluate::isMetacasting) + ).apply(it, ::FrameEvaluate) + } } } } \ No newline at end of file diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt index 72bbb8c80c..0299b3a72e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameFinishEval.kt @@ -1,12 +1,17 @@ package at.petrak.hexcasting.api.casting.eval.vm +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.NullIota import at.petrak.hexcasting.api.utils.NBTBuilder +import at.petrak.hexcasting.api.utils.deserializeWithCodec +import at.petrak.hexcasting.api.utils.serializeWithCodec import at.petrak.hexcasting.common.lib.hex.HexEvalSounds +import com.mojang.serialization.Codec import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.server.level.ServerLevel /** @@ -14,6 +19,7 @@ import net.minecraft.server.level.ServerLevel * so that we know when to stop removing frames during a Halt. */ object FrameFinishEval : ContinuationFrame { + // Don't do anything else to the stack, just finish the halt statement. override fun breakDownwards(stack: List) = true to stack @@ -33,13 +39,21 @@ object FrameFinishEval : ContinuationFrame { ) } - override fun serializeToNBT() = CompoundTag() + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("serializeWithCodec(FrameFinishEval.TYPE.getCodec())") + ) + override fun serializeToNBT() = + this.serializeWithCodec(TYPE.getCodec()) as CompoundTag override fun size() = 0 @JvmField val TYPE: ContinuationFrame.Type = object : ContinuationFrame.Type { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel) = FrameFinishEval + override fun getCodec(): Codec = Codec.unit { FrameFinishEval } + + override fun getCodec(world: ServerLevel): Codec = Codec.unit { FrameFinishEval } + } override val type = TYPE diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt index 0221c1f36d..0dc5a18bda 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/FrameForEach.kt @@ -1,19 +1,22 @@ package at.petrak.hexcasting.api.casting.eval.vm +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.SpellList import at.petrak.hexcasting.api.casting.eval.CastResult import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType +import at.petrak.hexcasting.api.casting.eval.vm.FrameEvaluate.Companion import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota -import at.petrak.hexcasting.api.utils.NBTBuilder -import at.petrak.hexcasting.api.utils.getList -import at.petrak.hexcasting.api.utils.hasList -import at.petrak.hexcasting.api.utils.serializeToNBT +import at.petrak.hexcasting.api.utils.* import at.petrak.hexcasting.common.lib.hex.HexEvalSounds import at.petrak.hexcasting.common.lib.hex.HexIotaTypes +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel +import java.util.Collections /** * A frame representing all the state for a Thoth evaluation. @@ -81,13 +84,13 @@ data class FrameForEach( ) } - override fun serializeToNBT() = NBTBuilder { - "data" %= data.serializeToNBT() - "code" %= code.serializeToNBT() - if (baseStack != null) - "base" %= baseStack.serializeToNBT() - "accumulator" %= acc.serializeToNBT() - } + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("serializeWithCodec(FrameForEach.TYPE.getCodec())") + ) + override fun serializeToNBT() = + this.serializeWithCodec(TYPE.getCodec()) as CompoundTag + override fun size() = data.size() + code.size() + acc.size + (baseStack?.size ?: 0) @@ -96,21 +99,26 @@ data class FrameForEach( companion object { @JvmField val TYPE: ContinuationFrame.Type = object : ContinuationFrame.Type { - override fun deserializeFromNBT(tag: CompoundTag, world: ServerLevel): FrameForEach { - return FrameForEach( - HexIotaTypes.LIST.deserialize(tag.getList("data", Tag.TAG_COMPOUND), world)!!.list, - HexIotaTypes.LIST.deserialize(tag.getList("code", Tag.TAG_COMPOUND), world)!!.list, - if (tag.hasList("base", Tag.TAG_COMPOUND)) - HexIotaTypes.LIST.deserialize(tag.getList("base", Tag.TAG_COMPOUND), world)!!.list.toList() - else - null, - HexIotaTypes.LIST.deserialize( - tag.getList("accumulator", Tag.TAG_COMPOUND), - world - )!!.list.toMutableList() - ) + override fun getCodec(): Codec = RecordCodecBuilder.create { + it.group( + SpellList.getCodec().fieldOf("data").forGetter(FrameForEach::data), + SpellList.getCodec().fieldOf("code").forGetter(FrameForEach::code), + Iota.getCodec().listOf().nullableFieldOf("base").forGetter(FrameForEach::baseStack), + Iota.getCodec().listOf().xmap(List::toMutableList, Collections::unmodifiableList) + .fieldOf("acc").forGetter(FrameForEach::acc) + ).apply(it, ::FrameForEach) } + override fun getCodec(world: ServerLevel): Codec = + RecordCodecBuilder.create { + it.group( + SpellList.getCodec(world).fieldOf("data").forGetter(FrameForEach::data), + SpellList.getCodec(world).fieldOf("code").forGetter(FrameForEach::code), + Iota.getCodec(world).listOf().nullableFieldOf("base").forGetter(FrameForEach::baseStack), + Iota.getCodec(world).listOf().xmap(List::toMutableList, Collections::unmodifiableList) + .fieldOf("acc").forGetter(FrameForEach::acc) + ).apply(it, ::FrameForEach) + } } } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt index ec706c2858..9491011bc7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/vm/SpellContinuation.kt @@ -1,8 +1,13 @@ package at.petrak.hexcasting.api.casting.eval.vm +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.utils.NBTBuilder +import at.petrak.hexcasting.api.utils.deserializeWithCodec import at.petrak.hexcasting.api.utils.getList +import at.petrak.hexcasting.api.utils.serializeWithCodec +import com.mojang.serialization.Codec import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag import net.minecraft.server.level.ServerLevel @@ -16,28 +21,51 @@ sealed interface SpellContinuation { fun pushFrame(frame: ContinuationFrame): SpellContinuation = NotDone(frame, this) - fun serializeToNBT() = NBTBuilder { - TAG_FRAME %= list(getNBTFrames()) - } - fun getNBTFrames(): List { + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("serializeWithCodec(SpellContinuation.getCodec())") + ) + fun serializeToNBT(): CompoundTag = this.serializeWithCodec(getCodec()) as CompoundTag + + private fun toList(): List { var self = this - val frames = mutableListOf() + val frames = mutableListOf() while (self is NotDone) { - frames.add(ContinuationFrame.toNBT(self.frame)) + frames.add(self.frame) self = self.next } return frames } + companion object { - const val TAG_FRAME = "frame" + @JvmStatic + fun getCodec(): Codec = ContinuationFrame.getCodec().listOf() + .xmap(SpellContinuation::fromList, SpellContinuation::toList) @JvmStatic - fun fromNBT(nbt: CompoundTag, world: ServerLevel): SpellContinuation { - val frames = nbt.getList(TAG_FRAME, Tag.TAG_COMPOUND) + fun getCodec(world: ServerLevel): Codec = ContinuationFrame.getCodec(world).listOf() + .xmap(SpellContinuation::fromList, SpellContinuation::toList) + + @JvmField + val TAG_FRAME = "frame" + + /** + * Takes a tag containing the ContinuationFrame.Type resourcelocation and the serialized continuation frame, and returns + * the deserialized continuation frame. + */ + @Deprecated( + "Use the codec instead.", + replaceWith = ReplaceWith("tag.deserializeWithCodec(SpellContinuation.getCodec(world))") + ) + @JvmStatic + fun fromNBT(nbt: CompoundTag, world: ServerLevel): SpellContinuation = + nbt.deserializeWithCodec(getCodec(world))!! + + private fun fromList(frames: List): SpellContinuation { var result: SpellContinuation = Done for (frame in frames.asReversed()) { if (frame is CompoundTag) { - result = result.pushFrame(ContinuationFrame.fromNBT(frame, world)) + result = result.pushFrame(frame) } } return result diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java index 91cf0b339d..1fb1e3802b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/BooleanIota.java @@ -1,9 +1,11 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; -import net.minecraft.nbt.ByteTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -31,22 +33,38 @@ public boolean toleratesOther(Iota that) { && this.getBool() == b.getBool(); } + /** + * @deprecated + * Use {@link BooleanIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - // there is no boolean tag :( - return ByteTag.valueOf(this.getBool()); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return Codec.BOOL.xmap(BooleanIota::new, BooleanIota::getBool); + } + + /** + * @deprecated + * Use {@link BooleanIota#TYPE#getCodec} instead. + */ + @Deprecated @Nullable @Override public BooleanIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return BooleanIota.deserialize(tag); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } + @Override public Component display(Tag tag) { - return BooleanIota.display(BooleanIota.deserialize(tag).getBool()); + return BooleanIota.display(HexUtils.deserializeWithCodec(tag, getCodec()).getBool()); } @Override @@ -56,11 +74,6 @@ public int color() { } }; - public static BooleanIota deserialize(Tag tag) throws IllegalArgumentException { - var dtag = HexUtils.downcast(tag, ByteTag.TYPE); - return new BooleanIota(dtag.getAsByte() != 0); - } - public static Component display(boolean b) { return Component.translatable(b ? "hexcasting.tooltip.boolean_true" : "hexcasting.tooltip.boolean_false") .withStyle(b ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java index 13764c4675..80a622bb60 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ContinuationIota.java @@ -1,20 +1,29 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.eval.CastResult; import at.petrak.hexcasting.api.casting.eval.ResolvedPatternType; import at.petrak.hexcasting.api.casting.eval.vm.CastingVM; +import at.petrak.hexcasting.api.casting.eval.vm.ContinuationFrame; import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation; import at.petrak.hexcasting.api.utils.HexUtils; +import at.petrak.hexcasting.common.lib.hex.HexContinuationTypes; import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.google.common.base.Suppliers; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.function.Supplier; /** * An iota storing a continuation (in essence an execution state). @@ -40,10 +49,14 @@ public boolean toleratesOther(Iota that) { return typesMatch(this, that) && that instanceof ContinuationIota cont && cont.getContinuation().equals(getContinuation()); } + /** + * @deprecated + * Use {@link ContinuationIota#TYPE#getCodec} instead. + */ + @Deprecated @Override - public @NotNull - Tag serialize() { - return getContinuation().serializeToNBT(); + public @NotNull Tag serialize() { + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } @Override @@ -71,9 +84,24 @@ public int size() { public static IotaType TYPE = new IotaType<>() { @Override - public @NotNull ContinuationIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var compoundTag = HexUtils.downcast(tag, CompoundTag.TYPE); - return new ContinuationIota(SpellContinuation.fromNBT(compoundTag, world)); + public Codec getCodec() { + return SpellContinuation.getCodec().xmap(ContinuationIota::new, ContinuationIota::getContinuation); + } + + @Override + public Codec getCodec(ServerLevel world) { + return SpellContinuation.getCodec(world).xmap(ContinuationIota::new, ContinuationIota::getContinuation); + } + + /** + * @deprecated + * Use {@link DoubleIota#TYPE#getCodec} instead. + */ + @Deprecated + @Nullable + @Override + public ContinuationIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return HexUtils.deserializeWithCodec(tag, getCodec()); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java index e9ff20f57c..62ad1468c7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/DoubleIota.java @@ -1,9 +1,12 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.DoubleTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -37,21 +40,37 @@ public static boolean tolerates(double a, double b) { return Math.abs(a - b) < TOLERANCE; } + /** + * @deprecated + * Use {@link DoubleIota#TYPE#getCodec()} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return DoubleTag.valueOf(this.getDouble()); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return Codec.DOUBLE.xmap(DoubleIota::new, DoubleIota::getDouble); + } + + /** + * @deprecated + * Use {@link DoubleIota#TYPE#getCodec} instead. + */ + @Deprecated @Nullable @Override public DoubleIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return DoubleIota.deserialize(tag); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { - return DoubleIota.display(DoubleIota.deserialize(tag).getDouble()); + return DoubleIota.display(HexUtils.deserializeWithCodec(tag, getCodec()).getDouble()); } @Override @@ -60,10 +79,6 @@ public int color() { } }; - public static DoubleIota deserialize(Tag tag) throws IllegalArgumentException { - var dtag = HexUtils.downcast(tag, DoubleTag.TYPE); - return new DoubleIota(dtag.getAsDouble()); - } public static Component display(double d) { return Component.literal(String.format("%.2f", d)).withStyle(ChatFormatting.GREEN); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java index fe2ee51f45..19d979e810 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/EntityIota.java @@ -2,30 +2,63 @@ import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; +import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.ExtraCodecs; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.UUID; + public class EntityIota extends Iota { + + + record Payload(UUID uuid, Component name) { + } + public EntityIota(@NotNull Entity e) { - super(HexIotaTypes.ENTITY, e); + this(e.getUUID(), e.getName()); + } + + private EntityIota(@NotNull UUID uuid, @NotNull Component name) { + this(new Payload(uuid, name)); + } + + private EntityIota(Payload payload) { + super(HexIotaTypes.ENTITY, payload); + } + + private Boolean isTrueName = false; + + public Boolean isTrueName() { + return isTrueName; + } + + public Component getName() { + return ((Payload) this.payload).name; + } + + public UUID getUUID() { + return ((Payload) this.payload).uuid; } - public Entity getEntity() { - return (Entity) this.payload; + @Nullable + public Entity getEntity(ServerLevel world) { + return world.getEntity(getUUID()); } @Override public boolean toleratesOther(Iota that) { return typesMatch(this, that) - && that instanceof EntityIota dent - && this.getEntity() == dent.getEntity(); + && that instanceof EntityIota dent + && this.getUUID() == dent.getUUID(); } @Override @@ -33,47 +66,58 @@ public boolean isTruthy() { return true; } + /** + * @deprecated Use {@link EntityIota#TYPE#getCodec) instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - var out = new CompoundTag(); - out.putUUID("uuid", this.getEntity().getUUID()); - out.putString("name", Component.Serializer.toJson(this.getEntity().getName())); - return out; + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } @Override public Component display() { - return this.getEntity().getName().copy().withStyle(ChatFormatting.AQUA); + return this.getName().copy().withStyle(ChatFormatting.AQUA); } public static IotaType TYPE = new IotaType<>() { - @Nullable + @Override - public EntityIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var ctag = HexUtils.downcast(tag, CompoundTag.TYPE); - Tag uuidTag = ctag.get("uuid"); - if (uuidTag == null) { - return null; - } - var uuid = NbtUtils.loadUUID(uuidTag); - var entity = world.getEntity(uuid); + public Codec getCodec() { + return RecordCodecBuilder.create(instance -> instance.group( + UUIDUtil.CODEC.fieldOf("uuid").forGetter(Payload::uuid), + ExtraCodecs.COMPONENT.fieldOf("name").forGetter(Payload::name) + ).apply(instance, Payload::new)).xmap(EntityIota::new, iota -> (Payload) iota.payload); + } + + @Override + protected boolean validate(EntityIota iota, ServerLevel world) { + var entity = iota.getEntity(world); if (entity == null) { - return null; + return false; + } else { + iota.isTrueName = entity instanceof Player; + return true; } - return new EntityIota(entity); + } + + /** + * @deprecated + * Use {@link EntityIota#TYPE#getCodec} instead. + */ + @Deprecated + @Nullable + @Override + public EntityIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { - if (!(tag instanceof CompoundTag ctag)) { - return Component.translatable("hexcasting.spelldata.entity.whoknows"); - } - if (!ctag.contains("name", Tag.TAG_STRING)) { - return Component.translatable("hexcasting.spelldata.entity.whoknows"); - } - var nameJson = ctag.getString("name"); - return Component.Serializer.fromJsonLenient(nameJson).withStyle(ChatFormatting.AQUA); + var data = HexUtils.deserializeWithCodec(tag, getCodec()); + + return data.getName().copy().withStyle(ChatFormatting.AQUA); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java index 0824985852..31f6970a89 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/GarbageIota.java @@ -1,8 +1,12 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -38,16 +42,26 @@ public boolean toleratesOther(Iota that) { return typesMatch(this, that); } + /** + * @deprecated + * Use {@link GarbageIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return new CompoundTag(); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + @Override + public Codec getCodec() { + return Codec.unit(GarbageIota::new); + } + @Nullable @Override public GarbageIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return new GarbageIota(); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java index 7f024abc94..178a93b0d4 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Iota.java @@ -11,6 +11,9 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapUnescapedValue; import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.google.common.base.Suppliers; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -18,8 +21,32 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; public abstract class Iota { + + /** + * Get a generic Iota codec for encoding/decoding any Iota, without validating iotas. + * This codec is useful for serialization, and deserialization on the client side. + * @return an Iota codec. + */ + public static Codec getCodec() { + return HexIotaTypes.REGISTRY.byNameCodec().dispatchMap(HexIotaTypes.KEY_TYPE, Iota::getType, + iotaType -> iotaType.getCodec().fieldOf(HexIotaTypes.KEY_DATA).codec()).codec(); + } + + /** + * Get a generic Iota codec for encoding/decoding any Iota, validating iotas using the given world. + * This codec is useful for deserialization on the server side. + * @param world the world to be used for validation + * @return an Iota codec + */ + public static Codec getCodec(@Nullable ServerLevel world) { + return HexIotaTypes.REGISTRY.byNameCodec().dispatchMap(HexIotaTypes.KEY_TYPE, Iota::getType, + iotaType -> iotaType.getCodec(world).fieldOf(HexIotaTypes.KEY_DATA).codec()).codec().orElseGet(NullIota::new); + } + @NotNull protected final Object payload; @NotNull @@ -45,7 +72,11 @@ protected Iota(@NotNull IotaType type, @NotNull Object payload) { * Serialize this under the {@code data} tag. *

* You probably don't want to call this directly; use {@link IotaType#serialize}. + * + * @deprecated + * Use the Iota's {@code CODEC} instead. */ + @Deprecated abstract public @NotNull Tag serialize(); /** @@ -54,17 +85,17 @@ protected Iota(@NotNull IotaType type, @NotNull Object payload) { */ public @NotNull CastResult execute(CastingVM vm, ServerLevel world, SpellContinuation continuation) { return new CastResult( - this, - continuation, - null, // Should never matter - List.of( - new OperatorSideEffect.DoMishap( - new MishapUnescapedValue(this), - new Mishap.Context(new HexPattern(HexDir.WEST, List.of()), null) - ) - ), - ResolvedPatternType.INVALID, - HexEvalSounds.MISHAP); + this, + continuation, + null, // Should never matter + List.of( + new OperatorSideEffect.DoMishap( + new MishapUnescapedValue(this), + new Mishap.Context(new HexPattern(HexDir.WEST, List.of()), null) + ) + ), + ResolvedPatternType.INVALID, + HexEvalSounds.MISHAP); } /** diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java index 4bcf9b4b1f..454b0dbfc0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/IotaType.java @@ -4,9 +4,13 @@ import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.MapCodec; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Font; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextColor; @@ -19,10 +23,38 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.function.Function; +import java.util.function.Supplier; // Take notes from ForgeRegistryEntry public abstract class IotaType { + public abstract Codec getCodec(); + + public Codec getCodec(ServerLevel world) { + Function> validate = iota -> { + if (validate(iota, world)) { + return DataResult.success(iota); + } else { + return DataResult.error(() -> "iota validation failed"); + } + }; + + return getCodec().flatXmap(validate, validate); + } + + /** + * Validates an iota using the world. + * This can be used for iotas the reference things that may not currently be present in the world, like entities. + * + * @param iota the iota to validate + * @param world the world to use for validation + * @return true if the iota is valid. false if it is not. + */ + protected boolean validate(T iota, ServerLevel world) { + return true; + } + /** * Spell datums are stored as such: {@code { "type": "modid:type", "datum": a_tag }}. *

@@ -31,7 +63,10 @@ public abstract class IotaType { *

* Returning {@code null} makes the resulting datum be {@link NullIota}. * Throwing an exception raises a mishap. + * + * @deprecated use {@code Codec} from {@link IotaType#getCodec()} instead. */ + @Deprecated @Nullable public abstract T deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException; @@ -52,28 +87,15 @@ public abstract class IotaType { public Component typeName() { var key = HexIotaTypes.REGISTRY.getKey(this); return Component.translatable("hexcasting.iota." + key) - .withStyle(style -> style.withColor(TextColor.fromRgb(color()))); + .withStyle(style -> style.withColor(TextColor.fromRgb(color()))); } + /** + * @deprecated Use {@link Iota#getCodec()} instead. + */ + @Deprecated public static CompoundTag serialize(Iota iota) { - var type = iota.getType(); - var typeId = HexIotaTypes.REGISTRY.getKey(type); - if (typeId == null) { - throw new IllegalStateException( - "Tried to serialize an unregistered iota type. Iota: " + iota - + " ; Type" + type.getClass().getTypeName()); - } - - // We check if it's too big on serialization; if it is we just return a garbage. - if (isTooLargeToSerialize(List.of(iota), 0)) { - // Garbage will never be too large so we just recurse - return serialize(new GarbageIota()); - } - var dataTag = iota.serialize(); - var out = new CompoundTag(); - out.putString(HexIotaTypes.KEY_TYPE, typeId.toString()); - out.put(HexIotaTypes.KEY_DATA, dataTag); - return out; + return (CompoundTag) Iota.getCodec().encodeStart(NbtOps.INSTANCE, iota).resultOrPartial(HexAPI.LOGGER::error).orElseThrow(); } public static boolean isTooLargeToSerialize(Iterable examinee) { @@ -139,29 +161,17 @@ public static IotaType getTypeFromTag(CompoundTag tag) { * "data": {...} * } * + * + * @deprecated Use {@link Iota#getCodec()} instead. */ + @Deprecated public static Iota deserialize(CompoundTag tag, ServerLevel world) { - var type = getTypeFromTag(tag); - if (type == null) { - return new GarbageIota(); - } - var data = tag.get(HexIotaTypes.KEY_DATA); - if (data == null) { - return new GarbageIota(); - } - Iota deserialized; - try { - deserialized = Objects.requireNonNullElse(type.deserialize(data, world), new NullIota()); - } catch (IllegalArgumentException exn) { - HexAPI.LOGGER.warn("Caught an exception deserializing an iota", exn); - deserialized = new GarbageIota(); - } - return deserialized; + return Iota.getCodec(world).parse(NbtOps.INSTANCE, tag).resultOrPartial(HexAPI.LOGGER::error).orElseThrow(); } private static Component brokenIota() { return Component.translatable("hexcasting.spelldata.unknown") - .withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); + .withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); } public static Component getDisplay(CompoundTag tag) { @@ -194,7 +204,7 @@ else if (splitted.size() == 1) else { var first = splitted.get(0); return FormattedCharSequence.fromPair(first, - Component.literal("...").withStyle(ChatFormatting.GRAY).getVisualOrderText()); + Component.literal("...").withStyle(ChatFormatting.GRAY).getVisualOrderText()); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java index 255d54662f..cd1c9d17ef 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/ListIota.java @@ -1,11 +1,14 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.casting.SpellList; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -64,13 +67,14 @@ public boolean toleratesOther(Iota that) { } } + /** + * @deprecated + * use {@link ListIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - var out = new ListTag(); - for (var subdatum : this.getList()) { - out.add(IotaType.serialize(subdatum)); - } - return out; + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } @Override @@ -79,27 +83,31 @@ public boolean toleratesOther(Iota that) { } public static IotaType TYPE = new IotaType<>() { - @Nullable @Override - public ListIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - var listTag = HexUtils.downcast(tag, ListTag.TYPE); - var out = new ArrayList(listTag.size()); + public Codec getCodec() { + return SpellList.getCodec().xmap(ListIota::new, ListIota::getList); + } - for (var sub : listTag) { - var csub = HexUtils.downcast(sub, CompoundTag.TYPE); - var subiota = IotaType.deserialize(csub, world); - if (subiota == null) { - return null; - } - out.add(subiota); - } + @Override + public Codec getCodec(ServerLevel world) { + return SpellList.getCodec(world).xmap(ListIota::new, ListIota::getList); + } - return new ListIota(out); + /** + * @deprecated + * use {@link ListIota#TYPE#getCodec} instead. + */ + @Deprecated + @Nullable + @Override + public ListIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { var out = Component.empty(); + var list = HexUtils.downcast(tag, ListTag.TYPE); for (int i = 0; i < list.size(); i++) { Tag sub = list.get(i); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java index 525e6b22a9..f9f68ee4de 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/NullIota.java @@ -1,8 +1,12 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -34,16 +38,32 @@ public boolean toleratesOther(Iota that) { return typesMatch(this, that); } + /** + * @deprecated + * use {@link NullIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return new CompoundTag(); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return Codec.unit(NullIota::new); + } + + /** + * @deprecated + * use {@link NullIota#TYPE#getCodec} instead. + */ + @Deprecated @Nullable @Override public NullIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return new NullIota(); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override 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..aad20352eb 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 @@ -21,8 +21,10 @@ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; import at.petrak.hexcasting.xplat.IXplatAbstractions; +import com.mojang.serialization.Codec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; @@ -32,6 +34,7 @@ import java.util.List; import java.util.Objects; +import java.util.function.Supplier; import static at.petrak.hexcasting.api.utils.HexUtils.isOfTag; @@ -57,17 +60,22 @@ 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()); } + /** + * @deprecated + * Use {@link PatternIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return this.getPattern().serializeToNBT(); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } @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 +93,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 +101,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 +135,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); } @@ -139,14 +147,25 @@ public boolean executable() { } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return HexPattern.CODEC.xmap(PatternIota::new, PatternIota::getPattern); + } + + /** + * @deprecated + * Use {@link PatternIota#TYPE#getCodec} instead. + */ + @Deprecated @Override public PatternIota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return PatternIota.deserialize(tag); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { - return PatternIota.display(PatternIota.deserialize(tag).getPattern()); + return PatternIota.display(HexUtils.deserializeWithCodec(tag, getCodec()).getPattern()); } @Override @@ -155,12 +174,6 @@ public int color() { } }; - public static PatternIota deserialize(Tag tag) throws IllegalArgumentException { - var patTag = HexUtils.downcast(tag, CompoundTag.TYPE); - HexPattern pat = HexPattern.fromNBT(patTag); - return new PatternIota(pat); - } - public static Component display(HexPattern pat) { var bob = new StringBuilder(); bob.append(pat.getStartDir()); diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java index 9d9d7fbf67..5396845d88 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/iota/Vec3Iota.java @@ -1,10 +1,16 @@ package at.petrak.hexcasting.api.casting.iota; +import at.petrak.hexcasting.api.HexAPI; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.lib.hex.HexIotaTypes; +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.LongArrayTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -12,18 +18,46 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + public class Vec3Iota extends Iota { + + private record Vec3CompoundRepresentation(double x, double y, double z) { + static Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + Codec.DOUBLE.fieldOf("x").forGetter(Vec3CompoundRepresentation::x), + Codec.DOUBLE.fieldOf("y").forGetter(Vec3CompoundRepresentation::y), + Codec.DOUBLE.fieldOf("z").forGetter(Vec3CompoundRepresentation::z) + ).apply(instance, Vec3CompoundRepresentation::new)) + .xmap(Vec3CompoundRepresentation::toVec3, Vec3CompoundRepresentation::fromVec3); + + static Vec3CompoundRepresentation fromVec3(Vec3 vec) { + return new Vec3CompoundRepresentation(vec.x, vec.y, vec.z); + } + + Vec3 toVec3() { + return new Vec3(x, y, z); + } + } + + private static final Codec Vec3CursedCodec = Codec.LONG.listOf().xmap( + list -> new Vec3( + Double.longBitsToDouble(list.get(0)), + Double.longBitsToDouble(list.get(1)), + Double.longBitsToDouble(list.get(2))), + vec -> List.of( + Double.doubleToLongBits(vec.x), + Double.doubleToLongBits(vec.y), + Double.doubleToLongBits(vec.z)) + ); + public Vec3Iota(@NotNull Vec3 datum) { super(HexIotaTypes.VEC3, datum); } public Vec3 getVec3() { var v = (Vec3) this.payload; - return new Vec3( - HexUtils.fixNAN(v.x), - HexUtils.fixNAN(v.y), - HexUtils.fixNAN(v.z) - ); + return new Vec3(HexUtils.fixNAN(v.x), HexUtils.fixNAN(v.y), HexUtils.fixNAN(v.z)); } @Override @@ -34,26 +68,45 @@ public boolean isTruthy() { @Override public boolean toleratesOther(Iota that) { - return typesMatch(this, that) - && that instanceof Vec3Iota viota - && this.getVec3().distanceToSqr(viota.getVec3()) < DoubleIota.TOLERANCE * DoubleIota.TOLERANCE; + return typesMatch(this, that) && that instanceof Vec3Iota viota && this.getVec3().distanceToSqr(viota.getVec3()) < DoubleIota.TOLERANCE * DoubleIota.TOLERANCE; } + /** + * @deprecated use {@link Vec3Iota#TYPE#getCodec} instead. + */ + @Deprecated @Override public @NotNull Tag serialize() { - return HexUtils.serializeToNBT(this.getVec3()); + return HexUtils.serializeWithCodec(this, TYPE.getCodec()); } public static IotaType TYPE = new IotaType<>() { + + @Override + public Codec getCodec() { + return Codec.either(Vec3CompoundRepresentation.CODEC, Vec3CursedCodec).flatXmap(either -> { + if (either.left().isPresent()) { + return DataResult.success(new Vec3Iota(either.left().get())); + } else if (either.right().isPresent()) { + return DataResult.success(new Vec3Iota(either.right().get())); + } else return DataResult.error(() -> "Not a valid Vec3 format: " + either); + }, iota -> DataResult.success(Either.left(iota.getVec3()))); + } + + /** + * @deprecated + * use {@link Vec3Iota#TYPE#getCodec} instead. + */ + @Deprecated @Nullable @Override public Vec3Iota deserialize(Tag tag, ServerLevel world) throws IllegalArgumentException { - return Vec3Iota.deserialize(tag); + return HexUtils.deserializeWithCodec(tag, getCodec(world)); } @Override public Component display(Tag tag) { - return Vec3Iota.display(Vec3Iota.deserialize(tag).getVec3()); + return Vec3Iota.display(HexUtils.deserializeWithCodec(tag, getCodec()).getVec3()); } @Override @@ -67,14 +120,12 @@ public static Vec3Iota deserialize(Tag tag) throws IllegalArgumentException { if (tag.getType() == LongArrayTag.TYPE) { var lat = HexUtils.downcast(tag, LongArrayTag.TYPE); vec = HexUtils.vecFromNBT(lat.getAsLongArray()); - } else - vec = HexUtils.vecFromNBT(HexUtils.downcast(tag, CompoundTag.TYPE)); + } else vec = HexUtils.vecFromNBT(HexUtils.downcast(tag, CompoundTag.TYPE)); return new Vec3Iota(vec); } public static Component display(double x, double y, double z) { - return Component.literal(String.format("(%.2f, %.2f, %.2f)", x, y, z)) - .withStyle(ChatFormatting.RED); + return Component.literal(String.format("(%.2f, %.2f, %.2f)", x, y, z)).withStyle(ChatFormatting.RED); } public static Component display(Vec3 v) { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt index bca8b0b94b..505452f2be 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexAngle.kt @@ -1,8 +1,15 @@ package at.petrak.hexcasting.api.casting.math +import com.mojang.serialization.Codec + enum class HexAngle { FORWARD, RIGHT, RIGHT_BACK, BACK, LEFT_BACK, LEFT; fun rotatedBy(a: HexAngle) = values()[(this.ordinal + a.ordinal) % values().size] operator fun times(a: HexAngle) = this.rotatedBy(a) + + companion object { + val CODEC: Codec = + Codec.BYTE.xmap({ ordinal -> HexAngle.values()[ordinal.toInt()] }, { dir -> dir.ordinal.toByte() }) + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt index 514cb0e467..75ec5eeba8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/math/HexDir.kt @@ -1,6 +1,7 @@ package at.petrak.hexcasting.api.casting.math import at.petrak.hexcasting.api.utils.getSafe +import com.mojang.serialization.Codec enum class HexDir { NORTH_EAST, EAST, SOUTH_EAST, SOUTH_WEST, WEST, NORTH_WEST; @@ -26,6 +27,10 @@ enum class HexDir { } companion object { + @JvmStatic + val CODEC: Codec = + Codec.BYTE.xmap({ ordinal -> HexDir.values()[ordinal.toInt()] }, { dir -> dir.ordinal.toByte() }) + @JvmStatic fun fromString(key: String): HexDir { return values().getSafe(key, WEST) 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..c882033760 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 @@ -1,17 +1,23 @@ package at.petrak.hexcasting.api.casting.math +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.utils.NBTBuilder import at.petrak.hexcasting.api.utils.coordToPx import at.petrak.hexcasting.api.utils.findCenter import at.petrak.hexcasting.api.utils.getSafe +import com.google.common.collect.ImmutableList +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps import net.minecraft.nbt.Tag import net.minecraft.world.phys.Vec2 +import java.util.Collections /** * 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. */ @@ -71,11 +77,12 @@ data class HexPattern(public val startDir: HexDir, public val angles: MutableLis fun finalDir(): HexDir = this.angles.fold(this.startDir) { acc, angle -> acc * angle } - - fun serializeToNBT() = NBTBuilder { - TAG_START_DIR %= byte(startDir.ordinal) - TAG_ANGLES %= byteArray(angles.map(HexAngle::ordinal)) - } + @Deprecated( + "Use the CODEC instead.", + replaceWith = ReplaceWith("serializeWithCodec(HexPattern.CODEC)") + ) + fun serializeToNBT() = + CODEC.encodeStart(NbtOps.INSTANCE, this).resultOrPartial(HexAPI.LOGGER::error).orElseThrow() as CompoundTag // Terrible shorthand method for easy matching fun anglesSignature(): String { @@ -113,7 +120,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[") @@ -127,18 +134,28 @@ data class HexPattern(public val startDir: HexDir, public val angles: MutableLis const val TAG_START_DIR = "start_dir" const val TAG_ANGLES = "angles" + @JvmField + val CODEC: Codec = RecordCodecBuilder.create { + it.group( + HexDir.CODEC.fieldOf(TAG_START_DIR).forGetter(HexPattern::startDir), + HexAngle.CODEC.listOf().fieldOf(TAG_ANGLES) + .xmap(List::toMutableList, Collections::unmodifiableList).forGetter(HexPattern::angles) + ).apply(it, ::HexPattern) + } + @JvmStatic fun isPattern(tag: CompoundTag): Boolean { return tag.contains(TAG_START_DIR, Tag.TAG_ANY_NUMERIC.toInt()) - && tag.contains(TAG_ANGLES, Tag.TAG_BYTE_ARRAY.toInt()) + && tag.contains(TAG_ANGLES, Tag.TAG_BYTE_ARRAY.toInt()) } + @Deprecated( + "Use the CODEC instead.", + replaceWith = ReplaceWith("tag.deserializeWithCodec(HexPattern.CODEC)") + ) @JvmStatic - fun fromNBT(tag: CompoundTag): HexPattern { - val startDir = HexDir.values().getSafe(tag.getByte(TAG_START_DIR)) - val angles = tag.getByteArray(TAG_ANGLES).map(HexAngle.values()::getSafe) - return HexPattern(startDir, angles.toMutableList()) - } + fun fromNBT(tag: CompoundTag): HexPattern = + CODEC.parse(NbtOps.INSTANCE, tag).resultOrPartial(HexAPI.LOGGER::error).orElseThrow() @JvmStatic fun fromAngles(signature: String, startDir: HexDir): HexPattern { 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..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 @@ -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) @@ -17,15 +17,15 @@ class MishapBadOffhandItem(val item: ItemStack, val hand: InteractionHand?, val env.mishapEnvironment.dropHeldItems() } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = if (item.isEmpty) - 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 - 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/casting/mishaps/MishapEntityNotFound.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt new file mode 100644 index 0000000000..55f1a136e8 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapEntityNotFound.kt @@ -0,0 +1,22 @@ +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.api.utils.aqua +import at.petrak.hexcasting.api.utils.asTranslatedComponent +import net.minecraft.network.chat.Component +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.item.ItemEntity +import net.minecraft.world.item.DyeColor + +class MishapEntityNotFound : Mishap() { + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.BROWN) + + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + } + + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("entity_not_found") +} \ No newline at end of file diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIotas.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIotas.kt deleted file mode 100644 index 34a13f7acd..0000000000 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidIotas.kt +++ /dev/null @@ -1,32 +0,0 @@ -package at.petrak.hexcasting.api.casting.mishaps - -import at.petrak.hexcasting.api.casting.eval.CastingEnvironment -import at.petrak.hexcasting.api.casting.iota.GarbageIota -import at.petrak.hexcasting.api.casting.iota.Iota -import at.petrak.hexcasting.api.casting.math.HexPattern -import at.petrak.hexcasting.api.pigment.FrozenPigment -import net.minecraft.network.chat.ComponentContents -import net.minecraft.network.chat.MutableComponent -import net.minecraft.world.item.DyeColor - -/** - * The value failed some kind of predicate. - */ -class MishapInvalidOperatorArgs( - val perpetrators: List, - val operator: HexPattern -) : Mishap() { - override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = - dyeColor(DyeColor.GRAY) - - override fun execute(ctx: CastingEnvironment, errorCtx: Context, stack: MutableList) { - for (i in perpetrators.indices) { - stack[stack.size - 1 - i] = GarbageIota() - } - } - - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = - error( - "invalid_operator_args", operator, perpetrators.fold(MutableComponent.create(ComponentContents.EMPTY)) { mc, iota -> mc.append(iota.display()) } - ) -} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt new file mode 100644 index 0000000000..a16c083f4c --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapInvalidOperatorArgs.kt @@ -0,0 +1,42 @@ +package at.petrak.hexcasting.api.casting.mishaps + +import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +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.api.utils.asTextComponent +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.ComponentUtils +import net.minecraft.world.item.DyeColor + +/** + * The value failed some kind of predicate. + */ +class MishapInvalidOperatorArgs(val perpetrators: List) : Mishap() { + override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = + dyeColor(DyeColor.GRAY) + + override fun execute(env: CastingEnvironment, errorCtx: Context, stack: MutableList) { + for (i in perpetrators.indices) { + stack[stack.size - 1 - i] = GarbageIota() + } + } + + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context): Component { + return if (perpetrators.size == 1) { + error( + "invalid_operator_args.one", + 0, + perpetrators[0].display() + ) + } else { + error( + "invalid_operator_args.many", + perpetrators.size, + 0, + perpetrators.lastIndex, + ComponentUtils.formatList(perpetrators.map { it.display() }, ", ".asTextComponent) + ) + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt index e6ea0326ed..d916a4e1ba 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapOthersName.kt @@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.casting.iota.EntityIota import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.pigment.FrozenPigment +import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.player.Player import net.minecraft.world.item.DyeColor @@ -33,14 +34,17 @@ class MishapOthersName(val confidant: Player) : Mishap() { * If `caster` is non-null, it will ignore that when checking. */ @JvmStatic - fun getTrueNameFromDatum(datum: Iota, caster: Player?): Player? { + fun getTrueNameFromDatum(datum: Iota, caster: Player?, world: ServerLevel): Player? { val poolToSearch = ArrayDeque() poolToSearch.addLast(datum) while (poolToSearch.isNotEmpty()) { val datumToCheck = poolToSearch.removeFirst() - if (datumToCheck is EntityIota && datumToCheck.entity is Player && datumToCheck.entity != caster) - return datumToCheck.entity as Player + if (datumToCheck is EntityIota && datumToCheck.isTrueName) { + val player = datumToCheck.getEntity(world) as Player + if (player != caster) + return player + } val datumSubIotas = datumToCheck.subIotas() if (datumSubIotas != null) poolToSearch.addAll(datumSubIotas) @@ -50,8 +54,8 @@ class MishapOthersName(val confidant: Player) : Mishap() { } @JvmStatic - fun getTrueNameFromArgs(datums: List, caster: Player?): Player? { - return datums.firstNotNullOfOrNull { getTrueNameFromDatum(it, caster) } + fun getTrueNameFromArgs(datums: List, caster: Player?, world: ServerLevel): Player? { + return datums.firstNotNullOfOrNull { getTrueNameFromDatum(it, caster, world) } } } } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapShameOnYou.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt similarity index 64% rename from Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapShameOnYou.kt rename to Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt index 6f36b4580c..571e39bcd9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapShameOnYou.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/mishaps/MishapStackSize.kt @@ -1,22 +1,24 @@ 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 import net.minecraft.world.item.DyeColor -class MishapShameOnYou() : Mishap() { +class MishapStackSize() : Mishap() { override fun accentColor(ctx: CastingEnvironment, errorCtx: Context): FrozenPigment = 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.SHAME_ON_YOU), 69420f) - } + stack.clear() + stack.add(GarbageIota()) } - override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = error("shame") + override fun errorMessage(ctx: CastingEnvironment, errorCtx: Context) = + error("stack_size") } 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..b2fe3e5b58 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 @@ -46,7 +46,7 @@ default Iota readIota(ItemStack stack, ServerLevel world) { var tag = dh.readIotaTag(stack); if (tag != null) { - return IotaType.deserialize(tag, world); + return HexUtils.deserializeWithCodec(tag, Iota.getCodec(world)); } else { return null; } @@ -54,8 +54,6 @@ 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) { @@ -87,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/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/Common/src/main/java/at/petrak/hexcasting/api/mod/HexTags.java b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexTags.java index d8e77e3c76..238afae719 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/mod/HexTags.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/mod/HexTags.java @@ -2,8 +2,6 @@ import at.petrak.hexcasting.api.casting.ActionRegistryEntry; import at.petrak.hexcasting.xplat.IXplatAbstractions; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; @@ -47,6 +45,8 @@ public static final class Blocks { // Used to determine what blocks should be replaced with air by OpDestroyFluid public static final TagKey WATER_PLANTS = create("water_plants"); + public static final TagKey CHEAP_TO_BREAK_BLOCK = create("cheap_to_break_block"); + public static TagKey create(String name) { return TagKey.create(Registries.BLOCK, modLoc(name)); } diff --git a/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt index 209297766a..fc428439c7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/utils/HexUtils.kt @@ -2,10 +2,14 @@ package at.petrak.hexcasting.api.utils +import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.IotaType import at.petrak.hexcasting.api.casting.iota.ListIota import at.petrak.hexcasting.api.casting.math.HexCoord +import com.mojang.serialization.Codec +import com.mojang.serialization.MapCodec +import com.mojang.serialization.codecs.OptionalFieldCodec import net.minecraft.ChatFormatting import net.minecraft.core.Registry import net.minecraft.nbt.* @@ -44,6 +48,7 @@ fun vecFromNBT(tag: LongArray): Vec3 = if (tag.size != 3) Vec3.ZERO else Double.fromBits(tag[1]), Double.fromBits(tag[2]) ) + fun vecFromNBT(tag: CompoundTag): Vec3 { return if (!tag.contains("x") || !tag.contains("y") || !tag.contains("z")) Vec3.ZERO @@ -313,3 +318,18 @@ fun isOfTag(registry: Registry, loc: ResourceLocation, tag: TagKey): B val key = ResourceKey.create(registry.key(), loc); return isOfTag(registry, key, tag) } + +fun Codec.nullableFieldOf(name: String): MapCodec { + return OptionalFieldCodec(name, this).xmap( + { optional -> if (optional.isPresent) optional.get() else null }, + { obj -> Optional.ofNullable(obj) } + ) +} + +fun T.serializeWithCodec(codec: Codec): Tag? { + return codec.encodeStart(NbtOps.INSTANCE, this).resultOrPartial(HexAPI.LOGGER::error).orElse(null) +} + +fun Tag.deserializeWithCodec(codec: Codec): T? { + return codec.parse(NbtOps.INSTANCE, this).resultOrPartial(HexAPI.LOGGER::error).orElse(null) +} \ No newline at end of file diff --git a/Common/src/main/java/at/petrak/hexcasting/client/ShiftScrollListener.java b/Common/src/main/java/at/petrak/hexcasting/client/ShiftScrollListener.java index a35a711719..c6073517cc 100644 --- a/Common/src/main/java/at/petrak/hexcasting/client/ShiftScrollListener.java +++ b/Common/src/main/java/at/petrak/hexcasting/client/ShiftScrollListener.java @@ -5,7 +5,6 @@ import at.petrak.hexcasting.common.msgs.MsgShiftScrollC2S; import at.petrak.hexcasting.xplat.IClientXplatAbstractions; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.item.Item; @@ -46,7 +45,7 @@ public static boolean onScroll(double delta, boolean needsSneaking) { public static void clientTickEnd() { if (mainHandDelta != 0 || offHandDelta != 0) { IClientXplatAbstractions.INSTANCE.sendPacketToServer( - new MsgShiftScrollC2S(mainHandDelta, offHandDelta, Screen.hasControlDown(), + new MsgShiftScrollC2S(mainHandDelta, offHandDelta, Minecraft.getInstance().options.keySprint.isDown(), HexConfig.client().invertSpellbookScrollDirection(), HexConfig.client().invertAbacusScrollDirection())); mainHandDelta = 0; diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java index db3f96ac14..71cf6bae11 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockAkashicRecord.java @@ -3,6 +3,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.casting.math.HexPattern; +import at.petrak.hexcasting.api.utils.HexUtils; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; @@ -57,7 +58,7 @@ Iota lookupPattern(BlockPos herePos, HexPattern key, ServerLevel slevel) { var tile = (BlockEntityAkashicBookshelf) slevel.getBlockEntity(foundPos); var tag = tile.getIotaTag(); - return tag == null ? null : IotaType.deserialize(tag, slevel); + return tag == null ? null : HexUtils.deserializeWithCodec(tag, Iota.getCodec()); } // TODO get comparators working again and also cache the number of iotas somehow? diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java index d6e4cd8041..03b6a917f3 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/akashic/BlockEntityAkashicBookshelf.java @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.casting.math.HexPattern; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.client.render.HexPatternPoints; import at.petrak.hexcasting.common.lib.HexBlockEntities; import net.minecraft.core.BlockPos; @@ -42,7 +43,7 @@ public CompoundTag getIotaTag() { public void setNewMapping(HexPattern pattern, Iota iota) { var previouslyEmpty = this.pattern == null; this.pattern = pattern; - this.iotaTag = IotaType.serialize(iota); + this.iotaTag = (CompoundTag) HexUtils.serializeWithCodec(iota, Iota.getCodec()); if (previouslyEmpty) { var oldBs = this.getBlockState(); 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 diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEntitySlate.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEntitySlate.java index 63489e8c0e..2eec827fe7 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEntitySlate.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockEntitySlate.java @@ -2,6 +2,7 @@ import at.petrak.hexcasting.api.block.HexBlockEntity; import at.petrak.hexcasting.api.casting.math.HexPattern; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.client.render.HexPatternPoints; import at.petrak.hexcasting.common.lib.HexBlockEntities; import net.minecraft.core.BlockPos; @@ -10,6 +11,8 @@ import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.Nullable; +import java.util.Objects; + public class BlockEntitySlate extends HexBlockEntity { public static final String TAG_PATTERN = "pattern"; @@ -24,7 +27,7 @@ public BlockEntitySlate(BlockPos pos, BlockState state) { @Override protected void saveModData(CompoundTag tag) { if (this.pattern != null) { - tag.put(TAG_PATTERN, this.pattern.serializeToNBT()); + tag.put(TAG_PATTERN, Objects.requireNonNull(HexUtils.serializeWithCodec(this.pattern, HexPattern.CODEC))); } else { tag.put(TAG_PATTERN, new CompoundTag()); } @@ -35,7 +38,7 @@ protected void loadModData(CompoundTag tag) { if (tag.contains(TAG_PATTERN, Tag.TAG_COMPOUND)) { CompoundTag patternTag = tag.getCompound(TAG_PATTERN); if (HexPattern.isPattern(patternTag)) { - this.pattern = HexPattern.fromNBT(patternTag); + this.pattern = HexUtils.deserializeWithCodec(patternTag, HexPattern.CODEC); } else { this.pattern = null; } 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; diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRedstoneImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRedstoneImpetus.java index 58b3ac7c18..164f8fa08f 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRedstoneImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockRedstoneImpetus.java @@ -54,7 +54,7 @@ public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Pla if (datumContainer != null) { var stored = datumContainer.readIota(level); if (stored instanceof EntityIota eieio) { - var entity = eieio.getEntity(); + var entity = eieio.getEntity((ServerLevel) pLevel); if (entity instanceof Player player) { // phew, we got something tile.setPlayer(player.getGameProfile(), entity.getUUID()); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt index eea382d0e4..f08b0ac545 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityHeight.kt @@ -10,7 +10,7 @@ object OpEntityHeight : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val e = args.getEntity(0, argc) + val e = args.getEntity(0, argc, env.world) env.assertEntityInRange(e) return e.bbHeight.asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt index 14faec64eb..8846eea496 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityLook.kt @@ -10,7 +10,7 @@ object OpEntityLook : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val e = args.getEntity(0, argc) + val e = args.getEntity(0, argc, env.world) env.assertEntityInRange(e) return e.lookAngle.asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt index 80ab0e23f0..f92d9fd98a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityPos.kt @@ -10,7 +10,7 @@ class OpEntityPos(val feet: Boolean) : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val e = args.getEntity(0, argc) + val e = args.getEntity(0, argc, env.world) env.assertEntityInRange(e) return (if (this.feet) e.position() else e.eyePosition).asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt index b1b7330969..c6f6291c15 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/OpEntityVelocity.kt @@ -11,7 +11,7 @@ object OpEntityVelocity : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val e = args.getEntity(0, argc) + val e = args.getEntity(0, argc, env.world) env.assertEntityInRange(e) val vel = HexAPI.instance().getEntityVelocitySpecial(e) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt index 2089965835..9f57d88437 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/akashic/OpAkashicWrite.kt @@ -34,7 +34,7 @@ object OpAkashicWrite : SpellAction { throw MishapNoAkashicRecord(pos) } - val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer) + val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer, env.world) if (trueName != null) throw MishapOthersName(trueName) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt index bb5ccafa8b..bdd4f76f7a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/eval/OpForEach.kt @@ -17,8 +17,8 @@ object OpForEach : Action { if (stack.size < 2) throw MishapNotEnoughArgs(2, stack.size) - val instrs = stack.getList(stack.lastIndex - 1) - val datums = stack.getList(stack.lastIndex) + val instrs = stack.getList(stack.lastIndex - 1, stack.size) + val datums = stack.getList(stack.lastIndex, stack.size) stack.removeLastOrNull() stack.removeLastOrNull() 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/common/casting/actions/rw/OpRead.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpRead.kt index fceb1a1af1..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 @@ -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 @@ -11,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) - } ?: return listOf(NullIota()) + } + // 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/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/OpTheCoolerRead.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt index 4fd4a69f8b..dfe8a2f511 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerRead.kt @@ -14,7 +14,7 @@ object OpTheCoolerRead : ConstMediaAction { args: List, env: CastingEnvironment ): List { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) env.assertEntityInRange(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt index aa118182af..0db1a1b3f1 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerReadable.kt @@ -14,7 +14,7 @@ object OpTheCoolerReadable : ConstMediaAction { args: List, env: CastingEnvironment ): List { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) env.assertEntityInRange(target) val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt index 598ae8b145..ce32790676 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWritable.kt @@ -15,7 +15,7 @@ object OpTheCoolerWritable : ConstMediaAction { args: List, env: CastingEnvironment ): List { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) env.assertEntityInRange(target) val datumHolder = IXplatAbstractions.INSTANCE.findDataHolder(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt index 27e02a8f97..7124ed3738 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpTheCoolerWrite.kt @@ -19,7 +19,7 @@ object OpTheCoolerWrite : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) val datum = args[1] env.assertEntityInRange(target) @@ -32,7 +32,7 @@ object OpTheCoolerWrite : SpellAction { // We pass null here so that even the own caster won't be allowed into a focus. // Otherwise, you could sentinel scout to people and remotely write their names into things using a cleric circle. - val trueName = MishapOthersName.getTrueNameFromDatum(datum, null) + val trueName = MishapOthersName.getTrueNameFromDatum(datum, null, env.world) if (trueName != null) throw MishapOthersName(trueName) 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/casting/actions/rw/OpWrite.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/rw/OpWrite.kt index 211f74a30f..47a349323a 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 { @@ -20,19 +19,25 @@ 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 + } + // 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) - ?: 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) + val trueName = MishapOthersName.getTrueNameFromDatum(datum, env.castingEntity as? ServerPlayer, env.world) if (trueName != null) throw MishapOthersName(trueName) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt index 7f45168f85..c96b1a08b6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpAddMotion.kt @@ -25,7 +25,7 @@ object OpAddMotion : SpellAction { env: CastingEnvironment, userData: CompoundTag ): SpellAction.Result { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) val motion = args.getVec3(1, argc) env.assertEntityInRange(target) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt index f7fd817308..6f0120e4d0 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpBlink.kt @@ -23,7 +23,7 @@ object OpBlink : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) val delta = args.getDouble(1, argc) env.assertEntityInRange(target) 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..796e82ccd0 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 @@ -8,8 +8,10 @@ import at.petrak.hexcasting.api.casting.getVec3 import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.misc.MediaConstants import at.petrak.hexcasting.api.mod.HexConfig +import at.petrak.hexcasting.api.mod.HexTags 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 { @@ -17,16 +19,18 @@ object OpBreakBlock : SpellAction { get() = 1 override fun execute( - args: List, - env: CastingEnvironment + args: List, + env: CastingEnvironment ): SpellAction.Result { val vecPos = args.getVec3(0, argc) val pos = BlockPos.containing(vecPos) env.assertPosInRangeForEditing(pos) + val isCheap = env.world.getBlockState(pos).`is`(HexTags.Blocks.CHEAP_TO_BREAK_BLOCK) + return SpellAction.Result( Spell(pos), - MediaConstants.DUST_UNIT / 8, + if (isCheap) MediaConstants.DUST_UNIT / 100 else MediaConstants.DUST_UNIT / 8, listOf(ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0)) ) } @@ -40,6 +44,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) } 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/OpExplode.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExplode.kt index 9535523457..0bed07989c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExplode.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpExplode.kt @@ -8,9 +8,11 @@ import at.petrak.hexcasting.api.casting.getPositiveDoubleUnderInclusive import at.petrak.hexcasting.api.casting.getVec3 import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.misc.MediaConstants +import at.petrak.hexcasting.common.casting.actions.selectors.OpGetEntitiesBy import net.minecraft.core.BlockPos import net.minecraft.util.Mth import net.minecraft.world.level.Level +import net.minecraft.world.phys.AABB import net.minecraft.world.phys.Vec3 class OpExplode(val fire: Boolean) : SpellAction { @@ -18,13 +20,24 @@ class OpExplode(val fire: Boolean) : SpellAction { get() = 2 override fun execute( - args: List, - env: CastingEnvironment + args: List, + env: CastingEnvironment ): SpellAction.Result { - val pos = args.getVec3(0, argc) + var pos = args.getVec3(0, argc) val strength = args.getPositiveDoubleUnderInclusive(1, 10.0, argc) env.assertVecInRange(pos) + // Prevent the footgun of explosions exactly at an entity's eye position not doing damage + val eps = 0.01; + val epsv = Vec3(eps, eps, eps) + val aabb = AABB(pos.subtract(epsv), pos.add(epsv)) + val tooCloseToEyePos = env.world.getEntities(null, aabb) { + OpGetEntitiesBy.isReasonablySelectable(env, it) + }.any { it.eyePosition.distanceToSqr(pos) == 0.0 } + if (tooCloseToEyePos) { + pos = pos.add(0.0, 0.000001, 0.0) + } + val clampedStrength = Mth.clamp(strength, 0.0, 10.0) val cost = MediaConstants.DUST_UNIT * (3 * clampedStrength + if (fire) 1.0 else 0.125) return SpellAction.Result( diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt index 9258cc059e..25a5ad908e 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt @@ -31,7 +31,7 @@ class OpFlight(val type: Type) : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getPlayer(0, argc) + val target = args.getPlayer(0, argc, env.world) val theArg = args.getPositiveDouble(1, argc) env.assertEntityInRange(target) 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..84d3e71e9d 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 @@ -26,22 +26,20 @@ object OpMakeBattery : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) + val entity = args.getItemEntity(0, argc, env.world) 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..a4bc84f7c2 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 @@ -25,20 +25,20 @@ class OpMakePackagedSpell(val itemType: T, val cost: Long) args: List, env: CastingEnvironment ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) + val entity = args.getItemEntity(0, argc, env.world) 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) @@ -54,7 +54,7 @@ class OpMakePackagedSpell(val itemType: T, val cost: Long) ) } - val trueName = MishapOthersName.getTrueNameFromArgs(patterns, env.castingEntity as? ServerPlayer) + val trueName = MishapOthersName.getTrueNameFromArgs(patterns, env.castingEntity as? ServerPlayer, env.world) if (trueName != null) throw MishapOthersName(trueName) 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/OpPotionEffect.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpPotionEffect.kt index cea6c99faf..5cecc45f66 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 @@ -21,10 +21,10 @@ class OpPotionEffect( args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getLivingEntityButNotArmorStand(0, argc) + val target = args.getLivingEntityButNotArmorStand(0, argc, env.world) 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) 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..77fb953431 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 @@ -21,20 +21,19 @@ object OpRecharge : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val entity = args.getItemEntity(0, argc) + val entity = args.getItemEntity(0, argc, env.world) - 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" ) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt index 515518cadc..3e73b310b5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpAltiora.kt @@ -20,7 +20,7 @@ object OpAltiora : SpellAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): SpellAction.Result { - val target = args.getPlayer(0, argc) + val target = args.getPlayer(0, argc, env.world) env.assertEntityInRange(target) return SpellAction.Result( diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt index b6325f685a..4ce4dedf9a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpBrainsweep.kt @@ -35,7 +35,7 @@ object OpBrainsweep : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val sacrifice = args.getMob(0, argc) + val sacrifice = args.getMob(0, argc, env.world) val vecPos = args.getVec3(1, argc) val pos = BlockPos.containing(vecPos) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt index abd39e52e1..2d2fefb06a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/great/OpTeleport.kt @@ -32,7 +32,7 @@ object OpTeleport : SpellAction { env: CastingEnvironment ): SpellAction.Result { - val teleportee = args.getEntity(0, argc) + val teleportee = args.getEntity(0, argc, env.world) val delta = args.getVec3(1, argc) env.assertEntityInRange(teleportee) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpDuplicateN.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpDuplicateN.kt index fd3aa008c0..ca92c7f082 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpDuplicateN.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/stack/OpDuplicateN.kt @@ -4,17 +4,20 @@ import at.petrak.hexcasting.api.casting.castables.ConstMediaAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.getPositiveInt import at.petrak.hexcasting.api.casting.iota.Iota -import at.petrak.hexcasting.api.casting.mishaps.MishapShameOnYou +import at.petrak.hexcasting.common.lib.hex.HexIotaTypes object OpDuplicateN : ConstMediaAction { override val argc: Int get() = 2 override fun execute(args: List, env: CastingEnvironment): List { - val count = args.getPositiveInt(1, argc) + var count = args.getPositiveInt(1, argc) - if (count > 1000) { - throw MishapShameOnYou() + if (count > HexIotaTypes.MAX_SERIALIZATION_TOTAL) { + // If we throw here, the message will point to us, which usually doesn't happen. + // So ensure that this check has no user-facing effects, just cap to MAX_SERIALIZATION_TOTAL, + // which will unconditionally trigger Too Many Iotas after we return. + count = HexIotaTypes.MAX_SERIALIZATION_TOTAL } return (List(count) { args[0] }) 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..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,7 +57,8 @@ 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) } + // 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) } SIN -> make1 { a -> sin(a) } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/command/ListPerWorldPatternsCommand.java b/Common/src/main/java/at/petrak/hexcasting/common/command/ListPerWorldPatternsCommand.java index f39e14d47f..c5c45ad7d8 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/command/ListPerWorldPatternsCommand.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/command/ListPerWorldPatternsCommand.java @@ -100,7 +100,7 @@ private static int giveAll(CommandSourceStack source, Collection t var tag = new CompoundTag(); tag.putString(ItemScroll.TAG_OP_ID, key.location().toString()); - tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); + tag.put(ItemScroll.TAG_PATTERN, HexUtils.serializeWithCodec(pat, HexPattern.CODEC)); var stack = new ItemStack(HexItems.SCROLL_LARGE); stack.setTag(tag); @@ -134,7 +134,7 @@ private static int giveOne(CommandSourceStack source, Collection t if (!targets.isEmpty()) { var tag = new CompoundTag(); tag.putString(ItemScroll.TAG_OP_ID, patternName.toString()); - tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); + tag.put(ItemScroll.TAG_PATTERN, HexUtils.serializeWithCodec(pat, HexPattern.CODEC)); var stack = new ItemStack(HexItems.SCROLL_LARGE); stack.setTag(tag); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/entities/EntityWallScroll.java b/Common/src/main/java/at/petrak/hexcasting/common/entities/EntityWallScroll.java index cd9ab651cb..de6879b066 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/entities/EntityWallScroll.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/entities/EntityWallScroll.java @@ -71,7 +71,7 @@ public EntityWallScroll(Level world, BlockPos pos, Direction dir, ItemStack scro public void recalculateDisplay() { CompoundTag patternTag = NBTHelper.getCompound(scroll, ItemScroll.TAG_PATTERN); if (patternTag != null) { - this.pattern = HexPattern.fromNBT(patternTag); + this.pattern = HexUtils.deserializeWithCodec(patternTag, HexPattern.CODEC); if (this.level().isClientSide) { var pair = RenderLib.getCenteredPattern(pattern, 128f / 3 * blockSize, 128f / 3 * blockSize, 16f / 3 * blockSize); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java index a189fd0703..27f238dda5 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/items/magic/ItemPackagedHex.java @@ -8,6 +8,7 @@ import at.petrak.hexcasting.api.casting.iota.PatternIota; import at.petrak.hexcasting.api.item.HexHolderItem; import at.petrak.hexcasting.api.pigment.FrozenPigment; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.common.msgs.MsgNewSpiralPatternsS2C; import at.petrak.hexcasting.xplat.IXplatAbstractions; @@ -76,7 +77,7 @@ public boolean hasHex(ItemStack stack) { var out = new ArrayList(); for (var patTag : patsTag) { CompoundTag tag = NBTHelper.getAsCompound(patTag); - out.add(IotaType.deserialize(tag, level)); + out.add(HexUtils.deserializeWithCodec(tag, Iota.getCodec(level))); } return out; } @@ -85,7 +86,7 @@ public boolean hasHex(ItemStack stack) { public void writeHex(ItemStack stack, List program, @Nullable FrozenPigment pigment, long media) { ListTag patsTag = new ListTag(); for (Iota pat : program) { - patsTag.add(IotaType.serialize(pat)); + patsTag.add(HexUtils.serializeWithCodec(pat, Iota.getCodec())); } NBTHelper.putList(stack, TAG_PROGRAM, patsTag); 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..21e7e6ea56 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 @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.common.lib.HexSounds; import net.minecraft.nbt.CompoundTag; @@ -30,7 +31,12 @@ public ItemAbacus(Properties pProperties) { public @Nullable CompoundTag readIotaTag(ItemStack stack) { var datum = new DoubleIota(NBTHelper.getDouble(stack, TAG_VALUE)); - return IotaType.serialize(datum); + return (CompoundTag) HexUtils.serializeWithCodec(datum, Iota.getCodec()); + } + + @Override + public boolean writeable(ItemStack stack) { + return false; } @Override 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..304252a1d9 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,9 +2,9 @@ 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.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -45,13 +45,13 @@ public String getDescriptionId(ItemStack stack) { } @Override - public @Nullable Iota emptyIota(ItemStack stack) { - return new NullIota(); + public boolean writeable(ItemStack stack) { + return !isSealed(stack); } @Override public boolean canWrite(ItemStack stack, Iota datum) { - return datum == null || !NBTHelper.getBoolean(stack, TAG_SEALED); + return datum == null || !isSealed(stack); } @Override @@ -60,7 +60,7 @@ public void writeDatum(ItemStack stack, Iota datum) { stack.removeTagKey(TAG_DATA); stack.removeTagKey(TAG_SEALED); } else if (!isSealed(stack)) { - NBTHelper.put(stack, TAG_DATA, IotaType.serialize(datum)); + NBTHelper.put(stack, TAG_DATA, HexUtils.serializeWithCodec(datum, Iota.getCodec())); } } 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..3443dc4da5 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 @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.iota.PatternIota; import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.api.item.IotaHolderItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.client.gui.PatternTooltipComponent; import at.petrak.hexcasting.common.entities.EntityWallScroll; @@ -63,6 +64,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; @@ -72,7 +78,7 @@ public boolean canWrite(ItemStack stack, Iota datum) { public void writeDatum(ItemStack stack, Iota datum) { if (this.canWrite(stack, datum)) { if (datum instanceof PatternIota pat) { - NBTHelper.putCompound(stack, TAG_PATTERN, pat.getPattern().serializeToNBT()); + NBTHelper.put(stack, TAG_PATTERN, HexUtils.serializeWithCodec(pat.getPattern(), HexPattern.CODEC)); } else if (datum == null) { NBTHelper.remove(stack, TAG_PATTERN); } @@ -139,7 +145,7 @@ public Component getName(ItemStack pStack) { public Optional getTooltipImage(ItemStack stack) { var compound = NBTHelper.getCompound(stack, ItemScroll.TAG_PATTERN); if (compound != null) { - var pattern = HexPattern.fromNBT(compound); + var pattern = HexUtils.deserializeWithCodec(compound, HexPattern.CODEC); return Optional.of(new PatternTooltip( pattern, NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) 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..a5f87e2b80 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 @@ -6,6 +6,7 @@ import at.petrak.hexcasting.api.casting.iota.PatternIota; import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.api.item.IotaHolderItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import at.petrak.hexcasting.client.gui.PatternTooltipComponent; import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate; @@ -84,6 +85,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; @@ -100,7 +106,7 @@ public void writeDatum(ItemStack stack, Iota datum) { } } else if (datum instanceof PatternIota pat) { var beTag = NBTHelper.getOrCreateCompound(stack, "BlockEntityTag"); - beTag.put(BlockEntitySlate.TAG_PATTERN, pat.getPattern().serializeToNBT()); + beTag.put(BlockEntitySlate.TAG_PATTERN, HexUtils.serializeWithCodec(pat.getPattern(), HexPattern.CODEC)); } } } @@ -112,7 +118,7 @@ public Optional getTooltipImage(ItemStack stack) { if (bet != null && bet.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND)) { var patTag = bet.getCompound(BlockEntitySlate.TAG_PATTERN); if (!patTag.isEmpty()) { - var pattern = HexPattern.fromNBT(patTag); + var pattern = HexUtils.deserializeWithCodec(patTag, HexPattern.CODEC); return Optional.of(new PatternTooltip(pattern, PatternTooltipComponent.SLATE_BG)); } } 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..6618ec760f 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,9 +2,9 @@ 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.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; @@ -130,9 +130,8 @@ CompoundTag readIotaTag(ItemStack stack) { } @Override - public @Nullable - Iota emptyIota(ItemStack stack) { - return new NullIota(); + public boolean writeable(ItemStack stack) { + return !isSealed(stack); } @Override @@ -154,14 +153,14 @@ public void writeDatum(ItemStack stack, Iota datum) { pages.remove(key); NBTHelper.remove(NBTHelper.getCompound(stack, TAG_SEALED), key); } else { - pages.put(key, IotaType.serialize(datum)); + pages.put(key, HexUtils.serializeWithCodec(datum, Iota.getCodec())); } if (pages.isEmpty()) { NBTHelper.remove(stack, TAG_PAGES); } } else if (datum != null) { - NBTHelper.getOrCreateCompound(stack, TAG_PAGES).put(key, IotaType.serialize(datum)); + NBTHelper.getOrCreateCompound(stack, TAG_PAGES).put(key, HexUtils.serializeWithCodec(datum, Iota.getCodec())); } else { NBTHelper.remove(NBTHelper.getCompound(stack, TAG_SEALED), key); } 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..2d5b7880f4 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 @@ -3,6 +3,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.api.utils.NBTHelper; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -32,15 +33,20 @@ 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); + return iota != null && writeable(stack); } @Override public void writeDatum(ItemStack stack, @Nullable Iota iota) { if (iota != null) { - NBTHelper.putCompound(stack, TAG_DATA, IotaType.serialize(iota)); + NBTHelper.put(stack, TAG_DATA, HexUtils.serializeWithCodec(iota, Iota.getCodec())); } } 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 e7ca5402c2..d0451ec184 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 @@ -1,12 +1,21 @@ package at.petrak.hexcasting.common.lib; import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstapContext; import net.minecraft.resources.ResourceKey; +import net.minecraft.world.damagesource.DamageScaling; import net.minecraft.world.damagesource.DamageType; import static at.petrak.hexcasting.api.HexAPI.modLoc; 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("overcast")); + + public static void bootstrap(BootstapContext ctx) { + ctx.register(OVERCAST, new DamageType( + "hexcasting.overcast", + DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER, + 0f + )); + } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexActions.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexActions.java index deca2c26de..27398b8787 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexActions.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/hex/HexActions.java @@ -395,6 +395,9 @@ public class HexActions { public static final ActionRegistryEntry WRITE$LOCAL = make("write/local", new ActionRegistryEntry(HexPattern.fromAngles("eqqwawqaaw", HexDir.NORTH_WEST), OpPushLocal.INSTANCE)); + public static final ActionRegistryEntry THANATOS = make("thanatos", + new ActionRegistryEntry(HexPattern.fromAngles("qqaed", HexDir.SOUTH_EAST), OpThanos.INSTANCE)); + // == Consts == public static final ActionRegistryEntry CONST$NULL = make("const/null", diff --git a/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java b/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java index 30c9f97370..2788d98e86 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/loot/AddPerWorldPatternToScrollFunc.java @@ -1,6 +1,7 @@ package at.petrak.hexcasting.common.loot; import at.petrak.hexcasting.api.casting.ActionRegistryEntry; +import at.petrak.hexcasting.api.casting.math.HexPattern; import at.petrak.hexcasting.api.mod.HexTags; import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.common.casting.PatternRegistryManifest; @@ -49,7 +50,7 @@ public static ItemStack doStatic(ItemStack stack, LootContext ctx) { var pat = PatternRegistryManifest.getCanonicalStrokesPerWorld(key, ctx.getLevel().getServer().overworld()); var tag = new CompoundTag(); tag.putString(ItemScroll.TAG_OP_ID, key.location().toString()); - tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT()); + tag.put(ItemScroll.TAG_PATTERN, HexUtils.serializeWithCodec(pat, HexPattern.CODEC)); stack.getOrCreateTag().merge(tag); diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternC2S.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternC2S.java index ce19d966b3..0b18ac3041 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternC2S.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpellPatternC2S.java @@ -3,7 +3,9 @@ import at.petrak.hexcasting.api.casting.eval.ResolvedPattern; import at.petrak.hexcasting.api.casting.eval.env.StaffCastEnv; import at.petrak.hexcasting.api.casting.math.HexPattern; +import at.petrak.hexcasting.api.utils.HexUtils; import io.netty.buffer.ByteBuf; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; @@ -32,12 +34,12 @@ public ResourceLocation getFabricId() { public static MsgNewSpellPatternC2S deserialize(ByteBuf buffer) { var buf = new FriendlyByteBuf(buffer); var hand = buf.readEnum(InteractionHand.class); - var pattern = HexPattern.fromNBT(buf.readNbt()); + var pattern = HexUtils.deserializeWithCodec(buf.readNbt(), HexPattern.CODEC); var resolvedPatternsLen = buf.readInt(); var resolvedPatterns = new ArrayList(resolvedPatternsLen); for (int i = 0; i < resolvedPatternsLen; i++) { - resolvedPatterns.add(ResolvedPattern.fromNBT(buf.readNbt())); + resolvedPatterns.add(HexUtils.deserializeWithCodec(buf.readNbt(), ResolvedPattern.CODEC)); } return new MsgNewSpellPatternC2S(hand, pattern, resolvedPatterns); } @@ -45,10 +47,10 @@ public static MsgNewSpellPatternC2S deserialize(ByteBuf buffer) { @Override public void serialize(FriendlyByteBuf buf) { buf.writeEnum(handUsed); - buf.writeNbt(this.pattern.serializeToNBT()); + buf.writeNbt((CompoundTag) HexUtils.serializeWithCodec(this.pattern, HexPattern.CODEC)); buf.writeInt(this.resolvedPatterns.size()); for (var pat : this.resolvedPatterns) { - buf.writeNbt(pat.serializeToNBT()); + buf.writeNbt((CompoundTag) HexUtils.serializeWithCodec(pat, ResolvedPattern.CODEC)); } } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpiralPatternsS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpiralPatternsS2C.java index 9c5a02180c..dcf07f92bd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpiralPatternsS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgNewSpiralPatternsS2C.java @@ -1,9 +1,11 @@ package at.petrak.hexcasting.common.msgs; import at.petrak.hexcasting.api.casting.math.HexPattern; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.xplat.IClientXplatAbstractions; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; @@ -25,7 +27,7 @@ public static MsgNewSpiralPatternsS2C deserialize(ByteBuf buffer) { var buf = new FriendlyByteBuf(buffer); var player = buf.readUUID(); - var patterns = buf.readCollection(ArrayList::new, buff -> HexPattern.fromNBT(buf.readNbt())); + var patterns = buf.readCollection(ArrayList::new, buff -> HexUtils.deserializeWithCodec(buf.readNbt(), HexPattern.CODEC)); var lifetime = buf.readInt(); @@ -35,7 +37,7 @@ public static MsgNewSpiralPatternsS2C deserialize(ByteBuf buffer) { @Override public void serialize(FriendlyByteBuf buf) { buf.writeUUID(playerUUID); - buf.writeCollection(patterns, (buff, pattern) -> buff.writeNbt(pattern.serializeToNBT())); + buf.writeCollection(patterns, (buff, pattern) -> buff.writeNbt((CompoundTag) HexUtils.serializeWithCodec(pattern, HexPattern.CODEC))); buf.writeInt(lifetime); } diff --git a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgOpenSpellGuiS2C.java b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgOpenSpellGuiS2C.java index a06e608bdb..b4e20144bd 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgOpenSpellGuiS2C.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/msgs/MsgOpenSpellGuiS2C.java @@ -1,6 +1,8 @@ package at.petrak.hexcasting.common.msgs; import at.petrak.hexcasting.api.casting.eval.ResolvedPattern; +import at.petrak.hexcasting.api.casting.iota.PatternIota; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.client.gui.GuiSpellcasting; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; @@ -47,7 +49,7 @@ public static MsgOpenSpellGuiS2C deserialize(ByteBuf buffer) { public void serialize(FriendlyByteBuf buf) { buf.writeEnum(this.hand); - buf.writeCollection(this.patterns, (fbb, pat) -> fbb.writeNbt(pat.serializeToNBT())); + buf.writeCollection(this.patterns, (fbb, pat) -> fbb.writeNbt((CompoundTag) HexUtils.serializeWithCodec(pat, ResolvedPattern.CODEC))); buf.writeCollection(this.stack, FriendlyByteBuf::writeNbt); buf.writeNbt(this.ravenmind); 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() diff --git a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexBlockTagProvider.java b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexBlockTagProvider.java index 75b0435235..dffbb06364 100644 --- a/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexBlockTagProvider.java +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexBlockTagProvider.java @@ -16,7 +16,8 @@ public class HexBlockTagProvider extends PaucalBlockTagProvider { public final IXplatTags xtags; - public HexBlockTagProvider(PackOutput output, CompletableFuture lookupProvider, IXplatTags xtags) { + public HexBlockTagProvider(PackOutput output, CompletableFuture lookupProvider, + IXplatTags xtags) { super(output, lookupProvider); this.xtags = xtags; } @@ -94,18 +95,17 @@ protected void addTags(HolderLookup.Provider provider) { add(tag(BlockTags.STAIRS), HexBlocks.EDIFIED_STAIRS); add(tag(BlockTags.FENCES), - HexBlocks.EDIFIED_FENCE); + HexBlocks.EDIFIED_FENCE); add(tag(BlockTags.WOODEN_FENCES), - HexBlocks.EDIFIED_FENCE); + HexBlocks.EDIFIED_FENCE); add(tag(BlockTags.FENCE_GATES), - HexBlocks.EDIFIED_FENCE_GATE); + HexBlocks.EDIFIED_FENCE_GATE); add(tag(BlockTags.UNSTABLE_BOTTOM_CENTER), - HexBlocks.EDIFIED_FENCE_GATE); - + HexBlocks.EDIFIED_FENCE_GATE); add(tag(BlockTags.WOODEN_FENCES), - HexBlocks.EDIFIED_FENCE); + HexBlocks.EDIFIED_FENCE); add(tag(BlockTags.WOODEN_STAIRS), HexBlocks.EDIFIED_STAIRS); add(tag(BlockTags.DOORS), @@ -127,6 +127,8 @@ protected void addTags(HolderLookup.Provider provider) { add(tag(HexTags.Blocks.WATER_PLANTS), Blocks.KELP, Blocks.KELP_PLANT, Blocks.SEAGRASS, Blocks.TALL_SEAGRASS); + add(tag(HexTags.Blocks.CHEAP_TO_BREAK_BLOCK), + HexBlocks.CONJURED_BLOCK, HexBlocks.CONJURED_LIGHT); } void add(TagAppender appender, Block... blocks) { 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 new file mode 100644 index 0000000000..16e7020d08 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/datagen/tag/HexDamageTypeTagProvider.java @@ -0,0 +1,35 @@ +package at.petrak.hexcasting.datagen.tag; + +import at.petrak.hexcasting.common.lib.HexDamageTypes; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.data.tags.DamageTypeTagsProvider; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.DamageTypeTags; +import net.minecraft.tags.TagKey; +import net.minecraft.world.damagesource.DamageType; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.CompletableFuture; + +public class HexDamageTypeTagProvider extends DamageTypeTagsProvider { + public HexDamageTypeTagProvider(PackOutput output, CompletableFuture provider) { + super(output, provider); + } + + @Override + protected void addTags(@NotNull HolderLookup.Provider provider) { + add(HexDamageTypes.OVERCAST, + DamageTypeTags.BYPASSES_ARMOR, + DamageTypeTags.BYPASSES_EFFECTS, + DamageTypeTags.BYPASSES_SHIELD + ); + } + + @SafeVarargs + private void add(ResourceKey damageType, TagKey... tags) { + for (var tag : tags) { + this.tag(tag).add(damageType); + } + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt index d1a9868c51..828f1e17a6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt +++ b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpGetScale.kt @@ -11,7 +11,7 @@ object OpGetScale : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) env.assertEntityInRange(target) return IXplatAbstractions.INSTANCE.pehkuiApi.getScale(target).toDouble().asActionResult } diff --git a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt index 9c171c5784..aa5c40ced9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt +++ b/Common/src/main/java/at/petrak/hexcasting/interop/pehkui/OpSetScale.kt @@ -17,7 +17,7 @@ object OpSetScale : SpellAction { args: List, env: CastingEnvironment ): SpellAction.Result { - val target = args.getEntity(0, argc) + val target = args.getEntity(0, argc, env.world) val scale = args.getDoubleBetween(1, 1.0 / 32.0, 8.0, argc) env.assertEntityInRange(target) 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 2047c39c47..93ca9c9c0b 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 @@ -19,34 +19,34 @@ quenched: "Quenched Shard Staff", mindsplice: "Mindsplice Staff", }, - + amethyst_dust: "Amethyst Dust", charged_amethyst: "Charged Amethyst", quenched_allay_shard: "Shard of Quenched Allay", - + scroll_small: { "": "Small Scroll", of: "How did you get this item of %s", empty: "Empty Small Scroll", }, - + scroll_medium: { "": "Medium Scroll", of: "How did you get this item of %s", empty: "Empty Medium Scroll", }, - + scroll: { "": "Large Scroll", of: "Ancient Scroll of %s", empty: "Empty Large Scroll", }, - + focus: { "": "Focus", sealed: "Sealed Focus", }, - + thought_knot: "Thought-Knot", spellbook: "Spellbook", cypher: "Cypher", @@ -57,7 +57,7 @@ abacus: "Abacus", jeweler_hammer: "Jeweler's Hammer", sub_sandwich: "Submarine Sandwich", - + dye_colorizer_: { white: "White Pigment", orange: "Orange Pigment", @@ -76,7 +76,7 @@ red: "Red Pigment", black: "Black Pigment", }, - + pride_colorizer_: { agender: "Agender Pigment", aroace: "Aroace Pigment", @@ -95,17 +95,17 @@ plural: "Plural Pigment", transgender: "Transgender Pigment", }, - + uuid_colorizer: "Soulglimmer Pigment", default_colorizer: "Vacant Pigment", - + creative_unlocker: { "": "The Media Cube", for_emphasis: "INFINITE MEDIA", tooltip: "Consume to unlock all %s knowledge.", mod_name: "Hexcasting", }, - + lore_fragment: { "": "Lore Fragment", all: "It seems I have found all the lore this world has to offer.", @@ -119,32 +119,32 @@ "block.hexcasting": { conjured_light: "Conjured Light", conjured_block: "Conjured Block", - + directrix: { empty: "Empty Directrix", redstone: "Mason Directrix", boolean: "??? Directrix", }, - + impetus: { empty: "Empty Impetus", rightclick: "Toolsmith Impetus", look: "Fletcher Impetus", redstone: "Cleric Impetus", }, - + akashic_: { record: "Akashic Record", bookshelf: "Akashic Bookshelf", connector: "Akashic Ligature", }, - + slate: { "": "Slate", blank: "Blank Slate", written: "Patterned Slate", }, - + slate_: { block: "Block of Slate", tiles: "Slate Tiles", @@ -152,7 +152,7 @@ bricks_small: "Small Slate Bricks", pillar: "Slate Pillar", }, - + amethyst_: { dust_block: "Block of Amethyst Dust", tiles: "Amethyst Tiles", @@ -160,20 +160,20 @@ bricks_small: "Small Amethyst Bricks", pillar: "Amethyst Pillar", }, - + slate_amethyst_: { tiles: "Slate & Amethyst Tiles", bricks: "Slate & Amethyst Bricks", bricks_small: "Small Slate & Amethyst Bricks", pillar: "Slate & Amethyst Pillar", }, - + scroll_paper: "Scroll Paper", ancient_scroll_paper: "Ancient Scroll Paper", scroll_paper_lantern: "Paper Lantern", ancient_scroll_paper_lantern: "Ancient Paper Lantern", amethyst_sconce: "Amethyst Sconce", - + edified_: { log: "Edified Log", log_amethyst: "Amethyst Edified Log", @@ -193,39 +193,39 @@ fence: "Edified Fence", fence_gate: "Edified Fence Gate", }, - + stripped_edified_log: "Stripped Edified Log", stripped_edified_wood: "Stripped Edified Wood", - + amethyst_edified_leaves: "Amethyst Edified Leaves", aventurine_edified_leaves: "Aventurine Edified Leaves", citrine_edified_leaves: "Citrine Edified Leaves", - - quenched_allay: "Quenched Allay", + quenched_allay: "Quenched Allay", + quenched_allay_: { tiles: "Quenched Allay Tiles", bricks: "Quenched Allay Bricks", bricks_small: "Small Quenched Allay Bricks", }, }, - + "itemGroup.hexcasting": { "": "Hexcasting", creative_tab: "Hexcasting", }, - + "gui.hexcasting": { spellcasting: "Hex Grid", }, - + "tag.hexcasting": { staves: "Hex Staves", edified_logs: "Edified Logs", edified_planks: "Edified Planks", phial_base: "Empty Phials", }, - + "tag.item.hexcasting": { brainswept_circle_components: "Brainswept Circle Components", directrices: "Directrices", @@ -233,7 +233,7 @@ impeti: "Impeti", seal_materials: "Seal Materials", }, - + "emi.category.hexcasting": { brainsweep: "Flay Mind", "craft.battery": "Craft Phial", @@ -244,13 +244,13 @@ "text.autoconfig.hexcasting": { title: "Hexcasting Config", - + category: { common: "Common", client: "Client", server: "Server", }, - + option: { common: { dustMediaAmount: { @@ -282,7 +282,7 @@ "@Tooltip": "Cooldown of an artifact in ticks", }, }, - + client: { ctrlTogglesOffStrokeOrder: { "": "Ctrl Toggles Off Stroke Order", @@ -301,7 +301,7 @@ "@Tooltip": "When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 means 50% of the way (0.5-1)", }, }, - + server: { opBreakHarvestLevel: { "": "Break Harvest Level", @@ -335,7 +335,7 @@ "": "Amethyst Shard Drop Rate Change", "@Tooltip": "How much the number of amethyst shards dropped from clusters is increased/decreased.", }, - + // TODO: are these used anywhere?? "fewScrollTables.@Tooltip": "Loot tables that a small number of Ancient Scrolls are injected into", "someScrollTables.@Tooltip": "Loot tables that a decent number of Ancient Scrolls are injected into", @@ -343,7 +343,7 @@ }, }, }, - + "advancement.hexcasting:": { root: { "": "Hexcasting Research", @@ -399,28 +399,30 @@ inventory: "Restoration Log 72", }, }, - + "stat.hexcasting": { media_used: "Media Consumed (in dust)", - media_overcasted: "Media Overcast (in dust)", + media_overcast: "Media Overcast (in dust)", patterns_drawn: "Patterns Drawn", spells_cast: "Spells Cast", }, - + "death.attack.hexcasting": { - overcast: "%s's mind was subsumed into energy", - shame: "Shame on %s!", + overcast: { + "": "%s's mind was subsumed into energy", + player: "%s's mind was subsumed into energy while fighting %s", + }, }, - + "command.hexcasting": { recalc: "Recalculated patterns", - + pats: { listing: "Patterns in this world:", all: "Gave all %d scrolls to %s", "specific.success": "Gave %s with id %s to %s", }, - + brainsweep: { "": "Brainswept %s", "fail.badtype": "%s is not a mob", @@ -462,13 +464,13 @@ }, sealed: "Sealed", }, - + abacus: { "": "%d", reset: "Reset to 0", "reset.nice": "nice", }, - + circle: { no_exit: "The flow of media could not find an exit at %s", many_exits: "The flow of media had too many exits at %s", @@ -493,17 +495,17 @@ }, }, }, - + brainsweep: { min_level: "Level %s or higher", level: "Level %s", product: "Mindless Body", }, - + media: "%d dust", media_amount: "Contains: %s (%s)", "media_amount.advanced": "Contains: %s/%s (%s)", - + list_contents: "[%s]", null_iota: "Null", jump_iota: "[Jump]", @@ -566,7 +568,7 @@ "null": "Nullary Reflection", "true": "True Reflection", "false": "False Reflection", - + "vec/": { px: "Vector Reflection +X", py: "Vector Reflection +Y", @@ -576,14 +578,14 @@ nz: "Vector Reflection -Z", "0": "Vector Reflection Zero", }, - + "double/": { pi: "Arc's Reflection", tau: "Circle's Reflection", "e": "Euler's Reflection", }, }, - + get_caster: "Mind's Reflection", "entity_pos/eye": "Compass' Purification", "entity_pos/foot": "Compass' Purification II", @@ -593,14 +595,14 @@ raycast: "Archer's Distillation", "raycast/axis": "Architect's Distillation", "raycast/entity": "Scout's Distillation", - + "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", @@ -624,7 +626,7 @@ player: "Entity Purification: Player", living: "Entity Purification: Living", }, - + zone_entity: "Zone Distillation: Any", "zone_entity/": { animal: "Zone Distillation: Animal", @@ -638,7 +640,7 @@ not_player: "Zone Distillation: Non-Player", not_living: "Zone Distillation: Non-Living", }, - + swap: "Jester's Gambit", rotate: "Rotation Gambit", rotate_reverse: "Rotation Gambit II", @@ -692,18 +694,18 @@ read: "Scribe's Reflection", "read/entity": "Chronicler's Purification", "read/local": "Muninn's Reflection", - + write: "Scribe's Gambit", "write/entity": "Chronicler's Gambit", "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", @@ -712,12 +714,12 @@ 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", @@ -729,7 +731,7 @@ bonemeal: "Overgrow", edify: "Edify Sapling", colorize: "Internalize Pigment", - + "sentinel/": { create: "Summon Sentinel", "create/great": "Summon Greater Sentinel", @@ -737,43 +739,44 @@ get_pos: "Locate Sentinel", wayfind: "Wayfind Sentinel", }, - + "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", - + 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", }, - + 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", + thanatos: "Thanatos' Reflection", "interop/": { "gravity/": { get: "Gravitational Purification", set: "Alter Gravity", }, - + "pehkui/": { get: "Gulliver's Purification", set: "Alter Scale", @@ -784,7 +787,7 @@ // 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/": { animal: "Entity Prfn.: Animal", monster: "Entity Prfn.: Monster", @@ -792,7 +795,7 @@ player: "Entity Prfn.: Player", living: "Entity Prfn.: Living", }, - + zone_entity: "Zone Dstl.: Any", "zone_entity/": { animal: "Zone Dstl.: Animal", @@ -806,20 +809,20 @@ not_player: "Zone Dstl.: Non-Player", not_living: "Zone Dstl.: Non-Living", }, - + mul: "Multiplicative Dstl.", div: "Division Dstl.", arcsin: "Inverse Sine Prfn.", arccos: "Inverse Cosine Prfn.", arctan: "Inverse Tangent Prfn.", arctan2: "Inverse Tan. Prfn. II", - + "const/vec/": { x: "Vector Rfln. +X/-X", y: "Vector Rfln. +Y/-Y", z: "Vector Rfln. +Z/-Z", }, - + "read/entity": "Chronicler's Prfn.", bool_to_number: "Numerologist's Prfn.", number: "Numerical Reflection", @@ -827,19 +830,19 @@ }, }, // ^ action - + "special.hexcasting:": { number: "Numerical Reflection: %s", mask: "Bookkeeper's Gambit: %s", }, - + "rawhook.hexcasting:": { open_paren: "Introspection", close_paren: "Retrospection", escape: "Consideration", undo: "Evanition", }, - + "iota.hexcasting:": { "null": "Null", double: "Number", @@ -850,7 +853,7 @@ garbage: "Garbage", vec3: "Vector", }, - + mishap: { "": "%s: %s", @@ -873,13 +876,13 @@ no_spell_circle: "%s requires a spell circle", others_name: "Tried to invade the privacy of %s's soul", "others_name.self": "Tried to divulge my Name too recklessly", - + divide_by_zero: { divide: "Attempted to divide %s by %s", project: "Attempted to project %s onto %s", exponent: "Attempted to raise %s to the %s", logarithm: "Attempted to get the logarithm of %s in base %s", - + zero: { "": "zero", power: "zeroth power", @@ -889,17 +892,22 @@ sin: "the sine of %s", cos: "the cosine of %s", }, - + + invalid_operator_args: { + one: "got an unexpected iota at index %d of the stack: %s", + many: "got %d unexpected iotas at indices %d-%d of the stack: %s", + }, + no_akashic_record: "No Akashic Record at %s", disallowed: "has been disallowed by the server admins", disallowed_circle: "has been disallowed in spell circles by the server admins", 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 the size limit of the stack", invalid_value: { "": "expected %s at index %s of the stack, but got %s", - + class: { double: "a number", boolean: "a boolean", @@ -907,7 +915,7 @@ list: "a list", widget: "an influence", pattern: "a pattern", - + entity: { "": "an entity", item: "an item entity", @@ -915,14 +923,14 @@ villager: "a villager", living: "a living entity", }, - + unknown: "(unknown, uh-oh, this is a bug)", }, - + numvec: "a number or vector", numlist: "an integer or list", "list.pattern": "a list of patterns", - + double: { positive: { "": "a positive number", @@ -931,7 +939,7 @@ }, between: "a number between %d and %d", }, - + int: { "": "an integer", positive: { @@ -941,12 +949,12 @@ }, between: "an integer between %d and %d", }, - + evaluatable: "something evaluatable", bool_commute: "a boolean, 0, or 1", }, - - location: { + + location_: { too_far: "%s is out of range", out_of_world: "%s is not within the world", too_close_to_out: "%s is too close to the boundary of the world", @@ -957,14 +965,14 @@ bad_item: { "": "needs %s but got %dx %s", offhand: "needs %s in the other hand but got %dx %s", - + iota: { "": "a place to store iotas", read: "a place to read iotas from", write: "a place to write iotas to", readonly: "a place that will accept %s", }, - + media: "a media-containing item", media_for_battery: "a raw media item", only_one: "exactly one item", @@ -974,17 +982,19 @@ colorizer: "a pigment", variant: "an item with variants", }, - + bad_block: { "": "Expected %s at %s, but got %s", sapling: "a sapling", replaceable: "somewhere to place a block", }, - + "circle.bool_directrix": { no_bool: "the iota encountered at %s was %s, not a bool", empty_stack: "the stack was empty at %s", }, + + entity_not_found: "the entity referenced by %s at index %s of the stack could not be found" }, // ^ mishap @@ -993,9 +1003,9 @@ many_exits: "The flow of media at %s had too many exits", }, - + // === Patchi stuff! === - + landing: "I seem to have discovered a new method of magical arts, in which one draws patterns strange and wild onto a hexagonal grid. \ It fascinates me. I've decided to start a journal of my thoughts and findings.\ @@ -1025,13 +1035,13 @@ I have seen I have seen I have s$(k)get stick bugged lmao/$", // alwinfy you think you're so funny }, - + lore: { "": "Lore", desc: "I have uncovered some letters and text not of direct relevance to my art. \ But, I think I may be able to divine some of the history of the world from these. Let me see...", }, - + interop: { "": "Cross-Mod Compatibility", desc: "It appears I have installed some mods Hexcasting interoperates with! I've detailed them here.", @@ -1159,32 +1169,32 @@ "2": "_Media can exert influences on other media-- the strength and type of influence can be manipulated by drawing _media out into patterns.$(p)Scholars of the art used a concentrated blob of _media on the end of a stick: by waving it in the air in precise configurations, they were able to manipulate enough _media with enough precision to influence the world itself, in the form of a _Hex.", "3": "Sadly, even a fully sentient being (like myself, presumably) can only generate miniscule amounts of _media. It would be quite impractical to try and use my own brainpower to cast Hexes.$(br2)But legend has it that there are underground deposits where _media slowly accumulates, growing into crystalline forms.$(p)If I could just find one of those...", }, - + geodes: { "1": "Aha! While mining deep underground, I found an enormous geode resonating with energy-- energy which pressed against my skull and my thoughts. And now, I hold that pressure in my hand, in solid form. That proves it. This $(italic)must/$ be the place spoken about in legends where _media accumulates.$(br2)These $(l:items/amethyst)$(item)amethyst crystals/$ must be a $(l:items/amethyst)$(thing)convenient, solidified form of _Media/$.", "2": "It appears that, in addition to the $(l:items/amethyst)$(item)Amethyst Shards/$ I have seen in the past, these crystals can also drop bits of powdered $(l:items/amethyst)$(item)Amethyst Dust/$, as well as these $(l:items/amethyst)$(item)Charged Amethyst Crystals/$. It looks like I'll have a better chance of finding the $(l:items/amethyst)$(item)Charged Amethyst Crystals/$ by using a Fortune pickaxe.", "3": "As I take the beauty of the crystal in, I can feel connections flashing wildly in my mind. It's like the _media in the air is entering me, empowering me, elucidating me... It feels wonderful.$(br2)Finally, my study into the arcane is starting to make some sense!$(p)Let me reread those old legends again, now that I know what I'm looking at.", }, - + couldnt_cast: { "1": "Argh! Why won't it let me cast the spell?!$(br2)The scroll I found rings with authenticity. I can $(italic)feel/$ it humming in the scroll-- the pattern is true, or as true as it can be. The spell is $(italic)right there/$.$(p)But it feels as if it's on the other side of some thin membrane. I called it-- it tried to manifest-- yet it $(italic)COULD NOT/$.", "2": "It felt like the barrier may have weakened ever so slightly from the force that I exerted on the spell; yet despite my greatest efforts-- my deepest focus, my finest amethyst, my precisest drawings-- it $(italic)refuses/$ to cross the barrier. It's maddening.$(p)$(italic)This/$ is where my arcane studies end? Cursed by impotence, cursed to lose my rightful powers?$(br2)I should take a deep breath. I should meditate on what I have learned, even if it wasn't very much...", "3": "...After careful reflection... I have discovered a change in myself.$(p)It seems... in lieu of $(l:items/amethyst)$(item)amethyst/$, I've unlocked the ability to cast spells using my own mind and life energy-- just as I read of in the legends of old.$(p)I'm not sure why I can now. It's just... the truth-knowledge-burden was always there, and I see it now. I know it. I bear it.$(br2)Fortunately, I feel my limits as well-- I would get approximately two $(l:items/amethyst)$(item)Charged Amethyst/$'s worth of _media out of my health at its prime.", "4": "I shudder to even consider it-- I've kept my mind mostly intact so far, in my studies. But the fact is-- I form one side of a tenuous link.$(p)I'm connected to some other side-- a side whose boundary has thinned from that trauma. A place where simple actions spell out eternal glory.$(p)Is it so wrong, to want it for myself?", }, - + start_to_see: { "1": "The texts weren't lying. Nature took its due.", "2": "That... that was...$(p)...that was one of the $(italic)worst/$ things I've $(italic)ever/$ experienced. I offered my plan to Nature, and got a firm smile and a tearing sensation in return-- a piece of myself breaking away, like amethyst dust in the rain.$(p)I feel lucky to have $(italic)survived/$, much less have the sagacity to write this-- I should declare the matter closed, double-check my math before I cast any more _Hexes, and never make such a mistake again.", "3": "...But.$(br2)But for the scarcest instant, that part of myself... it $(italic)saw/$... $(l:greatwork/the_work)$(thing)something/$. A place-- a design, perhaps? (Such distinctions didn't seem to matter in the face of... that.)$(p)And a... a membrane-barrier-skin-border, separating myself from a realm of raw thought-flow-light-energy. I remember-- I saw-thought-recalled-felt-- the barrier fuzzing at its edges, just so slightly.$(p)I wanted $(italic)through./$", "4": "I shouldn't. I $(italic)know/$ I shouldn't. It's dangerous. It's too dangerous. The force required... I'd have to bring myself within a hair's breadth of Death itself with a $(italic)single stroke/$.$(br2)But I'm. So. $(italic)Close/$.$(p)$(italic)This/$ is the culmination of my art. This is the $(#54398a)Enlightenment/$ I've been seeking. $(br2)I want more. I need to see it again. I $(italic)will/$ see it.$(p)What is my mortal mind against immortal glory?", }, - + casting: { overview: { "1": "I believe it's good to always start off on the right foot. So, I've compiled the patterns for a _Hex that will cause a modest explosion at the position I am looking at. I believe examining the inner workings of this _Hex will be quite edifying.", }, - + grid: { "1": "I will generally provide my patterns to Nature via my $(l:items/staff)$(item)Staff/$. \ Pressing $(thing)$(k:use)/$ with one in my hand will cause a hexagonal grid of dots to appear in front of me. \ @@ -1252,7 +1262,7 @@ "14.link_text": "Goblin Punch", "15": "Finally, it seems spells have a maximum range of influence, about 32 blocks from my position. Trying to affect anything outside of that will cause the spell to fail.$(br2)Despite this, if I have a player's reference, I can affect them from anywhere. This only applies to affecting them directly, though; I cannot use this to affect the world around them if they're outside of my range.$(br)I ought to be careful when giving out a reference like that. While friendly _Hexcasters could use them to great effect and utility, I shudder to think of what someone malicious might do with this.", }, - + vectors: { "1": "It seems I will need to be adroit with vectors if I am to get anywhere in my studies. I have compiled some resources here on vectors if I find I do not know how to work with them.$(br2)First off, an enlightening video on the topic.", "1.link_text": "3blue1brown", @@ -1260,148 +1270,151 @@ "3": "Link here.", "3.link_text": "Psi Codex", }, - + mishaps: { "1": "Unfortunately, I am not (yet) a perfect being. I make mistakes from time to time in my study and casting of _Hexes; for example, misdrawing a pattern, or trying to an invoke an action with the wrong iotas. And Nature usually doesn't look too kindly on my mistakes-- causing what is called a $(italic)mishap/$.", "2": "A pattern that causes a mishap will glow red in my grid. Depending on the type of mistake, I can also expect a certain deleterious effect and a spray of red and colorful sparks as the mishandled _media curdles into light of a given color.", "3": "Fortunately, although the bad effects of mishaps are certainly $(italic)annoying/$, none of them are especially destructive in the long term. Nothing better to do than dust myself off and try again ... but I should strive for better anyways.$(br2)Following is a list of mishaps I have compiled.", - + "invalid_pattern.title": "Invalid Pattern", invalid_pattern: "The pattern drawn is not associated with any action.$(br2)Causes yellow sparks, and a $(l:casting/influences)$(action)Garbage/$ will be pushed to the top of my stack.", - + "not_enough_iotas.title": "Not Enough Iotas", not_enough_iotas: "The action required more iotas than were on the stack.$(br2)Causes light gray sparks, and as many $(l:casting/influences)$(action)Garbages/$ as would be required to fill up the argument count will be pushed.", - + + "stack_size.title": "Too Many Iotas", + "stack_size": "I tried to cast a spell which exceeded the size limit of the stack.$(br2)Causes black sparks, and my entire stack will be replaced with a single $(l:casting/influences)$(action)Garbage/$.", + "incorrect_iota.title": "Incorrect Iota", incorrect_iota: "The action that was executed expected an iota of a certain type for an argument, but it got something invalid. If multiple iotas are invalid, the error message will only tell me about the error deepest in the stack.$(br2)Causes dark gray sparks, and the invalid iota will be replaced with $(l:casting/influences)$(action)Garbage/$.", - + "vector_out_of_range.title": "Vector Out of Ambit", vector_out_of_range: "The action tried to affect the world at a point that was out of my range.$(br2)Causes magenta sparks, and the items in my hands will be yanked out and flung towards the offending location.", - + "entity_out_of_range.title": "Entity Out of Ambit", entity_out_of_range: "The action tried to affect an entity that was out of my range.$(br2)Causes pink sparks, and the items in my hands will be yanked out and flung towards the offending entity.", - + "entity_immune.title": "Entity is Immune", entity_immune: "The action tried to affect an entity that cannot be altered by it.$(br2)Causes blue sparks, and the items in my hands will be yanked out and flung towards the offending entity.", - + "math_error.title": "Mathematical Error", math_error: "The action did something offensive to the laws of mathematics, such as dividing by zero.$(br2)Causes red sparks, pushes a $(l:casting/influences)$(action)Garbage/$ to my stack, and my mind will be ablated, stealing half the vigor I have remaining. It seems that Nature takes offense to such operations, and divides $(italic)me/$ in retaliation.", - + "incorrect_item.title": "Incorrect Item", incorrect_item: "The action requires some sort of item, but the item I supplied was not suitable.$(br2)Causes brown sparks. If the offending item was in my hand, it will be flung to the floor. If it was in entity form, it will be flung in the air.", - + "incorrect_block.title": "Incorrect Block", incorrect_block: "The action requires some sort of block at a target location, but the block supplied was not suitable.$(br2)Causes bright green sparks, and causes an ephemeral explosion at the given location. The explosion doesn't seem to harm me, the world, or anything else though; it's just startling.", - + "retrospection.title": "Hasty Retrospection", retrospection: "I attempted to draw $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ without first drawing $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$.$(br2)Causes orange sparks, and pushes the pattern for $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ to the stack as a pattern iota.", - + "too_deep.title": "Delve Too Deep", too_deep: "Evaluated too many spells with meta-evaluation from one spell.$(br2)Causes dark blue sparks, and chokes all the air out of me.", - + "true_name.title": "Transgress Other", true_name: "I attempted to $(l:patterns/readwrite#hexcasting:write)$(action)save a reference/$ to another player to a permanent medium.$(br2)Causes black sparks, and robs me of my sight for approximately one minute.", - + "disabled.title": "Disallowed Action", disabled: "I tried to cast an action that has been disallowed by a server administrator.$(br2)Causes black sparks.", - + "other.title": "Catastrophic Failure", other: "A bug in the mod caused an iota of an invalid type or otherwise caused the spell to crash. $(l:https://github.com/gamma-delta/HexMod/issues)Please open a bug report!/$$(br2)Causes black sparks.", }, - + stack: { "1": "A $(thing)Stack/$, also known as a \"LIFO\", is a concept borrowed from computer science. In short, it's a collection of things designed so that you can only interact with the most recently used thing.$(br2)Think of a stack of plates, where new plates are added to the top: if you want to interact with a plate halfway down the stack, you have to remove the plates above it in order to get ahold of it.", "2": "Because a stack is so simple, there's only so many things you can do with it:$(li)$(italic)Adding something to it/$, known formally as pushing,$(li)$(italic)Removing the last added element/$, known as popping, or$(li)$(italic)Examining or modifying the last added element/$, known as peeking.$(br)We call the last-added element the \"top\" of the stack, in accordance with the dinner plate analogy.$(p)As an example, if we push 1 to a stack, then push 2, then pop, the top of the stack is now 1.", "3": "Actions are (on the most part) restricted to interacting with the casting stack in these ways. They will pop some iotas they're interested in (known as \"arguments\" or \"parameters\"), process them, and push some number of results.$(br2)Of course, some actions (e.g. $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$) might pop no arguments, and some actions (particularly spells) might push nothing afterwards.", "4": "Even more complicated actions can be expressed in terms of pushing, popping, and peeking. For example, $(l:patterns/stackmanip#hexcasting:swap)$(action)Jester's Gambit/$ swaps the top two items of the stack. This can be thought of as popping two items and pushing them in opposite order. For another, $(l:patterns/stackmanip#hexcasting:duplicate)$(action)Gemini Decomposition/$ duplicates the top of the stack-- in other words, it peeks the stack and pushes a copy of what it finds.", }, - + naming: { "1": "The names given to actions by the ancients were certainly peculiar, but I think there's a certain kind of logic to them.$(br2)There seem to be certain groups of actions with common names, named for the number of iotas they remove from and add to the stack.", "2": "$(li)A $(thing)Reflection/$ pops nothing and pushes one iota.$(li)A $(thing)Purification/$ pops one and pushes one.$(li)A $(thing)Distillation/$ pops two and pushes one.$(li)An $(thing)Exaltation/$ pops three or more and pushes one.$(li)A $(thing)Decomposition/$ pops one argument and pushes two.$(li)A $(thing)Disintegration/$ pops one and pushes three or more.$(li)Finally, a $(thing)Gambit/$ pushes or pops some other number (or rearranges the stack in some other manner).", "3": "Spells seem to be exempt from this nomenclature and are more or less named after what they do-- after all, why call it a $(action)Demoman's Gambit/$ when you could just say $(l:patterns/spells/basic#hexcasting:explode)$(action)Explosion/$?", }, - + influences: { "1": "Influences are ... strange, to say the least. Whereas most iotas seem to represent something about the world, influences represent something more... abstract, or formless.$(br2)For example, one influence I've named $(l:casting/influences)$(thing)Null/$ seems to represent nothing at all. It's created when there isn't a suitable answer to a question asked, such as an $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$ facing the sky.", "2": "In addition, I've discovered a curious quartet of influences I've named $(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/$, and $(l:patterns/patterns_as_iotas#hexcasting:undo)$(action)Evanition/$. They seem to have properties of both patterns and other influences, yet act very differently. I can use these to add patterns to my stack as iotas, instead of matching them to actions. $(l:patterns/patterns_as_iotas)My notes on the subject are here/$.", "3": "Finally, there seems to be an infinite family of influences that just seem to be a tangled mess of _media. I've named them $(l:casting/influences)$(action)Garbage/$, as they are completely useless. They seem to appear in my stack at various places in response to $(l:casting/mishaps)$(thing)mishaps/$, and appear to my senses as a nonsense jumble.", }, - + mishaps2: { "1": "I have discovered new and horrifying modes of failure. I must not succumb to them.", - + "bad_mindflay.title": "Inert Mindflay", bad_mindflay: "Attempted to flay the mind of something that I have either already used, or of a character not suitable for the target block.$(br2)Causes dark green sparks, and kills the subject. If a villager sees that, I doubt they would look on it favorably.", - + "no_circle.title": "Lack Spell Circle", 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_record.title": "Lack Akashic Record", no_record: "Tried to access an $(l:greatwork/akashiclib)$(item)Akashic Record/$ at a location where there isn't one.$(br2)Causes purple sparks, and steals away some of my experience.", }, - - + + // Items - + amethyst: { dust: "It seems that I'll find three different forms of amethyst when breaking a crystal inside a geode. The smallest denomination seems to be a small pile of shimmering dust, worth a relatively small amount of _media.", shard: "The second is a whole shard of amethyst, of the type non-_Hexcasters might be used to. This has about as much _media inside as five $(l:items/amethyst)$(item)Amethyst Dust/$.", crystal: "Finally, I'll rarely find a large crystal crackling with energy. This has about as much _media inside as ten units of $(l:items/amethyst)$(item)Amethyst Dust/$ (or two $(l:items/amethyst)$(item)Amethyst Shards/$).", lore: "$(italic)The old man sighed and raised a hand toward the fire. He unlocked a part of his brain that held the memories of the mountains around them. He pulled the energies from those lands, as he learned to do in Terisia City with Drafna, Hurkyl, the archimandrite, and the other mages of the Ivory Towers. He concentrated, and the flames writhed as they rose from the logs, twisting upon themselves until they finally formed a soft smile./$", }, - + staff: { "1": "A $(l:items/staff)$(item)Staff/$ is my entry point into casting all _Hexes, large and small. By holding it and pressing $(thing)$(k:use)/$, I begin casting a _Hex; then I can click and drag to draw patterns.$(br2)It's little more than a chunk of _media on the end of a stick; that's all that's needed, after all.", "crafting.header": "Staves", "crafting.desc": "$(italic)Don't fight; flame, light; ignite; burn bright./$", }, - + lens: { "1": "_Media can have peculiar effects on any type of information, in specific circumstances. Coating a glass in a thin film of it can lead to ... elucidating insights.$(br2)By holding a $(l:items/lens)$(item)Scrying Lens/$ in my hand, certain blocks will display additional information when I look at them.", "2": "For example, looking at a piece of $(item)Redstone/$ will display its signal strength. I suspect I will discover other blocks with additional insight as my studies into my art progress.$(br2)In addition, holding it while casting using a $(l:items/staff)$(item)Staff/$ will shrink the spacing between dots, allowing me to draw more on my grid.$(br2)I can also wear it on my head as a strange sort of monocle.", "crafting.desc": "$(italic)You must learn... to see what you are looking at./$", }, - + thought_knot: { "1": "The forgetful often tie a piece of string about their finger to help them remember something important. I believe this idea might be of use in my art. A specially knotted piece of string should be able to hold a single iota stably, irregardless of my stack.$(br2)I will call my invention a $(item)Thought-Knot/$.", "2": "When I craft it, it stores no iota. Using $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ while holding a $(item)Thought-Knot/$ in my other hand will remove the top of the stack and save it into the $(item)Thought-Knot/$. Using $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$ will copy whatever iota's in the $(item)Thought-Knot/$ and add it to the stack.$(br2)Once a $(item)Thought-Knot/$ has been written to, the string is indelibly tangled; the iota can be read any number of times, but there is no way to erase or overwrite it. Fortunately, they are not expensive.", "3": "Also, if I store an entity in a $(item)Thought-Knot/$ and try to recall it after the referenced entity has died or otherwise disappeared, the $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$ will add $(l:casting/influences)$(thing)Null/$ to the stack instead.", "crafting.desc": "$(italic)How would you feel if someone saw you wearing a sign that said, \"I am dashing and handsome?\"/$", }, - + focus: { "1": "A $(item)Focus/$ is like a $(l:items/thought_knot)$(item)Thought-Knot/$, in that iota can be written to or read from it. However, the advantage of a focus is that it is $(italic)reusable/$. If I make a mistake in the iota I write to a $(item)Focus/$, I can simply cast $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ again and write over the iota inside.", "2": "If I wish to protect a $(l:items/focus)$(item)focus/$ from accidentally being overwritten, I can seal it with wax by crafting it with a $(item)Honeycomb/$. Attempting to use $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ on a sealed focus will fail.$(br2)$(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ will remove this seal along with the contents.", "3": "Indeed, the only advantage of my $(l:items/thought_knot)$(item)Thought-Knot/$s have over $(item)Foci/$ is that $(item)Foci/$ are more expensive to produce. My research indicates that the early practitioners of the art used exclusively $(item)Foci/$, with the $(l:items/thought_knot)$(item)Thought-Knot/$ being an original creation of mine.$(br2)Whoever those ancient people were, they must have been very prosperous.", "crafting.desc": "$(italic)Poison apples, poison worms./$", }, - + abacus: { "1": "Although there are $(l:patterns/numbers)$(action)patterns for drawing numbers/$, I find them ... cumbersome, to say the least.$(br2)Fortunately, the old masters of my craft invented an ingenious device called an $(l:items/abacus)$(item)Abacus/$ to provide numbers to my casting. I simply set the number to what I want, then read the value using $(l:patterns/readwrite#hexcasting:read)$(action)Scribe's Reflection/$, just like I would read a $(l:items/thought_knot)$(item)Thought-Knot/$ or $(l:items/focus)$(item)Focus/$.", - "2": "To operate one, I simply hold it, sneak, and scroll. If in my main hand, the number will increment or decrement by 1, or 10 if I am also holding Control/Command. If in my off hand, the number will increment or decrement by 0.1, or 0.001 if I am also holding Control/Command.$(br2)I can shake the abacus to reset it to zero by sneak-right-clicking.", + "2": "To operate one, I simply hold it, sneak, and scroll. If in my main hand, the number will increment or decrement by 1, or 10 if I am also holding $(k:sprint). If in my off hand, the number will increment or decrement by 0.1, or 0.001 if I am also holding $(k:sprint).$(br2)I can shake the abacus to reset it to zero by sneak-right-clicking.", "crafting.desc": "$(italic)Mathematics? That's for eggheads!/$", }, - + spellbook: { "1": "A $(l:items/spellbook)$(item)Spellbook/$ is the culmination of my art-- it acts like an entire library of $(l:items/focus)$(item)Foci/$. Up to $(thing)sixty-four/$ of them, to be exact.$(br2)Each page can hold a single iota, and I can select the active page (the page that iotas are saved to and copied from) by sneak-scrolling while holding it, or simply holding it in my off-hand and scrolling while casting a _Hex.", "2": "Like a $(l:items/focus)$(item)Focus/$, there exists a simple method to prevent accidental overwriting. Crafting it with a $(item)Honeycomb/$ will lacquer the current page, preventing $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$ from modifying its contents. Also like a $(l:items/focus)$(item)Focus/$, using $(l:patterns/spells/hexcasting#hexcasting:erase)$(action)Erase Item/$ will remove the lacquer along with the page's contents.$(br2)I can also name each page individually in an anvil. Naming it will change only the name of the currently selected page, for easy browsing.", "crafting.desc": "$(italic)Wizards love words. Most of them read a great deal, and indeed one strong sign of a potential wizard is the inability to get to sleep without reading something first.", }, - + scroll: { "1": "A $(l:items/scroll)$(item)Scroll/$ is a convenient method of sharing a pattern with others. I can copy a pattern onto one with $(l:patterns/readwrite#hexcasting:write)$(action)Scribe's Gambit/$, after which it will display in a tooltip.$(br2)I can also place them on the wall as decoration or edification, like a painting, in sizes from 1x1 to 3x3 blocks. Using $(l:items/amethyst)$(item)Amethyst Dust/$ on such a scroll will have it display the stroke order.", "2": "In addition, I can also find so-called $(l:items/scroll)$(item)Ancient Scrolls/$ in the dungeons and strongholds of the world. These contain the stroke order of $(thing)Great Spells/$, powerful magicks rumored to be too powerful for the hands and minds of mortals...$(br2)If those \"mortals\" couldn't cast them, I'm not sure they deserve to know them.", "crafting.desc": "$(italic)I write upon clean white parchment with a sharp quill and the blood of my students, divining their secrets./$", }, - + slate: { "1": "$(l:items/slate)$(item)Slates/$ are similar to $(l:items/scroll)$(item)Scrolls/$; I can copy a pattern to them and place them in the world to display the pattern.$(br2)However, I have read vague tales of grand assemblies of $(l:items/slate)$(item)Slates/$, used to cast $(l:greatwork/spellcircles)$(thing)great rituals/$ more powerful than can be handled by a $(l:items/staff)$(item)Staff/$.", "2": "Perhaps this knowledge will be revealed to me with time. But for now, I suppose they make a quaint piece of decor.$(br2)At the least, they can be placed on any side of a block, unlike $(l:items/scroll)$(item)Scrolls/$.", "crafting.desc": "$(italic)This is the letter \"a.\" Learn it./$", "3": "I'm also aware of other types of $(l:items/slate)$(item)Slates/$, slates that do not contain patterns but seem to be inlaid with other ... strange ... oddities. It hurts my brain to think about them, as if my thoughts get bent around their designs, following their pathways, bending and wefting through their labyrinthine depths, through and through and through channeled through and processed and--$(br2)... I almost lost myself. Maybe I should postpone my studies of those.", }, - + // roll credits hexcasting: { "1": "Although the flexibility of casting _Hexes \"on the go\" with my $(l:items/staff)$(item)Staff/$ is quite helpful, it's a huge pain to have to wave it around repeatedly just to accomplish a basic task. If I could save a common spell for later reuse, it would simplify things a lot-- and allow me to share my _Hexes with friends, too.", @@ -1411,57 +1424,57 @@ "5": "Each infusion spell requires an entity and a list of patterns on the stack. The entity must be a _media-holding item entity (i.e. $(l:items/amethyst)$(item)amethyst/$ crystals, dropped on the ground); the entity is consumed and forms the battery.$(br2)Usefully, it seems that the _media in the battery is not consumed in chunks as it is when casting with a $(l:items/staff)$(item)Staff/$-- rather, the _media \"melts down\" into one continuous pool. Thus, if I store a _Hex that only costs one $(l:items/amethyst)$(item)Amethyst Dust/$'s worth of media, a $(l:items/amethyst)$(item)Charged Crystal/$ used as the battery will allow me to cast it 10 times.", "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.", "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.", "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.", desc: "$(italic)Drink the milk./$", }, - + pigments: { "1": "The old practitioners of my art sometimes identified themselves by a color, emblematic of them and their _Hexes. Although their names have faded, their colors remain. It seems a special kind of pigment, offered to Nature in the right way, would \"[...] paint one's thoughts in a manner pleasing to Nature, inducing a miraculous change in personal colour.\"", "2": "I'm not certain on the specifics, but I believe I have isolated the formulae for many different colors and blends of pigments. To apply a pigment, I hold it in one hand and cast $(l:patterns/spells/colorize)$(action)Internalize Pigment/$ with the other; this consumes the pigment.$(br2)The pigments seem to affect the color of the sparks of _media emitted when I cast a _Hex and my $(l:patterns/spells/sentinels)$(thing)sentinel/$, but I don't doubt that the color will show up elsewhere.", - + "colored.crafting.header": "Chromatic Pigments", "colored.crafting.desc": "Pigments in all the colors of the rainbow.", - + special: "And finally, a pair of special pigments. $(item)Soulglimmer Pigment/$ shines with colors wholly unique to me, and $(item)Vacant Pigment/$ restores my original purplish-orange spread.$(br2)$(italic)And all the colors I am inside have not been invented yet./$", }, - + edified: { "1": "By infusing _media into a sapling via the use of $(l:patterns/spells/blockworks#hexcasting:edify)$(action)Edify Sapling/$, I can create what is called an $(l:items/edified)$(thing)Edified Tree/$. They tend to be tall and pointy, with ridged bark and wood that grows in a strange spiral pattern. Their leaves come in three pretty colors.", "2": "I would assume the wood would have some properties relevant to _Hexcasting. But, if it does, I cannot seem to find them. For all intents and purposes it appears to be just wood, albeit of a very strange color.$(br2)I suppose for now I will use it for decoration; the full suite of standard wood blocks can be crafted from them.$(br2)Of course, I can strip them with an axe as well.", "crafting.desc": "$(italic)Their smooth trunks, with white bark, gave the effect of enormous columns sustaining the weight of an immense foliage, full of shade and silence./$", }, - + jeweler_hammer: { "1": "After being careless with the sources of my _media one too many times, I have devised a tool to work around my clumsiness.$(br2)Using the delicate nature of crystallized _media as a fixture for a pickaxe, I can create the $(l:items/jeweler_hammer)$(item)Jeweler's Hammer/$. It acts like an $(item)Iron Pickaxe/$, for the most part, but can't break anything that takes up an entire block's space.", "crafting.desc": "$(italic)Carefully, she cracked the half ruby, letting the spren escape./$", }, - + decoration: { "1": "In the course of my studies I have discovered some building blocks and trifles that I may find aesthetically pleasing. I've compiled the methods of making them here.", "ancient_scroll.crafting.desc": "Brown dye works well enough to simulate the look of an $(l:items/scroll)$(item)ancient scroll/$.", "tiles.crafting.desc": "$(l:items/decoration)$(item)Amethyst Tiles/$ can also be made in a Stonecutter.$(br2)$(l:items/decoration)$(item)Blocks of Amethyst Dust/$ (next page) will fall like sand.", "sconce.crafting.desc": "$(l:items/decoration)$(item)Amethyst Sconces/$ emit light and particles, as well as a pleasing chiming sound.", }, - - + + // The Work the_work: { "1": "I have seen so many things. Unspeakable things. Innumerable things. I could write three words and turn my mind inside-out and smear my brains across the shadowed walls of my skull to decay into fluff and nothing.", "2": "I have seen staccato-needle patterns and acid-etched schematics written on the inside of my eyelids. They smolder there-- they dance, they taunt, they $(italic)ache/$. I'm possessed by an intense $(italic)need/$ to draw them, create them. Form them. Liberate them from the gluey shackles of my mortal mind-- present them in their Glory to the world for all to see.$(p)All shall see.$(p)All will see.", }, - + brainsweeping: { "1": "A secret was revealed to me. I saw it. I cannot forget its horror. The idea skitters across my brain.$(br2)I believed-- oh, foolishly, I $(italic)believed/$ --that _Media is the spare energy left over by thought. But now I $(italic)know/$ what it is: the energy $(italic)of/$ thought.", "2": "It is produced by thinking sentience and allows sentience to think. It is a knot tying that braids into its own string. The Entity I naively anthromorphized as Nature is simply a grand such tangle, or perhaps the set of all tangles, or ... if I think it hurts I have so many synapses and all of them can think pain at once ALL OF THEM CAN SEE$(br2)I am not holding on. My notes. Quickly.", "3": "The villagers of this world have enough consciousness left to be extracted. Place it into a block, warp it, change it. Intricate patterns caused by different patterns of thought, the abstract neural pathways of their jobs and lives mapped into the cold physic of solid atoms.$(br2)This is what $(l:patterns/great_spells/brainsweep)$(action)Flay Mind/$ does, the extraction. Target the villager entity and the destination block. Ten $(l:items/amethyst)$(item)Charged Amethyst/$ for this perversion of will.", budding_amethyst: "And an application. For this flaying, any sort of villager will do, if it has developed enough. Other recipes require more specific types. NO MORE must I descend into the hellish earth for my _media.", }, - + spellcircles: { "1": "I KNOW what the $(l:items/slate)$(item)slates/$ are for. The grand assemblies lost to time. The patterns scribed on them can be actuated in sequence, automatically. Thought and power ricocheting through, one by one by one by one by one by through and through and THROUGH AND -- I must not I must not I should know better than to think that way.", "2": "To start the ritual I need an $(l:greatwork/impetus)$(item)Impetus/$ to create a self-sustaining wave of _media. That wave travels along a track of $(l:items/slate)$(item)slates/$ or other blocks suitable for the energies, one by one, collecting any patterns it finds. Once the wave circles back around to the $(l:greatwork/impetus)$(item)Impetus/$, all the patterns encountered are cast in order.$(br2)The direction the _media exits any given block MUST be unambiguous, or the casting will fail at the block with too many neighbors.", @@ -1472,13 +1485,13 @@ "7": "I also found a sketch of a spell circle used by the ancients buried in my notes. Facing this page is my (admittedly poor) copy of it.$(br2)The patterns there would have been executed counter-clockwise, starting with $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$ and ending with $(l:patterns/great_spells/teleport#hexcasting:teleport/great)$(action)Greater Teleport/$.", "teleport_circle.title": "Teleportation Circle", }, - + impetus: { "1": "The fluctuation of _media required to actuate a spell circle is complex. Even the mortal with sharpest eyes and steadiest hands could not serve as an $(l:greatwork/impetus)$(item)Impetus/$ and weave _media into the self-sustaining oroboros required.$(br2)The problem is that the mind is too full of other useless $(italics)garbage/$.", "2": "At a ... metaphysical level-- I must be careful with these thoughts, I cannot lose myself, I have become too valuable --moving _media moves the mind, and the mind must be moved for the process to work. But, the mind is simply too $(italic)heavy/$ with other thoughts to move nimbly enough.$(br2)It is like an artisan trying to repair a watch while wearing mittens.", "3": "There are several solutions to this conundrum: through meditative techniques one can learn to blank the mind, although I am not certain a mind free enough to actuate a circle can concentrate hard enough to do the motions.$(br2)Certain unsavory compounds can create a similar effect, but I know nothing of them and do not plan to learn. I must not rely on the chemicals of my brain.", "4": "The solution I aim for, then, is to specialize a mind. Remove it from the tyranny of nerves, clip all outputs but delicate splays of _media-manipulating apparati, cauterize all inputs but the signal to start its work.$(br2)The process of $(l:greatwork/brainsweeping)$(action)mindflaying/$ I am now familiar with will do excellently; the mind of a villager is complex enough to do the work, but not so complex as to resist its reformation.", - + empty_impetus: "First, the cradle. Although it does not work as an $(l:greatwork/impetus)$(item)Impetus/$, the flow of _media in a circle will only exit out the side pointed to by the arrows. This allows me to change the plane in which the wave flows, for example.", impetus_rightclick: "Then, to transpose the mind. Villagers of different professions will lend different actuation conditions to the resulting $(l:greatwork/impetus)$(item)Impetus/$. A $(l:greatwork/impetus)$(item)Toolsmith Impetus/$ activates on a simple $(k:use).", impetus_storedplayer: { @@ -1487,22 +1500,22 @@ }, impetus_look: "A $(l:greatwork/impetus)$(item)Fletcher Impetus/$ activates when looked at for a short time.", }, - + directrix: { "1": "Simpler than the task of creating a self-sustaining wave of _media is the task of directing it. Ordinarily the wave disintegrates when coming upon a crossroads, but with a mind to guide it, an exit direction can be controlled.$(br2)This manipulation is not nearly so fine as the delicacy of actuating a spell circle. In fact, it might be possible to do it by hand... but the packaged minds I have access to now would be so very convenient.", "2": "A $(l:greatwork/directrix)$(item)Directrix/$ accepts a wave of _media and determines to which of the arrows it will exit from, depending on the villager mind inside.$(br2)I am not certain if this idea was bestowed upon me, or if my mind is bent around the barrier enough to splint off its own ideas now... but if the idea came from my own mind, if I thought it, can it be said it was bestowed? The brain is a vessel for the mind and the mind is a vessel for ideas and the ideas vessel thought and thought sees all and knows all-- I MUST N O T", - + empty_directrix: "Firstly, a design for the cradle ... although, perhaps \"substrate\" would be more accurate a word. Without a mind guiding it, the output direction is determined by microscopic fluctuations in the _media wave and surroundings, making it effectively random.", directrix_redstone: "A $(l:greatwork/directrix)$(item)Mason Directrix/$ switches output side based on a redstone signal. Without a signal, the exit is the _media-color side; with a signal, the exit is the redstone-color side.", }, - + akashiclib: { "1": "I KNOW SO MUCH it is ONLY RIGHT to have a place to store it all. Information can be stored in books but it is oh so so so so $(italic)slow/$ to write by hand and read by eye. I demand BETTER. And so I shall MAKE better.$(br2)... I am getting worse ... do not know if I have time to write everything bursting through my head before expiring.", "2": "The library. Here. My plans.$(br2)Like how patterns are associated with actions, I can associate my own patterns with iotas in any way I choose. An $(l:greatwork/akashiclib)$(item)Akashic Record/$ controls the library, and each $(l:greatwork/akashiclib)$(item)Akashic Bookshelf/$ stores one pattern mapped to one iota. These must all be directly connected together, touching, within 32 blocks. An $(l:greatwork/akashiclib)$(item)Akashic Ligature/$ doesn't do anything but count as a connecting block, to extend the size of my library.", akashic_record: "Allocating and assigning patterns is simple but oh so boring. I have better things to do. I will need a mind well-used to its work for the extraction to stay sound.", "3": "Then to operate the library is simple, the patterns are routed through the librarian and it looks them up and returns the iota to you. Two actions do the work. $(l:patterns/akashic_patterns)Notes here/$.$(br2)Using an empty $(l:items/scroll)$(item)scroll/$ on a bookshelf copies the pattern there onto the $(l:items/scroll)$(item)scroll/$. Sneaking and using an empty hand clears the datum in the shelf.", }, - + quenching_allays: { "1": "THEY ARE BITS OF MEDIA. How did I not see it sooner? They are -- as I am a heap of flesh with a scrap, blessed with a scrap of thought, an Allay is a self-sustaining quarrel of media pinned to a scrap of flesh. It explains everything -- their propensity for media, their response to music, I SEE NOW, HOW did the ones before NOT?", "2": "And given this it is only RIGHT I conquer their peculiar minds -- their peculiar selves -- that is all they are, a mind, a self, a coda. Something about their phase speaks to me. I can... I can compress _media with them, overlay two wends of thought in one space, physical and cognitive, all and once.$(br2)Somehow, the process produces _media of its own. How? Perhaps -- perhaps MY work, the process of doing it --", @@ -1510,19 +1523,19 @@ "4": "The product is fragile. Breaking it shatters it into pieces, with $(thing)Fortune/$ increasing the yield... if I wish the block itself I need a silken touch.$(br2)The produced shards are worth thrice an $(l:items/amethyst)$(item)Charged Amethyst Crystal/$ apiece. The block itself is worth four of the shards.", "5": "They are mercurial, they seem to twist and wink under my fingers, and by giving them a mentor in another form of _media they may be coerced into its shape, in an equivalent exchange of _media.", }, - - + + "fanciful_staves.1": "It is only right as I shed the husk of ignorance I replace my tools, my palm-polished staves. These new constructions of mine have no additional properties -- but they are so glorious, oh so Glorious... They match the radiance winking at the corners of my sight.", // Patterns - + readers_guide: { "1": "I've divided all the valid patterns I've found into sections based on what they do, more or less. I've written down the stroke order of the patterns as well, if I managed to find it in my studies, with the start of the pattern marked with a red dot.$(br2)If an action is cast by multiple patterns, as is the case with some, I'll write them all side-by-side.", "2": "For a few patterns, however, I was $(italic)not/$ able to find the stroke order, just the shape. I suspect the order to draw them in are out there, locked away in the ancient libraries and dungeons of the world.$(br2)In such cases I just draw the pattern without any information on the order to draw it in.", "3": "I also write the types of iota that the action will consume or modify, a \"\u2192\", and the types of iota the action will create.$(p)For example, \"$(n)vector, number/$ \u2192 $(n)vector/$\" means the action will remove a vector and a number from the top of the stack, and then add a vector; or, put another way, will remove a number from the stack, and then modify the vector at the top of the stack. (The number needs to be on the top of the stack, with the vector right below it.)", "4": "\"\u2192 $(n)entity/$\" means it'll just push an entity. \"$(n)entity, vector/$ \u2192\" means it removes an entity and a vector, and doesn't push anything.$(br2)Finally, if I find the little dot marking the stroke order too slow or confusing, I can press $(thing)Control/Command/$ to display a gradient, where the start of the pattern is darkest and the end is lightest. This works on scrolls and when casting, too!", }, - + basics_pattern: { get_caster: "Adds me, the caster, to the stack.", "entity_pos/eye": "Transforms an entity on the stack into the position of its eyes. I should probably use this on myself.", @@ -1541,47 +1554,47 @@ get_entity_height: "Transforms an entity on the stack into its height.", get_entity_velocity: "Transforms an entity on the stack into the direction in which it's moving, with the speed of that movement as that direction's magnitude.", }, - + numbers: { "1": "Irritatingly, there is no easy way to draw numbers. Here is the method Nature deigned to give us.", "2": "First, I draw one of the two shapes shown on the other page. Next, the $(italic)angles/$ following will modify a running count starting at 0.$(li)Forward: Add 1$(li)Left: Add 5$(li)Right: Add 10$(li)Sharp Left: Multiply by 2$(li)Sharp Right: Divide by 2.$(br)The clockwise version of the pattern, on the right of the other page, will negate the value at the very end. (The left-hand counter-clockwise version keeps the number positive).$(p)Once I finish drawing, the number's pushed to the top of the stack.", example: { "10.header": "Example 1", "10": "This pattern pushes 10.", - + "7.header": "Example 2", "7": "This pattern pushes 7: 5 + 1 + 1.", - + "-32.header": "Example 3", "-32": "This pattern pushes -32: negate 1 + 5 + 10 * 2.", - + "4.5.header": "Example 4", "4.5": "This pattern pushes 4.5: 5 / 2 + 1 + 1.", }, "3": "In certain cases it might be easier to just use an $(l:items/abacus)$(item)Abacus/$. But, it's worth knowing the \"proper\" way to do things.", }, - + math: { numvec: "Many mathematical operations function on both numbers and vectors. Such arguments are written as \"num|vec\".", - + "add.1": "Perform addition.", "add.2": "As such:$(li)With two numbers at the top of the stack, combines them into their sum.$(li)With a number and a vector, removes the number from the stack and adds it to each element of the vector.$(li)With two vectors, combines them by summing corresponding components into a new vector (i.e. [1, 2, 3] + [0, 4, -1] = [1, 6, 2]).", - + "sub.1": "Perform subtraction.", "sub.2": "As such:$(li)With two numbers at the top of the stack, combines them into their difference.$(li)With a number and a vector, removes the number from the stack and subtracts it from each element of the vector.$(li)With two vectors, combines them by subtracting each component.$(br2)In all cases, the top of the stack or its components are subtracted $(italic)from/$ the second-from-the-top.", - + "mul.1": "Perform multiplication or the dot product.", "mul.2": "As such:$(li)With two numbers, combines them into their product.$(li)With a number and a vector, removes the number from the stack and multiplies each component of the vector by that number.$(li)With two vectors, combines them into their $(l:https://www.mathsisfun.com/algebra/vectors-dot-product.html)dot product/$.", - + "div.1": "Perform division or the cross product.", "div.2": "As such:$(li)With two numbers, combines them into their quotient.$(li)With a number and a vector, removes the number and divides it by each element of the vector.$(li)With two vectors, combines them into their $(l:https://www.mathsisfun.com/algebra/vectors-cross-product.html)cross product/$.$(br2)In the first and second cases, the top of the stack or its components comprise the dividend, and the second-from-the-top or its components are the divisor.$(p)WARNING: Never divide by zero!", - + "abs.1": "Compute the absolute value or length.", "abs.2": "Replaces a number with its absolute value, or a vector with its length.", - + "pow.1": "Perform exponentiation or vector projection.", "pow.2": "With two numbers, combines them by raising the first to the power of the second.$(li)With a number and a vector, removes the number and raises each component of the vector to the number's power.$(li)With two vectors, combines them into the $(l:https://en.wikipedia.org/wiki/Vector_projection)vector projection/$ of the top of the stack onto the second-from-the-top.$(br2)In the first and second cases, the first argument or its components are the base, and the second argument or its components are the exponent.", - + floor: "\"Floors\" a number, cutting off the fractional component and leaving an integer value. If passed a vector, instead floors each of its components.", ceil: "\"Ceilings\" a number, raising it to the next integer value if it has a fractional component. If passed a vector, instead ceils each of its components.", construct_vec: "Combine three numbers at the top of the stack into a vector's X, Y, and Z components (top to bottom).", @@ -1590,7 +1603,7 @@ coerce_axial: "For a vector, coerce it to its nearest axial direction, a unit vector. For a number, return the sign of the number; 1 if positive, -1 if negative. In both cases, zero is unaffected.", random: "Creates a random number between 0 and 1.", }, - + advanced_math: { sin: "Takes the sine of an angle in radians, yielding the vertical component of that angle drawn on a unit circle. Related to the values of $(l:patterns/consts#hexcasting:const/double/pi)$(thing)π/$ and $(l:patterns/consts#hexcasting:const/double/tau)$(thing)τ/$.", cos: "Takes the cosine of an angle in radians, yielding the horizontal component of that angle drawn on a unit circle. Related to the values of $(l:patterns/consts#hexcasting:const/double/pi)$(thing)π/$ and $(l:patterns/consts#hexcasting:const/double/tau)$(thing)τ/$.", @@ -1601,46 +1614,46 @@ arctan2: "Takes the inverse tangent of a Y and X value, yielding the angle between the X-axis and a line from the origin to that point.", logarithm: "Removes the number at the top of the stack, then takes the logarithm of the number at the top using the other number as its base. Related to the value of $(l:patterns/consts#hexcasting:const/double/e)$(thing)$(italic)e/$.", }, - + sets: { numlist: "Set operations are odd, in that some of them can accept two numbers or two lists, but not a combination thereof. Such arguments will be written as \"(num, num)|(list, list)\".$(br2)When numbers are used in those operations, they are being used as so-called binary \"bitsets\", lists of 1 and 0, true and false, \"on\" and \"off\".", - + "or.1": "Unifies two sets.", "or.2": "As such:$(li)With two numbers at the top of the stack, combines them into a bitset containing every \"on\" bit in either bitset.$(li)With two lists, this creates a list of every element from the first list, plus every element from the second list that is not in the first list. This is similar to $(l:patterns/lists#hexcasting:add)$(action)Combination Distillation/$.", - + "and.1": "Takes the intersection of two sets.", "and.2": "As such:$(li)With two numbers at the top of the stack, combines them into a bitset containing every \"on\" bit present in $(italics)both/$ bitsets.$(li)With two lists, this creates a list of every element from the first list that is also in the second list.", - + "xor.1": "Takes the exclusive disjunction of two sets.", "xor.2": "As such:$(li)With two numbers at the top of the stack, combines them into a bitset containing every \"on\" bit present in $(italics)exactly one/$ of the bitsets.$(li)With two lists, this creates a list of every element in both lists that is $(italics)not/$ in the other list.", - + not: "Takes the inversion of a bitset, changing all \"on\" bits to \"off\" and vice versa. In my experience, this will take the form of that number negated and decreased by one. For example, 0 will become -1, and -100 will become 99.", to_set: "Removes duplicate entries from a list.", }, - + "consts.const/": { "null": "Adds the $(l:casting/influences)$(thing)Null/$ influence to the top of the stack.", "true": "Adds $(thing)True/$ to the top of the stack.", "false": "Adds $(thing)False/$ to the top of the stack.", - + "vec/": { x: "The left-hand counter-clockwise pattern adds [1, 0, 0] to the stack; the right-hand clockwise pattern adds [-1, 0, 0].", y: "The left-hand counter-clockwise pattern adds [0, 1, 0] to the stack; the right-hand clockwise pattern adds [0, -1, 0].", z: "The left-hand counter-clockwise pattern adds [0, 0, 1]; the right-hand clockwise pattern adds [0, 0, -1].", "0": "Adds [0, 0, 0] to the stack.", }, - + "double/": { tau: "Adds τ, the radial representation of a complete circle, to the stack.", pi: "Adds π, the radial representation of half a circle, to the stack.", "e": "Adds $(italic)e/$, the base of natural logarithms, to the stack.", }, }, - + stackmanip: { "pseudo-novice.title": "Novice's Gambit", "pseudo-novice": "Removes the first iota from the stack.$(br2)This seems to be a special case of $(l:patterns/stackmanip#hexcasting:mask)$(action)Bookkeeper's Gambit/$.", - + swap: "Swaps the top two iotas of the stack.", rotate: "Yanks the iota third from the top of the stack to the top. [0, 1, 2] becomes [1, 2, 0].", rotate_reverse: "Yanks the top iota to the third position. [0, 1, 2] becomes [2, 0, 1].", @@ -1652,19 +1665,19 @@ duplicate_n: "Removes the number at the top of the stack, then copies the top iota of the stack that number of times. (A count of 2 results in two of the iota on the stack, not three.)", fisherman: "Grabs the element in the stack indexed by the number and brings it to the top. If the number is negative, instead moves the top element of the stack down that many elements.", "fisherman/copy": "Like $(l:patterns/stackmanip#hexcasting:fisherman)$(action)Fisherman's Gambit/$, but instead of moving the iota, copies it.", - + mask: { "1": "An infinite family of actions that keep or remove elements at the top of the stack based on the sequence of dips and lines.", "2": "Assuming that I draw a Bookkeeper's Gambit pattern left-to-right, the number of iotas the action will require is determined by the horizontal distance covered by the pattern. From deepest in the stack to shallowest, a flat line will keep the iota, whereas a triangle dipping down will remove it.$(br2)If my stack contains $(italic)0, 1, 2/$ from deepest to shallowest, drawing the first pattern opposite will give me $(italic)1/$, the second will give me $(italic)0/$, and the third will give me $(italic)0, 2/$ (the 0 at the bottom is left untouched).", }, - + swizzle: { "1": "Rearranges the top elements of the stack based on the given numerical code, which is the index of the permutation wanted.", "2": "Although I can't pretend to know the mathematics behind calculating this permutation code, I have managed to dig up an extensive chart of them, enumerating all permutations of up to six elements.$(br2)If I wish to do further study, the key word is \"Lehmer Code.\"", link: "Table of Codes", }, }, - + logic: { bool_coerce: "Convert an argument to a boolean. The number $(thing)0/$, $(l:casting/influences)$(thing)Null/$, and the empty list become False; everything else becomes True.", bool_to_number: "Convert a boolean to a number; True becomes $(thing)1/$, and False becomes $(thing)0/$.", @@ -1680,7 +1693,7 @@ greater_eq: "If the first argument is greater than or equal to the second, return True. Otherwise, return False.", less_eq: "If the first argument is less than or equal to the second, return True. Otherwise, return False.", }, - + entities: { get_entity: "Transform the position on the stack into the entity at that location (or $(l:casting/influences)$(thing)Null/$ if there isn't one).", "get_entity/": { @@ -1690,7 +1703,7 @@ player: "Transform the position on the stack into the player at that location (or $(l:casting/influences)$(thing)Null/$ if there isn't one).", living: "Transform the position on the stack into the living creature at that location (or $(l:casting/influences)$(thing)Null/$ if there isn't one).", }, - + zone_entity: "Take a position and maximum distance on the stack, and combine them into a list of all entities near the position.", "zone_entity/": { animal: "Take a position and maximum distance on the stack, and combine them into a list of animals near the position.", @@ -1705,7 +1718,7 @@ not_living: "Take a position and maximum distance on the stack, and combine them into a list of non-living entities near the position.", }, }, - + lists: { index: "Remove the number at the top of the stack, then replace the list at the top with the nth element of that list (where n is the number you removed). Replaces the list with $(l:casting/influences)$(thing)Null/$ if the number is out of bounds.", slice: "Remove the two numbers at the top of the stack, then take a sublist of the list at the top of the stack between those indices, lower bound inclusive, upper bound exclusive. For example, the 0, 2 sublist of [0, 1, 2, 3, 4] would be [0, 1].", @@ -1724,7 +1737,7 @@ construct: "Remove the top iota, then add it as the first element to the list at the top of the stack.", deconstruct: "Remove the first iota from the list at the top of the stack, then push that iota to the stack.", }, - + patterns_as_iotas: { "1": "One of the many peculiarities of this art is that $(italic)patterns themselves/$ can act as iotas-- I can even put them onto my stack when casting.$(br2)This raises a fairly obvious question: how do I express them? If I simply drew a pattern, it would hardly tell Nature to add it to my stack-- rather, it would simply be matched to an action.", "2": "Fortunately, Nature has provided me with a set of $(l:casting/influences)influences/$ that I can use to work with patterns directly.$(br2)In short, $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ lets me add one pattern to the stack, and $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Introspection/$ and $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ let me add a whole list.", @@ -1739,7 +1752,7 @@ }, undo: "Finally, if I make a mistake while drawning patterns inside $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)Intro-/$ and $(l:patterns/patterns_as_iotas#hexcasting:close_paren)$(action)Retrospection/$ I can draw $(l:patterns/patterns_as_iotas#hexcasting:undo)$(action)Evanition/$ to remove the last pattern that I drew from the pattern list that is being constructed.", }, - + readwrite: { "1": "This section deals with the storage of $(thing)Iotas/$ in a more permanent medium. Nearly any iota can be stored to a suitable item, such as a $(l:items/focus)$(item)Focus/$ or $(l:items/spellbook)$(item)Spellbook/$), and read back later. Certain items, such as an $(l:items/abacus)$(item)Abacus/$, can only be read from.$(br2)Iotas are usually read and written from the other hand, but it is also possible to read and write with an item when it is sitting on the ground as an item entity, or when in an item frame.", "2": "There may be other entities I can interact with in this way. For example, a $(l:items/scroll)$(item)Scroll/$ hung on the wall can have its pattern read off of it.$(br2)However, it seems I am unable to save a reference to another player, only me. I suppose an entity reference is similar to the idea of a True Name; perhaps Nature is helping to keep our Names out of the hands of enemies. If I want a friend to have my Name I can make a $(l:items/focus)$(item)Focus/$ for them.", @@ -1756,35 +1769,37 @@ "write/local": "Removes the top iota from the stack, and saves it to my $(l:patterns/readwrite#hexcasting:local)$(thing)ravenmind/$, storing it there until I stop casting the _Hex.", "read/local": "Copy the iota out of my $(l:patterns/readwrite#hexcasting:local)$(thing)ravenmind/$, which I likely just wrote with $(l:patterns/readwrite#hexcasting:write/local)$(action)Huginn's Gambit/$.", }, - + meta: { "eval.1": "Remove a pattern or list of patterns from the stack, then cast them as if I had drawn them myself with my $(l:items/staff)$(item)Staff/$ (until a $(l:patterns/meta#hexcasting:halt)$(action)Charon's Gambit/$ is encountered). If an iota is escaped with $(l:patterns/patterns_as_iotas#hexcasting:escape)$(action)Consideration/$ or $(l:patterns/patterns_as_iotas#hexcasting:open_paren)$(action)its ilk/$, it will be pushed to the stack. Otherwise, non-patterns will fail.", "eval.2": "This can be $(italic)very/$ powerful in tandem with $(l:items/focus)$(item)Foci/$.$(br2)It also makes the bureaucracy of Nature a \"Turing-complete\" system, according to one esoteric scroll I found.$(br2)However, it seems there's a limit to how many times a _Hex can cast itself-- Nature doesn't look kindly on runaway spells!$(br2)In addition, with the energies of the patterns occurring without me to guide them, any mishap will cause the remaining actions to become too unstable and immediately unravel.", - + "for_each.1": "Remove a list of patterns and a list from the stack, then cast the given pattern over each element of the second list.", "for_each.2": "More specifically, for each element in the second list, it will:$(li)Create a new stack, with everything on the current stack plus that element$(li)Draw all the patterns in the first list$(li)Save all the iotas remaining on the stack to a list$(br)Then, after all is said and done, pushes the list of saved iotas onto the main stack.$(br2)No wonder all the practitioners of this art go mad.", - + "halt.1": "This pattern forcibly halts a _Hex. This is mostly useless on its own, as I could simply just stop writing patterns, or put down my staff.", "halt.2": "But when combined with $(l:patterns/meta#hexcasting:eval)$(action)Hermes'/$ or $(l:patterns/meta#hexcasting:for_each)$(action)Thoth's Gambits/$, it becomes $(italics)far/$ more interesting. Those patterns serve to 'contain' that halting, and rather than ending the entire _Hex, those gambits end instead. This can be used to cause $(l:patterns/meta#hexcasting:for_each)$(action)Thoth's Gambit/$ not to operate on every iota it's given. An escape from the madness, as it were.", - + "eval/cc.1": "Cast a pattern or list of patterns from the stack exactly like $(l:patterns/meta#hexcasting:eval)$(action)Hermes' Gambit/$, except that a unique \"Jump\" iota is pushed to the stack beforehand. ", "eval/cc.2": "When the \"Jump\"-iota is executed, it'll skip the rest of the patterns and jump directly to the end of the pattern list.$(p)While this may seem redundant given $(l:patterns/meta#hexcasting:halt)$(action)Charon's Gambit/$ exists, this allows you to exit $(italic)nested/$ $(l:patterns/meta#hexcasting:eval)$(action)Hermes'/$ invocations in a controlled way, where Charon only allows you to exit one.$(p)The \"Jump\" iota will apparently stay on the stack even after execution is finished... better not think about the implications of that.", + + "thanatos.1": "Adds the number of patterns a _Hex is still capable of evaluating to the stack. This is reduced by one for each pattern cast by the _Hex." }, - + circle_patterns: { disclaimer: "These patterns must be cast from a $(l:greatwork/spellcircles)$(item)Spell Circle/$; trying to cast them through a $(l:items/staff)$(item)Staff/$ will fail rather spectacularly.", - + "circle/impetus_pos": "Returns the position of the $(l:greatwork/impetus)$(item)Impetus/$ of this spell circle.", "circle/impetus_dir": "Returns the direction the $(l:greatwork/impetus)$(item)Impetus/$ of this spell circle is facing as a unit vector.", "circle/bounds/min": "Returns the position of the lower-north-west corner of the bounds of this spell circle.", "circle/bounds/max": "Returns the position of the upper-south-east corner of the bounds of this spell circle.", }, - + akashic_patterns: { "akashic/read": "Read the iota associated with the given pattern out of the $(l:greatwork/akashiclib)$(item)Akashic Library/$ with its $(l:greatwork/akashiclib)$(item)Record/$ at the given position. This has no range limit. Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.", "akashic/write": "Associate the iota with the given pattern in the $(l:greatwork/akashiclib)$(item)Akashic Library/$ with its $(l:greatwork/akashiclib)$(item)Record/$ at the given position. This $(italic)does/$ have a range limit. Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.", }, - + // Normal Spells itempicking: { @@ -1792,24 +1807,24 @@ "2": "More specifically:$(li)First, the spell will search for the first valid item in my hotbar to the $(italic)right of my $(l:items/staff)$(item)staff/$, wrapping around at the right-hand side, and starting at the first slot if my $(l:items/staff)$(item)staff/$ is in my off-hand.$(li)Second, the spell will draw that item from as $(italic)far back in my inventory/$ as possible, prioritizing the main inventory over the hotbar.", "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.", }, - + basic_spell: { "explode.1": "Remove a number and vector from the stack, then create an explosion at the given location with the given power.", "explode.2": "A power of 3 is about as much as a Creeper's blast; 4 is about as much as a TNT blast. Nature refuses to give me a blast of more than 10 power, though.$(br2)Strangely, this explosion doesn't seem to harm me. Perhaps it's because $(italic)I/$ am the one exploding?$(br2)Costs a negligible amount at power 0, plus 3 extra $(l:items/amethyst)$(item)Amethyst Dust/$ per point of explosion power.", - + "explode.fire.1": "Remove a number and vector from the stack, then create a fiery explosion at the given location with the given power.", "explode.fire.2": "Costs one $(l:items/amethyst)$(item)Amethyst Dust/$, plus about 3 extra $(l:items/amethyst)$(item)Amethyst Dust/$s per point of explosion power. Otherwise, the same as $(l:patterns/spells/basic#hexcasting:explode)$(action)Explosion/$, except with fire.", - + add_motion: "Remove an entity and direction from the stack, then give a shove to the given entity in the given direction. The strength of the impulse is determined by the length of the vector.$(br)Costs units of $(l:items/amethyst)$(item)Amethyst Dust/$ equal to the square of the length of the vector, plus one for every Impulse except the first targeting an entity.", blink: "Remove an entity and length from the stack, then teleport the given entity along its look vector by the given length.$(br)Costs about one $(l:items/amethyst)$(item)Amethyst Shard/$ per two blocks travelled.", - + "beep.1": "Remove a vector and two numbers from the stack. Plays an $(thing)instrument/$ defined by the first number at the given location, with a $(thing)note/$ defined by the second number. Costs a negligible amount of _media.", "beep.2": "There appear to be 16 different $(thing)instruments/$ and 25 different $(thing)notes/$. Both are indexed by zero.$(br2)These seem to be the same instruments I can produce with a $(item)Note Block/$, though the reason for each instrument's number being what it is eludes me.$(br2)Either way, I can find the numbers I need to use by inspecting a $(item)Note Block/$ through a $(l:items/lens)$(item)Scrying Lens/$.", }, - + blockworks: { place_block: "Remove a location from the stack, then pick a block item and place it at the given location.$(br)Costs about an eighth of one $(l:items/amethyst)$(item)Amethyst Dust/$.", - break_block: "Remove a location from the stack, then break the block at the given location. This spell can break nearly anything a Diamond Pickaxe can break.$(br)Costs about an eighth of one $(l:items/amethyst)$(item)Amethyst Dust/$.", + break_block: "Remove a location from the stack, then break the block at the given location. This spell can break nearly anything a Diamond Pickaxe can break.$(br)Costs about an eighth of one $(l:items/amethyst)$(item)Amethyst Dust, or a negligible amount if breaking a $(l:patterns/spells/blockworks#hexcasting:conjure_block)$(action)Conjured Block/$ or $(l:patterns/spells/blockworks#hexcasting:conjure_light)$(action)Conjured Light/$.", create_water: "Summon a block of water (or insert up to a bucket's worth) into a block at the given position. Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.", destroy_water: "Drains either a liquid container at, or a body of liquid around, the given position. Costs about two $(l:items/amethyst)$(item)Charged Amethyst/$.", conjure_block: "Conjure an ethereal, but solid, block that sparkles with my pigment at the given position. Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.", @@ -1819,98 +1834,98 @@ ignite: "Start a fire on top of the given location, as if a $(item)Fire Charge/$ was applied. Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.", extinguish: "Extinguish blocks in a large area. Costs about six $(l:items/amethyst)$(item)Amethyst Dust/$.", }, - + nadirs: { "1": "This family of spells all impart a negative potion effect upon an entity. They all take an entity, the recipient, and one or two numbers, the first being the duration and the second, if present, being the potency (starting at 1).$(br2)Each one has a \"base cost;\" the actual cost is equal to that base cost, multiplied by the potency squared.", "2": "According to certain legends, these spells and their sisters, the $(l:patterns/great_spells/zeniths)$(action)Zeniths/$, were \"[...] inspired by a world near to this one, where powerful wizards would gather magic from the land and hold duels to the death. Unfortunately, much was lost in translation...\"$(br2)Perhaps that is the reason for their peculiar names.", - + "potion/weakness": "Inflicts $(thing)weakness/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per 10 seconds.", "potion/levitation": "Inflicts $(thing)levitation/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per 5 seconds.", "potion/wither": "Inflicts $(thing)withering/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per second.", "potion/poison": "Inflicts $(thing)poison/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per 3 seconds.", "potion/slowness": "Inflicts $(thing)slowness/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per 5 seconds.", }, - + hexcasting_spell: { basics: "These three spells each create an $(l:items/hexcasting)$(thing)item that casts a _Hex./$$(br)They all require me to hold the empty item in my off-hand, and require two things: the list of patterns to be cast, and an entity representing a dropped stack of $(l:items/amethyst)$(item)Amethyst/$ to form the item's battery.$(br2)See $(l:items/hexcasting)this entry/$ for more information.", "craft/cypher": "Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$.", "craft/trinket": "Costs about five $(l:items/amethyst)$(item)Charged Amethysts/$.", "craft/artifact": "Costs about ten $(l:items/amethyst)$(item)Charged Amethysts/$.", - + "recharge.1": "Recharge a _media-containing item in my other hand. Costs about one $(l:items/amethyst)$(item)Amethyst Shard/$.", "recharge.2": "This spell is cast in a similar method to the crafting spells; an entity representing a dropped stack of $(l:items/amethyst)$(item)Amethyst/$ is provided, and recharges the _media battery of the item in my other hand.$(br2)This spell $(italic)cannot/$ recharge the item farther than its original battery size.", - + "erase.1": "Clear a _Hex-containing item in my other hand. Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.", "erase.2": "The spell will also void all the _media stored inside the item, releasing it back to Nature and returning the item to a perfectly clean slate. This way, I can re-use $(l:items/hexcasting)$(item)Trinkets/$ I have put an erroneous spell into, for example.$(br2)This also works to clear a $(l:items/focus)$(item)Focus/$ or $(l:items/spellbook)$(item)Spellbook/$ page, unsealing them in the process.", }, - + sentinels: { "1": "$(italic)Hence, away! Now all is well,$(br)One aloof stand sentinel./$$(br2)A $(l:patterns/spells/sentinels)$(thing)Sentinel/$ is a mysterious force I can summon to assist in the casting of _Hexes, like a familiar or guardian spirit. It appears as a spinning geometric shape to my eyes, but is invisible to everyone else.", "2": "It has several interesting properties:$(li)It does not appear to be tangible; no one can touch it.$(li)Only my _Hexes can interact with it.$(li)Once summoned, it stays in place until banished.$(li)I am always able to see it if I'm close enough, even through solid objects.", - + "sentinel/create": "Summons my $(l:patterns/spells/sentinels)$(thing)sentinel/$ at the given position. Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.", "sentinel/destroy": "Banish my $(l:patterns/spells/sentinels)$(thing)sentinel/$, and remove it from the world. Costs a negligible amount of _media.", "sentinel/get_pos": "Add the position of my $(l:patterns/spells/sentinels)$(thing)sentinel/$ to the stack, or $(l:casting/influences)$(thing)Null/$ if it isn't summoned. Costs a negligible amount of _media.", "sentinel/wayfind": "Transform the position vector on the top of the stack into a unit vector pointing from that position to my $(l:patterns/spells/sentinels)$(thing)sentinel/$, or $(l:casting/influences)$(thing)Null/$ if it isn't summoned. Costs a negligible amount of _media.", }, - + colorize: "I must be holding a $(l:items/pigments)$(item)Pigment/$ in my other hand to cast this spell. When I do, it will consume the dye and permanently change my mind's coloration (at least, until I cast the spell again). Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.", flights: { "1": "Although it seems that true, limitless flight is out of my grasp, I have nonetheless found some methods of holding one in the sky, each with their respective drawbacks.$(br2)All forms produce a shimmer of excess _media; as the spell gets closer to ending, the sparks are shot through with more red and black.", "2": "Other forms of flight do exist, of course. For example, a combination of $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ and $(l:patterns/spells/nadirs#hexcasting:potion/levitation)$(action)Blue Sun's Nadir/$ has been used since antiquity for a flight of sorts.$(br2)I've also heard tell of a thin membrane worn on the back that allows the ability to glide. From my research, I believe the Great spell $(l:patterns/great_spells/altiora)$(action)Altiora/$ may be used to mimic it.", - + "range.1": "A flight limited in its range.", "range.2": "The second argument is a horizontal radius, in meters, in which the spell is stable. Moving outside of that radius will end the spell, dropping me out of the sky. As long as I stay inside the safe zone, however, the spell lasts indefinitely. An additional shimmer of _media marks the origin point of the safe zone. $(br2)Costs about 1 $(l:items/amethyst)$(item)Amethyst Dust/$ per meter of safety.", - + "time.1": "A flight limited in its duration.", "time.2": "The second argument is an amount of time in seconds for which the spell is stable. After that time, the spell ends and I am dropped from the sky. $(br2)It is relatively expensive at about 1 $(l:items/amethyst)$(item)Charged Crystal/$ per second of flight; I believe it is best suited for travel.", }, - + create_lava: { "1": "Summon a block of lava (or insert up to a bucket's worth) into a block at the given position. Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$.", "2": "It may be advisable to keep my knowledge of this spell secret. A certain faction of botanists get... touchy about it, or so I've heard.$(br2)Well, no one said tracing the deep secrets of the universe was going to be an easy time.", }, - + weather_manip: { lightning: "I command the heavens! This spell will summon a bolt of lightning to strike the earth where I direct it. Costs about three $(l:items/amethyst)$(item)Amethyst Shards/$.", summon_rain: "I control the clouds! This spell will summon rain across the world I cast it upon. Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$. Does nothing if it is already raining.", dispel_rain: "A counterpart to summoning rain. This spell will dispel rain across the world I cast it upon. Costs about one $(l:items/amethyst)$(item)Amethyst Shard/$. Does nothing if the skies are already clear.", }, - + altiora: { "1": "Summon a sheaf of _media about me in the shape of wings, endowed with enough substance to allow gliding.", "2": "Using them is identical to using $(item)Elytra/$; the target (which must be a player) is lofted into the air, after which pressing $(k:jump) will deploy the wings. The wings are fragile, and break upon touching any surface. Longer flights may benefit from $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ or (for the foolhardy) $(item)Fireworks/$.$(br2)Costs about one $(l:items/amethyst)$(item)Charged Crystal/$.", }, - + "teleport/great": { "1": "Far more powerful than $(l:patterns/spells/basic#hexcasting:blink)$(action)Blink/$, this spell lets me teleport nearly anywhere in the entire world! There does seem to be a limit, but it is $(italic)much/$ greater than the normal radius of influence I am used to.", "2": "The entity will be teleported by the given vector, which is an offset from its given position. No matter the distance, it always seems to cost about ten $(l:items/amethyst)$(item)Charged Amethyst/$.$(br2)The transference is not perfect, and it seems when teleporting something as complex as a player, their inventory doesn't $(italic)quite/$ stay attached, and tends to splatter everywhere at the destination. In addition, the target will be forcibly removed from anything inanimate they are riding or sitting on ... but I've read scraps that suggest animals can come along for the ride, so to speak.", }, - + zeniths: { "1": "This family of spells all impart a positive potion effect upon an entity, similar to the $(l:patterns/spells/nadirs)$(action)Nadirs/$. However, these have their _media costs increase with the $(italic)cube/$ of the potency.", - + "potion/regeneration": "Bestows $(thing)regeneration/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per second.", "potion/night_vision": "Bestows $(thing)night vision/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per 5 seconds.", "potion/absorption": "Bestows $(thing)absorption/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per second.", "potion/haste": "Bestows $(thing)haste/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per 3 seconds.", "potion/strength": "Bestows $(thing)strength/$. Base cost is one $(l:items/amethyst)$(item)Amethyst Dust/$ per 3 seconds.", }, - + greater_sentinel: { "1": "Summon a greater version of my $(l:patterns/spells/sentinels)$(thing)Sentinel/$. Costs about two $(l:items/amethyst)$(item)Amethyst Dust/$.", "2": "The stronger $(l:patterns/spells/sentinels)$(thing)sentinel/$ acts like the normal one I can summon without the use of a Great Spell, if a little more visually interesting. However, the range in which my spells can work is extended to a small region around my greater $(l:patterns/spells/sentinels)$(thing)sentinel/$, about 16 blocks. In other words, no matter where in the world I am, I can interact with things around my $(l:patterns/spells/sentinels)$(thing)sentinel/$ (the mysterious forces of chunkloading notwithstanding).", }, - + make_battery: { "1": "Infuse a bottle with _media to form a $(l:items/phials)$(item)Phial./$", "2": "Similarly to the spells for $(l:patterns/spells/hexcasting)$(action)Crafting Casting Items/$, I must hold a $(item)Glass Bottle/$ in my other hand, and provide the spell with a dropped stack of $(l:items/amethyst)$(item)Amethyst/$. See $(l:items/phials)this page/$ for more information.$(br2)Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$.", }, - + "brainsweep_spell.1": "I cannot make heads or tails of this spell... To be honest, I'm not sure I want to know what it does.", - + 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.", @@ -1922,7 +1937,7 @@ "7": "As a student, I am entitled to send one letter by Akashic post every three months, free of charge. Unfortunately, you know how thin my moneybags are ... so I am afraid this offer is the only method I may communicate with you. I will of course appreciate immensely if you manage to scrounge together the money to send a letter back, but it seems our communications may be limited. I hate to be cut off from you so, but the skills I gain here will be more than repayment. Imagine, I will be the first member of our family to be anything other than a farmer!", "8": "So, I suppose I will write again in three months' time.$(br2)Yours,$(br)-- Cardamom Steles", }, - + 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.", "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.)", @@ -1932,7 +1947,7 @@ "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", }, - + 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.", "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.", @@ -1947,7 +1962,7 @@ "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", }, - + 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.", "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.", @@ -1960,7 +1975,7 @@ "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", }, - + 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--", "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/$?", @@ -1968,7 +1983,7 @@ "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.", "5": "i can no longer write, my hands shake so much, please, rescue us.", }, - + inventory: { "1": "Cell 39, Restoration Log #72, Detainment Center Beta$(br2)Prisoner Name: Raphael Barr$(br)Crime: Knowledge of Project Wooleye$(br)Reason for Cell Vacancy: Death$(br)Additional notes: The following letter was scrawled over most of the wall space.", "2": "I see hexagons when I close my eyes.$(br2)The patterns, they invade the space between my eyes and my eyelids, my mind, my dreams. I sparkle in and out of lucidity, like a crystal dangling from a string, sometimes catching the light, sometimes consumed by it.", @@ -1984,7 +1999,7 @@ "12": "they're going to kill everyone n the whole world aren't they the grand needs to eat just as much as i ... when did i lasst eat$(br2)everyone else has to eat and they cannot do that if all the farmers in the world are empty and all the knowledge of farming is underground or at least someone else is going to Find out and melt their smug faces to wax", "13": "maybe wake up someday and wonder about all the thngs we left them and wonder why there are million miles of tunnels underground with no one smart enough to mine them$(br2)i can see them reading this . they ... will be too far gone to care", }, - + experiment1: { "1": "$(italic)I only managed to find these five entries from this log./$$(br2)Detonation #26$(li)Location: Carpenter's North$(li)Population: 174$(li)Nodes Formed: 3$(li)Node Distance from Epicenter: 55-80m vertical, 85-156m horizontal$(li)Media Generation: 1320 uθ/min", "2": "Detonation #27$(li)Location: Brackenfalls$(li)Population: 79$(li)Nodes Formed: 1$(li)Node Distance from Epicenter: 95m vertical, 67m horizontal$(li)Media Generation: 412 uθ/min", @@ -1993,7 +2008,7 @@ "5": "Detonation #30$(li)Location: Boiling Brook$(li)Population: 231$(li)Nodes Formed: 4$(li)Node Distance from Epicenter: 61-89m vertical, 78-191m horizontal$(li)Media Generation: 1862 uθ/min", "6": "Conclusion: approx 60 needed for one node. Too few consumes them but does not provide enough energy for node formation. Little correlation between input count and breadth/depth.$(br2)Effects on inhabitants still consistently more severe than with single-target testing, especially the physical effects.", }, - + experiment2: { "1": "$(italic)These documents were heavily redacted. I have copied the readable text from them here./$$(br2)Subject #1 \"A.E.\"$(br)Stopped struggling immediately after procedure. Facial expression and limbs slack, but can stand unassisted. When left unattended, absently pantomimes actions commonly done in previous profession (groundskeeping).", "2": "Heartrate high immediately after procedure, but this is inconclusive due to state of fear immediately before. Resulting bud produced 35 uθ/min.$(br)...$(br)Subject #4 \"P.I.\"$(br)Psychological tests run on P.I. Subject has object permanence, spatial awareness, basic numerical reasoning. Difficulty learning new tasks. $(br2) ...", @@ -2002,18 +2017,18 @@ }, }, // ^ lore - + interop: { "1": "The art of _Hexcasting is versatile. If I find that my world has been $(italic)modified/$ by certain other powers, it's possible that I may use _Hexcasting in harmony and combination with them.", "2": "I should keep in mind, however, that Nature seems to have paid less attention in crafting these aspects of my art; strange behavior and bugs are to be expected. I'm sure the mod developer will do her best to correct them, but I must remember this is a less important pastime to her.$(br2)I may also find that there are sharp disregards to balance in the costs and effects of the interoperating powers. In such a case I suppose I will have to be responsible and restrain myself from using them.", "3": "Finally, if I find myself interested in the lore and stories of this world, I do not think any notes compiled while examining these interoperations should be considered as anything more than light trifles.", - + gravity: { "1": "I have discovered actions to get and set an entity's gravity. I find them interesting, if slightly nauseating.$(br2)Interestingly, although $(l:patterns/great_spells/flight)$(action)Flight/$ is a great spell, and manipulates gravity similarly, these are not. It baffles me why... Perhaps the mod developer wanted players to have fun, for once.", get: "Get the main direction gravity pulls the given entity in, as a unit vector. For most entities, this will be down, <0, -1, 0>.", set: "Set the main direction gravity pulls the given entity in. The given vector will be coerced into the nearest axis, as per $(l:patterns/math#hexcasting:coerce_axial)$(action)Axial Purification/$. Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$.", }, - + pehkui: { "1": "I have discovered methods of changing the size of entities, and querying how much larger or smaller they are than normal.", get: "Get the scale of the entity, as a proportion of their normal size. For most entities, this will be 1.", 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..1b94caa75f 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: "Кажется, я постиг все, что может предложить этот мир.", }, }, @@ -121,22 +121,22 @@ conjured_block: "Магический Блок", directrix: { - empty: "Empty Directrix", - redstone: "Mason Directrix", - boolean: "??? Directrix", + empty: "Пустой Направитель", + redstone: "Направитель Каменщика", + boolean: "Логический Направитель", }, impetus: { - empty: "Empty Impetus", - rightclick: "Toolsmith Impetus", - look: "Fletcher Impetus", - redstone: "Cleric Impetus", + empty: "Пустой Инициатор", + rightclick: "Инициатор Инструментальщика", + look: "Инициатор Лучника", + redstone: "Инициатор Священника", }, 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", - bricks: "Аметистовые Кирпечи", - bricks_small: "Маленькие Аметистовые Кирпечи", - pillar: "Amethyst Pillar", + tiles: "Аметистовая Плитка", + bricks: "Аметистовые Кирпичи", + 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,26 +220,26 @@ }, "tag.hexcasting": { - staves: "Hex Staves", - edified_logs: "Edified Брёвна", - edified_planks: "Edified Доски", + staves: "Посохи", + edified_logs: "Брёвна Созидани", + edified_planks: "Доски Созидания", phial_base: "Пустой Сосуд", }, "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": { - 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,52 +346,52 @@ "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: { - "": "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", @@ -401,35 +401,34 @@ }, "stat.hexcasting": { - media_used: "Media потребляемые (в виде пыли)", - media_overcasted: "Media Overcast (в виде пыли)", - patterns_drawn: "Нарисованные Patterns", - spells_cast: "Каст Заклинаний", + media_used: "Мысли потребляемые (в виде пыли)", + media_overcast: "Переиспользовано мысли (в виде пыли)", + patterns_drawn: "Рун нарисовано", + spells_cast: "Заклинаний использовано", }, "death.attack.hexcasting": { - overcast: "%s' его разум превратился в энергию", - shame: "Позор %s!", + overcast: "Разум %s был полноценно поглощён как оплата заклинания.", }, "command.hexcasting": { 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 +441,8 @@ // TODO: post-eigengrau make these less anticlimactic message: { - cant_overcast: "Для этого заклинания требовалось больше Media, чем у меня было... Мне следует еще раз проверить свои расчеты.", - cant_great_spell: "Заклинание каким-то образом не сработало... неужели я недостаточно искусен?", + cant_overcast: "Для этого заклинания требовалось больше мысли, чем у меня было... Мне следует еще раз проверить свои расчеты.", + cant_great_spell: "Заклинание каким-то образом не сработало... неужели у меня не хватает знаний?", }, tooltip: { @@ -470,13 +469,13 @@ }, circle: { - no_exit: "Поток Media не смог найти выхода в %s", - many_exits: "У потока Media было слишком много выходов в %s", - no_closure: "Поток Media не сможет вернуться к прежнему impetus на %s", + no_exit: "Поток мысли не смог найти выхода в %s", + many_exits: "У потока мысли было слишком много выходов в %s", + no_closure: "Поток мысли не сможет вернуться к прежнему Инициатору на %s", }, lens: { - "pattern.invalid": "Недопустимый Pattern", + "pattern.invalid": "Неизвестная руна", bee: { "": "%s bees", single: "%s bee", @@ -488,7 +487,7 @@ akashic: { "bookshelf.location": "Запись на %s", "record.count": { - "": "%s iotas хранящиеся", + "": "%s йоты хранящиеся", single: "%s iota хранящаяся", }, }, @@ -500,60 +499,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": "Инициатор Лучника кликает", + "impetus.redstone.register": "Инициатор Священника звенит", + "lore_fragment.read": "Прочтен фрагмент истории", + "flight.ambience": "Игрок летит", + "flight.finish": "Полет окончился", }, attributes: { - grid_zoom: "Размер сетки каста", + grid_zoom: "Размер сетки заклинания", // TODO: the +1 is kind of janky scry_sight: "Магический взгляд", }, @@ -563,303 +562,303 @@ 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", - 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", - swizzle: "Swindler'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: "Гамбит Гробовщика", + "2dup": "Гамбит Дубля", + duplicate_n: "Гамбит Близнецов", + stack_len: "Отражение Группы", + fisherman: "Гамбит Рыбака", + "fisherman/copy": "Гамбит Рыбака II", + swizzle: "Гамбит Мошенника", - unique: "Uniqueness Purification", - and: "Conjunction Distillation", - or: "Disjunction Distillation", - xor: "Exclusion Distillation", + unique: "Преображение Уникальности", + and: "Объединение Совпадения", + or: "Объединение Дизъюнкции", + xor: "Объединение Исключения", - 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/local": "Muninn's Reflection", - - write: "Scribe's Gambit", - "write/entity": "Chronicler's Gambit", - "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", + read: "Отражение Писаря", + "read/entity": "Преображение Летописца", + "read/local": "Отражение Мунин", + + write: "Гамбит Писаря", + "write/entity": "Гамбит Летописца", + "write/local": "Гамбит Хугин", + + 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", - - 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", - }, - - 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", + weakness: "Надир Белого Солнца", + levitation: "Надир Синего Солнца", + wither: "Надир Черного Солнца", + poison: "Надир Красного Солнца", + slowness: "Надир Зеленого Солнца", + + regeneration: "Зенит Белого Солнца", + night_vision: "Зенит Синего Солнца", + absorption: "Зенит Черного Солнца", + haste: "Зенит Красного Солнца", + strength: "Зенит Зеленого Солнца", + }, + + flight: "Альтиора", + "flight/range": "Дальность Полета", + "flight/time": "Время Полета", + + 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 +875,8 @@ divide_by_zero: { divide: "Попытался разделить %s на %s", - project: "Попытался спроецировать %s на %s", - exponent: "Попытался увеличить значение %s до значения %s", + project: "Попытался спроецировать %s на %s", + exponent: "Попытался возвести %s в степень %s", logarithm: "Попытался получить логарифм %s в виде базового значения %s", zero: { @@ -890,30 +889,29 @@ cos: "косинус %s", }, - no_akashic_record: "Нет Akashic Record на %s", + no_akashic_record: "Нет Записи Акаши на %s", disallowed: "был запрещен администраторами сервера", disallowed_circle: "был запрещен в кругах заклинаний администраторами сервера", invalid_spell_datum_type: "Пытался использовать значение недопустимого типа в качестве параметра для написания: %s (класс %s). Это ошибка в настройках.", unknown: "возникло исключение (%s). Это ошибка в моде.", - shame: "Как вам не стыдно!", - + invalid_value: { "": "ожидал %s по индексу %s стека, но получил %s", 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 +919,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,11 +940,11 @@ between: "целое число между %d и %d", }, - evaluatable: "something evaluatable", - bool_commute: "boolean - 0 или 1", + evaluatable: "нечто исполняемое", + bool_commute: "Логика - 0 или 1", }, - location: { + location_: { too_far: "%s находится вне диапазона", out_of_world: "%s находится за пределами этого мира", too_close_to_out: "%s находится слишком близко к границе мира", @@ -959,14 +957,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 +980,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 +1036,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", - quenching_allays: "Quenching Allays", - fanciful_staves: "Fanciful Staves", + impetus: "Инициатор", + directrix: "Направитель", + akashiclib: "Библиотеки Акаши", + quenching_allays: "Погашенные Тихони", + 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: "Полет", @@ -1132,11 +1130,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", @@ -1155,289 +1153,289 @@ 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: { "1": "Как правило, я предоставляю свои шаблоны природе с помощью моего $(l:items/staff)$(item)Staff/$. \ Применив $(thing)$(k:use)/$ держа его в руке, передо мной появится шестиугольная сетка из точек. \ - Затем я могу щелкнуть, перетащить от точки к точке и отпустить, чтобы нарисовать узор.$(br2)\ + Затем я могу щелкнуть, перетащить от точки к точке и отпустить, чтобы нарисовать руну.$(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)Отражение Нарцисса/$ создаст йота представляющую $(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)Список нескольких из вышеперечисленного, собранных в одну йота.", + "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: "Нарисованный узор не связан ни с одним действием.$(br2)Вызывает желтые искры, и $(l:casting/influences)$(action)Мусор/$ будет помещен в верхнюю часть моего стека.", + "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.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": "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/$) могут не извлекать аргументы, и некоторые действия (особенно заклинания) могут ничего не добавлять после этого.", - "4": "Еще более сложные действия могут быть выражены в терминах добавления, удаления и просмотра. Например, $(l:patterns/stackmanip#hexcasting:swap)$(action)Jester's Gambit/$ меняет местами два верхних элемента стека. Это можно рассматривать как извлечение двух элементов и добавление их в обратном порядке. Для другого примера, $(l:patterns/stackmanip#hexcasting:duplicate)$(action)Gemini Decomposition/$ дублирует вершину стека - другими словами, она просматривает стек и добавляет копию найденного элемента.", + "3": "Действия (в большинстве случаев) ограничены взаимодействием со стеком такими способами. Они будут извлекать некоторые иоты, которые их интересуют (известные как \"аргументы\" или \"параметры\"), обрабатывать их и затем добавлять некоторое количество результатов.$(br2)Конечно, некоторые действия (например, $(l:patterns/basics#hexcasting:get_caster)$(action)Отражение Нарцисса/$) могут не извлекать аргументы, и некоторые действия (особенно заклинания) могут ничего не добавлять после этого.", + "4": "Еще более сложные действия могут быть выражены в терминах добавления, удаления и просмотра. Например, $(l:patterns/stackmanip#hexcasting:swap)$(action)Гамбит Шута/$ меняет местами два верхних элемента стека. Это можно рассматривать как извлечение двух элементов и добавление их в обратном порядке. Для другого примера, $(l:patterns/stackmanip#hexcasting:duplicate)$(action)Разбор Близнецов/$ дублирует вершину стека - другими словами, она просматривает стек и добавляет копию найденного элемента.", }, naming: { "1": "Названия, данные действиям древними, были, безусловно, странными, но я думаю, что в них есть определенная логика.$(br2)Кажется, есть определенные группы действий с общими названиями, названными по числу иот, которые они удаляют из стека и добавляют в стек.", - "2": "$(li) $(thing)Отражение/$ не удаляет ничего и добавляет один иот.$(li) $(thing)Purification/$ удаляет один иот и добавляет один.$(li) $(thing)Distillation/$ удаляет два и добавляет один.$(li) $(thing)Exaltation/$ удаляет три или более и добавляет один.$(li) $(thing)Decomposition/$ удаляет один аргумент и добавляет два.$(li) $(thing)Disintegration/$ удаляет один и добавляет три или более.$(li) Наконец, $(thing)Gambit/$ добавляет или удаляет другое количество (или перестраивает стек другим образом).", - "3": "Похоже, что заклинания освобождены от этой номенклатуры и в основном названы по тому, что они делают - в конце концов, зачем называть его $(action)Demoman's Gambit/$, когда можно просто сказать $(l:patterns/spells/basic#hexcasting:explode)$(action)Explosion/$?", + "2": "$(li) $(thing)Отражение/$ не удаляет ничего и добавляет один иот.$(li) $(thing)Преображение/$ удаляет один иот и добавляет один.$(li) $(thing)Объединение/$ удаляет два и добавляет один.$(li) $(thing)Возвышение/$ удаляет три или более и добавляет один.$(li) $(thing)Разбор/$ удаляет один аргумент и добавляет два.$(li) $(thing)Распад/$ удаляет один и добавляет три или более.$(li) Наконец, $(thing)Гамбит/$ добавляет или удаляет другое количество (или перестраивает стек другим образом).", + "3": "Похоже, что заклинания освобождены от этой номенклатуры и в основном названы по тому, что они делают - в конце концов, зачем называть его $(action)Гамбит Демона/$, когда можно просто сказать $(l:patterns/spells/basic#hexcasting:explode)$(action)Взрыв/$?", }, 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: "Попытка получить доступ к $(l:greatwork/akashiclib)$(item)Akashic Record/$ в месте, где ее нет.$(br2)Вызывает фиолетовые искры и уносит часть моего опыта.", + "no_record.title": "Отсутствие Записи Акаши", + no_record: "Попытка получить доступ к $(l:greatwork/akashiclib)$(item)Записи Акаши/$ в месте, где ее нет.$(br2)Вызывает фиолетовые искры и уносит часть моего опыта.", }, // 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: { "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/$ удалит эту печать вместе с содержимым.", - "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)Гамбит Писаря/$ и перезаписать иоту внутри.", + "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)Я также могу назвать каждую страницу индивидуально на наковальне. Название изменит только имя выбранной в данный момент страницы для удобного просмотра.", + "1": "$(l:items/spellbook)$(item)Книга заклинаний/$ - это вершина моего искусства - она действует как целая библиотека $(l:items/focus)$(item)Талисманов/$. До $(thing)шестидесяти четырех/$ из них, чтобы быть точным.$(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 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)Преображение Луча/$ потребует весь кристалл, растрачивая оставшееся Мысли.$(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 +1450,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)Инициатор/$, чтобы создать самоподдерживающуюся волну Мысли. Эта волна движется по дорожке из $(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)Я не уверен, была ли эта идея мне внушена, или мой разум достаточно изогнут вокруг барьера, чтобы самостоятельно выделять свои идеи теперь... но если идея произошла от моего собственного разума, если я думал об этом, можно ли сказать, что она была внушена? Мозг - сосуд для разума, а разум - сосуд для идей, идеи - сосуд для мыслей, и мысли видят все и знают все", + "1": "Задача направления самоподдерживающейся волны Мысли проще, чем задача ее создания. Обычно волна распадается, когда она сталкивается с перекрёстком, но с умом, направляющим ее, можно контролировать направление выхода.$(br2)Это управление далеко не так тонкое, как активация заклинательного круга. Фактически, возможно, это можно сделать вручную... но упакованные разумы, к которым у меня сейчас есть доступ, были бы так удобны.", + "2": "$(l:greatwork/directrix)$(item)Направитель/$ принимает волну Мысли и определяет, к какой из стрелок она выйдет, в зависимости от разума жителя внутри.$(br2)Я не уверен, была ли эта идея мне внушена, или мой разум достаточно изогнут вокруг барьера, чтобы самостоятельно выделять свои идеи теперь... но если идея произошла от моего собственного разума, если я думал об этом, можно ли сказать, что она была внушена? Мозг - сосуд для разума, а разум - сосуд для идей, идеи - сосуд для мыслей, и мысли видят все и знают все", - empty_directrix: "Прежде всего, дизайн для колыбели... хотя, возможно, слово \"субстрат\" было бы более точным. Без ума, направляющего его, направление выхода определяется микроскопическими флуктуациями волн _медиа и окружающей среды, что делает его фактически случайным.", - directrix_redstone: "$(l:greatwork/directrix)$(item)Mason Directrix/$ переключает сторону выхода в зависимости от сигнала красного камня. Без сигнала выход - цвет _медиа; с сигналом выход - сторона красного камня.", + empty_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: { - "1": "ЭТО КУСОЧКИ _МЕДИА. Как я не заметил этого раньше? Они - как и я - куча плоти с обрывком, благословленным обрывком мысли, Аллей - это самоподдерживающаяся ссора _медиа, прикрепленная к обрывку плоти. Это объясняет все - их склонность к _медиа, их реакцию на музыку, Я ВИДЕЛ СЕЙЧАС, КАК НЕ ВИДЕЛИ те, кто был раньше?", - "2": "И учитывая это, было бы правильно, если бы я покорил их своеобразные умы - их своеобразные \"я\" - это все, чем они являются, умом, \"сознанием\". Что-то в них говорит со мной. Я могу... Я могу сжать _медиа с ними, наложить две ветви мысли на одно пространство, физическое и когнитивное, все и сразу. Как? Возможно... возможно, моя работа, процесс ее выполнения...", + "1": "Это же и есть живые Мысли. Как я не заметил этого раньше? Они - как и я - куча плоти с обрывком, благословленным обрывком мысли, Тихоня - это самоподдерживающаяся кучка Мысли, прикрепленная к обрывку плоти. Это объясняет все - их склонность к Мысли, их реакцию на музыку, как можно было это не заметить?", + "2": "И учитывая это, было бы правильно, если бы я покорил их своеобразные умы - их своеобразные \"я\" - это все, чем они являются, умом, \"сознанием\". Что-то в них говорит со мной. Я могу... Я могу сжать Мысли с ними, наложить две ветви мысли на одно пространство, физическое и когнитивное, все и сразу. Как? Возможно... возможно, моя работа, процесс ее выполнения...", "3": "Это не имеет значения. Я не имею значения. Они не имеют значения, все, что имеет значение, это то, что это делает. И вот это.$(br2)Это должно так болезненно.", - "4": "Продукт хрупок. Разбив его, вы раскалываете его на кусочки, и $(thing)зачерование Удачи/$ увеличивает выход... если я хочу сам блок, мне нужно легкое прикосновение.$(br2)Полученные осколки стоят втрое дороже $(l:items/amethyst)$(item)Заряженного Аметистового Кристалла/$ за штуку. Сам блок стоит четыре осколка.", - "5": "Они непостоянны, кажется, что они изгибаются и мигают под моими пальцами, и, дав им пример в другой форме _медиа, их можно заставить принять его форму, в эквивалентном обмене _медиа.", + "4": "Продукт хрупок. Разбив его, вы раскалываете его на кусочки, и $(thing)зачарование Удачи/$ увеличивает выход... если я хочу сам блок, мне нужно легкое прикосновение.$(br2)Полученные осколки стоят втрое дороже $(l:items/amethyst)$(item)Заряженного Аметистового Кристалла/$ за штуку. Сам блок стоит четыре осколка.", + "5": "Они непостоянны, кажется, что они изгибаются и мигают под моими пальцами, и, дав им пример в другой форме Мысли, их можно заставить принять его форму, в эквивалентном обмене Мысли.", }, @@ -1520,25 +1518,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)Ничто/$.$(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)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: "Преобразует сущность в стеке в направление, в котором она движется, со скоростью этого движения в качестве величины этого направления.", }, @@ -1606,7 +1604,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)С двумя списками это создает список каждого элемента из первого списка, который также присутствует во втором списке.", @@ -1619,14 +1617,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 +1636,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 +1649,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,48 +1664,48 @@ }, 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)Ничто/$ и пустой список становятся Ложь; всё остальное становится Истина.", + 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)Ничто/$, если ее там нет).", "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: "Берёт позицию и радиус в стеке и объедините их в список всех 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: "Берёт позицию и радиус в стеке и объедините их в список сущность, не являющихся живыми, находящихся в заданном радиусе от позиции.", }, }, 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 +1717,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 +1728,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/$, они добавляются на стек как список йот.", @@ -1741,56 +1739,56 @@ }, 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/$ и самостоятельно записать себя на него.", + "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/$.", + "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: "Если я могу сохранить йоту в предмете, который держу в другой руке, возвращается Истина. В противном случае возвращается Ложь.", + "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)Гамбит Хугина/$.", }, 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)Гамбит Харона/$). Если йота была выведена с помощью $(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.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.1": "Вызывает паттерн или список паттернов из стека точно так же, как Гамбит Гермеса, за исключением того, что в стек предварительно помещается уникальная йота \"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)Посоха/$ приведёт к весьма впечатляющему провалу.", + 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: { @@ -1800,11 +1798,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 +1813,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 +1830,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)Часовые/$ - это таинственная сила, которую я могу призвать для помощи в произнесении заклинаний, подобно знакомому или духу-хранителю. Для меня он выглядит как вращающаяся геометрическая форма, но он невидим для всех остальных.", + "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/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)Все формы производят избыток _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 +1877,32 @@ }, altiora: { - "1": "Вызывает вокруг тебя сноп _media в форме крыльев, наделенных достаточным количеством вещества, чтобы обеспечить скольжение по воздуху.", - "2": "Их использование идентично использованию $(item)Елитр/$; цель(которой должен быть игрок) поднимается в воздух, после нажатие $(k:jump) приводит в действие крылья. Крылья хрупкие и ломаются при соприкосновении с любой поверхностью. Для более длительных полетов можно использовать $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ или (для самых отважных) $(item)Феерверки/$.$(br2)Стоит около одного $(l:items/amethyst)$(item)Заряженного Аметиста/$.", + "1": "Вызывает вокруг тебя сноп Мысли в форме крыльев, наделенных достаточным количеством вещества, чтобы обеспечить скольжение по воздуху.", + "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)гораздо/$ больше, чем обычный радиус влияния, к которому я привык.", - "2": "Entity будет телепортировано по заданному вектору, который является смещением от его текущего положения. Независимо от расстояния, это всегда стоит около десяти $(l:items/amethyst)$(item)Заряженных Аметистов/$.$(br2)Перенос не идеален, и кажется, что при телепортации чего-то такого сложного, как игрок, их инвентарь не $(italic)всегда/$ остается прикрепленным и склонен разлетаться повсюду на месте назначения. Кроме того, цель будет насильственно удалена от всего неживого, на чем они едут или сидят... но я прочитал кое-какие обрывки, которые предполагают, что животные могут пойти вместе в путь, так сказать.", + "1": "Гораздо мощнее, чем $(l:patterns/spells/basic#hexcasting:blink)$(action)Перенос/$, это заклинание позволяет мне телепортироваться практически в любое место на всей планете! Похоже, что есть ограничение, но оно $(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,28 +1911,28 @@ 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: { - "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 +1943,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 +1956,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.", @@ -1975,7 +1973,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,19 +2002,19 @@ // ^ lore interop: { - "1": "Искусство _Hexcasting универсально. Если я обнаружу, что мой мир был $(italic)изменен/$ определенными другими силами, возможно, что я смогу использовать _Hexcasting в гармонии и сочетании с ними.", + "1": "Искусство написания рун универсально. Если я обнаружу, что мой мир был $(italic)изменен/$ определенными другими силами, возможно, что я смогу использовать руны в гармонии и сочетании с ними.", "2": "Я должен помнить, однако, что Природа, кажется, уделила меньше внимания при создании этих аспектов моего искусства; странное поведение и ошибки можно ожидать. Я уверен, что разработчик мода сделает все возможное, чтобы их исправить, но я должен помнить, что это для нее менее важное занятие.$(br2)Мне также может показаться, что есть явные нарушения баланса в затратах и эффектах взаимодействующих сил. В таком случае, предполагаю, мне придется быть ответственным и воздерживаться от их использования.", "3": "Наконец, если я обнаружу, что меня заинтересовали легенды и истории этого мира, я не думаю, что какие-либо заметки, составленные во время изучения этих взаимодействий, следует рассматривать как что-то более серьезное, чем легкие пустяки.", 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: { "1": "Я обнаружил способы изменения размера сущностей и запроса, насколько они больше или меньше обычного.", - get: "Получите масштаб сущности как пропорцию их нормального размера. Для большинства сущностей это будет 1.", + get: "Получите масштаб сущности как отношение к их нормальному размеру. Для большинства сущностей это будет 1.", set: "Установите масштаб сущности, передавая пропорцию их нормального размера. Стоимость около 1 $(item)Осколка Аметиста/$.", }, }, 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..20c7e04591 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 @@ -402,14 +402,13 @@ "stat.hexcasting": { media_used: "消耗媒质量(以紫水晶粉计)", - media_overcasted: "过度施法消耗媒质量(以紫水晶粉计)", + media_overcast: "过度施法消耗媒质量(以紫水晶粉计)", patterns_drawn: "绘制图案次数", spells_cast: "施放法术次数", }, "death.attack.hexcasting": { overcast: "%s的意识消散为了能量", - shame: "%s真是可耻!", }, "command.hexcasting": { @@ -890,12 +889,16 @@ cos: "%s的余弦", }, + invalid_operator_args: { + one: "在栈下标为%d处获取到意外iota:%s", + many: "在栈下标为%2$d到%3$d处获取到意外iota:%4$s", + }, + no_akashic_record: "%s处无阿卡夏记录", disallowed: "已被服务器管理员禁用于施法", disallowed_circle: "已被服务器管理员禁用于法术环", invalid_spell_datum_type: "尝试将某无效类型的值用作SpellDatum:%s(class %s)。这是模组中的bug。", unknown: "抛出异常(%s)。这是模组中的bug。", - shame: "你真是可耻!", invalid_value: { "": "本应在栈下标为%2$s处接受%1$s,而实际接受了%3$s", @@ -946,7 +949,7 @@ bool_commute: "一个布尔值、0或1", }, - location: { + location_: { too_far: "%s超出影响范围", out_of_world: "%s不在此世界内", too_close_to_out: "%s离世界边界太近了", diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/casting/mishaps.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/casting/mishaps.json index a5b5984076..08fb6d0335 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/casting/mishaps.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/casting/mishaps.json @@ -28,6 +28,11 @@ "title": "hexcasting.page.mishaps.not_enough_iotas.title", "text": "hexcasting.page.mishaps.not_enough_iotas" }, + { + "type": "patchouli:text", + "title": "hexcasting.page.mishaps.stack_size.title", + "text": "hexcasting.page.mishaps.stack_size" + }, { "type": "patchouli:text", "title": "hexcasting.page.mishaps.incorrect_iota.title", diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/meta.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/meta.json index 4c0225732f..63e7f68c4a 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/meta.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/meta.json @@ -51,6 +51,13 @@ { "type": "patchouli:text", "text": "hexcasting.page.meta.halt.2" + }, + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:thanatos", + "anchor": "hexcasting:thanatos", + "output": "number", + "text": "hexcasting.page.meta.thanatos.1" } ] } diff --git a/Common/src/main/resources/data/hexcasting/damage_type/shame.json b/Common/src/main/resources/data/hexcasting/damage_type/shame.json deleted file mode 100644 index e7cd1eda85..0000000000 --- a/Common/src/main/resources/data/hexcasting/damage_type/shame.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "exhaustion": 0, - "message_id": "hexcasting.shame", - "scaling": "when_caused_by_living_non_player" -} \ No newline at end of file diff --git a/Common/src/main/resources/data/hexcasting/patchouli_books/thehexbook/book.json b/Common/src/main/resources/data/hexcasting/patchouli_books/thehexbook/book.json index fec05cd261..146a1d2642 100644 --- a/Common/src/main/resources/data/hexcasting/patchouli_books/thehexbook/book.json +++ b/Common/src/main/resources/data/hexcasting/patchouli_books/thehexbook/book.json @@ -4,7 +4,7 @@ "version": 1, "show_progress": false, "nameplate_color": "00072b", - "creative_tab": "hexcasting", + "creative_tab": "hexcasting:hexcasting", "model": "hexcasting:patchouli_book", "book_texture": "hexcasting:textures/gui/patchi_book.png", "filler_texture": "hexcasting:textures/gui/patchi_filler.png", diff --git a/Fabric/src/generated/resources/.cache/19f2b40f78e342d65a8cb499a41e3fcb2eadaca3 b/Fabric/src/generated/resources/.cache/19f2b40f78e342d65a8cb499a41e3fcb2eadaca3 index 8c5031dfbe..e5e85cf919 100644 --- a/Fabric/src/generated/resources/.cache/19f2b40f78e342d65a8cb499a41e3fcb2eadaca3 +++ b/Fabric/src/generated/resources/.cache/19f2b40f78e342d65a8cb499a41e3fcb2eadaca3 @@ -1,58 +1,58 @@ -// 1.20.1 2024-06-13T19:17:10.5236232 Hex Casting/Loot Tables -b19ac49146149555038e6d2e06200d514df1ef43 data\hexcasting\loot_tables\blocks\akashic_bookshelf.json -b6c23fdde4f2c22c81f008604d5ff1c32ca8eb61 data\hexcasting\loot_tables\blocks\amethyst_tiles.json -df5496da8e48b61a171bc7a3936495c016cc002e data\hexcasting\loot_tables\blocks\directrix\empty.json -74159c21634679a6ab1dde1c181433db8b31c6ae data\hexcasting\loot_tables\blocks\edified_log_citrine.json -cc7313cc33609fe1120baa7b4db631eaa29fbba1 data\hexcasting\loot_tables\blocks\citrine_edified_leaves.json -847bc3ead8a88a8f210a24e7732c28d50aa2f5dc data\hexcasting\loot_tables\blocks\edified_planks.json -49940d1cb2599212e2837d7ed66c6c66e54f80f8 data\hexcasting\loot_tables\blocks\akashic_record.json -7123b1a0469d7bd5bf8a2772182d222bf354df1a data\hexcasting\loot_tables\blocks\slate_bricks_small.json -95be0cf7f277257671631929462131b6d611119a data\hexcasting\loot_tables\inject\amethyst_cluster.json -d16fa9e366d48646686470c2d1f9bda4db3a1afa data\hexcasting\loot_tables\blocks\ancient_scroll_paper.json -2902c4dae60875a1b2daf0a948a49a3419d8ec9d data\hexcasting\loot_tables\blocks\edified_log.json -b706c8a064f717c57104c48ea42aa860b45cf7a4 data\hexcasting\loot_tables\blocks\amethyst_dust_block.json -c81a5cb81141ab1fe09dd5dd3a0968b69dfffbd7 data\hexcasting\loot_tables\blocks\stripped_edified_log.json -0b734693c926045b60fb515814b7a6695d0295fc data\hexcasting\loot_tables\blocks\impetus\look.json -6c35afda4ca349f3506fe08f86f0afe58a6f2c44 data\hexcasting\loot_tables\blocks\quenched_allay.json -9ff760d5db5628328ea9274c98e18a08f1ab983e data\hexcasting\loot_tables\blocks\slate_block.json -ecaeb4d5703a7aa206627ed38ee71aeb7e93d688 data\hexcasting\loot_tables\blocks\impetus\rightclick.json -44658abcf122575878834d276ebcf5d8a6b7b398 data\hexcasting\loot_tables\blocks\aventurine_edified_leaves.json -4efd95d408d050c36ff21b18f3c37116491fef92 data\hexcasting\loot_tables\blocks\directrix\redstone.json -434c2a6d2645e56e9a6ca56249ffa84645558e3b data\hexcasting\loot_tables\blocks\quenched_allay_bricks_small.json -bedbc2bd04f79372aedea64214ba2ea49cde9640 data\hexcasting\loot_tables\blocks\amethyst_edified_leaves.json -ab86e126a704550d3f21c0b43f99fdc2665e4b09 data\hexcasting\loot_tables\blocks\slate_amethyst_tiles.json -6eecc98b606d7ea5ec6f4c1fa4f63f7c1eba9223 data\hexcasting\loot_tables\blocks\slate_amethyst_bricks.json -2ac70e3c3600c88b2544d9755fc634216a7a523c data\hexcasting\loot_tables\blocks\edified_wood.json -92331eb19422730ffda0a3e52427a75aa1f7aff2 data\hexcasting\loot_tables\blocks\ancient_scroll_paper_lantern.json -c426245d51f1e0fa0db7c4bfb454284d75506c9c data\hexcasting\loot_tables\blocks\quenched_allay_bricks.json -dc4c6d270b8e93d05ac8ddeb1b9dd1d64828ac5d data\hexcasting\loot_tables\blocks\stripped_edified_wood.json -1dd4268edf7d6fa247013ab45541c7bfb915eef8 data\hexcasting\loot_tables\blocks\amethyst_bricks_small.json -849afa706e7479d1c11bb40ae223ae5833e71286 data\hexcasting\loot_tables\blocks\scroll_paper_lantern.json -45ae0ec668a07aa5b33d491377b2978f69f9f019 data\hexcasting\loot_tables\blocks\edified_panel.json -e6ff979aa47877c1b807075c448defd249cd3484 data\hexcasting\loot_tables\blocks\slate_amethyst_pillar.json -65fe724d4c4ba8b0ab7d7a11bf37687413d9119d data\hexcasting\loot_tables\blocks\edified_fence.json -a4e0194d8966a24531e43e04437cdb2a96456898 data\hexcasting\loot_tables\blocks\edified_tile.json -509ecbb9731e75b63638c6012b2f986f131fd42f data\hexcasting\loot_tables\blocks\slate_amethyst_bricks_small.json -601384d888edab27efe4a33027bb557eb7cb6ca2 data\hexcasting\loot_tables\blocks\edified_log_purple.json -1a1236e54c24b5aeff05919c73c76151da2cf115 data\hexcasting\loot_tables\blocks\amethyst_sconce.json -5f8d09e8c759d05cf9c2265ae28ea942cfbbe2be data\hexcasting\loot_tables\blocks\edified_pressure_plate.json -147e0739a712a9050856cebcad1757b3f418f647 data\hexcasting\loot_tables\blocks\edified_trapdoor.json -55f265961463a89c243ec8ac1970c70185f064a6 data\hexcasting\loot_tables\blocks\edified_button.json -f1145860d80ff053970b1ad4f3b2f5d9f28e7c73 data\hexcasting\loot_tables\blocks\directrix\boolean.json -2ab674e834184b4e17dc002556d4473cac137445 data\hexcasting\loot_tables\blocks\edified_slab.json -c15d3ced89c882dfe552f84435fcdd560b729567 data\hexcasting\loot_tables\blocks\scroll_paper.json -8c6c0486170537d73b923a2b9f83722107fc8716 data\hexcasting\loot_tables\blocks\edified_log_aventurine.json -6920654f50532b5e557646e34edc4872339eb79f data\hexcasting\loot_tables\blocks\edified_log_amethyst.json -9905b767be7849e02a8e4ec4170af1bdde4e7fab data\hexcasting\loot_tables\blocks\edified_stairs.json -30f06db8c1ea74c9f4d95474e412336d065ac888 data\hexcasting\loot_tables\blocks\edified_door.json -2ad288784b0dc106ace2e6e0a40669f83476c414 data\hexcasting\loot_tables\blocks\slate.json -92528799c8ee13ff26c3c505e4dfb286c30f97c7 data\hexcasting\loot_tables\blocks\akashic_connector.json -8ea8fd68719a960c2e132df441564a70c0e376a8 data\hexcasting\loot_tables\blocks\amethyst_pillar.json -45dc91d820caa5c421fe6f2afc7f71e45d6acd4d data\hexcasting\loot_tables\blocks\slate_pillar.json -10cb1b94596ac7131efe3bd5c36c1543ddba9302 data\hexcasting\loot_tables\blocks\impetus\redstone.json -499af9f15cf0a7f16fd2939e5d3af60a8089cc3e data\hexcasting\loot_tables\blocks\slate_bricks.json -2c9af74a82ca462e5986354966d5a0a1fd5a2083 data\hexcasting\loot_tables\blocks\slate_tiles.json -cf6ff1ed1ee6fdbb05af16468a0a0ced79ac334e data\hexcasting\loot_tables\blocks\amethyst_bricks.json -7c9c94d5b6b570d25eff32d4fa2ecc1e842e5231 data\hexcasting\loot_tables\blocks\quenched_allay_tiles.json -a62ffbcec2aa40172e05cd9fcd8e70e295d008e9 data\hexcasting\loot_tables\blocks\edified_fence_gate.json -1c6b077aae560e780be29e74ddcd4b0ca10ce3cf data\hexcasting\loot_tables\blocks\impetus\empty.json +// 1.20.1 2024-08-27T12:42:38.112410929 Hex Casting/Loot Tables +1dd4268edf7d6fa247013ab45541c7bfb915eef8 data/hexcasting/loot_tables/blocks/amethyst_bricks_small.json +601384d888edab27efe4a33027bb557eb7cb6ca2 data/hexcasting/loot_tables/blocks/edified_log_purple.json +2c9af74a82ca462e5986354966d5a0a1fd5a2083 data/hexcasting/loot_tables/blocks/slate_tiles.json +7c9c94d5b6b570d25eff32d4fa2ecc1e842e5231 data/hexcasting/loot_tables/blocks/quenched_allay_tiles.json +ecaeb4d5703a7aa206627ed38ee71aeb7e93d688 data/hexcasting/loot_tables/blocks/impetus/rightclick.json +a4e0194d8966a24531e43e04437cdb2a96456898 data/hexcasting/loot_tables/blocks/edified_tile.json +847bc3ead8a88a8f210a24e7732c28d50aa2f5dc data/hexcasting/loot_tables/blocks/edified_planks.json +92331eb19422730ffda0a3e52427a75aa1f7aff2 data/hexcasting/loot_tables/blocks/ancient_scroll_paper_lantern.json +4efd95d408d050c36ff21b18f3c37116491fef92 data/hexcasting/loot_tables/blocks/directrix/redstone.json +8c6c0486170537d73b923a2b9f83722107fc8716 data/hexcasting/loot_tables/blocks/edified_log_aventurine.json +ab86e126a704550d3f21c0b43f99fdc2665e4b09 data/hexcasting/loot_tables/blocks/slate_amethyst_tiles.json +7123b1a0469d7bd5bf8a2772182d222bf354df1a data/hexcasting/loot_tables/blocks/slate_bricks_small.json +b6c23fdde4f2c22c81f008604d5ff1c32ca8eb61 data/hexcasting/loot_tables/blocks/amethyst_tiles.json +b706c8a064f717c57104c48ea42aa860b45cf7a4 data/hexcasting/loot_tables/blocks/amethyst_dust_block.json +6eecc98b606d7ea5ec6f4c1fa4f63f7c1eba9223 data/hexcasting/loot_tables/blocks/slate_amethyst_bricks.json +b19ac49146149555038e6d2e06200d514df1ef43 data/hexcasting/loot_tables/blocks/akashic_bookshelf.json +9ff760d5db5628328ea9274c98e18a08f1ab983e data/hexcasting/loot_tables/blocks/slate_block.json +2ab674e834184b4e17dc002556d4473cac137445 data/hexcasting/loot_tables/blocks/edified_slab.json +df5496da8e48b61a171bc7a3936495c016cc002e data/hexcasting/loot_tables/blocks/directrix/empty.json +49940d1cb2599212e2837d7ed66c6c66e54f80f8 data/hexcasting/loot_tables/blocks/akashic_record.json +c81a5cb81141ab1fe09dd5dd3a0968b69dfffbd7 data/hexcasting/loot_tables/blocks/stripped_edified_log.json +10cb1b94596ac7131efe3bd5c36c1543ddba9302 data/hexcasting/loot_tables/blocks/impetus/redstone.json +499af9f15cf0a7f16fd2939e5d3af60a8089cc3e data/hexcasting/loot_tables/blocks/slate_bricks.json +147e0739a712a9050856cebcad1757b3f418f647 data/hexcasting/loot_tables/blocks/edified_trapdoor.json +2ad288784b0dc106ace2e6e0a40669f83476c414 data/hexcasting/loot_tables/blocks/slate.json +6c35afda4ca349f3506fe08f86f0afe58a6f2c44 data/hexcasting/loot_tables/blocks/quenched_allay.json +e6ff979aa47877c1b807075c448defd249cd3484 data/hexcasting/loot_tables/blocks/slate_amethyst_pillar.json +55f265961463a89c243ec8ac1970c70185f064a6 data/hexcasting/loot_tables/blocks/edified_button.json +c15d3ced89c882dfe552f84435fcdd560b729567 data/hexcasting/loot_tables/blocks/scroll_paper.json +1c6b077aae560e780be29e74ddcd4b0ca10ce3cf data/hexcasting/loot_tables/blocks/impetus/empty.json +dc4c6d270b8e93d05ac8ddeb1b9dd1d64828ac5d data/hexcasting/loot_tables/blocks/stripped_edified_wood.json +a62ffbcec2aa40172e05cd9fcd8e70e295d008e9 data/hexcasting/loot_tables/blocks/edified_fence_gate.json +cc7313cc33609fe1120baa7b4db631eaa29fbba1 data/hexcasting/loot_tables/blocks/citrine_edified_leaves.json +6920654f50532b5e557646e34edc4872339eb79f data/hexcasting/loot_tables/blocks/edified_log_amethyst.json +849afa706e7479d1c11bb40ae223ae5833e71286 data/hexcasting/loot_tables/blocks/scroll_paper_lantern.json +9905b767be7849e02a8e4ec4170af1bdde4e7fab data/hexcasting/loot_tables/blocks/edified_stairs.json +92528799c8ee13ff26c3c505e4dfb286c30f97c7 data/hexcasting/loot_tables/blocks/akashic_connector.json +45dc91d820caa5c421fe6f2afc7f71e45d6acd4d data/hexcasting/loot_tables/blocks/slate_pillar.json +1a1236e54c24b5aeff05919c73c76151da2cf115 data/hexcasting/loot_tables/blocks/amethyst_sconce.json +74159c21634679a6ab1dde1c181433db8b31c6ae data/hexcasting/loot_tables/blocks/edified_log_citrine.json +30f06db8c1ea74c9f4d95474e412336d065ac888 data/hexcasting/loot_tables/blocks/edified_door.json +95be0cf7f277257671631929462131b6d611119a data/hexcasting/loot_tables/inject/amethyst_cluster.json +bedbc2bd04f79372aedea64214ba2ea49cde9640 data/hexcasting/loot_tables/blocks/amethyst_edified_leaves.json +44658abcf122575878834d276ebcf5d8a6b7b398 data/hexcasting/loot_tables/blocks/aventurine_edified_leaves.json +cf6ff1ed1ee6fdbb05af16468a0a0ced79ac334e data/hexcasting/loot_tables/blocks/amethyst_bricks.json +45ae0ec668a07aa5b33d491377b2978f69f9f019 data/hexcasting/loot_tables/blocks/edified_panel.json +5f8d09e8c759d05cf9c2265ae28ea942cfbbe2be data/hexcasting/loot_tables/blocks/edified_pressure_plate.json +c426245d51f1e0fa0db7c4bfb454284d75506c9c data/hexcasting/loot_tables/blocks/quenched_allay_bricks.json +0b734693c926045b60fb515814b7a6695d0295fc data/hexcasting/loot_tables/blocks/impetus/look.json +d16fa9e366d48646686470c2d1f9bda4db3a1afa data/hexcasting/loot_tables/blocks/ancient_scroll_paper.json +2ac70e3c3600c88b2544d9755fc634216a7a523c data/hexcasting/loot_tables/blocks/edified_wood.json +509ecbb9731e75b63638c6012b2f986f131fd42f data/hexcasting/loot_tables/blocks/slate_amethyst_bricks_small.json +2902c4dae60875a1b2daf0a948a49a3419d8ec9d data/hexcasting/loot_tables/blocks/edified_log.json +434c2a6d2645e56e9a6ca56249ffa84645558e3b data/hexcasting/loot_tables/blocks/quenched_allay_bricks_small.json +65fe724d4c4ba8b0ab7d7a11bf37687413d9119d data/hexcasting/loot_tables/blocks/edified_fence.json +f1145860d80ff053970b1ad4f3b2f5d9f28e7c73 data/hexcasting/loot_tables/blocks/directrix/boolean.json +8ea8fd68719a960c2e132df441564a70c0e376a8 data/hexcasting/loot_tables/blocks/amethyst_pillar.json diff --git a/Fabric/src/generated/resources/.cache/2ba8da2cf2d44ff18dc72cc891b094eca6836a5c b/Fabric/src/generated/resources/.cache/2ba8da2cf2d44ff18dc72cc891b094eca6836a5c index 4ab33a45b7..d7f56c26ff 100644 --- a/Fabric/src/generated/resources/.cache/2ba8da2cf2d44ff18dc72cc891b094eca6836a5c +++ b/Fabric/src/generated/resources/.cache/2ba8da2cf2d44ff18dc72cc891b094eca6836a5c @@ -1,25 +1,25 @@ -// 1.20.1 2024-06-13T19:17:10.5291355 Hex Casting/Tags for minecraft:item -20183cd61968ff6548df2dde1100b6378d68d64b data\minecraft\tags\items\buttons.json -e186f43ed06770e698c886691f91b2c6acdb5a2a data\hexcasting\tags\items\seal_materials.json -38d781b60c5c37dc025d4c7e9ec5aa680f2a5835 data\c\tags\items\gems.json -c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data\minecraft\tags\items\logs.json -5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data\minecraft\tags\items\slabs.json -c72a147bc65d26424df199388969ebd11119aed3 data\hexcasting\tags\items\brainswept_circle_components.json -20183cd61968ff6548df2dde1100b6378d68d64b data\minecraft\tags\items\wooden_buttons.json -c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data\minecraft\tags\items\logs_that_burn.json -e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data\minecraft\tags\items\planks.json -5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data\minecraft\tags\items\wooden_trapdoors.json -e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data\hexcasting\tags\items\edified_planks.json -c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data\hexcasting\tags\items\edified_logs.json -9d18fb7a889031a704ca0e553600e1d6f8c3759d data\hexcasting\tags\items\directrices.json -24145229528668829a1bcecf18a6377ebd07ccf8 data\hexcasting\tags\items\grants_root_advancement.json -5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data\minecraft\tags\items\trapdoors.json -37cff4ce449b8069b59b2327d78e073fc026d348 data\minecraft\tags\items\wooden_pressure_plates.json -4461ef6db41a675fd077dd833cfd0ea537e755be data\c\tags\items\amethyst_dusts.json -5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data\minecraft\tags\items\wooden_slabs.json -5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data\minecraft\tags\items\leaves.json -fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data\minecraft\tags\items\doors.json -fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data\minecraft\tags\items\wooden_doors.json -bdb90cee0e88e02f0b98f12d5dd212adfaca9afd data\hexcasting\tags\items\impeti.json -5928bad07d3872bb60f29ef4f3c885c8e1967c20 data\hexcasting\tags\items\phial_base.json -30780136e6469a01369d7e278998edb6d7f6a16b data\hexcasting\tags\items\staves.json +// 1.20.1 2024-08-27T12:42:38.116625477 Hex Casting/Tags for minecraft:item +5928bad07d3872bb60f29ef4f3c885c8e1967c20 data/hexcasting/tags/items/phial_base.json +fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/items/wooden_doors.json +fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/items/doors.json +37cff4ce449b8069b59b2327d78e073fc026d348 data/minecraft/tags/items/wooden_pressure_plates.json +30780136e6469a01369d7e278998edb6d7f6a16b data/hexcasting/tags/items/staves.json +20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/items/wooden_buttons.json +c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data/hexcasting/tags/items/edified_logs.json +e186f43ed06770e698c886691f91b2c6acdb5a2a data/hexcasting/tags/items/seal_materials.json +4461ef6db41a675fd077dd833cfd0ea537e755be data/c/tags/items/amethyst_dusts.json +5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/items/trapdoors.json +e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/minecraft/tags/items/planks.json +c72a147bc65d26424df199388969ebd11119aed3 data/hexcasting/tags/items/brainswept_circle_components.json +5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/items/wooden_trapdoors.json +bdb90cee0e88e02f0b98f12d5dd212adfaca9afd data/hexcasting/tags/items/impeti.json +e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/hexcasting/tags/items/edified_planks.json +20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/items/buttons.json +38d781b60c5c37dc025d4c7e9ec5aa680f2a5835 data/c/tags/items/gems.json +c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data/minecraft/tags/items/logs_that_burn.json +24145229528668829a1bcecf18a6377ebd07ccf8 data/hexcasting/tags/items/grants_root_advancement.json +5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data/minecraft/tags/items/leaves.json +9d18fb7a889031a704ca0e553600e1d6f8c3759d data/hexcasting/tags/items/directrices.json +c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data/minecraft/tags/items/logs.json +5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/items/slabs.json +5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/items/wooden_slabs.json diff --git a/Fabric/src/generated/resources/.cache/3cb4ab563deee432e7d307024048f57946bafb1c b/Fabric/src/generated/resources/.cache/3cb4ab563deee432e7d307024048f57946bafb1c index b98bee8dbf..1e7f2dc25b 100644 --- a/Fabric/src/generated/resources/.cache/3cb4ab563deee432e7d307024048f57946bafb1c +++ b/Fabric/src/generated/resources/.cache/3cb4ab563deee432e7d307024048f57946bafb1c @@ -1,4 +1,4 @@ -// 1.20.1 2024-06-13T19:17:10.5351337 Hex Casting/Tags for hexcasting:action -6fe30f41e2bcd48589caab26d210a513dce1ab7c data\hexcasting\tags\action\requires_enlightenment.json -6fe30f41e2bcd48589caab26d210a513dce1ab7c data\hexcasting\tags\action\per_world_pattern.json -6fe30f41e2bcd48589caab26d210a513dce1ab7c data\hexcasting\tags\action\can_start_enlighten.json +// 1.20.1 2024-08-27T12:42:38.120411259 Hex Casting/Tags for hexcasting:action +6fe30f41e2bcd48589caab26d210a513dce1ab7c data/hexcasting/tags/action/per_world_pattern.json +6fe30f41e2bcd48589caab26d210a513dce1ab7c data/hexcasting/tags/action/requires_enlightenment.json +6fe30f41e2bcd48589caab26d210a513dce1ab7c data/hexcasting/tags/action/can_start_enlighten.json diff --git a/Fabric/src/generated/resources/.cache/812fdb58b7018b2d5c5af7da57a2b1857fa66794 b/Fabric/src/generated/resources/.cache/812fdb58b7018b2d5c5af7da57a2b1857fa66794 index cb9ce27405..e7b75bcd42 100644 --- a/Fabric/src/generated/resources/.cache/812fdb58b7018b2d5c5af7da57a2b1857fa66794 +++ b/Fabric/src/generated/resources/.cache/812fdb58b7018b2d5c5af7da57a2b1857fa66794 @@ -1,32 +1,33 @@ -// 1.20.1 2024-06-13T19:17:10.5266238 Hex Casting/Tags for minecraft:block -c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data\minecraft\tags\blocks\logs_that_burn.json -7e1e353cb7f561f086898f991ece48e047991934 data\minecraft\tags\blocks\fence_gates.json -e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data\hexcasting\tags\blocks\edified_planks.json -7e1e353cb7f561f086898f991ece48e047991934 data\minecraft\tags\blocks\unstable_bottom_center.json -357eddf3cee6f16725bed0701d57b2ca3097d74d data\minecraft\tags\blocks\mineable\shovel.json -c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data\minecraft\tags\blocks\logs.json -37cff4ce449b8069b59b2327d78e073fc026d348 data\minecraft\tags\blocks\wooden_pressure_plates.json -37cff4ce449b8069b59b2327d78e073fc026d348 data\minecraft\tags\blocks\pressure_plates.json -20183cd61968ff6548df2dde1100b6378d68d64b data\minecraft\tags\blocks\wooden_buttons.json -7acae0c88f5ead65339db1b11b16f60214434c86 data\minecraft\tags\blocks\wooden_fences.json -5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data\minecraft\tags\blocks\trapdoors.json -5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data\minecraft\tags\blocks\wooden_slabs.json -fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data\minecraft\tags\blocks\wooden_doors.json -c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data\hexcasting\tags\blocks\edified_logs.json -6ae561f7399e39ffa0e97bd0569aeffa9eabff6a data\hexcasting\tags\blocks\water_plants.json -e8d5ef7eabb567228b279b2419e4f042082d7491 data\minecraft\tags\blocks\fences.json -c72a147bc65d26424df199388969ebd11119aed3 data\hexcasting\tags\blocks\brainswept_circle_components.json -8cd7a960fd719f200b0bf38100cd17c73b66d39c data\minecraft\tags\blocks\mineable\pickaxe.json -5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data\minecraft\tags\blocks\mineable\hoe.json -fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data\minecraft\tags\blocks\doors.json -e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data\minecraft\tags\blocks\planks.json -5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data\minecraft\tags\blocks\leaves.json -281cb08b9b68ef049820c4f3f36b40820044681e data\minecraft\tags\blocks\stairs.json -9d18fb7a889031a704ca0e553600e1d6f8c3759d data\hexcasting\tags\blocks\directrices.json -281cb08b9b68ef049820c4f3f36b40820044681e data\minecraft\tags\blocks\wooden_stairs.json -6f52ca5e42991af6d7b829f626010ce304277464 data\minecraft\tags\blocks\crystal_sound_blocks.json -5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data\minecraft\tags\blocks\wooden_trapdoors.json -20183cd61968ff6548df2dde1100b6378d68d64b data\minecraft\tags\blocks\buttons.json -bdb90cee0e88e02f0b98f12d5dd212adfaca9afd data\hexcasting\tags\blocks\impeti.json -5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data\minecraft\tags\blocks\slabs.json -643994ee757a533cfb5001689e0f0263956b8a35 data\minecraft\tags\blocks\mineable\axe.json +// 1.20.1 2024-08-27T12:42:38.115300691 Hex Casting/Tags for minecraft:block +c72a147bc65d26424df199388969ebd11119aed3 data/hexcasting/tags/blocks/brainswept_circle_components.json +357eddf3cee6f16725bed0701d57b2ca3097d74d data/minecraft/tags/blocks/mineable/shovel.json +20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/blocks/buttons.json +8cd7a960fd719f200b0bf38100cd17c73b66d39c data/minecraft/tags/blocks/mineable/pickaxe.json +643994ee757a533cfb5001689e0f0263956b8a35 data/minecraft/tags/blocks/mineable/axe.json +5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data/minecraft/tags/blocks/mineable/hoe.json +6ae561f7399e39ffa0e97bd0569aeffa9eabff6a data/hexcasting/tags/blocks/water_plants.json +e8d5ef7eabb567228b279b2419e4f042082d7491 data/minecraft/tags/blocks/fences.json +c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data/minecraft/tags/blocks/logs_that_burn.json +eba53f6c7645de4ef5ffb1e10ef34a4c23e98887 data/hexcasting/tags/blocks/cheap_to_break_block.json +7e1e353cb7f561f086898f991ece48e047991934 data/minecraft/tags/blocks/unstable_bottom_center.json +5f3b600b4fd98744bd08c993ce7bcb9c2f195cd2 data/minecraft/tags/blocks/leaves.json +281cb08b9b68ef049820c4f3f36b40820044681e data/minecraft/tags/blocks/wooden_stairs.json +6f52ca5e42991af6d7b829f626010ce304277464 data/minecraft/tags/blocks/crystal_sound_blocks.json +5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/blocks/trapdoors.json +37cff4ce449b8069b59b2327d78e073fc026d348 data/minecraft/tags/blocks/wooden_pressure_plates.json +20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/blocks/wooden_buttons.json +5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/blocks/wooden_trapdoors.json +7acae0c88f5ead65339db1b11b16f60214434c86 data/minecraft/tags/blocks/wooden_fences.json +fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/blocks/wooden_doors.json +7e1e353cb7f561f086898f991ece48e047991934 data/minecraft/tags/blocks/fence_gates.json +c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data/minecraft/tags/blocks/logs.json +c562b4be24d0b6b13f3c65599d3bfa3bf2c4ce21 data/hexcasting/tags/blocks/edified_logs.json +5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/blocks/slabs.json +e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/minecraft/tags/blocks/planks.json +281cb08b9b68ef049820c4f3f36b40820044681e data/minecraft/tags/blocks/stairs.json +bdb90cee0e88e02f0b98f12d5dd212adfaca9afd data/hexcasting/tags/blocks/impeti.json +9d18fb7a889031a704ca0e553600e1d6f8c3759d data/hexcasting/tags/blocks/directrices.json +37cff4ce449b8069b59b2327d78e073fc026d348 data/minecraft/tags/blocks/pressure_plates.json +fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/blocks/doors.json +5bbfd513fd2eb2090b0c2d1ec33504deb79d53b9 data/minecraft/tags/blocks/wooden_slabs.json +e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/hexcasting/tags/blocks/edified_planks.json diff --git a/Fabric/src/generated/resources/.cache/c70ef2fe5da52437c1f53bcc9ea0e416f16bcc0b b/Fabric/src/generated/resources/.cache/c70ef2fe5da52437c1f53bcc9ea0e416f16bcc0b index c07a79c63a..1a07bbdc44 100644 --- a/Fabric/src/generated/resources/.cache/c70ef2fe5da52437c1f53bcc9ea0e416f16bcc0b +++ b/Fabric/src/generated/resources/.cache/c70ef2fe5da52437c1f53bcc9ea0e416f16bcc0b @@ -1,218 +1,218 @@ -// 1.20.1 2024-06-13T19:17:10.5301427 Hex Casting/Recipes -7522be58b09554a3f1a54d5b2343c3eab01447a3 data\hexcasting\recipes\dye_colorizer_magenta.json -8b7136c206b799a2e394aa02316b0509674ff64f data\hexcasting\advancements\recipes\tools\staff\bamboo.json -92bdf87687d8823036fae6bd01782c653831286b data\hexcasting\recipes\brainsweep\impetus_look.json -5e28e2c352366720ce91b73f8c8c38e217f7198d data\hexcasting\recipes\edified_fence_gate.json -ea63e49709bd80cb9f4cd1fe13e9bd0281101c9a data\hexcasting\recipes\slate.json -3608f0ec056f2c5d29a9a89305218497fd2c4383 data\hexcasting\recipes\stonecutting\amethyst_tiles.json -0f2e63a9361d18aac764f6a4a4f13b9b862ac2ee data\hexcasting\recipes\compat\create\crushing\amethyst_shard.json -12bd3d04c791ef16aad5e992f038d6726229a436 data\hexcasting\advancements\recipes\tools\artifact.json -45915b542d8070f2502a4047218679b08033b12d data\hexcasting\advancements\recipes\decorations\scroll_paper_lantern.json -2c292e12b5e85b1701740c222e5c5465799ad1dc data\hexcasting\recipes\pride_colorizer_aroace.json -78958099bf4337ad281580d90f434b3074ad18c8 data\hexcasting\recipes\pride_colorizer_genderqueer.json -b84c113ef5321c9df9ac9080de03e8d8639feab2 data\hexcasting\advancements\recipes\misc\pride_colorizer_genderqueer.json -c2ef04b311251b4eb22320b2f5313c54533a9974 data\hexcasting\advancements\recipes\tools\staff\birch.json -499c5c09e3772989350f9ab3264b8692449a6dea data\hexcasting\advancements\recipes\misc\pride_colorizer_gay.json -f08a0aee92b281ae325d907e6fe4a3b03980f2aa data\hexcasting\advancements\recipes\tools\staff\edified.json -42b8e462de1d7006de3a7658757377450e773107 data\hexcasting\advancements\recipes\misc\dye_colorizer_blue.json -838b91c33a72a58aa286607eaaa17cdd6b4c90ba data\hexcasting\recipes\amethyst_sconce.json -8f7b81add0153ad94900acc66cd8174ae7115f64 data\hexcasting\advancements\recipes\building_blocks\slate_block_from_slates.json -b624d103d944a8a1d4d8a9e85c198a5492b476f8 data\hexcasting\advancements\recipes\redstone\edified_trapdoor.json -0e792d49c81d2164e827d1bdedaa0fa358dfc437 data\hexcasting\advancements\recipes\misc\pride_colorizer_aromantic.json -151875101066f7af5788c7a2e1c6b342971a546a data\hexcasting\recipes\compat\farmersdelight\cutting\akashic_wood.json -7f2f29981df2ca4464ee0250180e670f5331f65b data\hexcasting\recipes\dye_colorizer_pink.json -2fff80cd3dabd2bc1744eecd72b2364b0f91c7c1 data\hexcasting\advancements\recipes\misc\dye_colorizer_yellow.json -71d38559bf455ea343ac0237a57db4d3f0833a7c data\hexcasting\advancements\recipes\misc\dye_colorizer_magenta.json -b7084f131b0cdb9c2c698a3c5b3450d69e788d6e data\hexcasting\recipes\dye_colorizer_yellow.json -40ed21dc80d39236ca0e6d2cea60861c637cf931 data\hexcasting\advancements\recipes\misc\pride_colorizer_nonbinary.json -203b7035125390abb4ed77b3a4dca8f8f8f57bc5 data\hexcasting\recipes\dye_colorizer_light_gray.json -2003fed3aa4eb622b6b07a9e65946fb40be14420 data\hexcasting\advancements\recipes\brainsweep\brainsweep\impetus_rightclick.json -fb852d8e4bcfa7b75f41a6ac7dc1e76b00d95fb1 data\hexcasting\advancements\recipes\misc\dye_colorizer_red.json -e9166f40c8797cdbf3d8062dfa35c74f850f1000 data\hexcasting\advancements\recipes\misc\dye_colorizer_white.json -04902d4eca30560bc601a8196d82f74f3fa5b191 data\hexcasting\recipes\dynamicseal_spellbook.json -fb486df96798724da2fcc0df5706f19bc1ff94dc data\hexcasting\advancements\recipes\misc\dye_colorizer_light_blue.json -ed5c690324e3d9b55599f00f078ae225072a2e7f data\hexcasting\recipes\brainsweep\impetus_rightclick.json -98c0843e6a83b91820f1c720e206295eec20ff95 data\hexcasting\recipes\ancient_scroll_paper.json -9ea4fe5272ce2241d98f30359f55cfc1936c7b48 data\hexcasting\advancements\recipes\tools\staff\cherry.json -e6a592721234448f2ee7ec402bca10a9b78b4677 data\hexcasting\advancements\recipes\decorations\slate.json -775560efa36581389c0319435bda035be262ed4f data\hexcasting\advancements\recipes\building_blocks\edified_stairs.json -bc8fe4d2f55fe119b0b146a71782a3d4788380b1 data\create\recipes\crushing\amethyst_block.json -31ec6474ddae967a6c1dadf9be8292d375510364 data\hexcasting\advancements\recipes\building_blocks\edified_tile.json -5401828f85e709b5817ecc8464dc63e536a730dc data\hexcasting\recipes\staff\cherry.json -4aaefc65af5fe69d312247fdda7d983edf8dcd9a data\hexcasting\recipes\pride_colorizer_intersex.json -410bfde90cb977db3f13814e94484fa11fca7cfc data\hexcasting\recipes\thought_knot.json -011f8daf15148d4b77686c6d382d8f5c288a333d data\hexcasting\advancements\recipes\building_blocks\ancient_scroll_paper.json -c1541738df1ee41c362ad3b9c3a9f0e181bd5c62 data\hexcasting\recipes\pride_colorizer_plural.json -8815ea5d8d7379062e050adc5736cc579c3bdd9e data\hexcasting\recipes\edified_stairs.json -1ad54df5eaee3d1e810d2c91bd03f626084e30b6 data\hexcasting\recipes\edified_trapdoor.json -903cbe4d4c4e5abcd5e006f9d0237e8c596228ba data\hexcasting\recipes\edified_tile.json -5a90084c03d6e8424872870c8b65f4771b447f03 data\hexcasting\recipes\brainsweep\budding_amethyst.json -27dc4a1647f264c45b27f5552fd9403a02853484 data\hexcasting\advancements\recipes\tools\spellbook.json -09096a40275b6c49d4b4e6984869aa43b34712c3 data\hexcasting\recipes\dynamicseal_focus.json -b300f7729e75614fce412457f6717686680f81da data\hexcasting\recipes\sub_sandwich.json -eb9ebf77f0daa32f665a60888fcda19c940f0b2f data\hexcasting\advancements\recipes\misc\pride_colorizer_demigirl.json -5d6d73e16a36da5f9df6a7b8ac859181d401766d data\hexcasting\recipes\uuid_colorizer.json -de38d15e7a91c77df24c1dc954b3e98ee197876f data\hexcasting\recipes\focus.json -8e48c680b38666c2e7da71fbe4ceddf5d99a5cbc data\hexcasting\advancements\recipes\food\sub_sandwich.json -0038883bd294cc8a1b324d6782478d5e37b4dbf9 data\hexcasting\advancements\recipes\misc\dye_colorizer_pink.json -55ea553a96e1d6a54385890f7c48fe7b2bed6871 data\hexcasting\advancements\recipes\tools\trinket.json -f0e71ae8c6a9170669f44096a55a875d11497c56 data\hexcasting\recipes\staff\warped.json -93ed0491548920bc75797d18501c750ef07fe3ea data\hexcasting\advancements\recipes\misc\pride_colorizer_bisexual.json -49e706193bb57a957091e419bd0d8aa58135da1f data\hexcasting\recipes\dye_colorizer_green.json -648f1862fde1dd8ade80b2991b8c8e3991389e95 data\hexcasting\recipes\dye_colorizer_light_blue.json -a3130e3098e35b75afae4f31996d9ab7468e0bc3 data\hexcasting\advancements\recipes\tools\thought_knot.json -daa7b13d5370f4306f8cdf3037fc346e8918950a data\hexcasting\recipes\dye_colorizer_brown.json -db5ae3a2fda235cf1c83fd83e0026a262e668217 data\hexcasting\advancements\recipes\building_blocks\edified_slab.json -0b951ce7b9d1bfb07ae012b12225b595d36c6e66 data\hexcasting\recipes\amethyst_dust_packing.json -c4b985635c3b1a519d7a83da65daba5bdd3a5f59 data\hexcasting\advancements\recipes\decorations\ageing_scroll_paper_lantern.json -095aeb2882c6849f10fb6536e7c780790778e5e7 data\hexcasting\recipes\staff\jungle.json -2c56c267e23e75d5a3b9358d424d69642e001b50 data\hexcasting\recipes\decompose_quenched_shard\dust.json -7aa3bf4a3d6fb92743b29dfe89d50537fefc0db9 data\hexcasting\advancements\recipes\misc\pride_colorizer_intersex.json -3bf96944a8eed8b8d3f5d96b609297727c078cb7 data\hexcasting\advancements\recipes\misc\dye_colorizer_purple.json -a0b87b1b21506708d09c9295b7afc13de6b1fce6 data\hexcasting\recipes\pride_colorizer_aromantic.json -e0609202271e402d8ae58e4f8eaf11dcdda10a9e data\hexcasting\recipes\brainsweep\akashic_record.json -e765ee2bd324240e8ed3d625be431de3281f0070 data\hexcasting\recipes\dye_colorizer_gray.json -dcc9bf721dd40724abcc69f1f7e8a1610dbf88f3 data\hexcasting\recipes\compat\farmersdelight\cutting\akashic_door.json -afb422ad4a918ee0161bf077f09475bb1da2b4eb data\hexcasting\recipes\amethyst_dust_unpacking.json -7baf0777533737aef68bcac36944943b77138d29 data\hexcasting\recipes\edified_button.json -a8d604ba059d54502837809815d3ac9bbcaa89bf data\hexcasting\advancements\recipes\redstone\akashic_bookshelf.json -1b570b35288be9f6faab1536d6e45cb52eb088c0 data\hexcasting\advancements\recipes\tools\staff\dark_oak.json -b6720c1c73455ad817bac9b5ca2ca045c5c4050c data\hexcasting\recipes\pride_colorizer_agender.json -c43fb770003c8d882fd9c1e7d1ecb5f196cba1ab data\hexcasting\recipes\cypher.json -3b03fdae3896212a0b8b9b3a2d4880d197e67d2d data\hexcasting\recipes\jeweler_hammer.json -7166cd4355d11c209bc7749bc862caddcfd795fb data\hexcasting\recipes\dye_colorizer_cyan.json -ef96ae9709ec931ce6b6af8a539f9bc483236449 data\hexcasting\recipes\scroll_medium.json -6f2634e5588aede8e29157ecc859652d8a9f4065 data\hexcasting\advancements\recipes\misc\dye_colorizer_orange.json -41a570f970c9af8229cb1140a11a5220fac00957 data\hexcasting\advancements\recipes\tools\staff\spruce.json -8f515bf8ccea70b3d88845ed83966dc0c66082f6 data\hexcasting\advancements\recipes\tools\staff\oak.json -30352d8ad510768770bb1b2d378959b7a502f825 data\hexcasting\advancements\recipes\brainsweep\brainsweep\impetus_look.json -ea46e570a43cd3ea1cc78c51d9da45d93944730a data\hexcasting\advancements\recipes\redstone\directrix\empty.json -cedc2889c4f327b18755bbe8c3c595d302e2a9d0 data\hexcasting\recipes\decompose_quenched_shard\shard.json -7ca0f9fc6e8ae1ad08ef5c29a0b279b891f7d8d4 data\hexcasting\advancements\recipes\misc\pride_colorizer_aroace.json -923e7cd200518042f11474713eca9ccad126dab7 data\hexcasting\recipes\staff\spruce.json -6e2dc32f975d987b8dfd329507334f647bceadc0 data\hexcasting\advancements\recipes\tools\staff\mangrove.json -7552df3fc726cc4cdaa88aa4823eff6ce069fb75 data\hexcasting\recipes\slate_block_from_slates.json -5e66982df6a1074c81f381898033b521ca337695 data\hexcasting\recipes\staff\quenched.json -b94bc4dd4a63db10af86c524ba00eae157c1824b data\hexcasting\advancements\recipes\building_blocks\edified_fence_gate.json -1093cccc6b1c45eb91f7c1680ef575a7bffb2744 data\hexcasting\advancements\recipes\building_blocks\edified_planks.json -36d26f34d0405ff2d1e728e5b5174502686e3590 data\hexcasting\advancements\recipes\brainsweep\brainsweep\budding_amethyst.json -441f336edb635e5d8c2a7183906fed1c501f06fd data\hexcasting\recipes\pride_colorizer_bisexual.json -51b047601368a103be166d907633b196d2d8a4e8 data\hexcasting\recipes\compat\farmersdelight\cutting\edified_log.json -ea87956c49dcfabb0d39af45c016130d258181da data\hexcasting\recipes\staff\birch.json -0654e70ed1ed8be20ae3dd9f4955cd14f9fa40d0 data\hexcasting\advancements\recipes\tools\staff\jungle.json -846baaef37844216b57bb9b35e52b1bb6b56b413 data\hexcasting\advancements\recipes\decorations\scroll_small.json -4d941fc399c6b7a470513a572ecd88982823da84 data\hexcasting\advancements\recipes\building_blocks\edified_wood.json -5889e2df2fb4e1ea29f2590b96bb3aa94961a09a data\hexcasting\recipes\scroll.json -ce9d0b976f7cc8ad4a0815bbea6c43115addb90f data\hexcasting\advancements\recipes\building_blocks\scroll_paper.json -b5946314683e5a823b577a18d13fb437a35aafd5 data\hexcasting\recipes\decompose_quenched_shard\charged.json -97062771a426f6e4b9e3bfd6daa62b1d4b3c7039 data\hexcasting\recipes\abacus.json -f482a4349786388cc8f11d5550548f7d60265438 data\hexcasting\recipes\staff\mangrove.json -f4c56ea7143ce92a0ae0b663310e53644a7309f7 data\hexcasting\advancements\recipes\misc\pride_colorizer_pansexual.json -2aa7d74e29a7c5ee4f1b8835cf7c6109eed81d77 data\hexcasting\recipes\brainsweep\quench_allay.json -862f1a61a296a834df8a93dbd5a6cdfa2df15721 data\hexcasting\advancements\recipes\tools\staff\acacia.json -23eff6111b0385b66d3ad5fbabfc625f426517a6 data\hexcasting\advancements\recipes\brainsweep\brainsweep\directrix_redstone.json -af8fe74b624df4a31727347b9826614a66092b0a data\hexcasting\advancements\recipes\misc\pride_colorizer_agender.json -9b7c5220fbaf3e84fa9e81eae322eed5d37b22d3 data\hexcasting\recipes\pride_colorizer_transgender.json -1a9dd55a24f56a4e9467f1117e0898f7e71ade67 data\hexcasting\advancements\recipes\decorations\amethyst_sconce.json -6493676f8ca93a7be8d70e25d69ddad935b3f16b data\hexcasting\advancements\recipes\tools\lens.json -c8f2ad363e4d20054f4e56fde02c8775a45a7169 data\hexcasting\recipes\artifact.json -552c235dc58a46a3e57913c9b9faf3f21abeae32 data\hexcasting\advancements\recipes\building_blocks\stripped_edified_wood.json -b6fa898369ac52cdd9d7f91e3b8a2cb881c3829f data\hexcasting\advancements\recipes\decorations\scroll_medium.json -641d8c38b8109665314fccbebd9068ba10b04118 data\hexcasting\advancements\recipes\misc\dye_colorizer_gray.json -54335e0004423899ad37763a1d8456cc0a6e72a7 data\hexcasting\advancements\recipes\misc\decompose_quenched_shard\charged.json -af9a260c24e0a65eea321f0dd9dd2fa7d648707f data\hexcasting\advancements\recipes\building_blocks\amethyst_dust_packing.json -2b64261bd4aefdc55d35400f25835434f88856cf data\hexcasting\recipes\amethyst_tiles.json -b20be6eb5a8b60567871444e65d773ec9a67ece1 data\hexcasting\recipes\staff\crimson.json -fd2f25b0a71806c96af5a307fad76f66de6210a4 data\hexcasting\advancements\recipes\building_blocks\slate_block.json -5e98cec2084f0cfbb959c3ec39bd85a3369f443b data\hexcasting\advancements\recipes\tools\abacus.json -b10d590e918e35b16578a8b739a1c4e7e2202e16 data\hexcasting\advancements\recipes\misc\dye_colorizer_cyan.json -e536791d0c6fb48206e6e30d56879eaf0a9e4bd7 data\hexcasting\recipes\akashic_bookshelf.json -e11aeded7f5d3fdd224627c67661bbd993901703 data\hexcasting\recipes\edified_pressure_plate.json -b16ff5314d457bc7e9e224e102d1e04ce3a62361 data\hexcasting\recipes\brainsweep\directrix_redstone.json -f1bae034d27d218bf262a8c777b787d232489f16 data\hexcasting\recipes\lens.json -a8cab28cffdf495253a320094d202fccc5aeb113 data\hexcasting\advancements\recipes\decorations\ancient_scroll_paper_lantern.json -157ee5fba985bbd01a87f44578890dab5489a8e5 data\hexcasting\advancements\recipes\misc\dye_colorizer_green.json -494aa470790ae46baebbf24ee5b76f5885c1af1a data\hexcasting\recipes\ageing_scroll_paper_lantern.json -a1f9df0537c0ef33a1164cf94e8ff4b1094f889f data\hexcasting\advancements\recipes\tools\staff\warped.json -d6b7a9392320c11866b3f139f97977dc9f55bc47 data\hexcasting\recipes\scroll_small.json -1d1e73244fb3da633d8a5f84bad93c6022a94368 data\hexcasting\advancements\recipes\misc\pride_colorizer_demiboy.json -f64fa00d85a9abb24e89b0d2c9f818001371f5e6 data\hexcasting\recipes\slate_block.json -0864e8b86bdad0bf9ab2ddeb0cd5a182808b5a0a data\hexcasting\recipes\default_colorizer.json -5fab1b9c93304a53a4c305b511704458e4593444 data\hexcasting\recipes\pride_colorizer_demigirl.json -72447ac69a0d85f91064180d3c852040a9e33832 data\hexcasting\recipes\pride_colorizer_asexual.json -8c52917fc7041c483fb6dfe8d16c90f096f2beaf data\hexcasting\recipes\compat\farmersdelight\cutting\edified_log_amethyst.json -d47352426739a0fc500a385d820d767a307e1d16 data\hexcasting\advancements\recipes\misc\dye_colorizer_black.json -c03c81dc123294472e8bb6f836c319e96f8db4f5 data\hexcasting\advancements\recipes\building_blocks\edified_fence.json -233aeedc73173427e7b2287772a4f914f97b072c data\hexcasting\recipes\dye_colorizer_red.json -7d71eb93bbb0856167cf4521283e39f0048078ee data\hexcasting\advancements\recipes\redstone\edified_button.json -bd63b845e02ee4b1b9abe168a196335ccbed1ca5 data\hexcasting\recipes\scroll_paper_lantern.json -14f3b217e150efbbff329d67aec96f818a1da99c data\hexcasting\recipes\dye_colorizer_purple.json -170af3c83a45f9550827cc48e4bb5a621d06d685 data\hexcasting\advancements\recipes\misc\pride_colorizer_transgender.json -d7de5d626fd799a2522af36f0c62c52fe490e6d2 data\hexcasting\recipes\edified_door.json -ee5db13cbb33d9c62bcb1eb645e2c4bea97ad44a data\hexcasting\advancements\recipes\building_blocks\amethyst_dust_unpacking.json -417695497a95436186c1a4ed842d7975d754f9eb data\hexcasting\recipes\stripped_edified_wood.json -aa7558ec1baf6070efbe448d886e20e964e33f96 data\hexcasting\advancements\recipes\brainsweep\brainsweep\quench_allay.json -06402fb37fe4bb05918d13dbfdb89f4c2b67f3ec data\hexcasting\advancements\recipes\tools\cypher.json -7e1a5a873d655e0efba80f22ae9b1de4f248e67a data\hexcasting\advancements\recipes\misc\decompose_quenched_shard\shard.json -0aaf55492e850d2bb1ec2f9986406ca61fde4cfd data\hexcasting\recipes\dye_colorizer_lime.json -1e51cd4f527b3aea4d61d91829e47c191c9c05bb data\hexcasting\recipes\pride_colorizer_gay.json -4a803e049915fd3c7144155ae3a1b05a917ea290 data\hexcasting\recipes\pride_colorizer_pansexual.json -1a0d55e6824c078453c1d44e885a1c51ba707a41 data\hexcasting\recipes\dye_colorizer_white.json -ad647a2078099344ea7f9836a68e1bf8e8119277 data\hexcasting\advancements\recipes\misc\dye_colorizer_brown.json -63189af501442318a90c16d6951e51c0c5d6d4f3 data\hexcasting\recipes\compat\farmersdelight\cutting\edified_log_purple.json -06ca609ba1a32f094cf6edbc989bc9ddaf9d342c data\hexcasting\advancements\recipes\misc\pride_colorizer_genderfluid.json -f77518b6993fe8e31de10af286c33ab72c0f9077 data\hexcasting\advancements\recipes\redstone\impetus\empty.json -c3f7b03fe184ed5e54a8ae06d130adf507b7683d data\hexcasting\recipes\staff\bamboo.json -4003f297be29810cebde4995fb2838c2c68a25ea data\hexcasting\recipes\pride_colorizer_lesbian.json -505eb9192df0b48867e58e09ce36b2259dc6d3e8 data\hexcasting\advancements\recipes\decorations\scroll.json -bc729ac7cf84d29a99cd34d50c152c0b9d20bd7a data\hexcasting\advancements\recipes\brainsweep\brainsweep\akashic_record.json -4680e9dafcf9b60b3485609519d66eefcfd539bc data\hexcasting\recipes\staff\dark_oak.json -0bd7c9f4a9bf29c1b63b2f9378f0a7e2f594b7b7 data\hexcasting\recipes\pride_colorizer_nonbinary.json -963d87d2738686e5398a178b8b369228ff067403 data\hexcasting\recipes\spellbook.json -e691130641b11c0a030a51c71dee0ba356f3b5bd data\hexcasting\recipes\compat\farmersdelight\cutting\edified_log_aventurine.json -faaa9c39dbcdd131c5fbec9ac6a26d6dc5e72053 data\hexcasting\advancements\recipes\misc\dye_colorizer_light_gray.json -f8ee073c1c03f1c11147e4801eeba1f86e5459ba data\hexcasting\recipes\dye_colorizer_blue.json -77369113dc54d1c64b9101861dd8a1930bf1c1c4 data\hexcasting\recipes\edified_wood.json -f81053a3269c1b371be3f8057bad4803056ee0f9 data\hexcasting\recipes\dye_colorizer_orange.json -a366ea3750adc0d336ab8f318c40baed3f9c3eb7 data\hexcasting\recipes\brainsweep\impetus_storedplayer.json -61fafd43af83bdca6720d0993ab71f40a8bebd40 data\hexcasting\advancements\recipes\redstone\akashic_connector.json -0b172aef920da7ba63fe152903ce005c1f5df5f1 data\hexcasting\recipes\staff\acacia.json -9269b17eaae3217422352354fc6006c9808b398c data\hexcasting\recipes\dye_colorizer_black.json -7c479398bbc7185a2c3efd568ad266d8109245bf data\hexcasting\advancements\recipes\redstone\edified_door.json -071e5875b13b60aac33bc97e408d2ca710ac5d02 data\hexcasting\advancements\recipes\building_blocks\stonecutting\amethyst_tiles.json -b29f9d9c14e60ded1148680e2e0ef405b5a3c845 data\hexcasting\advancements\recipes\misc\uuid_colorizer.json -8bea75fdc5e64c464dcf5f85166e767ff44e6dc2 data\hexcasting\advancements\recipes\misc\pride_colorizer_lesbian.json -17a1adf747b99848381ca8e7c5e2cd9dd96c014f data\hexcasting\advancements\recipes\misc\default_colorizer.json -664ce1a38c9b1c9ec21b7e078631e181fc0b2498 data\hexcasting\recipes\staff\edified.json -c6228d72ca800a7dd336e82bbb9b4f20f89de29d data\hexcasting\advancements\recipes\redstone\edified_pressure_plate.json -72f70637aea1c11683e9ee91d83c2807c6ec33a9 data\hexcasting\recipes\compat\farmersdelight\cutting\akashic_trapdoor.json -b6e762c198b9632defd7f8b11287702abecd681d data\hexcasting\recipes\staff\mindsplice.json -2eacf53894ae97712dc3874777e29dce0a0e5540 data\hexcasting\advancements\recipes\misc\pride_colorizer_asexual.json -c1846dd794f5cc5814b8a839291e82512a02ba12 data\hexcasting\advancements\recipes\misc\pride_colorizer_plural.json -71f821f5d24b0bf9ecd860d51e055628fe4af50c data\hexcasting\recipes\edified_panel.json -61e53f02baefd31308e99407d56403dfc18e36e1 data\hexcasting\recipes\akashic_connector.json -8c043c7f6a7911b67324e2fd42f0b3b19a792af3 data\hexcasting\recipes\ancient_scroll_paper_lantern.json -c2a0a489967db4064dfbe1ee6367e132665f3c00 data\hexcasting\recipes\edified_slab.json -004e0694b3bf53140be7df89a4defc255b800619 data\hexcasting\advancements\recipes\tools\focus_rotated.json -8f8773a541bc6a4a6c55a23f4f98b5da4f61a031 data\hexcasting\recipes\scroll_paper.json -55602e415fc1b797439b674050887e9e388558c9 data\hexcasting\advancements\recipes\building_blocks\edified_panel.json -68ab70e0b4e432a3492767c5597ecd836f106714 data\hexcasting\advancements\recipes\tools\staff\mindsplice.json -1b092acfc3115702c74e141492e649d58512f259 data\hexcasting\recipes\staff\oak.json -aa1caae7eba6aede0f179619488e2253b3b723dd data\hexcasting\recipes\focus_rotated.json -2cea013887734cbc4971bcd57e7e4f6a2b25c8e1 data\hexcasting\advancements\recipes\tools\focus.json -5f216dbb7b89fd837e2dd73e3ed41c8d412de234 data\hexcasting\advancements\recipes\misc\decompose_quenched_shard\dust.json -b1f8375aaf0d66035dee720ea59605f69fc0a154 data\hexcasting\recipes\edified_fence.json -ae88fcdecbfbdd0a0fe778467421a3b32d7ed735 data\create\recipes\crushing\amethyst_cluster.json -0ead307e47242ba140584f6bd20088a1fa7c2909 data\hexcasting\recipes\directrix\empty.json -946cde51bbfc2af344b078f6b39389ffc44462f4 data\hexcasting\advancements\recipes\brainsweep\brainsweep\impetus_storedplayer.json -f80dbf59957be175fbcd63224005e09c4cd1a122 data\hexcasting\recipes\compat\farmersdelight\cutting\edified_log_citrine.json -a72a0fcc0f3a81d31b30a7a626aef537796ca73b data\hexcasting\advancements\recipes\tools\staff\quenched.json -a85cfbd7988f5df0b18d160591605aea8e6808d2 data\hexcasting\recipes\trinket.json -24c244e53c7e47b85845d2ee36b1665410cf495a data\hexcasting\recipes\edified_planks.json -fd7c8325fcaa6a718e90c09251b447fb365523d4 data\hexcasting\recipes\pride_colorizer_demiboy.json -2a2f60fb0f63ee278b74c418acf04575304c521f data\hexcasting\advancements\recipes\tools\jeweler_hammer.json -f347f4ce869207e62a7887df1252505a3432e12a data\hexcasting\recipes\pride_colorizer_genderfluid.json -996c8361766377a70e0b5a5caff3076fc6031b0a data\hexcasting\recipes\impetus\empty.json -b90ad4cbffc2e3c01671dfe8bda5e42d9b8a685c data\hexcasting\advancements\recipes\tools\staff\crimson.json -a9111ff52513200af47b79cf98b2e545699497bb data\hexcasting\advancements\recipes\building_blocks\amethyst_tiles.json -4d5e4a6374731b2d0a90c70a5d489703fd966977 data\hexcasting\advancements\recipes\misc\dye_colorizer_lime.json +// 1.20.1 2024-08-27T12:42:38.11755991 Hex Casting/Recipes +f482a4349786388cc8f11d5550548f7d60265438 data/hexcasting/recipes/staff/mangrove.json +b10d590e918e35b16578a8b739a1c4e7e2202e16 data/hexcasting/advancements/recipes/misc/dye_colorizer_cyan.json +7aa3bf4a3d6fb92743b29dfe89d50537fefc0db9 data/hexcasting/advancements/recipes/misc/pride_colorizer_intersex.json +648f1862fde1dd8ade80b2991b8c8e3991389e95 data/hexcasting/recipes/dye_colorizer_light_blue.json +23eff6111b0385b66d3ad5fbabfc625f426517a6 data/hexcasting/advancements/recipes/brainsweep/brainsweep/directrix_redstone.json +a3130e3098e35b75afae4f31996d9ab7468e0bc3 data/hexcasting/advancements/recipes/tools/thought_knot.json +c8f2ad363e4d20054f4e56fde02c8775a45a7169 data/hexcasting/recipes/artifact.json +f80dbf59957be175fbcd63224005e09c4cd1a122 data/hexcasting/recipes/compat/farmersdelight/cutting/edified_log_citrine.json +2fff80cd3dabd2bc1744eecd72b2364b0f91c7c1 data/hexcasting/advancements/recipes/misc/dye_colorizer_yellow.json +9269b17eaae3217422352354fc6006c9808b398c data/hexcasting/recipes/dye_colorizer_black.json +441f336edb635e5d8c2a7183906fed1c501f06fd data/hexcasting/recipes/pride_colorizer_bisexual.json +a72a0fcc0f3a81d31b30a7a626aef537796ca73b data/hexcasting/advancements/recipes/tools/staff/quenched.json +2aa7d74e29a7c5ee4f1b8835cf7c6109eed81d77 data/hexcasting/recipes/brainsweep/quench_allay.json +2c292e12b5e85b1701740c222e5c5465799ad1dc data/hexcasting/recipes/pride_colorizer_aroace.json +5d6d73e16a36da5f9df6a7b8ac859181d401766d data/hexcasting/recipes/uuid_colorizer.json +49e706193bb57a957091e419bd0d8aa58135da1f data/hexcasting/recipes/dye_colorizer_green.json +2cea013887734cbc4971bcd57e7e4f6a2b25c8e1 data/hexcasting/advancements/recipes/tools/focus.json +36d26f34d0405ff2d1e728e5b5174502686e3590 data/hexcasting/advancements/recipes/brainsweep/brainsweep/budding_amethyst.json +daa7b13d5370f4306f8cdf3037fc346e8918950a data/hexcasting/recipes/dye_colorizer_brown.json +b94bc4dd4a63db10af86c524ba00eae157c1824b data/hexcasting/advancements/recipes/building_blocks/edified_fence_gate.json +9ea4fe5272ce2241d98f30359f55cfc1936c7b48 data/hexcasting/advancements/recipes/tools/staff/cherry.json +e0609202271e402d8ae58e4f8eaf11dcdda10a9e data/hexcasting/recipes/brainsweep/akashic_record.json +c3f7b03fe184ed5e54a8ae06d130adf507b7683d data/hexcasting/recipes/staff/bamboo.json +7ca0f9fc6e8ae1ad08ef5c29a0b279b891f7d8d4 data/hexcasting/advancements/recipes/misc/pride_colorizer_aroace.json +4aaefc65af5fe69d312247fdda7d983edf8dcd9a data/hexcasting/recipes/pride_colorizer_intersex.json +641d8c38b8109665314fccbebd9068ba10b04118 data/hexcasting/advancements/recipes/misc/dye_colorizer_gray.json +fd2f25b0a71806c96af5a307fad76f66de6210a4 data/hexcasting/advancements/recipes/building_blocks/slate_block.json +b1f8375aaf0d66035dee720ea59605f69fc0a154 data/hexcasting/recipes/edified_fence.json +ae88fcdecbfbdd0a0fe778467421a3b32d7ed735 data/create/recipes/crushing/amethyst_cluster.json +8b7136c206b799a2e394aa02316b0509674ff64f data/hexcasting/advancements/recipes/tools/staff/bamboo.json +fb852d8e4bcfa7b75f41a6ac7dc1e76b00d95fb1 data/hexcasting/advancements/recipes/misc/dye_colorizer_red.json +5401828f85e709b5817ecc8464dc63e536a730dc data/hexcasting/recipes/staff/cherry.json +54335e0004423899ad37763a1d8456cc0a6e72a7 data/hexcasting/advancements/recipes/misc/decompose_quenched_shard/charged.json +c1846dd794f5cc5814b8a839291e82512a02ba12 data/hexcasting/advancements/recipes/misc/pride_colorizer_plural.json +0ead307e47242ba140584f6bd20088a1fa7c2909 data/hexcasting/recipes/directrix/empty.json +b7084f131b0cdb9c2c698a3c5b3450d69e788d6e data/hexcasting/recipes/dye_colorizer_yellow.json +55ea553a96e1d6a54385890f7c48fe7b2bed6871 data/hexcasting/advancements/recipes/tools/trinket.json +2003fed3aa4eb622b6b07a9e65946fb40be14420 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_rightclick.json +1b092acfc3115702c74e141492e649d58512f259 data/hexcasting/recipes/staff/oak.json +5a90084c03d6e8424872870c8b65f4771b447f03 data/hexcasting/recipes/brainsweep/budding_amethyst.json +61e53f02baefd31308e99407d56403dfc18e36e1 data/hexcasting/recipes/akashic_connector.json +93ed0491548920bc75797d18501c750ef07fe3ea data/hexcasting/advancements/recipes/misc/pride_colorizer_bisexual.json +0f2e63a9361d18aac764f6a4a4f13b9b862ac2ee data/hexcasting/recipes/compat/create/crushing/amethyst_shard.json +c4b985635c3b1a519d7a83da65daba5bdd3a5f59 data/hexcasting/advancements/recipes/decorations/ageing_scroll_paper_lantern.json +b6720c1c73455ad817bac9b5ca2ca045c5c4050c data/hexcasting/recipes/pride_colorizer_agender.json +5f216dbb7b89fd837e2dd73e3ed41c8d412de234 data/hexcasting/advancements/recipes/misc/decompose_quenched_shard/dust.json +903cbe4d4c4e5abcd5e006f9d0237e8c596228ba data/hexcasting/recipes/edified_tile.json +fb486df96798724da2fcc0df5706f19bc1ff94dc data/hexcasting/advancements/recipes/misc/dye_colorizer_light_blue.json +410bfde90cb977db3f13814e94484fa11fca7cfc data/hexcasting/recipes/thought_knot.json +30352d8ad510768770bb1b2d378959b7a502f825 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_look.json +a8cab28cffdf495253a320094d202fccc5aeb113 data/hexcasting/advancements/recipes/decorations/ancient_scroll_paper_lantern.json +af8fe74b624df4a31727347b9826614a66092b0a data/hexcasting/advancements/recipes/misc/pride_colorizer_agender.json +e765ee2bd324240e8ed3d625be431de3281f0070 data/hexcasting/recipes/dye_colorizer_gray.json +a0b87b1b21506708d09c9295b7afc13de6b1fce6 data/hexcasting/recipes/pride_colorizer_aromantic.json +4d941fc399c6b7a470513a572ecd88982823da84 data/hexcasting/advancements/recipes/building_blocks/edified_wood.json +aa1caae7eba6aede0f179619488e2253b3b723dd data/hexcasting/recipes/focus_rotated.json +505eb9192df0b48867e58e09ce36b2259dc6d3e8 data/hexcasting/advancements/recipes/decorations/scroll.json +1d1e73244fb3da633d8a5f84bad93c6022a94368 data/hexcasting/advancements/recipes/misc/pride_colorizer_demiboy.json +71d38559bf455ea343ac0237a57db4d3f0833a7c data/hexcasting/advancements/recipes/misc/dye_colorizer_magenta.json +fd7c8325fcaa6a718e90c09251b447fb365523d4 data/hexcasting/recipes/pride_colorizer_demiboy.json +b5946314683e5a823b577a18d13fb437a35aafd5 data/hexcasting/recipes/decompose_quenched_shard/charged.json +011f8daf15148d4b77686c6d382d8f5c288a333d data/hexcasting/advancements/recipes/building_blocks/ancient_scroll_paper.json +494aa470790ae46baebbf24ee5b76f5885c1af1a data/hexcasting/recipes/ageing_scroll_paper_lantern.json +c6228d72ca800a7dd336e82bbb9b4f20f89de29d data/hexcasting/advancements/recipes/redstone/edified_pressure_plate.json +5889e2df2fb4e1ea29f2590b96bb3aa94961a09a data/hexcasting/recipes/scroll.json +a9111ff52513200af47b79cf98b2e545699497bb data/hexcasting/advancements/recipes/building_blocks/amethyst_tiles.json +e9166f40c8797cdbf3d8062dfa35c74f850f1000 data/hexcasting/advancements/recipes/misc/dye_colorizer_white.json +2c56c267e23e75d5a3b9358d424d69642e001b50 data/hexcasting/recipes/decompose_quenched_shard/dust.json +ea87956c49dcfabb0d39af45c016130d258181da data/hexcasting/recipes/staff/birch.json +98c0843e6a83b91820f1c720e206295eec20ff95 data/hexcasting/recipes/ancient_scroll_paper.json +bc8fe4d2f55fe119b0b146a71782a3d4788380b1 data/create/recipes/crushing/amethyst_block.json +97062771a426f6e4b9e3bfd6daa62b1d4b3c7039 data/hexcasting/recipes/abacus.json +24c244e53c7e47b85845d2ee36b1665410cf495a data/hexcasting/recipes/edified_planks.json +417695497a95436186c1a4ed842d7975d754f9eb data/hexcasting/recipes/stripped_edified_wood.json +7f2f29981df2ca4464ee0250180e670f5331f65b data/hexcasting/recipes/dye_colorizer_pink.json +ea63e49709bd80cb9f4cd1fe13e9bd0281101c9a data/hexcasting/recipes/slate.json +f64fa00d85a9abb24e89b0d2c9f818001371f5e6 data/hexcasting/recipes/slate_block.json +14f3b217e150efbbff329d67aec96f818a1da99c data/hexcasting/recipes/dye_colorizer_purple.json +9b7c5220fbaf3e84fa9e81eae322eed5d37b22d3 data/hexcasting/recipes/pride_colorizer_transgender.json +17a1adf747b99848381ca8e7c5e2cd9dd96c014f data/hexcasting/advancements/recipes/misc/default_colorizer.json +a85cfbd7988f5df0b18d160591605aea8e6808d2 data/hexcasting/recipes/trinket.json +4003f297be29810cebde4995fb2838c2c68a25ea data/hexcasting/recipes/pride_colorizer_lesbian.json +41a570f970c9af8229cb1140a11a5220fac00957 data/hexcasting/advancements/recipes/tools/staff/spruce.json +b300f7729e75614fce412457f6717686680f81da data/hexcasting/recipes/sub_sandwich.json +0b951ce7b9d1bfb07ae012b12225b595d36c6e66 data/hexcasting/recipes/amethyst_dust_packing.json +2b64261bd4aefdc55d35400f25835434f88856cf data/hexcasting/recipes/amethyst_tiles.json +963d87d2738686e5398a178b8b369228ff067403 data/hexcasting/recipes/spellbook.json +6e2dc32f975d987b8dfd329507334f647bceadc0 data/hexcasting/advancements/recipes/tools/staff/mangrove.json +996c8361766377a70e0b5a5caff3076fc6031b0a data/hexcasting/recipes/impetus/empty.json +71f821f5d24b0bf9ecd860d51e055628fe4af50c data/hexcasting/recipes/edified_panel.json +7166cd4355d11c209bc7749bc862caddcfd795fb data/hexcasting/recipes/dye_colorizer_cyan.json +f347f4ce869207e62a7887df1252505a3432e12a data/hexcasting/recipes/pride_colorizer_genderfluid.json +1b570b35288be9f6faab1536d6e45cb52eb088c0 data/hexcasting/advancements/recipes/tools/staff/dark_oak.json +31ec6474ddae967a6c1dadf9be8292d375510364 data/hexcasting/advancements/recipes/building_blocks/edified_tile.json +5e66982df6a1074c81f381898033b521ca337695 data/hexcasting/recipes/staff/quenched.json +45915b542d8070f2502a4047218679b08033b12d data/hexcasting/advancements/recipes/decorations/scroll_paper_lantern.json +946cde51bbfc2af344b078f6b39389ffc44462f4 data/hexcasting/advancements/recipes/brainsweep/brainsweep/impetus_storedplayer.json +1093cccc6b1c45eb91f7c1680ef575a7bffb2744 data/hexcasting/advancements/recipes/building_blocks/edified_planks.json +72447ac69a0d85f91064180d3c852040a9e33832 data/hexcasting/recipes/pride_colorizer_asexual.json +0e792d49c81d2164e827d1bdedaa0fa358dfc437 data/hexcasting/advancements/recipes/misc/pride_colorizer_aromantic.json +b84c113ef5321c9df9ac9080de03e8d8639feab2 data/hexcasting/advancements/recipes/misc/pride_colorizer_genderqueer.json +e6a592721234448f2ee7ec402bca10a9b78b4677 data/hexcasting/advancements/recipes/decorations/slate.json +de38d15e7a91c77df24c1dc954b3e98ee197876f data/hexcasting/recipes/focus.json +157ee5fba985bbd01a87f44578890dab5489a8e5 data/hexcasting/advancements/recipes/misc/dye_colorizer_green.json +c1541738df1ee41c362ad3b9c3a9f0e181bd5c62 data/hexcasting/recipes/pride_colorizer_plural.json +233aeedc73173427e7b2287772a4f914f97b072c data/hexcasting/recipes/dye_colorizer_red.json +12bd3d04c791ef16aad5e992f038d6726229a436 data/hexcasting/advancements/recipes/tools/artifact.json +862f1a61a296a834df8a93dbd5a6cdfa2df15721 data/hexcasting/advancements/recipes/tools/staff/acacia.json +a1f9df0537c0ef33a1164cf94e8ff4b1094f889f data/hexcasting/advancements/recipes/tools/staff/warped.json +b6e762c198b9632defd7f8b11287702abecd681d data/hexcasting/recipes/staff/mindsplice.json +7c479398bbc7185a2c3efd568ad266d8109245bf data/hexcasting/advancements/recipes/redstone/edified_door.json +5fab1b9c93304a53a4c305b511704458e4593444 data/hexcasting/recipes/pride_colorizer_demigirl.json +e536791d0c6fb48206e6e30d56879eaf0a9e4bd7 data/hexcasting/recipes/akashic_bookshelf.json +b90ad4cbffc2e3c01671dfe8bda5e42d9b8a685c data/hexcasting/advancements/recipes/tools/staff/crimson.json +68ab70e0b4e432a3492767c5597ecd836f106714 data/hexcasting/advancements/recipes/tools/staff/mindsplice.json +c2ef04b311251b4eb22320b2f5313c54533a9974 data/hexcasting/advancements/recipes/tools/staff/birch.json +1a0d55e6824c078453c1d44e885a1c51ba707a41 data/hexcasting/recipes/dye_colorizer_white.json +8f8773a541bc6a4a6c55a23f4f98b5da4f61a031 data/hexcasting/recipes/scroll_paper.json +bc729ac7cf84d29a99cd34d50c152c0b9d20bd7a data/hexcasting/advancements/recipes/brainsweep/brainsweep/akashic_record.json +4a803e049915fd3c7144155ae3a1b05a917ea290 data/hexcasting/recipes/pride_colorizer_pansexual.json +0654e70ed1ed8be20ae3dd9f4955cd14f9fa40d0 data/hexcasting/advancements/recipes/tools/staff/jungle.json +8bea75fdc5e64c464dcf5f85166e767ff44e6dc2 data/hexcasting/advancements/recipes/misc/pride_colorizer_lesbian.json +5e98cec2084f0cfbb959c3ec39bd85a3369f443b data/hexcasting/advancements/recipes/tools/abacus.json +0b172aef920da7ba63fe152903ce005c1f5df5f1 data/hexcasting/recipes/staff/acacia.json +7e1a5a873d655e0efba80f22ae9b1de4f248e67a data/hexcasting/advancements/recipes/misc/decompose_quenched_shard/shard.json +3608f0ec056f2c5d29a9a89305218497fd2c4383 data/hexcasting/recipes/stonecutting/amethyst_tiles.json +2a2f60fb0f63ee278b74c418acf04575304c521f data/hexcasting/advancements/recipes/tools/jeweler_hammer.json +8c043c7f6a7911b67324e2fd42f0b3b19a792af3 data/hexcasting/recipes/ancient_scroll_paper_lantern.json +4680e9dafcf9b60b3485609519d66eefcfd539bc data/hexcasting/recipes/staff/dark_oak.json +095aeb2882c6849f10fb6536e7c780790778e5e7 data/hexcasting/recipes/staff/jungle.json +b624d103d944a8a1d4d8a9e85c198a5492b476f8 data/hexcasting/advancements/recipes/redstone/edified_trapdoor.json +eb9ebf77f0daa32f665a60888fcda19c940f0b2f data/hexcasting/advancements/recipes/misc/pride_colorizer_demigirl.json +8f7b81add0153ad94900acc66cd8174ae7115f64 data/hexcasting/advancements/recipes/building_blocks/slate_block_from_slates.json +838b91c33a72a58aa286607eaaa17cdd6b4c90ba data/hexcasting/recipes/amethyst_sconce.json +664ce1a38c9b1c9ec21b7e078631e181fc0b2498 data/hexcasting/recipes/staff/edified.json +7522be58b09554a3f1a54d5b2343c3eab01447a3 data/hexcasting/recipes/dye_colorizer_magenta.json +ee5db13cbb33d9c62bcb1eb645e2c4bea97ad44a data/hexcasting/advancements/recipes/building_blocks/amethyst_dust_unpacking.json +203b7035125390abb4ed77b3a4dca8f8f8f57bc5 data/hexcasting/recipes/dye_colorizer_light_gray.json +f8ee073c1c03f1c11147e4801eeba1f86e5459ba data/hexcasting/recipes/dye_colorizer_blue.json +a366ea3750adc0d336ab8f318c40baed3f9c3eb7 data/hexcasting/recipes/brainsweep/impetus_storedplayer.json +51b047601368a103be166d907633b196d2d8a4e8 data/hexcasting/recipes/compat/farmersdelight/cutting/edified_log.json +f4c56ea7143ce92a0ae0b663310e53644a7309f7 data/hexcasting/advancements/recipes/misc/pride_colorizer_pansexual.json +6f2634e5588aede8e29157ecc859652d8a9f4065 data/hexcasting/advancements/recipes/misc/dye_colorizer_orange.json +f1bae034d27d218bf262a8c777b787d232489f16 data/hexcasting/recipes/lens.json +06402fb37fe4bb05918d13dbfdb89f4c2b67f3ec data/hexcasting/advancements/recipes/tools/cypher.json +ed5c690324e3d9b55599f00f078ae225072a2e7f data/hexcasting/recipes/brainsweep/impetus_rightclick.json +c43fb770003c8d882fd9c1e7d1ecb5f196cba1ab data/hexcasting/recipes/cypher.json +4d5e4a6374731b2d0a90c70a5d489703fd966977 data/hexcasting/advancements/recipes/misc/dye_colorizer_lime.json +0864e8b86bdad0bf9ab2ddeb0cd5a182808b5a0a data/hexcasting/recipes/default_colorizer.json +7d71eb93bbb0856167cf4521283e39f0048078ee data/hexcasting/advancements/recipes/redstone/edified_button.json +72f70637aea1c11683e9ee91d83c2807c6ec33a9 data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_trapdoor.json +1e51cd4f527b3aea4d61d91829e47c191c9c05bb data/hexcasting/recipes/pride_colorizer_gay.json +42b8e462de1d7006de3a7658757377450e773107 data/hexcasting/advancements/recipes/misc/dye_colorizer_blue.json +775560efa36581389c0319435bda035be262ed4f data/hexcasting/advancements/recipes/building_blocks/edified_stairs.json +09096a40275b6c49d4b4e6984869aa43b34712c3 data/hexcasting/recipes/dynamicseal_focus.json +8f515bf8ccea70b3d88845ed83966dc0c66082f6 data/hexcasting/advancements/recipes/tools/staff/oak.json +b29f9d9c14e60ded1148680e2e0ef405b5a3c845 data/hexcasting/advancements/recipes/misc/uuid_colorizer.json +071e5875b13b60aac33bc97e408d2ca710ac5d02 data/hexcasting/advancements/recipes/building_blocks/stonecutting/amethyst_tiles.json +3bf96944a8eed8b8d3f5d96b609297727c078cb7 data/hexcasting/advancements/recipes/misc/dye_colorizer_purple.json +846baaef37844216b57bb9b35e52b1bb6b56b413 data/hexcasting/advancements/recipes/decorations/scroll_small.json +db5ae3a2fda235cf1c83fd83e0026a262e668217 data/hexcasting/advancements/recipes/building_blocks/edified_slab.json +6493676f8ca93a7be8d70e25d69ddad935b3f16b data/hexcasting/advancements/recipes/tools/lens.json +a8d604ba059d54502837809815d3ac9bbcaa89bf data/hexcasting/advancements/recipes/redstone/akashic_bookshelf.json +0aaf55492e850d2bb1ec2f9986406ca61fde4cfd data/hexcasting/recipes/dye_colorizer_lime.json +dcc9bf721dd40724abcc69f1f7e8a1610dbf88f3 data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_door.json +f81053a3269c1b371be3f8057bad4803056ee0f9 data/hexcasting/recipes/dye_colorizer_orange.json +f77518b6993fe8e31de10af286c33ab72c0f9077 data/hexcasting/advancements/recipes/redstone/impetus/empty.json +3b03fdae3896212a0b8b9b3a2d4880d197e67d2d data/hexcasting/recipes/jeweler_hammer.json +d7de5d626fd799a2522af36f0c62c52fe490e6d2 data/hexcasting/recipes/edified_door.json +aa7558ec1baf6070efbe448d886e20e964e33f96 data/hexcasting/advancements/recipes/brainsweep/brainsweep/quench_allay.json +cedc2889c4f327b18755bbe8c3c595d302e2a9d0 data/hexcasting/recipes/decompose_quenched_shard/shard.json +8c52917fc7041c483fb6dfe8d16c90f096f2beaf data/hexcasting/recipes/compat/farmersdelight/cutting/edified_log_amethyst.json +40ed21dc80d39236ca0e6d2cea60861c637cf931 data/hexcasting/advancements/recipes/misc/pride_colorizer_nonbinary.json +ef96ae9709ec931ce6b6af8a539f9bc483236449 data/hexcasting/recipes/scroll_medium.json +61fafd43af83bdca6720d0993ab71f40a8bebd40 data/hexcasting/advancements/recipes/redstone/akashic_connector.json +f08a0aee92b281ae325d907e6fe4a3b03980f2aa data/hexcasting/advancements/recipes/tools/staff/edified.json +7552df3fc726cc4cdaa88aa4823eff6ce069fb75 data/hexcasting/recipes/slate_block_from_slates.json +77369113dc54d1c64b9101861dd8a1930bf1c1c4 data/hexcasting/recipes/edified_wood.json +1ad54df5eaee3d1e810d2c91bd03f626084e30b6 data/hexcasting/recipes/edified_trapdoor.json +ce9d0b976f7cc8ad4a0815bbea6c43115addb90f data/hexcasting/advancements/recipes/building_blocks/scroll_paper.json +af9a260c24e0a65eea321f0dd9dd2fa7d648707f data/hexcasting/advancements/recipes/building_blocks/amethyst_dust_packing.json +923e7cd200518042f11474713eca9ccad126dab7 data/hexcasting/recipes/staff/spruce.json +ad647a2078099344ea7f9836a68e1bf8e8119277 data/hexcasting/advancements/recipes/misc/dye_colorizer_brown.json +0038883bd294cc8a1b324d6782478d5e37b4dbf9 data/hexcasting/advancements/recipes/misc/dye_colorizer_pink.json +170af3c83a45f9550827cc48e4bb5a621d06d685 data/hexcasting/advancements/recipes/misc/pride_colorizer_transgender.json +8815ea5d8d7379062e050adc5736cc579c3bdd9e data/hexcasting/recipes/edified_stairs.json +b6fa898369ac52cdd9d7f91e3b8a2cb881c3829f data/hexcasting/advancements/recipes/decorations/scroll_medium.json +04902d4eca30560bc601a8196d82f74f3fa5b191 data/hexcasting/recipes/dynamicseal_spellbook.json +d6b7a9392320c11866b3f139f97977dc9f55bc47 data/hexcasting/recipes/scroll_small.json +8e48c680b38666c2e7da71fbe4ceddf5d99a5cbc data/hexcasting/advancements/recipes/food/sub_sandwich.json +5e28e2c352366720ce91b73f8c8c38e217f7198d data/hexcasting/recipes/edified_fence_gate.json +004e0694b3bf53140be7df89a4defc255b800619 data/hexcasting/advancements/recipes/tools/focus_rotated.json +faaa9c39dbcdd131c5fbec9ac6a26d6dc5e72053 data/hexcasting/advancements/recipes/misc/dye_colorizer_light_gray.json +55602e415fc1b797439b674050887e9e388558c9 data/hexcasting/advancements/recipes/building_blocks/edified_panel.json +151875101066f7af5788c7a2e1c6b342971a546a data/hexcasting/recipes/compat/farmersdelight/cutting/akashic_wood.json +0bd7c9f4a9bf29c1b63b2f9378f0a7e2f594b7b7 data/hexcasting/recipes/pride_colorizer_nonbinary.json +ea46e570a43cd3ea1cc78c51d9da45d93944730a data/hexcasting/advancements/recipes/redstone/directrix/empty.json +b20be6eb5a8b60567871444e65d773ec9a67ece1 data/hexcasting/recipes/staff/crimson.json +c03c81dc123294472e8bb6f836c319e96f8db4f5 data/hexcasting/advancements/recipes/building_blocks/edified_fence.json +92bdf87687d8823036fae6bd01782c653831286b data/hexcasting/recipes/brainsweep/impetus_look.json +06ca609ba1a32f094cf6edbc989bc9ddaf9d342c data/hexcasting/advancements/recipes/misc/pride_colorizer_genderfluid.json +552c235dc58a46a3e57913c9b9faf3f21abeae32 data/hexcasting/advancements/recipes/building_blocks/stripped_edified_wood.json +c2a0a489967db4064dfbe1ee6367e132665f3c00 data/hexcasting/recipes/edified_slab.json +1a9dd55a24f56a4e9467f1117e0898f7e71ade67 data/hexcasting/advancements/recipes/decorations/amethyst_sconce.json +27dc4a1647f264c45b27f5552fd9403a02853484 data/hexcasting/advancements/recipes/tools/spellbook.json +2eacf53894ae97712dc3874777e29dce0a0e5540 data/hexcasting/advancements/recipes/misc/pride_colorizer_asexual.json +e11aeded7f5d3fdd224627c67661bbd993901703 data/hexcasting/recipes/edified_pressure_plate.json +e691130641b11c0a030a51c71dee0ba356f3b5bd data/hexcasting/recipes/compat/farmersdelight/cutting/edified_log_aventurine.json +7baf0777533737aef68bcac36944943b77138d29 data/hexcasting/recipes/edified_button.json +63189af501442318a90c16d6951e51c0c5d6d4f3 data/hexcasting/recipes/compat/farmersdelight/cutting/edified_log_purple.json +499c5c09e3772989350f9ab3264b8692449a6dea data/hexcasting/advancements/recipes/misc/pride_colorizer_gay.json +b16ff5314d457bc7e9e224e102d1e04ce3a62361 data/hexcasting/recipes/brainsweep/directrix_redstone.json +bd63b845e02ee4b1b9abe168a196335ccbed1ca5 data/hexcasting/recipes/scroll_paper_lantern.json +afb422ad4a918ee0161bf077f09475bb1da2b4eb data/hexcasting/recipes/amethyst_dust_unpacking.json +d47352426739a0fc500a385d820d767a307e1d16 data/hexcasting/advancements/recipes/misc/dye_colorizer_black.json +f0e71ae8c6a9170669f44096a55a875d11497c56 data/hexcasting/recipes/staff/warped.json +78958099bf4337ad281580d90f434b3074ad18c8 data/hexcasting/recipes/pride_colorizer_genderqueer.json diff --git a/Fabric/src/generated/resources/data/hexcasting/tags/blocks/cheap_to_break_block.json b/Fabric/src/generated/resources/data/hexcasting/tags/blocks/cheap_to_break_block.json new file mode 100644 index 0000000000..61cb019a11 --- /dev/null +++ b/Fabric/src/generated/resources/data/hexcasting/tags/blocks/cheap_to_break_block.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "hexcasting:conjured_block", + "hexcasting:conjured_light" + ] +} \ No newline at end of file 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..0b94fa551a 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 @@ -3,6 +3,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; import at.petrak.hexcasting.api.item.IotaHolderItem; +import at.petrak.hexcasting.api.utils.HexUtils; import at.petrak.hexcasting.fabric.cc.HexCardinalComponents; import dev.onyxstudios.cca.api.v3.item.ItemComponent; import net.minecraft.nbt.CompoundTag; @@ -32,6 +33,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); @@ -56,7 +62,12 @@ public Static(ItemStack stack, Function provider) { @Override public @Nullable CompoundTag readIotaTag() { var iota = this.provider.apply(this.stack); - return iota == null ? null : IotaType.serialize(iota); + return iota == null ? null : (CompoundTag) HexUtils.serializeWithCodec(iota, Iota.getCodec()); + } + + @Override + public boolean writeable() { + return false; } @Override 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/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricPlayerRendererMixin.java b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricPlayerRendererMixin.java new file mode 100644 index 0000000000..ec5bd74371 --- /dev/null +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/mixin/client/FabricPlayerRendererMixin.java @@ -0,0 +1,24 @@ +package at.petrak.hexcasting.fabric.mixin.client; + +import at.petrak.hexcasting.client.model.AltioraLayer; +import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(PlayerRenderer.class) +public abstract class FabricPlayerRendererMixin extends LivingEntityRenderer> { + public FabricPlayerRendererMixin(EntityRendererProvider.Context context, PlayerModel entityModel, float f) { + super(context, entityModel, f); + } + + @Inject(method = "", at = @At("TAIL")) + private void addAltiora(EntityRendererProvider.Context ctx, boolean bl, CallbackInfo ci) { + this.addLayer(new AltioraLayer<>((PlayerRenderer)(Object)this, ctx.getModelSet())); + } +} diff --git a/Fabric/src/main/resources/fabricasting.mixins.json b/Fabric/src/main/resources/fabricasting.mixins.json index 5a816cf1ba..f23162f39f 100644 --- a/Fabric/src/main/resources/fabricasting.mixins.json +++ b/Fabric/src/main/resources/fabricasting.mixins.json @@ -22,6 +22,7 @@ "client.FabricMixinGameRenderer", "client.FabricModelManagerMixin", "client.FabricMouseHandlerMixin", - "client.FabricParticleEngineMixin" + "client.FabricParticleEngineMixin", + "client.FabricPlayerRendererMixin" ] } diff --git a/Forge/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 b/Forge/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 index f38d8f9048..590a18fdb1 100644 --- a/Forge/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 +++ b/Forge/src/generated/resources/.cache/50b16d832771f8a8317f4d1b88c5121208c8c4f9 @@ -1,5 +1,6 @@ -// 1.20.1 2023-12-24T17:58:56.8920242 Tags for minecraft:block mod id vanilla +// 1.20.1 2024-08-27T12:44:48.881057546 Tags for minecraft:block mod id vanilla c5aac196bf97183b43d794c6aac8e206f4b71e37 data/hexcasting/tags/blocks/brainswept_circle_components.json +0ac2f0afe13705ae24edcb339a5e1e2cdcfe51cf data/hexcasting/tags/blocks/cheap_to_break_block.json abaec2d0102fef5865ac638cf7c528a4d5b2a69b data/hexcasting/tags/blocks/directrices.json 7e27f819889d2f0bca863b1cdb6d7d640ea21986 data/hexcasting/tags/blocks/edified_logs.json 86828f8056bfdfdd2aff10d7a9dbc6c269c25b8a data/hexcasting/tags/blocks/edified_planks.json @@ -8,8 +9,8 @@ abaec2d0102fef5865ac638cf7c528a4d5b2a69b data/hexcasting/tags/blocks/directrices 841dfbe4970e9167b205e5aa2b0f0936c6b9af60 data/minecraft/tags/blocks/buttons.json 8b7d16a34235e6062e47f6b3a3a08be760a3bb85 data/minecraft/tags/blocks/crystal_sound_blocks.json cba96d2ff28087e7fd9807e5e80104f3befc2512 data/minecraft/tags/blocks/doors.json -c460821db89b3d3f95a0fb336b6b6625da65ec37 data/minecraft/tags/blocks/fences.json d57d93d193fada6e232bde266430a155fa6e1707 data/minecraft/tags/blocks/fence_gates.json +c460821db89b3d3f95a0fb336b6b6625da65ec37 data/minecraft/tags/blocks/fences.json 6312e44ef31d2401dddbd46c4d3eda03da6e2db3 data/minecraft/tags/blocks/leaves.json 7e27f819889d2f0bca863b1cdb6d7d640ea21986 data/minecraft/tags/blocks/logs.json 7e27f819889d2f0bca863b1cdb6d7d640ea21986 data/minecraft/tags/blocks/logs_that_burn.json diff --git a/Forge/src/generated/resources/data/hexcasting/tags/blocks/cheap_to_break_block.json b/Forge/src/generated/resources/data/hexcasting/tags/blocks/cheap_to_break_block.json new file mode 100644 index 0000000000..7fc52a816b --- /dev/null +++ b/Forge/src/generated/resources/data/hexcasting/tags/blocks/cheap_to_break_block.json @@ -0,0 +1,6 @@ +{ + "values": [ + "hexcasting:conjured_block", + "hexcasting:conjured_light" + ] +} \ No newline at end of file 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/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 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..266bb5fc61 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 @@ -3,6 +3,7 @@ import at.petrak.hexcasting.api.addldata.ADIotaHolder; import at.petrak.hexcasting.api.casting.iota.Iota; import at.petrak.hexcasting.api.casting.iota.IotaType; +import at.petrak.hexcasting.api.utils.HexUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; @@ -17,7 +18,7 @@ public record CapStaticIotaHolder(Function provider, public @Nullable CompoundTag readIotaTag() { var iota = provider.apply(stack); - return iota == null ? null : IotaType.serialize(iota); + return iota == null ? null : (CompoundTag) HexUtils.serializeWithCodec(iota, Iota.getCodec()); } @Override @@ -26,6 +27,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; diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexDataGenerators.java b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexDataGenerators.java index 1e3a9bcb6a..c5ed351ea7 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexDataGenerators.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/datagen/ForgeHexDataGenerators.java @@ -1,6 +1,7 @@ package at.petrak.hexcasting.forge.datagen; import at.petrak.hexcasting.api.HexAPI; +import at.petrak.hexcasting.common.lib.HexDamageTypes; import at.petrak.hexcasting.datagen.HexAdvancements; import at.petrak.hexcasting.datagen.HexLootTables; import at.petrak.hexcasting.datagen.IXplatIngredients; @@ -8,12 +9,15 @@ import at.petrak.hexcasting.datagen.recipe.builders.FarmersDelightToolIngredient; import at.petrak.hexcasting.datagen.tag.HexActionTagProvider; import at.petrak.hexcasting.datagen.tag.HexBlockTagProvider; +import at.petrak.hexcasting.datagen.tag.HexDamageTypeTagProvider; import at.petrak.hexcasting.datagen.tag.HexItemTagProvider; import at.petrak.hexcasting.forge.datagen.xplat.HexBlockStatesAndModels; import at.petrak.hexcasting.forge.datagen.xplat.HexItemModels; import at.petrak.hexcasting.forge.recipe.ForgeModConditionalIngredient; import at.petrak.hexcasting.xplat.IXplatAbstractions; import com.google.gson.JsonObject; +import net.minecraft.core.RegistrySetBuilder; +import net.minecraft.core.registries.Registries; import net.minecraft.data.DataGenerator; import net.minecraft.data.advancements.AdvancementProvider; import net.minecraft.data.loot.LootTableProvider; @@ -26,6 +30,7 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraftforge.common.Tags; import net.minecraftforge.common.ToolActions; +import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider; import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.data.event.GatherDataEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -53,14 +58,28 @@ private static void configureXplatDatagen(GatherDataEvent ev) { var output = gen.getPackOutput(); var lookup = ev.getLookupProvider(); ExistingFileHelper efh = ev.getExistingFileHelper(); + + // https://docs.minecraftforge.net/en/latest/datagen/server/datapackregistries/ + // https://github.com/MinecraftForge/MinecraftForge/pull/9580 + var datapackProvider = new DatapackBuiltinEntriesProvider( + output, + lookup, + new RegistrySetBuilder() + .add(Registries.DAMAGE_TYPE, HexDamageTypes::bootstrap), + Set.of(HexAPI.MOD_ID) + ); + var datapackLookup = datapackProvider.getRegistryProvider(); + gen.addProvider(ev.includeClient(), new HexItemModels(output, efh)); gen.addProvider(ev.includeClient(), new HexBlockStatesAndModels(output, efh)); gen.addProvider(ev.includeServer(), new AdvancementProvider( output, lookup, List.of(new HexAdvancements()) )); + gen.addProvider(ev.includeServer(), datapackProvider); + gen.addProvider(ev.includeServer(), new HexDamageTypeTagProvider(output, datapackLookup)); } - @SuppressWarnings("DataFlowIssue") + @SuppressWarnings({"DataFlowIssue", "UnreachableCode"}) private static void configureForgeDatagen(GatherDataEvent ev) { HexAPI.LOGGER.info("Starting Forge-specific datagen"); @@ -73,6 +92,7 @@ private static void configureForgeDatagen(GatherDataEvent ev) { )); gen.addProvider(ev.includeServer(), new HexplatRecipes(output, INGREDIENTS, ForgeHexConditionsBuilder::new)); + // TODO: refactor? var xtags = IXplatAbstractions.INSTANCE.tags(); var blockTagProvider = new HexBlockTagProvider(output, lookup, xtags); ((TagsProviderEFHSetter) blockTagProvider).setEFH(efh); 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": [