优化样板生成逻辑
This commit is contained in:
parent
5b6642bbe4
commit
e7d9e02043
|
|
@ -21,8 +21,6 @@ import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.client.event.ScreenEvent;
|
import net.minecraftforge.client.event.ScreenEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -39,7 +37,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
*/
|
*/
|
||||||
@Mod.EventBusSubscriber(modid = ExtendedAEPlus.MODID, value = Dist.CLIENT)
|
@Mod.EventBusSubscriber(modid = ExtendedAEPlus.MODID, value = Dist.CLIENT)
|
||||||
public class CtrlQPatternKeyHandler {
|
public class CtrlQPatternKeyHandler {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger("ExtendedAE Plus - CtrlQKeyHandler");
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onScreenKeyPressed(ScreenEvent.KeyPressed event) {
|
public static void onScreenKeyPressed(ScreenEvent.KeyPressed event) {
|
||||||
|
|
@ -59,7 +56,6 @@ public class CtrlQPatternKeyHandler {
|
||||||
|
|
||||||
// JEI 必须可用
|
// JEI 必须可用
|
||||||
if (JeiRuntimeProxy.get() == null) {
|
if (JeiRuntimeProxy.get() == null) {
|
||||||
LOGGER.warn("[CtrlQKeyHandler] JEI not available");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,7 +63,6 @@ public class CtrlQPatternKeyHandler {
|
||||||
Optional<ITypedIngredient<?>> ingredient = JeiRuntimeProxy.getIngredientUnderMouse();
|
Optional<ITypedIngredient<?>> ingredient = JeiRuntimeProxy.getIngredientUnderMouse();
|
||||||
|
|
||||||
if (ingredient.isEmpty()) {
|
if (ingredient.isEmpty()) {
|
||||||
LOGGER.warn("[CtrlQKeyHandler] No ingredient under mouse");
|
|
||||||
Minecraft mc = Minecraft.getInstance();
|
Minecraft mc = Minecraft.getInstance();
|
||||||
if (mc.player != null) {
|
if (mc.player != null) {
|
||||||
mc.player.displayClientMessage(
|
mc.player.displayClientMessage(
|
||||||
|
|
@ -86,7 +81,6 @@ public class CtrlQPatternKeyHandler {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (recipes.isEmpty()) {
|
if (recipes.isEmpty()) {
|
||||||
LOGGER.warn("[CtrlQKeyHandler] No recipes found");
|
|
||||||
if (mc.player != null) {
|
if (mc.player != null) {
|
||||||
mc.player.displayClientMessage(
|
mc.player.displayClientMessage(
|
||||||
Component.translatable("message.extendedae_plus.no_recipes_found"),
|
Component.translatable("message.extendedae_plus.no_recipes_found"),
|
||||||
|
|
@ -99,7 +93,6 @@ public class CtrlQPatternKeyHandler {
|
||||||
// 自动选择最佳配方(优先CraftingRecipe)
|
// 自动选择最佳配方(优先CraftingRecipe)
|
||||||
Recipe<?> selectedRecipe = RecipeFinderUtil.selectBestRecipe(recipes);
|
Recipe<?> selectedRecipe = RecipeFinderUtil.selectBestRecipe(recipes);
|
||||||
if (selectedRecipe == null) {
|
if (selectedRecipe == null) {
|
||||||
LOGGER.error("[CtrlQKeyHandler] selectBestRecipe returned null");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
package com.extendedae_plus.network.pattern;
|
package com.extendedae_plus.network.pattern;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.extendedae_plus.util.wireless.WirelessTerminalLocator;
|
||||||
|
|
||||||
import appeng.api.crafting.PatternDetailsHelper;
|
import appeng.api.crafting.PatternDetailsHelper;
|
||||||
import appeng.api.networking.IGrid;
|
import appeng.api.networking.IGrid;
|
||||||
import appeng.api.networking.energy.IEnergyService;
|
import appeng.api.networking.energy.IEnergyService;
|
||||||
|
|
@ -11,7 +17,6 @@ import appeng.core.definitions.AEItems;
|
||||||
import appeng.items.tools.powered.WirelessCraftingTerminalItem;
|
import appeng.items.tools.powered.WirelessCraftingTerminalItem;
|
||||||
import appeng.items.tools.powered.WirelessTerminalItem;
|
import appeng.items.tools.powered.WirelessTerminalItem;
|
||||||
import appeng.me.helpers.PlayerSource;
|
import appeng.me.helpers.PlayerSource;
|
||||||
import com.extendedae_plus.util.wireless.WirelessTerminalLocator;
|
|
||||||
import de.mari_023.ae2wtlib.terminal.WTMenuHost;
|
import de.mari_023.ae2wtlib.terminal.WTMenuHost;
|
||||||
import de.mari_023.ae2wtlib.wut.WTDefinition;
|
import de.mari_023.ae2wtlib.wut.WTDefinition;
|
||||||
import de.mari_023.ae2wtlib.wut.WUTHandler;
|
import de.mari_023.ae2wtlib.wut.WUTHandler;
|
||||||
|
|
@ -26,14 +31,11 @@ import net.minecraft.world.item.crafting.Recipe;
|
||||||
import net.minecraft.world.item.crafting.RecipeManager;
|
import net.minecraft.world.item.crafting.RecipeManager;
|
||||||
import net.minecraftforge.network.NetworkEvent;
|
import net.minecraftforge.network.NetworkEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C2S: Ctrl+Q快速创建样板数据包
|
* C2S: Ctrl+Q快速创建样板数据包
|
||||||
*
|
*
|
||||||
* <p>从客户端发送配方ID和选择的材料到服务器,服务器消耗空白样板并创建编码样板掉落到玩家脚下</p>
|
* <p>
|
||||||
|
* 从客户端发送配方ID和选择的材料到服务器,服务器消耗空白样板并创建编码样板掉落到玩家脚下</p>
|
||||||
*/
|
*/
|
||||||
public class CreateCtrlQPatternC2SPacket {
|
public class CreateCtrlQPatternC2SPacket {
|
||||||
|
|
||||||
|
|
@ -75,15 +77,14 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 1. 验证配方存在
|
// 1. 验证配方存在
|
||||||
RecipeManager recipeManager = player.level().getRecipeManager();
|
RecipeManager recipeManager = player.level().getRecipeManager();
|
||||||
var recipeOpt = recipeManager.byKey(msg.recipeId);
|
var recipeOpt = recipeManager.byKey(msg.recipeId);
|
||||||
|
|
||||||
if (recipeOpt.isEmpty()) {
|
if (recipeOpt.isEmpty()) {
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.translatable("message.extendedae_plus.recipe_not_found"),
|
Component.translatable("message.extendedae_plus.recipe_not_found"),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -93,8 +94,8 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
// 2. 消耗空白样板
|
// 2. 消耗空白样板
|
||||||
if (!consumeBlankPattern(player)) {
|
if (!consumeBlankPattern(player)) {
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.translatable("message.extendedae_plus.no_blank_pattern"),
|
Component.translatable("message.extendedae_plus.no_blank_pattern"),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -106,26 +107,17 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
// 创建失败,退还空白样板
|
// 创建失败,退还空白样板
|
||||||
player.getInventory().add(AEItems.BLANK_PATTERN.stack());
|
player.getInventory().add(AEItems.BLANK_PATTERN.stack());
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.translatable("message.extendedae_plus.pattern_creation_failed"),
|
Component.translatable("message.extendedae_plus.pattern_creation_failed"),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 根据样板类型选择交付方式
|
// 4. 交付样板:优先放入背包,满了再掉落
|
||||||
if (msg.isCraftingPattern) {
|
if (!player.getInventory().add(pattern)) {
|
||||||
// 合成样板:始终掉落到玩家脚下
|
|
||||||
player.drop(pattern, false);
|
player.drop(pattern, false);
|
||||||
} else {
|
|
||||||
// 处理样板:优先放入背包,满了再掉落
|
|
||||||
boolean added = player.getInventory().add(pattern);
|
|
||||||
if (added) {
|
|
||||||
} else {
|
|
||||||
player.drop(pattern, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 移除成功消息(仅失败时提示)
|
|
||||||
});
|
});
|
||||||
ctx.setPacketHandled(true);
|
ctx.setPacketHandled(true);
|
||||||
}
|
}
|
||||||
|
|
@ -169,8 +161,8 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
return false; // 没有无线终端
|
return false; // 没有无线终端
|
||||||
}
|
}
|
||||||
|
|
||||||
IGrid grid = null;
|
IGrid grid;
|
||||||
boolean usedWtHost = false;
|
boolean usedWtHost;
|
||||||
|
|
||||||
// 若来自 Curios:优先通过 ae2wtlib 的 WTMenuHost 获取量子桥网络
|
// 若来自 Curios:优先通过 ae2wtlib 的 WTMenuHost 获取量子桥网络
|
||||||
String curiosSlotId = located.getCuriosSlotId();
|
String curiosSlotId = located.getCuriosSlotId();
|
||||||
|
|
@ -181,7 +173,8 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
String current = WUTHandler.getCurrentTerminal(terminal);
|
String current = WUTHandler.getCurrentTerminal(terminal);
|
||||||
WTDefinition def = WUTHandler.wirelessTerminals.get(current);
|
WTDefinition def = WUTHandler.wirelessTerminals.get(current);
|
||||||
if (def != null) {
|
if (def != null) {
|
||||||
WTMenuHost wtHost = def.wTMenuHostFactory().create(player, null, terminal, (p, sub) -> {});
|
WTMenuHost wtHost = def.wTMenuHostFactory().create(player, null, terminal, (p, sub) -> {
|
||||||
|
});
|
||||||
if (wtHost != null) {
|
if (wtHost != null) {
|
||||||
var node = wtHost.getActionableNode();
|
var node = wtHost.getActionableNode();
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
|
|
@ -217,6 +210,7 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
if (!wt.hasPower(player, 0.5, terminal)) {
|
if (!wt.hasPower(player, 0.5, terminal)) {
|
||||||
return false; // 能量不足
|
return false; // 能量不足
|
||||||
}
|
}
|
||||||
|
usedWtHost = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从网络提取空白样板
|
// 从网络提取空白样板
|
||||||
|
|
@ -225,11 +219,11 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
MEStorage storage = grid.getStorageService().getInventory();
|
MEStorage storage = grid.getStorageService().getInventory();
|
||||||
|
|
||||||
long extracted = StorageHelper.poweredExtraction(
|
long extracted = StorageHelper.poweredExtraction(
|
||||||
energy,
|
energy,
|
||||||
storage,
|
storage,
|
||||||
blankPatternKey,
|
blankPatternKey,
|
||||||
1, // 只提取1个
|
1, // 只提取1个
|
||||||
new PlayerSource(player)
|
new PlayerSource(player)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (extracted > 0) {
|
if (extracted > 0) {
|
||||||
|
|
@ -282,11 +276,11 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
// 使用 encodeCraftingPattern 创建合成样板
|
// 使用 encodeCraftingPattern 创建合成样板
|
||||||
// 直接传递 CraftingRecipe 对象而非 RecipeHolder
|
// 直接传递 CraftingRecipe 对象而非 RecipeHolder
|
||||||
ItemStack encodedPattern = PatternDetailsHelper.encodeCraftingPattern(
|
ItemStack encodedPattern = PatternDetailsHelper.encodeCraftingPattern(
|
||||||
craftingRecipe,
|
craftingRecipe,
|
||||||
inputs,
|
inputs,
|
||||||
output,
|
output,
|
||||||
true, // allowSubstitutes - 允许替代材料
|
true, // allowSubstitutes - 允许替代材料
|
||||||
false // allowFluidSubstitutes - 不允许流体替代
|
false // allowFluidSubstitutes - 不允许流体替代
|
||||||
);
|
);
|
||||||
|
|
||||||
// 添加编码玩家信息到NBT
|
// 添加编码玩家信息到NBT
|
||||||
|
|
@ -304,8 +298,8 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
for (ItemStack item : selectedIngredients) {
|
for (ItemStack item : selectedIngredients) {
|
||||||
if (!item.isEmpty()) {
|
if (!item.isEmpty()) {
|
||||||
inputs.add(new GenericStack(
|
inputs.add(new GenericStack(
|
||||||
AEItemKey.of(item),
|
AEItemKey.of(item),
|
||||||
item.getCount()
|
item.getCount()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -314,15 +308,15 @@ public class CreateCtrlQPatternC2SPacket {
|
||||||
ItemStack result = recipe.getResultItem(player.level().registryAccess());
|
ItemStack result = recipe.getResultItem(player.level().registryAccess());
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
outputs.add(new GenericStack(
|
outputs.add(new GenericStack(
|
||||||
AEItemKey.of(result),
|
AEItemKey.of(result),
|
||||||
result.getCount()
|
result.getCount()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 encodeProcessingPattern 创建处理样板
|
// 使用 encodeProcessingPattern 创建处理样板
|
||||||
ItemStack encodedPattern = PatternDetailsHelper.encodeProcessingPattern(
|
ItemStack encodedPattern = PatternDetailsHelper.encodeProcessingPattern(
|
||||||
inputs.toArray(new GenericStack[inputs.size()]),
|
inputs.toArray(new GenericStack[0]),
|
||||||
outputs.toArray(new GenericStack[outputs.size()])
|
outputs.toArray(new GenericStack[0])
|
||||||
);
|
);
|
||||||
|
|
||||||
// 添加编码玩家信息到NBT
|
// 添加编码玩家信息到NBT
|
||||||
|
|
|
||||||
|
|
@ -48,24 +48,19 @@ public class RecipeFinderUtil {
|
||||||
*/
|
*/
|
||||||
private static List<Recipe<?>> findRecipesByItem(ItemStack item, Level level) {
|
private static List<Recipe<?>> findRecipesByItem(ItemStack item, Level level) {
|
||||||
List<Recipe<?>> results = new ArrayList<>();
|
List<Recipe<?>> results = new ArrayList<>();
|
||||||
int totalRecipes = level.getRecipeManager().getRecipes().size();
|
|
||||||
|
|
||||||
// 1. 查找以该物品为输出的配方
|
// 1. 查找以该物品为输出的配方
|
||||||
int outputMatches = 0;
|
|
||||||
for (Recipe<?> recipe : level.getRecipeManager().getRecipes()) {
|
for (Recipe<?> recipe : level.getRecipeManager().getRecipes()) {
|
||||||
if (matchesOutput(recipe, item)) {
|
if (matchesOutput(recipe, item, level)) {
|
||||||
results.add(recipe);
|
results.add(recipe);
|
||||||
outputMatches++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 如果按住Shift,也查找以该物品为输入的配方
|
// 2. 如果按住Shift,也查找以该物品为输入的配方
|
||||||
if (Screen.hasShiftDown()) {
|
if (Screen.hasShiftDown()) {
|
||||||
int inputMatches = 0;
|
|
||||||
for (Recipe<?> recipe : level.getRecipeManager().getRecipes()) {
|
for (Recipe<?> recipe : level.getRecipeManager().getRecipes()) {
|
||||||
if (matchesInput(recipe, item) && !results.contains(recipe)) {
|
if (matchesInput(recipe, item) && !results.contains(recipe)) {
|
||||||
results.add(recipe);
|
results.add(recipe);
|
||||||
inputMatches++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,11 +102,13 @@ public class RecipeFinderUtil {
|
||||||
/**
|
/**
|
||||||
* 检查配方输出是否匹配目标物品
|
* 检查配方输出是否匹配目标物品
|
||||||
*/
|
*/
|
||||||
private static boolean matchesOutput(Recipe<?> recipe, ItemStack target) {
|
private static boolean matchesOutput(Recipe<?> recipe, ItemStack target, Level level) {
|
||||||
try {
|
try {
|
||||||
ItemStack result = recipe.getResultItem(null);
|
ItemStack result = recipe.getResultItem(level.registryAccess());
|
||||||
boolean matches = ItemStack.isSameItemSameTags(result, target);
|
if (result.isEmpty()) {
|
||||||
return matches;
|
return false;
|
||||||
|
}
|
||||||
|
return ItemStack.isSameItemSameTags(result, target);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.warn("[RecipeFinder] Exception in matchesOutput for recipe {}: {}", recipe.getId(), e.getMessage());
|
LOGGER.warn("[RecipeFinder] Exception in matchesOutput for recipe {}: {}", recipe.getId(), e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -123,9 +120,8 @@ public class RecipeFinderUtil {
|
||||||
*/
|
*/
|
||||||
private static boolean matchesInput(Recipe<?> recipe, ItemStack target) {
|
private static boolean matchesInput(Recipe<?> recipe, ItemStack target) {
|
||||||
try {
|
try {
|
||||||
boolean matches = recipe.getIngredients().stream()
|
return recipe.getIngredients().stream()
|
||||||
.anyMatch(ingredient -> ingredient.test(target));
|
.anyMatch(ingredient -> ingredient.test(target));
|
||||||
return matches;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.warn("[RecipeFinder] Exception in matchesInput for recipe {}: {}", recipe.getId(), e.getMessage());
|
LOGGER.warn("[RecipeFinder] Exception in matchesInput for recipe {}: {}", recipe.getId(), e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user