增加编码终端上传合成样板按钮
This commit is contained in:
parent
8923fe7a62
commit
4b243461cf
|
|
@ -0,0 +1,72 @@
|
|||
package com.extendedae_plus.mixin;
|
||||
|
||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||
import com.extendedae_plus.util.ExtendedAEPatternUploadUtil;
|
||||
import com.glodblock.github.glodium.network.packet.sync.IActionHolder;
|
||||
import com.glodblock.github.glodium.network.packet.sync.Paras;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
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 java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 给 AE2 的 PatternEncodingTermMenu 增加一个通用动作持有者,实现接收 EPP 的 CGenericPacket 动作。
|
||||
* 注册动作 "upload_to_matrix":仅上传“合成图样”到 ExtendedAE 装配矩阵。
|
||||
*/
|
||||
@Mixin(PatternEncodingTermMenu.class)
|
||||
public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHolder {
|
||||
|
||||
@Unique
|
||||
private final Map<String, Consumer<Paras>> actions = createHolder();
|
||||
|
||||
@Unique
|
||||
private Player epp$player;
|
||||
|
||||
// AE2 终端主构造:PatternEncodingTermMenu(int id, Inventory ip, IPatternTerminalMenuHost host)
|
||||
@Inject(method = "<init>(ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/IPatternTerminalMenuHost;)V", at = @At("TAIL"), remap = false)
|
||||
private void epp$ctorA(int id, net.minecraft.world.entity.player.Inventory ip, appeng.helpers.IPatternTerminalMenuHost host, CallbackInfo ci) {
|
||||
this.epp$player = ip.player;
|
||||
// 注册动作:无参,由服务端直接读 encoded 槽位。
|
||||
System.out.println("[EAE+][Server] Register action 'upload_to_matrix' for PatternEncodingTermMenu ctorA");
|
||||
this.actions.put("upload_to_matrix", p -> {
|
||||
try {
|
||||
var sp = (ServerPlayer) this.epp$player;
|
||||
System.out.println("[EAE+][Server] Handle action 'upload_to_matrix' from " + sp.getGameProfile().getName());
|
||||
ExtendedAEPatternUploadUtil.uploadFromEncodingMenuToMatrix(sp, (PatternEncodingTermMenu) (Object) this);
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Server] Exception in 'upload_to_matrix': " + t);
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// AE2 另一个构造:PatternEncodingTermMenu(MenuType, int, Inventory, IPatternTerminalMenuHost, boolean)
|
||||
@Inject(method = "<init>(Lnet/minecraft/world/inventory/MenuType;ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/IPatternTerminalMenuHost;Z)V", at = @At("TAIL"), remap = false)
|
||||
private void epp$ctorB(net.minecraft.world.inventory.MenuType<?> menuType, int id, net.minecraft.world.entity.player.Inventory ip, appeng.helpers.IPatternTerminalMenuHost host, boolean bindInventory, CallbackInfo ci) {
|
||||
this.epp$player = ip.player;
|
||||
System.out.println("[EAE+][Server] Register action 'upload_to_matrix' for PatternEncodingTermMenu ctorB");
|
||||
this.actions.put("upload_to_matrix", p -> {
|
||||
try {
|
||||
var sp = (ServerPlayer) this.epp$player;
|
||||
System.out.println("[EAE+][Server] Handle action 'upload_to_matrix' from " + sp.getGameProfile().getName());
|
||||
ExtendedAEPatternUploadUtil.uploadFromEncodingMenuToMatrix(sp, (PatternEncodingTermMenu) (Object) this);
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Server] Exception in 'upload_to_matrix': " + t);
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Consumer<Paras>> getActionMap() {
|
||||
return this.actions;
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ public abstract class ContainerUWirelessExPatternTerminalMixin implements IActio
|
|||
private Player epp$player;
|
||||
|
||||
// 明确目标构造签名:<init>(int, Inventory, HostUWirelessExPAT)
|
||||
@Inject(method = "<init>(ILnet/minecraft/world/entity/player/Inventory;Lcom/glodblock/github/extendedae/xmod/wt/HostUWirelessExPAT;)V", at = @At("TAIL"))
|
||||
@Inject(method = "<init>(ILnet/minecraft/world/entity/player/Inventory;Lcom/glodblock/github/extendedae/xmod/wt/HostUWirelessExPAT;)V", at = @At("TAIL"), remap = false)
|
||||
private void init(int id, net.minecraft.world.entity.player.Inventory playerInventory, HostUWirelessExPAT host, CallbackInfo ci) {
|
||||
this.epp$player = playerInventory.player;
|
||||
// 注册上传动作:参数顺序必须与客户端 CGenericPacket 保持一致
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
package com.extendedae_plus.mixin;
|
||||
|
||||
import com.extendedae_plus.mixin.accessor.AEBaseScreenAccessor;
|
||||
import appeng.client.gui.me.items.PatternEncodingTermScreen;
|
||||
import appeng.client.gui.widgets.IconButton;
|
||||
import appeng.client.gui.Icon;
|
||||
import appeng.client.gui.style.ScreenStyle;
|
||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
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 com.glodblock.github.extendedae.network.EPPNetworkHandler;
|
||||
import com.glodblock.github.glodium.network.packet.CGenericPacket;
|
||||
|
||||
/**
|
||||
* 在 AE2 的 PatternEncodingTermScreen 界面中,给编码按钮旁添加一个“上传到矩阵”按钮。
|
||||
* 客户端点击后,使用 ExtendedAE 的网络通道发送通用数据包到服务端,由容器 Mixin 处理。
|
||||
*/
|
||||
@Mixin(PatternEncodingTermScreen.class)
|
||||
public abstract class GuiPatternEncodingTermMixin<C extends PatternEncodingTermMenu> {
|
||||
|
||||
@Unique
|
||||
private IconButton epp$uploadButton;
|
||||
|
||||
// 通过 Accessor 调用 AEBaseScreen#addToLeftToolbar
|
||||
|
||||
// 在构造函数尾部创建按钮实例(仅创建,不添加)
|
||||
@Inject(method = "<init>", at = @At("TAIL"), remap = false)
|
||||
private void epp$onInit(C menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
|
||||
// 选择一个合适的图标占位(AE2 暂无显式“上传”图标,这里先用 PATTERN_ACCESS_SHOW)
|
||||
this.epp$uploadButton = new IconButton(b -> {
|
||||
// 直接发送无参动作,服务端容器会根据当前 encoded 槽位处理
|
||||
System.out.println("[EAE+][Client] Click upload button -> send CGenericPacket('upload_to_matrix')");
|
||||
try {
|
||||
var mc = net.minecraft.client.Minecraft.getInstance();
|
||||
var cm = mc.player != null ? mc.player.containerMenu : null;
|
||||
System.out.println("[EAE+][Client] Current container: " + (cm == null ? "null" : cm.getClass().getName()));
|
||||
if (cm instanceof com.glodblock.github.glodium.network.packet.sync.IActionHolder ah) {
|
||||
var keys = ah.getActionMap().keySet();
|
||||
System.out.println("[EAE+][Client] IActionHolder detected. actions=" + keys);
|
||||
} else {
|
||||
System.out.println("[EAE+][Client] Current container is NOT IActionHolder");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Client] Inspect container failed: " + t);
|
||||
}
|
||||
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("upload_to_matrix"));
|
||||
}) {
|
||||
@Override
|
||||
protected Icon getIcon() {
|
||||
return Icon.PATTERN_ACCESS_SHOW;
|
||||
}
|
||||
};
|
||||
this.epp$uploadButton.setTooltip(Tooltip.create(Component.translatable("extendedae_plus.upload_to_matrix")));
|
||||
System.out.println("[EAE+][Client] Created upload button in PatternEncodingTermScreen ctor tail");
|
||||
// 直接在构造尾部加入左侧工具栏,避免目标类未覆写 init 导致的注入不到
|
||||
((AEBaseScreenAccessor) (Object) this).epp$addToLeftToolbar(this.epp$uploadButton);
|
||||
System.out.println("[EAE+][Client] Added upload button to left toolbar in ctor tail");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.extendedae_plus.mixin.accessor;
|
||||
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
import appeng.client.gui.AEBaseScreen;
|
||||
|
||||
@Mixin(AEBaseScreen.class)
|
||||
public interface AEBaseScreenAccessor {
|
||||
@Invoker(value = "addToLeftToolbar", remap = false)
|
||||
<B extends Button> B epp$addToLeftToolbar(B button);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.extendedae_plus.mixin.accessor;
|
||||
|
||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||
import appeng.menu.slot.RestrictedInputSlot;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(PatternEncodingTermMenu.class)
|
||||
public interface PatternEncodingTermMenuAccessor {
|
||||
@Accessor("encodedPatternSlot")
|
||||
RestrictedInputSlot epp$getEncodedPatternSlot();
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.extendedae_plus.util;
|
|||
|
||||
import appeng.api.inventories.InternalInventory;
|
||||
import appeng.api.crafting.PatternDetailsHelper;
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.helpers.patternprovider.PatternContainer;
|
||||
import appeng.menu.implementations.PatternAccessTermMenu;
|
||||
import appeng.util.inv.FilteredInternalInventory;
|
||||
|
|
@ -12,6 +14,14 @@ import net.minecraft.network.chat.Component;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||
import appeng.api.crafting.IPatternDetails;
|
||||
import appeng.crafting.pattern.AECraftingPattern;
|
||||
import com.glodblock.github.extendedae.common.tileentities.matrix.TileAssemblerMatrixBase;
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
/**
|
||||
* ExtendedAE扩展样板管理终端专用的样板上传工具类
|
||||
|
|
@ -29,22 +39,180 @@ public class ExtendedAEPatternUploadUtil {
|
|||
if (player == null || player.containerMenu == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 优先检查ExtendedAE的扩展样板管理终端(使用类名检查避免直接导入)
|
||||
String containerClassName = player.containerMenu.getClass().getName();
|
||||
if (containerClassName.equals("com.glodblock.github.extendedae.container.ContainerExPatternTerminal")) {
|
||||
// ExtendedAE的容器继承自PatternAccessTermMenu,可以安全转换
|
||||
return (PatternAccessTermMenu) player.containerMenu;
|
||||
}
|
||||
|
||||
// 兼容原版AE2的样板访问终端
|
||||
if (player.containerMenu instanceof PatternAccessTermMenu) {
|
||||
return (PatternAccessTermMenu) player.containerMenu;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 AE2 的图样编码终端菜单上传当前“已编码图样”至 ExtendedAE 装配矩阵(仅合成图样)。
|
||||
* 不会处理“处理图样”。
|
||||
*
|
||||
* @param player 服务器玩家
|
||||
* @param menu PatternEncodingTermMenu
|
||||
* @return 是否成功插入矩阵
|
||||
*/
|
||||
public static boolean uploadFromEncodingMenuToMatrix(ServerPlayer player, PatternEncodingTermMenu menu) {
|
||||
if (player == null || menu == null) {
|
||||
System.out.println("[EAE+][Server] uploadFromEncodingMenuToMatrix: player or menu is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 读取已编码槽位的物品
|
||||
var encodedSlot = ((com.extendedae_plus.mixin.accessor.PatternEncodingTermMenuAccessor) (Object) menu)
|
||||
.epp$getEncodedPatternSlot();
|
||||
ItemStack stack = encodedSlot.getItem();
|
||||
System.out.println("[EAE+][Server] Encoded slot stack: " + stack + ", count=" + stack.getCount());
|
||||
if (stack.isEmpty() || !PatternDetailsHelper.isEncodedPattern(stack)) {
|
||||
sendMessage(player, "ExtendedAE Plus: 没有可上传的编码样板");
|
||||
System.out.println("[EAE+][Server] Fail: stack empty or not encoded pattern");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 仅允许“合成图样”
|
||||
IPatternDetails details = PatternDetailsHelper.decodePattern(stack, player.level());
|
||||
System.out.println("[EAE+][Server] Decoded details: " + (details == null ? "null" : details.getClass().getName()));
|
||||
if (!(details instanceof AECraftingPattern)) {
|
||||
sendMessage(player, "extendedae_plus.upload_to_matrix.fail_not_crafting");
|
||||
System.out.println("[EAE+][Server] Fail: not AECraftingPattern");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取 AE 网络
|
||||
IGridNode node = menu.getNetworkNode();
|
||||
System.out.println("[EAE+][Server] Grid node: " + node);
|
||||
if (node == null) {
|
||||
sendMessage(player, "ExtendedAE Plus: 当前不在有效的 AE 网络中");
|
||||
System.out.println("[EAE+][Server] Fail: grid node null");
|
||||
return false;
|
||||
}
|
||||
IGrid grid = node.getGrid();
|
||||
System.out.println("[EAE+][Server] Grid: " + grid);
|
||||
if (grid == null) {
|
||||
sendMessage(player, "ExtendedAE Plus: 当前不在有效的 AE 网络中");
|
||||
System.out.println("[EAE+][Server] Fail: grid null");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查找已成型的装配矩阵(图样模块)的内部库存(优先使用内部库存,其带有正确过滤逻辑)
|
||||
InternalInventory matrixInv = findFirstMatrixPatternInventory(grid);
|
||||
System.out.println("[EAE+][Server] Matrix internal inventory: " + matrixInv);
|
||||
if (matrixInv == null) {
|
||||
// 回退:尝试 Forge 能力(旧实现)
|
||||
IItemHandler cap = findFirstMatrixPatternHandler(grid);
|
||||
System.out.println("[EAE+][Server] Fallback Matrix item handler: " + cap);
|
||||
if (cap == null) {
|
||||
sendMessage(player, "extendedae_plus.upload_to_matrix.fail_no_matrix");
|
||||
System.out.println("[EAE+][Server] Fail: no formed matrix found");
|
||||
return false;
|
||||
}
|
||||
// 使用能力插入
|
||||
ItemStack toInsert = stack.copy();
|
||||
System.out.println("[EAE+][Server] Try insert via capability, count=" + toInsert.getCount());
|
||||
ItemStack remain = insertIntoAnySlot(cap, toInsert);
|
||||
System.out.println("[EAE+][Server] Insert remain count=" + remain.getCount());
|
||||
if (remain.getCount() < stack.getCount()) {
|
||||
int inserted = stack.getCount() - remain.getCount();
|
||||
stack.shrink(inserted);
|
||||
if (stack.isEmpty()) {
|
||||
encodedSlot.set(ItemStack.EMPTY);
|
||||
}
|
||||
sendMessage(player, "extendedae_plus.upload_to_matrix.success");
|
||||
System.out.println("[EAE+][Server] Success via capability: inserted=" + inserted);
|
||||
return true;
|
||||
} else {
|
||||
sendMessage(player, "extendedae_plus.upload_to_matrix.fail_full");
|
||||
System.out.println("[EAE+][Server] Fail via capability: inventory full or cannot accept pattern");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 通过内部库存插入(遵循其过滤规则)
|
||||
ItemStack toInsert = stack.copy();
|
||||
System.out.println("[EAE+][Server] Try insert via internal inventory, count=" + toInsert.getCount());
|
||||
ItemStack remain = matrixInv.addItems(toInsert);
|
||||
System.out.println("[EAE+][Server] Internal inventory remain count=" + remain.getCount());
|
||||
if (remain.getCount() < stack.getCount()) {
|
||||
// 扣除插入数量
|
||||
int inserted = stack.getCount() - remain.getCount();
|
||||
stack.shrink(inserted);
|
||||
if (stack.isEmpty()) {
|
||||
encodedSlot.set(ItemStack.EMPTY);
|
||||
}
|
||||
sendMessage(player, "extendedae_plus.upload_to_matrix.success");
|
||||
System.out.println("[EAE+][Server] Success via internal inventory: inserted=" + inserted);
|
||||
return true;
|
||||
} else {
|
||||
sendMessage(player, "extendedae_plus.upload_to_matrix.fail_full");
|
||||
System.out.println("[EAE+][Server] Fail via internal inventory: inventory full or cannot accept pattern");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在给定 AE Grid 中查找第一台已成型且在线的装配矩阵“图样模块”,并返回其用于外部插入的内部库存。
|
||||
* 优先使用 TileAssemblerMatrixPattern#getExposedInventory(仅允许插入,且已带AE过滤规则)。
|
||||
*/
|
||||
private static InternalInventory findFirstMatrixPatternInventory(IGrid grid) {
|
||||
try {
|
||||
var tiles = grid.getMachines(com.glodblock.github.extendedae.common.tileentities.matrix.TileAssemblerMatrixPattern.class);
|
||||
for (com.glodblock.github.extendedae.common.tileentities.matrix.TileAssemblerMatrixPattern tile : tiles) {
|
||||
if (tile != null && tile.isFormed() && tile.getMainNode().isActive()) {
|
||||
var inv = tile.getExposedInventory();
|
||||
if (inv != null) {
|
||||
return inv;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.out.println("[EAE+][Server] findFirstMatrixPatternInventory exception: " + t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在给定 AE Grid 中查找第一台已成型的装配矩阵,并返回其聚合图样仓的 IItemHandler。
|
||||
*/
|
||||
private static IItemHandler findFirstMatrixPatternHandler(IGrid grid) {
|
||||
try {
|
||||
Set<TileAssemblerMatrixBase> matrices = grid.getMachines(TileAssemblerMatrixBase.class);
|
||||
for (TileAssemblerMatrixBase tile : matrices) {
|
||||
if (tile != null && tile.isFormed()) {
|
||||
var capOpt = tile.getCapability(ForgeCapabilities.ITEM_HANDLER, null);
|
||||
if (capOpt != null) {
|
||||
var handler = capOpt.orElse(null);
|
||||
if (handler != null) {
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试将整个物品栈插入到 IItemHandler 的任意槽位,返回剩余物品。
|
||||
*/
|
||||
private static ItemStack insertIntoAnySlot(IItemHandler handler, ItemStack stack) {
|
||||
ItemStack remaining = stack.copy();
|
||||
if (handler == null || remaining.isEmpty()) return remaining;
|
||||
for (int i = 0; i < handler.getSlots(); i++) {
|
||||
remaining = handler.insertItem(i, remaining, false);
|
||||
if (remaining.isEmpty()) break;
|
||||
}
|
||||
return remaining;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前菜单是否为ExtendedAE的扩展样板管理终端
|
||||
*
|
||||
|
|
|
|||
|
|
@ -5,5 +5,10 @@
|
|||
"gui.expatternprovider.clear_selection": "取消选择",
|
||||
"block.extendedae_plus.wireless_transceiver": "无线收发器",
|
||||
"item.extendedae_plus.wireless_transceiver": "无线收发器",
|
||||
"itemGroup.extendedae_plus.main": "扩展AE Plus"
|
||||
"itemGroup.extendedae_plus.main": "扩展AE Plus",
|
||||
"extendedae_plus.upload_to_matrix": "上传到装配矩阵",
|
||||
"extendedae_plus.upload_to_matrix.success": "样板已上传到装配矩阵",
|
||||
"extendedae_plus.upload_to_matrix.fail_not_crafting": "仅支持上传合成样板,处理样板将被忽略",
|
||||
"extendedae_plus.upload_to_matrix.fail_no_matrix": "未在当前网络中找到已成型的装配矩阵",
|
||||
"extendedae_plus.upload_to_matrix.fail_full": "装配矩阵的样板仓已满或无法插入"
|
||||
}
|
||||
|
|
@ -7,7 +7,9 @@
|
|||
"GuiExPatternProviderMixin",
|
||||
"SlotGridLayoutMixin",
|
||||
"GuiExPatternTerminalMixin",
|
||||
"HighlightButtonMixin"
|
||||
"HighlightButtonMixin",
|
||||
"GuiPatternEncodingTermMixin",
|
||||
"accessor.AEBaseScreenAccessor"
|
||||
],
|
||||
"mixins": [
|
||||
"ContainerExPatternProviderMixin",
|
||||
|
|
@ -16,8 +18,9 @@
|
|||
"ContainerUWirelessExPatternTerminalMixin",
|
||||
"TileExPatternProviderMixin",
|
||||
"PartExPatternProviderMixin",
|
||||
"PatternEncodingTermMenuMixin",
|
||||
"accessor.MEStorageMenuAccessor"
|
||||
"ContainerPatternEncodingTermMenuMixin",
|
||||
"accessor.MEStorageMenuAccessor",
|
||||
"accessor.PatternEncodingTermMenuAccessor"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user