修复使用内存卡刷取实体加速卡的bug

This commit is contained in:
GaLi 2026-04-16 18:31:31 +08:00
parent 56a64b921c
commit c8ae498808

View File

@ -14,6 +14,7 @@ import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -23,6 +24,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
@Mixin(value = MemoryCardItem.class, remap = false) @Mixin(value = MemoryCardItem.class, remap = false)
public class MemoryCardItemMixin { public class MemoryCardItemMixin {
@ -46,7 +49,6 @@ public class MemoryCardItemMixin {
if (upgradeStack.getItem().equals(ModItems.ENTITY_SPEED_CARD.get())) { if (upgradeStack.getItem().equals(ModItems.ENTITY_SPEED_CARD.get())) {
CompoundTag stackTag = new CompoundTag(); CompoundTag stackTag = new CompoundTag();
stackTag.putInt("Slot", i);
upgradeStack.save(stackTag); upgradeStack.save(stackTag);
entitySpeedCards.add(stackTag); entitySpeedCards.add(stackTag);
} else { } else {
@ -78,6 +80,8 @@ public class MemoryCardItemMixin {
CompoundTag desiredUpgradesTag = input.getCompound("upgrades"); CompoundTag desiredUpgradesTag = input.getCompound("upgrades");
InternalInventory upgrades = upgradeableObject.getUpgrades(); InternalInventory upgrades = upgradeableObject.getUpgrades();
var desiredUpgrades = new IdentityHashMap<Item, Integer>();
var desiredEntitySpeedCards = new ArrayList<ItemStack>();
// 收集背包和网络工具作为升级卡来源 // 收集背包和网络工具作为升级卡来源
var upgradeSources = new ArrayList<InternalInventory>(); var upgradeSources = new ArrayList<InternalInventory>();
@ -87,77 +91,21 @@ public class MemoryCardItemMixin {
upgradeSources.add(networkTool.getInventory()); 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)) { if (desiredUpgradesTag.contains("entity_speed_cards", Tag.TAG_LIST)) {
ListTag entitySpeedCards = desiredUpgradesTag.getList("entity_speed_cards", Tag.TAG_COMPOUND); ListTag entitySpeedCards = desiredUpgradesTag.getList("entity_speed_cards", Tag.TAG_COMPOUND);
for (int i = 0; i < entitySpeedCards.size(); i++) { for (int i = 0; i < entitySpeedCards.size(); i++) {
CompoundTag stackTag = entitySpeedCards.getCompound(i); ItemStack desiredStack = ItemStack.of(entitySpeedCards.getCompound(i));
ItemStack desiredStack = ItemStack.of(stackTag); if (!desiredStack.isEmpty()) {
int slot = stackTag.contains("Slot") ? stackTag.getInt("Slot") : i; desiredEntitySpeedCards.add(desiredStack);
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()) { for (String key : desiredUpgradesTag.getAllKeys()) {
if ("entity_speed_cards".equals(key)) {
continue;
}
ResourceLocation id; ResourceLocation id;
try { try {
id = new ResourceLocation(key); id = new ResourceLocation(key);
@ -166,58 +114,249 @@ public class MemoryCardItemMixin {
} }
var item = BuiltInRegistries.ITEM.getOptional(id).orElse(null); var item = BuiltInRegistries.ITEM.getOptional(id).orElse(null);
if (item == null || item.equals(ModItems.ENTITY_SPEED_CARD.get())) continue; if (item == null || item.equals(ModItems.ENTITY_SPEED_CARD.get())) {
continue;
}
int desiredCount = desiredUpgradesTag.getInt(key); int desiredCount = desiredUpgradesTag.getInt(key);
if (desiredCount > 0) { if (desiredCount > 0) {
if (player.getAbilities().instabuild) { desiredUpgrades.put(item, desiredCount);
// 创造模式直接生成 }
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) { if (player.getAbilities().instabuild) {
ItemStack cards = source.removeItems(missingAmount, potential, null); for (int i = 0; i < upgrades.size(); i++) {
if (!cards.isEmpty()) { upgrades.setItemDirect(i, ItemStack.EMPTY);
overflow = upgrades.addItems(cards); }
if (!overflow.isEmpty()) { for (var desiredStack : desiredEntitySpeedCards) {
player.getInventory().placeItemBackInInventory(overflow); upgrades.addItems(desiredStack.copy());
} }
missingAmount -= cards.getCount(); for (var entry : desiredUpgrades.entrySet()) {
} upgrades.addItems(new ItemStack(entry.getKey(), entry.getValue()));
if (missingAmount <= 0) break; }
} markUpgradesChanged(upgradeableObject);
cir.setReturnValue(true);
return;
}
if (missingAmount > 0 && !player.level().isClientSide()) { // 先精确移除多余的实体加速卡按完整 NBT 匹配
player.displayClientMessage( var desiredEntityStacks = new ArrayList<ItemStack>();
PlayerMessages.MissingUpgrades.text(item.getDescription(), missingAmount), var desiredEntityCounts = new ArrayList<Integer>();
true for (var desiredStack : desiredEntitySpeedCards) {
); mergeExactCount(desiredEntityStacks, desiredEntityCounts, desiredStack, desiredStack.getCount());
}
var currentEntityStacks = new ArrayList<ItemStack>();
var currentEntityCounts = new ArrayList<Integer>();
collectInstalledEntitySpeedCards(upgrades, currentEntityStacks, currentEntityCounts);
for (int i = 0; i < upgrades.size(); i++) {
ItemStack stack = upgrades.getStackInSlot(i);
if (stack.isEmpty() || !stack.getItem().equals(ModItems.ENTITY_SPEED_CARD.get())) {
continue;
}
int installed = getExactCount(currentEntityStacks, currentEntityCounts, stack);
int desired = getExactCount(desiredEntityStacks, desiredEntityCounts, stack);
int excess = installed - desired;
if (excess <= 0) {
continue;
}
ItemStack removed = upgrades.extractItem(i, Math.min(excess, stack.getCount()), false);
if (removed.isEmpty()) {
continue;
}
decrementExactCount(currentEntityStacks, currentEntityCounts, stack, removed.getCount());
for (var source : upgradeSources) {
if (!removed.isEmpty()) {
removed = source.addItems(removed);
}
}
if (!removed.isEmpty()) {
player.drop(removed, false);
}
}
// AE2 原逻辑移除多余的其他升级卡
for (int i = 0; i < upgrades.size(); i++) {
var current = upgrades.getStackInSlot(i);
if (current.isEmpty() || current.getItem().equals(ModItems.ENTITY_SPEED_CARD.get())) {
continue;
}
var desiredCount = desiredUpgrades.getOrDefault(current.getItem(), 0);
var totalInstalled = upgradeableObject.getInstalledUpgrades(current.getItem());
var toRemove = totalInstalled - desiredCount;
if (toRemove > 0) {
var removed = upgrades.extractItem(i, toRemove, false);
for (var upgradeSource : upgradeSources) {
if (!removed.isEmpty()) {
removed = upgradeSource.addItems(removed);
} }
} }
if (!removed.isEmpty()) {
player.drop(removed, false);
}
} }
} }
// 标记保存并通知升级变化 // 精确补回缺失的实体加速卡按完整 NBT 匹配
if (upgradeableObject instanceof EntitySpeedTickerPart speedTickerPart) { var afterRemovalEntityStacks = new ArrayList<ItemStack>();
BlockEntity be = speedTickerPart.getBlockEntity(); var afterRemovalEntityCounts = new ArrayList<Integer>();
if (be != null) { collectInstalledEntitySpeedCards(upgrades, afterRemovalEntityStacks, afterRemovalEntityCounts);
be.setChanged(); for (int i = 0; i < desiredEntityStacks.size(); i++) {
var desiredStack = desiredEntityStacks.get(i);
int desiredCount = desiredEntityCounts.get(i);
int missingAmount = desiredCount - getExactCount(afterRemovalEntityStacks, afterRemovalEntityCounts, desiredStack);
if (missingAmount <= 0) {
continue;
}
var potential = desiredStack.copy();
potential.setCount(missingAmount);
var overflow = upgrades.addItems(potential, true);
if (!overflow.isEmpty()) {
missingAmount -= overflow.getCount();
}
if (missingAmount <= 0) {
continue;
}
for (var source : upgradeSources) {
var preciseRequest = desiredStack.copy();
preciseRequest.setCount(missingAmount);
var cards = source.removeItems(missingAmount, preciseRequest, 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(desiredStack.getHoverName(), missingAmount),
true
);
} }
speedTickerPart.upgradesChanged();
} }
// 恢复其他升级卡 AE2 原逻辑
for (var entry : desiredUpgrades.entrySet()) {
int missingAmount = entry.getValue() - upgradeableObject.getInstalledUpgrades(entry.getKey());
if (missingAmount > 0) {
ItemStack potential = new ItemStack(entry.getKey(), 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(entry.getKey().getDescription(), missingAmount),
true
);
}
}
}
markUpgradesChanged(upgradeableObject);
cir.setReturnValue(true); cir.setReturnValue(true);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
cir.setReturnValue(false); cir.setReturnValue(false);
} }
} }
}
private static void markUpgradesChanged(IUpgradeableObject upgradeableObject) {
if (upgradeableObject instanceof EntitySpeedTickerPart speedTickerPart) {
BlockEntity be = speedTickerPart.getBlockEntity();
if (be != null) {
be.setChanged();
}
speedTickerPart.upgradesChanged();
}
}
private static void collectInstalledEntitySpeedCards(InternalInventory upgrades, List<ItemStack> stacks,
List<Integer> counts) {
for (int i = 0; i < upgrades.size(); i++) {
var stack = upgrades.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem().equals(ModItems.ENTITY_SPEED_CARD.get())) {
mergeExactCount(stacks, counts, stack, stack.getCount());
}
}
}
private static void mergeExactCount(List<ItemStack> stacks, List<Integer> counts, ItemStack stack, int amount) {
if (stack.isEmpty() || amount <= 0) {
return;
}
for (int i = 0; i < stacks.size(); i++) {
if (sameExactStack(stacks.get(i), stack)) {
counts.set(i, counts.get(i) + amount);
return;
}
}
stacks.add(copySingle(stack));
counts.add(amount);
}
private static int getExactCount(List<ItemStack> stacks, List<Integer> counts, ItemStack stack) {
for (int i = 0; i < stacks.size(); i++) {
if (sameExactStack(stacks.get(i), stack)) {
return counts.get(i);
}
}
return 0;
}
private static void decrementExactCount(List<ItemStack> stacks, List<Integer> counts, ItemStack stack, int amount) {
if (amount <= 0) {
return;
}
for (int i = 0; i < stacks.size(); i++) {
if (sameExactStack(stacks.get(i), stack)) {
int remaining = counts.get(i) - amount;
if (remaining <= 0) {
stacks.remove(i);
counts.remove(i);
} else {
counts.set(i, remaining);
}
return;
}
}
}
private static boolean sameExactStack(ItemStack a, ItemStack b) {
return ItemStack.isSameItemSameTags(a, b);
}
private static ItemStack copySingle(ItemStack stack) {
var copy = stack.copy();
copy.setCount(1);
return copy;
}
}