promotional bannermobile promotional banner

EnderFrameLib

Universal HTML/CSS Web UI and Rendering Library for Minecraft.

EnderFrameLib

EnderFrameLib is a comprehensive, lightweight HTML/CSS rendering and UI framework for Minecraft (NeoForge 1.21.1). It brings modern web layout engines, reactive data bindings, animations, media playback, and 3D/2D interactive surfaces directly into Minecraft without requiring an embedded Chromium browser (CEF).


✨ Key Features

  • Pure Java HTML & CSS Engine: Supports Block, Flexbox (flex-direction, flex-wrap, gap, flex-grow, flex-shrink), and CSS Grid (grid-template-columns, repeat(), fr, span) layouts.
  • Virtual DOM & Diff Engine: Efficiently computes differences between virtual and real DOM trees (DomDiffEngine) and supports lightweight delta-patch packets (dom_patch) for high-frequency updates.
  • CSS Transitions & Keyframe Animations: Hardware-accelerated interpolation for transform (translate, scale, rotate), opacity, color, and background-color, plus @keyframes animations and :hover, :active, and :focus pseudo-classes.
  • Multi-Surface Rendering:
    • 3D World Multiblock Screens: Automatic raytrace hit-testing (click, drag, scroll, hover) and Level-of-Detail (LOD) rendering.
    • 3D Handheld Items: Render live interactive web UIs directly onto items in first-person or third-person views.
    • 2D GUI Screens: Ready-to-use AbstractWebScreen base class with pan, zoom, and keyboard input support.
    • AR HUD & 3D Entity Trackers: Declarative HUD overlays and floating 3D entity status bars driven by HTML templates and server-synced NBT data.
  • Minecraft-Native Media & Assets: Render Minecraft items (item:), potion effects (effect:), player face avatars (player:), remote web images (https://), and video/audio streams (including YouTube via yt-dlp and 3D spatial OpenAL speaker linking).
  • Declarative Pub/Sub Data Binding: Bind server-side data channels and virtualized scrolling lists (data-bind, data-list) directly in HTML without writing boilerplate sync code.

🚀 Getting Started

1. Network & Callback Initialization

Register EnderFrameNetwork on your mod event bus and initialize the common callbacks during setup:

public MyMod(IEventBus modEventBus) {
    modEventBus.addListener(EnderFrameNetwork::registerPayloads);
}

private void clientSetup(final FMLClientSetupEvent event) {
    event.enqueueWork(() -> {
        EnderFrameNetwork.initCommonCallbacks();

        // Optional: Hook client-side UI events (onclick, oninput, onchange, etc.)
        ClientScreenInteractionManager.clientEventCallback = (sessionId, elementId, eventName, actionName, value) -> {
            // Handle event in your custom scripting engine or client handler
        };
    });
}

2. Creating a 3D World Screen Block

Implement IWebScreenBlockEntity on your BlockEntity and register WebBlockRenderer:

public class MyScreenBlockEntity extends BlockEntity implements IWebScreenBlockEntity {
    @Override public boolean isMaster() { return true; }
    @Override public BlockPos getScreenMasterPos() { return this.worldPosition; }
    @Override public Direction getFacing() { return getBlockState().getValue(BlockStateProperties.HORIZONTAL_FACING); }
    @Override public int getScreenWidth() { return 3; }  // Width in blocks
    @Override public int getScreenHeight() { return 2; } // Height in blocks
    @Override public String getSessionId() { return "my_screen_session"; }
}

Register the renderer in EntityRenderersEvent.RegisterRenderers:

event.registerBlockEntityRenderer(MyMod.MY_SCREEN_BE.get(), WebBlockRenderer::new);

Raytrace clicking, dragging, hovering, scrolling, and <input> text editing are handled automatically by ClientScreenInteractionManager.

3. Rendering on a 3D Handheld Item

Use WebItemRendererHelper inside your BlockEntityWithoutLevelRenderer:

@Override
public void renderByItem(ItemStack stack, ItemDisplayContext ctx, PoseStack pose, MultiBufferSource buffer, int light, int overlay) {
    pose.pushPose();
    WebItemRendererHelper.applyFirstPersonHandShift(stack, ctx, pose);
    // Draw your item model here...
    WebItemRendererHelper.renderWebOnItem(
            stack, ctx, pose, buffer, light, overlay,
            768, 1024,                // Virtual resolution (px)
            0.499f, 0.5f, 5f / 16f,   // Local origin (X, Y, Z)
            -90f, 0.375f              // Y-rotation and physical width in blocks
    );
    pose.popPose();
}

🖥️ Server-Side Session & DOM Management

Standalone Sessions

You can create and control a WebSession from the server at any time:

int widthPx = 3 * (int) WebRenderCore.RESOLUTION;
int heightPx = 2 * (int) WebRenderCore.RESOLUTION;

WebSession session = WebSessionManager.getOrCreateStandaloneSession("my_screen_session", widthPx, heightPx);

// Load full HTML & CSS
session.loadWithCss("<div id='counter'>0</div>", "#counter { font-size: 2rem; color: #00e5ff; }");

// Send lightweight delta patches without re-sending the entire DOM tree
session.patchText("counter", "42");
session.patchStyle("counter", "color", "#55ff55");
session.patchClass("counter", "highlighted", "add");
session.patchInnerHtml("container", "<p>Updated dynamically!</p>");

Programmatic DOM Manipulation (HtmlNode & DomUtils)

Manipulate nodes directly on either the server or client:

HtmlNode node = doc.root.querySelector("#main-panel .item");
node.addClass("active");
node.toggleClass("hidden");
node.setStyleProperty("background-color", "rgba(0, 122, 204, 0.8)");
node.setTextContent("Hello Minecraft!");
node.setInnerHTML("<span>Nested <b>HTML</b></span>");

🎨 Supported HTML & CSS Reference

HTML Tags

  • Structure & Layout: <div>, <section>, <main>, <header>, <footer>, <article>, <nav>, <span>, <p>, <h1>, <h2>, <h3>, <ul>, <li>, <hr>, <br>, <template>
  • Interactive & Forms:
    • <button data-sound="minecraft:ui.button.click" onclick="myAction">
    • <input type="text" placeholder="Enter text..." oninput="onType" onchange="onSubmit" />
    • <input type="checkbox" checked /> / <input type="radio" />
    • <input type="range" min="0" max="100" value="50" />
    • <select onchange="onSelect"><option value="a">Option A</option><option value="b">Option B</option></select>
    • <progress value="75" max="100"></progress>
  • Media: <img src="..." />, <video src="..." />

Special Image Sources (<img>)

Prefix Example Description
item: <img src="item:minecraft:diamond_sword" /> Renders a 3D/2D Minecraft ItemStack.
effect: <img src="effect:minecraft:speed" /> Renders a MobEffect icon from the texture atlas.
player: <img src="player:@self" /> or player:Notch Renders a player's 2-layer skin face (base + hat layer).
https:// <img src="" rel="noopener nofollow" target="_blank">https://example.com/icon.png&quot; /> Asynchronously downloads and caches remote images (supports Google Drive direct links).
ResourceLocation <img src="minecraft:textures/block/stone.png" /> Renders any registered Minecraft texture.

Supported CSS Properties

  • Layout Mode: display: block | inline | inline-block | flex | grid | none
  • Flexbox: flex-direction: row | column, flex-wrap: nowrap | wrap, justify-content: flex-start | center | flex-end | space-between, align-items: stretch | flex-start | center | flex-end, flex, flex-grow, flex-shrink, flex-basis, gap
  • CSS Grid: grid-template-columns, grid-template-rows (supports px, %, fr, repeat()), grid-column, grid-row (span N, start / end), gap
  • Positioning & Box Model: position: static | relative | absolute | fixed, top, right, bottom, left, z-index, width, height, min-width, max-width, min-height, aspect-ratio, margin, padding, box-sizing: border-box | content-box
  • Units & Functions: px, %, vw, vh, rem, em, calc(...), clamp(min, pref, max), CSS Variables (--my-var, var(--my-var, fallback))
  • Visuals & Clipping: color, background-color (#hex, rgb(), rgba(), linear-gradient(...)), border, border-radius (per-corner support), box-shadow, opacity, overflow: visible | hidden | clip | scroll | auto (with automatic scrollbar rendering)
  • Typography: font-size, font-weight: normal | bold, line-height, text-align: left | center | right, text-transform: uppercase
  • Transforms & Animations: transform (translate, translateX, translateY, scale, rotate), transform-origin, transition, transition-delay, transition-timing-function (linear, ease, ease-in, ease-out, ease-in-out), animation, @keyframes
  • Selectors & Pseudo-Classes: Tag, #id, .class, [attr=val], :not(...), :nth-child(n), :hover, :active, :focus, :checked, :disabled, ::before, ::after, and combinators ( , >, +, ~)

🔄 Declarative Data Binding & Pub/Sub

Publish data from the server using ServerPubSubManager:

Map<String, Object> status = Map.of("energy", "8500 FE", "progress", "85%");
ServerPubSubManager.publish("machine_status", status);

Bind it directly in HTML using data-channel and data-bind (or data-list for virtualized scrolling lists):

<div data-channel="machine_status">
    <span data-bind="text:energy">0 FE</span>
    <div style="width: 100px; height: 10px; background: #222;">
        <div data-bind="style.width:progress" style="height: 100%; background: #00ff88;"></div>
    </div>
</div>

<!-- Virtualized List (renders only visible rows in DOM) -->
<div data-channel="storage_items" data-list="storage_items" data-item-width="48" data-item-height="48" style="height: 200px; overflow-y: scroll;">
    <template>
        <div class="slot">
            <img src="item:{{id}}" />
            <span>{{count}}</span>
        </div>
    </template>
</div>

🕶️ AR HUD & 3D World Entity Trackers

EnderFrameLib can render dynamic HUDs when looking at blocks/entities (data-hud) and floating 3D status bars above entities in the world (data-tracker), including server-side NBT inspection:

<!-- Crosshair Target HUD -->
<div id="look_hud" data-hud="true" data-hud-display="flex" data-hud-require-nbt="ForgeEnergy,Items">
    <h2>{{name}}</h2>
    <p data-show="{{is_entity}}">HP: {{hp}} / {{max_hp}}</p>
    <p data-show="{{is_block}}">Hardness: {{hardness}}</p>
</div>

<!-- 3D Floating Entity Tracker -->
<div data-tracker="true" data-tracker-radius="24.0" data-tracker-y-offset="0.8" data-tracker-type="living">
    <span>{{name}} ({{hp_percent}}%)</span>
</div>

📦 Package Architecture

  • com.nishiyu.enderframelib.api: Host interfaces (IWebScreenBlockEntity, IWebSessionProvider).
  • com.nishiyu.enderframelib.core.dom: Tokenizer, parser, HtmlNode, DomUtils, DomDiffEngine, and NBT serializer.
  • com.nishiyu.enderframelib.core.css: CssParser, specificity calculation, selector matching, calc() evaluator, and style computation.
  • com.nishiyu.enderframelib.core.layout: LayoutBox, BlockLayoutEngine, FlexLayoutEngine, and GridLayoutEngine.
  • com.nishiyu.enderframelib.client: ClientWebManager, ClientScreenInteractionManager, DeclarativeBindingManager, ClientPubSubManager, GUI screens (AbstractWebScreen, InvisibleInputScreen), and renderers (UIRenderer, WebRenderCore, WebAnimator, WebMediaManager, WebBlockRenderer, WebItemRendererHelper, WebHudRenderer).
  • com.nishiyu.enderframelib.server: WebSession, WebSessionManager, ServerPubSubManager, and ServerTargetSyncHandler.
  • com.nishiyu.enderframelib.network: S2C/C2S payload definitions and rate-limiting handlers.

EnderFrameLib Team

profile avatar
  • 2
    Projects
  • 26
    Downloads

More from nishiyu24

  • Lunex project image

    Lunex

    A programming and automation mod that allows players to use Lua scripts to control machines, interactive turtles, item logistics, HTML/CSS UIs, and custom mob AI.

    • 22
    • September 30, 2026
  • Lunex project image

    Lunex

    A programming and automation mod that allows players to use Lua scripts to control machines, interactive turtles, item logistics, HTML/CSS UIs, and custom mob AI.

    • 22
    • September 30, 2026