diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8fc3827..2606ecd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: - name: setup jdk uses: actions/setup-java@v4 with: - java-version: '21' + java-version: '25' distribution: 'microsoft' - name: make gradle wrapper executable run: chmod +x ./gradlew diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 913970d..37e08bc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,7 +16,7 @@ jobs: - name: setup jdk uses: actions/setup-java@v4 with: - java-version: '21' + java-version: '25' distribution: 'microsoft' - name: make gradle wrapper executable run: chmod +x ./gradlew @@ -34,4 +34,4 @@ jobs: version: ${{ github.event.release.tag_name }} version-type: release loaders: fabric - game-versions: 1.21.11 + game-versions: 26.1 diff --git a/build.gradle b/build.gradle index d5e412e..d642e60 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'net.fabricmc.fabric-loom-remap' version "${loom_version}" + id 'net.fabricmc.fabric-loom' version "${loom_version}" id 'maven-publish' } @@ -38,13 +38,12 @@ loom { dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings loom.officialMojangMappings() - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + implementation "net.fabricmc:fabric-loader:${project.loader_version}" // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modCompileOnly "maven.modrinth:iris:${project.iris_version}" + compileOnly "maven.modrinth:iris:${project.iris_version}" } processResources { @@ -56,7 +55,7 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + it.options.release = 25 } java { @@ -65,8 +64,8 @@ java { // If you remove this line, sources will not be generated. withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } jar { diff --git a/gradle.properties b/gradle.properties index d2ddfd9..8bfd4d2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,9 +7,9 @@ org.gradle.configuration-cache=false # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.11 +minecraft_version=26.1 loader_version=0.18.4 -loom_version=1.14-SNAPSHOT +loom_version=1.15-SNAPSHOT # Mod Properties mod_version=0.0.7 @@ -17,5 +17,5 @@ maven_group=net.imaginefun archives_base_name=ImagineFunUtils # Dependencies -fabric_version=0.140.2+1.21.11 -iris_version=1.10.5+1.21.11-fabric +fabric_version=0.144.3+26.1 +iris_version=1.10.8+26.1-fabric diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 23449a2..dbc3ce4 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-9.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/client/java/net/imaginefun/ImagineFunUtilsClient.java b/src/client/java/net/imaginefun/ImagineFunUtilsClient.java index 0847851..6d28224 100644 --- a/src/client/java/net/imaginefun/ImagineFunUtilsClient.java +++ b/src/client/java/net/imaginefun/ImagineFunUtilsClient.java @@ -4,6 +4,7 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.loader.api.FabricLoader; +import net.imaginefun.gui.TitleScreenHandler; import net.imaginefun.networking.ClientCustomPacketListener; import net.imaginefun.networking.ClientCustomPacketListenerImpl; import net.imaginefun.networking.HandshakePayload; @@ -26,6 +27,8 @@ public void onInitializeClient() { ClientPlayNetworking.send(new HandshakePayload(version)); }); + TitleScreenHandler.register(); + } public ClientCustomPacketListener getClientCustomPacketListener() { diff --git a/src/client/java/net/imaginefun/gui/ImagineFunButton.java b/src/client/java/net/imaginefun/gui/ImagineFunButton.java index 72dab09..9c851e9 100644 --- a/src/client/java/net/imaginefun/gui/ImagineFunButton.java +++ b/src/client/java/net/imaginefun/gui/ImagineFunButton.java @@ -1,22 +1,17 @@ package net.imaginefun.gui; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ActiveTextCollector; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.components.WidgetSprites; -import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; -import net.minecraft.resources.Identifier; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; +import net.minecraft.network.chat.TextColor; public class ImagineFunButton extends Button { - private static final WidgetSprites SPRITES = new WidgetSprites( - Identifier.withDefaultNamespace("widget/button"), - Identifier.withDefaultNamespace("widget/button_disabled"), - Identifier.withDefaultNamespace("widget/button_highlighted") - ); - private static final int COLOR_FROM = 0xFFee609c; private static final int COLOR_TO = 0xFF4f88de; @@ -25,36 +20,29 @@ public ImagineFunButton(int x, int y, int width, int height, Component message, } @Override - protected void renderContents(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) { - if (this.alpha <= 0.0f) { - return; - } - Identifier sprite = SPRITES.get(this.active, this.isHovered()); - graphics.blitSprite(RenderPipelines.GUI_TEXTURED, sprite, this.getX(), this.getY(), this.width, this.height); + protected void extractContents(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + this.extractDefaultSprite(graphics); - Minecraft minecraft = Minecraft.getInstance(); - Font font = minecraft.font; + Font font = Minecraft.getInstance().font; String text = this.getMessage().getString(); - int textWidth = font.width(text); - int textHeight = font.lineHeight; - float startX = this.getX() + (this.width - textWidth) / 2.0f; - float startY = this.getY() + (this.height - textHeight) / 2.0f; - - float currentX = startX; + MutableComponent gradientText = Component.empty(); + float currentWidth = 0; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); String charStr = String.valueOf(c); int charWidth = font.width(charStr); - float gradientPos = (currentX - startX + charWidth / 2.0f) / textWidth; + float gradientPos = textWidth > 0 ? (currentWidth + charWidth / 2.0f) / textWidth : 0; int color = interpolateColor(COLOR_FROM, COLOR_TO, gradientPos); - graphics.drawString(font, charStr, (int) currentX, (int) startY, color, true); - - currentX += charWidth; + gradientText.append(Component.literal(charStr).withStyle(Style.EMPTY.withColor(TextColor.fromRgb(color & 0xFFFFFF)))); + currentWidth += charWidth; } + + ActiveTextCollector textCollector = graphics.textRendererForWidget(this, GuiGraphicsExtractor.HoveredTextEffects.NONE); + this.extractScrollingStringOverContents(textCollector, gradientText, 2); } private int interpolateColor(int from, int to, float t) { diff --git a/src/client/java/net/imaginefun/gui/TitleScreenHandler.java b/src/client/java/net/imaginefun/gui/TitleScreenHandler.java new file mode 100644 index 0000000..a0aa669 --- /dev/null +++ b/src/client/java/net/imaginefun/gui/TitleScreenHandler.java @@ -0,0 +1,65 @@ +package net.imaginefun.gui; + +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.client.screen.v1.Screens; +import net.imaginefun.ImaginefunUtilsConstants; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.screens.ConnectScreen; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.client.multiplayer.resolver.ServerAddress; +import net.minecraft.network.chat.Component; + +public class TitleScreenHandler { + + public static void register() { + ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + if (!(screen instanceof TitleScreen)) return; + + // Screens.getWidgets() is the Fabric API-provided modifiable widget list. + // Adding to it is the correct way to register widgets from outside a Screen + // subclass (addRenderableWidget is protected). This is the same approach + // used by ModMenu. + var widgets = Screens.getWidgets(screen); + + // Find the Singleplayer button dynamically so we anchor to its actual + // position after all other mods (e.g. ModMenu) have already shifted things + // in their own AFTER_INIT or @Inject TAIL handlers. + int singleplayerIndex = -1; + AbstractWidget singleplayerButton = null; + String singleplayerText = Component.translatable("menu.singleplayer").getString(); + for (int i = 0; i < widgets.size(); i++) { + AbstractWidget widget = widgets.get(i); + if (singleplayerText.equals(widget.getMessage().getString())) { + singleplayerIndex = i; + singleplayerButton = widget; + break; + } + } + if (singleplayerButton == null) return; + + int y = singleplayerButton.getY() + 24; + int x = screen.width / 2 - 100; + + for (AbstractWidget widget : widgets) { + if (widget != singleplayerButton && widget.getY() >= y) { + widget.setY(widget.getY() + 24); + } + } + + widgets.add(singleplayerIndex + 1, new ImagineFunButton( + x, y, 200, 20, + Component.literal("Join " + ImaginefunUtilsConstants.serverName), + button -> { + ServerData serverData = new ServerData( + ImaginefunUtilsConstants.serverName, + ImaginefunUtilsConstants.serverAddress, + ServerData.Type.OTHER + ); + serverData.setResourcePackStatus(ServerData.ServerPackStatus.ENABLED); + ConnectScreen.startConnecting(screen, client, ServerAddress.parseString(ImaginefunUtilsConstants.serverAddress), serverData, false, null); + } + )); + }); + } +} diff --git a/src/client/java/net/imaginefun/mixins/client/ScreenAccessor.java b/src/client/java/net/imaginefun/mixins/client/ScreenAccessor.java deleted file mode 100644 index 4b18994..0000000 --- a/src/client/java/net/imaginefun/mixins/client/ScreenAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.imaginefun.mixins.client; - -import java.util.List; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.client.gui.components.Renderable; -import net.minecraft.client.gui.screens.Screen; - -@Mixin(Screen.class) -public interface ScreenAccessor { - @Accessor("renderables") - List imaginefunutils$getRenderables(); -} diff --git a/src/client/java/net/imaginefun/mixins/client/SkullBlockRendererMixin.java b/src/client/java/net/imaginefun/mixins/client/SkullBlockRendererMixin.java index f6f73a2..b894b04 100644 --- a/src/client/java/net/imaginefun/mixins/client/SkullBlockRendererMixin.java +++ b/src/client/java/net/imaginefun/mixins/client/SkullBlockRendererMixin.java @@ -3,6 +3,8 @@ import java.util.Map; +import org.joml.Quaternionfc; +import org.joml.Vector3fc; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -12,16 +14,18 @@ import net.imaginefun.playerheads.PlayerHeadRenderer; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Transformation; import net.minecraft.client.model.object.skull.SkullModelBase; import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.blockentity.SkullBlockRenderer; +import net.minecraft.client.renderer.blockentity.state.SkullBlockRenderState; import net.minecraft.client.renderer.feature.ModelFeatureRenderer; import net.minecraft.client.renderer.rendertype.RenderSetup; import net.minecraft.client.renderer.rendertype.RenderType; -import net.minecraft.resources.Identifier; - +import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.core.Direction; +import net.minecraft.resources.Identifier; @Mixin(SkullBlockRenderer.class) public abstract class SkullBlockRendererMixin { @@ -35,50 +39,170 @@ private static Identifier getTextureLocation(RenderSetup renderSetup, String tex return ((TextureBindingAccessor) textureBinding).invokeLocation(); } - + + @Unique + private static Identifier getTextureFromRenderType(RenderType renderType) { + if (renderType == null) { + return null; + } + RenderTypeAccessor renderTypeAccessor = (RenderTypeAccessor) renderType; + RenderSetup renderSetup = renderTypeAccessor.getState(); + if (renderSetup == null) { + return null; + } + return getTextureLocation(renderSetup, "Sampler0"); + } + + /** + * Caller 1: SkullBlockRenderer.submit (skull blocks placed in the world). + * + * In 1.21.11, submit passed state.direction and state.rotationDegrees to submitSkull, + * which applied translate + scale(-1,-1,1) internally. In 26.1, those fields were replaced + * by state.transformation, and submitSkull no longer applies any transforms. + * + * We inject at HEAD (before mulPose(transformation)), extract direction and yaw from + * the transformation, and call PlayerHeadRenderer with the same interface as 1.21.11. + * Cancelling submit prevents submitSkull from being called, so the submitSkull mixin + * below won't double-fire. + */ @Inject( - method = "submitSkull(Lnet/minecraft/core/Direction;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/model/object/skull/SkullModelBase;Lnet/minecraft/client/renderer/rendertype/RenderType;ILnet/minecraft/client/renderer/feature/ModelFeatureRenderer$CrumblingOverlay;)V", + method = "submit(Lnet/minecraft/client/renderer/blockentity/state/SkullBlockRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/level/CameraRenderState;)V", at = @At("HEAD"), cancellable = true ) - private static void onStaticRender( - Direction facing, - float yaw, - float poweredTicks, - PoseStack matrices, - SubmitNodeCollector queue, - int light, - SkullModelBase model, - RenderType renderLayer, - int outlineColor, - ModelFeatureRenderer.CrumblingOverlay crumblingOverlay, + private void onSubmit( + SkullBlockRenderState state, + PoseStack poseStack, + SubmitNodeCollector submitNodeCollector, + CameraRenderState camera, CallbackInfo ci ) { - if (renderLayer == null) { + Identifier texture = getTextureFromRenderType(state.renderType); + if (texture == null) { return; } - RenderTypeAccessor playerSkinCacheEntryAccessor = (RenderTypeAccessor) renderLayer; - RenderSetup renderSetup = playerSkinCacheEntryAccessor.getState(); - if (renderSetup == null) { - return; + // In 26.1, state.direction/rotationDegrees were replaced by state.transformation. + // Use Transformation's built-in decomposition to recover direction and yaw. + // The transformation is constructed as T * R_Y(-yaw) * S(-1,-1,1). + Transformation t = state.transformation; + Vector3fc translation = t.translation(); + Direction direction; + + if (Math.abs(translation.y() - 0.25F) < 0.01F) { + // Wall skull — direction from translation offsets + direction = imaginefunutils$directionFromTranslation(translation.x(), translation.z()); + } else { + // Ground skull + direction = null; } - Identifier texture = getTextureLocation(renderSetup, "Sampler0"); + // leftRotation is Axis.YP.rotationDegrees(-yaw), i.e. quaternion (0, sin(-yaw/2), 0, cos(-yaw/2)). + // Extract yaw: for a pure Y-rotation quaternion, angle = 2*atan2(q.y, q.w), negate to undo the sign. + Quaternionfc q = t.leftRotation(); + float yaw = -(float) Math.toDegrees(2.0 * Math.atan2(q.y(), q.w())); + + boolean success = PlayerHeadRenderer.render( + texture, + poseStack, + direction, + state.lightCoords, + yaw + ); + + if (success) { + ci.cancel(); + } + } + + /** + * Callers 2/3/4: CustomHeadLayer, PlayerHeadSpecialRenderer, SkullSpecialRenderer. + * + * In 1.21.11, these all passed direction=null and yaw=180.0F to submitSkull. + * In 26.1, submitSkull lost those parameters but the callers' intent is unchanged. + * + * This injection only fires for callers 2/3/4 because when caller 1's submit mixin + * succeeds, it cancels submit entirely (submitSkull is never called). + */ + @Inject( + method = "submitSkull(FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/model/object/skull/SkullModelBase;Lnet/minecraft/client/renderer/rendertype/RenderType;ILnet/minecraft/client/renderer/feature/ModelFeatureRenderer$CrumblingOverlay;)V", + at = @At("HEAD"), + cancellable = true + ) + private static void onStaticRender( + float animationValue, + PoseStack poseStack, + SubmitNodeCollector submitNodeCollector, + int lightCoords, + SkullModelBase model, + RenderType renderType, + int outlineColor, + ModelFeatureRenderer.CrumblingOverlay breakProgress, + CallbackInfo ci + ) { + Identifier texture = getTextureFromRenderType(renderType); if (texture == null) { return; } + // In 26.1, CustomHeadLayer changed two things vs 1.21.11: + // 1. scale(1.1875, -1.1875, -1.1875) → scale(1.1875, 1.1875, 1.1875) + // 2. Removed the translate(-0.5, 0, -0.5) that followed the scale + // Additionally, 26.1's submitSkull no longer applies translate(0.5,0,0.5) + // + scale(-1,-1,1) internally (those were in 1.21.11's submitSkull). + // + // Our renderCustomSkull was designed for the 1.21.11 poseStack state, which + // had: scale(1.1875,-1.1875,-1.1875) * translate(-0.5,0,-0.5). + // We restore that here by flipping Y/Z and adding back the translate. + boolean fromCustomHeadLayer = imaginefunutils$isCalledFromCustomHeadLayer(); + if (fromCustomHeadLayer) { + poseStack.pushPose(); + poseStack.scale(1.0F, -1.0F, -1.0F); + poseStack.translate(-0.5F, 0.0F, -0.5F); + } + + // In 1.21.11, callers 2/3/4 always passed direction=null, yaw=180.0F boolean success = PlayerHeadRenderer.render( texture, - matrices, - facing, - light, - yaw + poseStack, + null, + lightCoords, + 180.0F ); + if (fromCustomHeadLayer) { + poseStack.popPose(); + } + if (success) { ci.cancel(); } } + + @Unique + private static boolean imaginefunutils$isCalledFromCustomHeadLayer() { + for (StackTraceElement e : Thread.currentThread().getStackTrace()) { + if (e.getClassName().endsWith("CustomHeadLayer")) { + return true; + } + } + return false; + } + + /** + * Determine the wall skull direction from the translation offsets. + * Wall translations: 0.5 - direction.getStepX() * 0.25, 0.25, 0.5 - direction.getStepZ() * 0.25 + */ + @Unique + private static Direction imaginefunutils$directionFromTranslation(float tx, float tz) { + // NORTH: stepX=0, stepZ=-1 -> tx=0.5, tz=0.75 + // SOUTH: stepX=0, stepZ=1 -> tx=0.5, tz=0.25 + // WEST: stepX=-1, stepZ=0 -> tx=0.75, tz=0.5 + // EAST: stepX=1, stepZ=0 -> tx=0.25, tz=0.5 + if (Math.abs(tz - 0.75F) < 0.01F) return Direction.NORTH; + if (Math.abs(tz - 0.25F) < 0.01F) return Direction.SOUTH; + if (Math.abs(tx - 0.75F) < 0.01F) return Direction.WEST; + if (Math.abs(tx - 0.25F) < 0.01F) return Direction.EAST; + return Direction.NORTH; // fallback + } } diff --git a/src/client/java/net/imaginefun/mixins/client/TitleScreenMixin.java b/src/client/java/net/imaginefun/mixins/client/TitleScreenMixin.java deleted file mode 100644 index 65047f3..0000000 --- a/src/client/java/net/imaginefun/mixins/client/TitleScreenMixin.java +++ /dev/null @@ -1,60 +0,0 @@ -package net.imaginefun.mixins.client; - -import net.imaginefun.ImaginefunUtilsConstants; -import net.imaginefun.gui.ImagineFunButton; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.components.AbstractWidget; -import net.minecraft.client.gui.components.Renderable; -import net.minecraft.client.gui.screens.ConnectScreen; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.TitleScreen; -import net.minecraft.client.multiplayer.ServerData; -import net.minecraft.client.multiplayer.resolver.ServerAddress; -import net.minecraft.network.chat.Component; -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(TitleScreen.class) -public abstract class TitleScreenMixin extends Screen { - - protected TitleScreenMixin(Component title) { - super(title); - } - - @Inject(method = "init", at = @At("TAIL")) - private void addImagineFunButton(CallbackInfo ci) { - Minecraft minecraft = Minecraft.getInstance(); - - int buttonWidth = 200; - int buttonHeight = 20; - int x = this.width / 2 - 100; - int y = this.height / 4 + 48 + 24; - - for (Renderable renderable : ((ScreenAccessor) this).imaginefunutils$getRenderables()) { - if (renderable instanceof AbstractWidget widget) { - if (widget.getY() >= y) { - widget.setY(widget.getY() + 24); - } - } - } - - ImagineFunButton joinButton = new ImagineFunButton( - x, y, buttonWidth, buttonHeight, - Component.literal("Join " + ImaginefunUtilsConstants.serverName), - button -> { - ServerData serverData = new ServerData( - ImaginefunUtilsConstants.serverName, - ImaginefunUtilsConstants.serverAddress, - ServerData.Type.OTHER - ); - serverData.setResourcePackStatus(ServerData.ServerPackStatus.ENABLED); - ServerAddress serverAddress = ServerAddress.parseString(ImaginefunUtilsConstants.serverAddress); - ConnectScreen.startConnecting((TitleScreen) (Object) this, minecraft, serverAddress, serverData, false, null); - } - ); - - this.addRenderableWidget(joinButton); - } -} diff --git a/src/client/java/net/imaginefun/playerheads/PlayerHeadRenderer.java b/src/client/java/net/imaginefun/playerheads/PlayerHeadRenderer.java index 2d5468c..bdfda71 100644 --- a/src/client/java/net/imaginefun/playerheads/PlayerHeadRenderer.java +++ b/src/client/java/net/imaginefun/playerheads/PlayerHeadRenderer.java @@ -33,7 +33,7 @@ public class PlayerHeadRenderer { private static final String NEW_NAMESPACE = "processed_images"; private static final Map processedTextures = new HashMap<>(); - + public static boolean render( Identifier skinTexture, PoseStack matrixStack, @@ -57,7 +57,7 @@ public static boolean render( } else { image = getTextureImageViaReflection(texture); } - + if(image == null) return false; int pixel = image.getPixel(MARKER_X, MARKER_Y); @@ -126,14 +126,6 @@ public static Identifier getNewImage(Identifier original, NativeImage input) { return newId; } - /** - * Renders a custom skull with the given texture and scale. - * - * @param skullBlockEntityRenderState The render state for the skull block entity - * @param matrixStack The matrix stack for transformations - * @param skinTexture The texture identifier for the skin - * @param scale The scale factor for the skull (based on alpha channel of marker pixel) - */ public static void renderCustomSkull( Direction direction, int light, @@ -158,7 +150,7 @@ public static void renderCustomSkull( matrixStack.translate(0.0F, -0.211F, -0.211F); int overlay = OverlayTexture.NO_OVERLAY; - + float scaleX = 0; float scaleY = 0; @@ -184,7 +176,7 @@ public static void renderCustomSkull( float z = 0.0f; MultiBufferSource.BufferSource bufferSource = Minecraft.getInstance().renderBuffers().bufferSource(); - VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderTypes.entityCutoutNoCull(actualIdentifier)); + VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderTypes.entityCutout(actualIdentifier)); Matrix4f matrix4f = matrixStack.last().pose(); Pose pose = matrixStack.last(); @@ -195,21 +187,21 @@ public static void renderCustomSkull( .setOverlay(overlay) .setLight(light) .setNormal(pose, 0, 0, -1); - + vertexConsumer.addVertex(matrix4f, scaleX, -scaleY, z) .setColor(255, 255, 255, 255) .setUv(maxU, 0) .setOverlay(overlay) .setLight(light) .setNormal(pose, 0, 0, -1); - + vertexConsumer.addVertex(matrix4f, scaleX, scaleY, z) .setColor(255, 255, 255, 255) .setUv(maxU, 1) .setOverlay(overlay) .setLight(light) .setNormal(pose, 0, 0, -1); - + vertexConsumer.addVertex(matrix4f, -scaleX, scaleY, z) .setColor(255, 255, 255, 255) .setUv(minU, 1) diff --git a/src/client/resources/imaginefunutils.client.mixins.json b/src/client/resources/imaginefunutils.client.mixins.json index 6e66e5e..73ab88c 100644 --- a/src/client/resources/imaginefunutils.client.mixins.json +++ b/src/client/resources/imaginefunutils.client.mixins.json @@ -6,10 +6,8 @@ "GameTestBlockHighlightRendererMixin", "RenderSetupAccessor", "RenderTypeAccessor", - "ScreenAccessor", "SkullBlockRendererMixin", - "TextureBindingAccessor", - "TitleScreenMixin" + "TextureBindingAccessor" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/java/net/imaginefun/ImagineFunUtils.java b/src/main/java/net/imaginefun/ImagineFunUtils.java index ea8c443..ece382a 100644 --- a/src/main/java/net/imaginefun/ImagineFunUtils.java +++ b/src/main/java/net/imaginefun/ImagineFunUtils.java @@ -20,9 +20,9 @@ public class ImagineFunUtils implements ModInitializer { @Override public void onInitialize() { - PayloadTypeRegistry.playS2C().register(GameTestAddMarkerPayload.TYPE, GameTestAddMarkerPayload.STREAM_CODEC); - PayloadTypeRegistry.playS2C().register(PlayerForceLookPayload.TYPE, PlayerForceLookPayload.STREAM_CODEC); - PayloadTypeRegistry.playC2S().register(HandshakePayload.TYPE, HandshakePayload.STREAM_CODEC); + PayloadTypeRegistry.clientboundPlay().register(GameTestAddMarkerPayload.TYPE, GameTestAddMarkerPayload.STREAM_CODEC); + PayloadTypeRegistry.clientboundPlay().register(PlayerForceLookPayload.TYPE, PlayerForceLookPayload.STREAM_CODEC); + PayloadTypeRegistry.serverboundPlay().register(HandshakePayload.TYPE, HandshakePayload.STREAM_CODEC); FabricLoader.getInstance().getModContainer(MOD_ID).ifPresent(mod -> ResourceLoader.registerBuiltinPack( diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index f5fcf46..4132b87 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -31,8 +31,8 @@ ], "depends": { "fabricloader": ">=0.18.3", - "minecraft": "~1.21.11", - "java": ">=21", + "minecraft": "~26.1", + "java": ">=25", "fabric-api": "*" } } diff --git a/src/main/resources/imaginefunutils.accesswidener b/src/main/resources/imaginefunutils.accesswidener index 4ddf8ab..0b481ad 100644 --- a/src/main/resources/imaginefunutils.accesswidener +++ b/src/main/resources/imaginefunutils.accesswidener @@ -1,4 +1,4 @@ -accessWidener v2 named +accessWidener v2 official accessible class net/minecraft/client/renderer/debug/GameTestBlockHighlightRenderer$Marker accessible class net/minecraft/client/renderer/rendertype/RenderSetup$TextureBinding diff --git a/src/main/resources/resourcepacks/imaginefunutils/pack.mcmeta b/src/main/resources/resourcepacks/imaginefunutils/pack.mcmeta index 3e2d0d2..df59131 100644 --- a/src/main/resources/resourcepacks/imaginefunutils/pack.mcmeta +++ b/src/main/resources/resourcepacks/imaginefunutils/pack.mcmeta @@ -1,6 +1,6 @@ { "pack": { - "pack_format": 88, + "pack_format": 84, "min_format": 46, "max_format": 1995, "supported_formats": {