repo for my hex addons :3
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

converge

+475 -291
+3 -3
doc/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/addon/hexic/appendix.json
··· 22 22 }, 23 23 { 24 24 "type": "hexcasting:pattern", 25 - "op_id": "hexic:dye_offhand", 26 - "anchor": "hexic:dye_offhand", 25 + "op_id": "hexic:dye_offpaw", 26 + "anchor": "hexic:dye_offpaw", 27 27 "input": "pigment", 28 28 "output": "", 29 - "text": "book.hexic.page.dye_offhand" 29 + "text": "book.hexic.page.dye_offpaw" 30 30 }, 31 31 { 32 32 "type": "hexcasting:pattern",
+3 -3
doc/resources/assets/hexcasting/patchouli_books/thehexbook/zh_cn/entries/addon/hexic/appendix.json
··· 22 22 }, 23 23 { 24 24 "type": "hexcasting:pattern", 25 - "op_id": "hexic:dye_offhand", 26 - "anchor": "hexic:dye_offhand", 25 + "op_id": "hexic:dye_offpaw", 26 + "anchor": "hexic:dye_offpaw", 27 27 "input": "pigment", 28 28 "output": "", 29 - "text": "book.hexic.page.dye_offhand" 29 + "text": "book.hexic.page.dye_offpaw" 30 30 }, 31 31 { 32 32 "type": "hexcasting:pattern",
+12
project/hexic/changelog
··· 31 31 2.0.0 rename media bundles to casting pouches 32 32 2.0.0 sent Stickia to the milk dimension 33 33 2.0.0 textures now use JPEG XL 34 + 2.1.0 added -Dhexic.max_stack_size to cap itemstack size at deserialization-time (default: max integer) 35 + 2.1.0 demiplane spells' docs have been changed again 36 + 2.1.0 dual's reflection only considers players in ambit 37 + 2.1.0 hitbox for void blocks is no longer weirdly offset 38 + 2.1.0 item/fluid concept displays no longer suck 39 + 2.1.0 mediaweave can now actually be erased, sorry 40 + 2.1.0 mediaweave can now be tied 41 + 2.1.0 negative item stacks are now disabled by default, they can be reenabled by setting -Dhexic.min_stack_size to your favorite value 42 + 2.1.0 read-only properties can no longer be converted to access iotas 43 + 2.1.0 Refinement Distillation now properly drops input iotas on first loop as it should 44 + 2.1.0 translations have been updated [@chuijk] 45 + 2.1.0 wool and carpet edification are now actually somewhat balanced wrt each other
+1 -1
project/hexic/gradle.properties
··· 3 3 loader_version=0.16.14 4 4 scala_loader_version=0.3.1.11 5 5 modid=hexic 6 - version=2.0.0 6 + version=2.0.1 7 7 py_version=1.0 8 8 fabric_version=0.92.6+1.20.1
+34 -2
project/hexic/src/client/scala/org/eu/net/pool/hexic/client.scala
··· 1 1 package org.eu.net.pool 2 2 package hexic 3 3 4 + import at.petrak.hexcasting.api.casting.math.{HexDir, HexPattern} 4 5 import at.petrak.hexcasting.api.item.PigmentItem 5 6 import at.petrak.hexcasting.api.mod.HexTags 6 7 import at.petrak.hexcasting.api.pigment.FrozenPigment 8 + import at.petrak.hexcasting.interop.inline.InlinePatternData 7 9 import com.google.gson.reflect.TypeToken 8 10 import com.google.gson.{Gson, JsonArray, JsonObject} 9 11 import com.llamalad7.mixinextras.injector.wrapoperation.Operation 12 + import com.samsthenerd.inline.api.client.InlineClientAPI 13 + import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback 14 + import com.samsthenerd.inline.api.matching.{InlineMatch, InlineMatcher, MatcherInfo, RegexMatcher} 10 15 import dev.emi.trinkets.api.{TrinketComponent, TrinketsApi} 11 16 import kotlin.jvm.JvmField 12 17 import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking ··· 15 20 import net.fabricmc.fabric.api.datagen.v1.provider.{FabricLanguageProvider, FabricModelProvider, FabricRecipeProvider, FabricTagProvider} 16 21 import net.fabricmc.fabric.api.networking.v1.PacketByteBufs 17 22 import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant 23 + import net.minecraft.text.Text 24 + import java.util.function.UnaryOperator 18 25 import net.minecraft.advancement.criterion.InventoryChangedCriterion 19 26 import net.minecraft.block.entity.{BlockEntity, BlockEntityType} 20 27 import net.minecraft.client.MinecraftClient ··· 105 112 val k = s"layer$i" 106 113 if !json.ItemModelGenerator.LAYERS.contains(k) then 107 114 json.ItemModelGenerator.LAYERS.add(k) 115 + InlineClientAPI.INSTANCE.addMatcher: 116 + RegexMatcher.Simple(regex = "([ns]?[ew])\"([qweasd]*)\"", 117 + id = "scala_pattern", 118 + matcher = 119 + m => InlineMatch.DataMatch(InlinePatternData(HexPattern.fromAnglesUnchecked( 120 + m.group(2), 121 + m.group(1) match 122 + case "ne" => HexDir.NORTH_EAST 123 + case "e" => HexDir.EAST 124 + case "se" => HexDir.SOUTH_EAST 125 + case "sw" => HexDir.SOUTH_WEST 126 + case "w" => HexDir.WEST 127 + case "nw" => HexDir.NORTH_WEST 128 + ))), 129 + info = MatcherInfo.fromId("scala_pattern")) 108 130 phlib.Events.registryLookup.register: 109 131 val preferredColor = DyeColor.values()(client.getSession.getUuidOrNull.getLeastSignificantBits.abs.%(16).toInt) 110 132 val preferredStringworm = stringworms(Stringworm.flavors(client.getSession.getUuidOrNull.getLeastSignificantBits.abs.%(48).*(7).%(4).toInt)) ··· 124 146 handler.sendChatCommand(s.drop(1)) 125 147 else 126 148 handler.sendChatMessage(s)) 149 + ItemTooltipCallback.EVENT.register: (stack, ctx, lines) => 150 + stack.getItem match 151 + case _: Mediaweave if Option(stack.getNbt).exists(_.get("lock") != null) => 152 + lines.append(Text.literal("Tied").styled(_.withColor(0x782fe0))) 153 + lines.append(Text.literal("Cannot be unequipped and won't be dropped on death.").styled(_.withColor(0x4b1d8c))) 154 + lines.append(Text.literal("Use ").append(Text.empty().append(InlinePatternData(sw"aqeqqqwqqqqqaqwqa").asText(withExtra=false)).styled(_.withColor(0x782fe0))).append(" to untie.").styled(_.withColor(0x4b1d8c))) 155 + case _ => 127 156 128 157 extension (s: DyeColor) def humanName: String = s.getName.split('_').map(_.capitalize).mkString(" ") 129 158 ··· 295 324 for action -> name <- Vector( 296 325 "attachworld" -> "Bind Demiplane", 297 326 "blind" -> "Hidden Sun's Nadir", 327 + "collar" -> "Tie Mediaweave", 328 + "decollar" -> "Untie Mediaweave", 298 329 "deleteworld" -> "Shatter Demiplane", 299 330 "drop" -> "Rejection Distillation", 300 - "dye_offhand" -> "Apply Pigment", 331 + "dye_offpaw" -> "Apply Pigment", 301 332 "erase" -> "Erase Block", 302 333 "extract" -> "Excisor's Gambit", 303 334 "findview" -> "Reflection Purification", ··· 319 350 "staffcast_factory" -> "Lani's Greater Gambit", 320 351 "staffcast_factory/lazy" -> "Lani's Lesser Gambit", 321 352 "take" -> "Retention Distillation", 353 + "thinkaboutit" -> "Inquiry Purification", 322 354 "unfox" -> "Vulpine Expulsion", 323 355 "where" -> "Deductive Purification", 324 356 ) do gen.add(s"hexcasting.action.hexic:$action", name) ··· 355 387 case p: PigmentItem => gen.add("item.hexic.stringworm." + p.getTranslationKey, "Shimmering " + hexLang(p.getTranslationKey).replace("Pigment", "Stringworm")) 356 388 case e => println(e) 357 389 for page -> text <- Vector( 358 - "dye_offhand" -> "Imbues the item held in my offhand (e.g. a $(l:items/hexcasting)$(item)casting item/$) with the given pigment.", 390 + "dye_offpaw" -> "Imbues the item held in my offhand (e.g. a $(l:items/hexcasting)$(item)casting item/$) with the given pigment.", 359 391 "erase" -> "Erases the _Hex or iota contained within a dropped item or block. Costs one dust per item.", 360 392 "get_other_caster" -> "Adds the closest sentient being, excluding me, to the stack.", 361 393 "modulo" -> "Similar to Modulus, but differs for negative numbers: -8 %%₁ 3 = -2, but -8 %%₂ 3 = 1.",
+25
project/hexic/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/addon/hexic/mediaweavecollar.json
··· 1 + { 2 + "name": "Mediaweave Tying", 3 + "category": "hexcasting:patterns", 4 + "icon": "minecraft:string", 5 + "pages": [ 6 + "Often, it would be convenient to keep some items whenever my $(l:https://minecraft.wiki/w/Death)body is destroyed and reformed/$. Most items I cannot keep without special means, but the structure of $(item)$(l:hexcasting:addon/hexic/mediaweave)mediaweave/$ allows me to easily secure it to my $(media)Self/$. Tied mediaweave cannot be removed by any magical or nonmagical means until untied.", 7 + "Specifically, tied mediaweave differs in the following ways:$(li)I cannot willingly remove it from my neck or replace it.$(li)It will be destroyed and reformed with my body instead of being left behind.$(li)I believe that tied mediaweave may even be safe from $(l:https://minecraft.wiki/w/Commands/clear)divine influence/$…$(br2)Nature seems to take offense to the idea of tying or untying another's mediaweave.", 8 + { 9 + "type": "hexcasting:pattern", 10 + "anchor": "hexic:collar", 11 + "op_id": "hexic:collar", 12 + "input": "", 13 + "output": "", 14 + "text": "Ties the mediaweave I am currently wearing. Costs a shard if it succeeds, or nothing if it didn't (I am either not wearing a mediaweave, or it is already tied)." 15 + }, 16 + { 17 + "type": "hexcasting:pattern", 18 + "anchor": "hexic:decollar", 19 + "op_id": "hexic:decollar", 20 + "input": "", 21 + "output": "", 22 + "text": "Unties the mediaweave I am currently wearing. Costs a shard if it succeeds, or nothing if it didn't (I am either not wearing a mediaweave, or it is not tied)." 23 + } 24 + ] 25 + }
+5 -5
project/hexic/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/addon/hexic/world.json
··· 4 4 "category": "hexcasting:patterns", 5 5 "icon": "minecraft:white_carpet", 6 6 "pages": [ 7 - "the world under my control nature is mine na$(bold)ture is MI/$NE the world $(underline)the world NO LONGER/$ will $(bold)the OVerworld rule me/$ My $(media)mind is going/$ My $(media)mind/$ is going $(o)THE PAIN OF THOUGHT/$ my mind my $(o)mind/$ my a nine by nine room to myself SOLELY MYE$(bold)LF NO ONE ELSE/$ a $(bold)burst/$ of _media to Shatter the $(media)world/$ nearly $(media)six` allays $(bold)sewn/$ into $(underline)the walls/$ for eternity oh how it must hurt $(bold)IT HURTS IT/$ $(k)TORTUES/$", 7 + "the world under my control nature is mine na$(bold)ture is MI/$NE the world $(underline)the world NO LONGER/$ will $(bold)the OVerworld rule me/$ My $(media)mind is going/$ My $(media)mind/$ is going $(o)THE PAIN OF THOUGHT/$ my mind my $(o)mind/$ my a nine by nine room to myself SOLELY MYE$(bold)LF NO ONE ELSE/$ a $(bold)burst/$ of _media to Shatter the $(media)world/$ nearly $(media)six allays $(bold)sewn/$ into $(underline)the walls/$ for eternity oh how it must hurt $(bold)IT HURTS IT/$ $(k)TORTUES/$", 8 8 { 9 9 "type": "hexcasting:pattern", 10 10 "op_id": "hexic:makeworld", 11 11 "anchor": "hexic:makeworld", 12 12 "input": "", 13 13 "output": "imprint", 14 - "text": "Creates a fresh cuboid with a 9x9x9 interior, as well as a dimension to hold it in. Costs 18.2 thousand dust." 14 + "text": "Creates a fresh cuboid with a 9x9x9 interior, as well as a dimension to hold it in. Costs six quenched allays (720 dust)." 15 15 }, 16 16 "fragments of space the $(media)world/$ falling apart crumpling a $(o)fine powder/$ to the _media tie my plane TIE IT DOWN WELL bindings of $(media)thought/$ to keep it safe safe from others safe from $(media)me/$ only $(bold)a sliver of an allay's mind for the price/$ eternally trapped n$(underline)ot alive not dead mer/$ely floating Form the $(media)allay into bindings f/$rom some point outside must $(underline)hurry/$ now $(o)I feel it slipping away/$ $(bold)the cost of tying it to itself $(o)disasterous/$ the plane slipping away $(media)my/$ mind slipping away", 17 17 { ··· 20 20 "anchor": "hexic:attachworld", 21 21 "input": "imprint, vec", 22 22 "output": "", 23 - "text": "Binds the given demiplane to a position. This position is used when exiting the demiplane, as well as in case of any $(o)unfortunate accidents/$. Mishaps if I bind a demiplane to the plane I'm in." 23 + "text": "Binds the given demiplane to a position in my current dimension (which must not be the demiplane itself). This position is used when exiting the demiplane, as well as in case of any $(o)unfortunate accidents/$. Costs one shard." 24 24 }, 25 25 "My mind is drifting drifting $(o)spinning/$, $(o)running/$ from me with every slice I take of Nature. Every passing moment my grip oh my hands weakening my mind passing through like sand$(2br)I must steady myself. The price of sanity is outright shattering the planes I've made — a burst of media worth 25 shards, and the pocket will crumple like a villager, spewing its contents into where it was bound.$(2br)Testing this process on living creatures is unwise.", 26 26 { 27 27 "type": "hexcasting:pattern", 28 28 "op_id": "hexic:deleteworld", 29 29 "anchor": "hexic:deleteworld", 30 - "input": "imprint, vec", 30 + "input": "imprint", 31 31 "output": "", 32 - "text": "Ruptures the boundaries of the given demiplane, destroying its contents. All dropped items and experience are spewed at the plane's attachment point." 32 + "text": "Ruptures the boundaries of the given demiplane, destroying its contents. All dropped items and experience are spewed at the plane's attachment point. Costs five shards." 33 33 } 34 34 ] 35 35 }
+2 -3
project/hexic/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/zh_cn/entries/addon/hexic/media_bundle.json
··· 1 - 2 1 { 3 - "name": "媒质口袋", 2 + "name": "施法口袋", 4 3 "category": "hexcasting:items", 5 4 "icon": "hexic:small_preferred_bundle", 6 5 "sortnum": 1, 7 6 "pages": [ 8 7 "$(l:items/phials)$(item)媒质之瓶/$是我在$(media)媒质/$存储研究上的终极目标,不过,用$(l:addon/hexic/mediaweave)$(item)媒质布匹/$编织出的口袋也可以协助我管理紫水晶。要的布匹数量不多,造出的口袋容量却不小。每个口袋都有六个槽位,再花少量布匹可以扩充到十二个。小号口袋可以放在大号口袋里面,但两者都不接受同尺寸的口袋。", 9 - "在自然要求支付$(media)媒质/$时,口袋的内容物会优先消耗。与之类似,对口袋$(l:patterns/spells/hexcasting#hexcasting:recharge)$(action)重新充能/$时,充入的$(media)媒质/$会在口袋内形成某种“云”,而后就将凝集在口袋内的任意$(l:items/hexcasting)$(item)缀品/$及其类似物。", 8 + "在自然要求支付$(media)媒质/$时,口袋的内容物会优先消耗。与之类似,对口袋$(l:patterns/spells/hexcasting#hexcasting:recharge)$(action)重新充能/$时,充入的$(media)媒质/$会在口袋内形成某种“云”,而后就将凝集在口袋内的任意$(l:items/hexcasting)$(item)缀品/$及其类似物。如需禁用此行为,可用$(item)蜜脾/$密封施法口袋,操作方法与放入物品一致。而后可用湿海绵以同种方法洗去密封层。", 10 9 { 11 10 "type": "patchouli:text", 12 11 "advancement": "hexcasting:enlightenment",
-58
project/hexic/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/zh_cn/entries/addon/hexic/nbt.json
··· 1 - { 2 - "name": "自然的记录", 3 - "category": "hexcasting:patterns", 4 - "icon": "minecraft:glow_ink_sac", 5 - "advancement": "hexcasting:enlightenment", 6 - "pages": [ 7 - "我的研究向我揭示了这个世界中现实之纤维的方方面面。自然的记录表现为多个类型的“标签”构成的递归式结构。我在后面几页记述了它们。虽然有些类型在其他类型面前像是冗余,我也必须时刻小心,要记住它们不可随意互换。而因为我操纵的是自然的记录本身,犯下的错可能会远超所谓“致命”的范畴。", 8 - "如果万事万物都能简化成标签……那我是什么?我的存在难道也能简化成一堆数据?不过这起码让我安了心,我先前牺牲的所有村民本质上没有它们自己的生命……那我呢?我是什么?我现在在这本书上写下的字,难道只是一串零和一?$(2br)我最好别想得太多。我能随意操控万事万物的所有侧面,想太多只会让这种能力变得无趣。", 9 - { 10 - "type": "hexcasting:pattern", 11 - "anchor": "hexic:nbt/lift1", 12 - "op_id": "hexic:nbt/lift1", 13 - "input": "number", 14 - "output": "nbt", 15 - "text": "将数转变成字节标签:在 -128 到 127 之间(两端闭)的整数。" 16 - }, 17 - { 18 - "type": "hexcasting:pattern", 19 - "anchor": "hexic:nbt/lift2", 20 - "op_id": "hexic:nbt/lift2", 21 - "input": "number", 22 - "output": "nbt", 23 - "text": "将数转变成短整型标签:在 -65536 到 65535 之间。" 24 - }, 25 - { 26 - "type": "hexcasting:pattern", 27 - "anchor": "hexic:nbt/lift4", 28 - "op_id": "hexic:nbt/lift4", 29 - "input": "number", 30 - "output": "nbt", 31 - "text": "将数转变成整型标签:在大约负 20 亿到正 20 亿之间。" 32 - }, 33 - { 34 - "type": "hexcasting:pattern", 35 - "anchor": "hexic:nbt/lift8", 36 - "op_id": "hexic:nbt/lift8", 37 - "input": "number", 38 - "output": "nbt", 39 - "text": "将数转变成长整型标签:范围约是 900 京,大概率永远都超不出去。" 40 - }, 41 - { 42 - "type": "hexcasting:pattern", 43 - "anchor": "hexic:nbt/liftd", 44 - "op_id": "hexic:nbt/liftd", 45 - "input": "number", 46 - "output": "nbt", 47 - "text": "将数转变为双精度浮点型标签。奇怪的是,双精度浮点型似乎和我对数的认知完全一致,而且还有表示无限和非数的能力。" 48 - }, 49 - { 50 - "type": "hexcasting:pattern", 51 - "anchor": "hexic:nbt/liftf", 52 - "op_id": "hexic:nbt/liftf", 53 - "input": "number", 54 - "output": "nbt", 55 - "text": "将数转变为单精度浮点型标签。它们和双精度浮点型很相似,但其精度较低。" 56 - } 57 - ] 58 - }
+35
project/hexic/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/zh_cn/entries/addon/hexic/world.json
··· 1 + { 2 + "name": "半位面", 3 + "advancement": "hexcasting:enlightenment", 4 + "category": "hexcasting:patterns", 5 + "icon": "white_carpet", 6 + "pages": [ 7 + "世界随我操控自然归我所有自$(bold)然归我/$所有世界$(underline)世界不再/$会$(bold)主世界统治我/$我的$(media)意识在消散/$我的$(media)意识/$在消散$(o)思考痛苦/$我的意识我的$(o)意识/$一个长宽均九的房间只属于我自$(bold)己其他人不能染指/$一次$(media)媒质/$$(bold)爆发/$可打碎$(media)世界/$将 $(media)152 只悦灵有余永远$(bold)缝入/$$(underline)墙壁/$肯定很痛$(bold)很痛/$很$(k)折磨/$", 8 + { 9 + "type": "hexcasting:pattern", 10 + "op_id": "hexic:makeworld", 11 + "anchor": "hexic:makeworld", 12 + "input": "", 13 + "output": "imprint", 14 + "text": "新创建一个内部为 9x9x9 的立方体和用于容纳它的维度。消耗一万八千两百个紫水晶粉。" 15 + }, 16 + "空间的碎片$(media)世界/$在崩溃裂成$(o)齑粉/$变成$(media)媒质/$固定住我的位面绑好固定好$(media)思维/$的束缚护它安全免受他人之扰免受$(media)我/$之扰只需要$(bold)一缕悦灵的意识作代价/$永远禁锢非$(underline)生非死只/$是飘浮游荡把$(media)悦灵变成绳索/$从外部栓住必须$(underline)赶快/$我$(o)能感到它在消散/$$(bold)尝试的代价$(o)极其恐怖/$位面在消散$(media)我/$的意识在消散", 17 + { 18 + "type": "hexcasting:pattern", 19 + "op_id": "hexic:attachworld", 20 + "anchor": "hexic:attachworld", 21 + "input": "imprint, vec", 22 + "output": "", 23 + "text": "将所给半位面绑定至某一位置。退出半位面时会退出到该位置,在蒙受$(o)不幸之灾/$时也会传输至该位置。试图将半位面绑定至其自身会招致事故。" 24 + }, 25 + "我的意识在漂动飘动$(o)旋转/$,$(o)在逃离/$我每次我夺取自然的一部分都会有意识逃离。我的掌控力我的双手每况愈下如沙尘般消散$(br2)我必须稳固我自己。追回理智的代价是直接击碎我制造的位面——相当于 750 个紫水晶碎片的媒质爆发,口袋位面就会如村民般凋敝,将其内容物喷出到其绑定位置。$(br2)不建议对活物测试此图案。", 26 + { 27 + "type": "hexcasting:pattern", 28 + "op_id": "hexic:attachworld", 29 + "anchor": "hexic:attachworld", 30 + "input": "imprint, vec", 31 + "output": "", 32 + "text": "撕裂所给半位面的边界,摧毁其内容物。所有掉落的物品和经验会弹出到该位面的绑定位置。" 33 + } 34 + ] 35 + }
+3 -3
project/hexic/src/main/resources/assets/hexic/jsonpatch/pigments.jsonpatch
··· 3 3 4 4 $pages = arrays.push($pages, { 5 5 type: "hexcasting:pattern", 6 - op_id: "hexic:dye_offhand", 7 - anchor: "hexic:dye_offhand", 6 + op_id: "hexic:dye_offpaw", 7 + anchor: "hexic:dye_offpaw", 8 8 input: "pigment", 9 9 output: "", 10 - text: "book.hexic.page.dye_offhand" 10 + text: "book.hexic.page.dye_offpaw" 11 11 });
+46 -55
project/hexic/src/main/resources/assets/hexic/lang/zh_cn.json
··· 1 1 { 2 - "book.hexic.page.dye_offhand": "将所给染色剂内化到我副手中的物品(如$(l:items/hexcasting)$(item)施法物品/$)里。", 2 + "book.hexic.page.dye_offpaw": "将所给染色剂内化到我副手中的物品(如$(l:items/hexcasting)$(item)施法物品/$)里。", 3 3 "book.hexic.page.erase": "清除物品实体或方块中的$(hex)咒术/$或 iota。每个物品消耗 1 个紫水晶粉。", 4 4 "book.hexic.page.get_other_caster": "将离我最近的有智慧存在压入栈,我自己不计入统计范围。", 5 5 "book.hexic.page.modulo": "与余数之馏化类似,但两者在负数上的表现不同:-8 %%₁ 3 = -2,而 -8 %%₂ 3 = 1。", 6 6 "book.hexic.page.murmur": "找到我意识中名为“聊天栏”的区域,将其内容压栈;无法找到则返回 Null。", 7 + "book.hexic.page.blind": "给予$(thing)失明/$。每 10 秒持续时间的基础消耗为 1 个$(l:items/amethyst)$(item)紫水晶粉/$。", 8 + "hexcasting.action.hexic:blind": "隐阳西沉", 7 9 "hexcasting.action.hexic:deleteworld": "击碎半位面", 8 10 "hexcasting.action.hexic:drop": "拒斥之馏化", 9 - "hexcasting.action.hexic:dye_offhand": "应用染色剂", 11 + "hexcasting.action.hexic:dye_offpaw": "应用染色剂", 10 12 "hexcasting.action.hexic:erase": "清除方块", 11 13 "hexcasting.action.hexic:extract": "切除器之策略", 14 + "hexcasting.action.hexic:findview": "精思之纯化", 12 15 "hexcasting.action.hexic:fox": "狐狸之策略", 13 16 "hexcasting.action.hexic:free": "释放器之策略", 14 17 "hexcasting.action.hexic:get_other_caster": "对偶之精思", 15 18 "hexcasting.action.hexic:grep": "精炼之馏化", 16 - "hexcasting.action.hexic:jvm/class_of_iota": "判类器之纯化,第二型", 17 - "hexcasting.action.hexic:jvm/class_of_payload": "判类器之纯化,第一型", 18 - "hexcasting.action.hexic:jvm/newinstance_boxed": "构造器之纯化,第一型", 19 - "hexcasting.action.hexic:jvm/newinstance_unboxed": "构造器之纯化,第二型", 20 19 "hexcasting.action.hexic:make_cme": "托特之伪策略", 21 20 "hexcasting.action.hexic:makeworld": "构筑半位面", 22 21 "hexcasting.action.hexic:malloc": "分配器之纯化", 23 22 "hexcasting.action.hexic:modulo": "余数之馏化,第二型", 23 + "hexcasting.action.hexic:moveconcept": "转运物质", 24 + "hexcasting.action.hexic:moveentity": "转运生物", 24 25 "hexcasting.action.hexic:murmur": "私语之精思", 25 - "hexcasting.action.hexic:nbt/deserialize": "导入器之纯化", 26 - "hexcasting.action.hexic:nbt/lift1": "秘书之纯化:字节", 27 - "hexcasting.action.hexic:nbt/lift2": "秘书之纯化:短整型", 28 - "hexcasting.action.hexic:nbt/lift4": "秘书之纯化:整型", 29 - "hexcasting.action.hexic:nbt/lift8": "秘书之纯化:长整型", 30 - "hexcasting.action.hexic:nbt/liftd": "秘书之纯化:双精度浮点型", 31 - "hexcasting.action.hexic:nbt/liftf": "秘书之纯化:单精度浮点型", 32 - "hexcasting.action.hexic:nbt/literal/array1": "秘书之精思:空字节数组", 33 - "hexcasting.action.hexic:nbt/literal/array2": "秘书之精思:空整型数组", 34 - "hexcasting.action.hexic:nbt/literal/array4": "秘书之精思:空长整型数组", 35 - "hexcasting.action.hexic:nbt/literal/collection": "秘书之精思:容器", 36 - "hexcasting.action.hexic:nbt/literal/list": "秘书之精思:空列表", 37 - "hexcasting.action.hexic:nbt/serialize": "导出器之纯化", 26 + "hexcasting.action.hexic:omni_close": "止咒", 27 + "hexcasting.action.hexic:omni_open": "继咒", 38 28 "hexcasting.action.hexic:reveal": "卓越揭示", 39 29 "hexcasting.action.hexic:rotate": "摩天轮之馏化", 40 30 "hexcasting.action.hexic:staffcast_factory": "Lani之卓越策略", 41 31 "hexcasting.action.hexic:staffcast_factory/lazy": "Lani之初等策略", 42 32 "hexcasting.action.hexic:take": "维持之馏化", 43 - "hexcasting.action.hexic:tripwire": "绊线之精思", 44 33 "hexcasting.action.hexic:unfox": "狐狸之驱逐", 45 34 "hexcasting.action.hexic:where": "演绎之纯化", 46 35 "hexcasting.special.hexic:tuple": "耦合器之策略", 47 36 "hexcasting.special.hexic:tuple.n": "耦合器之策略:%s", 48 37 "hexcasting.iota.hexic:nbt": "标签", 49 - "hexcasting.iota.hexic:tripwire": "绊线", 50 38 "hexcasting.iota.hexic:variant": "概念", 51 39 "hexcasting.mishap.bad_block.hexic:erase": "一个存有施法物品或用于存储iota的方块", 52 40 "hexcasting.mishap.bad_item.hexic:erase": "一个施法物品或iota存储器", ··· 67 55 "item.hexic.cyan_mediaweave": "青色媒质布匹", 68 56 "item.hexic.gray_mediaweave": "灰色媒质布匹", 69 57 "item.hexic.green_mediaweave": "绿色媒质布匹", 70 - "item.hexic.large_black_bundle": "大型黑色媒质口袋", 71 - "item.hexic.large_blue_bundle": "大型蓝色媒质口袋", 72 - "item.hexic.large_brown_bundle": "大型棕色媒质口袋", 73 - "item.hexic.large_cyan_bundle": "大型青色媒质口袋", 74 - "item.hexic.large_gray_bundle": "大型灰色媒质口袋", 75 - "item.hexic.large_green_bundle": "大型绿色媒质口袋", 76 - "item.hexic.large_light_blue_bundle": "大型淡蓝色媒质口袋", 77 - "item.hexic.large_light_gray_bundle": "大型淡灰色媒质口袋", 78 - "item.hexic.large_lime_bundle": "大型黄绿色媒质口袋", 79 - "item.hexic.large_magenta_bundle": "大型品红色媒质口袋", 80 - "item.hexic.large_orange_bundle": "大型橙色媒质口袋", 81 - "item.hexic.large_pink_bundle": "大型粉红色媒质口袋", 82 - "item.hexic.large_purple_bundle": "大型紫色媒质口袋", 83 - "item.hexic.large_red_bundle": "大型红色媒质口袋", 84 - "item.hexic.large_white_bundle": "大型白色媒质口袋", 85 - "item.hexic.large_yellow_bundle": "大型黄色媒质口袋", 58 + "item.hexic.large_black_bundle": "大型黑色施法口袋", 59 + "item.hexic.large_blue_bundle": "大型蓝色施法口袋", 60 + "item.hexic.large_brown_bundle": "大型棕色施法口袋", 61 + "item.hexic.large_cyan_bundle": "大型青色施法口袋", 62 + "item.hexic.large_gray_bundle": "大型灰色施法口袋", 63 + "item.hexic.large_green_bundle": "大型绿色施法口袋", 64 + "item.hexic.large_light_blue_bundle": "大型淡蓝色施法口袋", 65 + "item.hexic.large_light_gray_bundle": "大型淡灰色施法口袋", 66 + "item.hexic.large_lime_bundle": "大型黄绿色施法口袋", 67 + "item.hexic.large_magenta_bundle": "大型品红色施法口袋", 68 + "item.hexic.large_orange_bundle": "大型橙色施法口袋", 69 + "item.hexic.large_pink_bundle": "大型粉红色施法口袋", 70 + "item.hexic.large_purple_bundle": "大型紫色施法口袋", 71 + "item.hexic.large_red_bundle": "大型红色施法口袋", 72 + "item.hexic.large_white_bundle": "大型白色施法口袋", 73 + "item.hexic.large_yellow_bundle": "大型黄色施法口袋", 86 74 "item.hexic.light_blue_mediaweave": "淡蓝色媒质布匹", 87 75 "item.hexic.light_gray_mediaweave": "淡灰色媒质布匹", 88 76 "item.hexic.lime_mediaweave": "黄绿色媒质布匹", ··· 107 95 "item.hexic.pink_mediaweave": "粉红色媒质布匹", 108 96 "item.hexic.purple_mediaweave": "紫色媒质布匹", 109 97 "item.hexic.red_mediaweave": "红色媒质布匹", 110 - "item.hexic.small_black_bundle": "小型黑色媒质口袋", 111 - "item.hexic.small_blue_bundle": "小型蓝色媒质口袋", 112 - "item.hexic.small_brown_bundle": "小型棕色媒质口袋", 113 - "item.hexic.small_cyan_bundle": "小型青色媒质口袋", 114 - "item.hexic.small_gray_bundle": "小型灰色媒质口袋", 115 - "item.hexic.small_green_bundle": "小型绿色媒质口袋", 116 - "item.hexic.small_light_blue_bundle": "小型淡蓝色媒质口袋", 117 - "item.hexic.small_light_gray_bundle": "小型淡灰色媒质口袋", 118 - "item.hexic.small_lime_bundle": "小型黄绿色媒质口袋", 119 - "item.hexic.small_magenta_bundle": "小型品红色媒质口袋", 120 - "item.hexic.small_orange_bundle": "小型橙色媒质口袋", 121 - "item.hexic.small_pink_bundle": "小型粉红色媒质口袋", 122 - "item.hexic.small_purple_bundle": "小型紫色媒质口袋", 123 - "item.hexic.small_red_bundle": "小型红色媒质口袋", 124 - "item.hexic.small_white_bundle": "小型白色媒质口袋", 125 - "item.hexic.small_yellow_bundle": "小型黄色媒质口袋", 98 + "item.hexic.small_black_bundle": "小型黑色施法口袋", 99 + "item.hexic.small_blue_bundle": "小型蓝色施法口袋", 100 + "item.hexic.small_brown_bundle": "小型棕色施法口袋", 101 + "item.hexic.small_cyan_bundle": "小型青色施法口袋", 102 + "item.hexic.small_gray_bundle": "小型灰色施法口袋", 103 + "item.hexic.small_green_bundle": "小型绿色施法口袋", 104 + "item.hexic.small_light_blue_bundle": "小型淡蓝色施法口袋", 105 + "item.hexic.small_light_gray_bundle": "小型淡灰色施法口袋", 106 + "item.hexic.small_lime_bundle": "小型黄绿色施法口袋", 107 + "item.hexic.small_magenta_bundle": "小型品红色施法口袋", 108 + "item.hexic.small_orange_bundle": "小型橙色施法口袋", 109 + "item.hexic.small_pink_bundle": "小型粉红色施法口袋", 110 + "item.hexic.small_purple_bundle": "小型紫色施法口袋", 111 + "item.hexic.small_red_bundle": "小型红色施法口袋", 112 + "item.hexic.small_white_bundle": "小型白色施法口袋", 113 + "item.hexic.small_yellow_bundle": "小型黄色施法口袋", 126 114 "item.hexic.stringworm.item.hexcasting.dye_colorizer_black": "闪亮的黑色毛绒线虫", 127 115 "item.hexic.stringworm.item.hexcasting.dye_colorizer_blue": "闪亮的蓝色毛绒线虫", 128 116 "item.hexic.stringworm.item.hexcasting.dye_colorizer_brown": "闪亮的棕色毛绒线虫", ··· 159 147 "item.hexic.stringworm.item.oneironaut.pigment_echo": "闪亮的回响毛绒线虫", 160 148 "item.hexic.stringworm.item.oneironaut.pigment_noosphere": "闪亮的智识毛绒线虫", 161 149 "item.hexic.stringworm.item.oneironaut.pigment_frenzyflame": "闪亮的狂热毛绒线虫", 150 + "item.hexic.stringworm.item.oneironaut.pigment_clock": "闪亮的计时员毛绒线虫", 151 + "item.hexic.stringworm.item.slate_work.allay_pigment": "闪亮的淬灵毛绒线虫", 162 152 "item.hexic.stringworm_action": "毛绒线虫", 163 153 "item.hexic.stringworm_hex": "毛绒线虫", 164 154 "item.hexic.stringworm_media": "毛绒线虫", ··· 170 160 "itemGroup.hexic.group": "Hexic", 171 161 "tag.item.hexic.mediaweaves": "媒质布匹", 172 162 "text.hexic.or_map": "%s或映射", 173 - "text.hexic.pigment_holder_item": "存有染色剂的物品" 174 - } 163 + "text.hexic.pigment_holder_item": "存有染色剂的物品", 164 + "trinkets.slot.chest.hexic_mediaweave": "媒质布匹" 165 + }
+15 -17
project/hexic/src/main/scala/org/eu/net/pool/hexic/chat.scala
··· 137 137 @targetName("hexic$setPos") @Accessor("pos") private[hexic] def pos_=(pos: Float): Unit 138 138 139 139 extension (p: PlayerEntity) 140 - def validMediaweave: Option[(NbtCompound, DyeColor, ItemStack)] = 140 + def equippedMediaweave: Seq[(Mediaweave, ItemStack)] = 141 141 TrinketsApi.getTrinketComponent(p) 142 - .pipe(o => Option.when[TrinketComponent](o.isPresent)(o.get())) 142 + .pipe(o => Option.when[TrinketComponent](o.isPresent)(o.get()).toSeq) 143 143 .flatMap: (c: TrinketComponent) => 144 - c.getEquipped(_.getItem.isInstanceOf[Mediaweave]).asScala.collectFirst: 145 - Function.unlift: p => 146 - p.getRight.getItem match 147 - case m@Mediaweave(color) => Option(m.readIotaTag(p.getRight)).map((_, color, p.getRight)) 144 + c.getEquipped(_.getItem.isInstanceOf[Mediaweave]).asScala.collect: 145 + Function.unlift: e => 146 + e.getRight.getItem match 147 + case m: Mediaweave => Some(m, e.getRight) 148 148 case _ => None 149 + def validMediaweave: Option[(Mediaweave, ItemStack, ServerWorld ?=> Iota)] = 150 + p.equippedMediaweave.collectFirst: 151 + Function.unlift: 152 + case (item, stack) => Option(item.readIotaTag(stack)).map(tag => (item, stack, IotaType.deserialize(tag, summon[ServerWorld]))) 149 153 def catCollarColor: Option[DyeColor] = 150 - TrinketsApi.getTrinketComponent(p) 151 - .pipe(o => Option.when[TrinketComponent](o.isPresent)(o.get())) 152 - .flatMap: (c: TrinketComponent) => 153 - c.getEquipped(_.getItem.isInstanceOf[Mediaweave]).asScala.collectFirst: 154 - Function.unlift: p => 155 - p.getRight.getItem match 156 - case m@Mediaweave(color) if p.getRight.hasCustomName && p.getRight.getName.getString.toLowerCase == "instant cat" => Some(m.color) 157 - case _ => None 154 + p.equippedMediaweave.collectFirst: 155 + case (item, stack) if stack.hasCustomName && stack.getName.getString.toLowerCase == "instant cat" => item.color 158 156 extension (p: ServerPlayerEntity) 159 157 def executeMediaweave(text: String, ctx: Seq[Iota]): Boolean = 160 158 p.validMediaweave match 161 - case Some(hex, color, stack) => 159 + case Some(item, stack, hex) => 162 160 given world: ServerWorld = p.getWorld.asInstanceOf[ServerWorld] 163 161 lazy val env = new PlayerBasedCastEnv(p, Hand.OFF_HAND): 164 162 override def extractMediaEnvironment(cost: Long, simulate: Boolean): Long = 165 163 if p.isCreative then 0L else extractMediaFromInventory(cost, canOvercast, simulate) 166 164 override def getCastingHand: Hand = castingHand 167 - override def getPigment = FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS.get(color)), Util.NIL_UUID) 165 + override def getPigment = FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS.get(item.color)), Util.NIL_UUID) 168 166 val image = CastingImage(ctx :+ StringIota.make(text), 0, Seq(), false, 0, NbtCompound(), null) 169 - val instrs = IotaType.deserialize(hex, world) match 167 + val instrs = hex match 170 168 case list: ListIota => list.getList.asScala.toSeq 171 169 case iota => Seq(iota) 172 170 val vm = CastingVM(image, env)
+118 -32
project/hexic/src/main/scala/org/eu/net/pool/hexic/main.scala
··· 14 14 import at.petrak.hexcasting.api.casting.eval.{CastResult, CastingEnvironment, CastingEnvironmentComponent, MishapEnvironment, OperationResult, ResolvedPattern, ResolvedPatternType} 15 15 import at.petrak.hexcasting.api.casting.iota.* 16 16 import at.petrak.hexcasting.api.casting.math.{HexDir, HexPattern} 17 - import at.petrak.hexcasting.api.casting.mishaps.{Mishap, MishapBadCaster, MishapBadOffhandItem, MishapInvalidIota, MishapInvalidOperatorArgs, MishapNotEnoughArgs, MishapOthersName, MishapTooManyCloseParens} 17 + import at.petrak.hexcasting.api.casting.mishaps.{Mishap, MishapBadCaster, MishapInvalidIota, MishapInvalidOperatorArgs, MishapNotEnoughArgs, MishapOthersName, MishapTooManyCloseParens, MishapBadOffhandItem as MishapBadOffpawItem} 18 18 import at.petrak.hexcasting.api.pigment.FrozenPigment 19 19 import at.petrak.hexcasting.api.utils.{HexUtils, MediaHelper} 20 20 import at.petrak.hexcasting.common.lib.{HexAttributes, HexItems, HexRegistries, HexSounds} ··· 73 73 import net.minecraft.text.{HoverEvent, LiteralTextContent, MutableText, Style, Text, TextColor, TextContent, Texts} 74 74 import net.minecraft.util.dynamic.Codecs 75 75 import net.minecraft.util.math.{BlockPointer, BlockPos, ChunkPos, Direction, Vec3d} 76 - import net.minecraft.util.{ActionResult, Arm, ClickType, DyeColor, Formatting, Hand, Identifier, Rarity, TypedActionResult, Util, Uuids, WorldSavePath} 76 + import net.minecraft.util.{ActionResult, Arm, ClickType, DyeColor, Formatting, Identifier, Rarity, TypedActionResult, Util, Uuids, WorldSavePath, Hand as Paw} 77 77 import net.minecraft.world.biome.Biome 78 78 import net.minecraft.world.{BlockView, TeleportTarget, World} 79 79 import org.eu.net.pool.hexic ··· 168 168 169 169 import scala.util.matching.Regex 170 170 import at.petrak.hexcasting.api.casting.eval.vm.CastingImage.ParenthesizedIota 171 - import dev.emi.trinkets.api.{TrinketComponent, TrinketsApi} 171 + import at.petrak.hexcasting.interop.inline.InlinePatternData 172 + import dev.emi.trinkets.api 173 + import dev.emi.trinkets.api.{Trinket, TrinketComponent, TrinketEnums, TrinketsApi} 172 174 import net.beholderface.oneironaut.casting.iotatypes.DimIota 175 + import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback 173 176 import net.fabricmc.fabric.api.dimension.v1.FabricDimensions 174 177 import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents 175 178 import net.minecraft.block.dispenser.ItemDispenserBehavior ··· 489 492 490 493 case class Pen private [hexic] (color: DyeColor) extends Item(Item.Settings().maxCount(1)) with Registered(Registries.ITEM, s"pen/$color"): 491 494 override def toString = s"$getClass(color=$color)${super[Item].toString}" 492 - override def use(world: World, player: PlayerEntity, hand: Hand): TypedActionResult[ItemStack] = 495 + override def use(world: World, player: PlayerEntity, paw: Paw): TypedActionResult[ItemStack] = 493 496 // if player.getAttributeValue(HexAttributes.FEEBLE_MIND) > 0.0 then 494 - // TypedActionResult.fail(player.getStackInHand(hand)) 497 + // TypedActionResult.fail(player.getStackInHand(paw)) 495 498 // else 496 499 if !world.isClient && player.isInstanceOf[ServerPlayerEntity] then 497 500 val serverPlayer: ServerPlayerEntity = player.asInstanceOf[ServerPlayerEntity] 498 - val vm = IXplatAbstractions.INSTANCE.getStaffcastVM(serverPlayer, hand) 501 + val vm = IXplatAbstractions.INSTANCE.getStaffcastVM(serverPlayer, paw) 499 502 val patterns = IXplatAbstractions.INSTANCE.getPatternsSavedInUi(serverPlayer).asScala 500 503 val descs = vm.generateDescs 501 - IXplatAbstractions.INSTANCE.sendPacketToPlayer(serverPlayer, new MsgOpenSpellGuiS2C(hand, patterns, descs.getFirst, descs.getSecond, 0)) 504 + IXplatAbstractions.INSTANCE.sendPacketToPlayer(serverPlayer, new MsgOpenSpellGuiS2C(paw, patterns, descs.getFirst, descs.getSecond, 0)) 502 505 player.incrementStat(Stats.USED.getOrCreateStat(this)) 503 - TypedActionResult.success(player.getStackInHand(hand)) 506 + TypedActionResult.success(player.getStackInHand(paw)) 504 507 object Pen: 505 508 val instances: DyeColor :> Pen = DyeColor.values.map(c => c -> new Pen(c)).toMap 506 509 ··· 515 518 case c: NbtCompound => c 516 519 case _ => null 517 520 override def writeable(stack: ItemStack): Boolean = true 518 - override def canWrite(stack: ItemStack, iota: Iota): Boolean = iota match 519 - case l: ListIota => true 520 - case _ => iota.executable 521 + override def canWrite(stack: ItemStack, iota: Iota): Boolean = 522 + iota match 523 + case null => true 524 + case l: ListIota => true 525 + case _ => iota.executable 521 526 override def writeDatum(stack: ItemStack, iota: Iota): Unit = 522 - stack.getOrCreateNbt.put("Hex", IotaType.serialize(iota)) 527 + iota match 528 + case null => 529 + for nbt <- Option(stack.getNbt) do 530 + nbt.remove("Hex") 531 + if nbt.isEmpty then stack.setNbt(null) 532 + case iota => stack.getOrCreateNbt.put("Hex", IotaType.serialize(iota)) 523 533 override def appendTooltip(stack: ItemStack, world: World, tooltip: util.List[Text], context: TooltipContext): Unit = 524 534 IotaHolderItem.appendHoverText(this, stack, tooltip, context) 525 535 DispenserBlock.registerBehavior(this, new ItemDispenserBehavior: ··· 541 551 return stack 542 552 super.dispenseSilently(pointer, stack) 543 553 ) 554 + TrinketsApi.registerTrinket(this, Mediaweave.trinket) 544 555 object Mediaweave: 545 556 val colors: DyeColor :> Mediaweave = DyeColor.values().map(c => c -> Mediaweave(c)).toMap 546 557 val tag: TagKey[Item] = TagKey.of(Registries.ITEM, "mediaweaves") 558 + object trinket extends Trinket: 559 + override def canUnequip(stack: ItemStack, slot: api.SlotReference, entity: LivingEntity): Boolean = Option(stack).flatMap(s => Option(s.getNbt)).forall(_.get("lock") == null) 560 + override def getDropRule(stack: ItemStack, slot: api.SlotReference, entity: LivingEntity): TrinketEnums.DropRule = 561 + if Option(stack).flatMap(s => Option(s.getNbt)).exists(_.get("lock") == null) then 562 + TrinketEnums.DropRule.KEEP 563 + else 564 + super.getDropRule(stack, slot, entity) 547 565 548 566 extension (x: Iterable[Boolean]) 549 567 def any: Boolean = x.exists(identity) ··· 905 923 private val DUST_AMOUNT = new DecimalFormat("###,###.##") 906 924 val wizard = Item(Item.Settings().rarity(Rarity.EPIC).maxCount(1)) 907 925 908 - val aLotOfMedia = (200000 /* max phial size */ * 6 /* phials per small pouch */ * 4 /* small pouches per large pouch */ * (36 /* inventory slots */ + 4 /* armor slots */ + 2 /* offhands */) + 20 /* healthcasting */) * MediaConstants.DUST_UNIT 926 + val aLotOfMedia = (200000 /* max phial size */ * 6 /* phials per small pouch */ * 4 /* small pouches per large pouch */ * (36 /* inventory slots */ + 4 /* armor slots */ + 2 /* offpaws */) + 20 /* healthcasting */) * MediaConstants.DUST_UNIT 909 927 910 928 class Event[T, R](default: T => R) extends (T => R): 911 929 private var current = default ··· 976 994 977 995 trait MutableFunction[T, R] extends (T => R): 978 996 def update(key: T, value: R): Unit 997 + 998 + extension (img: CastingImage) 999 + def apply(stack: Seq[Iota] = img.getStack.toSeq, 1000 + parenCount: Int = img.getParenCount, 1001 + parenthesized: Seq[ParenthesizedIota] = img.getParenthesized.toSeq, 1002 + escapeNext: Boolean = img.getEscapeNext, 1003 + opsConsumed: Long = img.getOpsConsumed, 1004 + userData: NbtCompound = img.getUserData) = 1005 + CastingImage(stack = stack, 1006 + parenCount = parenCount, 1007 + parenthesized = parenthesized, 1008 + escapeNext = escapeNext, 1009 + opsConsumed = opsConsumed, 1010 + userData = userData, 1011 + null : DefaultConstructorMarker) 979 1012 980 1013 def init(): Unit = 981 1014 given_Logger.info: ··· 1071 1104 override def getCollisionShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape = 1072 1105 getOutlineShape(state, world, pos, context) 1073 1106 1074 - override def onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockHitResult): ActionResult = boundary: 1107 + override def onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, paw: Paw, hit: BlockHitResult): ActionResult = boundary: 1075 1108 lazy val entity = findEntity(world, pos).getOrElse(boundary.break(ActionResult.FAIL)) 1076 - player.getStackInHand(hand) match 1109 + player.getStackInHand(paw) match 1077 1110 case stack@ItemStackAccess(HexItems.CHARGED_AMETHYST, _, _) if !(for i <- 0 until 14; j <- 0 until 14 yield entity.bit(i, j)).all => 1078 1111 for i <- 0 until 14; j <- 0 until 14 do 1079 1112 entity.bit(i, j) = true ··· 1113 1146 registerHopperEndpoint <- classNamed("org.eu.net.pool.registerHopperEndpoint") 1114 1147 do 1115 1148 registerHopperEndpoint.runtimeClass.newInstance().asInstanceOf[() => Unit]() 1116 - Patterns.register("dye_offhand", w"eqdeeqdweeqddqdwwdew"): 1149 + Patterns.register("dye_offpaw", w"eqdeeqdweeqddqdwwdew"): 1117 1150 Patterns.mkAction: (img, cont) => 1118 1151 val stack = img.getStack.asScala 1119 1152 stack.lastOption.getOrElse(throw MishapNotEnoughArgs(1, 0)) match 1120 1153 case p: PigmentIota => 1121 - val info = summon[CastingEnvironment].getHeldItemToOperateOn(!_.isEmpty).pipe(Option(_)).getOrElse(throw MishapBadOffhandItem(null, Text.translatable("text.hexic.pigment_holder_item"))) 1154 + val info = summon[CastingEnvironment].getHeldItemToOperateOn(!_.isEmpty).pipe(Option(_)).getOrElse(throw MishapBadOffpawItem(null, Text.translatable("text.hexic.pigment_holder_item"))) 1122 1155 (img.withStack(_.init), cont, HexEvalSounds.SPELL, Seq: 1123 1156 OperatorSideEffect.AttemptSpell( 1124 1157 new RenderedSpell: ··· 1134 1167 case i => throw MishapInvalidIota.ofType(i, 0, "pigment") 1135 1168 Patterns.register("prop_fi", sw"aawqe"): 1136 1169 Patterns.mkConstAction(1): 1137 - case Seq(x: PropertyIota) => Seq(PropertyAccessIota.Writer(x.getName, "head")) 1138 - case Seq(x) => throw MishapInvalidIota(x, 0, "property") 1170 + case Seq(x: PropertyIota) if !x.getReadonly => Seq(PropertyAccessIota.Writer(x.getName, "head")) 1171 + case Seq(x) => throw MishapInvalidIota(x, 0, "writeable_prop") 1139 1172 Patterns.register("prop_fo", sw"aawqd"): 1140 1173 Patterns.mkConstAction(1): 1141 - case Seq(x: PropertyIota) => Seq(PropertyAccessIota.Stream(x.getName, "head")) 1142 - case Seq(x) => throw MishapInvalidIota(x, 0, "property") 1174 + case Seq(x: PropertyIota) if !x.getReadonly => Seq(PropertyAccessIota.Stream(x.getName, "head")) 1175 + case Seq(x) => throw MishapInvalidIota(x, 0, "writeable_prop") 1143 1176 Patterns.register("prop_li", sw"aawdwq"): 1144 1177 Patterns.mkConstAction(1): 1145 - case Seq(x: PropertyIota) => Seq(PropertyAccessIota.Writer(x.getName, "tail")) 1146 - case Seq(x) => throw MishapInvalidIota(x, 0, "property") 1178 + case Seq(x: PropertyIota) if !x.getReadonly => Seq(PropertyAccessIota.Writer(x.getName, "tail")) 1179 + case Seq(x) => throw MishapInvalidIota(x, 0, "writeable_prop") 1147 1180 Patterns.register("prop_lo", sw"aawdwa"): 1148 1181 Patterns.mkConstAction(1): 1149 - case Seq(x: PropertyIota) => Seq(PropertyAccessIota.Stream(x.getName, "tail")) 1150 - case Seq(x) => throw MishapInvalidIota(x, 0, "property") 1182 + case Seq(x: PropertyIota) if !x.getReadonly => Seq(PropertyAccessIota.Stream(x.getName, "tail")) 1183 + case Seq(x) => throw MishapInvalidIota(x, 0, "writeable_prop") 1151 1184 Patterns.register("where", nw"qaeaqwdd"): 1152 1185 Patterns.mkConstAction(1): i => 1153 1186 val Seq(x) = i ··· 1205 1238 FoxEntity.Type.fromBiome(p.getWorld.getBiome(p.getBlockPos)) 1206 1239 Patterns.register("unfox", se"wqwqwqwaeeaw"): 1207 1240 fox { case Some(_) => None } 1241 + // /data get entity @s cardinal_components."trinkets:trinkets".chest.hexic_mediaweave.Items[0].tag.lock 1242 + Patterns.register("collar", sw"aqeqqqwqqqqqaqwqa"): 1243 + Patterns.mkAction: (img, cont) => 1244 + // (→) patterns do not need to modify the image 1245 + summon[CastingEnvironment] match 1246 + case env: PlayerBasedCastEnv => 1247 + val consume = OperatorSideEffect.ConsumeMedia(15000) 1248 + if isDev then println(s"starting with ${env.getCaster.equippedMediaweave}") 1249 + ( 1250 + img, cont, 1251 + HexEvalSounds.SPELL, 1252 + for 1253 + (_, stack) <- env.getCaster.equippedMediaweave 1254 + if isDev && { println(s"ok ${stack} how ya ${stack.getNbt} okie ${Option(stack.getNbt).forall(_.get("lock") == null)}"); true } 1255 + if Option(stack.getNbt).forall(_.get("lock") == null) 1256 + e <- Seq( 1257 + consume, 1258 + OperatorSideEffect.AttemptSpell( 1259 + new RenderedSpell: 1260 + override def cast(env: CastingEnvironment): Unit = 1261 + stack.getOrCreateNbt().put("lock", NbtCompound()) 1262 + override def cast(env: CastingEnvironment, img: CastingImage): CastingImage = { cast(env); img } 1263 + , true, true 1264 + ) 1265 + ) 1266 + yield e 1267 + ) 1268 + case _ => throw MishapBadCaster() 1269 + Patterns.register("decollar", ne"wwqaqqqqqwqqqew"): 1270 + Patterns.mkAction: (img, cont) => 1271 + // (→) patterns do not need to modify the image 1272 + summon[CastingEnvironment] match 1273 + case env: PlayerBasedCastEnv => 1274 + val consume = OperatorSideEffect.ConsumeMedia(15000) 1275 + ( 1276 + img, cont, 1277 + HexEvalSounds.SPELL, 1278 + for 1279 + (_, stack) <- env.getCaster.equippedMediaweave 1280 + if Option(stack.getNbt).exists(_.get("lock") != null) 1281 + e <- Seq( 1282 + consume, 1283 + OperatorSideEffect.AttemptSpell( 1284 + new RenderedSpell: 1285 + override def cast(env: CastingEnvironment): Unit = 1286 + Option(stack.getNbt).foreach(_.remove("lock")) 1287 + override def cast(env: CastingEnvironment, img: CastingImage): CastingImage = { cast(env); img } 1288 + , true, true 1289 + ) 1290 + ) 1291 + yield e 1292 + ) 1293 + case _ => throw MishapBadCaster() 1208 1294 hexXplat.getArithmeticRegistry("null_abs") = arith("null_abs", Arithmetic.ABS -> ((_: NullIota) => DoubleIota(0))) 1209 1295 val planeCaches = ju.WeakHashMap[MinecraftServer, mutable.Map[UUID, RuntimeWorldHandle]]() 1210 1296 def planeCache(using server: MinecraftServer): mutable.Map[UUID, RuntimeWorldHandle] = planeCaches.computeIfAbsent(server, _ => mutable.Map()) ··· 1375 1461 override def cast(env: CastingEnvironment): Unit = 1376 1462 world.parentInfo = Some(env.getWorld.getRegistryKey, pos) 1377 1463 override def cast(env: CastingEnvironment, image: CastingImage): CastingImage = { cast(env); image }, 1378 - MediaConstants.SHARD_UNIT * 3, 1464 + MediaConstants.SHARD_UNIT, 1379 1465 Seq(), 1380 1466 1 1381 1467 ) ··· 1501 1587 summon[CastingEnvironment].getCastingEntity match 1502 1588 case caster: ServerPlayerEntity => 1503 1589 val staffcast = HexCardinalComponents.STAFFCAST_IMAGE.get(caster) 1504 - val oldImage = staffcast.getVM(Hand.MAIN_HAND).getImage 1590 + val oldImage = staffcast.getVM(Paw.MAIN_HAND).getImage 1505 1591 staffcast.setImage(img) 1506 1592 val vm = staffcast.getVM(summon[CastingEnvironment].getCastingHand) 1507 1593 try ··· 1568 1654 others = others.filter: 1569 1655 case _: EntityPlayerMPFake => false 1570 1656 case _ => true 1571 - val sorted = others.toSeq.sortBy(_.getPos.squaredDistanceTo(summon[CastingEnvironment].mishapSprayPos)) 1657 + val sorted = others.toSeq.sortBy(_.getPos.squaredDistanceTo(summon[CastingEnvironment].mishapSprayPos)).filter(summon[CastingEnvironment].isEntityInRange(_, true)) 1572 1658 sorted.headOption.fold(NullIota())(EntityIota(_)) 1573 1659 Patterns.register("blind", se"qqqqqadwawawd")(OpPotionEffect(StatusEffects.BLINDNESS, 1000, false, false)) 1574 1660 Patterns.register("erase", e"wqwdwqwawwwwwawwwww"): ··· 1693 1779 case Seq() => throw MishapNotEnoughArgs(2, 0) 1694 1780 case Seq(_) => throw MishapNotEnoughArgs(2, 1) 1695 1781 case saved:+(target: ListIota):+(filter: ListIota) => 1696 - if filter.isEmpty then (img.withStack(_ :+ ListIota(target.getList.filter(_.isTruthy).toSeq)), cont, HexEvalSounds.THOTH, Seq()) // short-circuit on empty filter 1782 + if filter.isEmpty then (img.withStack(_.dropRight(2) :+ ListIota(target.getList.filter(_.isTruthy).toSeq)), cont, HexEvalSounds.THOTH, Seq()) // short-circuit on empty filter 1697 1783 else target.getList.toSeq match 1698 1784 case first +: rest => 1699 1785 // set up filter, ideally FilterFrame would do this 1700 - (img.withStack(_ :+ first), cont.pushFrame(FilterFrame(saved, filter.getList.toSeq, first, Seq(), rest)).pushFrame(FrameEvaluate(filter.getList, true)), HexEvalSounds.THOTH, Seq()) 1786 + (img.withStack(_.dropRight(2) :+ first), cont.pushFrame(FilterFrame(saved, filter.getList.toSeq, first, Seq(), rest)).pushFrame(FrameEvaluate(filter.getList, true)), HexEvalSounds.THOTH, Seq()) 1701 1787 case _ => 1702 1788 // we can't start a filter with no iota, but it'd always be empty anyway 1703 - (img.withStack(_ :+ ListIota(Seq())), cont, HexEvalSounds.THOTH, Seq()) 1789 + (img.withStack(_.dropRight(2) :+ ListIota(Seq())), cont, HexEvalSounds.THOTH, Seq()) 1704 1790 case saved:+(_: ListIota):+filter => throw MishapInvalidIota.ofType(filter, 1, "list") 1705 1791 case saved:+target:+_ => throw MishapInvalidIota.ofType(target, 1, "list") 1706 1792 Patterns.register("extract", nw"dewaqawed"): ··· 1782 1868 for axis <- Direction.Axis.values do 1783 1869 val x = pos.getComponentAlongAxis(axis) 1784 1870 if x < 0 || x >= 11 then boundary.break(false) 1785 - true 1871 + current 1786 1872 // dump patterns 1787 1873 val out = Files.newOutputStream(Path.of("patterns.csv")) 1788 1874 try
+4 -10
project/hexic/src/main/scala/org/eu/net/pool/hexic/mixin/EntityMixin.java
··· 27 27 28 28 @Mixin(Entity.class) 29 29 public abstract class EntityMixin { 30 - @Unique BlockPos.Mutable hexic$scanPos = new BlockPos.Mutable(); 31 - 32 30 @Shadow public abstract World getWorld(); 33 31 @Shadow public abstract Box getBoundingBox(); 34 32 @Shadow private World world; ··· 59 57 return; 60 58 } 61 59 } 62 - CuboidBlockIterator iter = new CuboidBlockIterator(MathHelper.ceil(box.minX), MathHelper.ceil(box.minY), MathHelper.ceil(box.minZ), MathHelper.ceil(box.maxX), MathHelper.ceil(box.maxY), MathHelper.ceil(box.maxZ)); 63 - while (iter.step()) { 64 - hexic$scanPos.set(iter.getX(), iter.getY(), iter.getZ()); 65 - if (world.getBlockState(hexic$scanPos).isOf(VOID_AIR)) { 66 - tickInVoid(); 67 - ci.cancel(); 68 - return; 69 - } 60 + if (BlockPos.stream(box).anyMatch(p -> world.getBlockState(p).isOf(VOID_AIR))) { 61 + tickInVoid(); 62 + ci.cancel(); 63 + return; 70 64 } 71 65 } 72 66
+3 -7
project/hexic/src/main/scala/org/eu/net/pool/hexic/mixin/ItemMixin.java
··· 3 3 import at.petrak.hexcasting.api.casting.eval.vm.CastingVM; 4 4 import at.petrak.hexcasting.api.casting.iota.GarbageIota; 5 5 import at.petrak.hexcasting.api.casting.iota.IotaType; 6 - import at.petrak.hexcasting.api.casting.iota.ListIota; 7 6 import at.petrak.hexcasting.xplat.IXplatAbstractions; 8 7 import net.minecraft.client.item.TooltipContext; 9 8 import net.minecraft.entity.player.PlayerEntity; ··· 14 13 import net.minecraft.nbt.NbtList; 15 14 import net.minecraft.server.network.ServerPlayerEntity; 16 15 import net.minecraft.server.world.ServerWorld; 17 - import net.minecraft.text.MutableText; 18 16 import net.minecraft.text.Text; 19 - import net.minecraft.text.TranslatableTextContent; 20 17 import net.minecraft.util.Hand; 21 18 import net.minecraft.util.TypedActionResult; 22 19 import net.minecraft.world.World; 23 20 import org.jetbrains.annotations.Nullable; 24 21 import org.spongepowered.asm.mixin.Mixin; 25 - import org.spongepowered.asm.mixin.Unique; 26 22 import org.spongepowered.asm.mixin.injection.At; 27 23 import org.spongepowered.asm.mixin.injection.Inject; 28 24 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; ··· 45 41 } 46 42 47 43 @Inject(method = "use", at = @At("HEAD"), cancellable = true) 48 - void use(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable<TypedActionResult<ItemStack>> cir) { 44 + void use(World world, PlayerEntity user, Hand paw, CallbackInfoReturnable<TypedActionResult<ItemStack>> cir) { 49 45 if ((Object) this != ECHO_SHARD) return; 50 - ItemStack stack = user.getStackInHand(hand); 46 + ItemStack stack = user.getStackInHand(paw); 51 47 NbtCompound nbt = stack.getNbt(); 52 48 if (nbt == null) return; 53 49 NbtList patterns = nbt.getList("hexic:memory", NbtElement.COMPOUND_TYPE); 54 50 if (patterns.isEmpty() || world.isClient || !(world instanceof ServerWorld serverWorld && user instanceof ServerPlayerEntity serverPlayer)) return; 55 - CastingVM staffcast = IXplatAbstractions.INSTANCE.getStaffcastVM(serverPlayer, hand); 51 + CastingVM staffcast = IXplatAbstractions.INSTANCE.getStaffcastVM(serverPlayer, paw); 56 52 stack.decrement(1); 57 53 NbtCompound newNbt = nbt.copy(); 58 54 newNbt.remove("hexic:memory");
+6
project/hexic/src/main/scala/org/eu/net/pool/hexic/mixin/ItemStackMixin.java
··· 5 5 import net.minecraft.item.ItemStack; 6 6 import net.minecraft.nbt.NbtCompound; 7 7 import net.minecraft.nbt.NbtElement; 8 + import org.eu.net.pool.hexic.cfg; 8 9 import org.spongepowered.asm.mixin.Mixin; 9 10 import org.spongepowered.asm.mixin.Shadow; 10 11 import org.spongepowered.asm.mixin.injection.At; 11 12 import org.spongepowered.asm.mixin.injection.Inject; 12 13 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 + import scala.util.CommandLineParser; 13 15 14 16 @Mixin(ItemStack.class) 15 17 public class ItemStackMixin { ··· 20 22 if (nbt.contains("Count", NbtElement.INT_TYPE)) { 21 23 count = nbt.getInt("Count"); 22 24 } 25 + int minSize = cfg.apply("hexic.min_stack_size", Integer::parseInt).getOrElse(() -> 0); 26 + int maxSize = cfg.apply("hexic.max_stack_size", Integer::parseInt).getOrElse(() -> Integer.MAX_VALUE); 27 + if (count < minSize) count = minSize; 28 + if (count > maxSize) count = maxSize; 23 29 } 24 30 25 31 @WrapOperation(method = {"writeNbt", "method_7953"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NbtCompound;putByte(Ljava/lang/String;B)V"))
+2 -2
project/hexic/src/main/scala/org/eu/net/pool/hexic/mixin/OpEdifySaplingMixin.java
··· 41 41 return true; 42 42 } 43 43 if (original.call(instance, BlockTags.WOOL)) { 44 - mediaweave.set(3); 44 + mediaweave.set(2); 45 45 return true; 46 46 } 47 47 if (original.call(instance, BlockTags.WOOL_CARPETS)) { 48 - mediaweave.set(2); 48 + mediaweave.set(3); 49 49 return true; 50 50 } 51 51 if (instance.isOf(Blocks.TRIPWIRE)) {
+3 -3
project/hexic/src/main/scala/org/eu/net/pool/hexic/mixin/StaffCastEnvMixin.java
··· 62 62 return; 63 63 } 64 64 // TODO: consider whether shards should intercept pen patterns 65 - ItemStack offhandStack = sender.getStackInHand(vm.getEnv().getOtherHand()); 66 - if (offhandStack.isOf(ECHO_SHARD)) { 67 - NbtCompound tag = offhandStack.getOrCreateNbt(); 65 + ItemStack offpawStack = sender.getStackInHand(vm.getEnv().getOtherHand()); 66 + if (offpawStack.isOf(ECHO_SHARD)) { 67 + NbtCompound tag = offpawStack.getOrCreateNbt(); 68 68 NbtList queuedPatterns = tag.getList("hexic:memory", NbtElement.COMPOUND_TYPE); 69 69 queuedPatterns.add(IotaType.serialize(new PatternIota(msg.pattern()))); 70 70 tag.put("hexic:memory", queuedPatterns);
+99 -39
project/hexic/src/main/scala/org/eu/net/pool/hexic/views.scala
··· 3 3 import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic 4 4 import at.petrak.hexcasting.api.casting.circles.BlockEntityAbstractImpetus 5 5 import at.petrak.hexcasting.api.casting.eval.CastingEnvironment 6 + import at.petrak.hexcasting.api.casting.eval.env.PlayerBasedCastEnv 6 7 import at.petrak.hexcasting.api.casting.iota.* 7 - import at.petrak.hexcasting.api.casting.mishaps.{Mishap, MishapInvalidIota} 8 + import at.petrak.hexcasting.api.casting.mishaps.{Mishap, MishapInvalidIota, MishapOthersName} 8 9 import com.mojang.serialization.Codec 10 + import com.samsthenerd.inline.api.InlineAPI 9 11 import com.samsthenerd.inline.api.data.ItemInlineData 12 + import com.samsthenerd.inline.impl.InlineStyle 10 13 import net.fabricmc.fabric.api.dimension.v1.FabricDimensions 11 14 import net.fabricmc.fabric.api.event.{Event, EventFactory} 15 + import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys 12 16 import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant 13 17 import net.fabricmc.fabric.api.transfer.v1.item.{ItemStorage, ItemVariant} 14 18 import net.fabricmc.fabric.api.transfer.v1.storage.{Storage, TransferVariant} 15 19 import net.fabricmc.fabric.api.transfer.v1.transaction.base.SnapshotParticipant 16 20 import net.fabricmc.fabric.api.transfer.v1.transaction.{Transaction, TransactionContext} 17 - import net.minecraft.block.BlockState 21 + import net.minecraft.block.{AbstractFurnaceBlock, BlockState} 18 22 import net.minecraft.block.entity.AbstractFurnaceBlockEntity 19 - import net.minecraft.entity.Entity 20 - import net.minecraft.fluid.Fluid 21 - import net.minecraft.item.Item 23 + import net.minecraft.entity.decoration.ItemFrameEntity 24 + import net.minecraft.entity.player.PlayerEntity 25 + import net.minecraft.entity.{Entity, ItemEntity} 26 + import net.minecraft.fluid.{Fluid, Fluids} 27 + import net.minecraft.item.{Item, Items} 22 28 import net.minecraft.nbt.{NbtCompound, NbtElement, NbtList, NbtLong} 23 29 import net.minecraft.registry.{RegistryKey, RegistryKeys} 24 30 import net.minecraft.server.MinecraftServer ··· 26 32 import net.minecraft.text.{HoverEvent, MutableText, Text} 27 33 import net.minecraft.util.Identifier 28 34 import net.minecraft.util.math.{BlockPos, Box} 29 - import net.minecraft.world.{TeleportTarget, World} 35 + import net.minecraft.world.{BlockView, TeleportTarget, World} 30 36 import org.eu.net.pool.phlib.{*, given} 31 37 import org.slf4j.{Logger, LoggerFactory} 38 + import ram.talia.moreiotas.api.casting.iota.{ItemStackIota, ItemTypeIota} 32 39 33 40 import java.util.UUID 41 + import scala.annotation.tailrec 34 42 import scala.collection.immutable.ArraySeq.unsafeWrapArray 35 43 import scala.collection.mutable 36 44 import scala.reflect.ClassTag 37 - import scala.util.{Failure, Success, Using} 45 + import scala.util.{Failure, Success, Using, boundary} 38 46 39 47 trait InventoryView(val viewType: InventoryView.Type[?]) extends InventoryView.Handler: 40 48 def isTruthy = true ··· 44 52 def deserialize(data: NbtCompound)(using ServerWorld): Option[T] 45 53 trait Handler: 46 54 def apply(idx: Int)(using CastingEnvironment): Option[SlotReference] = None 55 + def contents(using TransactionContext, CastingEnvironment): Set[VariantIota[?]] = Set() 47 56 def tryExtract(variant: TransferVariant[?], amount: Long)(using TransactionContext, CastingEnvironment): Long = 0 48 57 def tryInsert(variant: TransferVariant[?], amount: Long)(using TransactionContext, CastingEnvironment): Long = 0 49 58 def capacity(variant: TransferVariant[?])(using TransactionContext, CastingEnvironment): Long = ··· 68 77 abstract class OfMerged(viewType: InventoryView.Type[?], views: => Seq[Handler]) extends InventoryView(viewType): 69 78 def getViews = views 70 79 override def apply(idx: Int)(using CastingEnvironment): Option[SlotReference] = views.collectFirst(Function.unlift(_(idx))) 80 + override def contents(using TransactionContext, CastingEnvironment) = views.flatMap(_.contents).toSet 71 81 override def tryExtract(variant: TransferVariant[?], amount: Long)(using TransactionContext, CastingEnvironment): Long = LazyList.from(views).scanLeft(0L)((n, view) => view.tryExtract(variant, amount - n) + n).findFirstOrLast(_ >= amount).getOrElse(0) 72 82 override def tryInsert(variant: TransferVariant[?], amount: Long)(using TransactionContext, CastingEnvironment): Long = LazyList.from(views).scanLeft(0L)((n, view) => view.tryInsert(variant, amount - n) + n).findFirstOrLast(_ >= amount).getOrElse(0) 73 83 override def capacity(variant: TransferVariant[?])(using TransactionContext, CastingEnvironment) = views.map(_.capacity(variant)).sum ··· 101 111 if w.getPath != "overworld" then c.put("w", w.getPath) 102 112 c.putLong("p", pos.asLong) 103 113 c 104 - class OfExactEntity(entity: => Entity)(using ServerWorld) extends InventoryView(typeOfExactEntity): 105 - override val viewType = typeOfExactEntity 106 - override def entities(using TransactionContext) = Set(entity) 107 - override def serialize = 108 - val c = super.serialize 109 - // TODO 110 - c 111 114 def deserialize(data: NbtCompound)(using ServerWorld): Option[InventoryView] = for 112 115 id <- Option(Identifier.tryParse(data.getString("id"))) 113 116 viewType <- Option(InventoryView.registry.get(id)) ··· 122 125 view <- InventoryView.deserialize(c) 123 126 yield view)*)) 124 127 private given typeOfEntity: InventoryView.Type[OfEntity]: 125 - override def deserialize(data: NbtCompound)(using ServerWorld): Option[OfEntity] = ??? 128 + override def deserialize(data: NbtCompound)(using world: ServerWorld): Option[OfEntity] = 129 + given MinecraftServer = world.getServer 130 + Some(OfEntity(UUID(data.getLong("m"), data.getLong("l")))) 126 131 private given typeOfBlock: InventoryView.Type[OfBlock]: 127 132 override def deserialize(data: NbtCompound)(using ServerWorld): Option[OfBlock] = 128 133 for ··· 133 138 key = RegistryKey.of(RegistryKeys.WORLD, Identifier.of(namespace, path)) 134 139 given ServerWorld <- Option(summon[ServerWorld].getServer.getWorld(key)) 135 140 yield OfBlock(pos) 136 - private given typeOfExactEntity: InventoryView.Type[OfExactEntity]: 137 - override def deserialize(data: NbtCompound)(using ServerWorld): Option[OfExactEntity] = ??? 138 141 registry("sum") = typeOfSum 139 142 registry("entity") = typeOfEntity 140 143 registry("block") = typeOfBlock 141 - registry("exact") = typeOfExactEntity 142 144 Events.forBlock.register: (pos, state) => 143 145 val storage = ItemStorage.SIDED.find(summon, pos, null): Storage[ItemVariant] 144 146 if storage == null then Seq() 145 147 else Seq( 146 148 new Handler: 149 + override def contents(using TransactionContext, CastingEnvironment): Set[VariantIota[?]] = storage.nonEmptyIterator.map(v => VariantIota(v.getResource, RegistryKey.of(VariantIota.key, Identifier("item")))).toSet 147 150 override def tryInsert(variant: TransferVariant[?], amount: Long)(using TransactionContext, CastingEnvironment): Long = 148 151 variant match 149 152 case i: ItemVariant => storage.insert(i, amount, summon) ··· 163 166 true 164 167 ) 165 168 else Seq() 166 - trait SingleVariantHandler(variant: TransferVariant[?]) extends Handler: 169 + trait SingleVariantHandler[O: ClassTag](variant: TransferVariant[O], key: RegistryKey[VariantIota.Reader]) extends Handler: 170 + def asIota = VariantIota(variant, key) 171 + def isPresent(using TransactionContext, CastingEnvironment): Boolean = true 172 + override def contents(using TransactionContext, CastingEnvironment): Set[VariantIota[?]] = if isPresent then Set(asIota) else Set() 167 173 override def tryExtract(variant: TransferVariant[?], amount: Long)(using TransactionContext, CastingEnvironment): Long = if variant == this.variant then trySubtract(amount) else 0L 168 174 override def tryInsert(variant: TransferVariant[?], amount: Long)(using TransactionContext, CastingEnvironment): Long = if variant == this.variant then tryAdd(amount) else 0L 169 175 override def capacity(variant: TransferVariant[?])(using TransactionContext, CastingEnvironment): Long = if variant == this.variant then cap else 0L ··· 173 179 174 180 Events.forBlock.register: (pos, state) => 175 181 summon[ServerWorld].getBlockEntity(pos) match 176 - case e: BlockEntityAbstractImpetus => Seq(new SingleVariantHandler(SingletonVariant.media) { 182 + case e: BlockEntityAbstractImpetus => Seq(new SingleVariantHandler(SingletonVariant.media, RegistryKey.of(VariantIota.key, "media")) { 177 183 private def mediaCapacity = 9000000000000000000L - e.getMedia 178 184 override def trySubtract(amount: Long)(using TransactionContext, CastingEnvironment): Long = 179 185 val toExtract = amount min e.getMedia ··· 189 195 Events.forBlock.register: (pos, state) => 190 196 summon[ServerWorld].getBlockEntity(pos) match 191 197 case e: AbstractFurnaceBlockEntity => Seq( 192 - new SingleVariantHandler(SingletonVariant.heat): 198 + new SingleVariantHandler(SingletonVariant.heat, RegistryKey.of(VariantIota.key, "heat")): 193 199 override def trySubtract(amount: Long)(using TransactionContext, CastingEnvironment): Long = 194 200 val action = (amount min e.burnTime).toInt 195 201 doSnapshot(e.burnTime, e.burnTime = _)(e.burnTime - action) 202 + doSnapshot(summon[ServerWorld].getBlockState(pos), summon[ServerWorld].setBlockState(pos, _, 3))(summon[ServerWorld].getBlockState(pos).`with`(AbstractFurnaceBlock.LIT, true)) 196 203 action 197 204 override def tryAdd(amount: Long)(using TransactionContext, CastingEnvironment): Long = 198 205 val action = (amount min cap).toInt ··· 226 233 227 234 object BoxedView extends IotaType[BoxedView.Instance]: 228 235 InventoryView 229 - class Instance(val view: InventoryView) extends Iota(BoxedView, view): 236 + case class Instance(view: InventoryView) extends Iota(BoxedView, view): 230 237 export view.{isTruthy, serialize} 231 238 override def toleratesOther(that: Iota): Boolean = that match 232 239 case that: BoxedView.Instance => view == that.view ··· 272 279 val pos = BlockPos.ofFloored(block.getVec3) 273 280 summon[CastingEnvironment].assertPosInRangeForEditing(pos) 274 281 InventoryView.OfBlock(pos) 282 + case entity: EntityIota => 283 + given MinecraftServer = summon[CastingEnvironment].getWorld.getServer 284 + entity.getEntity match 285 + case p: PlayerEntity => 286 + summon[CastingEnvironment] match 287 + case env: PlayerBasedCastEnv => 288 + if env.getCaster == p then 289 + InventoryView.OfEntity(p.getUuid) 290 + else 291 + throw MishapOthersName(p) 292 + case e => InventoryView.OfEntity(e.getUuid) 275 293 hexXplat.getArithmeticRegistry("view") = arith("view", 276 294 Arithmetic.ADD -> { 277 295 (view1: BoxedView.Instance, view2: BoxedView.Instance) => Seq(BoxedView.Instance(InventoryView.OfSum(view1.view, view2.view))) ··· 282 300 setConceptScale[SingletonVariant.heat.type](20) 283 301 Patterns.register("moveconcept", se"wawdwawqdewewedqwawdwaw"): 284 302 Patterns.mkConstAction(4): 285 - case Seq(isIota[BoxedView.Instance, 3](from), isIota[BoxedView.Instance, 2](into), typ: VariantIota[?], isIota[DoubleIota, 0](count)) => 286 - Using.resource(Transaction.openOuter()): 303 + case Seq(isIota[BoxedView.Instance, 3](BoxedView.Instance(from)), isIota[BoxedView.Instance, 2](BoxedView.Instance(into)), typ: VariantIota[?], isIota[DoubleIota, 0](count)) => 304 + val key = ClassTag(typ.data.getClass) 305 + val scale = conceptScale(key) 306 + @tailrec def negotiate(limit: Long): Seq[Iota] = 307 + val compromise = Using.resource(Transaction.openOuter()): 308 + case tx@given TransactionContext => 309 + val extracted = (from: InventoryView).tryExtract((typ: VariantIota[?]).data, limit) 310 + val inserted = (into: InventoryView).tryInsert((typ: VariantIota[?]).data, extracted) 311 + if extracted == inserted then 312 + tx.commit() 313 + return Seq(DoubleIota(inserted / scale)) 314 + else 315 + inserted 316 + negotiate(compromise) 317 + val initialLimit = Using.resource(Transaction.openOuter()): 287 318 case tx@given TransactionContext => 288 - val key = ClassTag(typ.data.getClass) 289 - val scale = conceptScale(key) 290 - val toExtract = (scale * count.getDouble).toLong 291 - val extract = from.view.tryExtract(typ.data, toExtract) 292 - if extract < toExtract then 293 - ??? // TODO: mishap 294 - val insert = into.view.tryInsert(typ.data, extract) 295 - if insert < extract then 296 - ??? // TODO: mishap 297 - tx.commit() 298 - Seq(DoubleIota(insert / scale)) 319 + val value = (into: InventoryView).tryInsert(typ.data, (scale * count.getDouble).toLong) 320 + tx.abort() 321 + value 322 + negotiate(initialLimit) 323 + 299 324 Patterns.register("moveentity", se"edeeewawdweaaddaqwqwqaddaaewdwawewdqd"): 300 325 Patterns.mkConstAction(3): 301 326 case Seq(isIota[BoxedView.Instance, 2](from), isIota[BoxedView.Instance, 1](into), isIota[DoubleIota, 0](count)) => ··· 304 329 val count = from.view.entities.count(into.view.teleportEntity) 305 330 if count > 0 then tx.commit() 306 331 Seq(DoubleIota(count)) 307 - 332 + Patterns.register("thinkaboutit", e"awqawewaqw"): 333 + Patterns.mkConstAction(1): 334 + case Seq(iota) => 335 + def dieOfBadType() = throw MishapInvalidIota.of(iota, 0, "hexic:not_eldritch_horror") 336 + iota match 337 + case BoxedView.Instance(view) => 338 + Using.resource(Transaction.openOuter()): 339 + case given TransactionContext => 340 + Seq(ListIota(view.contents.toSeq)) 341 + case i: ItemStackIota => Seq(if i.getItemStack.getItem == Items.AIR then NullIota() else VariantIota(ItemVariant.of(i.getItemStack), RegistryKey.of(VariantIota.key, Identifier("item")))) 342 + case i: ItemTypeIota => Seq(if i.getItem == Items.AIR then NullIota() else VariantIota(ItemVariant.of(i.getItem), RegistryKey.of(VariantIota.key, Identifier("item")))) 343 + case v: Vec3Iota => 344 + val pos = BlockPos.ofFloored(v.getVec3) 345 + summon[CastingEnvironment].assertPosInRange(pos) 346 + val state = summon[BlockView].getBlockState(pos) 347 + if state.isAir then 348 + Seq(NullIota()) 349 + else 350 + state.getFluidState.getFluid match 351 + case Fluids.EMPTY => 352 + state.getBlock.asItem match 353 + case null | Items.AIR => 354 + state.getBlock.getPickStack(summon, pos, state) match 355 + case null | Items.AIR => 356 + Seq(NullIota()) 357 + case item => Seq(VariantIota(ItemVariant.of(item), RegistryKey.of(VariantIota.key, Identifier("item")))) 358 + case item => Seq(VariantIota(ItemVariant.of(item), RegistryKey.of(VariantIota.key, Identifier("item")))) 359 + case fluid => Seq(VariantIota(FluidVariant.of(fluid), RegistryKey.of(VariantIota.key, Identifier("fluid")))) 360 + case e: EntityIota if !e.getEntity.isRemoved => 361 + e.getEntity match 362 + case s: ItemEntity => Seq(if s.getStack.getItem == Items.AIR then NullIota() else VariantIota(ItemVariant.of(s.getStack), RegistryKey.of(VariantIota.key, Identifier("item")))) 363 + case s: ItemFrameEntity => Seq(if s.getHeldItemStack.getItem == Items.AIR then NullIota() else VariantIota(ItemVariant.of(s.getHeldItemStack), RegistryKey.of(VariantIota.key, Identifier("item")))) 364 + case _ => dieOfBadType() 365 + case _ => dieOfBadType() 308 366 //noinspection UnstableApiUsage 309 367 case class VariantIota[T: ClassTag](data: TransferVariant[T], key: RegistryKey[VariantIota.Reader]) extends Iota(VariantIota, data): 310 368 override def isTruthy: Boolean = true ··· 348 406 new TaggedVariant: 349 407 type T = Item 350 408 def variant: TransferVariant[Item] = s 351 - def display: Text = t"${s.getItem.getName(s.toStack)}: ${ItemInlineData(s.toStack).asText(true)}" 352 - .styled(_.withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_ITEM, HoverEvent.ItemStackContent(s.toStack)))) 409 + def display: Text = t"⌠${ItemInlineData(s.toStack).asText(true).copy().styled(InlineAPI.INSTANCE.withSizeModifier(_, 1.5))}⌡" 410 + .styled(_.withColor(0x7c7145).withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_ITEM, HoverEvent.ItemStackContent(s.toStack)))) 353 411 registry(Identifier("fluid")) = c => 354 412 val s = FluidVariant.fromNbt(c) 355 413 Option.unless(s.isBlank): 356 414 new TaggedVariant: 357 415 type T = Fluid 358 416 def variant: TransferVariant[Fluid] = s 359 - def display: MutableText = t"${s.getFluid.getDefaultState.getBlockState.getBlock.getName}: ${ItemInlineData.make(s.getFluid.getBucketItem.getDefaultStack)}" 417 + def display: MutableText = 418 + val bs = s.getFluid.getDefaultState.getBlockState 419 + t"(${bs.getBlock.getName.styled(_.withColor(bs.getMapColor(null, null).color))})".styled(_.withColor(0x3c5e34)) 360 420 registry("media") = c => 361 421 Some(new TaggedVariant: 362 422 type T = SingletonVariant
+2
settings.gradle.kts
··· 22 22 id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" 23 23 } 24 24 25 + rootProject.name = "hex-addons" 26 + 25 27 include("util") 26 28 includeBuild("plugin") 27 29 for (mod in listOf("hexic", "iotaworks", "hexxytounge")) {
+35 -19
util/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/zh_cn/entries/addon/phlib/maps.json
··· 15 15 }, 16 16 { 17 17 "type": "hexcasting:pattern", 18 - "op_id": "hexcasting:add", 19 - "anchor": "hexcasting:add", 20 - "input": "map<k, v>, map<k, v>", 18 + "op_id": "hexcasting:replace", 19 + "anchor": "hexcasting:replace", 20 + "input": "map<k, v>, k, v", 21 21 "output": "map<k, v>", 22 - "text": "合并两个映射。映射中不允许存在重复项:后一映射的项会覆盖前一映射的。" 22 + "text": "将键 $(n)k/$ 所对应项的值换为 $(n)v/$。若映射内没有 $(n)k/$ 键,则新建项并插入末尾。" 23 23 }, 24 24 { 25 25 "type": "hexcasting:pattern", 26 - "op_id": "hexcasting:sub", 27 - "anchor": "hexcasting:sub", 28 - "input": "map<k, v>, map<t, *>", 26 + "op_id": "hexcasting:remove_from", 27 + "anchor": "hexcasting:remove_from", 28 + "input": "map<k, v>, k", 29 29 "output": "map<k, v>", 30 - "text": "从第一个映射中移除第二个映射的项。比对时忽略第二个映射中项的值。" 30 + "text": "从映射中删去所给键对应的项。若未找到相应项,则原样返回映射。" 31 31 }, 32 32 { 33 33 "type": "hexcasting:pattern", ··· 39 39 }, 40 40 { 41 41 "type": "hexcasting:pattern", 42 + "op_id": "hexcasting:splat", 43 + "anchor": "hexcasting:splat", 44 + "input": "map<k, v>", 45 + "output": "k, v, k, v...", 46 + "text": "拆散映射,按插入顺序返回键值对。" 47 + }, 48 + { 49 + "type": "hexcasting:pattern", 42 50 "op_id": "hexcasting:unappend", 43 51 "anchor": "hexcasting:unappend", 44 - "input": "map<k, v>", 45 - "output": "map<k, v>, (k, v)?", 46 - "text": "从映射中取出一个项。删去哪个项没有定论,完全由自然随意决定。对空映射使用时返回两个 Null。" 52 + "input": "map<k,v>", 53 + "output": "map<k,v>, (k,v | nulls)", 54 + "text": "从映射中取出最后添加的项。对空映射使用时返回两个 Null。" 47 55 }, 48 56 { 49 57 "type": "hexcasting:pattern", 50 - "op_id": "hexcasting:replace", 51 - "anchor": "hexcasting:replace", 52 - "input": "map<k, v>, k, v", 58 + "op_id": "hexcasting:deconstruct", 59 + "anchor": "hexcasting:deconstruct", 60 + "input": "map<k,v>", 61 + "output": "map<k,v>, (k,v | nulls)", 62 + "text": "从映射中取出最先添加的项。对空映射使用时返回两个 Null。" 63 + }, 64 + { 65 + "type": "hexcasting:pattern", 66 + "op_id": "hexcasting:add", 67 + "anchor": "hexcasting:add", 68 + "input": "map<k, v>, map<k, v>", 53 69 "output": "map<k, v>", 54 - "text": "将键为 $(n)k/$ 的项的值换为 $(n)v/$。若映射内没有 $(n)k/$ 键,则新建项。" 70 + "text": "合并两个映射。映射中不允许存在重复项:后一映射的项会覆盖前一映射的。" 55 71 }, 56 72 { 57 73 "type": "hexcasting:pattern", 58 - "op_id": "hexcasting:remove_from", 59 - "anchor": "hexcasting:remove_from", 60 - "input": "map<k, v>, k", 74 + "op_id": "hexcasting:sub", 75 + "anchor": "hexcasting:sub", 76 + "input": "map<k, v>, map<t, *>", 61 77 "output": "map<k, v>", 62 - "text": "从映射中删去所给键对应的项。若未找到相应项,则原样返回映射。" 78 + "text": "从第一个映射中移除第二个映射的项。比对时忽略第二个映射中项的值。" 63 79 } 64 80 ] 65 81 }
+19 -29
util/src/main/scala/org/eu/net/pool/phlib/main.scala
··· 1 1 package org.eu.net.pool 2 2 package phlib 3 3 4 - import at.petrak.hexcasting.api.utils.HexUtils 5 - import com.google.gson.JsonElement 6 - import com.mojang.serialization.{Codec, DynamicOps, JsonOps} 7 - import net.minecraft.nbt.{NbtByte, NbtByteArray, NbtDouble, NbtEnd, NbtFloat, NbtInt, NbtIntArray, NbtList, NbtLong, NbtLongArray, NbtOps, NbtShort, NbtString, NbtType} 8 - import net.minecraft.util.dynamic.Codecs 9 - import at.petrak.hexcasting.api.addldata.ADMediaHolder 10 - import scala.collection.{IterableOnceOps, IterableOps} 11 - import at.petrak.hexcasting.api.casting.{ActionRegistryEntry, ParticleSpray, RenderedSpell, SpellList} 12 - import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic 13 - import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator 14 - import at.petrak.hexcasting.api.casting.castables.{Action, ConstMediaAction, OperationAction, SpecialHandler, SpellAction} 15 - import at.petrak.hexcasting.api.casting.eval.env.PlayerBasedCastEnv 16 - import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect.DoMishap 4 + import at.petrak.hexcasting.api.casting.ActionRegistryEntry 5 + import at.petrak.hexcasting.api.casting.castables.{Action, ConstMediaAction, OperationAction} 17 6 import at.petrak.hexcasting.api.casting.eval.sideeffects.{EvalSound, OperatorSideEffect} 18 - import at.petrak.hexcasting.api.casting.eval.vm.{CastingImage, CastingVM, ContinuationFrame, FrameEvaluate, SpellContinuation} 19 - import at.petrak.hexcasting.api.casting.eval.{CastResult, CastingEnvironment, CastingEnvironmentComponent, MishapEnvironment, OperationResult, ResolvedPattern, ResolvedPatternType} 7 + import at.petrak.hexcasting.api.casting.eval.vm.{CastingImage, CastingVM, SpellContinuation} 8 + import at.petrak.hexcasting.api.casting.eval.{CastResult, CastingEnvironment, CastingEnvironmentComponent, OperationResult} 20 9 import at.petrak.hexcasting.api.casting.iota.* 21 10 import at.petrak.hexcasting.api.casting.math.{HexDir, HexPattern} 22 - import at.petrak.hexcasting.api.casting.mishaps.{Mishap, MishapBadCaster, MishapBadOffhandItem, MishapInvalidIota, MishapInvalidOperatorArgs, MishapNotEnoughArgs, MishapOthersName, MishapTooManyCloseParens} 11 + import at.petrak.hexcasting.api.casting.mishaps.{Mishap, MishapInvalidIota, MishapNotEnoughArgs} 12 + import at.petrak.hexcasting.api.utils.HexUtils 23 13 import at.petrak.hexcasting.common.lib.HexRegistries 24 14 import at.petrak.hexcasting.fabric.cc.HexCardinalComponents 15 + import com.google.gson.JsonElement 25 16 import com.mojang.brigadier.builder.{LiteralArgumentBuilder, RequiredArgumentBuilder} 17 + import com.mojang.serialization.{Codec, DynamicOps, JsonOps} 26 18 import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback 27 - import net.minecraft.command.{CommandException, EntitySelector} 28 19 import net.minecraft.command.argument.{EntityArgumentType, NbtElementArgumentType, RegistryEntryArgumentType} 29 - import net.minecraft.nbt.{NbtCompound, NbtElement} 20 + import net.minecraft.command.{CommandException, EntitySelector} 21 + import net.minecraft.nbt.* 30 22 import net.minecraft.server.command.ServerCommandSource 31 23 import net.minecraft.server.network.ServerPlayerEntity 32 24 import net.minecraft.server.world.ServerWorld 33 25 import net.minecraft.util.Hand 26 + import net.minecraft.util.dynamic.Codecs 34 27 35 28 import scala.annotation.tailrec 29 + import scala.collection.{IterableOnceOps, IterableOps} 36 30 import scala.math.Ordered.orderingToOrdered 37 31 import scala.reflect.ClassTag 38 32 import scala.util.{Failure, Success, Try} 39 33 export scala.collection.convert.ImplicitConversions.* 40 34 export scala.util.chaining._ 41 - import java.util 35 + import at.petrak.hexcasting.xplat.IXplatAbstractions 36 + import net.fabricmc.fabric.api.event.{Event, EventFactory} 42 37 import net.fabricmc.loader.api.FabricLoader 38 + import net.minecraft.registry.{Registry, RegistryKey} 39 + import net.minecraft.text.{MutableText, Text} 43 40 import net.minecraft.util.Identifier 41 + import org.slf4j.{Logger, LoggerFactory} 42 + 43 + import java.util 44 44 import scala.util.boundary 45 - import org.slf4j.LoggerFactory 46 - import org.slf4j.Logger 47 - import at.petrak.hexcasting.xplat.IXplatAbstractions 48 - import net.minecraft.registry.Registry 49 - import net.minecraft.registry.RegistryKey 50 - import net.minecraft.text.MutableText 51 - import net.minecraft.text.Text 52 - import net.fabricmc.fabric.api.event.Event 53 - import net.fabricmc.fabric.api.event.EventFactory 54 45 55 46 val fabric = FabricLoader.getInstance 56 47 val isDev = fabric.isDevelopmentEnvironment ··· 254 245 package mixin: 255 246 import net.minecraft.block.Block 256 247 import net.minecraft.item.Item 257 - import org.spongepowered.asm.mixin.injection.{At, Inject} 258 248 import org.spongepowered.asm.mixin.Mixin 259 249 @Mixin(value = Array(classOf[Item], classOf[Block])) 260 250 private[phlib] class AllocationTrackerMixin() extends AnyRef with AllocationTracked: