From b98fdf4434483f321b5a57909f92bdb75313ffeb Mon Sep 17 00:00:00 2001 From: A5ho9999 Date: Wed, 12 Mar 2025 12:45:23 +1030 Subject: [PATCH 1/4] Full working update with 1.21.4 (and 3 maybe) --- CHANGELOG.md | 14 ---- build.gradle | 67 ++++++++++------ gradle.properties | 24 +++--- gradle/wrapper/gradle-wrapper.properties | 2 +- .../java/io/ix0rai/rainglow/Rainglow.java | 78 ++++++++++++++++--- .../rainglow/client/RainglowClient.java | 21 +++++ .../rainglow/config/CustomModeScreen.java | 6 +- .../rainglow/config/PerWorldConfig.java | 21 +++-- .../data/EntityRenderStateTracker.java | 23 ++++++ .../ix0rai/rainglow/data/ParticleHelper.java | 22 ++++++ .../ix0rai/rainglow/data/RainglowEntity.java | 45 ++++++----- .../rainglow/data/RainglowNetworking.java | 42 +++++++++- .../rainglow/mixin/AllayEntityMixin.java | 19 ++--- .../ix0rai/rainglow/mixin/DyeItemMixin.java | 15 ++-- .../rainglow/mixin/GlowSquidEntityMixin.java | 18 ++--- .../ix0rai/rainglow/mixin/MobEntityMixin.java | 2 +- .../rainglow/mixin/SlimeEntityMixin.java | 58 +++++++++----- .../client/AllayEntityRendererMixin.java | 21 ++++- .../mixin/client/EntityRenderStateMixin.java | 29 +++++++ .../mixin/client/EntityRendererMixin.java | 20 +++++ .../client/GlowSquidEntityRendererMixin.java | 21 ++++- .../client/SlimeEntityRendererMixin.java | 21 ++++- .../SlimeOverlayFeatureRendererMixin.java | 64 +++++++++++++++ .../mixin/client/SlimeParticleMixin.java | 15 +++- .../mixin/client/SquidInkParticleMixin.java | 4 +- src/main/resources/fabric.mod.json | 8 +- src/main/resources/rainglow.accesswidener | 2 +- src/main/resources/rainglow.mixins.json | 3 + 28 files changed, 518 insertions(+), 167 deletions(-) create mode 100644 src/main/java/io/ix0rai/rainglow/data/EntityRenderStateTracker.java create mode 100644 src/main/java/io/ix0rai/rainglow/data/ParticleHelper.java create mode 100644 src/main/java/io/ix0rai/rainglow/mixin/client/EntityRenderStateMixin.java create mode 100644 src/main/java/io/ix0rai/rainglow/mixin/client/EntityRendererMixin.java create mode 100644 src/main/java/io/ix0rai/rainglow/mixin/client/SlimeOverlayFeatureRendererMixin.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5139d31..e69de29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +0,0 @@ -- data driving for rainglow modes - - modes are loaded from json through a server datapack - - when joining a server that has modes unknown to the client, they will be sent over - - modes define a text colour, an id, and a list of colours - -- config sync - - config sync can be toggled on and off through config - - when enabled, the client will send its config to the server on join - - the client cannot edit their config while in a server, either through the file or the screen - - this mode can be default, custom-defined through json, or even the builtin "custom" mode - - the client's config is reset when leaving the server - -- improvements to config parser -- stability improvements to data tracker registration \ No newline at end of file diff --git a/build.gradle b/build.gradle index 6a48f21..6745493 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,8 @@ +//file:noinspection GroovyAssignabilityCheck plugins { - id "fabric-loom" version "1.6.+" + id "fabric-loom" version "1.7.+" id "com.github.johnrengelman.shadow" version "7.1.+" - id "com.modrinth.minotaur" version "2.+" + id "me.modmuss50.mod-publish-plugin" version "0.5.2" } version = project.mod_version @@ -27,8 +28,8 @@ dependencies { modImplementation("net.fabricmc:fabric-loader:${project.loader_version}") modImplementation("com.terraformersmc:modmenu:${project.mod_menu_version}") - implementation("folk.sisby:kaleido-config:0.3.1+1.3.1") - include("folk.sisby:kaleido-config:0.3.1+1.3.1") + implementation("folk.sisby:kaleido-config:${project.kaleido_config_version}") + include("folk.sisby:kaleido-config:${project.kaleido_config_version}") Set apiModules = [ "fabric-networking-api-v1", @@ -56,26 +57,44 @@ loom { accessWidenerPath = file("src/main/resources/rainglow.accesswidener") } -//modrinth { -// syncBodyFrom = rootProject.file("README.md").text -// changelog = rootProject.file("CHANGELOG.md").text -// System.out.println("Enter your Modrinth API key: ") -// BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) -// token = br.readLine() -// projectId = "rainglow" -// versionNumber = project.version -// versionName = "rainglow " + project.version.toString().split("\\+")[0] + " for mc " + project.version.toString().split("\\+mc")[1] -// versionType = "release" -// uploadFile = remapJar -// gameVersions = ["1.19", "1.19.1", "1.19.2"] -// loaders = ["quilt", "fabric"] -// dependencies { -// optional.project "modmenu" -// } -// -// // sync readme -// tasks.modrinth.dependsOn(tasks.modrinthSyncBody) -//} +publishMods { + displayName = "rainglow ${project.version}" + file = remapJar.archiveFile + changelog = rootProject.file("CHANGELOG.md").getText() + type = STABLE + + modLoaders.add("quilt") + modLoaders.add("fabric") + + dryRun = !providers.environmentVariable("MODRINTH_TOKEN").isPresent() + || !providers.environmentVariable("CURSEFORGE_TOKEN").isPresent() + || property("pub.should_publish") == "false" + dryRun = false + + var mcVersions = [project.minecraft_version] + mcVersions.addAll(property("pub.additional_versions").toString().split(" ").findAll { !it.empty }) + + modrinth { + projectId = "Bk6pUD7R" + accessToken = providers.environmentVariable("MODRINTH_TOKEN") + mcVersions.forEach(minecraftVersions::add) + + requires "fabric-api" + optional "modmenu" + } + + curseforge { + accessToken = providers.environmentVariable("CURSEFORGE_TOKEN") + projectId = "682310" + mcVersions.forEach(minecraftVersions::add) + + clientRequired = true + serverRequired = false + + requires("fabric-api") + optional("modmenu") + } +} def targetJavaVersion = Integer.parseInt(project.java_version) tasks.withType(JavaCompile).configureEach { diff --git a/gradle.properties b/gradle.properties index 2b54143..f86f7e7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,22 @@ # increase gradle memory -org.gradle.jvmargs=-Xmx1G +org.gradle.jvmargs = -Xmx1G # minecraft, mappings and loader dependencies # check these on https://modmuss50.me/fabric.html -minecraft_version=1.21-rc1 -quilt_mappings=2 -loader_version=0.15.11 +minecraft_version = 1.21.4 +quilt_mappings = 3 +loader_version = 0.16.10 +kaleido_config_version = 0.3.1+1.3.2 # mod properties -mod_version=1.3.2+mc1.21 -maven_group=rainglow -archives_base_name=rainglow +mod_version = 1.3.5+mc1.21.4 +maven_group = rainglow +archives_base_name = rainglow # other dependencies -java_version=21 -mod_menu_version=11.0.0-beta.1 -fabric_api_version=0.100.1+1.21 +java_version = 21 +mod_menu_version = 13.0.0-beta.1 +fabric_api_version = 0.118.5+1.21.4 + +pub.should_publish = true +pub.additional_versions = 1.21.4 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23..a441313 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/io/ix0rai/rainglow/Rainglow.java b/src/main/java/io/ix0rai/rainglow/Rainglow.java index d8474fa..c1f97c1 100644 --- a/src/main/java/io/ix0rai/rainglow/Rainglow.java +++ b/src/main/java/io/ix0rai/rainglow/Rainglow.java @@ -8,11 +8,13 @@ import io.ix0rai.rainglow.config.RainglowConfig; import io.ix0rai.rainglow.data.*; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.entity.data.DataTracker; +import net.minecraft.entity.Entity; import net.minecraft.resource.ResourceType; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -22,7 +24,10 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.UUID; public class Rainglow implements ModInitializer { public static final String MOD_ID = "rainglow"; @@ -37,12 +42,16 @@ public class Rainglow implements ModInitializer { public static final Identifier SERVER_MODE_DATA_ID = id("server_mode_data"); public static final List RAINGLOW_DATAPACKS = new ArrayList<>(); + private static final Map COLOURS = new HashMap<>(); + @Override public void onInitialize() { ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener((RainglowResourceReloader) () -> SERVER_MODE_DATA_ID); PayloadTypeRegistry.playS2C().register(RainglowNetworking.ConfigSyncPayload.PACKET_ID, RainglowNetworking.ConfigSyncPayload.PACKET_CODEC); PayloadTypeRegistry.playS2C().register(RainglowNetworking.ModeSyncPayload.PACKET_ID, RainglowNetworking.ModeSyncPayload.PACKET_CODEC); + PayloadTypeRegistry.playS2C().register(RainglowNetworking.ColourPayload.PACKET_ID, RainglowNetworking.ColourPayload.PACKET_CODEC); + PayloadTypeRegistry.playC2S().register(RainglowNetworking.ColourPayload.PACKET_ID, RainglowNetworking.ColourPayload.PACKET_CODEC); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { // send modes to client @@ -50,21 +59,41 @@ public void onInitialize() { // send config to client RainglowNetworking.syncConfig(handler.player); + + // send all colours to client + RainglowNetworking.sendColoursTo(handler.player); }); + + ServerPlayNetworking.registerGlobalReceiver(RainglowNetworking.ColourPayload.PACKET_ID, (payload, context) -> { + for (var entry : payload.colours().entrySet()) { + RainglowColour colour = entry.getValue(); + Rainglow.setColour(entry.getKey(), colour); + } + }); + + ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> { + // Only clear colours on disconnect if server is NOT single-player to prevent NBT save failure (Unsure how this works with Lan-instances) + if (!server.isSingleplayer()) { + COLOURS.clear(); + } + }); + + // Instead use SERVER_STOPPED for clearing colours from single-player worlds. (Doesn't affect others because mod would most likely be shutdown in non-single-player instances) + ServerLifecycleEvents.SERVER_STOPPED.register(server -> COLOURS.clear()); } public static Identifier id(String id) { return Identifier.of(MOD_ID, id); } - public static String generateRandomColourId(World world, RandomGenerator random) { + public static RainglowColour generateRandomColour(World world, RandomGenerator random) { var colours = MODE_CONFIG.getMode(world).getColours(); - return colours.get(random.nextInt(colours.size())).getId(); + return colours.get(random.nextInt(colours.size())); } - public static boolean colourUnloaded(World world, RainglowEntity entityType, String colour) { + public static boolean colourUnloaded(World world, RainglowEntity entityType, RainglowColour colour) { var colours = MODE_CONFIG.getMode(world).getColours(); - return !colours.contains(RainglowColour.get(colour)) && !colour.equals(entityType.getDefaultColour().getId()); + return !colours.contains(colour) && colour != entityType.getDefaultColour(); } public static String translatableTextKey(String key) { @@ -80,15 +109,42 @@ public static Text translatableText(String key) { return Text.translatable(translatableTextKey(key)); } - public static RainglowColour getColour(World world, RainglowEntity entityType, DataTracker tracker, RandomGenerator random) { + public static RainglowColour getColour(Entity entity) { + RainglowColour colour = COLOURS.get(entity.getUuid()); + RainglowEntity entityType = RainglowEntity.get(entity); + // generate random colour if the squid's colour isn't currently loaded - String colour = tracker.get(entityType.getTrackedData()); - if (colourUnloaded(world, entityType, colour)) { + if (colourUnloaded(entity.getWorld(), entityType, colour)) { // Use last generated colour if not null else generate a new colour - tracker.set(entityType.getTrackedData(), generateRandomColourId(world, random)); - colour = tracker.get(entityType.getTrackedData()); + colour = generateRandomColour(entity.getWorld(), entity.getRandom()); + COLOURS.put(entity.getUuid(), colour); + } + + return colour; + } + + // Simplified method without any colour checks (Entity information isn't being passed through Rendering anymore, can be adjusted to apply in the RenderStateInteract if needed) + public static RainglowColour getColour(UUID entity) { + return COLOURS.get(entity); + } + + public static void setColour(Entity entity, RainglowColour colour) { + setColour(entity.getUuid(), colour); + + if (entity.getWorld().isClient()) { + // sync to server; will then be synced to all clients + RainglowNetworking.sendColourChangeToServer(entity, colour); + } else if (entity.getWorld().getServer().isDedicated()) { + // sync to all clients + RainglowNetworking.sendColourChangeToClients(entity, colour); } + } + + public static void setColour(UUID uuid, RainglowColour colour) { + COLOURS.put(uuid, colour); + } - return RainglowColour.get(colour); + public static Map getColours() { + return COLOURS; } } diff --git a/src/main/java/io/ix0rai/rainglow/client/RainglowClient.java b/src/main/java/io/ix0rai/rainglow/client/RainglowClient.java index 3d320ea..c540a2f 100644 --- a/src/main/java/io/ix0rai/rainglow/client/RainglowClient.java +++ b/src/main/java/io/ix0rai/rainglow/client/RainglowClient.java @@ -1,9 +1,11 @@ package io.ix0rai.rainglow.client; +import com.mojang.datafixers.util.Either; import folk.sisby.kaleido.lib.quiltconfig.api.values.TrackedValue; import folk.sisby.kaleido.lib.quiltconfig.api.values.ValueList; import folk.sisby.kaleido.lib.quiltconfig.api.values.ValueMap; import io.ix0rai.rainglow.Rainglow; +import io.ix0rai.rainglow.config.PerWorldConfig; import io.ix0rai.rainglow.data.RainglowColour; import io.ix0rai.rainglow.data.RainglowMode; import io.ix0rai.rainglow.data.RainglowResourceReloader; @@ -18,6 +20,7 @@ import net.minecraft.resource.ResourceType; import net.minecraft.util.Identifier; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -74,6 +77,16 @@ public void onInitializeClient() { }); }); + ClientPlayNetworking.registerGlobalReceiver(RainglowNetworking.ColourPayload.PACKET_ID, (payload, context) -> { + MinecraftClient client = context.client(); + client.execute(() -> { + for (var entry : payload.colours().entrySet()) { + RainglowColour colour = entry.getValue(); + Rainglow.setColour(entry.getKey(), colour); + } + }); + }); + ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> client.execute(() -> { // reset values to those configured in file @@ -95,4 +108,12 @@ public void log() { } }); } + + public static Either getSaveNameClient() { + if (MinecraftClient.getInstance().isInSingleplayer()) { + return Either.left(PerWorldConfig.getWorldPath(MinecraftClient.getInstance().getServer())); + } else { + return Either.right(MinecraftClient.getInstance().getCurrentServerEntry().address); + } + } } diff --git a/src/main/java/io/ix0rai/rainglow/config/CustomModeScreen.java b/src/main/java/io/ix0rai/rainglow/config/CustomModeScreen.java index 1e56d4a..5377505 100644 --- a/src/main/java/io/ix0rai/rainglow/config/CustomModeScreen.java +++ b/src/main/java/io/ix0rai/rainglow/config/CustomModeScreen.java @@ -100,7 +100,9 @@ public void init() { } @Override - protected void method_60325() {} + protected void initOptionButtons() { + // no-op + } @Override protected void repositionElements() { @@ -109,7 +111,7 @@ protected void repositionElements() { private static void sendNoColoursToast() { Toast toast = new SystemToast(SystemToast.Id.PACK_LOAD_FAILURE, Rainglow.translatableText("config.no_custom_colours"), Rainglow.translatableText("config.no_custom_colours_description")); - MinecraftClient.getInstance().getToastManager().add(toast); + MinecraftClient.getInstance().method_1566().method_1999(toast); } @Override diff --git a/src/main/java/io/ix0rai/rainglow/config/PerWorldConfig.java b/src/main/java/io/ix0rai/rainglow/config/PerWorldConfig.java index 47ca576..22dcf16 100644 --- a/src/main/java/io/ix0rai/rainglow/config/PerWorldConfig.java +++ b/src/main/java/io/ix0rai/rainglow/config/PerWorldConfig.java @@ -8,9 +8,9 @@ import folk.sisby.kaleido.lib.quiltconfig.api.values.TrackedValue; import folk.sisby.kaleido.lib.quiltconfig.api.values.ValueMap; import io.ix0rai.rainglow.Rainglow; +import io.ix0rai.rainglow.client.RainglowClient; import io.ix0rai.rainglow.data.RainglowMode; import io.ix0rai.rainglow.mixin.MinecraftServerAccessor; -import net.minecraft.client.MinecraftClient; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.world.World; @@ -46,11 +46,14 @@ public RainglowMode getMode(World world) { } } - if (mode == null) { - return RainglowMode.get(Rainglow.CONFIG.defaultMode.value()); - } else { - return RainglowMode.get(mode); + if (mode != null) { + RainglowMode rainglowMode = RainglowMode.get(mode); + if (rainglowMode != null) { + return rainglowMode; + } } + + return RainglowMode.get(Rainglow.CONFIG.defaultMode.value()); } public void setMode(World world, RainglowMode mode) { @@ -95,16 +98,12 @@ private static Either getSaveName(World world) { return Either.left(getWorldPath(world.getServer())); } } else { - if (MinecraftClient.getInstance().isInSingleplayer()) { - return Either.left(getWorldPath(MinecraftClient.getInstance().getServer())); - } else { - return Either.right(MinecraftClient.getInstance().getCurrentServerEntry().address); - } + return RainglowClient.getSaveNameClient(); } } @SuppressWarnings("ConstantConditions") - private static Path getWorldPath(MinecraftServer server) { + public static Path getWorldPath(MinecraftServer server) { return ((MinecraftServerAccessor) server).getSession().method_54543().path(); } diff --git a/src/main/java/io/ix0rai/rainglow/data/EntityRenderStateTracker.java b/src/main/java/io/ix0rai/rainglow/data/EntityRenderStateTracker.java new file mode 100644 index 0000000..9e9fdb5 --- /dev/null +++ b/src/main/java/io/ix0rai/rainglow/data/EntityRenderStateTracker.java @@ -0,0 +1,23 @@ +package io.ix0rai.rainglow.data; + +import net.minecraft.entity.Entity; + +import java.util.UUID; + +/** + * @author A5ho9999 + * Interface to track entity data in render states + */ +public interface EntityRenderStateTracker { + /** + * Set the associated entity + * @param entity The entity to associate with this render state + */ + void rainglow$setEntity(Entity entity); + + /** + * Get the associated entity UUID + * @return The UUID of the associated entity, or null if not set + */ + UUID rainglow$getEntityUuid(); +} \ No newline at end of file diff --git a/src/main/java/io/ix0rai/rainglow/data/ParticleHelper.java b/src/main/java/io/ix0rai/rainglow/data/ParticleHelper.java new file mode 100644 index 0000000..7b01172 --- /dev/null +++ b/src/main/java/io/ix0rai/rainglow/data/ParticleHelper.java @@ -0,0 +1,22 @@ +package io.ix0rai.rainglow.data; + +import net.minecraft.client.particle.ItemBreakParticle; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.unmapped.C_hvackyip; + +/** + * @author A5ho9999 + * Helper for creating particles because Mojang likes to torture everyone + */ +public class ParticleHelper { + public static class CustomItemBreakParticle extends ItemBreakParticle { + public CustomItemBreakParticle(ClientWorld world, double d, double e, double f, C_hvackyip c_hvackyip) { + super(world, d, e, f, c_hvackyip); + } + } + + public static Particle createItemBreakParticle(ClientWorld world, double d, double e, double f, C_hvackyip c_hvackyip) { + return new CustomItemBreakParticle(world, d, e, f, c_hvackyip); + } +} diff --git a/src/main/java/io/ix0rai/rainglow/data/RainglowEntity.java b/src/main/java/io/ix0rai/rainglow/data/RainglowEntity.java index d29a220..33f64c4 100644 --- a/src/main/java/io/ix0rai/rainglow/data/RainglowEntity.java +++ b/src/main/java/io/ix0rai/rainglow/data/RainglowEntity.java @@ -3,9 +3,6 @@ import io.ix0rai.rainglow.Rainglow; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityData; -import net.minecraft.entity.data.DataTracker; -import net.minecraft.entity.data.TrackedData; -import net.minecraft.entity.data.TrackedDataHandlerRegistry; import net.minecraft.entity.mob.SlimeEntity; import net.minecraft.entity.passive.AllayEntity; import net.minecraft.entity.passive.GlowSquidEntity; @@ -16,17 +13,17 @@ import net.minecraft.util.random.RandomGenerator; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Arrays; import java.util.HashMap; +import java.util.UUID; import java.util.function.Function; public enum RainglowEntity { - GLOW_SQUID("glow_squid", RainglowColour.BLUE, DataTracker.registerData(GlowSquidEntity.class, TrackedDataHandlerRegistry.STRING), GlowSquidEntityData::new), - ALLAY("allay", RainglowColour.BLUE, DataTracker.registerData(AllayEntity.class, TrackedDataHandlerRegistry.STRING), AllayEntityData::new), - SLIME("slime", RainglowColour.LIME, DataTracker.registerData(SlimeEntity.class, TrackedDataHandlerRegistry.STRING), SlimeEntityData::new); + GLOW_SQUID("glow_squid", RainglowColour.BLUE, GlowSquidEntityData::new), + ALLAY("allay", RainglowColour.BLUE, AllayEntityData::new), + SLIME("slime", RainglowColour.LIME, SlimeEntityData::new); private static final HashMap BY_ID = new HashMap<>(); static { @@ -35,13 +32,11 @@ public enum RainglowEntity { private final String id; private final RainglowColour defaultColour; - private final TrackedData trackedData; private final Function entityDataFactory; - RainglowEntity(String id, RainglowColour defaultColour, TrackedData trackedData, Function entityDataFactory) { + RainglowEntity(String id, RainglowColour defaultColour, Function entityDataFactory) { this.id = id; this.defaultColour = defaultColour; - this.trackedData = trackedData; this.entityDataFactory = entityDataFactory; } @@ -53,10 +48,6 @@ public RainglowColour getDefaultColour() { return this.defaultColour; } - public TrackedData getTrackedData() { - return this.trackedData; - } - public Identifier getDefaultTexture() { return this.defaultColour.getTexture(this); } @@ -74,13 +65,13 @@ public Item getItem(int index) { } public RainglowColour readNbt(World world, NbtCompound nbt, RandomGenerator random) { - String colour = nbt.getString(Rainglow.CUSTOM_NBT_KEY); + RainglowColour colour = RainglowColour.get(nbt.getString(Rainglow.CUSTOM_NBT_KEY)); if (Rainglow.colourUnloaded(world, this, colour)) { - colour = Rainglow.generateRandomColourId(world, random); + colour = Rainglow.generateRandomColour(world, random); } - return RainglowColour.get(colour); + return colour; } public static RainglowEntity read(PacketByteBuf buf) { @@ -96,7 +87,6 @@ public static RainglowEntity get(String id) { return BY_ID.get(id); } - @Unique @SuppressWarnings("all") public static RainglowEntity get(Entity entity) { if (entity instanceof GlowSquidEntity) { @@ -110,8 +100,8 @@ public static RainglowEntity get(Entity entity) { return null; } - public void overrideTexture(Entity entity, CallbackInfoReturnable cir) { - RainglowColour colour = Rainglow.getColour(entity.getWorld(), this, entity.getDataTracker(), entity.getWorld().getRandom()); + public void overrideTexture(UUID entity, CallbackInfoReturnable cir) { + RainglowColour colour = Rainglow.getColour(entity); // if the colour is default we don't need to override the method // this optimises a tiny bit @@ -120,4 +110,19 @@ public void overrideTexture(Entity entity, CallbackInfoReturnable ci cir.setReturnValue(texture != null ? texture : this.getDefaultTexture()); } } + + // Return the override texture instead of applying through callback + public Identifier overrideTexture(UUID entity) { + RainglowColour colour = Rainglow.getColour(entity); + + // Returning null will just use default texture, no need for extra checks + + // if the colour is default we don't need to override the method + // this optimises a tiny bit + if (Rainglow.CONFIG.isEntityEnabled(this) && colour != this.getDefaultColour()) { + return colour.getTexture(this); + } + + return null; + } } diff --git a/src/main/java/io/ix0rai/rainglow/data/RainglowNetworking.java b/src/main/java/io/ix0rai/rainglow/data/RainglowNetworking.java index 7435975..1225c3e 100644 --- a/src/main/java/io/ix0rai/rainglow/data/RainglowNetworking.java +++ b/src/main/java/io/ix0rai/rainglow/data/RainglowNetworking.java @@ -1,16 +1,20 @@ package io.ix0rai.rainglow.data; import io.ix0rai.rainglow.Rainglow; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.entity.Entity; import net.minecraft.network.PacketByteBuf; import net.minecraft.network.RegistryByteBuf; import net.minecraft.network.codec.PacketCodec; import net.minecraft.network.packet.payload.CustomPayload; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.UUID; public class RainglowNetworking { public static void syncConfig(ServerPlayerEntity player) { @@ -21,7 +25,7 @@ public static void syncConfig(ServerPlayerEntity player) { public record ConfigSyncPayload(String currentMode, List customMode, Map enabledMobs, Map rarities) implements CustomPayload { public static final CustomPayload.Id PACKET_ID = new CustomPayload.Id<>(Rainglow.id("config_sync")); - public static final PacketCodec PACKET_CODEC = PacketCodec.create(ConfigSyncPayload::write, ConfigSyncPayload::read); + public static final PacketCodec PACKET_CODEC = PacketCodec.of(ConfigSyncPayload::write, ConfigSyncPayload::read); public void write(RegistryByteBuf buf) { buf.writeString(this.currentMode); @@ -51,7 +55,7 @@ public static void syncModes(ServerPlayerEntity player) { public record ModeSyncPayload(Collection modes) implements CustomPayload { public static final CustomPayload.Id PACKET_ID = new CustomPayload.Id<>(Rainglow.id("mode_sync")); - public static final PacketCodec PACKET_CODEC = PacketCodec.create(ModeSyncPayload::write, ModeSyncPayload::read); + public static final PacketCodec PACKET_CODEC = PacketCodec.of(ModeSyncPayload::write, ModeSyncPayload::read); public void write(RegistryByteBuf buf) { buf.writeCollection(this.modes, RainglowMode::write); @@ -68,4 +72,38 @@ public Id getId() { return PACKET_ID; } } + + public static void sendColoursTo(ServerPlayerEntity player) { + ServerPlayNetworking.send(player, new ColourPayload(Rainglow.getColours())); + } + + public static void sendColourChangeToServer(Entity entity, RainglowColour colour) { + ClientPlayNetworking.send(new ColourPayload(Map.of(entity.getUuid(), colour))); + } + + public static void sendColourChangeToClients(Entity entity, RainglowColour colour) { + if (entity.getWorld() instanceof ServerWorld serverWorld) { + serverWorld.getPlayers().forEach(player -> ServerPlayNetworking.send(player, new ColourPayload(Map.of(entity.getUuid(), colour)))); + } else { + throw new RuntimeException("Cannot send colour change to clients from client"); + } + } + + public record ColourPayload(Map colours) implements CustomPayload { + public static final CustomPayload.Id PACKET_ID = new CustomPayload.Id<>(Rainglow.id("colour_change")); + public static final PacketCodec PACKET_CODEC = PacketCodec.of(ColourPayload::write, ColourPayload::read); + + public void write(RegistryByteBuf buf) { + buf.writeMap(this.colours, (b, uuid) -> b.writeUuid(uuid), RainglowColour::write); + } + + public static ColourPayload read(RegistryByteBuf buf) { + return new ColourPayload(buf.readMap(b -> b.readUuid(), RainglowColour::read)); + } + + @Override + public Id getId() { + return PACKET_ID; + } + } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/AllayEntityMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/AllayEntityMixin.java index f387c4c..a1ff810 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/AllayEntityMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/AllayEntityMixin.java @@ -6,11 +6,11 @@ import io.ix0rai.rainglow.data.RainglowEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; -import net.minecraft.entity.data.DataTracker.Builder; import net.minecraft.entity.passive.AllayEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -18,19 +18,16 @@ @Mixin(AllayEntity.class) public abstract class AllayEntityMixin extends Entity implements AllayVariantProvider { + @Shadow public abstract void writeCustomDataToNbt(NbtCompound nbt); + protected AllayEntityMixin(EntityType entityType, World world) { super(entityType, world); throw new UnsupportedOperationException(); } - @Inject(method = "initDataTracker", at = @At("TAIL")) - protected void initDataTracker(Builder builder, CallbackInfo ci) { - builder.add(RainglowEntity.ALLAY.getTrackedData(), RainglowEntity.ALLAY.getDefaultColour().getId()); - } - @Inject(method = "writeCustomDataToNbt", at = @At("TAIL")) public void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo ci) { - RainglowColour colour = Rainglow.getColour(this.getWorld(), RainglowEntity.ALLAY, this.getDataTracker(), this.random); + RainglowColour colour = Rainglow.getColour(this); nbt.putString(Rainglow.CUSTOM_NBT_KEY, colour.getId()); } @@ -42,18 +39,18 @@ public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) { // triggered when an allay duplicates, to apply the same colour as parent @Redirect(method = "duplicate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z")) public boolean spawnWithColour(World instance, Entity entity) { - RainglowColour colour = Rainglow.getColour(this.getWorld(), RainglowEntity.ALLAY, this.getDataTracker(), this.random); - entity.getDataTracker().set(RainglowEntity.ALLAY.getTrackedData(), colour.getId()); + RainglowColour colour = Rainglow.getColour(this); + ((AllayVariantProvider) entity).setVariant(colour); return this.getWorld().spawnEntity(entity); } @Override public RainglowColour getVariant() { - return Rainglow.getColour(this.getWorld(), RainglowEntity.ALLAY, this.getDataTracker(), this.random); + return Rainglow.getColour(this); } @Override public void setVariant(RainglowColour colour) { - this.getDataTracker().set(RainglowEntity.ALLAY.getTrackedData(), colour.getId()); + Rainglow.setColour(this, colour); } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/DyeItemMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/DyeItemMixin.java index eb0f556..7685cb4 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/DyeItemMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/DyeItemMixin.java @@ -1,9 +1,9 @@ package io.ix0rai.rainglow.mixin; import io.ix0rai.rainglow.Rainglow; +import io.ix0rai.rainglow.data.RainglowColour; import io.ix0rai.rainglow.data.RainglowEntity; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.data.DataTracker; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.DyeItem; import net.minecraft.item.ItemStack; @@ -24,21 +24,20 @@ public class DyeItemMixin { @Inject(method = "useOnEntity", at = @At("TAIL"), cancellable = true) private void useOnEntity(ItemStack stack, PlayerEntity user, LivingEntity entity, Hand hand, CallbackInfoReturnable cir) { if (Rainglow.CONFIG.allowDyeing.value()) { - String colour = getDye(stack); + RainglowColour colour = RainglowColour.get(getDye(stack)); RainglowEntity entityType = RainglowEntity.get(entity); - if (entityType != null && !Rainglow.colourUnloaded(user.getWorld(), entityType, colour) + if (entityType != null + && !Rainglow.colourUnloaded(user.getWorld(), entityType, colour) && Rainglow.CONFIG.isEntityEnabled(entityType) - && !Rainglow.getColour(user.getWorld(), entityType, entity.getDataTracker(), entity.getWorld().getRandom()).getId().equals(colour)) { + && Rainglow.getColour(entity) != colour) { entity.getWorld().playSoundFromEntity(user, entity, SoundEvents.BLOCK_AMETHYST_CLUSTER_BREAK, SoundCategory.PLAYERS, 5.0f, 1.0f); if (!user.getWorld().isClient()) { stack.decrement(1); } - DataTracker tracker = entity.getDataTracker(); - tracker.set(entityType.getTrackedData(), colour); - - cir.setReturnValue(ActionResult.success(user.getWorld().isClient())); + Rainglow.setColour(entity, colour); + cir.setReturnValue(ActionResult.SUCCESS); } } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/GlowSquidEntityMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/GlowSquidEntityMixin.java index fad2f04..5bf411d 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/GlowSquidEntityMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/GlowSquidEntityMixin.java @@ -5,10 +5,9 @@ import io.ix0rai.rainglow.data.RainglowEntity; import io.ix0rai.rainglow.data.GlowSquidVariantProvider; import net.minecraft.entity.EntityType; -import net.minecraft.entity.mob.WaterCreatureEntity; +import net.minecraft.entity.passive.WaterCreatureEntity; import net.minecraft.entity.passive.GlowSquidEntity; import net.minecraft.entity.passive.SquidEntity; -import net.minecraft.entity.data.DataTracker.Builder; import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleTypes; @@ -27,14 +26,9 @@ protected GlowSquidEntityMixin(EntityType entityType, Wor throw new UnsupportedOperationException(); } - @Inject(method = "initDataTracker", at = @At("TAIL")) - protected void initDataTracker(Builder builder, CallbackInfo ci) { - builder.add(RainglowEntity.GLOW_SQUID.getTrackedData(), RainglowEntity.GLOW_SQUID.getDefaultColour().getId()); - } - @Inject(method = "writeCustomDataToNbt", at = @At("TAIL")) public void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo ci) { - RainglowColour colour = Rainglow.getColour(this.getWorld(), RainglowEntity.GLOW_SQUID, this.getDataTracker(), this.random); + RainglowColour colour = Rainglow.getColour(this); nbt.putString(Rainglow.CUSTOM_NBT_KEY, colour.getId()); } @@ -49,7 +43,7 @@ public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) { */ @Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addParticle(Lnet/minecraft/particle/ParticleEffect;DDDDDD)V"), cancellable = true) public void tickMovement(CallbackInfo ci) { - RainglowColour colour = Rainglow.getColour(this.getWorld(), RainglowEntity.GLOW_SQUID, this.getDataTracker(), this.random); + RainglowColour colour = Rainglow.getColour(this); if (colour != RainglowColour.BLUE) { // we add 100 to g to let the mixin know that we want to override the method @@ -60,12 +54,12 @@ public void tickMovement(CallbackInfo ci) { @Override public RainglowColour getVariant() { - return Rainglow.getColour(this.getWorld(), RainglowEntity.GLOW_SQUID, this.getDataTracker(), this.random); + return Rainglow.getColour(this); } @Override public void setVariant(RainglowColour colour) { - this.getDataTracker().set(RainglowEntity.GLOW_SQUID.getTrackedData(), colour.getId()); + Rainglow.setColour(this, colour); } @Mixin(SquidEntity.class) @@ -85,7 +79,7 @@ protected SquidEntityMixin(EntityType entityType, private int spawnParticles(ServerWorld instance, ParticleEffect particle, double x, double y, double z, int count, double deltaX, double deltaY, double deltaZ, double speed) { if (((Object) this) instanceof GlowSquidEntity) { // send in custom colour data - RainglowColour colour = Rainglow.getColour(this.getWorld(), RainglowEntity.GLOW_SQUID, this.getDataTracker(), this.random); + RainglowColour colour = Rainglow.getColour(this); int index = colour.ordinal(); // round x to 1 decimal place and append index data to the next two return ((ServerWorld) this.getWorld()).spawnParticles(particle, (Math.round(x * 10)) / 10D + index / 1000D, y + 0.5, z, 0, deltaX, deltaY, deltaZ, speed); diff --git a/src/main/java/io/ix0rai/rainglow/mixin/MobEntityMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/MobEntityMixin.java index de59dc9..0359f48 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/MobEntityMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/MobEntityMixin.java @@ -41,6 +41,6 @@ private RainglowColour generateColour(RainglowEntity entity) { int i = random.nextInt(100); int rarity = Rainglow.CONFIG.getRarity(entity); - return i >= rarity ? entity.getDefaultColour() : RainglowColour.get(Rainglow.generateRandomColourId(this.getWorld(), this.random)); + return i >= rarity ? entity.getDefaultColour() : Rainglow.generateRandomColour(this.getWorld(), this.random); } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/SlimeEntityMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/SlimeEntityMixin.java index b63d9d2..2a69c87 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/SlimeEntityMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/SlimeEntityMixin.java @@ -4,19 +4,17 @@ import io.ix0rai.rainglow.data.RainglowColour; import io.ix0rai.rainglow.data.RainglowEntity; import io.ix0rai.rainglow.data.SlimeVariantProvider; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.data.DataTracker; +import net.minecraft.entity.*; import net.minecraft.entity.mob.SlimeEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleEffect; +import net.minecraft.scoreboard.Team; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -30,14 +28,9 @@ protected SlimeEntityMixin(EntityType entityType, World w throw new UnsupportedOperationException(); } - @Inject(method = "initDataTracker", at = @At("TAIL")) - protected void initDataTracker(DataTracker.Builder builder, CallbackInfo ci) { - builder.add(RainglowEntity.SLIME.getTrackedData(), RainglowEntity.SLIME.getDefaultColour().getId()); - } - @Inject(method = "writeCustomDataToNbt", at = @At("TAIL")) public void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo ci) { - RainglowColour colour = Rainglow.getColour(this.getWorld(), RainglowEntity.SLIME, this.getDataTracker(), this.random); + RainglowColour colour = Rainglow.getColour(this); nbt.putString(Rainglow.CUSTOM_NBT_KEY, colour.getId()); } @@ -49,11 +42,40 @@ public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) { /** * @reason make smaller slimes spawn with the same colour as the parent in a split */ - @Redirect(method = "remove", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z")) - public boolean spawnWithParentColour(World instance, Entity entity) { - RainglowColour colour = Rainglow.getColour(this.getWorld(), RainglowEntity.SLIME, this.getDataTracker(), this.random); - entity.getDataTracker().set(RainglowEntity.SLIME.getTrackedData(), colour.getId()); - return this.getWorld().spawnEntity(entity); + @Inject(method = "remove", at = @At("HEAD"), cancellable = true) + private void preserveColorOnSplit(Entity.RemovalReason reason, CallbackInfo ci) { + SlimeEntity thisSlime = (SlimeEntity) (Object) this; + int size = thisSlime.getSize(); + + if (!thisSlime.getWorld().isClient && size > 1 && thisSlime.isDead()) { + RainglowColour parentColor = Rainglow.getColour(thisSlime.getUuid()); + + float width = thisSlime.getDimensions(thisSlime.getPose()).width(); + float halfWidth = width / 2.0F; + int newSize = size / 2; + Team team = thisSlime.getScoreboardTeam(); + + int count = 2 + thisSlime.getRandom().nextInt(3); + + // Create multiple slimes individually while making sure it matches vanilla + for (int i = 0; i < count; i++) { + float offsetX = ((float) (i % 2) - 0.5F) * halfWidth; + float offsetZ = ((float) (i / 2) - 0.5F) * halfWidth; + + //noinspection unchecked + thisSlime.convert((EntityType) thisSlime.getType(), new EntityConversionParameters(EntityConversionType.SPLIT_ON_DEATH, false, false, team), SpawnReason.TRIGGERED, (newSlime) -> { + newSlime.setSize(newSize, true); + newSlime.refreshPositionAndAngles(thisSlime.getX() + offsetX, thisSlime.getY() + 0.5, thisSlime.getZ() + offsetZ, thisSlime.getRandom().nextFloat() * 360.0F, 0.0F); + + // Now that headache is done, finally set the child slime color to match the parent + ((SlimeVariantProvider) newSlime).setVariant(parentColor); + }); + } + + // Don't forget this, boy was that a mistake + super.remove(reason); + ci.cancel(); + } } /** @@ -68,7 +90,7 @@ public boolean spawnWithParentColour(World instance, Entity entity) { ) public void tick(CallbackInfo ci) { float size = this.getDimensions(this.getPose()).width(); - RainglowColour colour = Rainglow.getColour(this.getWorld(), RainglowEntity.SLIME, this.getDataTracker(), this.random); + RainglowColour colour = Rainglow.getColour(this); int index = colour.ordinal(); for (int j = 0; j < size / 2; j ++) { @@ -83,11 +105,11 @@ public void tick(CallbackInfo ci) { @Override public RainglowColour getVariant() { - return Rainglow.getColour(this.getWorld(), RainglowEntity.SLIME, this.getDataTracker(), this.random); + return Rainglow.getColour(this); } @Override public void setVariant(RainglowColour colour) { - this.getDataTracker().set(RainglowEntity.SLIME.getTrackedData(), colour.getId()); + Rainglow.setColour(this, colour); } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/AllayEntityRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/AllayEntityRendererMixin.java index 7df11b2..bb2eb03 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/AllayEntityRendererMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/AllayEntityRendererMixin.java @@ -1,18 +1,31 @@ package io.ix0rai.rainglow.mixin.client; +import io.ix0rai.rainglow.data.EntityRenderStateTracker; import io.ix0rai.rainglow.data.RainglowEntity; +import net.minecraft.class_9996; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.entity.AllayEntityRenderer; -import net.minecraft.entity.passive.AllayEntity; +import net.minecraft.client.world.ClientWorld; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.UUID; + @Mixin(AllayEntityRenderer.class) public class AllayEntityRendererMixin { - @Inject(method = "getTexture*", at = @At("HEAD"), cancellable = true) - public void getTexture(AllayEntity allayEntity, CallbackInfoReturnable cir) { - RainglowEntity.ALLAY.overrideTexture(allayEntity, cir); + @Inject(method = "m_vhdjjpxx", at = @At("HEAD"), cancellable = true) + public void getTexture(class_9996 state, CallbackInfoReturnable cir) { + if (state instanceof EntityRenderStateTracker) { + UUID entityUuid = ((EntityRenderStateTracker) state).rainglow$getEntityUuid(); + if (entityUuid != null) { + ClientWorld world = MinecraftClient.getInstance().world; + if (world != null) { + RainglowEntity.ALLAY.overrideTexture(entityUuid, cir); + } + } + } } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/EntityRenderStateMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/EntityRenderStateMixin.java new file mode 100644 index 0000000..3c6628f --- /dev/null +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/EntityRenderStateMixin.java @@ -0,0 +1,29 @@ +package io.ix0rai.rainglow.mixin.client; + +import io.ix0rai.rainglow.data.EntityRenderStateTracker; +import net.minecraft.class_10017; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +import java.util.UUID; + +@Mixin(class_10017.class) +public class EntityRenderStateMixin implements EntityRenderStateTracker { + @Unique + private UUID entityUuid; + + @Override + public void rainglow$setEntity(Entity entity) { + if (entity != null) { + this.entityUuid = entity.getUuid(); + } + } + + // TODO: This could be used to just get the Entity as well as the UUID but just saving the UUID is better for long term memory usage + + @Override + public UUID rainglow$getEntityUuid() { + return this.entityUuid; + } +} \ No newline at end of file diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/EntityRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/EntityRendererMixin.java new file mode 100644 index 0000000..d3c3778 --- /dev/null +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/EntityRendererMixin.java @@ -0,0 +1,20 @@ +package io.ix0rai.rainglow.mixin.client; + +import io.ix0rai.rainglow.data.EntityRenderStateTracker; +import net.minecraft.class_10017; +import net.minecraft.client.render.entity.EntityRenderer; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(EntityRenderer.class) +public class EntityRendererMixin { + @Inject(method = "method_62354", at = @At("HEAD")) + private void updateRenderState(T entity, S state, float f, CallbackInfo ci) { + if (state instanceof EntityRenderStateTracker) { + ((EntityRenderStateTracker) state).rainglow$setEntity(entity); + } + } +} diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/GlowSquidEntityRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/GlowSquidEntityRendererMixin.java index 183d38a..8eecbd3 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/GlowSquidEntityRendererMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/GlowSquidEntityRendererMixin.java @@ -1,22 +1,35 @@ package io.ix0rai.rainglow.mixin.client; +import io.ix0rai.rainglow.data.EntityRenderStateTracker; import io.ix0rai.rainglow.data.RainglowEntity; +import net.minecraft.class_10069; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.entity.GlowSquidEntityRenderer; -import net.minecraft.entity.passive.GlowSquidEntity; +import net.minecraft.client.world.ClientWorld; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.UUID; + @Mixin(GlowSquidEntityRenderer.class) public class GlowSquidEntityRendererMixin { /** * @reason use the colour from the entity's NBT data for textures * @author ix0rai */ - @Inject(method = "getTexture*", at = @At("HEAD"), cancellable = true) - public void getTexture(GlowSquidEntity glowSquidEntity, CallbackInfoReturnable cir) { - RainglowEntity.GLOW_SQUID.overrideTexture(glowSquidEntity, cir); + @Inject(method = "m_vhdjjpxx", at = @At("HEAD"), cancellable = true) + public void getTexture(class_10069 state, CallbackInfoReturnable cir) { + if (state instanceof EntityRenderStateTracker) { + UUID entityUuid = ((EntityRenderStateTracker) state).rainglow$getEntityUuid(); + if (entityUuid != null) { + ClientWorld world = MinecraftClient.getInstance().world; + if (world != null) { + RainglowEntity.GLOW_SQUID.overrideTexture(entityUuid, cir); + } + } + } } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeEntityRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeEntityRendererMixin.java index fe16520..672ab7b 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeEntityRendererMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeEntityRendererMixin.java @@ -1,18 +1,31 @@ package io.ix0rai.rainglow.mixin.client; +import io.ix0rai.rainglow.data.EntityRenderStateTracker; import io.ix0rai.rainglow.data.RainglowEntity; +import net.minecraft.class_10067; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.entity.SlimeEntityRenderer; -import net.minecraft.entity.mob.SlimeEntity; +import net.minecraft.client.world.ClientWorld; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.UUID; + @Mixin(SlimeEntityRenderer.class) public class SlimeEntityRendererMixin { - @Inject(method = "getTexture*", at = @At("HEAD"), cancellable = true) - public void getTexture(SlimeEntity entity, CallbackInfoReturnable cir) { - RainglowEntity.SLIME.overrideTexture(entity, cir); + @Inject(method = "m_vhdjjpxx", at = @At("HEAD"), cancellable = true) + public void getTexture(class_10067 state, CallbackInfoReturnable cir) { + if (state instanceof EntityRenderStateTracker) { + UUID entityUuid = ((EntityRenderStateTracker) state).rainglow$getEntityUuid(); + if (entityUuid != null) { + ClientWorld world = MinecraftClient.getInstance().world; + if (world != null) { + RainglowEntity.SLIME.overrideTexture(entityUuid, cir); + } + } + } } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeOverlayFeatureRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeOverlayFeatureRendererMixin.java new file mode 100644 index 0000000..2642215 --- /dev/null +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeOverlayFeatureRendererMixin.java @@ -0,0 +1,64 @@ +package io.ix0rai.rainglow.mixin.client; + +import io.ix0rai.rainglow.data.EntityRenderStateTracker; +import io.ix0rai.rainglow.data.RainglowEntity; +import net.minecraft.class_10067; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.SlimeEntityRenderer; +import net.minecraft.client.render.entity.feature.SlimeOverlayFeatureRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.UUID; + +/** + * @author A5ho9999 + * They've updated the render to display the outer and inner serperately, this could be used for some fun random combinations in the future. + */ +@Mixin(SlimeOverlayFeatureRenderer.class) +public class SlimeOverlayFeatureRendererMixin { + /** + * Override the outline texture for slimes, defaults back to normal if null + */ + @Redirect(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/class_10067;FF)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayer;getOutline(Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;")) + private RenderLayer rainglow$getOutline(Identifier defaultTexture, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, class_10067 state, float f, float g) { + Identifier overrideTexture = getOverrideTexture(state); + return overrideTexture != null ? RenderLayer.getOutline(overrideTexture) : RenderLayer.getOutline(SlimeEntityRenderer.TEXTURE); + } + + /** + * Override the translucent texture for slimes, defaults back to normal if null + */ + @Redirect(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/class_10067;FF)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayer;getEntityTranslucent(Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;")) + private RenderLayer rainglow$getEntityTranslucent(Identifier defaultTexture, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, class_10067 state, float f, float g) { + Identifier overrideTexture = getOverrideTexture(state); + return overrideTexture != null ? RenderLayer.getEntityTranslucent(overrideTexture) : RenderLayer.getEntityTranslucent(SlimeEntityRenderer.TEXTURE); + } + + @Unique + private Identifier getOverrideTexture(class_10067 state) { + if (state instanceof EntityRenderStateTracker) { + UUID entityUuid = ((EntityRenderStateTracker) state).rainglow$getEntityUuid(); + if (entityUuid != null) { + ClientWorld world = MinecraftClient.getInstance().world; + if (world != null) { + try { + return RainglowEntity.SLIME.overrideTexture(entityUuid); + } catch (Exception e) { + // ignore any errors and just let return null for default textures + } + } + } + } + return null; + } +} diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeParticleMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeParticleMixin.java index 83327e6..fc3ad08 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeParticleMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeParticleMixin.java @@ -1,13 +1,17 @@ package io.ix0rai.rainglow.mixin.client; import io.ix0rai.rainglow.Rainglow; +import io.ix0rai.rainglow.data.ParticleHelper; import io.ix0rai.rainglow.data.RainglowEntity; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.particle.ItemBreakParticle; import net.minecraft.client.particle.Particle; +import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.client.world.ClientWorld; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.particle.DefaultParticleType; +import net.minecraft.unmapped.C_hvackyip; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,19 +20,24 @@ @Mixin(ItemBreakParticle.SlimeballFactory.class) public class SlimeParticleMixin { /** - * @author ix0rai + * @author ix0rai, A5ho9999 * @reason recolor particles */ @Inject(method = "createParticle*", at = @At("HEAD"), cancellable = true) public void createParticle(DefaultParticleType defaultParticleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i, CallbackInfoReturnable cir) { + C_hvackyip itemRenderState = new C_hvackyip(); + if (!Rainglow.CONFIG.isEntityEnabled(RainglowEntity.SLIME)) { - cir.setReturnValue(new ItemBreakParticle(clientWorld, d, e, f, new ItemStack(Items.SLIME_BALL))); + MinecraftClient.getInstance().method_65386().method_65598(itemRenderState, new ItemStack(Items.SLIME_BALL), ModelTransformationMode.GROUND, false, clientWorld, null, 0); + cir.setReturnValue(ParticleHelper.createItemBreakParticle(clientWorld, d, e, f, itemRenderState)); // 99.9d and 100.1d are used to account for floating point errors } else if (h >= 99.9d && h <= 100.1d) { ItemStack stack = RainglowEntity.SLIME.getItem((int) g).getDefaultStack(); - cir.setReturnValue(new ItemBreakParticle(clientWorld, d, e, f, stack)); + MinecraftClient.getInstance().method_65386().method_65598(itemRenderState, stack, ModelTransformationMode.GROUND, false, clientWorld, null, 0); + cir.setReturnValue(ParticleHelper.createItemBreakParticle(clientWorld, d, e, f, itemRenderState)); } else { cir.setReturnValue(null); } } + } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/SquidInkParticleMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/SquidInkParticleMixin.java index a6ae80b..638327d 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/SquidInkParticleMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/SquidInkParticleMixin.java @@ -6,9 +6,9 @@ import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.SpriteProvider; import net.minecraft.client.particle.SquidInkParticle; -import net.minecraft.client.util.ColorUtil; import net.minecraft.client.world.ClientWorld; import net.minecraft.particle.DefaultParticleType; +import net.minecraft.util.ArgbHelper; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -50,7 +50,7 @@ public void createParticle(DefaultParticleType defaultParticleType, ClientWorld rgb = RainglowColour.WHITE.getInkRgb(); } - cir.setReturnValue(new SquidInkParticle(clientWorld, d, e, f, g, h, i, ColorUtil.Argb32.of(255, (int) rgb.r(), (int) rgb.g(), (int) rgb.b()), this.spriteProvider)); + cir.setReturnValue(new SquidInkParticle(clientWorld, d, e, f, g, h, i, ArgbHelper.color(255, (int) rgb.r(), (int) rgb.g(), (int) rgb.b()), this.spriteProvider)); } } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 78929db..2e356bd 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -19,7 +19,7 @@ "license": "MIT", "icon": "assets/rainglow/icon.png", "environment": "*", - "accessWidener" : "rainglow.accesswidener", + "accessWidener": "rainglow.accesswidener", "mixins": [ "rainglow.mixins.json" ], @@ -37,14 +37,14 @@ }, "depends": { - "fabricloader": ">=0.15.11", + "fabricloader": ">=0.16.7", "fabric-resource-loader-v0": "*", "fabric-networking-api-v1": "*", - "minecraft": ">=1.21-" + "minecraft": ">=1.21.2" }, "suggests": { - "modmenu": ">=11.0.0-" + "modmenu": ">=12.0.0-" }, "custom": { diff --git a/src/main/resources/rainglow.accesswidener b/src/main/resources/rainglow.accesswidener index 9225a7c..f26e0cb 100644 --- a/src/main/resources/rainglow.accesswidener +++ b/src/main/resources/rainglow.accesswidener @@ -14,7 +14,7 @@ accessible class net/minecraft/client/option/Option$CyclingValueSet accessible method net/minecraft/client/particle/GlowParticle (Lnet/minecraft/client/world/ClientWorld;DDDDDDLnet/minecraft/client/particle/SpriteProvider;)V accessible field net/minecraft/client/particle/GlowParticle RANDOM Lnet/minecraft/util/random/RandomGenerator; -accessible method net/minecraft/client/particle/ItemBreakParticle (Lnet/minecraft/client/world/ClientWorld;DDDLnet/minecraft/item/ItemStack;)V +accessible class net/minecraft/client/particle/ItemBreakParticle accessible method net/minecraft/client/particle/SquidInkParticle (Lnet/minecraft/client/world/ClientWorld;DDDDDDILnet/minecraft/client/particle/SpriteProvider;)V diff --git a/src/main/resources/rainglow.mixins.json b/src/main/resources/rainglow.mixins.json index 00c88d0..1688a03 100644 --- a/src/main/resources/rainglow.mixins.json +++ b/src/main/resources/rainglow.mixins.json @@ -14,9 +14,12 @@ ], "client": [ "client.AllayEntityRendererMixin", + "client.EntityRendererMixin", + "client.EntityRenderStateMixin", "client.GlowParticleMixin", "client.GlowSquidEntityRendererMixin", "client.SlimeEntityRendererMixin", + "client.SlimeOverlayFeatureRendererMixin", "client.SlimeParticleMixin", "client.SquidInkParticleMixin", "client.screen.CyclingValueSetMixin", From 5600a32172c2d7dd6bed80b8a064b6cf2959d0f5 Mon Sep 17 00:00:00 2001 From: A5ho9999 Date: Wed, 12 Mar 2025 13:12:22 +1030 Subject: [PATCH 2/4] Update build.yml --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e133f9..b94ce06 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: set up JDK 21 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '21' @@ -18,7 +18,7 @@ jobs: - name: build with gradle run: ./gradlew build - name: capture build artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: artifacts path: build/libs/ From 479e46c6c25387e228688864e806a4bbcf21ddb0 Mon Sep 17 00:00:00 2001 From: ix0rai Date: Thu, 20 Mar 2025 20:10:52 -0500 Subject: [PATCH 3/4] fix crash when spawning new entity --- .../ix0rai/rainglow/data/RainglowEntity.java | 23 +++++++++++-------- .../client/AllayEntityRendererMixin.java | 4 +++- .../client/GlowSquidEntityRendererMixin.java | 4 +++- .../client/SlimeEntityRendererMixin.java | 4 +++- .../SlimeOverlayFeatureRendererMixin.java | 2 +- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/ix0rai/rainglow/data/RainglowEntity.java b/src/main/java/io/ix0rai/rainglow/data/RainglowEntity.java index 33f64c4..7d5cdc0 100644 --- a/src/main/java/io/ix0rai/rainglow/data/RainglowEntity.java +++ b/src/main/java/io/ix0rai/rainglow/data/RainglowEntity.java @@ -1,6 +1,7 @@ package io.ix0rai.rainglow.data; import io.ix0rai.rainglow.Rainglow; +import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityData; import net.minecraft.entity.mob.SlimeEntity; @@ -13,11 +14,11 @@ import net.minecraft.util.random.RandomGenerator; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Arrays; import java.util.HashMap; import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; public enum RainglowEntity { @@ -100,19 +101,21 @@ public static RainglowEntity get(Entity entity) { return null; } - public void overrideTexture(UUID entity, CallbackInfoReturnable cir) { - RainglowColour colour = Rainglow.getColour(entity); + @Nullable + public Identifier overrideTexture(ClientWorld world, UUID uuid) { + AtomicReference texture = new AtomicReference<>(); - // if the colour is default we don't need to override the method - // this optimises a tiny bit - if (Rainglow.CONFIG.isEntityEnabled(this) && colour != this.getDefaultColour()) { - Identifier texture = colour.getTexture(this); - cir.setReturnValue(texture != null ? texture : this.getDefaultTexture()); - } + world.getEntities().forEach(entity -> { + if (entity.getUuid().equals(uuid)) { + texture.set(this.overrideTexture(entity)); + } + }); + + return texture.get(); } // Return the override texture instead of applying through callback - public Identifier overrideTexture(UUID entity) { + public Identifier overrideTexture(Entity entity) { RainglowColour colour = Rainglow.getColour(entity); // Returning null will just use default texture, no need for extra checks diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/AllayEntityRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/AllayEntityRendererMixin.java index bb2eb03..0a5563c 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/AllayEntityRendererMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/AllayEntityRendererMixin.java @@ -23,7 +23,9 @@ public void getTexture(class_9996 state, CallbackInfoReturnable cir) if (entityUuid != null) { ClientWorld world = MinecraftClient.getInstance().world; if (world != null) { - RainglowEntity.ALLAY.overrideTexture(entityUuid, cir); + RainglowEntity type = RainglowEntity.ALLAY; + Identifier texture = type.overrideTexture(world, entityUuid); + cir.setReturnValue(texture != null ? texture : type.getDefaultTexture()); } } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/GlowSquidEntityRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/GlowSquidEntityRendererMixin.java index 8eecbd3..d3d1921 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/GlowSquidEntityRendererMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/GlowSquidEntityRendererMixin.java @@ -27,7 +27,9 @@ public void getTexture(class_10069 state, CallbackInfoReturnable cir if (entityUuid != null) { ClientWorld world = MinecraftClient.getInstance().world; if (world != null) { - RainglowEntity.GLOW_SQUID.overrideTexture(entityUuid, cir); + RainglowEntity type = RainglowEntity.GLOW_SQUID; + Identifier texture = type.overrideTexture(world, entityUuid); + cir.setReturnValue(texture != null ? texture : type.getDefaultTexture()); } } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeEntityRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeEntityRendererMixin.java index 672ab7b..cf77e8b 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeEntityRendererMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeEntityRendererMixin.java @@ -23,7 +23,9 @@ public void getTexture(class_10067 state, CallbackInfoReturnable cir if (entityUuid != null) { ClientWorld world = MinecraftClient.getInstance().world; if (world != null) { - RainglowEntity.SLIME.overrideTexture(entityUuid, cir); + RainglowEntity type = RainglowEntity.SLIME; + Identifier texture = type.overrideTexture(world, entityUuid); + cir.setReturnValue(texture != null ? texture : type.getDefaultTexture()); } } } diff --git a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeOverlayFeatureRendererMixin.java b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeOverlayFeatureRendererMixin.java index 2642215..48bc6a2 100644 --- a/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeOverlayFeatureRendererMixin.java +++ b/src/main/java/io/ix0rai/rainglow/mixin/client/SlimeOverlayFeatureRendererMixin.java @@ -52,7 +52,7 @@ private Identifier getOverrideTexture(class_10067 state) { ClientWorld world = MinecraftClient.getInstance().world; if (world != null) { try { - return RainglowEntity.SLIME.overrideTexture(entityUuid); + return RainglowEntity.SLIME.overrideTexture(world, entityUuid); } catch (Exception e) { // ignore any errors and just let return null for default textures } From 81d4fac02b92996f0349c4b36a817f6406b9b36f Mon Sep 17 00:00:00 2001 From: ix0rai Date: Fri, 21 Mar 2025 21:00:47 -0500 Subject: [PATCH 4/4] fix a cast exception on glow squids --- .../ix0rai/rainglow/data/GlowSquidEntityData.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/ix0rai/rainglow/data/GlowSquidEntityData.java b/src/main/java/io/ix0rai/rainglow/data/GlowSquidEntityData.java index 2daa42a..5d03ccf 100644 --- a/src/main/java/io/ix0rai/rainglow/data/GlowSquidEntityData.java +++ b/src/main/java/io/ix0rai/rainglow/data/GlowSquidEntityData.java @@ -1,6 +1,17 @@ package io.ix0rai.rainglow.data; -import net.minecraft.entity.EntityData; +import net.minecraft.entity.passive.PassiveEntity; -public record GlowSquidEntityData(RainglowColour colour) implements EntityData { +public class GlowSquidEntityData extends PassiveEntity.PassiveData { + private final RainglowColour colour; + + public GlowSquidEntityData(RainglowColour colour) { + // copied from SquidEntity#initialize. as far as i can tell we have to duplicate this constant + super(0.05F); + this.colour = colour; + } + + public RainglowColour getColour() { + return colour; + } }