diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f02c478..fcd2c4c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,10 +26,15 @@ jobs: - version: 1.21.1-neoforge - version: 1.21.11-neoforge smoke: true + # Minecraft 26 gets the server smoke test too: the dev server was + # broken on both 26 targets for months precisely because nothing + # booted one in CI. - version: 26.2-neoforge java: '25' + smoke: true - version: 26.1.2-neoforge java: '25' + smoke: true steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cc4a18c..c82f3f5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -155,6 +155,7 @@ jobs: version: ${{ steps.meta.outputs.version }}+mc1.21.1-neoforge version-type: release loaders: neoforge + dependencies: rinku(required) game-versions: '1.21.1' changelog: ${{ steps.notes.outputs.body }} files: versions/1.21.1-neoforge/build/libs/!(*-@(dev|sources|javadoc)).jar @@ -170,6 +171,7 @@ jobs: version: ${{ steps.meta.outputs.version }}+mc1.21.11-neoforge version-type: release loaders: neoforge + dependencies: rinku(required) game-versions: '1.21.11' changelog: ${{ steps.notes.outputs.body }} files: versions/1.21.11-neoforge/build/libs/!(*-@(dev|sources|javadoc)).jar @@ -185,6 +187,7 @@ jobs: version: ${{ steps.meta.outputs.version }}+mc26.2-neoforge version-type: release loaders: neoforge + dependencies: rinku(required) game-versions: '26.2' changelog: ${{ steps.notes.outputs.body }} files: versions/26.2-neoforge/build/libs/!(*-@(dev|sources|javadoc)).jar @@ -200,6 +203,7 @@ jobs: version: ${{ steps.meta.outputs.version }}+mc26.1.2-neoforge version-type: release loaders: neoforge + dependencies: rinku(required) game-versions: '26.1.2' changelog: ${{ steps.notes.outputs.body }} files: versions/26.1.2-neoforge/build/libs/!(*-@(dev|sources|javadoc)).jar diff --git a/CHANGELOG.md b/CHANGELOG.md index 2742202..19d2932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 1.7.0 - 2026-09-08 + +### Changed +- **The browser library is now [Rinku](https://modrinth.com/mod/rinku), not MCEF.** MCEF [Keksuccino's Fork] was renamed, and its mod id changed from `mcef` to `rinku`. + - **On Fabric there is nothing to do** — Rinku ships inside the WebGUI jar, as MCEF did before it. + - **On NeoForge, install [Rinku](https://modrinth.com/mod/rinku) alongside WebGUI** and remove MCEF. WebGUI now declares Rinku as a required dependency, so launchers install it for you; if you copy jars by hand you need to add it yourself. +- Chromium is now version 151. The browser is no longer capped at 60 FPS, and browser windows can be muted. +- **Minecraft 26.1 and 26.2 are out of beta.** Both ship as regular releases now instead of beta builds. +- Updated NeoForge (26.2.0.82, 26.1.2.107, 21.11.45, 21.1.250), Fabric Loader 0.19.5, Fabric API, and Yarn for 1.21.11. + +### Fixed +- **Fixed a client crash on Minecraft 26.2** that hit after opening a web GUI a handful of times: `Texture view Sampler0 (MCEF Browser Texture 1x1) has been closed!`. If you worked around it by setting `browser-preload-enabled=false`, you can turn browser preloading back on. +- **Fixed the browser refusing to start against current Chromium.** WebGUI passed `--use-gl=desktop`, a switch Chromium removed years ago. It went unnoticed while the browser library still shipped an older Chromium, and would have broken on any Chromium update. +- **Fixed the game crashing on startup on NeoForge when the browser library was missing.** WebGUI declared no dependency on it at all, so launchers installed nothing and the game died during mod loading with `NoClassDefFoundError: org/cef/handler/CefDisplayHandler` instead of telling you what was missing. Fabric was never affected, because the library ships inside the jar there. +- Fixed the Minecraft 26 development server failing to boot, which made the mod impossible to test locally on those versions. Released servers were never affected. + ## 1.6.2 - 2026-07-26 ### Fixed diff --git a/README.md b/README.md index 1558529..9414db1 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,9 @@ Chromium (~150 MB) is downloaded automatically on first launch. Include [Rinku]( ## Installation 1. Download the latest JAR from [Modrinth](https://modrinth.com/project/webgui) (pick the right MC version). -2. Place it in `.minecraft/mods/` (on Fabric, also add Fabric API; NeoForge needs no extra dependencies). +2. Place it in `.minecraft/mods/`. + - **Fabric:** also add Fabric API. The browser library ships inside the WebGUI jar. + - **NeoForge:** also add [Rinku](https://modrinth.com/mod/rinku) — it is not bundled, and WebGUI cannot render a page without it. 3. Start the game. --- diff --git a/build.gradle b/build.gradle index 8b04f63..6cba9bf 100644 --- a/build.gradle +++ b/build.gradle @@ -60,12 +60,27 @@ if (sc_loader == "fabric") { mappings "net.fabricmc:yarn:${yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${loader_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}" - // MCEF [Keksuccino's Fork] was renamed to Rinku; the old `mcef-keksuccino` - // slug no longer resolves on Modrinth's maven. The 2.2.x artifacts are - // still served under the new slug, so only the artifact id changes here. - include(modImplementation("maven.modrinth:rinku:${mcef_version}")) + include(modImplementation("maven.modrinth:rinku:${rinku_version}")) } } else { + configurations { + rinkuArtifact + } + + // Rinku is a client-side library, and NeoForge's dev dist cleaner strips + // the client classes it constructs against. A plain `runtimeOnly` feeds + // BOTH dev runs, so runServer used to die during mod loading with + // NoClassDefFoundError on Screen — on every Minecraft 26 build, and never + // caught because 26.x had no server smoke test. moddev's per-run classpath + // is gone on modern Minecraft ("no additional classpath anymore"), so scope + // it by installing the jar into the client run's mods folder instead. That + // also mirrors production, where a server operator simply never installs + // Rinku and WebGUI never declares it as a dependency. + def installRinkuForClientRun = tasks.register('installRinkuForClientRun', Copy) { + from configurations.rinkuArtifact + into layout.projectDirectory.dir('run/mods') + } + neoForge { version = project.neoforge_version // Register the mod so moddev's JUnit runtime can load it during tests. @@ -84,14 +99,60 @@ if (sc_loader == "fabric") { runs { client { client() + // Rinku reaches the client the way a player installs it: as a + // jar in the mods folder, not on the runtime classpath. Keeping + // it off the classpath is what keeps runServer alive — see the + // installRinkuForClientRun task below. + taskBefore(installRinkuForClientRun) } server { server() } } } + + + // Rinku ships its NeoForge builds inconsistently: 26.2 has classes at the + // top level, but 1.21.1 and 26.1.2 are jarJar wrappers whose real mod sits + // in META-INF/jarjar/. NeoForge unpacks that at runtime, so the game is + // happy either way — javac is not, and sees an empty jar. Compile against + // whatever actually holds the classes; the published artifact stays on the + // runtime classpath untouched. + dependencies { + rinkuArtifact "maven.modrinth:rinku:${rinku_version}" + } + + def rinkuClassesDir = layout.buildDirectory.dir('rinku-compile') + def unwrapRinku = tasks.register('unwrapRinku') { + def artifact = configurations.rinkuArtifact + inputs.files(artifact) + outputs.dir(rinkuClassesDir) + doLast { + def dir = rinkuClassesDir.get().asFile + dir.deleteDir() + dir.mkdirs() + def outer = artifact.singleFile + def target = new File(dir, 'rinku.jar') + new java.util.zip.ZipFile(outer).withCloseable { zip -> + def nested = zip.entries().toList().find { + it.name.startsWith('META-INF/jarjar/') && it.name.endsWith('.jar') + } + if (nested != null) { + target.withOutputStream { out -> out << zip.getInputStream(nested) } + logger.lifecycle("rinku: compiling against nested ${nested.name}") + } else { + target.bytes = outer.bytes + } + } + } + } + dependencies { - implementation "maven.modrinth:rinku:${mcef_version}" + // Point at the jar itself, not the directory holding it — a directory + // on the compile classpath is searched for loose .class files only. + compileOnly files(rinkuClassesDir.map { it.file('rinku.jar') }) { + builtBy unwrapRinku + } } } diff --git a/gradle.properties b/gradle.properties index 6b9ec92..5a52918 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx4G org.gradle.parallel=true dev.kikugie.stonecutter.hard_mode=true -mod_version=1.6.2 +mod_version=1.7.0 maven_group=land.webgui archives_base_name=webgui diff --git a/src/main/java/land/webgui/WebGUIClient.java b/src/main/java/land/webgui/WebGUIClient.java index 8b19203..6b41065 100644 --- a/src/main/java/land/webgui/WebGUIClient.java +++ b/src/main/java/land/webgui/WebGUIClient.java @@ -1,6 +1,6 @@ package land.webgui; -import com.cinemamod.mcef.MCEF; +import de.keksuccino.rinku.Rinku; //? if fabric { import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; @@ -24,12 +24,12 @@ public final class WebGUIClient //? if fabric { @Override public void onInitializeClient() { - MCEF.scheduleForInit(success -> { + Rinku.scheduleForInit(success -> { if (!success) { - WebGUIMod.LOGGER.error("MCEF (Chromium) failed to initialize — web GUI will not work."); + WebGUIMod.LOGGER.error("Rinku (Chromium) failed to initialize — web GUI will not work."); return; } - MCEF.getClient().addDisplayHandler(new WebviewBrowserConsoleLogger()); + Rinku.getClient().addDisplayHandler(new WebviewBrowserConsoleLogger()); WebviewPageToClientBridge.register(); WebviewPageLoadHooks.register(); WebGUIMod.LOGGER.info("WebGUI bridge ready (console log, page↔game, client data)."); @@ -108,7 +108,7 @@ private static void onLeaveWorld() { } private static void handleOpenPayload(net.minecraft.client.MinecraftClient client, int mode, String url) { - if (!MCEF.isInitialized()) { + if (!Rinku.isInitialized()) { if (client.player != null) { client.player.sendMessage(net.minecraft.text.Text.translatable("message.webgui.mcef_not_ready"), false); } @@ -123,12 +123,12 @@ private static void handleOpenPayload(net.minecraft.client.MinecraftClient clien } //? } else { /*public static void initClient(IEventBus modBus) { - MCEF.scheduleForInit(success -> { + Rinku.scheduleForInit(success -> { if (!success) { - WebGUIMod.LOGGER.error("MCEF (Chromium) failed to initialize - web GUI will not work."); + WebGUIMod.LOGGER.error("Rinku (Chromium) failed to initialize - web GUI will not work."); return; } - MCEF.getClient().addDisplayHandler(new WebviewBrowserConsoleLogger()); + Rinku.getClient().addDisplayHandler(new WebviewBrowserConsoleLogger()); WebviewPageToClientBridge.register(); WebviewPageLoadHooks.register(); WebGUIMod.LOGGER.info("WebGUI bridge ready (console log, page<->game, client data)."); @@ -182,7 +182,7 @@ private static void onClientTick(ClientTickEvent.Post event) { } private static void handleOpenPayload(Minecraft client, int mode, String url) { - if (!MCEF.isInitialized()) { + if (!Rinku.isInitialized()) { if (client.player != null) { //? if >=26 { client.player.sendSystemMessage( diff --git a/src/main/java/land/webgui/WebGUIKeys.java b/src/main/java/land/webgui/WebGUIKeys.java index 506ade2..3ca0fa8 100644 --- a/src/main/java/land/webgui/WebGUIKeys.java +++ b/src/main/java/land/webgui/WebGUIKeys.java @@ -1,6 +1,6 @@ package land.webgui; -import com.cinemamod.mcef.MCEF; +import de.keksuccino.rinku.Rinku; //? if fabric { import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.MinecraftClient; @@ -117,7 +117,7 @@ private static void tryOpenMainMenu(MinecraftClient client) { if (client.currentScreen instanceof WebViewScreen) { return; } - if (!MCEF.isInitialized()) { + if (!Rinku.isInitialized()) { if (client.player != null) { client.player.sendMessage(Text.translatable("message.webgui.mcef_not_ready"), false); } @@ -134,7 +134,7 @@ private static void tryOpenMainMenu(MinecraftClient client) { //? } return; } - if (!MCEF.isInitialized()) { + if (!Rinku.isInitialized()) { if (client.player != null) { //? if >=26 { client.player.sendSystemMessage(Component.translatable("message.webgui.mcef_not_ready")); diff --git a/src/main/java/land/webgui/WebHudOverlay.java b/src/main/java/land/webgui/WebHudOverlay.java index 0f7afab..227b4a0 100644 --- a/src/main/java/land/webgui/WebHudOverlay.java +++ b/src/main/java/land/webgui/WebHudOverlay.java @@ -1,7 +1,7 @@ package land.webgui; -import com.cinemamod.mcef.MCEF; -import com.cinemamod.mcef.MCEFBrowser; +import de.keksuccino.rinku.Rinku; +import de.keksuccino.rinku.RinkuBrowser; //? if fabric { import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.minecraft.client.MinecraftClient; @@ -60,7 +60,7 @@ public static boolean shouldDeliverHudBrowserInput(MinecraftClient client) { //? } else { /*public static boolean shouldDeliverHudBrowserInput(Minecraft client) {*/ //? } - if (client == null || !MCEF.isInitialized()) { + if (client == null || !Rinku.isInitialized()) { return false; } //? if fabric { @@ -86,7 +86,7 @@ public static boolean shouldForwardHudArrowKeys(MinecraftClient client) { //? } else { /*public static boolean shouldForwardHudArrowKeys(Minecraft client) {*/ //? } - if (client == null || !MCEF.isInitialized()) { + if (client == null || !Rinku.isInitialized()) { return false; } //? if fabric { @@ -229,7 +229,7 @@ public static void toggleHud(MinecraftClient client) { //? } return; } - if (!MCEF.isInitialized()) { + if (!Rinku.isInitialized()) { notifyMcefMissing(client); return; } @@ -262,7 +262,7 @@ public static void toggleInteractive(MinecraftClient client) { //? } else { /*public static void toggleInteractive(Minecraft client) {*/ //? } - if (!MCEF.isInitialized()) { + if (!Rinku.isInitialized()) { return; } //? if fabric { @@ -356,7 +356,7 @@ public static void onGuiClosed(MinecraftClient client) { } } - static void onHudBrowserLoadStart(MCEFBrowser browser) { + static void onHudBrowserLoadStart(RinkuBrowser browser) { if (browser == null) { return; } @@ -365,7 +365,7 @@ static void onHudBrowserLoadStart(MCEFBrowser browser) { } } - static void onHudBrowserLoadFinished(MCEFBrowser browser) { + static void onHudBrowserLoadFinished(RinkuBrowser browser) { if (browser == null) { return; } @@ -407,7 +407,7 @@ private static void onHudRender(RenderGuiEvent.Post event) { if (!hudVisible) { return; } - MCEFBrowser browser = WebSession.hudBrowser(); + RinkuBrowser browser = WebSession.hudBrowser(); if (browser == null) { return; } @@ -429,7 +429,7 @@ private static void onHudRender(RenderGuiEvent.Post event) { //? if >=1.21.5 { net.minecraft.util.Identifier tex = browser.getTextureIdentifier(); //? } else { - /*net.minecraft.util.Identifier tex = browser.getTextureLocation();*/ + /*net.minecraft.util.Identifier tex = browser.getTextureIdentifier();*/ //? } if (tex == null) { return; @@ -446,7 +446,7 @@ private static void onHudRender(RenderGuiEvent.Post event) { //? if >=1.21.5 { net.minecraft.resources.Identifier tex = browser.getTextureIdentifier(); //? } else { - net.minecraft.resources.ResourceLocation tex = browser.getTextureLocation(); + net.minecraft.resources.ResourceLocation tex = browser.getTextureIdentifier(); //? } if (tex == null) return; int sw = client.getWindow().getGuiScaledWidth(); @@ -502,7 +502,7 @@ static void resizeBrowser(MinecraftClient client) { //? } else { /*static void resizeBrowser(Minecraft client) {*/ //? } - MCEFBrowser browser = WebSession.hudBrowser(); + RinkuBrowser browser = WebSession.hudBrowser(); if (browser == null) { return; } diff --git a/src/main/java/land/webgui/WebSession.java b/src/main/java/land/webgui/WebSession.java index 14906d0..e0dd0e4 100644 --- a/src/main/java/land/webgui/WebSession.java +++ b/src/main/java/land/webgui/WebSession.java @@ -1,11 +1,11 @@ package land.webgui; -import com.cinemamod.mcef.MCEF; -import com.cinemamod.mcef.MCEFBrowser; +import de.keksuccino.rinku.Rinku; +import de.keksuccino.rinku.RinkuBrowser; public final class WebSession { - private static MCEFBrowser browser; - private static MCEFBrowser suspendedHudBrowser; + private static RinkuBrowser browser; + private static RinkuBrowser suspendedHudBrowser; private static Mode mode = Mode.NONE; public enum Mode { @@ -16,11 +16,11 @@ public enum Mode { private WebSession() {} - public static MCEFBrowser browser() { + public static RinkuBrowser browser() { return browser; } - public static MCEFBrowser hudBrowser() { + public static RinkuBrowser hudBrowser() { if (mode == Mode.HUD_OVERLAY) { return browser; } @@ -70,7 +70,7 @@ public static void closeGuiAndRestoreHud() { WebviewClientBridge.clearCache(); } - public static MCEFBrowser openForGui(String url) { + public static RinkuBrowser openForGui(String url) { closeSuspendedHudBrowser(); if (mode == Mode.HUD_OVERLAY && browser != null) { suspendedHudBrowser = browser; @@ -78,13 +78,13 @@ public static MCEFBrowser openForGui(String url) { } else { closeActiveBrowser(); } - browser = MCEF.createBrowser(url, true); + browser = Rinku.createBrowser(url, true); mode = Mode.GUI_SCREEN; WebviewClientBridge.clearCache(); return browser; } - public static MCEFBrowser openForHud(String url) { + public static RinkuBrowser openForHud(String url) { closeSuspendedHudBrowser(); if (mode == Mode.HUD_OVERLAY && browser != null) { browser.loadURL(url); @@ -92,7 +92,7 @@ public static MCEFBrowser openForHud(String url) { return browser; } closeActiveBrowser(); - browser = MCEF.createBrowser(url, true); + browser = Rinku.createBrowser(url, true); mode = Mode.HUD_OVERLAY; WebviewClientBridge.clearCache(); return browser; diff --git a/src/main/java/land/webgui/WebViewLayout.java b/src/main/java/land/webgui/WebViewLayout.java index 3f42e31..1003406 100644 --- a/src/main/java/land/webgui/WebViewLayout.java +++ b/src/main/java/land/webgui/WebViewLayout.java @@ -1,13 +1,13 @@ package land.webgui; -import com.cinemamod.mcef.MCEFBrowser; +import de.keksuccino.rinku.RinkuBrowser; import org.lwjgl.glfw.GLFW; /** * Sizing/scale helpers for the embedded browser. The browser view is the physical framebuffer size * (so its texture draws 1:1 → crisp on HiDPI), and CEF page zoom scales the content up by the OS * content scale so the page's CSS viewport stays logical and independent of Minecraft's GUI Scale. - * Uses only the public {@link MCEFBrowser#setZoomLevel} API — no device_scale_factor, no reflection. + * Uses only the public {@link RinkuBrowser#setZoomLevel} API — no device_scale_factor, no reflection. */ final class WebViewLayout { private WebViewLayout() {} @@ -40,7 +40,7 @@ static double zoomLevel() { } /** Applies the content-scale zoom. CEF may reset zoom on navigation, so call after load too. */ - static void applyZoom(MCEFBrowser browser) { + static void applyZoom(RinkuBrowser browser) { if (browser == null) { return; } diff --git a/src/main/java/land/webgui/WebViewScreen.java b/src/main/java/land/webgui/WebViewScreen.java index dc3c1e5..8a88506 100644 --- a/src/main/java/land/webgui/WebViewScreen.java +++ b/src/main/java/land/webgui/WebViewScreen.java @@ -1,7 +1,7 @@ package land.webgui; -import com.cinemamod.mcef.MCEF; -import com.cinemamod.mcef.MCEFBrowser; +import de.keksuccino.rinku.Rinku; +import de.keksuccino.rinku.RinkuBrowser; //? if >=1.21.5 { //? if fabric { import net.minecraft.client.gl.RenderPipelines; @@ -43,7 +43,7 @@ public class WebViewScreen extends Screen { private static boolean guiPageReady; private final String initialUrl; - private MCEFBrowser browser; + private RinkuBrowser browser; //? if fabric { public WebViewScreen(String startUrl) { @@ -60,7 +60,7 @@ public WebViewScreen(String startUrl) { @Override protected void init() { super.init(); - if (!MCEF.isInitialized()) { + if (!Rinku.isInitialized()) { //? if fabric { if (this.client != null && this.client.player != null) { this.client.player.sendMessage(Text.translatable("message.webgui.mcef_not_ready"), false); @@ -177,7 +177,7 @@ public void onClose() { }*/ //? } - static void onGuiBrowserLoadStart(MCEFBrowser browser) { + static void onGuiBrowserLoadStart(RinkuBrowser browser) { if (browser == null) { return; } @@ -186,7 +186,7 @@ static void onGuiBrowserLoadStart(MCEFBrowser browser) { } } - static void onGuiBrowserLoadFinished(MCEFBrowser browser) { + static void onGuiBrowserLoadFinished(RinkuBrowser browser) { if (browser == null) { return; } @@ -203,7 +203,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { //? if >=1.21.5 { Identifier textureLocation = browser.getTextureIdentifier(); //? } else { - /*Identifier textureLocation = browser.getTextureLocation();*/ + /*Identifier textureLocation = browser.getTextureIdentifier();*/ //? } if (textureLocation != null) { int fw = getBrowserWidth(); @@ -227,7 +227,7 @@ public void render(GuiGraphics context, int mouseX, int mouseY, float delta) { //? if >=1.21.5 { net.minecraft.resources.Identifier textureLocation = browser.getTextureIdentifier(); //? } else { - net.minecraft.resources.ResourceLocation textureLocation = browser.getTextureLocation(); + net.minecraft.resources.ResourceLocation textureLocation = browser.getTextureIdentifier(); //? } if (textureLocation != null) { int fw = getBrowserWidth(); diff --git a/src/main/java/land/webgui/WebviewClientBridge.java b/src/main/java/land/webgui/WebviewClientBridge.java index 9345bbf..a457e2e 100644 --- a/src/main/java/land/webgui/WebviewClientBridge.java +++ b/src/main/java/land/webgui/WebviewClientBridge.java @@ -1,7 +1,7 @@ package land.webgui; -import com.cinemamod.mcef.MCEF; -import com.cinemamod.mcef.MCEFBrowser; +import de.keksuccino.rinku.Rinku; +import de.keksuccino.rinku.RinkuBrowser; import com.google.gson.Gson; import com.google.gson.JsonObject; //? if fabric { @@ -54,11 +54,11 @@ private static void tryPush(MinecraftClient client, boolean requireTexture, bool /*private static void tryPush(Minecraft client, boolean requireTexture, boolean ignoreDedup) { LocalPlayer player = client.player;*/ //? } - if (!MCEF.isInitialized()) return; + if (!Rinku.isInitialized()) return; if (player == null) return; - MCEFBrowser main = WebSession.browser(); - MCEFBrowser hud = WebSession.hudBrowser(); + RinkuBrowser main = WebSession.browser(); + RinkuBrowser hud = WebSession.hudBrowser(); //? if fabric { boolean hasMain = main != null && (!requireTexture || main.isTextureReady()); //? } else { @@ -90,7 +90,7 @@ private static void tryPush(MinecraftClient client, boolean requireTexture, bool if (hasHud) executeJs(hud, js); } - private static void executeJs(MCEFBrowser browser, String js) { + private static void executeJs(RinkuBrowser browser, String js) { try { String url = browser.getURL(); browser.executeJavaScript(js, url != null ? url : "", 0); diff --git a/src/main/java/land/webgui/WebviewClientEmit.java b/src/main/java/land/webgui/WebviewClientEmit.java index 9047053..4ff4967 100644 --- a/src/main/java/land/webgui/WebviewClientEmit.java +++ b/src/main/java/land/webgui/WebviewClientEmit.java @@ -1,6 +1,6 @@ package land.webgui; -import com.cinemamod.mcef.MCEFBrowser; +import de.keksuccino.rinku.RinkuBrowser; import com.google.gson.Gson; public final class WebviewClientEmit { @@ -10,8 +10,8 @@ private WebviewClientEmit() {} /** Called on the Minecraft client thread after receiving a WebviewEmitS2CPayload. */ public static void dispatch(String eventName, String jsonPayload) { - MCEFBrowser main = WebSession.browser(); - MCEFBrowser hud = WebSession.hudBrowser(); + RinkuBrowser main = WebSession.browser(); + RinkuBrowser hud = WebSession.hudBrowser(); if (main == null && hud == null) return; // GSON.toJson produces a properly escaped JS string literal, e.g. "\"my\\\"event\"" @@ -30,7 +30,7 @@ public static void dispatch(String eventName, String jsonPayload) { if (hud != null && hud != main) executeJs(hud, js); } - private static void executeJs(MCEFBrowser browser, String js) { + private static void executeJs(RinkuBrowser browser, String js) { try { String url = browser.getURL(); browser.executeJavaScript(js, url != null ? url : "", 0); diff --git a/src/main/java/land/webgui/WebviewPageLoadHooks.java b/src/main/java/land/webgui/WebviewPageLoadHooks.java index 4ff352a..6130257 100644 --- a/src/main/java/land/webgui/WebviewPageLoadHooks.java +++ b/src/main/java/land/webgui/WebviewPageLoadHooks.java @@ -1,7 +1,7 @@ package land.webgui; -import com.cinemamod.mcef.MCEF; -import com.cinemamod.mcef.MCEFBrowser; +import de.keksuccino.rinku.Rinku; +import de.keksuccino.rinku.RinkuBrowser; //? if fabric { import net.minecraft.client.MinecraftClient; //? } else { @@ -16,12 +16,12 @@ public final class WebviewPageLoadHooks { private WebviewPageLoadHooks() {} public static void register() { - MCEF.getClient().addLoadHandler(new CefLoadHandlerAdapter() { + Rinku.getClient().addLoadHandler(new CefLoadHandlerAdapter() { @Override public void onLoadStart(CefBrowser browser, CefFrame frame, org.cef.network.CefRequest.TransitionType transitionType) { - MCEFBrowser active = WebSession.browser(); + RinkuBrowser active = WebSession.browser(); if (active == null || browser != active) return; if (WebSession.mode() == WebSession.Mode.HUD_OVERLAY) { WebHudOverlay.onHudBrowserLoadStart(active); @@ -32,7 +32,7 @@ public void onLoadStart(CefBrowser browser, CefFrame frame, @Override public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) { - MCEFBrowser active = WebSession.browser(); + RinkuBrowser active = WebSession.browser(); if (active == null || browser != active) return; injectBridgeScript(active); @@ -57,7 +57,7 @@ public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) { public void onLoadError(CefBrowser browser, CefFrame frame, CefLoadHandler.ErrorCode errorCode, String errorText, String failedUrl) { - MCEFBrowser active = WebSession.browser(); + RinkuBrowser active = WebSession.browser(); if (active == null || browser != active) return; if (WebSession.mode() == WebSession.Mode.HUD_OVERLAY) { WebHudOverlay.onHudBrowserLoadFinished(active); @@ -68,7 +68,7 @@ public void onLoadError(CefBrowser browser, CefFrame frame, }); } - private static void injectBridgeScript(MCEFBrowser browser) { + private static void injectBridgeScript(RinkuBrowser browser) { try { String url = browser.getURL(); browser.executeJavaScript(WebviewScriptInject.bridgeSetup(), url != null ? url : "", 0); diff --git a/src/main/java/land/webgui/WebviewPageToClientBridge.java b/src/main/java/land/webgui/WebviewPageToClientBridge.java index d739782..f1abac3 100644 --- a/src/main/java/land/webgui/WebviewPageToClientBridge.java +++ b/src/main/java/land/webgui/WebviewPageToClientBridge.java @@ -1,6 +1,6 @@ package land.webgui; -import com.cinemamod.mcef.MCEF; +import de.keksuccino.rinku.Rinku; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -43,7 +43,7 @@ public boolean onQuery(CefBrowser browser, CefFrame frame, long queryId, return true; } }, true); - MCEF.getClient().getHandle().addMessageRouter(router); + Rinku.getClient().getHandle().addMessageRouter(router); } private static void dispatch(CefFrame frame, String request, CefQueryCallback callback) { diff --git a/src/main/java/land/webgui/mixin/CefUtilMixin.java b/src/main/java/land/webgui/mixin/CefUtilMixin.java index 6ec4712..3021b30 100644 --- a/src/main/java/land/webgui/mixin/CefUtilMixin.java +++ b/src/main/java/land/webgui/mixin/CefUtilMixin.java @@ -8,7 +8,7 @@ import java.util.Arrays; import java.util.List; -@Mixin(targets = "com.cinemamod.mcef.CefUtil", remap = false) +@Mixin(targets = "de.keksuccino.rinku.util.CefUtil", remap = false) public class CefUtilMixin { @ModifyArg( @@ -25,8 +25,6 @@ public class CefUtilMixin { args.add("--enable-gpu-rasterization"); // Out-of-process rasterization: separate GPU process handles raster work args.add("--enable-oop-rasterization"); - // Prefer native desktop OpenGL over ANGLE (better performance on desktop) - args.add("--use-gl=desktop"); // Remove GPU vsync so CEF isn't throttled by display refresh during off-screen render args.add("--disable-gpu-vsync"); return args.toArray(new String[0]); diff --git a/src/main/java/land/webgui/mixin/MouseMixin.java b/src/main/java/land/webgui/mixin/MouseMixin.java index ee3898e..22e57d0 100644 --- a/src/main/java/land/webgui/mixin/MouseMixin.java +++ b/src/main/java/land/webgui/mixin/MouseMixin.java @@ -1,6 +1,6 @@ package land.webgui.mixin; -import com.cinemamod.mcef.MCEFBrowser; +import de.keksuccino.rinku.RinkuBrowser; import land.webgui.WebHudOverlay; import land.webgui.WebSession; //? if fabric { @@ -93,7 +93,7 @@ public class MouseMixin { if (!WebHudOverlay.containsMouse(mx, my, client)) { return; } - MCEFBrowser browser = WebSession.browser(); + RinkuBrowser browser = WebSession.browser(); if (browser != null) { int lx = WebHudOverlay.toBrowserLocalX(mx, client); int ly = WebHudOverlay.toBrowserLocalY(my, client); @@ -157,7 +157,7 @@ public class MouseMixin { //? } return; } - MCEFBrowser browser = WebSession.browser(); + RinkuBrowser browser = WebSession.browser(); if (browser == null) { return; } @@ -219,7 +219,7 @@ public class MouseMixin { if (!WebHudOverlay.containsMouse(mx, my, client)) { return; } - MCEFBrowser browser = WebSession.browser(); + RinkuBrowser browser = WebSession.browser(); if (browser == null) { return; } diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index 0c0e5ab..08cddd8 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -22,5 +22,17 @@ versionRange = "${minecraft_range}" ordering = "NONE" side = "BOTH" +# Rinku is the browser. Without it WebGUI does not merely fail to render a page +# — its mixins target Rinku classes, so the game dies during mod construction +# with NoClassDefFoundError. Declaring the dependency turns that crash into +# FML's "missing dependency" screen, and lets launchers install it. +# Fabric needs no equivalent: there Rinku ships inside the jar via jar-in-jar. +[[dependencies.webgui]] +modId = "rinku" +type = "required" +versionRange = "[3,)" +ordering = "BEFORE" +side = "CLIENT" + [[mixins]] config = "webgui.mixins.json" diff --git a/versions/1.20.1-fabric/gradle.properties b/versions/1.20.1-fabric/gradle.properties index 639d910..34d7a6c 100644 --- a/versions/1.20.1-fabric/gradle.properties +++ b/versions/1.20.1-fabric/gradle.properties @@ -2,6 +2,6 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.10 loader_version=0.19.5 fabric_version=0.92.12+1.20.1 -mcef_version=2.2.0-1.20.1-fabric +rinku_version=3.0.4-1.20.1-fabric minecraft_range=>=1.20.1 <=1.20.1 loader_type=fabric diff --git a/versions/1.20.1-neoforge/gradle.properties b/versions/1.20.1-neoforge/gradle.properties index 102eb91..5ce3888 100644 --- a/versions/1.20.1-neoforge/gradle.properties +++ b/versions/1.20.1-neoforge/gradle.properties @@ -1,5 +1,5 @@ minecraft_version=1.20.1 loader_type=neoforge neoforge_version=47.3.0 -mcef_version=2.2.0-1.20.1-forge +rinku_version=3.0.4-1.20.1-forge minecraft_range=[1.20.1] diff --git a/versions/1.21.1-fabric/gradle.properties b/versions/1.21.1-fabric/gradle.properties index f689c10..e3f31cf 100644 --- a/versions/1.21.1-fabric/gradle.properties +++ b/versions/1.21.1-fabric/gradle.properties @@ -2,6 +2,6 @@ minecraft_version=1.21.1 yarn_mappings=1.21.1+build.3 loader_version=0.19.5 fabric_version=0.116.17+1.21.1 -mcef_version=2.2.0-1.21.1-fabric +rinku_version=3.0.4-1.21.1-fabric minecraft_range=>=1.21 <=1.21.1 loader_type=fabric diff --git a/versions/1.21.1-neoforge/gradle.properties b/versions/1.21.1-neoforge/gradle.properties index f408eb2..f6e27a8 100644 --- a/versions/1.21.1-neoforge/gradle.properties +++ b/versions/1.21.1-neoforge/gradle.properties @@ -1,5 +1,5 @@ minecraft_version=1.21.1 loader_type=neoforge neoforge_version=21.1.250 -mcef_version=2.2.0-1.21.1-neoforge +rinku_version=3.0.4-1.21.1-neoforge minecraft_range=[1.21,1.21.1] diff --git a/versions/1.21.11-fabric/gradle.properties b/versions/1.21.11-fabric/gradle.properties index a1671cd..79f34df 100644 --- a/versions/1.21.11-fabric/gradle.properties +++ b/versions/1.21.11-fabric/gradle.properties @@ -2,6 +2,6 @@ minecraft_version=1.21.11 yarn_mappings=1.21.11+build.6 loader_version=0.19.5 fabric_version=0.141.6+1.21.11 -mcef_version=2.2.0-1.21.11-fabric +rinku_version=3.0.4-1.21.11-fabric minecraft_range=>=1.21.5 <=1.21.11 loader_type=fabric diff --git a/versions/1.21.11-neoforge/gradle.properties b/versions/1.21.11-neoforge/gradle.properties index 412d06d..9fb04a6 100644 --- a/versions/1.21.11-neoforge/gradle.properties +++ b/versions/1.21.11-neoforge/gradle.properties @@ -1,5 +1,5 @@ minecraft_version=1.21.11 loader_type=neoforge neoforge_version=21.11.45 -mcef_version=2.2.0-1.21.11-neoforge +rinku_version=3.0.4-1.21.11-neoforge minecraft_range=[1.21.5,1.21.11] diff --git a/versions/26.1.2-neoforge/gradle.properties b/versions/26.1.2-neoforge/gradle.properties index 255a19f..1ef1c8e 100644 --- a/versions/26.1.2-neoforge/gradle.properties +++ b/versions/26.1.2-neoforge/gradle.properties @@ -1,6 +1,6 @@ minecraft_version=26.1.2 loader_type=neoforge neoforge_version=26.1.2.107 -mcef_version=2.2.0-26.1.1-neoforge +rinku_version=3.0.4-26.1.2-neoforge minecraft_range=[26.1.2,26.1.2] java_version=25 diff --git a/versions/26.2-neoforge/gradle.properties b/versions/26.2-neoforge/gradle.properties index 1d07792..1636ad0 100644 --- a/versions/26.2-neoforge/gradle.properties +++ b/versions/26.2-neoforge/gradle.properties @@ -1,6 +1,6 @@ minecraft_version=26.2 loader_type=neoforge neoforge_version=26.2.0.82 -mcef_version=2.2.1-26.2-neoforge +rinku_version=3.0.4-26.2-neoforge minecraft_range=[26.2,26.2] java_version=25