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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ src/test/*

# macOS
.DS_Store

# opencode
.omo
.opencode
10 changes: 10 additions & 0 deletions .omo/run-continuation/ses_154b374d0ffenb6pOEITn2kJq4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"sessionID": "ses_154b374d0ffenb6pOEITn2kJq4",
"updatedAt": "2026-06-09T07:34:36.095Z",
"sources": {
"background-task": {
"state": "idle",
"updatedAt": "2026-06-09T07:34:36.095Z"
}
}
}
10 changes: 10 additions & 0 deletions .omo/run-continuation/ses_15520a243ffe1boZ9xCFJR4DYc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"sessionID": "ses_15520a243ffe1boZ9xCFJR4DYc",
"updatedAt": "2026-06-09T05:37:52.672Z",
"sources": {
"background-task": {
"state": "idle",
"updatedAt": "2026-06-09T05:37:52.672Z"
}
}
}
10 changes: 10 additions & 0 deletions .omo/run-continuation/ses_1561201f3ffe5FecL1zDYz3OlR.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"sessionID": "ses_1561201f3ffe5FecL1zDYz3OlR",
"updatedAt": "2026-06-09T01:14:05.782Z",
"sources": {
"background-task": {
"state": "idle",
"updatedAt": "2026-06-09T01:14:05.782Z"
}
}
}
10 changes: 10 additions & 0 deletions .omo/run-continuation/ses_1582a1b3fffeVytcZ1qXuOdHd0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"sessionID": "ses_1582a1b3fffeVytcZ1qXuOdHd0",
"updatedAt": "2026-06-08T15:36:47.526Z",
"sources": {
"background-task": {
"state": "idle",
"updatedAt": "2026-06-08T15:36:47.526Z"
}
}
}
10 changes: 10 additions & 0 deletions .omo/run-continuation/ses_1582debb4ffe5n4umaN66NYAZ9.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"sessionID": "ses_1582debb4ffe5n4umaN66NYAZ9",
"updatedAt": "2026-06-08T15:25:47.646Z",
"sources": {
"background-task": {
"state": "idle",
"updatedAt": "2026-06-08T15:25:47.646Z"
}
}
}
10 changes: 10 additions & 0 deletions .omo/run-continuation/ses_15835033effetw28iiOqzf40dW.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"sessionID": "ses_15835033effetw28iiOqzf40dW",
"updatedAt": "2026-06-09T07:34:08.125Z",
"sources": {
"background-task": {
"state": "idle",
"updatedAt": "2026-06-09T07:34:08.125Z"
}
}
}
3 changes: 1 addition & 2 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,5 @@ dependencies {
// Immersive Aircraft
modImplementation(ctnh.immersiveaircraft)

//emiaccelerator
modImplementation(ctnh.emiaccelerator)
// emiaccelerator is not defined in the version catalog.
}
5 changes: 4 additions & 1 deletion src/generated/resources/assets/ctnhcore/lang/en_ud.json
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,9 @@
"ctnhcore.ctnhitems.heavy_plate_t3.tooltip": "Ɛ⟘ㄥ§",
"ctnhcore.ctnhitems.heavy_plate_t4.tooltip": "ㄣ⟘ㄥ§",
"ctnhcore.ctnhitems.radioactive_waste.tooltip": "ʇuǝıɔıɟɟnsuı sı pǝǝds ǝɥʇ uǝɥʍ ǝʇsɐʍ ǝɔnpoɹd ןןıʍ ɹoʇɐʌıʇɔⱯ uoɹʇnǝNㄥ§",
"ctnhcore.emi.collapsible.button.collapse_all": ")s% 个分组(部全叠折:键左",
"ctnhcore.emi.collapsible.button.collapse_all.right_click": "部全叠折:键右",
"ctnhcore.emi.collapsible.button.expand_all": ")s% 个已折叠(部全开展:键左",
"ctnhcore.hugeitembuspartmachine.refund_item.tooltip": "ʇuoɹɟ uı ɹǝuıɐʇuoɔ ǝɥʇ oʇ sɯǝʇı ןɐ suɹnʇǝᴚ",
"ctnhcore.largenaquadahreactormachine.power": "%s :ɹǝʍoԀ",
"ctnhcore.machine.digital_miner.tooltip.0": "sǝɹo buıuıɯ ʎןuo 'sǝdıd buıuıɯ ou puɐ pǝǝds ɹǝʇsɐɟ 'sbuıɥ⟘W⟘⅁ ɯoɹℲㄥ§",
Expand Down Expand Up @@ -955,4 +958,4 @@
"tuff_uraninite_vein_ad": "pⱯ uıǝΛ ǝʇıuıuɐɹ∩ ɟɟn⟘",
"uranium238_vein_ad": "pⱯ uıǝΛ 8Ɛᄅɯnıuɐɹ∩",
"wollastonite_vein": "uıǝΛ ǝʇıuoʇsɐןןoM"
}
}
5 changes: 4 additions & 1 deletion src/generated/resources/assets/ctnhcore/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,9 @@
"ctnhcore.ctnhitems.heavy_plate_t3.tooltip": "§7T3",
"ctnhcore.ctnhitems.heavy_plate_t4.tooltip": "§7T4",
"ctnhcore.ctnhitems.radioactive_waste.tooltip": "§7Neutron Activator will produce waste when the speed is insufficient",
"ctnhcore.emi.collapsible.button.collapse_all": "Left click: collapse all (%s groups)",
"ctnhcore.emi.collapsible.button.collapse_all.right_click": "Right click: collapse all",
"ctnhcore.emi.collapsible.button.expand_all": "Left click: expand all (%s collapsed)",
"ctnhcore.hugeitembuspartmachine.refund_item.tooltip": "Returns al items to the container in front",
"ctnhcore.largenaquadahreactormachine.power": "Power: %s",
"ctnhcore.machine.digital_miner.tooltip.0": "§7From GTMThings, faster speed and no mining pipes, only mining ores",
Expand Down Expand Up @@ -955,4 +958,4 @@
"tuff_uraninite_vein_ad": "Tuff Uraninite Vein Ad",
"uranium238_vein_ad": "Uranium238 Vein Ad",
"wollastonite_vein": "Wollastonite Vein"
}
}
5 changes: 4 additions & 1 deletion src/generated/resources/assets/ctnhcore/lang/zh_cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,9 @@
"ctnhcore.ctnhitems.heavy_plate_t3.tooltip": "§73阶",
"ctnhcore.ctnhitems.heavy_plate_t4.tooltip": "§74阶",
"ctnhcore.ctnhitems.radioactive_waste.tooltip": "§7中子活化器在速度不达标时运行配方会产生废料",
"ctnhcore.emi.collapsible.button.collapse_all": "左键:折叠全部(%s 个分组)",
"ctnhcore.emi.collapsible.button.collapse_all.right_click": "右键:折叠全部",
"ctnhcore.emi.collapsible.button.expand_all": "左键:展开全部(%s 个已折叠)",
"ctnhcore.hugeitembuspartmachine.refund_item.tooltip": "返还所有物品到面前的容器中",
"ctnhcore.largenaquadahreactormachine.power": "发电倍率: %s",
"ctnhcore.machine.digital_miner.tooltip.0": "§7来自GTMThings的挖矿黑科技,速度更快且无采矿管道,仅挖取矿石",
Expand Down Expand Up @@ -2058,4 +2061,4 @@
"uranium238_vein_ad": "铀238矿脉",
"wollastonite_vein": "白云石矿脉",
"zenith_machine_sp": "§5灵能灯塔屹立不倒!"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public static void init(RegistrateCNLangProvider provider) {
"缺少足够能量以启动核聚变反应");
provider.add("gtceu.recipe_modifier.coil_temperature_too_low", "线圈温度过低!");

provider.add("ctnhcore.emi.collapsible.button.expand_all", "左键:展开全部(%s 个已折叠)");
provider.add("ctnhcore.emi.collapsible.button.collapse_all", "左键:折叠全部(%s 个分组)");
provider.add("ctnhcore.emi.collapsible.button.collapse_all.right_click", "右键:折叠全部");

// Config
provider.add("config.ctnhcore.option.ftbPlugin", "FTB相关");
provider.add("config.ctnhcore.option.kinetic", "应力相关");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public static void init(RegistrateLangProvider provider) {
provider.add("config.jade.plugin_ctnhcore.recipe_logic_provider", "Recipe Logic Info");
provider.add("config.jade.plugin_ctnhcore.recipe_output_provider", "Recipe Output Info");

provider.add("ctnhcore.emi.collapsible.button.expand_all", "Left click: expand all (%s collapsed)");
provider.add("ctnhcore.emi.collapsible.button.collapse_all", "Left click: collapse all (%s groups)");
provider.add("ctnhcore.emi.collapsible.button.collapse_all.right_click", "Right click: collapse all");

// Recipe Types
provider.add("gtceu.underfloor_heating_system", "Underfloor Heating");
provider.add("gtceu.astronomical_observatory", "Astronomical Observatory");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package io.github.cpearl0.ctnhcore.mixin.emi;

import io.github.cpearl0.ctnhcore.utils.emi.collapsible.CTNHCollapsibleGroups;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;

import dev.emi.emi.api.stack.EmiIngredient;
import dev.emi.emi.api.stack.EmiStackInteraction;
import dev.emi.emi.config.SidebarType;
import dev.emi.emi.runtime.EmiDrawContext;
import dev.emi.emi.runtime.EmiSidebars;
import dev.emi.emi.screen.EmiScreenBase;
import dev.emi.emi.screen.EmiScreenManager;
import dev.emi.emi.screen.widget.EmiSearchWidget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.List;

/**
* 处理 EMI 折叠组的输入:单组切换、全部切换按钮和列表重建。
*/
@Mixin(value = EmiScreenManager.class, remap = false)
public class EmiScreenManagerInputMixin {

/** EMI 原生搜索框实例,用于把 G 按钮定位到搜索框右侧。 */
@Shadow
public static EmiSearchWidget search;

/** G 按钮边长,和 EMI 侧栏单格尺寸保持接近。 */
@Unique
private static final int TOGGLE_BUTTON_SIZE = 16;

/** G 按钮与搜索框之间的水平间距。 */
@Unique
private static final int TOGGLE_BUTTON_GAP = 4;

/** G 按钮左上角 X 坐标;-1 表示当前没有可点击按钮。 */
@Unique
private static int ctnhcore$toggleBtnX = -1;

/** G 按钮左上角 Y 坐标;-1 表示当前没有可点击按钮。 */
@Unique
private static int ctnhcore$toggleBtnY = -1;

/** 鼠标当前是否悬停在 G 按钮上,用于按钮高亮和 tooltip。 */
@Unique
private static boolean ctnhcore$hoveredToggleBtn = false;

/** 处理 G 按钮点击,以及 Alt + 左键切换单个分组。 */
@Inject(method = "mouseClicked", at = @At("HEAD"), cancellable = true)
private static void ctnhcore$handleMouseClicked(double mouseX, double mouseY, int button,
CallbackInfoReturnable<Boolean> cir) {
if (CTNHCollapsibleGroups.needsRebuild()) return;
if (!CTNHCollapsibleGroups.hasGroups()) return;

int mx = (int) mouseX;
int my = (int) mouseY;

if (ctnhcore$toggleBtnX >= 0 && ctnhcore$toggleBtnY >= 0 && mx >= ctnhcore$toggleBtnX &&
mx < ctnhcore$toggleBtnX + TOGGLE_BUTTON_SIZE && my >= ctnhcore$toggleBtnY &&
my < ctnhcore$toggleBtnY + TOGGLE_BUTTON_SIZE) {
if (button == 0) {
CTNHCollapsibleGroups.toggleAll(false);
} else if (button == 1) {
CTNHCollapsibleGroups.toggleAll(true);
}
EmiScreenManager.repopulatePanels(SidebarType.INDEX);
cir.setReturnValue(true);
return;
}

if (button == 0 && Screen.hasAltDown()) {
EmiStackInteraction interaction = EmiScreenManager.getHoveredStack(mx, my, false);
EmiIngredient hovered = interaction.getStack();
if (!hovered.isEmpty()) {
if (CTNHCollapsibleGroups.toggleGroup(hovered)) {
EmiScreenManager.repopulatePanels(SidebarType.INDEX);
cir.setReturnValue(true);
}
}
}
}

/** 在搜索框右侧绘制 G 按钮:左键智能切换,右键全部折叠。 */
@Inject(method = "renderWidgets", at = @At("TAIL"))
private static void ctnhcore$renderToggleButton(EmiDrawContext context, int mouseX, int mouseY,
float delta, EmiScreenBase base,
CallbackInfo ci) {
if (CTNHCollapsibleGroups.needsRebuild()) return;
if (!CTNHCollapsibleGroups.hasGroups()) {
ctnhcore$toggleBtnX = -1;
ctnhcore$toggleBtnY = -1;
ctnhcore$hoveredToggleBtn = false;
return;
}

if (base == null || search == null) return;
ctnhcore$toggleBtnX = search.getX() + search.getWidth() + TOGGLE_BUTTON_GAP;
ctnhcore$toggleBtnY = search.getY();

int x = ctnhcore$toggleBtnX;
int y = ctnhcore$toggleBtnY;

GuiGraphics graphics = context.raw();

ctnhcore$hoveredToggleBtn = mouseX >= x && mouseX < x + TOGGLE_BUTTON_SIZE && mouseY >= y &&
mouseY < y + TOGGLE_BUTTON_SIZE;

int bgColor = ctnhcore$hoveredToggleBtn ? 0xFF444444 : 0xFF333333;
graphics.fill(x, y, x + TOGGLE_BUTTON_SIZE, y + TOGGLE_BUTTON_SIZE, bgColor);

int borderColor = ctnhcore$hoveredToggleBtn ? 0xFF888888 : 0xFF555555;
graphics.fill(x, y, x + TOGGLE_BUTTON_SIZE, y + 1, borderColor);
graphics.fill(x, y + TOGGLE_BUTTON_SIZE - 1, x + TOGGLE_BUTTON_SIZE, y + TOGGLE_BUTTON_SIZE, borderColor);
graphics.fill(x, y, x + 1, y + TOGGLE_BUTTON_SIZE, borderColor);
graphics.fill(x + TOGGLE_BUTTON_SIZE - 1, y, x + TOGGLE_BUTTON_SIZE, y + TOGGLE_BUTTON_SIZE, borderColor);

int collapsedCount = CTNHCollapsibleGroups.collapsedGroupCount();
int textColor = collapsedCount > 0 ? 0xFF88FF88 : 0xFF888888;
graphics.drawString(Minecraft.getInstance().font, "G", x + 4, y + 4, textColor, false);

if (ctnhcore$hoveredToggleBtn) {
int totalCount = CTNHCollapsibleGroups.totalGroupCount();
if (collapsedCount > 0) {
graphics.renderComponentTooltip(Minecraft.getInstance().font,
List.of(
Component.translatable("ctnhcore.emi.collapsible.button.expand_all", collapsedCount),
Component.translatable("ctnhcore.emi.collapsible.button.collapse_all.right_click")),
x, y + TOGGLE_BUTTON_SIZE + 4);
} else {
graphics.renderComponentTooltip(Minecraft.getInstance().font,
List.of(
Component.translatable("ctnhcore.emi.collapsible.button.collapse_all", totalCount),
Component.translatable("ctnhcore.emi.collapsible.button.collapse_all.right_click")),
x, y + TOGGLE_BUTTON_SIZE + 4);
}
}
}

/** EMI 刷新搜索来源时,用 INDEX 完整列表重建分组。 */
@Inject(method = "getSearchSource", at = @At("RETURN"))
private static void ctnhcore$rebuildOnSearch(CallbackInfoReturnable<List<? extends EmiIngredient>> cir) {
if (CTNHCollapsibleGroups.needsRebuild()) {
List<? extends EmiIngredient> source = EmiSidebars.getStacks(SidebarType.INDEX);
if (source != null && !source.isEmpty()) {
CTNHCollapsibleGroups.rebuild(source);
}
}
}

/** EMI 开关或重载后,下一次搜索刷新时重新扫描列表。 */
@Inject(method = "toggleVisibility", at = @At("HEAD"))
private static void ctnhcore$markDirtyOnToggle(boolean notify, CallbackInfo ci) {
CTNHCollapsibleGroups.markDirty();
}
}
Loading
Loading