From c383705d8bedb716c6f3063de9c893dee601470a Mon Sep 17 00:00:00 2001 From: IAFEnvoy Date: Sun, 15 Dec 2024 22:54:08 +0800 Subject: [PATCH] add glint --- .../sow/mixin/BufferBuilderStorageMixin.java | 22 +++++++ .../iafenvoy/sow/mixin/ItemRendererMixin.java | 46 ++++++++++++++ .../sow/render/glint/GlintLayerManager.java | 61 +++++++++++++++++++ .../sow/render/glint/GlintManager.java | 51 ++++++++++++++++ common/src/main/resources/sow.mixins.json | 2 + 5 files changed, 182 insertions(+) create mode 100644 common/src/main/java/com/iafenvoy/sow/mixin/BufferBuilderStorageMixin.java create mode 100644 common/src/main/java/com/iafenvoy/sow/mixin/ItemRendererMixin.java create mode 100644 common/src/main/java/com/iafenvoy/sow/render/glint/GlintLayerManager.java create mode 100644 common/src/main/java/com/iafenvoy/sow/render/glint/GlintManager.java diff --git a/common/src/main/java/com/iafenvoy/sow/mixin/BufferBuilderStorageMixin.java b/common/src/main/java/com/iafenvoy/sow/mixin/BufferBuilderStorageMixin.java new file mode 100644 index 0000000..f74b184 --- /dev/null +++ b/common/src/main/java/com/iafenvoy/sow/mixin/BufferBuilderStorageMixin.java @@ -0,0 +1,22 @@ +package com.iafenvoy.sow.mixin; + +import com.iafenvoy.sow.render.glint.GlintLayerManager; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.BufferBuilderStorage; +import net.minecraft.client.render.RenderLayer; +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; + +@Environment(EnvType.CLIENT) +@Mixin(BufferBuilderStorage.class) +public class BufferBuilderStorageMixin { + @Inject(method = "assignBufferBuilder", at = @At("HEAD")) + private static void registerGlints(Object2ObjectLinkedOpenHashMap builderStorage, RenderLayer layer, CallbackInfo ci) { + GlintLayerManager.registerAll(builderStorage); + } +} diff --git a/common/src/main/java/com/iafenvoy/sow/mixin/ItemRendererMixin.java b/common/src/main/java/com/iafenvoy/sow/mixin/ItemRendererMixin.java new file mode 100644 index 0000000..39f7beb --- /dev/null +++ b/common/src/main/java/com/iafenvoy/sow/mixin/ItemRendererMixin.java @@ -0,0 +1,46 @@ +package com.iafenvoy.sow.mixin; + +import com.iafenvoy.sow.render.glint.GlintLayerManager; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +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.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Environment(EnvType.CLIENT) +@Mixin(value = ItemRenderer.class, priority = 1001) +public class ItemRendererMixin { + @Unique + private static ItemStack songsOfWar$tempStack = ItemStack.EMPTY; + + @Inject(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V", at = @At("HEAD")) + private void onStartRenderItem(ItemStack stack, ModelTransformationMode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model, CallbackInfo ci) { + songsOfWar$tempStack = stack; + } + + @Inject(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;)V", at = @At("TAIL")) + private void onEndRenderItem(ItemStack stack, ModelTransformationMode renderMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model, CallbackInfo ci) { + songsOfWar$tempStack = ItemStack.EMPTY; + } + + @ModifyVariable(method = "getDirectItemGlintConsumer", at = @At("HEAD"), ordinal = 1, argsOnly = true) + private static boolean changeGlint(boolean glint) { + return glint || GlintLayerManager.shouldAlwaysGlint(songsOfWar$tempStack); + } + + @ModifyExpressionValue(method = "getDirectItemGlintConsumer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayer;getDirectGlint()Lnet/minecraft/client/render/RenderLayer;")) + private static RenderLayer onGetDirectItemGlintConsumer(RenderLayer original) { + return GlintLayerManager.process(original, songsOfWar$tempStack); + } +} diff --git a/common/src/main/java/com/iafenvoy/sow/render/glint/GlintLayerManager.java b/common/src/main/java/com/iafenvoy/sow/render/glint/GlintLayerManager.java new file mode 100644 index 0000000..47be5ce --- /dev/null +++ b/common/src/main/java/com/iafenvoy/sow/render/glint/GlintLayerManager.java @@ -0,0 +1,61 @@ +package com.iafenvoy.sow.render.glint; + +import com.iafenvoy.neptune.render.glint.GlintManager; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.*; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtElement; +import org.jetbrains.annotations.ApiStatus; + +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; + +@Environment(EnvType.CLIENT) +public class GlintLayerManager { + private static final Map LAYERS = new HashMap<>(); + + static { + for (com.iafenvoy.neptune.render.glint.GlintManager.GlintHolder holder : com.iafenvoy.neptune.render.glint.GlintManager.HOLDERS) { + if (holder.texture() == null) continue; + RenderLayer layer = RenderLayer.of("glint_" + holder.id(), + VertexFormats.POSITION_TEXTURE, + VertexFormat.DrawMode.QUADS, + 256, + RenderLayer.MultiPhaseParameters.builder().program(RenderPhase.DIRECT_GLINT_PROGRAM) + .texture(new RenderPhase.Texture(holder.texture(), true, false)) + .writeMaskState(RenderPhase.COLOR_MASK) + .cull(RenderPhase.DISABLE_CULLING) + .depthTest(RenderPhase.EQUAL_DEPTH_TEST) + .transparency(RenderPhase.GLINT_TRANSPARENCY) + .texturing(RenderPhase.GLINT_TEXTURING) + .build(false)); + LAYERS.put(holder, layer); + } + } + + @ApiStatus.Internal + public static void registerAll(SortedMap map) { + for (Map.Entry entry : LAYERS.entrySet()) + if (!map.containsKey(entry.getValue())) + map.put(entry.getValue(), new BufferBuilder(entry.getValue().getExpectedBufferSize())); + } + + public static boolean shouldAlwaysGlint(ItemStack stack) { + return !stack.isEmpty() && + stack.getNbt() != null && + stack.getNbt().contains(com.iafenvoy.neptune.render.glint.GlintManager.GLINT_KEY, NbtElement.STRING_TYPE) && + com.iafenvoy.neptune.render.glint.GlintManager.BY_ID.containsKey(stack.getOrCreateNbt().getString(com.iafenvoy.neptune.render.glint.GlintManager.GLINT_KEY)) && + stack.getNbt().getBoolean(com.iafenvoy.neptune.render.glint.GlintManager.GLINT_ALWAYS_KEY); + } + + public static RenderLayer process(RenderLayer origin, ItemStack stack) { + if (!stack.isEmpty() && stack.getNbt() != null && stack.getNbt().contains(com.iafenvoy.neptune.render.glint.GlintManager.GLINT_KEY, NbtElement.STRING_TYPE)) { + String id = stack.getOrCreateNbt().getString(com.iafenvoy.neptune.render.glint.GlintManager.GLINT_KEY); + if (stack.getNbt().getBoolean(com.iafenvoy.neptune.render.glint.GlintManager.GLINT_ALWAYS_KEY)) + return LAYERS.getOrDefault(com.iafenvoy.neptune.render.glint.GlintManager.BY_ID.getOrDefault(id, GlintManager.DEFAULT), RenderLayer.getDirectGlint()); + } + return origin; + } +} diff --git a/common/src/main/java/com/iafenvoy/sow/render/glint/GlintManager.java b/common/src/main/java/com/iafenvoy/sow/render/glint/GlintManager.java new file mode 100644 index 0000000..4aa1839 --- /dev/null +++ b/common/src/main/java/com/iafenvoy/sow/render/glint/GlintManager.java @@ -0,0 +1,51 @@ +package com.iafenvoy.sow.render.glint; + +import com.iafenvoy.neptune.Neptune; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GlintManager { + public static final String GLINT_KEY = "glint"; + public static final String GLINT_ALWAYS_KEY = "glint_always"; + public static final List HOLDERS = new ArrayList<>(); + public static final Map BY_ID = new HashMap<>(); + + public static final GlintHolder DEFAULT = new GlintHolder("default", null, Formatting.WHITE); + public static final GlintHolder RED = new GlintHolder("red", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_red.png"), Formatting.RED); + public static final GlintHolder YELLOW = new GlintHolder("yellow", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_yellow.png"), Formatting.YELLOW); + public static final GlintHolder BLUE = new GlintHolder("blue", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_blue.png"), Formatting.BLUE); + public static final GlintHolder ORANGE = new GlintHolder("orange", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_orange.png"), Formatting.GOLD); + public static final GlintHolder GREEN = new GlintHolder("green", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_green.png"), Formatting.GREEN); + public static final GlintHolder PURPLE = new GlintHolder("purple", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_purple.png"), Formatting.DARK_PURPLE); + public static final GlintHolder WHITE = new GlintHolder("white", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_white.png"), Formatting.WHITE); + public static final GlintHolder PINK = new GlintHolder("pink", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_pink.png"), Formatting.LIGHT_PURPLE); + public static final GlintHolder AQUA = new GlintHolder("aqua", new Identifier(Neptune.MOD_ID, "textures/misc/glint_item_aqua.png"), Formatting.AQUA); + + public static ItemStack removeGlint(ItemStack stack) { + stack.getOrCreateNbt().remove(GLINT_KEY); + stack.getOrCreateNbt().remove(GLINT_ALWAYS_KEY); + return stack; + } + + public record GlintHolder(String id, Identifier texture, Formatting textColor) { + public GlintHolder(String id, Identifier texture, Formatting textColor) { + this.id = id; + this.texture = texture; + this.textColor = textColor; + HOLDERS.add(this); + BY_ID.put(this.id, this); + } + + public ItemStack apply(ItemStack stack, boolean always) { + stack.getOrCreateNbt().putString(GLINT_KEY, this.id); + stack.getOrCreateNbt().putBoolean(GLINT_ALWAYS_KEY, always); + return stack; + } + } +} diff --git a/common/src/main/resources/sow.mixins.json b/common/src/main/resources/sow.mixins.json index 9eef35f..29b9f2b 100644 --- a/common/src/main/resources/sow.mixins.json +++ b/common/src/main/resources/sow.mixins.json @@ -17,7 +17,9 @@ "integration.ModPacketsC2SMixin" ], "client": [ + "BufferBuilderStorageMixin", "InGameHudMixin", + "ItemRendererMixin", "PlayerEntityRendererMixin", "WorldAccessor" ],