Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

---
Expand Down
71 changes: 66 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 9 additions & 9 deletions src/main/java/land/webgui/WebGUIClient.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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).");
Expand Down Expand Up @@ -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);
}
Expand All @@ -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).");
Expand Down Expand Up @@ -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(
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/land/webgui/WebGUIKeys.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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"));
Expand Down
24 changes: 12 additions & 12 deletions src/main/java/land/webgui/WebHudOverlay.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -229,7 +229,7 @@ public static void toggleHud(MinecraftClient client) {
//? }
return;
}
if (!MCEF.isInitialized()) {
if (!Rinku.isInitialized()) {
notifyMcefMissing(client);
return;
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -356,7 +356,7 @@ public static void onGuiClosed(MinecraftClient client) {
}
}

static void onHudBrowserLoadStart(MCEFBrowser browser) {
static void onHudBrowserLoadStart(RinkuBrowser browser) {
if (browser == null) {
return;
}
Expand All @@ -365,7 +365,7 @@ static void onHudBrowserLoadStart(MCEFBrowser browser) {
}
}

static void onHudBrowserLoadFinished(MCEFBrowser browser) {
static void onHudBrowserLoadFinished(RinkuBrowser browser) {
if (browser == null) {
return;
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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();
Expand Down Expand Up @@ -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;
}
Expand Down
Loading
Loading