扩展了搜索的功能, 给配方界面也加了快速上传(‾◡◝)
This commit is contained in:
parent
cc1ec9fa16
commit
7eb9669180
|
|
@ -15,7 +15,7 @@ loader_version_range=[1,)
|
||||||
mod_id=extendedae_plus
|
mod_id=extendedae_plus
|
||||||
mod_name=ExtendedAE-Plus
|
mod_name=ExtendedAE-Plus
|
||||||
mod_license=LGPL-3.0-or-later
|
mod_license=LGPL-3.0-or-later
|
||||||
mod_version=1.0.1
|
mod_version=1.0.2
|
||||||
mod_group_id=com.extendedae_plus
|
mod_group_id=com.extendedae_plus
|
||||||
mod_authors=GaLicn, XianYuFish001
|
mod_authors=GaLicn, XianYuFish001
|
||||||
mod_description=
|
mod_description=
|
||||||
|
|
|
||||||
15
readme.md
15
readme.md
|
|
@ -1,6 +1,17 @@
|
||||||
# ExtendedAE Plus
|
# ExtendedAE Plus
|
||||||
_这个分支是粗浅的EMI适配,技术力不足,请见谅_
|
_这个分支是粗浅的EMI适配,技术力不足,请见谅_
|
||||||
|
|
||||||
### 相较于主分支(1.4.0)的改动:
|
### 相较于主分支(1.4.0)的改动
|
||||||
- 删除了JEI的适配
|
- 删除了JEI的适配
|
||||||
- 一些QoL功能, 针对EMI环境下遇到的问题
|
|
||||||
|
### 增加/更改的QoL功能
|
||||||
|
- 在EMI配方/配方树界面快速拉起样板编写&上传
|
||||||
|
- 扩展了样板供应器选择界面的搜索功能
|
||||||
|
- 现在可以匹配样板供应器目标方块的本地化键名
|
||||||
|
- 允许在多个获取到的关键词间切换
|
||||||
|
- 默认顺序:
|
||||||
|
- | 别名 _(不包含特殊字符的字符串现在都会被视为别名)_
|
||||||
|
- | EMI配方类别本地化关键词
|
||||||
|
- | 原版配方关键词
|
||||||
|
- ↓ EMI配方关键词
|
||||||
|
- 更多功能正在极速构思中 _(您知道吗? 这里的构思与构思谐音, 令人忍俊不禁)_
|
||||||
|
|
@ -3,6 +3,7 @@ package com.extendedae_plus.client;
|
||||||
import appeng.api.stacks.GenericStack;
|
import appeng.api.stacks.GenericStack;
|
||||||
import appeng.client.gui.me.common.MEStorageScreen;
|
import appeng.client.gui.me.common.MEStorageScreen;
|
||||||
import appeng.core.AEConfig;
|
import appeng.core.AEConfig;
|
||||||
|
import appeng.integration.modules.emi.EmiStackHelper;
|
||||||
import com.extendedae_plus.ExtendedAEPlus;
|
import com.extendedae_plus.ExtendedAEPlus;
|
||||||
import com.extendedae_plus.mixin.ae2.accessor.MEStorageScreenAccessor;
|
import com.extendedae_plus.mixin.ae2.accessor.MEStorageScreenAccessor;
|
||||||
import com.extendedae_plus.mixin.extendedae.accessor.GuiExPatternTerminalAccessor;
|
import com.extendedae_plus.mixin.extendedae.accessor.GuiExPatternTerminalAccessor;
|
||||||
|
|
@ -14,15 +15,11 @@ import dev.emi.emi.api.EmiApi;
|
||||||
import dev.emi.emi.api.stack.EmiStack;
|
import dev.emi.emi.api.stack.EmiStack;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.level.material.Fluid;
|
|
||||||
import net.neoforged.api.distmarker.Dist;
|
import net.neoforged.api.distmarker.Dist;
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
import net.neoforged.neoforge.client.event.InputEvent;
|
import net.neoforged.neoforge.client.event.InputEvent;
|
||||||
import net.neoforged.neoforge.client.event.ScreenEvent;
|
import net.neoforged.neoforge.client.event.ScreenEvent;
|
||||||
import net.neoforged.neoforge.fluids.FluidStack;
|
|
||||||
import net.neoforged.neoforge.network.PacketDistributor;
|
import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
|
@ -32,17 +29,6 @@ import java.util.List;
|
||||||
public final class InputEvents {
|
public final class InputEvents {
|
||||||
private InputEvents() {}
|
private InputEvents() {}
|
||||||
|
|
||||||
private static GenericStack toGenericStack(EmiStack stack) {
|
|
||||||
try {
|
|
||||||
GenericStack genericStack = null;
|
|
||||||
Object typed = stack.getKey();
|
|
||||||
if (typed instanceof Item item) genericStack = GenericStack.fromItemStack(new ItemStack(item));
|
|
||||||
else if (typed instanceof Fluid fluid) genericStack = GenericStack.fromFluidStack(new FluidStack(fluid, 1000));
|
|
||||||
return genericStack;
|
|
||||||
} catch (Throwable ignored) {}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onMouseButtonPre(InputEvent.MouseButton.Pre event) {
|
public static void onMouseButtonPre(InputEvent.MouseButton.Pre event) {
|
||||||
if (event.getAction() != GLFW.GLFW_PRESS) return;
|
if (event.getAction() != GLFW.GLFW_PRESS) return;
|
||||||
|
|
@ -55,7 +41,7 @@ public final class InputEvents {
|
||||||
// Optional<ITypedIngredient<?>> hovered = new JemiBookmarkOverlay().getIngredientUnderMouse();
|
// Optional<ITypedIngredient<?>> hovered = new JemiBookmarkOverlay().getIngredientUnderMouse();
|
||||||
List<EmiStack> stacks = EmiApi.getHoveredStack(false).getStack().getEmiStacks();
|
List<EmiStack> stacks = EmiApi.getHoveredStack(false).getStack().getEmiStacks();
|
||||||
if (stacks.isEmpty()) return;
|
if (stacks.isEmpty()) return;
|
||||||
GenericStack stack = toGenericStack(stacks.getFirst());
|
GenericStack stack = EmiStackHelper.toGenericStack(stacks.getFirst());
|
||||||
if (stack == null) return;
|
if (stack == null) return;
|
||||||
PacketDistributor.sendToServer(new PullFromJeiOrCraftC2SPacket(stack));
|
PacketDistributor.sendToServer(new PullFromJeiOrCraftC2SPacket(stack));
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +52,7 @@ public final class InputEvents {
|
||||||
List<EmiStack> stacks = EmiApi.getHoveredStack(false).getStack().getEmiStacks();
|
List<EmiStack> stacks = EmiApi.getHoveredStack(false).getStack().getEmiStacks();
|
||||||
if (stacks.isEmpty()) return;
|
if (stacks.isEmpty()) return;
|
||||||
|
|
||||||
GenericStack stack = toGenericStack(stacks.getFirst());
|
GenericStack stack = EmiStackHelper.toGenericStack(stacks.getFirst());
|
||||||
if (stack == null) return;
|
if (stack == null) return;
|
||||||
|
|
||||||
// 发送到服务端,让其验证并打开 CraftAmountMenu
|
// 发送到服务端,让其验证并打开 CraftAmountMenu
|
||||||
|
|
@ -112,13 +98,13 @@ public final class InputEvents {
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (event.getKeyCode() == GLFW.GLFW_KEY_LEFT_SHIFT)
|
} else if (event.getKeyCode() == GLFW.GLFW_KEY_LEFT_CONTROL)
|
||||||
PacketDistributor.sendToServer(new C2SPacketTargetKeyTriggered(C2SPacketTargetKeyTriggered.KeyType.SHIFT_DOWN));
|
PacketDistributor.sendToServer(new C2SPacketTargetKeyTriggered(C2SPacketTargetKeyTriggered.KeyType.CTRL_DOWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onKeyReleasePre(ScreenEvent.KeyReleased.Pre event) {
|
public static void onKeyReleasePre(ScreenEvent.KeyReleased.Pre event) {
|
||||||
if (event.getKeyCode() == GLFW.GLFW_KEY_LEFT_SHIFT)
|
if (event.getKeyCode() == GLFW.GLFW_KEY_LEFT_CONTROL)
|
||||||
PacketDistributor.sendToServer(new C2SPacketTargetKeyTriggered(C2SPacketTargetKeyTriggered.KeyType.SHIFT_UP));
|
PacketDistributor.sendToServer(new C2SPacketTargetKeyTriggered(C2SPacketTargetKeyTriggered.KeyType.CTRL_UP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
package com.extendedae_plus.client;
|
package com.extendedae_plus.client;
|
||||||
|
|
||||||
public interface PatternEncodingTermMenuMixinHelper {
|
public interface PatternEncodingTermMenuMixinHelper {
|
||||||
void eaep$setShiftPressed(boolean pressed);
|
void eaep$setCtrlPressed(boolean pressed);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
package com.extendedae_plus.client.ui;
|
package com.extendedae_plus.client.ui;
|
||||||
|
|
||||||
import com.extendedae_plus.network.UploadEncodedPatternToProviderC2SPacket;
|
import com.extendedae_plus.network.UploadEncodedPatternToProviderC2SPacket;
|
||||||
|
import com.extendedae_plus.util.ExtendedAEPatternUploadUtil;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
import net.minecraft.client.gui.components.EditBox;
|
import net.minecraft.client.gui.components.EditBox;
|
||||||
|
import net.minecraft.client.gui.components.Tooltip;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
@ -18,11 +22,13 @@ public class ProviderSelectScreen extends Screen {
|
||||||
// 原始数据
|
// 原始数据
|
||||||
private final List<Long> ids;
|
private final List<Long> ids;
|
||||||
private final List<String> names;
|
private final List<String> names;
|
||||||
|
private final List<String> i18nKeys;
|
||||||
private final List<Integer> emptySlots;
|
private final List<Integer> emptySlots;
|
||||||
|
|
||||||
// 分组后的数据(同名合并)
|
// 分组后的数据(同名合并)
|
||||||
private final List<Long> gIds = new ArrayList<>(); // 代表条目使用的 providerId:选择空位数最多的那个
|
private final List<Long> gIds = new ArrayList<>(); // 代表条目使用的 providerId:选择空位数最多的那个
|
||||||
private final List<String> gNames = new ArrayList<>(); // 分组名(供应器名称)
|
private final List<String> gNames = new ArrayList<>(); // 分组名(供应器名称)
|
||||||
|
private final List<String> gI18nKeys = new ArrayList<>(); // 分组名(供应器Key)
|
||||||
private final List<Integer> gTotalSlots = new ArrayList<>(); // 该名称下供应器空位总和
|
private final List<Integer> gTotalSlots = new ArrayList<>(); // 该名称下供应器空位总和
|
||||||
private final List<Integer> gCount = new ArrayList<>(); // 该名称下供应器数量
|
private final List<Integer> gCount = new ArrayList<>(); // 该名称下供应器数量
|
||||||
|
|
||||||
|
|
@ -35,8 +41,9 @@ public class ProviderSelectScreen extends Screen {
|
||||||
// 搜索框
|
// 搜索框
|
||||||
private EditBox searchBox;
|
private EditBox searchBox;
|
||||||
// 中文名输入框(用于添加映射)
|
// 中文名输入框(用于添加映射)
|
||||||
private EditBox cnInput;
|
private EditBox aliasInput;
|
||||||
private String query = "";
|
private String selectedQuery = "";
|
||||||
|
private List<String> query = new ArrayList<>();
|
||||||
private boolean needsRefresh = false;
|
private boolean needsRefresh = false;
|
||||||
|
|
||||||
private int page = 0;
|
private int page = 0;
|
||||||
|
|
@ -44,19 +51,26 @@ public class ProviderSelectScreen extends Screen {
|
||||||
|
|
||||||
private final List<Button> entryButtons = new ArrayList<>();
|
private final List<Button> entryButtons = new ArrayList<>();
|
||||||
|
|
||||||
public ProviderSelectScreen(Screen parent, List<Long> ids, List<String> names, List<Integer> emptySlots) {
|
public ProviderSelectScreen(Screen parent, List<Long> ids, List<String> names, List<String> i18nKeys, List<Integer> emptySlots) {
|
||||||
super(Component.translatable("extendedae_plus.screen.choose_provider.title"));
|
super(Component.translatable("extendedae_plus.screen.choose_provider.title"));
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.ids = ids;
|
this.ids = ids;
|
||||||
this.names = names;
|
this.names = names;
|
||||||
|
this.i18nKeys = i18nKeys;
|
||||||
this.emptySlots = emptySlots;
|
this.emptySlots = emptySlots;
|
||||||
// 如果有来自 JEI 的最近处理名称,则作为初始查询
|
// 如果有来自 JEI 的最近处理名称,则作为初始查询
|
||||||
try {
|
try {
|
||||||
String recent = com.extendedae_plus.util.ExtendedAEPatternUploadUtil.lastProcessingName;
|
List<String> recent = ExtendedAEPatternUploadUtil.lastProcessingNameList;
|
||||||
if (recent != null && !recent.isBlank()) {
|
if (recent != null && !recent.isEmpty()) {
|
||||||
this.query = recent;
|
this.query = new ArrayList<>();
|
||||||
|
recent.forEach(q -> {
|
||||||
|
String alias = ExtendedAEPatternUploadUtil.findMapping(q);
|
||||||
|
if (alias != null) query.addFirst(alias);
|
||||||
|
else query.addLast(q);
|
||||||
|
});
|
||||||
|
this.selectedQuery = query.getFirst();
|
||||||
// 用后即清空,避免污染下次
|
// 用后即清空,避免污染下次
|
||||||
com.extendedae_plus.util.ExtendedAEPatternUploadUtil.lastProcessingName = null;
|
ExtendedAEPatternUploadUtil.lastProcessingNameList.clear();
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {}
|
} catch (Throwable ignored) {}
|
||||||
buildGroups();
|
buildGroups();
|
||||||
|
|
@ -80,12 +94,28 @@ public class ProviderSelectScreen extends Screen {
|
||||||
searchBox.setY(startY - 25);
|
searchBox.setY(startY - 25);
|
||||||
searchBox.setWidth(240);
|
searchBox.setWidth(240);
|
||||||
}
|
}
|
||||||
searchBox.setValue(query);
|
searchBox.setValue(selectedQuery);
|
||||||
|
|
||||||
|
// 为多个候选的情况添加Tooltip指示
|
||||||
|
if (query.size() > 1) {
|
||||||
|
MutableComponent candidateQuery = Component.literal("候选关键词");
|
||||||
|
query.forEach(q -> {
|
||||||
|
if (selectedQuery.equalsIgnoreCase(q)) candidateQuery
|
||||||
|
.append(Component.literal("\n> ").withStyle(ChatFormatting.GREEN))
|
||||||
|
.append(Component.literal(q).withStyle(ChatFormatting.BOLD));
|
||||||
|
else candidateQuery.append("\n" +q);
|
||||||
|
});
|
||||||
|
searchBox.setTooltip(Tooltip.create(candidateQuery));
|
||||||
|
}
|
||||||
|
|
||||||
searchBox.setResponder(text -> {
|
searchBox.setResponder(text -> {
|
||||||
// 只有当输入真正发生变化时,才重置页码与过滤
|
// 只有当输入真正发生变化时,才重置页码与过滤
|
||||||
if (Objects.equals(text, query)) return;
|
if (Objects.equals(text, selectedQuery)) return;
|
||||||
query = text;
|
selectedQuery = text;
|
||||||
|
// 切换候选词不触发, 手动输入时重置query
|
||||||
|
query.clear();
|
||||||
page = 0;
|
page = 0;
|
||||||
|
searchBox.setTooltip(Tooltip.create(Component.empty()));
|
||||||
applyFilter();
|
applyFilter();
|
||||||
// 避免在回调中直接重建 UI,延迟到下一次 tick
|
// 避免在回调中直接重建 UI,延迟到下一次 tick
|
||||||
needsRefresh = true;
|
needsRefresh = true;
|
||||||
|
|
@ -129,14 +159,14 @@ public class ProviderSelectScreen extends Screen {
|
||||||
this.addRenderableWidget(reload);
|
this.addRenderableWidget(reload);
|
||||||
|
|
||||||
// 中文名输入框(用于新增映射的值)
|
// 中文名输入框(用于新增映射的值)
|
||||||
if (cnInput == null) {
|
if (aliasInput == null) {
|
||||||
cnInput = new EditBox(this.font, centerX + 50, navY + 30, 120, 20, Component.translatable("extendedae_plus.screen.cn_name"));
|
aliasInput = new EditBox(this.font, centerX + 50, navY + 30, 120, 20, Component.translatable("extendedae_plus.screen.cn_name"));
|
||||||
} else {
|
} else {
|
||||||
cnInput.setX(centerX + 50);
|
aliasInput.setX(centerX + 50);
|
||||||
cnInput.setY(navY + 30);
|
aliasInput.setY(navY + 30);
|
||||||
cnInput.setWidth(120);
|
aliasInput.setWidth(120);
|
||||||
}
|
}
|
||||||
this.addRenderableWidget(cnInput);
|
this.addRenderableWidget(aliasInput);
|
||||||
|
|
||||||
// 增加映射按钮(使用当前搜索关键字 -> 中文)
|
// 增加映射按钮(使用当前搜索关键字 -> 中文)
|
||||||
Button addMap = Button.builder(Component.translatable("extendedae_plus.screen.add_mapping"), b -> addMappingFromUI())
|
Button addMap = Button.builder(Component.translatable("extendedae_plus.screen.add_mapping"), b -> addMappingFromUI())
|
||||||
|
|
@ -212,12 +242,15 @@ public class ProviderSelectScreen extends Screen {
|
||||||
|
|
||||||
private void buildGroups() {
|
private void buildGroups() {
|
||||||
// 使用 LinkedHashMap 保持首次出现顺序
|
// 使用 LinkedHashMap 保持首次出现顺序
|
||||||
Map<String, Group> map = new LinkedHashMap<>();
|
Map<String, Group> nameMap = new LinkedHashMap<>();
|
||||||
for (int i = 0; i < names.size(); i++) {
|
for (int i = 0; i < names.size(); i++) {
|
||||||
String name = names.get(i);
|
String name = names.get(i);
|
||||||
|
String i18nKey = i18nKeys.get(i);
|
||||||
long id = ids.get(i);
|
long id = ids.get(i);
|
||||||
int slots = emptySlots.get(i);
|
int slots = emptySlots.get(i);
|
||||||
Group g = map.computeIfAbsent(name, k -> new Group());
|
Group g = nameMap.computeIfAbsent(name, k -> new Group());
|
||||||
|
// if (!i18nKey.isBlank() && !keyMap.containsKey(i18nKey))
|
||||||
|
// keyMap.put(i18nKey, name);
|
||||||
g.count++;
|
g.count++;
|
||||||
g.totalSlots += Math.max(0, slots);
|
g.totalSlots += Math.max(0, slots);
|
||||||
// 挑选空位最多的作为代表 id;若并列,保留先到者
|
// 挑选空位最多的作为代表 id;若并列,保留先到者
|
||||||
|
|
@ -225,11 +258,13 @@ public class ProviderSelectScreen extends Screen {
|
||||||
g.bestSlots = slots;
|
g.bestSlots = slots;
|
||||||
g.bestId = id;
|
g.bestId = id;
|
||||||
}
|
}
|
||||||
|
if (!i18nKey.isBlank()) g.i18nKey = i18nKey;
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, Group> e : map.entrySet()) {
|
for (Map.Entry<String, Group> e : nameMap.entrySet()) {
|
||||||
String name = e.getKey();
|
String name = e.getKey();
|
||||||
Group g = e.getValue();
|
Group g = e.getValue();
|
||||||
gNames.add(name);
|
gNames.add(name);
|
||||||
|
gI18nKeys.add(g.i18nKey);
|
||||||
gIds.add(g.bestId);
|
gIds.add(g.bestId);
|
||||||
gTotalSlots.add(g.totalSlots);
|
gTotalSlots.add(g.totalSlots);
|
||||||
gCount.add(g.count);
|
gCount.add(g.count);
|
||||||
|
|
@ -241,6 +276,7 @@ public class ProviderSelectScreen extends Screen {
|
||||||
int bestSlots = Integer.MIN_VALUE;
|
int bestSlots = Integer.MIN_VALUE;
|
||||||
int totalSlots = 0;
|
int totalSlots = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
String i18nKey = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyFilter() {
|
private void applyFilter() {
|
||||||
|
|
@ -248,10 +284,11 @@ public class ProviderSelectScreen extends Screen {
|
||||||
fNames.clear();
|
fNames.clear();
|
||||||
fTotalSlots.clear();
|
fTotalSlots.clear();
|
||||||
fCount.clear();
|
fCount.clear();
|
||||||
String q = query == null ? "" : query.trim();
|
String q = query == null ? "" : selectedQuery.trim();
|
||||||
for (int i = 0; i < gIds.size(); i++) {
|
for (int i = 0; i < gIds.size(); i++) {
|
||||||
String name = gNames.get(i);
|
String name = gNames.get(i);
|
||||||
if (q.isEmpty() || nameMatches(name, q)) {
|
String i18nKey = gI18nKeys.get(i);
|
||||||
|
if (q.isEmpty() || i18nKeyMatches(i18nKey, q) || nameMatches(name, q)) {
|
||||||
fIds.add(gIds.get(i));
|
fIds.add(gIds.get(i));
|
||||||
fNames.add(name);
|
fNames.add(name);
|
||||||
fTotalSlots.add(gTotalSlots.get(i));
|
fTotalSlots.add(gTotalSlots.get(i));
|
||||||
|
|
@ -278,7 +315,7 @@ public class ProviderSelectScreen extends Screen {
|
||||||
JEC_AVAILABLE = false;
|
JEC_AVAILABLE = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Boolean.TRUE.equals(JEC_AVAILABLE) && JEC_CONTAINS != null) {
|
if (JEC_AVAILABLE && JEC_CONTAINS != null) {
|
||||||
Object r = JEC_CONTAINS.invoke(null, name, key);
|
Object r = JEC_CONTAINS.invoke(null, name, key);
|
||||||
if (r instanceof Boolean && (Boolean) r) return true;
|
if (r instanceof Boolean && (Boolean) r) return true;
|
||||||
// 再尝试大小写不敏感:双方转为小写重新匹配
|
// 再尝试大小写不敏感:双方转为小写重新匹配
|
||||||
|
|
@ -294,6 +331,12 @@ public class ProviderSelectScreen extends Screen {
|
||||||
return name.toLowerCase().contains(key.toLowerCase());
|
return name.toLowerCase().contains(key.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean i18nKeyMatches(String i18nKey, String key) {
|
||||||
|
if (i18nKey == null || i18nKey.isBlank()) return false;
|
||||||
|
if (key == null || key.isEmpty()) return true;
|
||||||
|
return i18nKey.toLowerCase().contains(key.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||||
if (searchBox != null && searchBox.keyPressed(keyCode, scanCode, modifiers)) {
|
if (searchBox != null && searchBox.keyPressed(keyCode, scanCode, modifiers)) {
|
||||||
|
|
@ -322,8 +365,10 @@ public class ProviderSelectScreen extends Screen {
|
||||||
if (!this.searchBox.getValue().isEmpty()) {
|
if (!this.searchBox.getValue().isEmpty()) {
|
||||||
this.searchBox.setValue("");
|
this.searchBox.setValue("");
|
||||||
}
|
}
|
||||||
this.query = "";
|
this.selectedQuery = "";
|
||||||
|
this.query.clear();
|
||||||
this.page = 0;
|
this.page = 0;
|
||||||
|
searchBox.setTooltip(Tooltip.create(Component.empty()));
|
||||||
applyFilter();
|
applyFilter();
|
||||||
this.needsRefresh = true;
|
this.needsRefresh = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -332,6 +377,37 @@ public class ProviderSelectScreen extends Screen {
|
||||||
return super.mouseClicked(mouseX, mouseY, button);
|
return super.mouseClicked(mouseX, mouseY, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
|
||||||
|
if (query.size() <= 1 || this.searchBox == null)
|
||||||
|
return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY);
|
||||||
|
|
||||||
|
boolean direction = scrollY > 0;
|
||||||
|
int boxX = this.searchBox.getX();
|
||||||
|
int boxY = this.searchBox.getY();
|
||||||
|
int boxWidth = this.searchBox.getWidth();
|
||||||
|
int boxHeight = this.searchBox.getHeight();
|
||||||
|
|
||||||
|
// 滚轮切换候选词
|
||||||
|
if (mouseX >= boxX && mouseX <= boxX + boxWidth &&
|
||||||
|
mouseY >= boxY && mouseY <= boxY + boxHeight &&
|
||||||
|
query.contains(selectedQuery)) {
|
||||||
|
int index = query.indexOf(selectedQuery);
|
||||||
|
|
||||||
|
if (direction && index == 0) selectedQuery = query.getLast();
|
||||||
|
else if (direction) selectedQuery = query.get(index - 1);
|
||||||
|
else if (index == query.size() - 1) selectedQuery = query.getFirst();
|
||||||
|
else selectedQuery = query.get(index + 1);
|
||||||
|
|
||||||
|
this.page = 0;
|
||||||
|
applyFilter();
|
||||||
|
this.needsRefresh = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
@ -343,25 +419,26 @@ public class ProviderSelectScreen extends Screen {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMappingFromUI() {
|
private void addMappingFromUI() {
|
||||||
String key = query == null ? "" : query.trim();
|
String key = query == null ? "" : selectedQuery.trim();
|
||||||
String val = cnInput == null ? "" : cnInput.getValue().trim();
|
String val = aliasInput == null ? "" : aliasInput.getValue().trim();
|
||||||
var player = Minecraft.getInstance().player;
|
var player = Minecraft.getInstance().player;
|
||||||
if (key.isEmpty()) {
|
if (key.isEmpty()) {
|
||||||
if (player != null) player.sendSystemMessage(Component.literal("请输入搜索关键字后再添加映射"));
|
if (player != null) player.sendSystemMessage(Component.literal("请输入搜索关键字后再添加映射"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (val.isEmpty()) {
|
if (val.isEmpty()) {
|
||||||
if (player != null) player.sendSystemMessage(Component.literal("请输入中文名称"));
|
if (player != null) player.sendSystemMessage(Component.literal("请输入待映射别名"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean ok = com.extendedae_plus.util.ExtendedAEPatternUploadUtil.addOrUpdateAliasMapping(key, val);
|
boolean ok = ExtendedAEPatternUploadUtil.addOrUpdateAliasMapping(key, val);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (player != null) player.sendSystemMessage(Component.literal("已添加/更新映射: " + key + " -> " + val));
|
if (player != null) player.sendSystemMessage(Component.literal("已添加/更新映射: " + key + " -> " + val));
|
||||||
// 将刚添加的中文名写入搜索框,作为当前查询
|
// 将刚添加的中文名写入搜索框,作为当前查询
|
||||||
this.query = val;
|
this.query.remove(selectedQuery);
|
||||||
if (this.searchBox != null) {
|
this.query.addFirst(val);
|
||||||
|
this.selectedQuery = val;
|
||||||
|
if (this.searchBox != null)
|
||||||
this.searchBox.setValue(val);
|
this.searchBox.setValue(val);
|
||||||
}
|
|
||||||
// 更新本地过滤显示(若名称包含中文可被搜索)
|
// 更新本地过滤显示(若名称包含中文可被搜索)
|
||||||
applyFilter();
|
applyFilter();
|
||||||
// 回到第一页以展示最新筛选结果
|
// 回到第一页以展示最新筛选结果
|
||||||
|
|
@ -374,19 +451,19 @@ public class ProviderSelectScreen extends Screen {
|
||||||
|
|
||||||
// 使用中文值精确匹配删除映射
|
// 使用中文值精确匹配删除映射
|
||||||
private void deleteMappingByCnFromUI() {
|
private void deleteMappingByCnFromUI() {
|
||||||
String val = cnInput == null ? "" : cnInput.getValue().trim();
|
String val = aliasInput == null ? "" : aliasInput.getValue().trim();
|
||||||
var player = Minecraft.getInstance().player;
|
var player = Minecraft.getInstance().player;
|
||||||
if (val.isEmpty()) {
|
if (val.isEmpty()) {
|
||||||
if (player != null) player.sendSystemMessage(Component.literal("请输入中文名称后再删除映射"));
|
if (player != null) player.sendSystemMessage(Component.literal("请输入存在别名后再删除映射"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int removed = com.extendedae_plus.util.ExtendedAEPatternUploadUtil.removeMappingsByCnValue(val);
|
int removed = com.extendedae_plus.util.ExtendedAEPatternUploadUtil.removeMappingsByCnValue(val);
|
||||||
if (removed > 0) {
|
if (removed > 0) {
|
||||||
if (player != null) player.sendSystemMessage(Component.literal("已删除 " + removed + " 条映射,中文= " + val));
|
if (player != null) player.sendSystemMessage(Component.literal("已删除 " + removed + " 条映射,别名: [" + val + "]"));
|
||||||
applyFilter();
|
applyFilter();
|
||||||
needsRefresh = true;
|
needsRefresh = true;
|
||||||
} else {
|
} else {
|
||||||
if (player != null) player.sendSystemMessage(Component.literal("未找到中文为 '" + val + "' 的映射"));
|
if (player != null) player.sendSystemMessage(Component.literal("未找到别名为 '" + val + "' 的映射"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,17 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HandlerBoMRecipes {
|
public class HandlerBoMRecipes {
|
||||||
public static HashMap<ResourceLocation, GenericStack> collectInputs(MaterialNode parentNode) {
|
public static HashMap<ResourceLocation, GenericStack> collectInputs(MaterialNode parentNode, long batches) {
|
||||||
var recipe = parentNode.recipe;
|
var recipe = parentNode.recipe;
|
||||||
|
if (recipe == null) return new HashMap<>();
|
||||||
if (parentNode.state != FoldState.EXPANDED) return new HashMap<>();
|
if (parentNode.state != FoldState.EXPANDED) return new HashMap<>();
|
||||||
if (parentNode.children == null) return new HashMap<>();
|
if (parentNode.children == null) return new HashMap<>();
|
||||||
|
|
||||||
HashMap<ResourceLocation, GenericStack> results = new HashMap<>();
|
HashMap<ResourceLocation, GenericStack> results = new HashMap<>();
|
||||||
var type = recipe.getBackingRecipe().value().getType();
|
RecipeType<?> type;
|
||||||
|
if (recipe.getBackingRecipe() != null)
|
||||||
|
type = recipe.getBackingRecipe().value().getType();
|
||||||
|
else type = null;
|
||||||
|
|
||||||
parentNode.children.forEach(child -> {
|
parentNode.children.forEach(child -> {
|
||||||
EmiStack stack;
|
EmiStack stack;
|
||||||
|
|
@ -31,8 +35,8 @@ public class HandlerBoMRecipes {
|
||||||
|
|
||||||
recipe.getInputs().forEach(input -> {
|
recipe.getInputs().forEach(input -> {
|
||||||
if (input.getEmiStacks().contains(stack)) {
|
if (input.getEmiStacks().contains(stack)) {
|
||||||
stack.setAmount(input.getEmiStacks().getFirst().getAmount());
|
EmiStack batchedStack = batchAmount(stack, batches);
|
||||||
GenericStack genericStack = EmiStackHelper.toGenericStack(stack);
|
GenericStack genericStack = EmiStackHelper.toGenericStack(batchedStack);
|
||||||
if (genericStack == null) return;
|
if (genericStack == null) return;
|
||||||
|
|
||||||
results.put(input.getEmiStacks().getFirst().getId(), genericStack);
|
results.put(input.getEmiStacks().getFirst().getId(), genericStack);
|
||||||
|
|
@ -42,42 +46,7 @@ public class HandlerBoMRecipes {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static void handle(C2SPacketStoneCuttingID packet, ServerPlayer player) {
|
public static List<List<GenericStack>> updateRecipe(EmiRecipe original,
|
||||||
// if (!(player.containerMenu instanceof PatternEncodingTermMenu menu)) return;
|
|
||||||
//// RecipeHolder<?> recipeHolder = player.level().getRecipeManager()
|
|
||||||
//// .byKey(packet.recipeID()).orElse(null);
|
|
||||||
// EmiRecipe recipe = EmiApi.getRecipeManager()
|
|
||||||
// .getRecipe(packet.recipeID());
|
|
||||||
//
|
|
||||||
// if (recipe == null) return;
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// menu.clear();
|
|
||||||
// List<List<GenericStack>> modifiedInputs = updateRecipe(recipe, packet.batches(), packet.selectedStacks());
|
|
||||||
//
|
|
||||||
// // 遍历原配方的每个输入
|
|
||||||
// for (EmiIngredient originalInput : recipe.getInputs()) {
|
|
||||||
// if (!originalInput.getEmiStacks().isEmpty()) {
|
|
||||||
// EmiStack firstStack = originalInput.getEmiStacks().getFirst();
|
|
||||||
// ResourceLocation stackId = firstStack.getId();
|
|
||||||
//
|
|
||||||
// if (packet.selectedStacks().containsKey(stackId))
|
|
||||||
// modifiedInputs.add(List.of(
|
|
||||||
// packet.selectedStacks().getOrDefault(stackId, EmiStackHelper.toGenericStack(firstStack))));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 获取输出(保持不变)
|
|
||||||
// List<GenericStack> outputs = EmiStackHelper.ofOutputs(recipe);
|
|
||||||
//
|
|
||||||
// // 编码修改后的配方
|
|
||||||
//// EncodingHelper.encodeProcessingRecipe(menu, modifiedInputs, outputs);
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// ExtendedAEPlus.LOGGER.debug("encode failed:", e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public static List<List<GenericStack>> updateRecipe(EmiRecipe original, long batches,
|
|
||||||
HashMap<ResourceLocation, GenericStack> selectedInputs) {
|
HashMap<ResourceLocation, GenericStack> selectedInputs) {
|
||||||
List<List<GenericStack>> modifiedInputs = new ArrayList<>();
|
List<List<GenericStack>> modifiedInputs = new ArrayList<>();
|
||||||
|
|
||||||
|
|
@ -93,4 +62,8 @@ public class HandlerBoMRecipes {
|
||||||
});
|
});
|
||||||
return modifiedInputs;
|
return modifiedInputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static EmiStack batchAmount(EmiStack original, long batches) {
|
||||||
|
return original.copy().setAmount(original.getAmount() * batches);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,8 @@ package com.extendedae_plus.mixin.ae2.accessor;
|
||||||
|
|
||||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||||
import appeng.menu.slot.RestrictedInputSlot;
|
import appeng.menu.slot.RestrictedInputSlot;
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
|
||||||
|
|
||||||
@Mixin(PatternEncodingTermMenu.class)
|
@Mixin(PatternEncodingTermMenu.class)
|
||||||
public interface PatternEncodingTermMenuAccessor {
|
public interface PatternEncodingTermMenuAccessor {
|
||||||
|
|
@ -14,10 +12,4 @@ public interface PatternEncodingTermMenuAccessor {
|
||||||
|
|
||||||
@Accessor("blankPatternSlot")
|
@Accessor("blankPatternSlot")
|
||||||
RestrictedInputSlot eap$getBlankPatternSlot();
|
RestrictedInputSlot eap$getBlankPatternSlot();
|
||||||
|
|
||||||
@Invoker("encodePattern")
|
|
||||||
ItemStack eaep$encodePattern();
|
|
||||||
|
|
||||||
@Invoker("isPattern")
|
|
||||||
boolean eaep$isPattern(ItemStack output);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.extendedae_plus.mixin.ae2.client.gui;
|
||||||
|
|
||||||
|
import appeng.client.gui.widgets.ActionButton;
|
||||||
|
import appeng.core.localization.ButtonToolTips;
|
||||||
|
import com.extendedae_plus.config.ModConfig;
|
||||||
|
import com.extendedae_plus.util.GetKey;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
@Mixin(ActionButton.class)
|
||||||
|
public class MixinActionButton {
|
||||||
|
// @ModifyVariable(method = "buildMessage", at = @At("STORE"))
|
||||||
|
// private static String eaep$modifyEncodeButtonTooltips(String value) {
|
||||||
|
// if ()
|
||||||
|
// }
|
||||||
|
@Inject(method = "buildMessage", at = @At("TAIL"), cancellable = true)
|
||||||
|
private void eaep$modifyButtonTooltips(ButtonToolTips displayName,
|
||||||
|
ButtonToolTips displayValue,
|
||||||
|
CallbackInfoReturnable<Component> cir) {
|
||||||
|
if (displayValue == ButtonToolTips.EncodeDescription && !ModConfig.INDEPENDENT_UPLOADING_BUTTON.getAsBoolean())
|
||||||
|
cir.setReturnValue(cir.getReturnValue().copy().append(
|
||||||
|
new GetKey(GetKey.TOOLTIP).addStr("encode_button_description").build()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -64,7 +64,6 @@ public abstract class PatternProviderScreenMixin<C extends PatternProviderMenu>
|
||||||
this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO,
|
this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO,
|
||||||
(btn, backwards) -> {
|
(btn, backwards) -> {
|
||||||
// 不做本地切换,点击仅发送自定义C2S,显示由@GuiSync回传
|
// 不做本地切换,点击仅发送自定义C2S,显示由@GuiSync回传
|
||||||
// debug removed
|
|
||||||
var conn = Minecraft.getInstance().getConnection();
|
var conn = Minecraft.getInstance().getConnection();
|
||||||
if (conn != null) conn.send(ToggleAdvancedBlockingC2SPacket.INSTANCE);
|
if (conn != null) conn.send(ToggleAdvancedBlockingC2SPacket.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +97,6 @@ public abstract class PatternProviderScreenMixin<C extends PatternProviderMenu>
|
||||||
Settings.BLOCKING_MODE,
|
Settings.BLOCKING_MODE,
|
||||||
this.eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO,
|
this.eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO,
|
||||||
(btn, backwards) -> {
|
(btn, backwards) -> {
|
||||||
// debug removed
|
|
||||||
var conn = Minecraft.getInstance().getConnection();
|
var conn = Minecraft.getInstance().getConnection();
|
||||||
if (conn != null) conn.send(ToggleSmartDoublingC2SPacket.INSTANCE);
|
if (conn != null) conn.send(ToggleSmartDoublingC2SPacket.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import appeng.core.definitions.AEItems;
|
||||||
import appeng.helpers.IPatternTerminalMenuHost;
|
import appeng.helpers.IPatternTerminalMenuHost;
|
||||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||||
import appeng.menu.slot.RestrictedInputSlot;
|
import appeng.menu.slot.RestrictedInputSlot;
|
||||||
import appeng.parts.encoding.EncodingMode;
|
|
||||||
import com.extendedae_plus.client.PatternEncodingTermMenuMixinHelper;
|
import com.extendedae_plus.client.PatternEncodingTermMenuMixinHelper;
|
||||||
import com.extendedae_plus.config.ModConfig;
|
import com.extendedae_plus.config.ModConfig;
|
||||||
import com.extendedae_plus.mixin.ae2.accessor.MEStorageMenuAccessor;
|
import com.extendedae_plus.mixin.ae2.accessor.MEStorageMenuAccessor;
|
||||||
|
|
@ -19,6 +18,7 @@ import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.inventory.MenuType;
|
import net.minecraft.world.inventory.MenuType;
|
||||||
import net.neoforged.neoforge.network.PacketDistributor;
|
import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
|
@ -31,16 +31,14 @@ public abstract class PatternEncodingTermMenuMixin implements PatternEncodingTer
|
||||||
// 防止重复执行
|
// 防止重复执行
|
||||||
@Unique
|
@Unique
|
||||||
private boolean eap$blankAutoFilled = false;
|
private boolean eap$blankAutoFilled = false;
|
||||||
@Shadow
|
@Shadow @Final
|
||||||
private RestrictedInputSlot blankPatternSlot;
|
private RestrictedInputSlot blankPatternSlot;
|
||||||
@Shadow
|
|
||||||
public EncodingMode mode;
|
|
||||||
@Unique
|
@Unique
|
||||||
public boolean isShiftPressed = false;
|
public boolean eaep$isCtrlPressed = false;
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
public void eaep$setShiftPressed(boolean press) {
|
public void eaep$setCtrlPressed(boolean press) {
|
||||||
isShiftPressed = press;
|
eaep$isCtrlPressed = press;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
|
|
@ -165,8 +163,8 @@ public abstract class PatternEncodingTermMenuMixin implements PatternEncodingTer
|
||||||
@Inject(method = "encode", at = @At("TAIL"))
|
@Inject(method = "encode", at = @At("TAIL"))
|
||||||
private void eaep$onEncode(CallbackInfo ci) {
|
private void eaep$onEncode(CallbackInfo ci) {
|
||||||
if (ModConfig.INDEPENDENT_UPLOADING_BUTTON.getAsBoolean()) return;
|
if (ModConfig.INDEPENDENT_UPLOADING_BUTTON.getAsBoolean()) return;
|
||||||
if (!isShiftPressed) return;
|
if (!eaep$isCtrlPressed) return;
|
||||||
isShiftPressed = false;
|
eaep$isCtrlPressed = false;
|
||||||
var self = (PatternEncodingTermMenu) (Object) this;
|
var self = (PatternEncodingTermMenu) (Object) this;
|
||||||
PacketDistributor.sendToPlayer((ServerPlayer) self.getPlayer(), C2SPacketEncodeFinished.INSTANCE);
|
PacketDistributor.sendToPlayer((ServerPlayer) self.getPlayer(), C2SPacketEncodeFinished.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,26 +56,36 @@ public abstract class MixinBoMScreen {
|
||||||
if (isCraftingRecipe) {
|
if (isCraftingRecipe) {
|
||||||
PatternFillingHelper.encodeCraftingRecipe(menu,
|
PatternFillingHelper.encodeCraftingRecipe(menu,
|
||||||
node.recipe.getBackingRecipe(),
|
node.recipe.getBackingRecipe(),
|
||||||
HandlerBoMRecipes.updateRecipe(node.recipe, BoM.tree.batches,
|
HandlerBoMRecipes.updateRecipe(node.recipe,
|
||||||
HandlerBoMRecipes.collectInputs(node)),
|
HandlerBoMRecipes.collectInputs(node, 1)),
|
||||||
stack -> true);
|
stack -> true);
|
||||||
|
|
||||||
menu.encode();
|
menu.encode();
|
||||||
} else {
|
} else {
|
||||||
EmiStack nodeStack = node.ingredient.getEmiStacks().getFirst();
|
|
||||||
List<EmiStack> outputs = new ArrayList<>(node.recipe.getOutputs());
|
List<EmiStack> outputs = new ArrayList<>(node.recipe.getOutputs());
|
||||||
|
EmiStack nodeStack = outputs.get(outputs.indexOf(node.ingredient.getEmiStacks().getFirst()));
|
||||||
outputs.remove(nodeStack);
|
outputs.remove(nodeStack);
|
||||||
outputs.addFirst(nodeStack);
|
outputs.addFirst(nodeStack);
|
||||||
PatternFillingHelper.encodeProcessingRecipe(menu,
|
PatternFillingHelper.encodeProcessingRecipe(menu,
|
||||||
HandlerBoMRecipes.updateRecipe(node.recipe, BoM.tree.batches,
|
HandlerBoMRecipes.updateRecipe(node.recipe,
|
||||||
HandlerBoMRecipes.collectInputs(node)),
|
HandlerBoMRecipes.collectInputs(node, BoM.tree.batches)),
|
||||||
outputs.stream().map(EmiStackHelper::toGenericStack).toList());
|
outputs.stream()
|
||||||
|
.map(stack -> HandlerBoMRecipes.batchAmount(stack, BoM.tree.batches))
|
||||||
|
.map(EmiStackHelper::toGenericStack).toList());
|
||||||
|
|
||||||
menu.encode();
|
menu.encode();
|
||||||
|
|
||||||
String name = ExtendedAEPatternUploadUtil.mapRecipeTypeToSearchKey(node.recipe.getBackingRecipe().value());
|
ExtendedAEPatternUploadUtil.addLastProcessingNameList(
|
||||||
if (!(name == null || name.isBlank()))
|
node.recipe.getCategory().getName().getString());
|
||||||
ExtendedAEPatternUploadUtil.setLastProcessingName(name);
|
|
||||||
|
if (node.recipe.getBackingRecipe() != null) {
|
||||||
|
String name = ExtendedAEPatternUploadUtil.mapRecipeTypeToSearchKey(node.recipe.getBackingRecipe().value());
|
||||||
|
if (!(name == null || name.isBlank()))
|
||||||
|
ExtendedAEPatternUploadUtil.addLastProcessingNameList(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtendedAEPatternUploadUtil.addLastProcessingNameList(
|
||||||
|
node.recipe.getId().toString().split("/")[0]);
|
||||||
|
|
||||||
PacketDistributor.sendToServer(RequestProvidersListC2SPacket.INSTANCE);
|
PacketDistributor.sendToServer(RequestProvidersListC2SPacket.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,14 @@ public abstract class MixinEncodePatternTransfer {
|
||||||
// 对不起老牛😭
|
// 对不起老牛😭
|
||||||
if (recipe == null) return;
|
if (recipe == null) return;
|
||||||
if (EncodingHelper.isSupportedCraftingRecipe(recipe)) return;
|
if (EncodingHelper.isSupportedCraftingRecipe(recipe)) return;
|
||||||
|
|
||||||
String name = ExtendedAEPatternUploadUtil.mapRecipeTypeToSearchKey(recipe);
|
String name = ExtendedAEPatternUploadUtil.mapRecipeTypeToSearchKey(recipe);
|
||||||
if (name == null || name.isBlank()) return;
|
if (!(name == null || name.isBlank()))
|
||||||
ExtendedAEPatternUploadUtil.setLastProcessingName(name);
|
ExtendedAEPatternUploadUtil.addLastProcessingNameList(name);
|
||||||
|
|
||||||
|
ExtendedAEPatternUploadUtil.addLastProcessingNameList(emiRecipe.getCategory().getName().getString());
|
||||||
|
|
||||||
|
if (emiRecipe.getId() != null)
|
||||||
|
ExtendedAEPatternUploadUtil.addLastProcessingNameList(emiRecipe.getId().toString().split("/")[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.extendedae_plus.mixin.emi;
|
||||||
|
|
||||||
|
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||||
|
import dev.emi.emi.api.widget.RecipeFillButtonWidget;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
@Mixin(RecipeFillButtonWidget.class)
|
||||||
|
public class MixinRecipeFillButton {
|
||||||
|
@Inject(method = "mouseClicked", at = @At("RETURN"))
|
||||||
|
private static void eaep$onMouseClicked(int mouseX, int mouseY, int button,
|
||||||
|
CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
if (!cir.getReturnValue()) return;
|
||||||
|
Player player = Minecraft.getInstance().player;
|
||||||
|
if (player == null) return;
|
||||||
|
if (!(player.containerMenu instanceof PatternEncodingTermMenu menu)) return;
|
||||||
|
if (!Screen.hasControlDown()) return;
|
||||||
|
menu.encode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,8 +13,8 @@ import net.neoforged.neoforge.network.handling.IPayloadContext;
|
||||||
|
|
||||||
public record C2SPacketTargetKeyTriggered(KeyType keyType) implements CustomPacketPayload{
|
public record C2SPacketTargetKeyTriggered(KeyType keyType) implements CustomPacketPayload{
|
||||||
public enum KeyType {
|
public enum KeyType {
|
||||||
SHIFT_DOWN,
|
CTRL_DOWN,
|
||||||
SHIFT_UP
|
CTRL_UP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -36,9 +36,9 @@ public record C2SPacketTargetKeyTriggered(KeyType keyType) implements CustomPack
|
||||||
|
|
||||||
if (player.containerMenu instanceof PatternEncodingTermMenu patternMenu) {
|
if (player.containerMenu instanceof PatternEncodingTermMenu patternMenu) {
|
||||||
if (patternMenu instanceof PatternEncodingTermMenuMixinHelper accessor) {
|
if (patternMenu instanceof PatternEncodingTermMenuMixinHelper accessor) {
|
||||||
accessor.eaep$setShiftPressed(switch (packet.keyType) {
|
accessor.eaep$setCtrlPressed(switch (packet.keyType) {
|
||||||
case SHIFT_UP -> false;
|
case CTRL_UP -> false;
|
||||||
case SHIFT_DOWN -> true;
|
case CTRL_DOWN -> true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@ package com.extendedae_plus.network;
|
||||||
|
|
||||||
import com.extendedae_plus.ExtendedAEPlus;
|
import com.extendedae_plus.ExtendedAEPlus;
|
||||||
import com.extendedae_plus.client.ui.ProviderSelectScreen;
|
import com.extendedae_plus.client.ui.ProviderSelectScreen;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
|
import net.minecraft.network.codec.ByteBufCodecs;
|
||||||
import net.minecraft.network.codec.StreamCodec;
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
@ -11,49 +13,24 @@ import net.neoforged.api.distmarker.Dist;
|
||||||
import net.neoforged.api.distmarker.OnlyIn;
|
import net.neoforged.api.distmarker.OnlyIn;
|
||||||
import net.neoforged.neoforge.network.handling.IPayloadContext;
|
import net.neoforged.neoforge.network.handling.IPayloadContext;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* S2C: 返回可见且有空位的样板供应器列表,客户端弹窗展示供用户选择。
|
* S2C: 返回可见且有空位的样板供应器列表,客户端弹窗展示供用户选择。
|
||||||
*/
|
*/
|
||||||
public class ProvidersListS2CPacket implements CustomPacketPayload {
|
public record ProvidersListS2CPacket(List<Long> ids, List<String> names, List<String> i18nKeys,
|
||||||
|
List<Integer> emptySlots) implements CustomPacketPayload {
|
||||||
public static final Type<ProvidersListS2CPacket> TYPE = new Type<>(
|
public static final Type<ProvidersListS2CPacket> TYPE = new Type<>(
|
||||||
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "providers_list"));
|
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "providers_list"));
|
||||||
|
|
||||||
public static final StreamCodec<RegistryFriendlyByteBuf, ProvidersListS2CPacket> STREAM_CODEC = StreamCodec.of(
|
public static final StreamCodec<RegistryFriendlyByteBuf, ProvidersListS2CPacket> STREAM_CODEC = StreamCodec.composite(
|
||||||
(buf, pkt) -> {
|
ByteBufCodecs.fromCodec(Codec.list(Codec.LONG)), ProvidersListS2CPacket::ids,
|
||||||
buf.writeVarInt(pkt.ids.size());
|
ByteBufCodecs.fromCodec(Codec.list(Codec.STRING)), ProvidersListS2CPacket::names,
|
||||||
for (int i = 0; i < pkt.ids.size(); i++) {
|
ByteBufCodecs.fromCodec(Codec.list(Codec.STRING)), ProvidersListS2CPacket::i18nKeys,
|
||||||
buf.writeLong(pkt.ids.get(i));
|
ByteBufCodecs.fromCodec(Codec.list(Codec.INT)), ProvidersListS2CPacket::emptySlots,
|
||||||
buf.writeUtf(pkt.names.get(i));
|
ProvidersListS2CPacket::new
|
||||||
buf.writeVarInt(pkt.emptySlots.get(i));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
buf -> {
|
|
||||||
int size = buf.readVarInt();
|
|
||||||
List<Long> ids = new ArrayList<>(size);
|
|
||||||
List<String> names = new ArrayList<>(size);
|
|
||||||
List<Integer> slots = new ArrayList<>(size);
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
ids.add(buf.readLong());
|
|
||||||
names.add(buf.readUtf());
|
|
||||||
slots.add(buf.readVarInt());
|
|
||||||
}
|
|
||||||
return new ProvidersListS2CPacket(ids, names, slots);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
private final List<Long> ids;
|
|
||||||
private final List<String> names;
|
|
||||||
private final List<Integer> emptySlots;
|
|
||||||
|
|
||||||
public ProvidersListS2CPacket(List<Long> ids, List<String> names, List<Integer> emptySlots) {
|
|
||||||
this.ids = ids;
|
|
||||||
this.names = names;
|
|
||||||
this.emptySlots = emptySlots;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type<? extends CustomPacketPayload> type() {
|
public Type<? extends CustomPacketPayload> type() {
|
||||||
return TYPE;
|
return TYPE;
|
||||||
|
|
@ -66,8 +43,7 @@ public class ProvidersListS2CPacket implements CustomPacketPayload {
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
private static void handleClient(ProvidersListS2CPacket msg) {
|
private static void handleClient(ProvidersListS2CPacket msg) {
|
||||||
var mc = Minecraft.getInstance();
|
var mc = Minecraft.getInstance();
|
||||||
if (mc == null) return;
|
|
||||||
var current = mc.screen;
|
var current = mc.screen;
|
||||||
mc.setScreen(new ProviderSelectScreen(current, msg.ids, msg.names, msg.emptySlots));
|
mc.setScreen(new ProviderSelectScreen(current, msg.ids, msg.names, msg.i18nKeys, msg.emptySlots));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ public class RequestProvidersListC2SPacket implements CustomPacketPayload {
|
||||||
List<Long> ids = ExtendedAEPatternUploadUtil.getAllProviderIds(accessMenu);
|
List<Long> ids = ExtendedAEPatternUploadUtil.getAllProviderIds(accessMenu);
|
||||||
List<Long> filteredIds = new ArrayList<>();
|
List<Long> filteredIds = new ArrayList<>();
|
||||||
List<String> names = new ArrayList<>();
|
List<String> names = new ArrayList<>();
|
||||||
|
List<String> i18nKeys = new ArrayList<>();
|
||||||
List<Integer> slots = new ArrayList<>();
|
List<Integer> slots = new ArrayList<>();
|
||||||
|
|
||||||
for (Long id : ids) {
|
for (Long id : ids) {
|
||||||
|
|
@ -54,29 +55,31 @@ public class RequestProvidersListC2SPacket implements CustomPacketPayload {
|
||||||
if (empty <= 0) continue; // 只列出有空位的
|
if (empty <= 0) continue; // 只列出有空位的
|
||||||
filteredIds.add(id);
|
filteredIds.add(id);
|
||||||
names.add(ExtendedAEPatternUploadUtil.getProviderDisplayName(id, accessMenu));
|
names.add(ExtendedAEPatternUploadUtil.getProviderDisplayName(id, accessMenu));
|
||||||
|
i18nKeys.add(ExtendedAEPatternUploadUtil.getProviderI18nName(id, accessMenu));
|
||||||
slots.add(empty);
|
slots.add(empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
player.connection.send(new ProvidersListS2CPacket(filteredIds, names, slots));
|
player.connection.send(new ProvidersListS2CPacket(filteredIds, names, i18nKeys, slots));
|
||||||
return;
|
} else {
|
||||||
|
// 回退:基于编码终端所在网络枚举供应器,用“负数ID编码索引”:encodedId = -1 - index
|
||||||
|
List<PatternContainer> containers = ExtendedAEPatternUploadUtil.listAvailableProvidersFromGrid(encMenu);
|
||||||
|
List<Long> idxIds = new ArrayList<>();
|
||||||
|
List<String> names = new ArrayList<>();
|
||||||
|
List<String> i18nKeys = new ArrayList<>();
|
||||||
|
List<Integer> slots = new ArrayList<>();
|
||||||
|
for (int i = 0; i < containers.size(); i++) {
|
||||||
|
var c = containers.get(i);
|
||||||
|
if (c == null) continue;
|
||||||
|
int empty = ExtendedAEPatternUploadUtil.getAvailableSlots(c);
|
||||||
|
if (empty <= 0) continue;
|
||||||
|
long encodedId = -1L - i; // 约定:负数代表按索引
|
||||||
|
idxIds.add(encodedId);
|
||||||
|
names.add(ExtendedAEPatternUploadUtil.getProviderDisplayName(c));
|
||||||
|
i18nKeys.add(ExtendedAEPatternUploadUtil.getProviderI18nName(c));
|
||||||
|
slots.add(empty);
|
||||||
|
}
|
||||||
|
player.connection.send(new ProvidersListS2CPacket(idxIds, names, i18nKeys, slots));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回退:基于编码终端所在网络枚举供应器,用“负数ID编码索引”:encodedId = -1 - index
|
|
||||||
List<PatternContainer> containers = ExtendedAEPatternUploadUtil.listAvailableProvidersFromGrid(encMenu);
|
|
||||||
List<Long> idxIds = new ArrayList<>();
|
|
||||||
List<String> names = new ArrayList<>();
|
|
||||||
List<Integer> slots = new ArrayList<>();
|
|
||||||
for (int i = 0; i < containers.size(); i++) {
|
|
||||||
var c = containers.get(i);
|
|
||||||
if (c == null) continue;
|
|
||||||
int empty = ExtendedAEPatternUploadUtil.getAvailableSlots(c);
|
|
||||||
if (empty <= 0) continue;
|
|
||||||
long encodedId = -1L - i; // 约定:负数代表按索引
|
|
||||||
idxIds.add(encodedId);
|
|
||||||
names.add(ExtendedAEPatternUploadUtil.getProviderDisplayName(c));
|
|
||||||
slots.add(empty);
|
|
||||||
}
|
|
||||||
player.connection.send(new ProvidersListS2CPacket(idxIds, names, slots));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ExtendedAE扩展样板管理终端专用的样板上传工具类
|
* ExtendedAE扩展样板管理终端专用的样板上传工具类
|
||||||
|
|
@ -124,10 +125,10 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 最近一次通过 JEI 填充到编码终端的“处理配方”的中文名称(如:烧炼/高炉/烟熏...)
|
// 最近一次通过 JEI 填充到编码终端的“处理配方”的中文名称(如:烧炼/高炉/烟熏...)
|
||||||
public static volatile String lastProcessingName = null;
|
public static volatile List<String> lastProcessingNameList = new ArrayList<>();
|
||||||
|
|
||||||
public static void setLastProcessingName(String name) {
|
public static void addLastProcessingNameList(String name) {
|
||||||
lastProcessingName = name;
|
lastProcessingNameList.add(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -257,19 +258,14 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
String id = key.toString();
|
String id = key.toString();
|
||||||
String path = key.getPath();
|
String path = key.getPath();
|
||||||
// 常见原版类型映射
|
// 常见原版类型映射
|
||||||
switch (path) {
|
return switch (path) {
|
||||||
case "smelting":
|
case "smelting" -> "熔炉"; // 熔炉
|
||||||
return "熔炉"; // 熔炉
|
case "blasting" -> "高炉";
|
||||||
case "blasting":
|
case "smoking" -> "烟熏";
|
||||||
return "高炉";
|
case "campfire_cooking" -> "营火";
|
||||||
case "smoking":
|
// 其他模组类型,若未配置中文则返回原始ID(namespace:path)作为英文回退
|
||||||
return "烟熏";
|
default -> id;
|
||||||
case "campfire_cooking":
|
};
|
||||||
return "营火";
|
|
||||||
default:
|
|
||||||
// 其他模组类型,若未配置中文则返回原始ID(namespace:path)作为英文回退
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -283,13 +279,14 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
ResourceLocation key = BuiltInRegistries.RECIPE_TYPE.getKey(type);
|
ResourceLocation key = BuiltInRegistries.RECIPE_TYPE.getKey(type);
|
||||||
if (key == null) return null;
|
if (key == null) return null;
|
||||||
// 先查别名(按 path 匹配)
|
// 先查别名(按 path 匹配)
|
||||||
String alias = CUSTOM_ALIASES.get(key.getPath().toLowerCase());
|
// 别名替换放在init做, 提前别名的次序
|
||||||
if (alias != null && !alias.isBlank()) return alias;
|
// String alias = CUSTOM_ALIASES.get(key.getPath().toLowerCase());
|
||||||
|
// if (alias != null && !alias.isBlank()) return alias;
|
||||||
// 再查完整ID映射
|
// 再查完整ID映射
|
||||||
String custom = CUSTOM_NAMES.get(key);
|
// String custom = CUSTOM_NAMES.get(key);
|
||||||
if (custom != null && !custom.isBlank()) {
|
// if (custom != null && !custom.isBlank()) {
|
||||||
return custom;
|
// return custom;
|
||||||
}
|
// }
|
||||||
return key.getPath();
|
return key.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -370,6 +367,25 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String findMapping(String key) {
|
||||||
|
if (key == null || key.isBlank()) return null;
|
||||||
|
|
||||||
|
if (CUSTOM_ALIASES.containsKey(key.toLowerCase()))
|
||||||
|
return CUSTOM_ALIASES.get(key.toLowerCase());
|
||||||
|
|
||||||
|
if (key.contains(":")) {
|
||||||
|
try {
|
||||||
|
ResourceLocation location = ResourceLocation.tryParse(key);
|
||||||
|
if (location != null && CUSTOM_NAMES.containsKey(location))
|
||||||
|
return CUSTOM_NAMES.get(location);
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Pattern.matches(".*[:._/\\-].*", key)) return key;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取玩家当前的样板访问终端菜单(支持ExtendedAE和原版AE2)
|
* 获取玩家当前的样板访问终端菜单(支持ExtendedAE和原版AE2)
|
||||||
*
|
*
|
||||||
|
|
@ -471,8 +487,7 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
// 收集所有可用的装配矩阵(图样模块)内部库存并逐一尝试(遵循其过滤规则)
|
// 收集所有可用的装配矩阵(图样模块)内部库存并逐一尝试(遵循其过滤规则)
|
||||||
List<InternalInventory> inventories = findAllMatrixPatternInventories(grid);
|
List<InternalInventory> inventories = findAllMatrixPatternInventories(grid);
|
||||||
if (!inventories.isEmpty()) {
|
if (!inventories.isEmpty()) {
|
||||||
for (int i = 0; i < inventories.size(); i++) {
|
for (InternalInventory inv : inventories) {
|
||||||
var inv = inventories.get(i);
|
|
||||||
ItemStack toInsert = stack.copy();
|
ItemStack toInsert = stack.copy();
|
||||||
ItemStack remain = inv.addItems(toInsert);
|
ItemStack remain = inv.addItems(toInsert);
|
||||||
if (remain.getCount() < stack.getCount()) {
|
if (remain.getCount() < stack.getCount()) {
|
||||||
|
|
@ -491,8 +506,7 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
// 回退:尝试 Forge 能力(可能为聚合图样仓),同样遍历所有矩阵
|
// 回退:尝试 Forge 能力(可能为聚合图样仓),同样遍历所有矩阵
|
||||||
List<?> handlers = findAllMatrixPatternHandlers(grid);
|
List<?> handlers = findAllMatrixPatternHandlers(grid);
|
||||||
if (!handlers.isEmpty()) {
|
if (!handlers.isEmpty()) {
|
||||||
for (int i = 0; i < handlers.size(); i++) {
|
for (Object cap : handlers) {
|
||||||
var cap = handlers.get(i);
|
|
||||||
ItemStack toInsert = stack.copy();
|
ItemStack toInsert = stack.copy();
|
||||||
ItemStack remain = insertIntoAnySlot(cap, toInsert);
|
ItemStack remain = insertIntoAnySlot(cap, toInsert);
|
||||||
if (remain.getCount() < stack.getCount()) {
|
if (remain.getCount() < stack.getCount()) {
|
||||||
|
|
@ -871,6 +885,32 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
return "样板供应器 #" + providerId;
|
return "样板供应器 #" + providerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取供应器显示名(优先组名) */
|
||||||
|
public static String getProviderDisplayName(PatternContainer container) {
|
||||||
|
if (container == null) return "未知供应器";
|
||||||
|
try {
|
||||||
|
var group = container.getTerminalGroup();
|
||||||
|
if (group != null) return group.name().getString();
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
return "样板供应器";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getProviderI18nName(Long providerId, PatternAccessTermMenu menu) {
|
||||||
|
return getProviderI18nName(getPatternContainerById(menu, providerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取样板供应器默认选取的方块名称 */
|
||||||
|
public static String getProviderI18nName(PatternContainer container) {
|
||||||
|
if (container == null) return "";
|
||||||
|
try {
|
||||||
|
var group = container.getTerminalGroup();
|
||||||
|
var name = group.name();
|
||||||
|
return name.toString().contains("literal") ? "" : name.toString();
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证样板供应器是否可用
|
* 验证样板供应器是否可用
|
||||||
*
|
*
|
||||||
|
|
@ -1078,14 +1118,14 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
List<PatternContainer> list = new ArrayList<>();
|
List<PatternContainer> list = new ArrayList<>();
|
||||||
if (menu == null) return list;
|
if (menu == null) return list;
|
||||||
try {
|
try {
|
||||||
IGrid grid = null;
|
IGrid grid = null;
|
||||||
if (menu instanceof AEBaseMenu abm) {
|
if (menu instanceof AEBaseMenu abm) {
|
||||||
Object target = abm.getTarget();
|
Object target = abm.getTarget();
|
||||||
if (target instanceof IActionHost host && host.getActionableNode() != null) {
|
if (target instanceof IActionHost host && host.getActionableNode() != null) {
|
||||||
grid = host.getActionableNode().getGrid();
|
grid = host.getActionableNode().getGrid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (grid == null) return list;
|
||||||
if (grid == null) return list;
|
|
||||||
for (var machineClass : grid.getMachineClasses()) {
|
for (var machineClass : grid.getMachineClasses()) {
|
||||||
if (PatternContainer.class.isAssignableFrom(machineClass)) {
|
if (PatternContainer.class.isAssignableFrom(machineClass)) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
@ -1096,7 +1136,10 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
if (inv == null || inv.size() <= 0) continue;
|
if (inv == null || inv.size() <= 0) continue;
|
||||||
boolean hasEmpty = false;
|
boolean hasEmpty = false;
|
||||||
for (int i = 0; i < inv.size(); i++) {
|
for (int i = 0; i < inv.size(); i++) {
|
||||||
if (inv.getStackInSlot(i).isEmpty()) { hasEmpty = true; break; }
|
if (inv.getStackInSlot(i).isEmpty()) {
|
||||||
|
hasEmpty = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hasEmpty) list.add(container);
|
if (hasEmpty) list.add(container);
|
||||||
}
|
}
|
||||||
|
|
@ -1107,17 +1150,6 @@ public class ExtendedAEPatternUploadUtil {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取供应器显示名(优先组名) */
|
|
||||||
public static String getProviderDisplayName(PatternContainer container) {
|
|
||||||
if (container == null) return "未知供应器";
|
|
||||||
try {
|
|
||||||
var group = container.getTerminalGroup();
|
|
||||||
if (group != null) return group.name().getString();
|
|
||||||
} catch (Throwable ignored) {
|
|
||||||
}
|
|
||||||
return "样板供应器";
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 计算供应器空槽位数量 */
|
/** 计算供应器空槽位数量 */
|
||||||
public static int getAvailableSlots(PatternContainer container) {
|
public static int getAvailableSlots(PatternContainer container) {
|
||||||
if (container == null) return -1;
|
if (container == null) return -1;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ public class GetKey {
|
||||||
public static final String GUI = "gui";
|
public static final String GUI = "gui";
|
||||||
public static final String MESSAGE = "message";
|
public static final String MESSAGE = "message";
|
||||||
public static final String CONFIG = "config";
|
public static final String CONFIG = "config";
|
||||||
|
public static final String TOOLTIP = "tooltip";
|
||||||
|
|
||||||
public GetKey() {
|
public GetKey() {
|
||||||
this.keyType = "";
|
this.keyType = "";
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
"item.extendedae_plus.infinity_biginteger_cell": "§4吞§c噬§6万§e籁§a的§b寂§d静",
|
"item.extendedae_plus.infinity_biginteger_cell": "§4吞§c噬§6万§e籁§a的§b寂§d静",
|
||||||
"tooltip.extendedae_plus.infinity_biginteger_cell.summon1": "§6九重献祭, 终得虚空回响§r——觐见§8虚空之主Iava§r, 赐汝此物",
|
"tooltip.extendedae_plus.infinity_biginteger_cell.summon1": "§6九重献祭, 终得虚空回响§r——觐见§8虚空之主Iava§r, 赐汝此物",
|
||||||
"tooltip.extendedae_plus.infinity_biginteger_cell.summon2": "§b——§4方§d寸§c之§e间§a, §6自§b有§5千§9寰",
|
"tooltip.extendedae_plus.infinity_biginteger_cell.summon2": "§b——§4方§d寸§c之§e间§a, §6自§b有§5千§9寰",
|
||||||
|
"tooltip.extendedae_plus.encode_button_description": "\n§a[Shift] §7上传样板",
|
||||||
|
|
||||||
"config.jade.plugin_extendedae_plus.wireless_transceiver_info": "无线收发器信息",
|
"config.jade.plugin_extendedae_plus.wireless_transceiver_info": "无线收发器信息",
|
||||||
"config.jade.plugin_extendedae_plus.wt_frequency": "显示频率",
|
"config.jade.plugin_extendedae_plus.wt_frequency": "显示频率",
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
"ae2.menu.PatternProviderMenuAdvancedMixin",
|
"ae2.menu.PatternProviderMenuAdvancedMixin",
|
||||||
"ae2.menu.PatternProviderMenuDoublingMixin",
|
"ae2.menu.PatternProviderMenuDoublingMixin",
|
||||||
"emi.MixinEncodePatternTransfer",
|
"emi.MixinEncodePatternTransfer",
|
||||||
|
"emi.MixinRecipeFillButton",
|
||||||
"extendedae.common.PartExPatternProviderMixin",
|
"extendedae.common.PartExPatternProviderMixin",
|
||||||
"extendedae.common.TileExPatternProviderMixin",
|
"extendedae.common.TileExPatternProviderMixin",
|
||||||
"extendedae.container.ContainerExPatternProviderMixin",
|
"extendedae.container.ContainerExPatternProviderMixin",
|
||||||
|
|
@ -43,6 +44,7 @@
|
||||||
"ae2.accessor.PatternAccessTermScreenSlotsRowAccessor",
|
"ae2.accessor.PatternAccessTermScreenSlotsRowAccessor",
|
||||||
"ae2.client.gui.AEBaseScreenMixin",
|
"ae2.client.gui.AEBaseScreenMixin",
|
||||||
"ae2.client.gui.InterfaceScreenMixin",
|
"ae2.client.gui.InterfaceScreenMixin",
|
||||||
|
"ae2.client.gui.MixinActionButton",
|
||||||
"ae2.client.gui.PatternEncodingTermScreenMixin",
|
"ae2.client.gui.PatternEncodingTermScreenMixin",
|
||||||
"ae2.client.gui.PatternProviderCloseMixin",
|
"ae2.client.gui.PatternProviderCloseMixin",
|
||||||
"ae2.client.gui.PatternProviderScreenMixin",
|
"ae2.client.gui.PatternProviderScreenMixin",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user