修复使用内存卡刷取实体加速卡的bug
This commit is contained in:
parent
56a64b921c
commit
c8ae498808
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user