From 77d6415f9dbc70e98df39c609c099f000c46ad23 Mon Sep 17 00:00:00 2001 From: IridescentVoid <265486018+IridescentVoid@users.noreply.github.com> Date: Thu, 30 Jul 2026 06:48:14 -0700 Subject: [PATCH 1/4] feat: block type comparison patterns --- CHANGELOG.md | 1 + .../actions/queryblock/OpBlockEquality.kt | 24 +++++++++++++++++++ .../hexcasting/common/lib/hex/HexActions.java | 15 ++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 042a99008..e9834ab5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - Added a pattern display overlay for pattern-holding items (ie scrolls or slates) while holding shift in the inventory ([#879](https://github.com/FallingColors/HexMod/pull/879)) @SamsTheNerd - Added connected textures for Akashic Ligatures when using Continuity or Optifine ([#885](https://github.com/FallingColors/HexMod/pull/885)) @kineticneticat - Added Similarity Distillation and Dissimilarity Distillation for comparing iota types ([#1114](https://github.com/FallingColors/HexMod/pull/1114)) @IridescentVoid +- Added patterns for comparing block types with strict and lenient variants ([#1224](https://github.com/FallingColors/HexMod/pull/1224)) @IridescentVoid - Added Contemplation for escaping without the exponential growth of Consideration ([#1102](https://github.com/FallingColors/HexMod/pull/1102)) @IridescentVoid ### Changed diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt new file mode 100644 index 000000000..08e9d8d08 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt @@ -0,0 +1,24 @@ +package at.petrak.hexcasting.common.casting.actions.queryblock + +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.getBlockPos +import at.petrak.hexcasting.api.casting.iota.Iota + +class OpBlockEquality(val exact: Boolean, val invert: Boolean) : ConstMediaAction { + override val argc = 2 + + override fun execute(args: List, env: CastingEnvironment): List { + val posA = args.getBlockPos(0).also { env.assertPosInRange(it) } + val posB = args.getBlockPos(1).also { env.assertPosInRange(it) } + + val blockA = env.world.getBlockState(posA) + val blockB = env.world.getBlockState(posB) + + // a unique BlockState only has one instance + val matches = if (exact) blockA === blockB else blockA.`is`(blockB.block) + + return (matches != invert).asActionResult + } +} 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 23103fac8..f9b2369d6 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 @@ -30,6 +30,7 @@ import at.petrak.hexcasting.common.casting.actions.math.logic.OpCoerceToBool; import at.petrak.hexcasting.common.casting.actions.math.logic.OpEquality; import at.petrak.hexcasting.common.casting.actions.math.logic.OpTypeEquality; +import at.petrak.hexcasting.common.casting.actions.queryblock.OpBlockEquality; import at.petrak.hexcasting.common.casting.actions.queryentity.*; import at.petrak.hexcasting.common.casting.actions.raycast.OpBlockAxisRaycast; import at.petrak.hexcasting.common.casting.actions.raycast.OpBlockRaycast; @@ -543,6 +544,20 @@ public class HexActions { true) )); + // == Blocks == + public static final ActionRegistryEntry COMPARE_BLOCK = make("compare_block", new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqeqeeeee", HexDir.NORTH_WEST), new OpBlockEquality(false, false) + )); + public static final ActionRegistryEntry COMPARE_BLOCK_INVERTED = make("compare_block/inverted", new ActionRegistryEntry( + HexPattern.fromAngles("eeeeeqeqqqqq", HexDir.NORTH_EAST), new OpBlockEquality(false, true) + )); + public static final ActionRegistryEntry COMPARE_BLOCK_STRICT = make("compare_block/strict", new ActionRegistryEntry( + HexPattern.fromAngles("qwawqwadadwewdwe", HexDir.NORTH_WEST), new OpBlockEquality(true, false) + )); + public static final ActionRegistryEntry COMPARE_BLOCK_STRICT_INVERTED = make("compare_block/strict/inverted", new ActionRegistryEntry( + HexPattern.fromAngles("ewdwewdadawqwawq", HexDir.NORTH_EAST), new OpBlockEquality(true, true) + )); + // == Lists == public static final ActionRegistryEntry APPEND = make("append", From da7d2f3f4856e2226d253fdd0af04cf87abbf710 Mon Sep 17 00:00:00 2001 From: IridescentVoid <265486018+IridescentVoid@users.noreply.github.com> Date: Thu, 30 Jul 2026 21:31:19 -0700 Subject: [PATCH 2/4] feat: remove inverting variants, add book entry --- CHANGELOG.md | 2 +- .../actions/queryblock/OpBlockEquality.kt | 4 +-- .../hexcasting/common/lib/hex/HexActions.java | 12 +++------ .../hexcasting/lang/en_us.flatten.json5 | 13 ++++++++++ .../entries/patterns/akashic_patterns.json | 2 +- .../en_us/entries/patterns/blocks.json | 26 +++++++++++++++++++ .../en_us/entries/patterns/circle.json | 2 +- .../en_us/entries/patterns/lists.json | 2 +- .../en_us/entries/patterns/meta.json | 2 +- .../entries/patterns/patterns_as_iotas.json | 2 +- .../en_us/entries/patterns/readwrite.json | 2 +- .../en_us/entries/patterns/sets.json | 2 +- 12 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/blocks.json diff --git a/CHANGELOG.md b/CHANGELOG.md index e9834ab5e..9bc18caff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - Added a pattern display overlay for pattern-holding items (ie scrolls or slates) while holding shift in the inventory ([#879](https://github.com/FallingColors/HexMod/pull/879)) @SamsTheNerd - Added connected textures for Akashic Ligatures when using Continuity or Optifine ([#885](https://github.com/FallingColors/HexMod/pull/885)) @kineticneticat - Added Similarity Distillation and Dissimilarity Distillation for comparing iota types ([#1114](https://github.com/FallingColors/HexMod/pull/1114)) @IridescentVoid -- Added patterns for comparing block types with strict and lenient variants ([#1224](https://github.com/FallingColors/HexMod/pull/1224)) @IridescentVoid +- Added Surveyor's Distillation and Inspector's Distillation ([#1224](https://github.com/FallingColors/HexMod/pull/1224)) @IridescentVoid - Added Contemplation for escaping without the exponential growth of Consideration ([#1102](https://github.com/FallingColors/HexMod/pull/1102)) @IridescentVoid ### Changed diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt index 08e9d8d08..75d074bae 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt @@ -6,7 +6,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.getBlockPos import at.petrak.hexcasting.api.casting.iota.Iota -class OpBlockEquality(val exact: Boolean, val invert: Boolean) : ConstMediaAction { +class OpBlockEquality(val exact: Boolean) : ConstMediaAction { override val argc = 2 override fun execute(args: List, env: CastingEnvironment): List { @@ -19,6 +19,6 @@ class OpBlockEquality(val exact: Boolean, val invert: Boolean) : ConstMediaActio // a unique BlockState only has one instance val matches = if (exact) blockA === blockB else blockA.`is`(blockB.block) - return (matches != invert).asActionResult + return matches.asActionResult } } 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 f9b2369d6..b84c305f6 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 @@ -545,17 +545,11 @@ public class HexActions { )); // == Blocks == - public static final ActionRegistryEntry COMPARE_BLOCK = make("compare_block", new ActionRegistryEntry( - HexPattern.fromAngles("qqqqqeqeeeee", HexDir.NORTH_WEST), new OpBlockEquality(false, false) - )); - public static final ActionRegistryEntry COMPARE_BLOCK_INVERTED = make("compare_block/inverted", new ActionRegistryEntry( - HexPattern.fromAngles("eeeeeqeqqqqq", HexDir.NORTH_EAST), new OpBlockEquality(false, true) + public static final ActionRegistryEntry COMPARE_BLOCK = make("compare_block/lenient", new ActionRegistryEntry( + HexPattern.fromAngles("qqqqqeqeeeee", HexDir.NORTH_WEST), new OpBlockEquality(false) )); public static final ActionRegistryEntry COMPARE_BLOCK_STRICT = make("compare_block/strict", new ActionRegistryEntry( - HexPattern.fromAngles("qwawqwadadwewdwe", HexDir.NORTH_WEST), new OpBlockEquality(true, false) - )); - public static final ActionRegistryEntry COMPARE_BLOCK_STRICT_INVERTED = make("compare_block/strict/inverted", new ActionRegistryEntry( - HexPattern.fromAngles("ewdwewdadawqwawq", HexDir.NORTH_EAST), new OpBlockEquality(true, true) + HexPattern.fromAngles("qwawqwadadwewdwe", HexDir.NORTH_WEST), new OpBlockEquality(true) )); // == Lists == 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 c138b18e6..99d55db82 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 @@ -789,6 +789,11 @@ not_player: "Zone Distillation: Non-Player", not_living: "Zone Distillation: Non-Living", }, + + "compare_block/": { + "lenient": "Surveyor's Distillation", + "strict": "Inspector's Distillation", + }, swap: "Jester's Gambit", rotate: "Rotation Gambit", @@ -1311,6 +1316,7 @@ stackmanip: "Stack Manipulation", logic: "Logical Operators", entities: "Entities", + blocks: "Blocks", lists: "List Manipulation", patterns_as_iotas: "Escaping Patterns", readwrite: "Reading and Writing", @@ -1941,6 +1947,13 @@ not_living: "Take a position and maximum distance on the stack, and combine them into a list of non-living entities near the position.", }, }, + + blocks: { + "compare_block/": { + lenient: "Removes two vectors from the top of the stack, and push whether they are of the same type in Nature's eye.", + strict: "Removes two vectors from the top of the stack, and push whether they are exactly the same.", + }, + }, 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.", diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/akashic_patterns.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/akashic_patterns.json index fab91f4ab..d6ebf609d 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/akashic_patterns.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/akashic_patterns.json @@ -2,7 +2,7 @@ "name": "hexcasting.entry.akashic_patterns", "category": "hexcasting:patterns", "icon": "hexcasting:akashic_bookshelf", - "sortnum": 14, + "sortnum": 15, "advancement": "hexcasting:enlightenment", "entry_color": "54398a", "pages": [ diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/blocks.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/blocks.json new file mode 100644 index 000000000..ab2291e82 --- /dev/null +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/blocks.json @@ -0,0 +1,26 @@ +{ + "name": "hexcasting.entry.blocks", + "category": "hexcasting:patterns", + "icon": "minecraft:grass_block", + "sortnum": 7, + "advancement": "hexcasting:root", + "read_by_default": true, + "pages": [ + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:compare_block/lenient", + "anchor": "hexcasting:compare_block/lenient", + "input": "vec, vec", + "output": "bool", + "text": "hexcasting.page.blocks.compare_block/lenient" + }, + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:compare_block/strict", + "anchor": "hexcasting:compare_block/strict", + "input": "vec, vec", + "output": "bool", + "text": "hexcasting.page.blocks.compare_block/strict" + } + ] +} diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/circle.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/circle.json index bb0e79860..f4b452ff9 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/circle.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/circle.json @@ -2,7 +2,7 @@ "name": "hexcasting.entry.circle_patterns", "category": "hexcasting:patterns", "icon": "hexcasting:impetus/empty", - "sortnum": 13, + "sortnum": 14, "advancement": "hexcasting:enlightenment", "entry_color": "54398a", "pages": [ diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/lists.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/lists.json index 8dfe25a29..61612c34a 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/lists.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/lists.json @@ -2,7 +2,7 @@ "name": "hexcasting.entry.lists", "category": "hexcasting:patterns", "icon": "minecraft:oak_sign", - "sortnum": 7, + "sortnum": 8, "advancement": "hexcasting:root", "read_by_default": true, "pages": [ 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 63e7f68c4..4bb81bb6f 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 @@ -2,7 +2,7 @@ "name": "hexcasting.entry.meta", "category": "hexcasting:patterns", "icon": "minecraft:shulker_box", - "sortnum": 12, + "sortnum": 13, "advancement": "hexcasting:root", "read_by_default": true, "pages": [ diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/patterns_as_iotas.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/patterns_as_iotas.json index 500f29689..edb11d186 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/patterns_as_iotas.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/patterns_as_iotas.json @@ -2,7 +2,7 @@ "name": "hexcasting.entry.patterns_as_iotas", "category": "hexcasting:patterns", "icon": "minecraft:emerald", - "sortnum": 8, + "sortnum": 9, "advancement": "hexcasting:root", "read_by_default": true, "pages": [ diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/readwrite.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/readwrite.json index c661d10d7..495702887 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/readwrite.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/readwrite.json @@ -2,7 +2,7 @@ "name": "hexcasting.entry.readwrite", "category": "hexcasting:patterns", "icon": "minecraft:writable_book", - "sortnum": 9, + "sortnum": 10, "advancement": "hexcasting:root", "read_by_default": true, "pages": [ diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/sets.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/sets.json index 936d929fc..edc213a06 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/sets.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/sets.json @@ -2,7 +2,7 @@ "name": "hexcasting.entry.sets", "category": "hexcasting:patterns", "icon": "minecraft:bundle", - "sortnum": 11, + "sortnum": 12, "advancement": "hexcasting:root", "read_by_default": true, "pages": [ From 75d152a771ac0aa66c17738e2b3b7b2ba40e0deb Mon Sep 17 00:00:00 2001 From: IridescentVoid <265486018+IridescentVoid@users.noreply.github.com> Date: Fri, 31 Jul 2026 13:20:48 -0700 Subject: [PATCH 3/4] doc: reorganize book entries to group type comparisons --- .../hexcasting/lang/en_us.flatten.json5 | 8 ++-- .../en_us/entries/patterns/blocks.json | 26 ------------ .../en_us/entries/patterns/entities.json | 2 +- .../en_us/entries/patterns/logic.json | 16 ------- .../en_us/entries/patterns/types.json | 42 +++++++++++++++++++ 5 files changed, 47 insertions(+), 47 deletions(-) delete mode 100644 Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/blocks.json create mode 100644 Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/types.json 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 99d55db82..1ca0746c8 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 @@ -1316,7 +1316,7 @@ stackmanip: "Stack Manipulation", logic: "Logical Operators", entities: "Entities", - blocks: "Blocks", + types: "Types", lists: "List Manipulation", patterns_as_iotas: "Escaping Patterns", readwrite: "Reading and Writing", @@ -1915,8 +1915,6 @@ if: "If the first argument is True, keeps the second and discards the third; otherwise discards the second and keeps the third.", equals: "If the first argument equals the second (within a small tolerance), return True. Otherwise, return False.", not_equals: "If the first argument does not equal the second (outside a small tolerance), return True. Otherwise, return False.", - type_equals: "If the type of the first argument matches the type of the second, return True. Otherwise, return False.", - type_not_equals: "If the type of the first argument does not match the type of the second, return True. Otherwise, return False.", greater: "If the first argument is greater than the second, return True. Otherwise, return False.", less: "If the first argument is less than the second, return True. Otherwise, return False.", greater_eq: "If the first argument is greater than or equal to the second, return True. Otherwise, return False.", @@ -1948,7 +1946,9 @@ }, }, - blocks: { + types: { + type_equals: "If the type of the first argument matches the type of the second, return True. Otherwise, return False.", + type_not_equals: "If the type of the first argument does not match the type of the second, return True. Otherwise, return False.", "compare_block/": { lenient: "Removes two vectors from the top of the stack, and push whether they are of the same type in Nature's eye.", strict: "Removes two vectors from the top of the stack, and push whether they are exactly the same.", diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/blocks.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/blocks.json deleted file mode 100644 index ab2291e82..000000000 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/blocks.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "hexcasting.entry.blocks", - "category": "hexcasting:patterns", - "icon": "minecraft:grass_block", - "sortnum": 7, - "advancement": "hexcasting:root", - "read_by_default": true, - "pages": [ - { - "type": "hexcasting:pattern", - "op_id": "hexcasting:compare_block/lenient", - "anchor": "hexcasting:compare_block/lenient", - "input": "vec, vec", - "output": "bool", - "text": "hexcasting.page.blocks.compare_block/lenient" - }, - { - "type": "hexcasting:pattern", - "op_id": "hexcasting:compare_block/strict", - "anchor": "hexcasting:compare_block/strict", - "input": "vec, vec", - "output": "bool", - "text": "hexcasting.page.blocks.compare_block/strict" - } - ] -} diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/entities.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/entities.json index c7cf30b4f..27a5bec8b 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/entities.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/entities.json @@ -2,7 +2,7 @@ "name": "hexcasting.entry.entities", "category": "hexcasting:patterns", "icon": "minecraft:pig_spawn_egg", - "sortnum": 6, + "sortnum": 7, "advancement": "hexcasting:root", "read_by_default": true, "pages": [ diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/logic.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/logic.json index f321377b4..84680b4de 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/logic.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/logic.json @@ -79,22 +79,6 @@ "output": "bool", "text": "hexcasting.page.logic.not_equals" }, - { - "type": "hexcasting:pattern", - "op_id": "hexcasting:type_equals", - "anchor": "hexcasting:type_equals", - "input": "any, any", - "output": "bool", - "text": "hexcasting.page.logic.type_equals" - }, - { - "type": "hexcasting:pattern", - "op_id": "hexcasting:type_not_equals", - "anchor": "hexcasting:type_not_equals", - "input": "any, any", - "output": "bool", - "text": "hexcasting.page.logic.type_not_equals" - }, { "type": "hexcasting:pattern", "op_id": "hexcasting:greater", diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/types.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/types.json new file mode 100644 index 000000000..7d1bd4931 --- /dev/null +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/types.json @@ -0,0 +1,42 @@ +{ + "name": "hexcasting.entry.types", + "category": "hexcasting:patterns", + "icon": "hexcasting:lens", + "sortnum": 6, + "advancement": "hexcasting:root", + "read_by_default": true, + "pages": [ + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:type_equals", + "anchor": "hexcasting:type_equals", + "input": "any, any", + "output": "bool", + "text": "hexcasting.page.types.type_equals" + }, + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:type_not_equals", + "anchor": "hexcasting:type_not_equals", + "input": "any, any", + "output": "bool", + "text": "hexcasting.page.types.type_not_equals" + }, + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:compare_block/lenient", + "anchor": "hexcasting:compare_block/lenient", + "input": "vec, vec", + "output": "bool", + "text": "hexcasting.page.types.compare_block/lenient" + }, + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:compare_block/strict", + "anchor": "hexcasting:compare_block/strict", + "input": "vec, vec", + "output": "bool", + "text": "hexcasting.page.types.compare_block/strict" + } + ] +} From 7ad28671962a88788a1418012bac8d71b18827ab Mon Sep 17 00:00:00 2001 From: IridescentVoid <265486018+IridescentVoid@users.noreply.github.com> Date: Sat, 1 Aug 2026 11:56:39 -0700 Subject: [PATCH 4/4] feat: item and entity comparison patterns, reword book entries again --- .../{queryblock => types}/OpBlockEquality.kt | 2 +- .../casting/actions/types/OpEntityEquality.kt | 18 +++++++ .../casting/actions/types/OpItemEquality.kt | 31 ++++++++++++ .../{math/logic => types}/OpTypeEquality.kt | 2 +- .../common/lib/HexItemHolderHandlers.java | 47 +++++++++++++++++++ .../hexcasting/common/lib/hex/HexActions.java | 17 +++++-- .../hexcasting/lang/en_us.flatten.json5 | 23 ++++++--- .../en_us/entries/patterns/types.json | 24 ++++++++++ .../hexcasting/fabric/FabricHexInitializer.kt | 1 + .../hexcasting/forge/ForgeHexInitializer.java | 1 + 10 files changed, 155 insertions(+), 11 deletions(-) rename Common/src/main/java/at/petrak/hexcasting/common/casting/actions/{queryblock => types}/OpBlockEquality.kt (93%) create mode 100644 Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpEntityEquality.kt create mode 100644 Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpItemEquality.kt rename Common/src/main/java/at/petrak/hexcasting/common/casting/actions/{math/logic => types}/OpTypeEquality.kt (89%) create mode 100644 Common/src/main/java/at/petrak/hexcasting/common/lib/HexItemHolderHandlers.java diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpBlockEquality.kt similarity index 93% rename from Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt rename to Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpBlockEquality.kt index 75d074bae..2e8cd090d 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/queryblock/OpBlockEquality.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpBlockEquality.kt @@ -1,4 +1,4 @@ -package at.petrak.hexcasting.common.casting.actions.queryblock +package at.petrak.hexcasting.common.casting.actions.types import at.petrak.hexcasting.api.casting.asActionResult import at.petrak.hexcasting.api.casting.castables.ConstMediaAction diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpEntityEquality.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpEntityEquality.kt new file mode 100644 index 000000000..6668f4cdd --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpEntityEquality.kt @@ -0,0 +1,18 @@ +package at.petrak.hexcasting.common.casting.actions.types + +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.getEntity +import at.petrak.hexcasting.api.casting.iota.Iota + +object OpEntityEquality : ConstMediaAction { + override val argc = 2 + + override fun execute(args: List, env: CastingEnvironment): List { + val entityA = args.getEntity(0).also { env.assertEntityInRange(it) } + val entityB = args.getEntity(1).also { env.assertEntityInRange(it) } + + return (entityA.type == entityB.type).asActionResult + } +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpItemEquality.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpItemEquality.kt new file mode 100644 index 000000000..609a34925 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpItemEquality.kt @@ -0,0 +1,31 @@ +package at.petrak.hexcasting.common.casting.actions.types + +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.getEntity +import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota +import at.petrak.hexcasting.common.lib.HexItemHolderHandlers +import net.minecraft.world.item.ItemStack + +class OpItemEquality(val exact: Boolean) : ConstMediaAction { + override val argc = 2 + + override fun execute(args: List, env: CastingEnvironment): List { + val itemA = args.getEntity(0).also { env.assertEntityInRange(it) } + .let { HexItemHolderHandlers.applyHandlerFor(it) } + ?: throw MishapInvalidIota.ofType(args[0], 0, "entity.item_holder") + + val itemB = args.getEntity(1).also { env.assertEntityInRange(it) } + .let { HexItemHolderHandlers.applyHandlerFor(it) } + ?: throw MishapInvalidIota.ofType(args[1], 1, "entity.item_holder") + + val matches = if (exact) ItemStack.isSameItemSameTags(itemA, itemB) + else ItemStack.isSameItem(itemA, itemB) + + return matches.asActionResult + } // TODO: move book entry again and have an extra page on 'item holder' + // and examples for type of item and identical + // types: "first iota given" +} diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpTypeEquality.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpTypeEquality.kt similarity index 89% rename from Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpTypeEquality.kt rename to Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpTypeEquality.kt index cd31212ca..9effc144c 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/math/logic/OpTypeEquality.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/types/OpTypeEquality.kt @@ -1,4 +1,4 @@ -package at.petrak.hexcasting.common.casting.actions.math.logic +package at.petrak.hexcasting.common.casting.actions.types import at.petrak.hexcasting.api.casting.asActionResult import at.petrak.hexcasting.api.casting.castables.ConstMediaAction diff --git a/Common/src/main/java/at/petrak/hexcasting/common/lib/HexItemHolderHandlers.java b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexItemHolderHandlers.java new file mode 100644 index 000000000..006f68ca7 --- /dev/null +++ b/Common/src/main/java/at/petrak/hexcasting/common/lib/HexItemHolderHandlers.java @@ -0,0 +1,47 @@ +package at.petrak.hexcasting.common.lib; + +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +public class HexItemHolderHandlers { + private static Map, Function> REGISTRY = new HashMap<>(); + + /** + * Register a handler for mapping an entity type to an item. + * + * @param type Type of entity to register the handler for. + * @param handler The handler function. May return null, in which case dependent patterns will mishap. + */ + public static void register(EntityType type, Function handler) { + REGISTRY.put(type, handler); + } + + @SuppressWarnings("unchecked") + public static @Nullable ItemStack applyHandlerFor(Entity e) { + var handler = REGISTRY.getOrDefault(e.getType(), entity -> null); + ItemStack stack = ((Function) handler).apply(e); + + if (stack != null && stack.isEmpty()) stack = null; + + return stack; + } + + public static void init() { + register(EntityType.ITEM, ItemEntity::getItem); + register(EntityType.ITEM_FRAME, ItemFrame::getItem); + register(EntityType.PLAYER, player -> { + ItemStack mainHand = player.getItemInHand(InteractionHand.MAIN_HAND); + if (!mainHand.isEmpty()) return mainHand; + return player.getItemInHand(InteractionHand.OFF_HAND); + }); + } +} 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 b84c305f6..dfdb73fa3 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 @@ -29,8 +29,10 @@ import at.petrak.hexcasting.common.casting.actions.math.logic.OpBoolIf; import at.petrak.hexcasting.common.casting.actions.math.logic.OpCoerceToBool; import at.petrak.hexcasting.common.casting.actions.math.logic.OpEquality; -import at.petrak.hexcasting.common.casting.actions.math.logic.OpTypeEquality; -import at.petrak.hexcasting.common.casting.actions.queryblock.OpBlockEquality; +import at.petrak.hexcasting.common.casting.actions.types.OpEntityEquality; +import at.petrak.hexcasting.common.casting.actions.types.OpItemEquality; +import at.petrak.hexcasting.common.casting.actions.types.OpTypeEquality; +import at.petrak.hexcasting.common.casting.actions.types.OpBlockEquality; import at.petrak.hexcasting.common.casting.actions.queryentity.*; import at.petrak.hexcasting.common.casting.actions.raycast.OpBlockAxisRaycast; import at.petrak.hexcasting.common.casting.actions.raycast.OpBlockRaycast; @@ -544,13 +546,22 @@ public class HexActions { true) )); - // == Blocks == + // == Types == public static final ActionRegistryEntry COMPARE_BLOCK = make("compare_block/lenient", new ActionRegistryEntry( HexPattern.fromAngles("qqqqqeqeeeee", HexDir.NORTH_WEST), new OpBlockEquality(false) )); public static final ActionRegistryEntry COMPARE_BLOCK_STRICT = make("compare_block/strict", new ActionRegistryEntry( HexPattern.fromAngles("qwawqwadadwewdwe", HexDir.NORTH_WEST), new OpBlockEquality(true) )); + public static final ActionRegistryEntry COMPARE_ENTITY = make("compare_entity", new ActionRegistryEntry( + HexPattern.fromAngles("aqaeqded", HexDir.NORTH_WEST), OpEntityEquality.INSTANCE + )); + public static final ActionRegistryEntry COMPARE_ITEM = make("compare_item/lenient", new ActionRegistryEntry( + HexPattern.fromAngles("qaeaqeqedqde", HexDir.NORTH_WEST), new OpItemEquality(false) + )); + public static final ActionRegistryEntry COMPARE_ITEM_STRICT = make("compare_item/strict", new ActionRegistryEntry( + HexPattern.fromAngles("qaeaqewqedqde", HexDir.NORTH_WEST), new OpItemEquality(true) + )); // == Lists == 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 1ca0746c8..370eb1681 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 @@ -790,10 +790,17 @@ not_living: "Zone Distillation: Non-Living", }, + type_equals: "Similarity Distillation", + type_not_equals: "Dissimilarity Distillation", "compare_block/": { "lenient": "Surveyor's Distillation", "strict": "Inspector's Distillation", }, + compare_entity: "Taxonomer's Distillation", + "compare_item/": { + "lenient": "Sorter's Distillation", + "strict": "Stacking Distillation", + }, swap: "Jester's Gambit", rotate: "Rotation Gambit", @@ -819,8 +826,6 @@ less_eq: "Minimus Distillation II", equals: "Equality Distillation", not_equals: "Inequality Distillation", - type_equals: "Similarity Distillation", - type_not_equals: "Dissimilarity Distillation", not: "Negation Purification", bool_coerce: "Augur's Purification", if: "Augur's Exaltation", @@ -1111,6 +1116,7 @@ "": "an entity", mob: "a mob", item: "an item entity", + item_holder: "an item-holding entity", player: "a player", living: "a living entity", }, @@ -1947,11 +1953,16 @@ }, types: { - type_equals: "If the type of the first argument matches the type of the second, return True. Otherwise, return False.", - type_not_equals: "If the type of the first argument does not match the type of the second, return True. Otherwise, return False.", + type_equals: "Compare the given iotas and push whether they are of the same type.", + type_not_equals: "Compare the given iotas and push whether they are of different types.", "compare_block/": { - lenient: "Removes two vectors from the top of the stack, and push whether they are of the same type in Nature's eye.", - strict: "Removes two vectors from the top of the stack, and push whether they are exactly the same.", + lenient: "Compare the blocks specified by the given vectors and push whether they are of the same type, in Nature's eye.", + strict: "Compare the blocks specified by the given vectors and push whether they appear to be identical.", + }, + compare_entity: "Compare the given entities and push whether they are of the same type.", + "compare_item/": { + lenient: "Compare the items within or held by the given entities and push whether they are the same type of item. Two $(l:items/focus)$(item)Foci/$ will always compare as equal.", + strict: "Like $(l:patterns/types#hexcasting:compare_item/lenient)$(action)Sorter's Distillation/$, but push whether they are identical items. Two $(l:items/focus)$(item)Foci/$ only compare as identical if they hold the same iota.", }, }, diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/types.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/types.json index 7d1bd4931..7e8d66c41 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/types.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/types.json @@ -37,6 +37,30 @@ "input": "vec, vec", "output": "bool", "text": "hexcasting.page.types.compare_block/strict" + }, + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:compare_item/lenient", + "anchor": "hexcasting:compare_item/lenient", + "input": "entity, entity", + "output": "bool", + "text": "hexcasting.page.types.compare_item/lenient" + }, + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:compare_item/strict", + "anchor": "hexcasting:compare_item/strict", + "input": "entity, entity", + "output": "bool", + "text": "hexcasting.page.types.compare_item/strict" + }, + { + "type": "hexcasting:pattern", + "op_id": "hexcasting:compare_entity", + "anchor": "hexcasting:compare_entity", + "input": "entity, entity", + "output": "bool", + "text": "hexcasting.page.types.compare_entity" } ] } diff --git a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt index 9dd280c0c..7b42011aa 100644 --- a/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt +++ b/Fabric/src/main/java/at/petrak/hexcasting/fabric/FabricHexInitializer.kt @@ -153,6 +153,7 @@ object FabricHexInitializer : ModInitializer { HexArithmetics.register(bind(IXplatAbstractions.INSTANCE.arithmeticRegistry)) HexContinuationTypes.registerContinuations(bind(IXplatAbstractions.INSTANCE.continuationTypeRegistry)) HexEvalSounds.register(bind(IXplatAbstractions.INSTANCE.evalSoundRegistry)) + HexItemHolderHandlers.init() // Because of Java's lazy-loading of classes, can't use Kotlin static initialization for // any calls that will eventually touch FeatureUtils.register(), as the growers here do, diff --git a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java index 638f573d2..c4618e295 100644 --- a/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java +++ b/Forge/src/main/java/at/petrak/hexcasting/forge/ForgeHexInitializer.java @@ -140,6 +140,7 @@ private static void initRegistry() { bind(HexRegistries.ARITHMETIC, HexArithmetics::register); bind(HexRegistries.CONTINUATION_TYPE, HexContinuationTypes::registerContinuations); bind(HexRegistries.EVAL_SOUND, HexEvalSounds::register); + HexItemHolderHandlers.init(); ForgeHexArgumentTypeRegistry.ARGUMENT_TYPES.register(getModEventBus()); ForgeHexLootMods.REGISTRY.register(getModEventBus());