From 6a4a63950d44e2a11803a6e57b0dfb2f2f6e8255 Mon Sep 17 00:00:00 2001 From: beemerwt Date: Sat, 18 Oct 2025 07:02:20 -0500 Subject: [PATCH 1/8] Minor changes --- .../fabric/FabricModWorldEditCUI.java | 21 ++++--- .../worldeditcui/gui/CUIConfigList.java | 55 +++++++++++-------- .../src/main/resources/fabric.mod.json | 9 +-- 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java index 1d80e5d8..ffa40b81 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java @@ -16,15 +16,15 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import org.enginehub.worldeditcui.WorldEditCUI; +import org.enginehub.worldeditcui.callback.WorldRenderCallback; import org.enginehub.worldeditcui.config.CUIConfiguration; import org.enginehub.worldeditcui.event.listeners.CUIListenerChannel; import org.enginehub.worldeditcui.event.listeners.CUIListenerWorldRender; @@ -33,6 +33,7 @@ import org.enginehub.worldeditcui.render.OptifinePipelineProvider; import org.enginehub.worldeditcui.render.PipelineProvider; import org.enginehub.worldeditcui.render.VanillaPipelineProvider; +import org.enginehub.worldeditcui.render.WecuiRenderContext; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.MixinEnvironment; @@ -49,10 +50,12 @@ public final class FabricModWorldEditCUI implements ModInitializer { public static final String MOD_ID = "worldeditcui"; private static FabricModWorldEditCUI instance; - private static final String KEYBIND_CATEGORY_WECUI = "key.categories.worldeditcui"; - private final KeyMapping keyBindToggleUI = key("toggle", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN); - private final KeyMapping keyBindClearSel = key("clear", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN); - private final KeyMapping keyBindChunkBorder = key("chunk", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN); + private static final KeyMapping.Category KEYBIND_CATEGORY_WECUI + = new KeyMapping.Category(ResourceLocation.fromNamespaceAndPath(MOD_ID, "")); + + private final KeyMapping keyBindToggleUI = key("toggle", GLFW.GLFW_KEY_UNKNOWN); + private final KeyMapping keyBindClearSel = key("clear", GLFW.GLFW_KEY_UNKNOWN); + private final KeyMapping keyBindChunkBorder = key("chunk", GLFW.GLFW_KEY_UNKNOWN); private static final List RENDER_PIPELINES = List.of( new OptifinePipelineProvider(), @@ -73,12 +76,12 @@ public final class FabricModWorldEditCUI implements ModInitializer { * Register a key binding * * @param name id, will be used as a localization key under {@code key.worldeditcui.} - * @param type type * @param code default value * @return new, registered keybinding in the mod category */ - private static KeyMapping key(final String name, final InputConstants.Type type, final int code) { - return KeyBindingHelper.registerKeyBinding(new KeyMapping("key." + MOD_ID + '.' + name, type, code, KEYBIND_CATEGORY_WECUI)); + private static KeyMapping key(final String name, final int code) { + return KeyBindingHelper.registerKeyBinding( + new KeyMapping("key." + MOD_ID + '.' + name, code, KEYBIND_CATEGORY_WECUI)); } @Override diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java index cda0bae1..ec801c68 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java @@ -28,9 +28,11 @@ import net.minecraft.util.FormattedCharSequence; import org.enginehub.worldeditcui.config.CUIConfiguration; import org.enginehub.worldeditcui.config.Colour; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import java.util.List; +import java.util.Objects; public class CUIConfigList extends ContainerObjectSelectionList { private static final Logger LOGGER = LogUtils.getLogger(); @@ -86,15 +88,6 @@ public OnOffEntry(String tag) { ); } - @Override - public void render(GuiGraphics gfx, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean isMouseOver, float partialTick) { - super.render(gfx, index, top, left, width, height, mouseX, mouseY, isMouseOver, partialTick); - - this.toggleBotton.setX(left + 105); - this.toggleBotton.setY(top); - this.toggleBotton.render(gfx, mouseX, mouseY, partialTick); - } - @Override public List children() { return ImmutableList.of(this.resetButton, this.toggleBotton); @@ -109,6 +102,15 @@ public List narratables() { protected void updateFromConfig() { this.toggleBotton.setValue((Boolean)configuration.getConfigArray().get(tag)); } + + @Override + public void renderContent(GuiGraphics gfx, int mouseX, int mouseY, boolean isMouseOver, float partialTick) { + super.renderContent(gfx, mouseX, mouseY, isMouseOver, partialTick); + + this.toggleBotton.setX(getRowLeft() + 105); + this.toggleBotton.setY(getY()); + this.toggleBotton.render(gfx, mouseX, mouseY, partialTick); + } } public class ColorConfigEntry extends ConfigEntry { @@ -127,7 +129,7 @@ public ColorConfigEntry(String tag) { configuration.changeValue(tag, tested); } }); - textField.setFormatter((string, integer) -> { + textField.addFormatter((string, integer) -> { final String colorSource = textField.getValue(); if (colorSource.length() != 9) { return FormattedCharSequence.forward(string, invalidFormat); @@ -155,20 +157,12 @@ public ColorConfigEntry(String tag) { } @Override - public void render(GuiGraphics gfx, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean isMouseOver, float partialTick) { - super.render(gfx, index, top, left, width, height, mouseX, mouseY, isMouseOver, partialTick); - this.textField.setX(left + 105); - this.textField.setY(top); - this.textField.render(gfx, mouseX, mouseY, partialTick); - } - - @Override - public List children() { + public @NotNull List children() { return ImmutableList.of(this.resetButton, this.textField); } @Override - public List narratables() { + public @NotNull List narratables() { return ImmutableList.of(this.resetButton, this.textField); } @@ -176,6 +170,14 @@ public List narratables() { protected void updateFromConfig() { this.textField.setValue(((Colour)configuration.getConfigArray().get(tag)).hexString()); } + + @Override + public void renderContent(GuiGraphics gfx, int mouseX, int mouseY, boolean isMouseOver, float partialTick) { + super.renderContent(gfx, mouseX, mouseY, isMouseOver, partialTick); + this.textField.setX(getRowLeft() + 105); + this.textField.setY(getY()); + this.textField.render(gfx, mouseX, mouseY, partialTick); + } } public abstract class ConfigEntry extends ContainerObjectSelectionList.Entry { @@ -186,13 +188,14 @@ public abstract class ConfigEntry extends ContainerObjectSelectionList.Entry { + this.resetButton = Button.builder(Component.translatable("controls.reset"), button -> { configuration.changeValue(tag, configuration.getDefaultValue(tag)); updateFromConfig(); }).bounds(0, 0, 50, BUTTON_HEIGHT).build(); - textField = new StringWidget(configuration.getDescription(tag), minecraft.font); - textField.alignLeft(); + + textField = new StringWidget(Objects.requireNonNull(configuration.getDescription(tag)), minecraft.font); + //textField.alignLeft(); Component tooltip = configuration.getTooltip(tag); if (tooltip != null) { textField.setTooltip(Tooltip.create(tooltip)); @@ -200,7 +203,11 @@ public ConfigEntry(String tag) { } @Override - public void render(GuiGraphics gfx, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean isMouseOver, float partialTick) { + public void renderContent(GuiGraphics gfx, int mouseX, int mouseY, boolean hovered, float partialTick) { + // new API handles entry position internally + int left = this.getX(); + int top = this.getY(); // or getRowTop() + int textLeft = left + 90 - maxNameWidth; this.textField.setX(textLeft); diff --git a/worldeditcui-fabric/src/main/resources/fabric.mod.json b/worldeditcui-fabric/src/main/resources/fabric.mod.json index 8573bacf..39537d0d 100644 --- a/worldeditcui-fabric/src/main/resources/fabric.mod.json +++ b/worldeditcui-fabric/src/main/resources/fabric.mod.json @@ -9,7 +9,8 @@ "yetanotherx", "Mumfrey", "TomyLobo", - "mikroskeem" + "mikroskeem", + "BeemerWT" ], "contact": { "homepage": "https://github.com/EngineHub/WorldEditCUI", @@ -43,13 +44,13 @@ "fabric-screen-api-v1": ">=1.0.9", "fabric-resource-loader-v0": ">=0.4.17", "fabric-transitive-access-wideners-v1": "*", - "minecraft": ">=1.21.5" + "minecraft": ">=1.21.9" }, "suggests": { - "worldedit": ">=7.3.12" + "worldedit": ">=7.3.17" }, "breaks": { - "worldedit": ["7.3.1", "7.3.2", "7.3.3", "7.3.4-beta-01", "7.3.4", "7.3.5", "7.3.6", "7.3.7", "7.3.8", "7.3.9-beta-01", "7.3.9", "7.3.10-beta-01", "7.3.10", "7.3.11", "7.3.12-beta-01", "7.3.12-beta-02"] + "worldedit": ["7.3.1", "7.3.2", "7.3.3", "7.3.4-beta-01", "7.3.4", "7.3.5", "7.3.6", "7.3.7", "7.3.8", "7.3.9-beta-01", "7.3.9", "7.3.10-beta-01", "7.3.10", "7.3.11", "7.3.12-beta-01", "7.3.12-beta-02", "7.3.12"] }, "accessWidener" : "worldeditcui.accesswidener" } From 4b6a0414b2df338ce96bd4cc0660b16532c4359f Mon Sep 17 00:00:00 2001 From: beemerwt Date: Sat, 18 Oct 2025 07:06:33 -0500 Subject: [PATCH 2/8] Add render mixin --- .../callback/BlockOutlineRenderCallback.java | 45 ++++ .../callback/WorldRenderCallback.java | 46 ++++ .../fabric/FabricModWorldEditCUI.java | 12 +- .../mixin/LevelRendererMixin.java | 233 ++++++++++++++++++ .../render/WecuiRenderContext.java | 30 +++ .../src/main/resources/fabric.mod.json | 3 + .../main/resources/worldeditcui.mixins.json | 14 ++ 7 files changed, 377 insertions(+), 6 deletions(-) create mode 100644 worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/BlockOutlineRenderCallback.java create mode 100644 worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/WorldRenderCallback.java create mode 100644 worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java create mode 100644 worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/WecuiRenderContext.java create mode 100644 worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/BlockOutlineRenderCallback.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/BlockOutlineRenderCallback.java new file mode 100644 index 00000000..3290f063 --- /dev/null +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/BlockOutlineRenderCallback.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.callback; + +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.state.BlockOutlineRenderState; +import org.joml.Matrix4f; + +public interface BlockOutlineRenderCallback { + record Context( + Minecraft client, + Camera camera, + PoseStack poseStack, + GpuBufferSlice projectionMatrixBuffer, + VertexConsumer vertexConsumer, + double camX, double camY, double camZ, + BlockOutlineRenderState state + ) {} + + /** + * Return true to cancel vanilla outline (replace it), false to let vanilla draw after you. + */ + boolean render(Context ctx); + + Event EVENT = + EventFactory.createArrayBacked(BlockOutlineRenderCallback.class, cbs -> ctx -> { + boolean cancel = false; + for (var cb : cbs) cancel |= cb.render(ctx); + return cancel; + }); +} + diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/WorldRenderCallback.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/WorldRenderCallback.java new file mode 100644 index 00000000..a1e63e78 --- /dev/null +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/WorldRenderCallback.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.callback; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import org.enginehub.worldeditcui.render.WecuiRenderContext; + +public interface WorldRenderCallback { + void render(WecuiRenderContext ctx); + + Event LAST = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); + Event START = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); + Event BEFORE_ENTITY_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); + Event AFTER_ENTITY_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); + Event BEFORE_BLOCK_ENTITY_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); + Event AFTER_BLOCK_ENTITY_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); + Event BEFORE_BLOCK_OUTLINE_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); + Event AFTER_TRANSLUCENT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); + Event AFTER_MAIN_PASS_SCHEDULED = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { + for (var cb : cbs) cb.render(ctx); + }); +} diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java index ffa40b81..d48fc9e5 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java @@ -97,11 +97,11 @@ public void onInitialize() { ClientLifecycleEvents.CLIENT_STARTED.register(this::onGameInitDone); CUINetworking.subscribeToCuiPacket(this::onPluginMessage); ClientPlayConnectionEvents.JOIN.register(this::onJoinGame); - WorldRenderEvents.AFTER_TRANSLUCENT.register(ctx -> { + WorldRenderCallback.AFTER_TRANSLUCENT.register(ctx -> { if (ctx.advancedTranslucency()) { try { RenderSystem.getModelViewStack().pushMatrix(); - RenderSystem.getModelViewStack().mul(ctx.matrixStack().last().pose()); + RenderSystem.getModelViewStack().mul(ctx.poseStack().last().pose()); // RenderSystem.applyModelViewMatrix(); //ctx.worldRenderer().getTranslucentTarget().bindWrite(false); this.onPostRenderEntities(ctx); @@ -111,11 +111,11 @@ public void onInitialize() { } } }); - WorldRenderEvents.LAST.register(ctx -> { + WorldRenderCallback.LAST.register(ctx -> { if (!ctx.advancedTranslucency()) { try { RenderSystem.getModelViewStack().pushMatrix(); - RenderSystem.getModelViewStack().mul(ctx.matrixStack().last().pose()); + RenderSystem.getModelViewStack().mul(ctx.poseStack().last().pose()); // RenderSystem.applyModelViewMatrix(); this.onPostRenderEntities(ctx); } finally { @@ -195,9 +195,9 @@ public void onJoinGame(final ClientPacketListener handler, final PacketSender se this.helo(handler); } - public void onPostRenderEntities(final WorldRenderContext ctx) { + public void onPostRenderEntities(final WecuiRenderContext ctx) { if (this.visible) { - this.worldRenderListener.onRender(ctx.tickCounter().getRealtimeDeltaTicks()); + this.worldRenderListener.onRender(ctx.delta().getRealtimeDeltaTicks()); } } diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java new file mode 100644 index 00000000..c04908d2 --- /dev/null +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.mixin; + +import com.mojang.blaze3d.buffers.GpuBufferSlice; +import com.mojang.blaze3d.resource.GraphicsResourceAllocator; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.Camera; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.state.BlockOutlineRenderState; +import org.enginehub.worldeditcui.callback.BlockOutlineRenderCallback; +import org.enginehub.worldeditcui.callback.WorldRenderCallback; +import org.enginehub.worldeditcui.render.WecuiRenderContext; +import org.joml.Matrix4f; +import org.joml.Vector4f; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LevelRenderer.class) +public abstract class LevelRendererMixin { + @Shadow @Final private Minecraft minecraft; + + // START (old START) + @Inject(method = "renderLevel", at = @At("HEAD")) + private void wecui$start( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, CallbackInfo ci + ) { + // per-frame prep (camera/projection etc.) + // modelView/projection are valid right here in 1.21.9 + } + + // LAST (old LAST) + @Inject(method = "renderLevel", at = @At("TAIL")) + private void wecui$last( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, CallbackInfo ci + ) { + PoseStack pose = new PoseStack(); + pose.last().pose().set(modelView); // copy modelView for parity with old ctx + WorldRenderCallback.LAST.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); + } + + // BEFORE_ENTITIES → right BEFORE extractVisibleEntities(...) + @Inject( + method = "renderLevel", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;extractVisibleEntities(" + + "Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/culling/Frustum;" + + "Lnet/minecraft/client/DeltaTracker;Lnet/minecraft/client/renderer/state/LevelRenderState;)V" + ) + ) + private void wecui$beforeEntities( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, + CallbackInfo ci + // Locals in scope at this point (order matters; keep in sync with the method body you posted) + ) { + var pose = new PoseStack(); + pose.last().pose().set(modelView); + WorldRenderCallback.BEFORE_ENTITY_EXTRACT.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); + } + + // AFTER_ENTITIES → right AFTER extractVisibleEntities(...) + @Inject( + method = "renderLevel", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;extractVisibleEntities(" + + "Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/culling/Frustum;" + + "Lnet/minecraft/client/DeltaTracker;Lnet/minecraft/client/renderer/state/LevelRenderState;)V", + shift = At.Shift.AFTER + ) + ) + private void wecui$afterEntities( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, + CallbackInfo ci + ) { + var pose = new PoseStack(); + pose.last().pose().set(modelView); + WorldRenderCallback.AFTER_ENTITY_EXTRACT.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); + } + + // BEFORE_BLOCK_ENTITY_EXTRACT + @Inject( + method = "renderLevel", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;extractVisibleBlockEntities(" + + "Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/state/LevelRenderState;)V" + ) + ) + private void wecui$beforeBlockEntityExtract( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, + CallbackInfo ci + ) { + var pose = new PoseStack(); + pose.last().pose().set(modelView); + WorldRenderCallback.BEFORE_BLOCK_ENTITY_EXTRACT.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); + } + + // AFTER_BLOCK_ENTITY_EXTRACT + @Inject( + method = "renderLevel", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;extractVisibleBlockEntities(" + + "Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/state/LevelRenderState;)V", + shift = At.Shift.AFTER + ) + ) + private void wecui$afterBlockEntityExtract( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, + CallbackInfo ci + ) { + var pose = new PoseStack(); + pose.last().pose().set(modelView); + WorldRenderCallback.AFTER_BLOCK_ENTITY_EXTRACT.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); + } + + @Inject( + method = "renderLevel", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;extractBlockOutline(" + + "Lnet/minecraft/client/Camera;" + + "Lnet/minecraft/client/renderer/state/LevelRenderState;)V" + ) + ) + private void wecui$beforeBlockOutlineExtract( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, + CallbackInfo ci + ) { + var pose = new PoseStack(); + pose.last().pose().set(modelView); + WorldRenderCallback.BEFORE_BLOCK_OUTLINE_EXTRACT.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); + } + + @Inject(method = "renderHitOutline", at = @At("HEAD"), cancellable = true) + private void wecui$blockOutline( + PoseStack pose, VertexConsumer consumer, + double camX, double camY, double camZ, + BlockOutlineRenderState state, int packedLight, + CallbackInfo ci + ) { + var ctx = new BlockOutlineRenderCallback.Context( + this.minecraft, + this.minecraft.gameRenderer.getMainCamera(), + pose, + RenderSystem.getProjectionMatrixBuffer(), + consumer, + camX, camY, camZ, + state + ); + if (BlockOutlineRenderCallback.EVENT.invoker().render(ctx)) { + ci.cancel(); // fully replace vanilla outline + } + } + + @Inject( + method = "renderLevel", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;addMainPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lnet/minecraft/client/renderer/culling/Frustum;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;ZLnet/minecraft/client/renderer/state/LevelRenderState;Lnet/minecraft/client/DeltaTracker;Lnet/minecraft/util/profiling/ProfilerFiller;)V", + shift = At.Shift.AFTER + ) + ) + private void wecui$afterMainPassScheduled( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, + CallbackInfo ci + ) { + var pose = new PoseStack(); + pose.last().pose().set(modelView); + WorldRenderCallback.AFTER_MAIN_PASS_SCHEDULED.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); + } + + // AFTER_TRANSLUCENT — fires immediately after translucent pass queued/executed + @Inject( + method = "renderLevel", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/LevelRenderer;addParticlesPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;)V" + ) + ) + private void wecui$afterTranslucent( + GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, + Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, + GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, + CallbackInfo ci + ) { + var pose = new PoseStack(); + pose.last().pose().set(modelView); + WorldRenderCallback.AFTER_TRANSLUCENT.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); + } + +} diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/WecuiRenderContext.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/WecuiRenderContext.java new file mode 100644 index 00000000..401072dc --- /dev/null +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/WecuiRenderContext.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Camera; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.GraphicsStatus; +import net.minecraft.client.Minecraft; +import org.joml.Matrix4f; + +public record WecuiRenderContext( + Minecraft client, + Camera camera, + DeltaTracker delta, + PoseStack poseStack, + Matrix4f projectionMatrix +) { + public boolean advancedTranslucency() { + var status = client.options.graphicsMode().get(); + return status == GraphicsStatus.FABULOUS; + } +} \ No newline at end of file diff --git a/worldeditcui-fabric/src/main/resources/fabric.mod.json b/worldeditcui-fabric/src/main/resources/fabric.mod.json index 39537d0d..4ad2f0f1 100644 --- a/worldeditcui-fabric/src/main/resources/fabric.mod.json +++ b/worldeditcui-fabric/src/main/resources/fabric.mod.json @@ -34,6 +34,9 @@ "org.enginehub.worldeditcui.fabric.ConfigPanelFactory" ] }, + "mixins": [ + "worldeditcui.mixins.json" + ], "depends": { "worldeditcui_protocol": "*", "fabric-api-base": "*", diff --git a/worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json b/worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json new file mode 100644 index 00000000..a96ed77c --- /dev/null +++ b/worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "org.enginehub.worldeditcui.mixin", + "compatibilityLevel": "JAVA_17", + "refmap": "worldeditcui-refmap.json", + "mixins": [], + "client": [ + "LevelRendererMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file From 52db1f1d4f64084e83dde803e981a3aeeb72738d Mon Sep 17 00:00:00 2001 From: beemerwt Date: Sat, 18 Oct 2025 07:15:23 -0500 Subject: [PATCH 3/8] Updated keybinds to new namespace standard --- .../enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java | 2 +- .../src/main/resources/assets/worldeditcui/lang/de_de.json | 5 +++-- .../src/main/resources/assets/worldeditcui/lang/en_us.json | 2 +- .../src/main/resources/assets/worldeditcui/lang/fr_fr.json | 2 +- .../src/main/resources/assets/worldeditcui/lang/nl_nl.json | 2 +- .../src/main/resources/assets/worldeditcui/lang/ru_ru.json | 2 +- .../src/main/resources/assets/worldeditcui/lang/uk_ua.json | 2 +- .../src/main/resources/assets/worldeditcui/lang/zh_cn.json | 2 +- 8 files changed, 10 insertions(+), 9 deletions(-) diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java index d48fc9e5..efacf760 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java @@ -51,7 +51,7 @@ public final class FabricModWorldEditCUI implements ModInitializer { private static FabricModWorldEditCUI instance; private static final KeyMapping.Category KEYBIND_CATEGORY_WECUI - = new KeyMapping.Category(ResourceLocation.fromNamespaceAndPath(MOD_ID, "")); + = new KeyMapping.Category(ResourceLocation.fromNamespaceAndPath(MOD_ID, "general")); private final KeyMapping keyBindToggleUI = key("toggle", GLFW.GLFW_KEY_UNKNOWN); private final KeyMapping keyBindClearSel = key("clear", GLFW.GLFW_KEY_UNKNOWN); diff --git a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json index 0483f9f7..a2213620 100644 --- a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json +++ b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json @@ -3,7 +3,7 @@ "key.worldeditcui.toggle": "CUI Sichtbarkeit An/Aus", "key.worldeditcui.clear": "WorldEdit Auswahl aufheben", "key.worldeditcui.chunk": "Chunkgrenzen An/Aus", - "key.categories.worldeditcui": "WorldEditCUI", + "key.category.worldeditcui.general": "WorldEditCUI", "worldeditcui.color.cuboidedge": "Quader Randfarbe", "worldeditcui.color.cuboidedge.tooltip": "Wähle die Farbe für den Rand einer Quader-Region aus", "worldeditcui.color.cuboidgrid": "Quader Rasterfarbe", @@ -41,5 +41,6 @@ "worldeditcui.options.extra.clearall.tooltip": "Entferne alle Regionen, wenn %s (%s) genutzt wird", "worldeditcui.options.done": "Anwenden", "worldeditcui.options.debugMode": "Debug Modus", - "worldeditcui.options.debugMode.tooltip": "Aktiviere erweiterten Debug Modus" + "worldeditcui.options.debugMode.tooltip": "Aktiviere erweiterten Debug Modus", + "key.category.worldeditcui.general": "WorldEditCUI" } diff --git a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/en_us.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/en_us.json index d2766435..8cb54396 100644 --- a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/en_us.json +++ b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/en_us.json @@ -3,7 +3,7 @@ "key.worldeditcui.toggle": "Toggle CUI visibility", "key.worldeditcui.clear": "Clear WorldEdit selection", "key.worldeditcui.chunk": "Toggle Chunk Border", - "key.categories.worldeditcui": "WorldEditCUI", + "key.category.worldeditcui.general": "WorldEditCUI", "worldeditcui.color.cuboidedge": "Cuboid Edge Color", "worldeditcui.color.cuboidedge.tooltip": "Select the color for the edge of a cuboid region", "worldeditcui.color.cuboidgrid": "Cuboid Grid Color", diff --git a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/fr_fr.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/fr_fr.json index 085eb37d..f1beee7e 100644 --- a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/fr_fr.json +++ b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/fr_fr.json @@ -2,7 +2,7 @@ "worldeditcui.options.title": "Options WorldEditCUI", "key.worldeditcui.toggle": "Bascule Visibilité du CUI", "key.worldeditcui.clear": "Effacer la sélection WorldEdit", - "key.categories.worldeditcui": "WorldEditCUI", + "key.category.worldeditcui.general": "WorldEditCUI", "worldeditcui.color.cuboidedge": "Couleur des bordures du Cuboïde", "worldeditcui.color.cuboidgrid": "Couleur de la grille du Cuboïde", "worldeditcui.color.cuboidpoint1": "Couleur du premier point du Cuboïde", diff --git a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/nl_nl.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/nl_nl.json index a22f4f1c..c4cf90fa 100644 --- a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/nl_nl.json +++ b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/nl_nl.json @@ -2,7 +2,7 @@ "worldeditcui.options.title": "WorldEditCUI Opties", "key.worldeditcui.toggle": "CUI zichtbaarheid omschakelen", "key.worldeditcui.clear": "WorldEdit selectie verwijderen", - "key.categories.worldeditcui": "WorldEditCUI", + "key.category.worldeditcui.general": "WorldEditCUI", "worldeditcui.color.cuboidedge": "Randkleur Balk", "worldeditcui.color.cuboidgrid": "Roosterkleur Balk", "worldeditcui.color.cuboidpoint1": "Eerste punt kleur Balk", diff --git a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/ru_ru.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/ru_ru.json index d614399f..f100b894 100644 --- a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/ru_ru.json +++ b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/ru_ru.json @@ -2,7 +2,7 @@ "worldeditcui.options.title": "Настройки WorldEditCUI", "key.worldeditcui.toggle": "Переключить видимость CUI", "key.worldeditcui.clear": "Очистить выделение WorldEdit", - "key.categories.worldeditcui": "WorldEditCUI", + "key.category.worldeditcui.general": "WorldEditCUI", "worldeditcui.color.cuboidedge": "Цвет границ кубоида", "worldeditcui.color.cuboidgrid": "Цвет сетки кубоида", "worldeditcui.color.cuboidpoint1": "Цвет первой точки кубоида", diff --git a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/uk_ua.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/uk_ua.json index ec6ec3e7..85f27714 100644 --- a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/uk_ua.json +++ b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/uk_ua.json @@ -2,7 +2,7 @@ "worldeditcui.options.title": "Налаштування WorldEditCUI", "key.worldeditcui.toggle": "Перемкнути видимість CUI", "key.worldeditcui.clear": "Очистити виділення", - "key.categories.worldeditcui": "WorldEditCUI", + "key.category.worldeditcui.general": "WorldEditCUI", "worldeditcui.color.cuboidedge": "Колір границі кубоїда", "worldeditcui.color.cuboidgrid": "Колір сітки кубоїда", "worldeditcui.color.cuboidpoint1": "Колір першої точки кубоїда", diff --git a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/zh_cn.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/zh_cn.json index 5548d40b..b73f0a55 100644 --- a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/zh_cn.json +++ b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/zh_cn.json @@ -2,7 +2,7 @@ "worldeditcui.options.title": "WorldEditCUI选项", "key.worldeditcui.toggle": "显示/隐藏 WECUI", "key.worldeditcui.clear": "取消WorldEdit选择区域", - "key.categories.worldeditcui": "WorldEditCUI按键设置", + "key.category.worldeditcui.general": "WorldEditCUI按键设置", "worldeditcui.color.cuboidedge": "长方体边缘颜色", "worldeditcui.color.cuboidgrid": "长方体网格颜色", "worldeditcui.color.cuboidpoint1": "长方体第一点颜色", From a4ff7633639798cbb6b60d942783d7f245a67870 Mon Sep 17 00:00:00 2001 From: beemerwt Date: Sat, 18 Oct 2025 07:21:49 -0500 Subject: [PATCH 4/8] Added refmap for loom --- worldeditcui-fabric/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/worldeditcui-fabric/build.gradle.kts b/worldeditcui-fabric/build.gradle.kts index f3dfaa0c..27d25d07 100644 --- a/worldeditcui-fabric/build.gradle.kts +++ b/worldeditcui-fabric/build.gradle.kts @@ -32,6 +32,10 @@ loom { } } + mixin { + defaultRefmapName.set("worldeditcui-refmap.json") + } + accessWidenerPath.set(project.file("src/main/resources/worldeditcui.accesswidener")) } From aaa19562e3a16511ac941e39f6fe81b3a1cf7d13 Mon Sep 17 00:00:00 2001 From: beemerwt Date: Sat, 18 Oct 2025 07:23:17 -0500 Subject: [PATCH 5/8] Fixed unnecessary warnings --- .../worldeditcui/callback/BlockOutlineRenderCallback.java | 1 - .../enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java | 1 - .../java/org/enginehub/worldeditcui/gui/CUIConfigList.java | 4 ++-- .../src/main/resources/assets/worldeditcui/lang/de_de.json | 3 +-- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/BlockOutlineRenderCallback.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/BlockOutlineRenderCallback.java index 3290f063..8402639b 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/BlockOutlineRenderCallback.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/BlockOutlineRenderCallback.java @@ -17,7 +17,6 @@ import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.state.BlockOutlineRenderState; -import org.joml.Matrix4f; public interface BlockOutlineRenderCallback { record Context( diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java index efacf760..117890e5 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java @@ -9,7 +9,6 @@ */ package org.enginehub.worldeditcui.fabric; -import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.systems.RenderSystem; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java index ec801c68..d611e003 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java @@ -89,12 +89,12 @@ public OnOffEntry(String tag) { } @Override - public List children() { + public @NotNull List children() { return ImmutableList.of(this.resetButton, this.toggleBotton); } @Override - public List narratables() { + public @NotNull List narratables() { return ImmutableList.of(this.resetButton, this.toggleBotton); } diff --git a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json index a2213620..f4504c79 100644 --- a/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json +++ b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json @@ -41,6 +41,5 @@ "worldeditcui.options.extra.clearall.tooltip": "Entferne alle Regionen, wenn %s (%s) genutzt wird", "worldeditcui.options.done": "Anwenden", "worldeditcui.options.debugMode": "Debug Modus", - "worldeditcui.options.debugMode.tooltip": "Aktiviere erweiterten Debug Modus", - "key.category.worldeditcui.general": "WorldEditCUI" + "worldeditcui.options.debugMode.tooltip": "Aktiviere erweiterten Debug Modus" } From c5708d82addcf1146607f440056576f17f147e78 Mon Sep 17 00:00:00 2001 From: beemerwt Date: Sat, 18 Oct 2025 07:28:40 -0500 Subject: [PATCH 6/8] Implement START callback for consistency --- .../enginehub/worldeditcui/mixin/LevelRendererMixin.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java index c04908d2..407805a9 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java @@ -42,8 +42,10 @@ public abstract class LevelRendererMixin { Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, CallbackInfo ci ) { - // per-frame prep (camera/projection etc.) - // modelView/projection are valid right here in 1.21.9 + PoseStack pose = new PoseStack(); + pose.last().pose().set(modelView); // copy modelView for parity with old ctx + WorldRenderCallback.START.invoker() + .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); } // LAST (old LAST) @@ -54,7 +56,7 @@ public abstract class LevelRendererMixin { GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, CallbackInfo ci ) { PoseStack pose = new PoseStack(); - pose.last().pose().set(modelView); // copy modelView for parity with old ctx + pose.last().pose().set(modelView); WorldRenderCallback.LAST.invoker() .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); } @@ -74,7 +76,6 @@ public abstract class LevelRendererMixin { Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, CallbackInfo ci - // Locals in scope at this point (order matters; keep in sync with the method body you posted) ) { var pose = new PoseStack(); pose.last().pose().set(modelView); From 8bae9625ca561fd6fd269a6859a39e212591d411 Mon Sep 17 00:00:00 2001 From: beemerwt Date: Mon, 20 Oct 2025 15:14:19 -0500 Subject: [PATCH 7/8] Removed 7.3.12 from breaking --- worldeditcui-fabric/src/main/resources/fabric.mod.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/worldeditcui-fabric/src/main/resources/fabric.mod.json b/worldeditcui-fabric/src/main/resources/fabric.mod.json index 4ad2f0f1..c1bfe189 100644 --- a/worldeditcui-fabric/src/main/resources/fabric.mod.json +++ b/worldeditcui-fabric/src/main/resources/fabric.mod.json @@ -9,8 +9,7 @@ "yetanotherx", "Mumfrey", "TomyLobo", - "mikroskeem", - "BeemerWT" + "mikroskeem" ], "contact": { "homepage": "https://github.com/EngineHub/WorldEditCUI", @@ -53,7 +52,7 @@ "worldedit": ">=7.3.17" }, "breaks": { - "worldedit": ["7.3.1", "7.3.2", "7.3.3", "7.3.4-beta-01", "7.3.4", "7.3.5", "7.3.6", "7.3.7", "7.3.8", "7.3.9-beta-01", "7.3.9", "7.3.10-beta-01", "7.3.10", "7.3.11", "7.3.12-beta-01", "7.3.12-beta-02", "7.3.12"] + "worldedit": ["7.3.1", "7.3.2", "7.3.3", "7.3.4-beta-01", "7.3.4", "7.3.5", "7.3.6", "7.3.7", "7.3.8", "7.3.9-beta-01", "7.3.9", "7.3.10-beta-01", "7.3.10", "7.3.11", "7.3.12-beta-01", "7.3.12-beta-02"] }, "accessWidener" : "worldeditcui.accesswidener" } From 12a894fcd9a2af83645775264d2f5107f69a959c Mon Sep 17 00:00:00 2001 From: beemerwt Date: Wed, 22 Oct 2025 04:43:35 -0500 Subject: [PATCH 8/8] Formatting and javadoc comments --- .../callback/WorldRenderCallback.java | 32 ++-- .../mixin/LevelRendererMixin.java | 172 +----------------- .../render/WecuiRenderContext.java | 13 +- .../main/resources/worldeditcui.mixins.json | 2 +- 4 files changed, 28 insertions(+), 191 deletions(-) diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/WorldRenderCallback.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/WorldRenderCallback.java index a1e63e78..89e95a0f 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/WorldRenderCallback.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/callback/WorldRenderCallback.java @@ -13,34 +13,24 @@ import net.fabricmc.fabric.api.event.EventFactory; import org.enginehub.worldeditcui.render.WecuiRenderContext; +/** + * A re-implementation of the old world render events for Fabric. + * Temporary until Fabric finishes their new rendering API. + */ public interface WorldRenderCallback { void render(WecuiRenderContext ctx); + /** + * Fires at the end of world rendering, after all other rendering is complete. + */ Event LAST = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { for (var cb : cbs) cb.render(ctx); }); - Event START = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { - for (var cb : cbs) cb.render(ctx); - }); - Event BEFORE_ENTITY_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { - for (var cb : cbs) cb.render(ctx); - }); - Event AFTER_ENTITY_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { - for (var cb : cbs) cb.render(ctx); - }); - Event BEFORE_BLOCK_ENTITY_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { - for (var cb : cbs) cb.render(ctx); - }); - Event AFTER_BLOCK_ENTITY_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { - for (var cb : cbs) cb.render(ctx); - }); - Event BEFORE_BLOCK_OUTLINE_EXTRACT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { - for (var cb : cbs) cb.render(ctx); - }); + + /** + * Fires immediately after the translucent rendering pass. + */ Event AFTER_TRANSLUCENT = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { for (var cb : cbs) cb.render(ctx); }); - Event AFTER_MAIN_PASS_SCHEDULED = EventFactory.createArrayBacked(WorldRenderCallback.class, cbs -> ctx -> { - for (var cb : cbs) cb.render(ctx); - }); } diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java index 407805a9..9d660a6f 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/mixin/LevelRendererMixin.java @@ -11,15 +11,11 @@ import com.mojang.blaze3d.buffers.GpuBufferSlice; import com.mojang.blaze3d.resource.GraphicsResourceAllocator; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.Camera; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.state.BlockOutlineRenderState; -import org.enginehub.worldeditcui.callback.BlockOutlineRenderCallback; import org.enginehub.worldeditcui.callback.WorldRenderCallback; import org.enginehub.worldeditcui.render.WecuiRenderContext; import org.joml.Matrix4f; @@ -31,23 +27,14 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +/** + * Mixin to LevelRenderer to inject our world render callbacks. + * Temporary until Fabric finishes their new rendering API. + */ @Mixin(LevelRenderer.class) public abstract class LevelRendererMixin { @Shadow @Final private Minecraft minecraft; - // START (old START) - @Inject(method = "renderLevel", at = @At("HEAD")) - private void wecui$start( - GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, - Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, - GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, CallbackInfo ci - ) { - PoseStack pose = new PoseStack(); - pose.last().pose().set(modelView); // copy modelView for parity with old ctx - WorldRenderCallback.START.invoker() - .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); - } - // LAST (old LAST) @Inject(method = "renderLevel", at = @At("TAIL")) private void wecui$last( @@ -61,156 +48,6 @@ public abstract class LevelRendererMixin { .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); } - // BEFORE_ENTITIES → right BEFORE extractVisibleEntities(...) - @Inject( - method = "renderLevel", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;extractVisibleEntities(" + - "Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/culling/Frustum;" + - "Lnet/minecraft/client/DeltaTracker;Lnet/minecraft/client/renderer/state/LevelRenderState;)V" - ) - ) - private void wecui$beforeEntities( - GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, - Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, - GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, - CallbackInfo ci - ) { - var pose = new PoseStack(); - pose.last().pose().set(modelView); - WorldRenderCallback.BEFORE_ENTITY_EXTRACT.invoker() - .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); - } - - // AFTER_ENTITIES → right AFTER extractVisibleEntities(...) - @Inject( - method = "renderLevel", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;extractVisibleEntities(" + - "Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/culling/Frustum;" + - "Lnet/minecraft/client/DeltaTracker;Lnet/minecraft/client/renderer/state/LevelRenderState;)V", - shift = At.Shift.AFTER - ) - ) - private void wecui$afterEntities( - GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, - Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, - GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, - CallbackInfo ci - ) { - var pose = new PoseStack(); - pose.last().pose().set(modelView); - WorldRenderCallback.AFTER_ENTITY_EXTRACT.invoker() - .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); - } - - // BEFORE_BLOCK_ENTITY_EXTRACT - @Inject( - method = "renderLevel", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;extractVisibleBlockEntities(" + - "Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/state/LevelRenderState;)V" - ) - ) - private void wecui$beforeBlockEntityExtract( - GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, - Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, - GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, - CallbackInfo ci - ) { - var pose = new PoseStack(); - pose.last().pose().set(modelView); - WorldRenderCallback.BEFORE_BLOCK_ENTITY_EXTRACT.invoker() - .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); - } - - // AFTER_BLOCK_ENTITY_EXTRACT - @Inject( - method = "renderLevel", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;extractVisibleBlockEntities(" + - "Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/state/LevelRenderState;)V", - shift = At.Shift.AFTER - ) - ) - private void wecui$afterBlockEntityExtract( - GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, - Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, - GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, - CallbackInfo ci - ) { - var pose = new PoseStack(); - pose.last().pose().set(modelView); - WorldRenderCallback.AFTER_BLOCK_ENTITY_EXTRACT.invoker() - .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); - } - - @Inject( - method = "renderLevel", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;extractBlockOutline(" + - "Lnet/minecraft/client/Camera;" + - "Lnet/minecraft/client/renderer/state/LevelRenderState;)V" - ) - ) - private void wecui$beforeBlockOutlineExtract( - GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, - Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, - GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, - CallbackInfo ci - ) { - var pose = new PoseStack(); - pose.last().pose().set(modelView); - WorldRenderCallback.BEFORE_BLOCK_OUTLINE_EXTRACT.invoker() - .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); - } - - @Inject(method = "renderHitOutline", at = @At("HEAD"), cancellable = true) - private void wecui$blockOutline( - PoseStack pose, VertexConsumer consumer, - double camX, double camY, double camZ, - BlockOutlineRenderState state, int packedLight, - CallbackInfo ci - ) { - var ctx = new BlockOutlineRenderCallback.Context( - this.minecraft, - this.minecraft.gameRenderer.getMainCamera(), - pose, - RenderSystem.getProjectionMatrixBuffer(), - consumer, - camX, camY, camZ, - state - ); - if (BlockOutlineRenderCallback.EVENT.invoker().render(ctx)) { - ci.cancel(); // fully replace vanilla outline - } - } - - @Inject( - method = "renderLevel", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/renderer/LevelRenderer;addMainPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lnet/minecraft/client/renderer/culling/Frustum;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;ZLnet/minecraft/client/renderer/state/LevelRenderState;Lnet/minecraft/client/DeltaTracker;Lnet/minecraft/util/profiling/ProfilerFiller;)V", - shift = At.Shift.AFTER - ) - ) - private void wecui$afterMainPassScheduled( - GraphicsResourceAllocator gfx, DeltaTracker delta, boolean renderBlockOutline, - Camera camera, Matrix4f modelView, Matrix4f projection, Matrix4f inverseProjection, - GpuBufferSlice slice, Vector4f clearColor, boolean renderSky, - CallbackInfo ci - ) { - var pose = new PoseStack(); - pose.last().pose().set(modelView); - WorldRenderCallback.AFTER_MAIN_PASS_SCHEDULED.invoker() - .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); - } - // AFTER_TRANSLUCENT — fires immediately after translucent pass queued/executed @Inject( method = "renderLevel", @@ -230,5 +67,4 @@ public abstract class LevelRendererMixin { WorldRenderCallback.AFTER_TRANSLUCENT.invoker() .render(new WecuiRenderContext(this.minecraft, camera, delta, pose, projection)); } - } diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/WecuiRenderContext.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/WecuiRenderContext.java index 401072dc..827767ea 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/WecuiRenderContext.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/WecuiRenderContext.java @@ -16,6 +16,17 @@ import net.minecraft.client.Minecraft; import org.joml.Matrix4f; +/** + * Temporary record for render context information used to render elements through + * {@link org.enginehub.worldeditcui.callback.WorldRenderCallback} until Fabric provides + * a proper rendering API. + * + * @param client The Minecraft client instance. + * @param camera The current camera. + * @param delta The delta tracker for interpolation. + * @param poseStack The pose stack for rendering transformations. + * @param projectionMatrix The projection matrix used for rendering. + */ public record WecuiRenderContext( Minecraft client, Camera camera, @@ -27,4 +38,4 @@ public boolean advancedTranslucency() { var status = client.options.graphicsMode().get(); return status == GraphicsStatus.FABULOUS; } -} \ No newline at end of file +} diff --git a/worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json b/worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json index a96ed77c..c53fdb27 100644 --- a/worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json +++ b/worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json @@ -11,4 +11,4 @@ "injectors": { "defaultRequire": 1 } -} \ No newline at end of file +}