From 12a8b185eed7ef55bb23b65879a70b6e8104691e Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Thu, 17 Sep 2026 15:34:17 +0100 Subject: [PATCH] Update Iris compat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Giving up on waiting for the NeoForge version, so we reshuffle this to avoid calling getUnderlyingVertexFormat — the RenderType's vertex format reports this fine. I did consider dropping all this code and just falling back to the slow fixed width font renderer when the vertex format doesn't match our direct one — the overhead is much lower than what it used to be — but does still touching some internals of BufferBuilder, so probably best avoided right now. --- .../cc-tweaked.base-convention.gradle.kts | 1 + gradle/libs.versions.toml | 27 +++++++++---------- .../client/integration/IrisShaderMod.java | 21 ++++++++------- .../client/integration/ShaderMod.java | 8 +++--- .../monitor/MonitorBlockEntityRenderer.java | 12 +++++---- .../render/monitor/MonitorRenderState.java | 10 +++---- .../text/DirectFixedWidthFontRenderer.java | 24 ++++++++--------- .../client/ForgeClientHooks.java | 7 ++--- 8 files changed, 52 insertions(+), 58 deletions(-) diff --git a/build-logic/base/src/main/kotlin/cc-tweaked.base-convention.gradle.kts b/build-logic/base/src/main/kotlin/cc-tweaked.base-convention.gradle.kts index 93218db29..342c6a4af 100644 --- a/build-logic/base/src/main/kotlin/cc-tweaked.base-convention.gradle.kts +++ b/build-logic/base/src/main/kotlin/cc-tweaked.base-convention.gradle.kts @@ -50,6 +50,7 @@ repositories { includeGroup("me.shedaniel.cloth") includeGroup("me.shedaniel") includeGroup("mezz.jei") + includeGroup("net.caffeinemc") includeModule("com.terraformersmc", "modmenu") } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 84783f432..653f79de9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ minecraft = "26.3" fabric-api = "0.160.5+26.3" fabric-loader = "0.19.4" -neoForge = "26.3.0.0-beta" +neoForge = "26.3.0.3-beta" neoMergeTool = "2.0.0" mixin = "0.8.5" @@ -34,12 +34,11 @@ nightConfig = "3.9.0" # Minecraft mods iris-fabric = "1.11.6+26.3-fabric" iris-forge = "1.9.1+1.21.7-neoforge" -jei = "29.5.0.26" -modmenu = "16.0.0-rc.1" +jei = "31.0.0.5" +modmenu = "21.0.0-beta.1" rei = "26.1.818" -sodium-fabric = "mc1.21.11-0.8.0-fabric" -sodium-forge = "mc1.21.11-0.8.0-neoforge" -mixinExtra = "0.3.5" +sodium = "0.9.2+mc26.3" +mixinExtra = "0.5.4" create-forge = "6.0.0-6" create-fabric = "6.0.7.0+mc1.20.1-build.1716" @@ -101,17 +100,17 @@ fabric-junit = { module = "net.fabricmc:fabric-loader-junit", version.ref = "fab fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" } iris-fabric = { module = "maven.modrinth:iris", version.ref = "iris-fabric" } iris-forge = { module = "maven.modrinth:iris", version.ref = "iris-forge" } -jei-api = { module = "mezz.jei:jei-26.1.2-common-api", version.ref = "jei" } -jei-fabric = { module = "mezz.jei:jei-26.1.2-fabric", version.ref = "jei" } -jei-forge = { module = "mezz.jei:jei-26.1.2-neoforge", version.ref = "jei" } +jei-api = { module = "mezz.jei:jei-26.3-common-api", version.ref = "jei" } +jei-fabric = { module = "mezz.jei:jei-26.3-fabric", version.ref = "jei" } +jei-forge = { module = "mezz.jei:jei-26.3-neoforge", version.ref = "jei" } mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" } mixinExtra = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinExtra" } modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" } rei-api = { module = "me.shedaniel:RoughlyEnoughItems-api", version.ref = "rei" } rei-builtin = { module = "me.shedaniel:RoughlyEnoughItems-default-plugin", version.ref = "rei" } rei-fabric = { module = "me.shedaniel:RoughlyEnoughItems-fabric", version.ref = "rei" } -sodium-fabric = { module = "maven.modrinth:sodium", version.ref = "sodium.fabric" } -sodium-forge = { module = "maven.modrinth:sodium", version.ref = "sodium.forge" } +sodium-fabric = { module = "net.caffeinemc:sodium-fabric", version.ref = "sodium" } +sodium-forge = { module = "net.caffeinemc:sodium-neoforge", version.ref = "sodium" } # Testing hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" } @@ -168,11 +167,11 @@ annotations = ["checkerFramework", "jetbrainsAnnotations", "jspecify"] kotlin = ["kotlin-stdlib", "kotlin-coroutines"] # Minecraft -externalMods-common = ["iris-forge", "jei-api", "nightConfig-core", "nightConfig-toml"] +externalMods-common = ["iris-fabric", "jei-api", "nightConfig-core", "nightConfig-toml"] externalMods-forge-compile = ["iris-forge", "jei-api"] -externalMods-forge-runtime = [] +externalMods-forge-runtime = ["jei-forge"] externalMods-fabric-compile = ["iris-fabric", "jei-api", "rei-api", "rei-builtin"] -externalMods-fabric-runtime = [] +externalMods-fabric-runtime = ["modmenu", "jei-fabric"] # Testing test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"] diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java b/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java index 6aa5e6e53..257b87e0b 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java @@ -30,21 +30,22 @@ public class IrisShaderMod implements ShaderMod.Provider { } @Override - public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int quadCount, IntFunction makeBuffer) { - return new IrisQuadEmitter(quadCount, makeBuffer); + public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(VertexFormat format, int quadCount, IntFunction makeBuffer) { + // If we're using the vanilla vertex format, fall back to our default emitter. + if (format == DirectFixedWidthFontRenderer.VERTEX_FORMAT) { + return super.getQuadEmitter(format, quadCount, makeBuffer); + } + + var sink = IrisApi.getInstance().createTextVertexSink(quadCount, makeBuffer); + // TODO(26.3): Verify the vertex format matches what we expect once Iris has updated. + return new IrisQuadEmitter(sink); } private static final class IrisQuadEmitter extends DirectFixedWidthFontRenderer.QuadEmitter { private final IrisTextVertexSink sink; - private IrisQuadEmitter(int vertexCount, IntFunction builder) { - sink = IrisApi.getInstance().createTextVertexSink(vertexCount, builder); - } - - @Override - public VertexFormat format() { - // TODO(26.3): return sink.getUnderlyingVertexFormat(); - throw new UnsupportedOperationException(); + private IrisQuadEmitter(IrisTextVertexSink sink) { + this.sink = sink; } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java b/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java index b49f02464..bb8a8ea3d 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java @@ -4,6 +4,7 @@ package dan200.computercraft.client.integration; +import com.mojang.renderpearl.api.vertex.VertexFormat; import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; import java.nio.ByteBuffer; @@ -11,8 +12,6 @@ import java.util.Optional; import java.util.ServiceLoader; import java.util.function.IntFunction; -import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.TERMINAL_TEXT; - /** * Find the currently loaded shader mod (if present) and provides utilities for interacting with it. */ @@ -33,12 +32,13 @@ public class ShaderMod { /** * Get an appropriate quad emitter for use with a vertex buffer and {@link DirectFixedWidthFontRenderer} . * + * @param format The vertex format to write. * @param quadCount The number of quads. * @param makeBuffer A function to allocate a temporary buffer. * @return The quad emitter. */ - public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int quadCount, IntFunction makeBuffer) { - return new DirectFixedWidthFontRenderer.ByteBufferEmitter(makeBuffer.apply(TERMINAL_TEXT.format().getVertexSize() * quadCount * 4)); + public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(VertexFormat format, int quadCount, IntFunction makeBuffer) { + return new DirectFixedWidthFontRenderer.ByteBufferEmitter(format, makeBuffer.apply(format.getVertexSize() * quadCount * 4)); } public interface Provider { diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java index 576a683f6..9b21c0b6e 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java @@ -101,7 +101,7 @@ public class MonitorBlockEntityRenderer implements BoundedBlockEntityRenderer allMonitors = new HashSet<>(); - long lastRenderFrame = -1; - @Nullable - BlockPos lastRenderPos = null; - - @Nullable - GpuBuffer vertexBuffer; + @Nullable VertexFormat vertexFormat; + @Nullable GpuBuffer vertexBuffer; int vertexCountAfterBackground; int vertexCountAfterForeground; diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/text/DirectFixedWidthFontRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/text/DirectFixedWidthFontRenderer.java index f17d37b6f..718d90ff2 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/text/DirectFixedWidthFontRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/text/DirectFixedWidthFontRenderer.java @@ -27,7 +27,7 @@ import static org.lwjgl.system.MemoryUtil.*; * There are some limitations here: *
    *
  • No transformation matrix (not needed for VBOs).
  • - *
  • Only works with {@link DefaultVertexFormat#POSITION_COLOR_TEX_LIGHTMAP}.
  • + *
  • Only works with {@link DefaultVertexFormat#POSITION_TEX_LIGHTMAP_COLOR}.
  • *
  • The buffer MUST be allocated with {@link MemoryUtil}, and not through any other means.
  • *
*

@@ -38,6 +38,11 @@ import static org.lwjgl.system.MemoryUtil.*; * {@link FixedWidthFontRenderer}. */ public final class DirectFixedWidthFontRenderer { + /** + * The vertex format {@link DirectFixedWidthFontRenderer} works with. + */ + public static final VertexFormat VERTEX_FORMAT = DefaultVertexFormat.POSITION_TEX_LIGHTMAP_COLOR; + private static final boolean IS_LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; private DirectFixedWidthFontRenderer() { @@ -173,8 +178,6 @@ public final class DirectFixedWidthFontRenderer { public abstract ByteBuffer byteBuffer(); - public abstract VertexFormat format(); - /** * Emit a quad to this buffer. * @@ -199,7 +202,8 @@ public final class DirectFixedWidthFontRenderer { public static final class ByteBufferEmitter extends QuadEmitter { private final ByteBuffer buffer; - public ByteBufferEmitter(ByteBuffer buffer) { + public ByteBufferEmitter(VertexFormat format, ByteBuffer buffer) { + if (format != VERTEX_FORMAT) throw new IllegalArgumentException("Unexpected vertex format"); this.buffer = buffer; } @@ -208,11 +212,6 @@ public final class DirectFixedWidthFontRenderer { return buffer; } - @Override - public VertexFormat format() { - return TERMINAL_TEXT.format(); - } - @Override public void quad(float x1, float y1, float x2, float y2, float z, int nativeColour, float u1, float v1, float u2, float v2) { DirectFixedWidthFontRenderer.quad(buffer, x1, y1, x2, y2, z, nativeColour, u1, v1, u2, v2); @@ -224,16 +223,15 @@ public final class DirectFixedWidthFontRenderer { // underlying buffer. This allows us to have a single bounds check up-front, rather than one for every write. // This provides significant performance gains, at the cost of well, using Unsafe. // Each vertex is 28 bytes, giving 112 bytes in total. Vertices are of the form (xyz:FFF)(uv1:FF)(uv2:SS)(abgr:BBBB), - // which matches the POSITION_COLOR_TEX_LIGHTMAP vertex format. + // which matches the POSITION_TEX_LIGHTMAP_COLOR vertex format. var position = buffer.position(); var addr = MemoryUtil.memAddress(buffer); // We're doing terrible unsafe hacks below, so let's be really sure that what we're doing is reasonable. + if (position < 0 || 112 > buffer.limit() - position) throw new IndexOutOfBoundsException(); // Require the pointer to be aligned to a 32-bit boundary. if ((addr & 3) != 0) throw new IllegalStateException("Memory is not aligned"); - if (TERMINAL_TEXT.format().getVertexSize() != 28) { - throw new IllegalStateException("Incorrect vertex size"); - } + if (VERTEX_FORMAT.getVertexSize() != 28) throw new IllegalStateException("Incorrect vertex size"); memPutFloat(addr + 0, x1); memPutFloat(addr + 4, y1); diff --git a/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientHooks.java b/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientHooks.java index 099215296..83027d243 100644 --- a/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientHooks.java +++ b/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientHooks.java @@ -58,12 +58,9 @@ public final class ForgeClientHooks { @SubscribeEvent public static void onRenderInHand(RenderHandEvent event) { - // TODO(26.3): Add these to the event in upstream NeoForge. - var minecraft = Minecraft.getInstance(); - var heldRenderer = minecraft.gameRenderer.firstPersonHandsAndItemsRenderer; - var playerState = minecraft.gameRenderer.gameRenderState().levelRenderState.playerRenderState; + var heldRenderer = Minecraft.getInstance().gameRenderer.firstPersonHandsAndItemsRenderer; if (ClientHooks.onRenderHeldItem( - heldRenderer, playerState, event.getPoseStack(), event.getSubmitNodeCollector(), event.getPackedLight(), + heldRenderer, event.getPlayerState(), event.getPoseStack(), event.getSubmitNodeCollector(), event.getPackedLight(), event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() )) { event.setCanceled(true);