repo for my hex addons :3
0
fork

Configure Feed

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

mediaweave rework

* mediaweave uses one trinket slot instead of two internal slots
* only one mediaweave can be equipped at a time
* mediaweave applies to *all* chat messages (prefixes are no longer a thing)
* mediaweave is now mutable

+145 -260
+17 -14
project/hexic/build.gradle.kts
··· 159 159 modImplementation("net.beholderface.oneironaut:oneironaut-fabric-1.20.1-fabric-fabric:1.20.1-SNAPSHOT") 160 160 compat("maven.modrinth:hexcassettes:1.1.4") 161 161 modLocalRuntime("maven.modrinth:trinkets:3.7.2") 162 - modImplementation("maven.modrinth:spasm:0.2.2") 163 162 // modImplementation("maven.modrinth:slate-works:1.0.5") 164 163 compat("miyucomics.hexical:hexical:2.0.0+a3c47ad9") 165 164 compat("miyucomics.overevaluate:overevaluate:main-SNAPSHOT") ··· 171 170 modImplementation("com.github.mattidragon:ConfigToolkit:v1.0.0") // trans maven.modrinth:jsonpatcher 172 171 modImplementation("miyucomics.hexpose:hexpose:1.0.0") 173 172 include(modApi("xyz.nucleoid:fantasy:0.4.11+1.20-rc1")!!) 173 + modImplementation("dev.emi:trinkets:3.7.2") 174 174 // modImplementation("miyucomics:hexpose:1.0.0") 175 175 // modImplementation(files("hexical-2.0.0.jar")) 176 176 include(implementation("net.bytebuddy:byte-buddy:1.17.7")!!) ··· 179 179 modImplementation("dev.onyxstudios.cardinal-components-api:cardinal-components-entity:5.2.3") 180 180 modImplementation("dev.onyxstudios.cardinal-components-api:cardinal-components-level:5.2.3") 181 181 modRuntimeOnly("dev.onyxstudios.cardinal-components-api:cardinal-components-api:5.2.3") 182 - modRuntimeOnly("com.unascribed:lib39-core:2.0.27+1.20.1") 183 - modRuntimeOnly("com.unascribed:lib39-avant:2.0.27+1.20.1") 184 - modRuntimeOnly("gay.object.hexdebug:hexdebug-fabric:0.5.0+1.20.1-SNAPSHOT") 182 + modRuntimeOnly("com.unascribed:lib39-core:[2.0.0,)!!2.0.27+1.20.1") 183 + modRuntimeOnly("com.unascribed:lib39-avant:[2.0.0,)!!2.0.27+1.20.1") 184 + modRuntimeOnly("com.unascribed:lib39-phantom:[2.0.0,)!!2.0.27+1.20.1") 185 + modLocalRuntime("gay.object.hexdebug:hexdebug-fabric:0.5.0+1.20.1-SNAPSHOT") 186 + modLocalRuntime("maven.modrinth:hexcessible:0.2.0") 187 + modLocalRuntime("maven.modrinth:complex-hex:0.1.3-beta") 185 188 } 186 189 187 190 val colors = mapOf( ··· 224 227 225 228 depends("mixinextras", "*") 226 229 depends("mm", "^2.3") 227 - depends("spasm", ">=0.2.2") 228 230 depends("moreiotas", ">=0.1.1") 229 231 depends("hexal", ">=0.3.0") 230 232 depends("hexcellular", "^1.1.0") 231 233 depends("jsonpatcher", "^1.0.0-beta.4+mc.1.20.1") 232 234 depends("hexpose", "^1.0.0") 235 + depends("trinkets", "^3.7.2") 233 236 conflicts("valkyrienskies", "*") // need to figure out how to create dimensions without causing a crash 234 237 235 238 entrypoint("org.eu.net.pool.hexic.main\$package::init") ··· 246 249 dependsOn(cloth) 247 250 dependsOn(*downloadedBags.values.toTypedArray()) 248 251 val itemsRoot = destinationDir.resolve("assets/hexic/textures/item") 249 - val jxlOpts = list("-quality", "100", "-define", "jxl:effort=11", "-define", "jxl:lossless=true", "-define", "jxl:modular=true") 252 + val jxlOpts = arrayOf("-quality", "100", "-define", "jxl:effort=11", "-define", "jxl:lossless=true", "-define", "jxl:modular=true") 250 253 doLast { 251 254 for ((name, color) in colors) { 252 255 exec { 253 - commandLine("env", "magick", cloth.dest, "-channel", "red,green,blue", "-fx", "u*#${color.toString(16)}", "jxl:${itemsRoot.resolve("${name}_mediaweave.png")}") 256 + commandLine("env", "magick", cloth.dest, "-channel", "red,green,blue", "-fx", "u*#${color.toString(16)}", *jxlOpts, "jxl:${itemsRoot.resolve("${name}_mediaweave.png")}") 254 257 } 255 258 val bag = downloadedBags[name]!!.dest 256 259 exec { 257 - commandLine("env", "magick", bag, "-write", "jxl:${itemsRoot.resolve("large_${name}_bundle.png")}", "-sample", "14x14", "-background", "transparent", "-extent", "16x16-1-2", "jxl:${itemsRoot.resolve("small_${name}_bundle.png")}") 260 + commandLine("env", "magick", bag, *jxlOpts, "-write", "jxl:${itemsRoot.resolve("large_${name}_bundle.png")}", "-sample", "14x14", "-background", "transparent", "-extent", "16x16-1-2", "jxl:${itemsRoot.resolve("small_${name}_bundle.png")}") 258 261 } 259 262 } 260 263 exec { 261 - commandLine("env", "magick", "wizard:", "jxl:${itemsRoot.resolve("wizard.png")}") 264 + commandLine("env", "magick", "wizard:", *jxlOpts, "jxl:${itemsRoot.resolve("wizard.png")}") 262 265 } 263 266 exec { 264 - commandLine("env", "magick", "null:", "jxl:${itemsRoot.resolve("no.jxl")}") 267 + commandLine("env", "magick", "null:", *jxlOpts, "jxl:${itemsRoot.resolve("no.jxl")}") 265 268 } 266 269 exec { 267 270 commandLine("env", "magick", ··· 289 292 "pure" to "u", 290 293 )) { 291 294 exec { 292 - commandLine("env", "magick", itemsRoot.resolve("stringworm.miff"), "-channel", "rgb", "-fx", expr, "jxl:$itemsRoot/stringworm_$name.png") 295 + commandLine("env", "magick", itemsRoot.resolve("stringworm.miff"), "-channel", "rgb", "-fx", expr, *jxlOpts, "jxl:$itemsRoot/stringworm_$name.png") 293 296 } 294 297 } 295 298 // people will hate this 296 299 for (i in 0..31) { 297 300 exec { 298 - commandLine("env", "magick", itemsRoot.resolve("stringworm.miff"), "-fx", "i+j == $i ? u : Transparent", "jxl:${itemsRoot.resolve("stringworm_tinted_$i.jxl")}") 301 + commandLine("env", "magick", itemsRoot.resolve("stringworm.miff"), "-fx", "i+j == $i ? u : Transparent", *jxlOpts, "jxl:${itemsRoot.resolve("stringworm_tinted_$i.png")}") 299 302 } 300 303 } 301 304 file("$itemsRoot/../block").mkdir() 302 305 exec { 303 - commandLine("env", "magick", "xc:#ffffff[16x16]", "jxl:${itemsRoot.resolveSibling("block/border.jxl")}") 306 + commandLine("env", "magick", "xc:#ffffff[16x16]", *jxlOpts, "jxl:${itemsRoot.resolveSibling("block/border.png")}") 304 307 } 305 308 file("$itemsRoot/stringworm.miff").delete() 306 309 exec { 307 - commandLine("env", "magick", "https://www.masterbuilt.com/cdn/shop/articles/162_20-_20Voodoo_20Baked_20Beans.jpg", "-sample", "256x256", "jxl:${itemsRoot.resolve("beans.jxl")}") 310 + commandLine("env", "magick", "https://www.masterbuilt.com/cdn/shop/articles/162_20-_20Voodoo_20Baked_20Beans.jpg", "-sample", "256x256", *jxlOpts, "jxl:${itemsRoot.resolve("beans.png")}") 308 311 } 309 312 } 310 313
+3
project/hexic/changelog
··· 1 1 2.0.0 engulfed hexxychests 2 2 2.0.0 load config from config/*.properties instead of config/jvm.properties 3 + 2.0.0 mediaweave now applies to all chat messages 4 + 2.0.0 !mediaweave now uses trinket slots 3 5 2.0.0 murmur and reveal now use separate components 6 + 2.0.0 !only one mediaweave can be equipped at a time 4 7 2.0.0 !removed tripwires 5 8 2.0.0 textures now use JPEG XL
+1 -3
project/hexic/src/client/resources/hexic.client.mixins.json
··· 5 5 "compatibilityLevel": "JAVA_17", 6 6 "client": [ 7 7 "ChatHudMixin", 8 - "ChatInputSuggestorMixin", 9 8 "ChatScreenAccess", 10 - "ChatScreenMixin", 11 - "InventoryScreenMixin" 9 + "ChatScreenMixin" 12 10 ], 13 11 "injectors": { 14 12 "defaultRequire": 1
+8 -34
project/hexic/src/client/scala/org/eu/net/pool/hexic/client.scala
··· 7 7 import com.google.gson.reflect.TypeToken 8 8 import com.google.gson.{Gson, JsonArray, JsonObject} 9 9 import com.llamalad7.mixinextras.injector.wrapoperation.Operation 10 + import dev.emi.trinkets.api.{TrinketComponent, TrinketsApi} 10 11 import kotlin.jvm.JvmField 11 12 import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking 12 13 import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry ··· 48 49 import scala.util.boundary 49 50 import scala.util.boundary.Label 50 51 import scala.util.chaining.scalaUtilChainingOps 51 - 52 - import phlib.{_, given} 52 + import phlib.{*, given} 53 53 54 54 given client: MinecraftClient = MinecraftClient.getInstance 55 55 ··· 59 59 case player => ifPresent(player) 60 60 61 61 object ClientHooks: 62 - def provideRenderText(string: String, firstCharacterIndex: Int, field: TextFieldWidget, original: OrderedText): OrderedText = 63 - foldLocalPlayer(original): p => 64 - val c = p.getComponent(PlayerInfoComponent.key) 65 - boundary[OrderedText]: 66 - if c.rightWeave.hasCustomName && c.rightWeave.getItem.isInstanceOf[Mediaweave] then 67 - val wake = c.rightWeave.getName.getString.toLowerCase 68 - if field.getText.toLowerCase.startsWith(s"$wake:") then 69 - boundary.break[OrderedText]: v => 70 - original.accept: (idx, style, p) => 71 - v.accept(idx, if idx + firstCharacterIndex <= wake.length then style.withColor(c.rightWeave.getItem.asInstanceOf[Mediaweave].color.getSignColor) else style, p) 72 - if c.leftWeave.hasCustomName && c.leftWeave.getItem.isInstanceOf[Mediaweave] then 73 - val wake = c.leftWeave.getName.getString.toLowerCase 74 - if field.getText.toLowerCase.startsWith(s"$wake:") then 75 - boundary.break[OrderedText]: v => 76 - original.accept: (idx, style, p) => 77 - v.accept(idx, if idx + firstCharacterIndex <= wake.length then style.withColor(c.leftWeave.getItem.asInstanceOf[Mediaweave].color.getSignColor) else style, p) 78 - original 79 62 def interceptSendMessage(handler: ClientPlayNetworkHandler, msg: String): Boolean = 80 63 foldLocalPlayer(false): p => 81 - boundary[Boolean]: 82 - val c = p.getComponent(PlayerInfoComponent.key) 83 - val (left, text) = boundary[(Boolean, String)]: 84 - if c.rightWeave.hasCustomName && c.rightWeave.getItem.isInstanceOf[Mediaweave] then 85 - val wake = c.rightWeave.getName.getString.toLowerCase 86 - if msg.toLowerCase.startsWith(s"$wake:") then 87 - boundary.break((false, msg.substring(wake.length + 1))) 88 - if c.leftWeave.hasCustomName && c.leftWeave.getItem.isInstanceOf[Mediaweave] then 89 - val wake = c.leftWeave.getName.getString.toLowerCase 90 - if msg.toLowerCase.startsWith(s"$wake:") then 91 - boundary.break((true, msg.substring(wake.length + 1))) 92 - boundary.break(false) 64 + if p.validMediaweave.isDefined then 93 65 val buf = PacketByteBufs.create() 94 - buf.writeByte(if left then 12 else 8) 95 - buf.writeString(text.trim) 96 - ClientPlayNetworking.send("sync_mediaweave", buf) 66 + buf.writeByte(0) 67 + buf.writeString(msg) 68 + ClientPlayNetworking.send("message", buf) 97 69 true 70 + else false 98 71 99 72 def init(): Unit = 100 73 BlockEntityRendererFactories.register( ··· 412 385 gen.add("hexic.spell_memory", "Hex memorized") 413 386 gen.add("tag.item.hexic.mediaweaves", "Mediaweave") 414 387 gen.add("text.hexic.pigment_holder_item", "an item storing a pigment") 388 + gen.add("trinkets.slot.chest.hexic_mediaweave", "Mediaweave") 415 389 pack.addProvider: 416 390 new FabricRecipeProvider(_): 417 391 override def generate(consumer: Consumer[RecipeJsonProvider]): Unit =
-21
project/hexic/src/client/scala/org/eu/net/pool/hexic/mixin/ChatInputSuggestorMixin.java
··· 1 - package org.eu.net.pool.hexic.mixin; 2 - 3 - import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; 4 - import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 5 - import net.minecraft.client.gui.screen.ChatInputSuggestor; 6 - import net.minecraft.client.gui.widget.TextFieldWidget; 7 - import net.minecraft.text.OrderedText; 8 - import org.eu.net.pool.hexic.ClientHooks; 9 - import org.spongepowered.asm.mixin.Final; 10 - import org.spongepowered.asm.mixin.Mixin; 11 - import org.spongepowered.asm.mixin.Shadow; 12 - 13 - @Mixin(ChatInputSuggestor.class) 14 - public class ChatInputSuggestorMixin { 15 - @Shadow @Final TextFieldWidget textField; 16 - 17 - @WrapMethod(method = "provideRenderText") 18 - OrderedText provideRenderText(String string, int firstCharacterIndex, Operation<OrderedText> original) { 19 - return ClientHooks.provideRenderText(string, firstCharacterIndex, textField, original.call(string, firstCharacterIndex)); 20 - } 21 - }
-83
project/hexic/src/client/scala/org/eu/net/pool/hexic/mixin/InventoryScreenMixin.java
··· 1 - package org.eu.net.pool.hexic.mixin; 2 - 3 - import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; 4 - import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; 5 - import net.fabricmc.loader.api.FabricLoader; 6 - import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen; 7 - import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; 8 - import net.minecraft.client.gui.screen.ingame.InventoryScreen; 9 - import net.minecraft.entity.player.PlayerInventory; 10 - import net.minecraft.item.ItemStack; 11 - import net.minecraft.screen.ScreenHandler; 12 - import net.minecraft.text.Text; 13 - import net.minecraft.util.Identifier; 14 - import org.eu.net.pool.hexic.PlayerInfoComponent; 15 - import org.spongepowered.asm.mixin.Mixin; 16 - import org.spongepowered.asm.mixin.injection.At; 17 - import org.spongepowered.asm.mixin.injection.Inject; 18 - import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 19 - 20 - @Mixin({InventoryScreen.class, CreativeInventoryScreen.class}) 21 - public abstract class InventoryScreenMixin extends AbstractInventoryScreen<ScreenHandler> { 22 - public InventoryScreenMixin(ScreenHandler screenHandler, PlayerInventory playerInventory, Text text) { 23 - super(screenHandler, playerInventory, text); 24 - } 25 - 26 - @Inject(method = "mouseClicked", at = @At(value = "HEAD"), cancellable = true) 27 - void mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir) { 28 - boolean creative = false; 29 - if ((AbstractInventoryScreen<?>) this instanceof CreativeInventoryScreen c) { 30 - if (!c.isInventoryTabSelected()) return; 31 - creative = true; 32 - } 33 - mouseX -= x; 34 - mouseY -= y; 35 - double lx = creative ? mouseX - 89 : mouseX - 50; 36 - double ly = creative ? mouseY - 42 : mouseY - 65; 37 - double w = creative ? 15 : 20; 38 - double h = creative ? 35 : 60; 39 - if (FabricLoader.getInstance().isDevelopmentEnvironment()) 40 - System.out.printf("s=(%d, %d) m=(%f, %f) l=(%f, %f)\n", x, y, mouseX, mouseY, lx, ly); 41 - if (lx < w && lx > -w && ly < 0 && ly > -h) { 42 - byte flags = 0; 43 - var c = client.player.getComponent(PlayerInfoComponent.key()); 44 - var held = handler.getCursorStack(); 45 - if (lx < 0) { 46 - var right = c.rightWeave(); 47 - if (right.isEmpty() && !held.isEmpty() && held.getItem() instanceof org.eu.net.pool.hexic.Mediaweave) { 48 - c.rightWeave_$eq(held); 49 - handler.setCursorStack(ItemStack.EMPTY); 50 - flags |= 3; 51 - } else if (held.isEmpty() && !right.isEmpty()) { 52 - handler.setCursorStack(right); 53 - c.rightWeave_$eq(ItemStack.EMPTY); 54 - flags |= 3; 55 - } else return; 56 - } else { 57 - var left = c.leftWeave(); 58 - if (left.isEmpty() && !held.isEmpty() && held.getItem() instanceof org.eu.net.pool.hexic.Mediaweave) { 59 - c.leftWeave_$eq(held); 60 - handler.setCursorStack(ItemStack.EMPTY); 61 - flags |= 7; 62 - } else if (held.isEmpty() && !left.isEmpty()) { 63 - handler.setCursorStack(left); 64 - c.leftWeave_$eq(ItemStack.EMPTY); 65 - flags |= 7; 66 - } else return; 67 - } 68 - // submit our changes to the server 69 - if (flags != 0) { 70 - var buf = PacketByteBufs.create(); 71 - buf.writeByte(flags); 72 - if ((flags & 1) != 0) buf.writeItemStack(handler.getCursorStack()); 73 - if ((flags & 2) != 0) 74 - if ((flags & 4) != 0) 75 - buf.writeItemStack(c.leftWeave()); 76 - else 77 - buf.writeItemStack(c.rightWeave()); 78 - ClientPlayNetworking.send(Identifier.of("hexic", "sync_mediaweave"), buf); 79 - cir.setReturnValue(true); 80 - } 81 - } 82 - } 83 - }
project/hexic/src/main/resources/assets/hexic/textures/gui/mediaweave.png

This is a binary file and will not be displayed.

+8
project/hexic/src/main/resources/data/trinkets/entities/hexic.json
··· 1 + { 2 + "entities": [ 3 + "player" 4 + ], 5 + "slots": [ 6 + "chest/hexic_mediaweave" 7 + ] 8 + }
+4
project/hexic/src/main/resources/data/trinkets/slots/chest/hexic_mediaweave.json
··· 1 + { 2 + "icon": "hexic:gui/mediaweave", 3 + "drop_rule": "keep" 4 + }
+5
project/hexic/src/main/resources/data/trinkets/tags/items/chest/hexic_mediaweave.json
··· 1 + { 2 + "values": [ 3 + "#hexic:mediaweaves" 4 + ] 5 + }
+88 -7
project/hexic/src/main/scala/org/eu/net/pool/hexic/chat.scala
··· 1 1 package org.eu.net.pool 2 2 package hexic 3 3 4 - import at.petrak.hexcasting.api.casting.eval.CastingEnvironment 5 - import at.petrak.hexcasting.api.casting.iota.{Iota, IotaType, ListIota, NullIota} 6 - import at.petrak.hexcasting.api.casting.mishaps.MishapBadCaster 4 + import at.petrak.hexcasting.api.casting.RenderedSpell 5 + import at.petrak.hexcasting.api.casting.eval.env.PlayerBasedCastEnv 6 + import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect 7 + import at.petrak.hexcasting.api.casting.eval.sideeffects.OperatorSideEffect.DoMishap 8 + import at.petrak.hexcasting.api.casting.eval.{CastResult, CastingEnvironment, ResolvedPatternType} 9 + import at.petrak.hexcasting.api.casting.eval.vm.{CastingImage, CastingVM, ContinuationFrame, SpellContinuation} 10 + import at.petrak.hexcasting.api.casting.iota.{ContinuationIota, Iota, IotaType, ListIota, NullIota} 11 + import at.petrak.hexcasting.api.casting.mishaps.{Mishap, MishapBadCaster, MishapInvalidIota, MishapNotEnoughArgs} 12 + import at.petrak.hexcasting.api.pigment.FrozenPigment 13 + import at.petrak.hexcasting.common.lib.HexItems 14 + import at.petrak.hexcasting.common.lib.hex.HexEvalSounds 7 15 import com.google.gson.JsonElement 8 16 import com.mojang.serialization.JsonOps 17 + import dev.emi.trinkets.api.{TrinketComponent, TrinketsApi} 9 18 import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent 10 19 import dev.onyxstudios.cca.api.v3.component.{Component, ComponentAccess, ComponentKey, ComponentRegistry} 11 20 import dev.onyxstudios.cca.api.v3.entity.{EntityComponentFactoryRegistry, EntityComponentInitializer, RespawnCopyStrategy} 12 - import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking 13 - import net.minecraft.nbt.{NbtCompound, NbtElement} 21 + import net.fabricmc.fabric.api.networking.v1.{PacketByteBufs, ServerPlayNetworking} 22 + import net.minecraft.entity.player.PlayerEntity 23 + import net.minecraft.item.ItemStack 24 + import net.minecraft.nbt.{NbtCompound, NbtElement, NbtOps} 14 25 import net.minecraft.server.network.ServerPlayerEntity 26 + import net.minecraft.server.world.ServerWorld 15 27 import net.minecraft.text.Text 16 - import net.minecraft.util.Identifier 28 + import net.minecraft.util.{DyeColor, Hand, Identifier, Pair, Util, Uuids} 17 29 import org.eu.net.pool.phlib.{Events as PhEvents, *, given} 18 30 import org.slf4j.{Logger, LoggerFactory} 19 31 import ram.talia.moreiotas.api.casting.iota.StringIota 20 32 33 + import java.util.UUID 21 34 import scala.collection.immutable.* 35 + import scala.jdk.CollectionConverters.* 22 36 import scala.language.implicitConversions 37 + import scala.util.boundary 23 38 24 39 private[hexic] case class MurmurCache(var value: Option[String]) extends Component: 25 40 override def readFromNbt(tag: NbtCompound): Unit = ··· 50 65 def component[C <: Component: ComponentKey as key]: C = c.getComponent(key) 51 66 def syncComponent[C <: Component: ComponentKey as key](): Unit = c.syncComponent(key) 52 67 68 + extension (p: PlayerEntity) 69 + def validMediaweave: Option[(NbtCompound, DyeColor, ItemStack)] = 70 + TrinketsApi.getTrinketComponent(p) 71 + .pipe(o => Option.when[TrinketComponent](o.isPresent)(o.get())) 72 + .flatMap: (c: TrinketComponent) => 73 + c.getEquipped(_.getItem.isInstanceOf[Mediaweave]).asScala.collectFirst: 74 + Function.unlift: p => 75 + p.getRight.getItem match 76 + case m@Mediaweave(color) => Option(m.readIotaTag(p.getRight)).map((_, color, p.getRight)) 77 + case _ => None 78 + extension (p: ServerPlayerEntity) 79 + def executeMediaweave(text: String, ctx: Seq[Iota]): Boolean = 80 + p.validMediaweave match 81 + case Some(hex, color, stack) => 82 + given world: ServerWorld = p.getWorld.asInstanceOf[ServerWorld] 83 + lazy val env = new PlayerBasedCastEnv(p, Hand.OFF_HAND): 84 + override def extractMediaEnvironment(cost: Long, simulate: Boolean): Long = 85 + if p.isCreative then 0L else extractMediaFromInventory(cost, canOvercast, simulate) 86 + override def getCastingHand: Hand = castingHand 87 + override def getPigment = FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS.get(color)), Util.NIL_UUID) 88 + val image = CastingImage(ctx :+ StringIota.make(text), 0, Seq(), false, 0, NbtCompound(), null) 89 + val instrs = IotaType.deserialize(hex, world) match 90 + case list: ListIota => list.getList.asScala.toSeq 91 + case iota => Seq(iota) 92 + val vm = CastingVM(image, env) 93 + val view = vm.queueExecuteAndWrapIotas(instrs :+ ContinuationIota(SpellContinuation.NotDone(MessageFrame(p.getUuid, stack.getName, p), SpellContinuation.Done.INSTANCE)), world) 94 + true 95 + case _ => false 96 + object MessageFrame extends ContinuationFrame.Type[MessageFrame]: 97 + override def deserializeFromNBT(c: NbtCompound, world: ServerWorld): MessageFrame = 98 + val id = Uuids.toUuid(c.getIntArray("id")) 99 + MessageFrame(id, Text.Serializer.fromJson(NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, c.getCompound("t"))), world.getServer.getPlayerManager.getPlayer(id)) 100 + class MessageFrame(id: UUID, text: Text, player: => ServerPlayerEntity) extends ContinuationFrame: 101 + override def getType: ContinuationFrame.Type[MessageFrame] = MessageFrame 102 + override def evaluate(rest: SpellContinuation, world: ServerWorld, vm: CastingVM): CastResult = 103 + boundary: 104 + def mishap(m: Mishap) = boundary.break(CastResult(NullIota(), rest, vm.getImage, Seq(DoMishap(m, Mishap.Context(null, text))), ResolvedPatternType.EVALUATED, HexEvalSounds.NORMAL_EXECUTE)) 105 + vm.getImage.getStack.toSeq.reverse match 106 + case Seq() => 107 + mishap(MishapNotEnoughArgs(1, 0)) 108 + case Seq(s: StringIota, stack*) => 109 + CastResult(NullIota(), rest, vm.getImage.withStack(_ => stack), Seq( 110 + OperatorSideEffect.AttemptSpell( 111 + new RenderedSpell: 112 + override def cast(env: CastingEnvironment): Unit = 113 + ServerPlayNetworking.send(player, "msg", PacketByteBufs.create.tap(_.writeString(s.getString))) 114 + override def cast(env: CastingEnvironment, img: CastingImage): CastingImage = { cast(env); img } 115 + , false, false 116 + ) 117 + ), ResolvedPatternType.EVALUATED, HexEvalSounds.NORMAL_EXECUTE) 118 + case Seq(i, _*) => 119 + mishap(MishapInvalidIota.ofType(i, 0, "string")) 120 + override def serializeToNBT(): NbtCompound = NbtCompound() 121 + .tap(_.putIntArray("id", Uuids.toIntArray(id))) 122 + .tap(_.put("t", JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, Text.Serializer.toJsonTree(text)))) 123 + override def breakDownwards(stack: java.util.List[? <: Iota]): kotlin.Pair[java.lang.Boolean, java.util.List[Iota]] = kotlin.Pair(false, stack.toSeq) 124 + override def size = 0 125 + 53 126 object hasComponent: 54 127 def unapply[C <: Component: ComponentKey](ctx: ComponentAccess): Option[C] = 55 128 try ··· 75 148 Patterns.register("murmur", e"wwaqwa"): 76 149 Patterns.mkLiteral: (env, _) ?=> 77 150 hasComponent.unapply[MurmurCache](env.getCastingEntity).fold(throw MishapBadCaster())(_.value.fold(NullIota())(StringIota.make)) 78 - ServerPlayNetworking.registerGlobalReceiver("murmur", { case (_, hasComponent[MurmurCache](c), _, buf, _) => c.value = Option.when(buf.readBoolean())(buf.readString()) }: ServerPlayNetworking.PlayChannelHandler) 151 + hexXplat.getContinuationTypeRegistry("send_message") = MessageFrame 152 + ServerPlayNetworking.registerGlobalReceiver("murmur", { case (_, hasComponent[MurmurCache](c), _, buf, _) => c.value = Option.when(buf.readBoolean())(buf.readString()) }: ServerPlayNetworking.PlayChannelHandler) 153 + ServerPlayNetworking.registerGlobalReceiver("message", (_, player, _, buf, _) => 154 + val context = buf.readByte() 155 + if context != 0 then 156 + throw IllegalArgumentException("Nonzero context is reserved for future use") 157 + val text = buf.readString() 158 + player.executeMediaweave(text, Seq()) 159 + )
+7 -98
project/hexic/src/main/scala/org/eu/net/pool/hexic/main.scala
··· 170 170 171 171 import scala.util.matching.Regex 172 172 import at.petrak.hexcasting.api.casting.eval.vm.CastingImage.ParenthesizedIota 173 + import dev.emi.trinkets.api.{TrinketComponent, TrinketsApi} 173 174 import net.beholderface.oneironaut.casting.iotatypes.DimIota 174 175 import net.fabricmc.fabric.api.dimension.v1.FabricDimensions 175 176 import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents ··· 187 188 import scala.concurrent.duration.Duration 188 189 import phlib.{Events as PhEvents, *, given} 189 190 190 - given Logger = LoggerFactory.getLogger("hexic") 191 - given Conversion[String, Identifier] = Identifier.of("hexic", _) 191 + private[hexic] given Logger = LoggerFactory.getLogger("hexic") 192 + private[hexic] given Conversion[String, Identifier] = Identifier.of("hexic", _) 192 193 193 194 extension (i: Iota) 194 195 def asIotaType[T <: Iota: ClassTag](idx: Int, expected: => Text): T = i match ··· 367 368 val player: PlayerEntity, 368 369 var leftWeave: ItemStack = ItemStack.EMPTY, 369 370 var rightWeave: ItemStack = ItemStack.EMPTY, 370 - var chatLines: Seq[Text] = Seq(), 371 371 var foxType: Option[FoxEntity.Type] = None, 372 372 ) extends Component, AutoSyncedComponent: 373 373 override def readFromNbt(c: NbtCompound): Unit = ··· 379 379 rightWeave = ItemStack.fromNbt(c.getCompound("shr")) 380 380 else 381 381 rightWeave = ItemStack.EMPTY 382 - chatLines = c.getList("chat", NbtElement.COMPOUND_TYPE).map(NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, _)).map(Text.Serializer.fromJson).toSeq 383 382 if c.contains("fox", NbtElement.STRING_TYPE) then 384 383 foxType = Some(FoxEntity.Type.valueOf(c.getString("fox"))) 385 384 else ··· 387 386 override def writeToNbt(c: NbtCompound): Unit = 388 387 if !leftWeave.isEmpty then c.put("shl", NbtCompound().tap(leftWeave.writeNbt)) 389 388 if !rightWeave.isEmpty then c.put("shr", NbtCompound().tap(rightWeave.writeNbt)) 390 - c.put("chat", NbtList().tap(_.addAll(chatLines.map(Text.Serializer.toJsonTree).map(JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, _))))) 391 389 foxType.fold(c.remove("fox"))(f => c.putString("fox", f.name)) 392 390 object PlayerInfoComponent: 393 391 given key: ComponentKey[PlayerInfoComponent] = ComponentRegistry.getOrCreate("player_wisp", classOf[PlayerInfoComponent]) ··· 501 499 case c => c.get("Hex") match 502 500 case c: NbtCompound => c 503 501 case _ => null 504 - override def writeable(stack: ItemStack): Boolean = readIotaTag(stack) == null 505 - override def canWrite(stack: ItemStack, iota: Iota): Boolean = writeable(stack) && (iota match 506 - case l: ListIota => 507 - val i = l.getList.asScala 508 - i.isEmpty || i.head.executable && i.last.executable 509 - case _ => false) 502 + override def writeable(stack: ItemStack): Boolean = true 503 + override def canWrite(stack: ItemStack, iota: Iota): Boolean = iota match 504 + case l: ListIota => true 505 + case _ => iota.executable 510 506 override def writeDatum(stack: ItemStack, iota: Iota): Unit = 511 - assume(canWrite(stack, iota)) 512 507 stack.getOrCreateNbt.put("Hex", IotaType.serialize(iota)) 513 508 override def appendTooltip(stack: ItemStack, world: World, tooltip: util.List[Text], context: TooltipContext): Unit = 514 509 IotaHolderItem.appendHoverText(this, stack, tooltip, context) ··· 1852 1847 case Seq(i, _: ListIota, _*) => throw MishapInvalidIota.ofType(i, 0, "list") 1853 1848 case Seq(_, i, _*) => throw MishapInvalidIota.ofType(i, 1, "list") 1854 1849 case s => throw MishapNotEnoughArgs(2, s.size) 1855 - lazy val messageFrameType: ContinuationFrame.Type[MessageFrame] = (c: NbtCompound, world: ServerWorld) => 1856 - val id = Uuids.toUuid(c.getIntArray("id")) 1857 - MessageFrame(id, Text.Serializer.fromJson(NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, c.getCompound("t"))), world.getServer.getPlayerManager.getPlayer(id)) 1858 - class MessageFrame(id: UUID, text: Text, player: => ServerPlayerEntity) extends ContinuationFrame: 1859 - override def getType: ContinuationFrame.Type[MessageFrame] = messageFrameType 1860 - override def evaluate(rest: SpellContinuation, world: ServerWorld, vm: CastingVM): CastResult = 1861 - boundary: 1862 - def mishap(m: Mishap) = boundary.break(CastResult(NullIota(), rest, vm.getImage, Seq(DoMishap(m, Mishap.Context(null, text))), ResolvedPatternType.EVALUATED, HexEvalSounds.NORMAL_EXECUTE)) 1863 - vm.getImage.getStack.toSeq.reverse match 1864 - case Seq() => 1865 - mishap(MishapNotEnoughArgs(1, 0)) 1866 - case Seq(s: StringIota, stack*) => 1867 - CastResult(NullIota(), rest, vm.getImage.withStack(_ => stack), Seq( 1868 - OperatorSideEffect.AttemptSpell( 1869 - new RenderedSpell: 1870 - override def cast(env: CastingEnvironment): Unit = 1871 - ServerPlayNetworking.send(player, "msg", PacketByteBufs.create.tap(_.writeString(s.getString))) 1872 - override def cast(env: CastingEnvironment, img: CastingImage): CastingImage = { cast(env); img } 1873 - , false, false 1874 - ) 1875 - ), ResolvedPatternType.EVALUATED, HexEvalSounds.NORMAL_EXECUTE) 1876 - case Seq(i, _*) => 1877 - mishap(MishapInvalidIota.ofType(i, 0, "string")) 1878 - override def serializeToNBT(): NbtCompound = NbtCompound() 1879 - .tap(_.putIntArray("id", Uuids.toIntArray(id))) 1880 - .tap(_.put("t", JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, Text.Serializer.toJsonTree(text)))) 1881 - override def breakDownwards(stack: ju.List[? <: Iota]): Pair[java.lang.Boolean, ju.List[Iota]] = Pair(false, stack.toSeq) 1882 - override def size = 0 1883 - hexXplat.getContinuationTypeRegistry("send_message") = messageFrameType 1884 1850 CastingEnvironment.addCreateEventListener: (env: CastingEnvironment, data: NbtCompound) => 1885 1851 val id = env.getWorld.getRegistryKey.getValue 1886 1852 if isDev then println(s"Environment created in $id") ··· 1899 1865 val x = pos.getComponentAlongAxis(axis) 1900 1866 if x < 0 || x >= 11 then boundary.break(false) 1901 1867 true 1902 - ServerPlayNetworking.registerGlobalReceiver("sync_mediaweave", (_, player, _, buf, _) => 1903 - val flags = buf.readByte() 1904 - val c = player.getComponent(PlayerInfoComponent.key) 1905 - val cursorStack = player.playerScreenHandler.getCursorStack() 1906 - def currentWeave = 1907 - if (flags & 4) != 0 then 1908 - c.leftWeave 1909 - else 1910 - c.rightWeave 1911 - lazy val lastWeave = currentWeave 1912 - if (flags & 1) != 0 && (flags & 8) == 0 then 1913 - assume(cursorStack.isEmpty || (flags & 2) != 0, "if this isn't empty, the player's held item gets voided") 1914 - buf.readItemStack() 1915 - player.playerScreenHandler.setCursorStack(lastWeave.copyAndEmpty()) 1916 - PlayerInfoComponent.key.sync(player) 1917 - if (flags & 2) != 0 then 1918 - buf.readItemStack() 1919 - assume(currentWeave.isEmpty, "if this isn't empty, an equipped mediaweave gets voided") 1920 - if (flags & 4) != 0 then 1921 - c.leftWeave = cursorStack 1922 - else 1923 - c.rightWeave = cursorStack 1924 - PlayerInfoComponent.key.sync(player) 1925 - if (flags & 8) != 0 then 1926 - val text = buf.readString() 1927 - val c = player.getComponent(PlayerInfoComponent.key) 1928 - val stack = if (flags & 4) != 0 then c.leftWeave else c.rightWeave 1929 - stack.getItem match 1930 - case m@Mediaweave(color) => m.readIotaTag(stack) match 1931 - case t: NbtCompound => IotaType.deserialize(t, player.getServerWorld) match 1932 - case s: ListIota => 1933 - given ServerWorld = env.getWorld 1934 - lazy val env = new PlayerBasedCastEnv(player, 1935 - if player.getMainArm match 1936 - case Arm.LEFT => (flags & 4) != 0 1937 - case Arm.RIGHT => (flags & 4) == 0 1938 - then Hand.MAIN_HAND else Hand.OFF_HAND 1939 - ): 1940 - override def extractMediaEnvironment(cost: Long, simulate: Boolean): Long = 1941 - if player.isCreative then 0L else extractMediaFromInventory(cost, canOvercast, simulate) 1942 - override def getCastingHand: Hand = castingHand 1943 - override def getPigment = FrozenPigment(ItemStack(HexItems.DYE_PIGMENTS.get(color)), Util.NIL_UUID) 1944 - val context = 1945 - if (flags & 1) != 0 then 1946 - Seq.fill(buf.readInt)(buf.readUnlimitedNbt: Iota) 1947 - else 1948 - Seq() 1949 - val image = CastingImage(context :+ StringIota.make(text), 0, Seq(), false, 0, NbtCompound(), null) 1950 - val instrs = s.getList.asScala.toSeq 1951 - val vm = CastingVM(image, env) 1952 - val view = vm.queueExecuteAndWrapIotas(instrs :+ ContinuationIota(SpellContinuation.NotDone(MessageFrame(player.getUuid, stack.getName, player), SpellContinuation.Done.INSTANCE)), player.getServerWorld) 1953 - val packet = MsgNewSpiralPatternsS2C(player.getUuid, instrs.collect { case p: PatternIota => p.getPattern }.asJava, 140) 1954 - hexXplat.sendPacketToPlayer(player, packet) 1955 - hexXplat.sendPacketTracking(player, packet) 1956 - case _ => 1957 - case null => 1958 - case _ =>) 1959 1868 // dump patterns 1960 1869 val out = Files.newOutputStream(Path.of("patterns.csv")) 1961 1870 try
+4
util/build.gradle.kts
··· 52 52 } 53 53 } 54 54 55 + tasks.jar { 56 + duplicatesStrategy = DuplicatesStrategy.WARN 57 + } 58 + 55 59 publishing { 56 60 publications { 57 61 create<MavenPublication>("mavenJava") {