diff --git a/src/main/java/com/listmore/config/ListMoreConfigGui.java b/src/main/java/com/listmore/config/ListMoreConfigGui.java index fd9d527..9029cfe 100644 --- a/src/main/java/com/listmore/config/ListMoreConfigGui.java +++ b/src/main/java/com/listmore/config/ListMoreConfigGui.java @@ -5,14 +5,42 @@ import com.listmore.ListMore; import fi.dy.masa.malilib.gui.GuiConfigsBase; +import fi.dy.masa.malilib.gui.button.ButtonBase; +import fi.dy.masa.malilib.gui.button.ButtonGeneric; +import fi.dy.masa.malilib.gui.button.IButtonActionListener; +import fi.dy.masa.malilib.util.StringUtils; public class ListMoreConfigGui extends GuiConfigsBase { + private static ConfigTab tab = ConfigTab.GENERIC; + public ListMoreConfigGui() { super(10, 50, ListMore.MOD_ID, null, "listmore.gui.title"); } + @Override + public void initGui() { + super.initGui(); + this.clearOptions(); + + int x = 10; + for (ConfigTab currentTab : ConfigTab.values()) { + x += this.createButton(x, 26, -1, currentTab) + 2; + } + } + + private int createButton(int x, int y, int width, ConfigTab configTab) { + ButtonGeneric button = new ButtonGeneric(x, y, width, 20, configTab.getDisplayName()); + button.setEnabled(tab != configTab); + this.addButton(button, new ButtonListener(configTab, this)); + return button.getWidth(); + } + @Override protected int getConfigWidth() { + if (tab == ConfigTab.GENERIC) { + return 200; + } + return 200; } @@ -21,8 +49,40 @@ protected int getBrowserHeight() { return this.height - 70; } + @Override + protected boolean useKeybindSearch() { + return tab == ConfigTab.ALL; + } + @Override public List getConfigs() { return ConfigOptionWrapper.createFor(ListMoreConfigs.Generic.OPTIONS); } + + private record ButtonListener(ConfigTab tab, ListMoreConfigGui parent) implements IButtonActionListener { + @Override + public void actionPerformedWithButton(ButtonBase button, int mouseButton) { + ListMoreConfigGui.tab = this.tab; + this.parent.reCreateListWidget(); + if (this.parent.getListWidget() != null) { + this.parent.getListWidget().resetScrollbarPosition(); + } + this.parent.initGui(); + } + } + + private enum ConfigTab { + ALL("malilib.gui.title.all"), + GENERIC("listmore.gui.tab.generic"); + + private final String translationKey; + + ConfigTab(String translationKey) { + this.translationKey = translationKey; + } + + public String getDisplayName() { + return StringUtils.translate(this.translationKey); + } + } } diff --git a/src/main/java/com/listmore/render/InvalidFurnaceInputRenderer.java b/src/main/java/com/listmore/render/InvalidFurnaceInputRenderer.java index 1dae683..c6dc2fd 100644 --- a/src/main/java/com/listmore/render/InvalidFurnaceInputRenderer.java +++ b/src/main/java/com/listmore/render/InvalidFurnaceInputRenderer.java @@ -7,14 +7,10 @@ //$$ import com.mojang.blaze3d.buffers.GpuBufferSlice; //#endif import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.MeshData; import com.listmore.config.ListMoreConfigs; +import com.listmore.utils.WorldRenderUtils; import fi.dy.masa.malilib.interfaces.IRenderer; -import fi.dy.masa.malilib.render.MaLiLibPipelines; -import fi.dy.masa.malilib.render.RenderContext; -import fi.dy.masa.malilib.render.RenderUtils; import fi.dy.masa.malilib.util.data.Color4f; import net.minecraft.client.Camera; @@ -187,76 +183,14 @@ private static LevelChunk getLoadedChunk(ClientLevel clientLevel, ServerLevel se // 为每个目标熔炉绘制 private static void drawMarkers(List furnaces) { - //#if MC >= 26.2 - //$$ Vec3 cameraPosition = Minecraft.getInstance().gameRenderer.mainCamera().position(); - //#elseif MC >= 12111 - //$$ Vec3 cameraPosition = Minecraft.getInstance().gameRenderer.getMainCamera().position(); - //#else - Vec3 cameraPosition = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); - //#endif - RenderContext fillContext = new RenderContext( - () -> "listmore:invalid_furnace_input_fill", - MaLiLibPipelines.POSITION_COLOR_MASA_NO_DEPTH_NO_CULL - //#if MC >= 26.2 - //$$ , 0 - //#endif - ); - RenderContext outlineContext = new RenderContext( - () -> "listmore:invalid_furnace_input_outline", - MaLiLibPipelines.DEBUG_LINES_MASA_SIMPLE_NO_DEPTH_NO_CULL - //#if MC >= 26.2 - //$$ , 0 - //#endif + Vec3 cameraPosition = WorldRenderUtils.getCameraPosition(); + WorldRenderUtils.drawFilledOutlinedBlockBoxes( + "listmore:invalid_furnace_input", + furnaces, + cameraPosition, + BOX_INSET, + FILL_COLOR, + OUTLINE_COLOR ); - //#if MC < 12111 - outlineContext.lineWidth(2.0F); - //#endif - - try { - // 世界末尾渲染使用相对于当前相机的坐标,使标记与视角保持正确对应 - BufferBuilder fillBuilder = fillContext.getBuilder(); - BufferBuilder outlineBuilder = outlineContext.getBuilder(); - for (BlockPos furnace : furnaces) { - float minX = (float) (furnace.getX() + BOX_INSET - cameraPosition.x); - float minY = (float) (furnace.getY() + BOX_INSET - cameraPosition.y); - float minZ = (float) (furnace.getZ() + BOX_INSET - cameraPosition.z); - float maxX = minX + 1.0F - BOX_INSET * 2.0F; - float maxY = minY + 1.0F - BOX_INSET * 2.0F; - float maxZ = minZ + 1.0F - BOX_INSET * 2.0F; - - RenderUtils.drawBoxAllSidesBatchedQuads(minX, minY, minZ, maxX, maxY, maxZ, FILL_COLOR, fillBuilder); - RenderUtils.drawBoxAllEdgesBatchedLines(minX, minY, minZ, maxX, maxY, maxZ, OUTLINE_COLOR - //#if MC >= 12111 - //$$ , 2.0F - //#endif - , outlineBuilder); - } - - draw(fillContext, fillBuilder.build()); - draw(outlineContext, outlineBuilder.build()); - } finally { - closeQuietly(fillContext); - closeQuietly(outlineContext); - } - } - - // 提交网格并在绘制完成后释放 - private static void draw(RenderContext context, MeshData mesh) { - if (mesh == null) { - return; - } - try { - context.draw(mesh, false, true); - } finally { - mesh.close(); - } - } - - // 渲染上下文关闭失败时不影响后续渲染 - private static void closeQuietly(RenderContext context) { - try { - context.close(); - } catch (Exception ignored) { - } } } diff --git a/src/main/java/com/listmore/render/ProjectileLandingRenderer.java b/src/main/java/com/listmore/render/ProjectileLandingRenderer.java index 6e77a8d..7a6dab4 100644 --- a/src/main/java/com/listmore/render/ProjectileLandingRenderer.java +++ b/src/main/java/com/listmore/render/ProjectileLandingRenderer.java @@ -1,16 +1,12 @@ package com.listmore.render; import com.listmore.config.ListMoreConfigs; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.MeshData; +import com.listmore.utils.WorldRenderUtils; //#if MC >= 26.1 //$$ import com.mojang.blaze3d.buffers.GpuBufferSlice; //#endif import com.mojang.blaze3d.pipeline.RenderTarget; import fi.dy.masa.malilib.interfaces.IRenderer; -import fi.dy.masa.malilib.render.MaLiLibPipelines; -import fi.dy.masa.malilib.render.RenderContext; -import fi.dy.masa.malilib.render.RenderUtils; import fi.dy.masa.malilib.util.data.Color4f; import net.minecraft.client.Camera; @@ -165,58 +161,14 @@ private static EntityHit findEntityHit(Level level, LocalPlayer player, Vec3 sta } private static void drawMarker(LandingPoint landing) { - //#if MC >= 26.2 - //$$ Vec3 position = landing.position.subtract(Minecraft.getInstance().gameRenderer.mainCamera().position()); - //#elseif MC >= 12111 - //$$ Vec3 position = landing.position.subtract(Minecraft.getInstance().gameRenderer.getMainCamera().position()); - //#else - Vec3 position = landing.position.subtract(Minecraft.getInstance().gameRenderer.getMainCamera().getPosition()); - //#endif + Vec3 position = landing.position.subtract(WorldRenderUtils.getCameraPosition()); Color4f color = landing.hitEntity ? new Color4f(1.0F, 0.0F, 0.0F, 0.6F) : new Color4f(0.0F, 1.0F, 0.2F, 0.6F); - RenderContext context = new RenderContext( - () -> "listmore:projectile_landing", - MaLiLibPipelines.DEBUG_LINES_MASA_SIMPLE_NO_DEPTH_NO_CULL - //#if MC >= 26.2 - //$$ , 0 - //#endif + WorldRenderUtils.drawOutlinedBox( + "listmore:projectile_landing", + position, + HALF_SIZE, + color ); - //#if MC < 12111 - context.lineWidth(2.0F); - //#endif - - try { - BufferBuilder builder = context.getBuilder(); - RenderUtils.drawBoxAllEdgesBatchedLines( - (float) (position.x - HALF_SIZE), (float) (position.y - HALF_SIZE), (float) (position.z - HALF_SIZE), - (float) (position.x + HALF_SIZE), (float) (position.y + HALF_SIZE), (float) (position.z + HALF_SIZE), - color - //#if MC >= 12111 - //$$ , 2.0F - //#endif - , builder - ); - draw(context, builder.build()); - } finally { - closeQuietly(context); - } - } - - private static void draw(RenderContext context, MeshData mesh) { - if (mesh == null) { - return; - } - try { - context.draw(mesh, false, true); - } finally { - mesh.close(); - } - } - - private static void closeQuietly(RenderContext context) { - try { - context.close(); - } catch (Exception ignored) { - } } private enum ProjectileSpec { diff --git a/src/main/java/com/listmore/render/TntExplosionPreviewRenderer.java b/src/main/java/com/listmore/render/TntExplosionPreviewRenderer.java index f142956..e52aa1b 100644 --- a/src/main/java/com/listmore/render/TntExplosionPreviewRenderer.java +++ b/src/main/java/com/listmore/render/TntExplosionPreviewRenderer.java @@ -9,15 +9,11 @@ //$$ import com.mojang.blaze3d.buffers.GpuBufferSlice; //#endif import com.mojang.blaze3d.pipeline.RenderTarget; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.MeshData; import com.listmore.config.ListMoreConfigs; import com.listmore.config.TntExplosionPreviewMode; +import com.listmore.utils.WorldRenderUtils; import fi.dy.masa.malilib.interfaces.IRenderer; -import fi.dy.masa.malilib.render.MaLiLibPipelines; -import fi.dy.masa.malilib.render.RenderContext; -import fi.dy.masa.malilib.render.RenderUtils; import fi.dy.masa.malilib.util.data.Color4f; import net.minecraft.client.Camera; @@ -199,13 +195,7 @@ private static Set calculateAffectedBlocks(ClientLevel level, Vec3 cen // 半预览仅绘制红色范围,全预览额外绘制红黄 private static void drawMarkers(PreviewBlocks blocks) { - //#if MC >= 26.2 - //$$ Vec3 cameraPosition = Minecraft.getInstance().gameRenderer.mainCamera().position(); - //#elseif MC >= 12111 - //$$ Vec3 cameraPosition = Minecraft.getInstance().gameRenderer.getMainCamera().position(); - //#else - Vec3 cameraPosition = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); - //#endif + Vec3 cameraPosition = WorldRenderUtils.getCameraPosition(); drawMarkers(blocks.conservative(), cameraPosition, "conservative", CONSERVATIVE_FILL_COLOR, CONSERVATIVE_OUTLINE_COLOR); if (ListMoreConfigs.Generic.TNT_EXPLOSION_PREVIEW_MODE.getOptionListValue() == TntExplosionPreviewMode.FULL) { drawMarkers(blocks.possible(), cameraPosition, "possible", POSSIBLE_FILL_COLOR, POSSIBLE_OUTLINE_COLOR); @@ -217,69 +207,14 @@ private static void drawMarkers(Set positions, Vec3 cameraPosition, St if (positions.isEmpty()) { return; } - - RenderContext fillContext = new RenderContext( - () -> "listmore:tnt_explosion_" + type + "_fill", - MaLiLibPipelines.POSITION_COLOR_MASA_NO_DEPTH_NO_CULL - //#if MC >= 26.2 - //$$ , 0 - //#endif - ); - RenderContext outlineContext = new RenderContext( - () -> "listmore:tnt_explosion_" + type + "_outline", - MaLiLibPipelines.DEBUG_LINES_MASA_SIMPLE_NO_DEPTH_NO_CULL - //#if MC >= 26.2 - //$$ , 0 - //#endif + WorldRenderUtils.drawFilledOutlinedBlockBoxes( + "listmore:tnt_explosion_" + type, + positions, + cameraPosition, + BOX_INSET, + fillColor, + outlineColor ); - //#if MC < 12111 - outlineContext.lineWidth(2.0F); - //#endif - - try { - BufferBuilder fillBuilder = fillContext.getBuilder(); - BufferBuilder outlineBuilder = outlineContext.getBuilder(); - for (BlockPos position : positions) { - float minX = (float) (position.getX() + BOX_INSET - cameraPosition.x); - float minY = (float) (position.getY() + BOX_INSET - cameraPosition.y); - float minZ = (float) (position.getZ() + BOX_INSET - cameraPosition.z); - float maxX = minX + 1.0F - BOX_INSET * 2.0F; - float maxY = minY + 1.0F - BOX_INSET * 2.0F; - float maxZ = minZ + 1.0F - BOX_INSET * 2.0F; - - RenderUtils.drawBoxAllSidesBatchedQuads(minX, minY, minZ, maxX, maxY, maxZ, fillColor, fillBuilder); - RenderUtils.drawBoxAllEdgesBatchedLines(minX, minY, minZ, maxX, maxY, maxZ, outlineColor - //#if MC >= 12111 - //$$ , 2.0F - //#endif - , outlineBuilder); - } - - draw(fillContext, fillBuilder.build()); - draw(outlineContext, outlineBuilder.build()); - } finally { - closeQuietly(fillContext); - closeQuietly(outlineContext); - } - } - - // 绘制后立即释放 - private static void draw(RenderContext context, MeshData mesh) { - if (mesh == null) { - return; - } - try { - context.draw(mesh, false, true); - } finally { - mesh.close(); - } - } - - private static void closeQuietly(RenderContext context) { - try { - context.close(); - } catch (Exception ignored) { - } } private record PreviewBlocks(Set conservative, Set possible) { diff --git a/src/main/java/com/listmore/utils/WorldRenderUtils.java b/src/main/java/com/listmore/utils/WorldRenderUtils.java new file mode 100644 index 0000000..10c1c02 --- /dev/null +++ b/src/main/java/com/listmore/utils/WorldRenderUtils.java @@ -0,0 +1,127 @@ +package com.listmore.utils; + +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.MeshData; + +import fi.dy.masa.malilib.render.MaLiLibPipelines; +import fi.dy.masa.malilib.render.RenderContext; +import fi.dy.masa.malilib.render.RenderUtils; +import fi.dy.masa.malilib.util.data.Color4f; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.Vec3; + +public final class WorldRenderUtils { + private WorldRenderUtils() { + } +//TODO 需要真正实现完整化渲染封装,包括但不限于渲染样式、是否深度测试 + public static Vec3 getCameraPosition() { + //#if MC >= 26.2 + //$$ return Minecraft.getInstance().gameRenderer.mainCamera().position(); + //#elseif MC >= 12111 + //$$ return Minecraft.getInstance().gameRenderer.getMainCamera().position(); + //#else + return Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); + //#endif + } + + // 批量绘制完整方块的半透明填充和描边 + // id渲染资源标识、positions要绘制的方块世界坐标、cameraPosition当前相机世界坐标、inset方块边界内缩量、fillColor填充颜色、outlineColor描边颜色 + public static void drawFilledOutlinedBlockBoxes(String id, Iterable positions, Vec3 cameraPosition, + float inset, Color4f fillColor, Color4f outlineColor) { + RenderContext fillContext = createFillContext(id + "_fill"); + RenderContext outlineContext = createOutlineContext(id + "_outline"); + try { + BufferBuilder fillBuilder = fillContext.getBuilder(); + BufferBuilder outlineBuilder = outlineContext.getBuilder(); + for (BlockPos position : positions) { + float minX = (float) (position.getX() + inset - cameraPosition.x); + float minY = (float) (position.getY() + inset - cameraPosition.y); + float minZ = (float) (position.getZ() + inset - cameraPosition.z); + float maxX = minX + 1.0F - inset * 2.0F; + float maxY = minY + 1.0F - inset * 2.0F; + float maxZ = minZ + 1.0F - inset * 2.0F; + + RenderUtils.drawBoxAllSidesBatchedQuads(minX, minY, minZ, maxX, maxY, maxZ, fillColor, fillBuilder); + drawBoxOutline(minX, minY, minZ, maxX, maxY, maxZ, outlineColor, outlineBuilder); + } + draw(fillContext, fillBuilder.build()); + draw(outlineContext, outlineBuilder.build()); + } finally { + closeQuietly(fillContext); + closeQuietly(outlineContext); + } + } + + // 绘制一个只有描边的立方体 + // id渲染资源标识、center相对于当前相机的立方体中心坐标、halfSize立方体半边长、color描边颜色 + public static void drawOutlinedBox(String id, Vec3 center, float halfSize, Color4f color) { + RenderContext context = createOutlineContext(id); + try { + BufferBuilder builder = context.getBuilder(); + drawBoxOutline( + (float) (center.x - halfSize), (float) (center.y - halfSize), (float) (center.z - halfSize), + (float) (center.x + halfSize), (float) (center.y + halfSize), (float) (center.z + halfSize), + color, builder + ); + draw(context, builder.build()); + } finally { + closeQuietly(context); + } + } + + // 填充 + private static RenderContext createFillContext(String id) { + return new RenderContext( + () -> id, + MaLiLibPipelines.POSITION_COLOR_MASA_NO_DEPTH_NO_CULL + //#if MC >= 26.2 + //$$ , 0 + //#endif + ); + } + + // 旧版本线宽由RenderContext设置,新版本在线段绘制调用中指定 + private static RenderContext createOutlineContext(String id) { + RenderContext context = new RenderContext( + () -> id, + MaLiLibPipelines.DEBUG_LINES_MASA_SIMPLE_NO_DEPTH_NO_CULL + //#if MC >= 26.2 + //$$ , 0 + //#endif + ); + //#if MC < 12111 + context.lineWidth(2.0F); + //#endif + return context; + } + + // 统一各版本的线框参数差异 + private static void drawBoxOutline(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, + Color4f color, BufferBuilder builder) { + RenderUtils.drawBoxAllEdgesBatchedLines(minX, minY, minZ, maxX, maxY, maxZ, color + //#if MC >= 12111 + //$$ , 2.0F + //#endif + , builder); + } + + private static void draw(RenderContext context, MeshData mesh) { + if (mesh == null) { + return; + } + try { + context.draw(mesh, false, true); + } finally { + mesh.close(); + } + } + + private static void closeQuietly(RenderContext context) { + try { + context.close(); + } catch (Exception ignored) { + } + } +} diff --git a/src/main/resources/assets/listmore/lang/en_us.json b/src/main/resources/assets/listmore/lang/en_us.json index 7f9e23d..d7f6a7d 100644 --- a/src/main/resources/assets/listmore/lang/en_us.json +++ b/src/main/resources/assets/listmore/lang/en_us.json @@ -2,6 +2,7 @@ "listmore.gui.title": "ListMore", "listmore.gui.button.trigger": "Trigger", "listmore.hotkeys.category.generic": "General Hotkeys", + "listmore.gui.tab.all": "All", "listmore.gui.tab.generic": "General", "listmore.config.generic.name.playerTracer": "Player Tracers", "listmore.config.generic.prettyName.playerTracer": "Player Tracers", diff --git a/src/main/resources/assets/listmore/lang/zh_cn.json b/src/main/resources/assets/listmore/lang/zh_cn.json index fd3e2ef..eae161b 100644 --- a/src/main/resources/assets/listmore/lang/zh_cn.json +++ b/src/main/resources/assets/listmore/lang/zh_cn.json @@ -2,6 +2,7 @@ "listmore.gui.title": "ListMore", "listmore.gui.button.trigger": "触发", "listmore.hotkeys.category.generic": "通用快捷键", + "listmore.gui.tab.all": "全部", "listmore.gui.tab.generic": "通用", "listmore.config.generic.name.playerTracer": "玩家追踪线", "listmore.config.generic.prettyName.playerTracer": "玩家追踪线",