feat: 添加内存卡对实体加速器、实体加速卡的复制粘贴支持
This commit is contained in:
parent
d61a418731
commit
869ab98af4
|
|
@ -0,0 +1,41 @@
|
|||
package com.extendedae_plus.ae.api.config;
|
||||
|
||||
import appeng.api.config.Setting;
|
||||
import appeng.api.config.YesNo;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class Settings {
|
||||
private static final Map<String, Setting<?>> SETTINGS = new HashMap<>();
|
||||
public static final Setting<YesNo> ACCELERATE = register("accelerate", YesNo.NO, YesNo.YES);
|
||||
|
||||
|
||||
private Settings() {
|
||||
}
|
||||
|
||||
private synchronized static <T extends Enum<T>> Setting<T> register(String name, Class<T> enumClass) {
|
||||
Preconditions.checkState(!SETTINGS.containsKey(name));
|
||||
var setting = new Setting<>(name, enumClass);
|
||||
SETTINGS.put(name, setting);
|
||||
return setting;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private synchronized static <T extends Enum<T>> Setting<T> register(String name, T firstOption, T... moreOptions) {
|
||||
Preconditions.checkState(!SETTINGS.containsKey(name));
|
||||
var setting = new Setting<T>(name, firstOption.getDeclaringClass(), EnumSet.of(firstOption, moreOptions));
|
||||
SETTINGS.put(name, setting);
|
||||
return setting;
|
||||
}
|
||||
|
||||
public static Setting<?> getOrThrow(String name) {
|
||||
var setting = SETTINGS.get(name);
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Unknown setting '" + name + "'");
|
||||
}
|
||||
return setting;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import com.extendedae_plus.util.entitySpeed.ConfigParsingUtils;
|
|||
import com.extendedae_plus.util.entitySpeed.PowerUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart
|
|||
* @param slot 发生变化的槽位
|
||||
*/
|
||||
@Override
|
||||
public void onSlotChange(net.minecraft.world.inventory.Slot slot) {
|
||||
public void onSlotChange(Slot slot) {
|
||||
super.onSlotChange(slot);
|
||||
if (isClientSide()) {
|
||||
updateCardCounts();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.extendedae_plus.ae.parts;
|
|||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.PowerMultiplier;
|
||||
import appeng.api.config.YesNo;
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.networking.energy.IEnergyService;
|
||||
|
|
@ -62,7 +63,6 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
|
|||
public static final PartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, new ResourceLocation(ExtendedAEPlus.MODID, "part/entity_speed_ticker_has_channel"));
|
||||
|
||||
public EntitySpeedTickerMenu menu; // 当前打开的菜单实例
|
||||
private boolean accelerateEnabled = true; // 是否启用加速
|
||||
private boolean networkEnergySufficient = true; // 网络能量是否充足
|
||||
|
||||
/**
|
||||
|
|
@ -75,14 +75,16 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
|
|||
.setFlags(GridFlags.REQUIRE_CHANNEL)
|
||||
.setIdlePowerUsage(1)
|
||||
.addService(IGridTickable.class, this);
|
||||
|
||||
// 注册可记忆的配置(YES/NO)
|
||||
this.getConfigManager().registerSetting(
|
||||
com.extendedae_plus.ae.api.config.Settings.ACCELERATE,
|
||||
YesNo.YES
|
||||
);
|
||||
}
|
||||
|
||||
public boolean getAccelerateEnabled() {
|
||||
return this.accelerateEnabled;
|
||||
}
|
||||
|
||||
public boolean isNetworkEnergySufficient() {
|
||||
return this.networkEnergySufficient;
|
||||
return this.getConfigManager().getSetting(com.extendedae_plus.ae.api.config.Settings.ACCELERATE) == YesNo.YES;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -90,12 +92,17 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
|
|||
* @param enabled 是否启用加速
|
||||
*/
|
||||
public void setAccelerateEnabled(boolean enabled) {
|
||||
this.accelerateEnabled = enabled;
|
||||
this.getConfigManager().putSetting(com.extendedae_plus.ae.api.config.Settings.ACCELERATE, enabled ? YesNo.YES : YesNo.NO);
|
||||
// 是否启用加速
|
||||
if (menu != null) {
|
||||
menu.setAccelerateEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNetworkEnergySufficient() {
|
||||
return this.networkEnergySufficient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新网络能量充足状态并通知菜单。
|
||||
* @param sufficient 是否能量充足
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ import java.util.Map;
|
|||
* 实体加速器界面,显示加速状态、卡数量、能耗和倍率信息。
|
||||
*/
|
||||
public class EntitySpeedTickerScreen<C extends EntitySpeedTickerMenu> extends UpgradeableScreen<C> {
|
||||
private boolean eap$entitySpeedTickerEnabled = false; // 本地缓存的加速开关状态
|
||||
private final SettingToggleButton<YesNo> eap$entitySpeedTickerToggle; // 加速开关按钮
|
||||
private boolean eap$entitySpeedTickerEnabled = false; // 本地缓存的加速开关状态
|
||||
private final SettingToggleButton<YesNo> eap$entitySpeedTickerToggle; // 加速开关按钮
|
||||
|
||||
/**
|
||||
* 构造函数,初始化界面和控件。
|
||||
|
|
|
|||
|
|
@ -6,14 +6,8 @@ import appeng.core.definitions.AEItems;
|
|||
import appeng.core.definitions.AEParts;
|
||||
import appeng.core.localization.GuiText;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.EX_PATTERN_PROVIDER;
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.EX_PATTERN_PROVIDER_PART;
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.EX_INTERFACE;
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.EX_INTERFACE_PART;
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.OVERSIZE_INTERFACE;
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.OVERSIZE_INTERFACE_PART;
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.EX_IMPORT_BUS;
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.EX_EXPORT_BUS;
|
||||
|
||||
import static com.glodblock.github.extendedae.common.EPPItemAndBlock.*;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,223 @@
|
|||
package com.extendedae_plus.mixin.ae2.items;
|
||||
|
||||
import appeng.api.inventories.InternalInventory;
|
||||
import appeng.api.upgrades.IUpgradeableObject;
|
||||
import appeng.core.localization.PlayerMessages;
|
||||
import appeng.items.tools.MemoryCardItem;
|
||||
import appeng.items.tools.NetworkToolItem;
|
||||
import appeng.util.inv.PlayerInternalInventory;
|
||||
import com.extendedae_plus.ae.parts.EntitySpeedTickerPart;
|
||||
import com.extendedae_plus.init.ModItems;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
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.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Mixin(value = MemoryCardItem.class, remap = false)
|
||||
public class MemoryCardItemMixin {
|
||||
|
||||
/**
|
||||
* 写入 Memory Card 时保留实体加速卡的完整 NBT 数据
|
||||
*/
|
||||
@Inject(method = "storeUpgrades", at = @At("HEAD"), cancellable = true)
|
||||
private static void storeUpgradesCustom(IUpgradeableObject upgradeableObject, CompoundTag output, CallbackInfo ci) {
|
||||
try {
|
||||
CompoundTag desiredUpgradesTag = new CompoundTag();
|
||||
ListTag entitySpeedCards = new ListTag();
|
||||
InternalInventory upgrades = upgradeableObject.getUpgrades();
|
||||
|
||||
for (int i = 0; i < upgrades.size(); i++) {
|
||||
ItemStack upgradeStack = upgrades.getStackInSlot(i);
|
||||
if (upgradeStack.isEmpty()) continue;
|
||||
|
||||
ResourceLocation itemId = BuiltInRegistries.ITEM.getKey(upgradeStack.getItem());
|
||||
String key = itemId.toString();
|
||||
|
||||
if (upgradeStack.getItem().equals(ModItems.ENTITY_SPEED_CARD.get())) {
|
||||
CompoundTag stackTag = new CompoundTag();
|
||||
stackTag.putInt("Slot", i);
|
||||
upgradeStack.save(stackTag);
|
||||
entitySpeedCards.add(stackTag);
|
||||
} else {
|
||||
desiredUpgradesTag.putInt(key, desiredUpgradesTag.getInt(key) + upgradeStack.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
if (!entitySpeedCards.isEmpty()) {
|
||||
desiredUpgradesTag.put("entity_speed_cards", entitySpeedCards);
|
||||
}
|
||||
|
||||
output.put("upgrades", desiredUpgradesTag);
|
||||
ci.cancel();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Memory Card 恢复升级时,从玩家背包或网络工具提取实体加速卡
|
||||
*/
|
||||
@Inject(method = "restoreUpgrades", at = @At("HEAD"), cancellable = true)
|
||||
private static void restoreUpgradesCustom(Player player, CompoundTag input, IUpgradeableObject upgradeableObject, CallbackInfoReturnable<Boolean> cir) {
|
||||
try {
|
||||
if (!input.contains("upgrades")) {
|
||||
cir.setReturnValue(false);
|
||||
return;
|
||||
}
|
||||
|
||||
CompoundTag desiredUpgradesTag = input.getCompound("upgrades");
|
||||
InternalInventory upgrades = upgradeableObject.getUpgrades();
|
||||
|
||||
// 收集背包和网络工具作为升级卡来源
|
||||
var upgradeSources = new ArrayList<InternalInventory>();
|
||||
upgradeSources.add(new PlayerInternalInventory(player.getInventory()));
|
||||
var networkTool = NetworkToolItem.findNetworkToolInv(player);
|
||||
if (networkTool != null) {
|
||||
upgradeSources.add(networkTool.getInventory());
|
||||
}
|
||||
|
||||
// 清空所有槽位中的 EntitySpeedCardItem
|
||||
for (int i = 0; i < upgrades.size(); i++) {
|
||||
ItemStack stack = upgrades.getStackInSlot(i);
|
||||
if (!stack.isEmpty() && stack.getItem().equals(ModItems.ENTITY_SPEED_CARD.get())) {
|
||||
ItemStack removed = upgrades.extractItem(i, stack.getCount(), false);
|
||||
for (var source : upgradeSources) {
|
||||
if (!removed.isEmpty()) {
|
||||
removed = source.addItems(removed);
|
||||
}
|
||||
}
|
||||
if (!removed.isEmpty()) {
|
||||
player.drop(removed, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复 EntitySpeedCardItem
|
||||
if (desiredUpgradesTag.contains("entity_speed_cards", Tag.TAG_LIST)) {
|
||||
ListTag entitySpeedCards = desiredUpgradesTag.getList("entity_speed_cards", Tag.TAG_COMPOUND);
|
||||
for (int i = 0; i < entitySpeedCards.size(); i++) {
|
||||
CompoundTag stackTag = entitySpeedCards.getCompound(i);
|
||||
ItemStack desiredStack = ItemStack.of(stackTag);
|
||||
int slot = stackTag.contains("Slot") ? stackTag.getInt("Slot") : i;
|
||||
|
||||
if (player.getAbilities().instabuild) {
|
||||
// 创造模式:直接生成
|
||||
if (slot >= 0 && slot < upgrades.size()) {
|
||||
upgrades.setItemDirect(slot, desiredStack);
|
||||
} else {
|
||||
upgrades.addItems(desiredStack);
|
||||
}
|
||||
} else {
|
||||
// 非创造模式:从背包或网络工具提取
|
||||
int missingAmount = desiredStack.getCount();
|
||||
ItemStack extracted = ItemStack.EMPTY;
|
||||
|
||||
for (var source : upgradeSources) {
|
||||
ItemStack potential = new ItemStack(desiredStack.getItem(), missingAmount);
|
||||
if (desiredStack.hasTag()) {
|
||||
potential.setTag(desiredStack.getTag().copy());
|
||||
}
|
||||
ItemStack cards = source.removeItems(missingAmount, potential, null);
|
||||
if (!cards.isEmpty()) {
|
||||
ItemStack overflow = upgrades.addItems(cards);
|
||||
if (!overflow.isEmpty()) {
|
||||
player.getInventory().placeItemBackInInventory(overflow);
|
||||
}
|
||||
missingAmount -= cards.getCount();
|
||||
extracted = cards;
|
||||
}
|
||||
if (missingAmount <= 0) break;
|
||||
}
|
||||
|
||||
if (missingAmount > 0 && !player.level().isClientSide()) {
|
||||
player.displayClientMessage(
|
||||
PlayerMessages.MissingUpgrades.text(desiredStack.getItem().getDescription(), missingAmount),
|
||||
true
|
||||
);
|
||||
} else if (!extracted.isEmpty()) {
|
||||
if (slot >= 0 && slot < upgrades.size()) {
|
||||
upgrades.setItemDirect(slot, extracted);
|
||||
} else {
|
||||
upgrades.addItems(extracted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复其他升级卡(按 AE2 原逻辑)
|
||||
for (String key : desiredUpgradesTag.getAllKeys()) {
|
||||
ResourceLocation id;
|
||||
try {
|
||||
id = new ResourceLocation(key);
|
||||
} catch (Exception ex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var item = BuiltInRegistries.ITEM.getOptional(id).orElse(null);
|
||||
if (item == null || item.equals(ModItems.ENTITY_SPEED_CARD.get())) continue;
|
||||
|
||||
int desiredCount = desiredUpgradesTag.getInt(key);
|
||||
if (desiredCount > 0) {
|
||||
if (player.getAbilities().instabuild) {
|
||||
// 创造模式:直接生成
|
||||
ItemStack stack = new ItemStack(item, desiredCount);
|
||||
upgrades.addItems(stack);
|
||||
} else {
|
||||
// 非创造模式:从背包或网络工具提取
|
||||
int missingAmount = desiredCount;
|
||||
ItemStack potential = new ItemStack(item, missingAmount);
|
||||
ItemStack overflow = upgrades.addItems(potential, true);
|
||||
if (!overflow.isEmpty()) {
|
||||
missingAmount -= overflow.getCount();
|
||||
}
|
||||
|
||||
for (var source : upgradeSources) {
|
||||
ItemStack cards = source.removeItems(missingAmount, potential, null);
|
||||
if (!cards.isEmpty()) {
|
||||
overflow = upgrades.addItems(cards);
|
||||
if (!overflow.isEmpty()) {
|
||||
player.getInventory().placeItemBackInInventory(overflow);
|
||||
}
|
||||
missingAmount -= cards.getCount();
|
||||
}
|
||||
if (missingAmount <= 0) break;
|
||||
}
|
||||
|
||||
if (missingAmount > 0 && !player.level().isClientSide()) {
|
||||
player.displayClientMessage(
|
||||
PlayerMessages.MissingUpgrades.text(item.getDescription(), missingAmount),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 标记保存并通知升级变化
|
||||
if (upgradeableObject instanceof EntitySpeedTickerPart speedTickerPart) {
|
||||
BlockEntity be = speedTickerPart.getBlockEntity();
|
||||
if (be != null) {
|
||||
be.setChanged();
|
||||
}
|
||||
speedTickerPart.upgradesChanged();
|
||||
}
|
||||
|
||||
cir.setReturnValue(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.extendedae_plus.mixin.ae2;
|
||||
package com.extendedae_plus.mixin.ae2.items;
|
||||
|
||||
import appeng.api.parts.IPartHost;
|
||||
import appeng.api.parts.SelectedPart;
|
||||
|
|
@ -9,7 +9,6 @@
|
|||
"accessor.ScreenAccessor",
|
||||
"advancedae.client.gui.AdvPatternProviderScreenMixin",
|
||||
"advancedae.client.gui.SmallAdvPatternProviderScreenMixin",
|
||||
"ae2.QuartzCuttingKnifeItemMixin",
|
||||
"ae2.accessor.AEBaseScreenAccessor",
|
||||
"ae2.accessor.MEStorageScreenAccessor",
|
||||
"ae2.accessor.PatternAccessTermScreenAccessor",
|
||||
|
|
@ -21,6 +20,7 @@
|
|||
"ae2.client.gui.PatternProviderScreenMixin",
|
||||
"ae2.client.gui.SlotGridLayoutMixin",
|
||||
"ae2.compat.PatternProviderScreenCompatMixin",
|
||||
"ae2.items.QuartzCuttingKnifeItemMixin",
|
||||
"ae2.menu.CraftConfirmMenuGoBackMixin",
|
||||
"extendedae.accessor.GuiExPatternTerminalAccessor",
|
||||
"extendedae.accessor.GuiExPatternTerminalSlotsRowAccessor",
|
||||
|
|
@ -62,6 +62,7 @@
|
|||
"ae2.helpers.PatternProviderLogicAdvancedMixin",
|
||||
"ae2.helpers.PatternProviderLogicDoublingMixin",
|
||||
"ae2.helpers.patternprovider.PatternProviderLogicTickerMixin",
|
||||
"ae2.items.MemoryCardItemMixin",
|
||||
"ae2.menu.ContainerPatternEncodingTermMenuMixin",
|
||||
"ae2.menu.MEStorageMenuMixin",
|
||||
"ae2.menu.PatternEncodingTermMenuMixin",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user