diff --git a/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoBarOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoBarOverlay.java index 9c9dbc7eb..7d036475a 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoBarOverlay.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoBarOverlay.java @@ -3,6 +3,7 @@ package com.atsuishio.superbwarfare.client.overlay; import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.capability.ModCapabilities; import com.atsuishio.superbwarfare.capability.player.PlayerVariable; +import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.config.client.DisplayConfig; import com.atsuishio.superbwarfare.entity.vehicle.base.ArmedVehicleEntity; import com.atsuishio.superbwarfare.init.ModItems; @@ -290,8 +291,9 @@ public class AmmoBarOverlay { boolean boxAmmoSelected = false; if (isAmmoBox) { - var tag = NBTTool.getTag(stack); - var ammoBoxType = tag.getString("Type"); + var data = stack.get(ModDataComponents.AMMO_BOX_INFO); + var ammoBoxType = data == null ? "All" : data.type(); + boxAmmoCount = type.get(stack); if (ammoBoxType.equals("All") || ammoBoxType.equals(type.name)) { boxAnimator.forward(currentTime); diff --git a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java index d3dd5a2a9..97e9aed33 100644 --- a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java +++ b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java @@ -42,7 +42,7 @@ public class ModDataComponents { ); public static final DeferredHolder, DataComponentType> AMMO_BOX_INFO = register( - "ammo_box_type", + "ammo_box_info", builder -> builder.persistent(AmmoBoxInfo.CODEC) ); diff --git a/src/main/java/com/atsuishio/superbwarfare/event/LivingEventHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/LivingEventHandler.java index a9fb2ebc0..aad910b03 100644 --- a/src/main/java/com/atsuishio/superbwarfare/event/LivingEventHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/event/LivingEventHandler.java @@ -2,6 +2,7 @@ package com.atsuishio.superbwarfare.event; import com.atsuishio.superbwarfare.capability.ModCapabilities; import com.atsuishio.superbwarfare.capability.player.PlayerVariable; +import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.config.common.GameplayConfig; import com.atsuishio.superbwarfare.config.server.MiscConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig; @@ -14,6 +15,7 @@ import com.atsuishio.superbwarfare.entity.vehicle.base.ContainerMobileVehicleEnt import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity; import com.atsuishio.superbwarfare.event.events.PreKillEvent; import com.atsuishio.superbwarfare.init.*; +import com.atsuishio.superbwarfare.item.common.ammo.box.AmmoBoxInfo; import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.ReloadState; @@ -24,7 +26,6 @@ import com.atsuishio.superbwarfare.perk.AmmoPerk; import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.PerkHelper; import com.atsuishio.superbwarfare.tools.*; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundStopSoundPacket; import net.minecraft.resources.ResourceKey; @@ -51,6 +52,7 @@ import net.neoforged.neoforge.event.entity.living.*; import net.neoforged.neoforge.event.entity.player.ItemEntityPickupEvent; import net.neoforged.neoforge.network.PacketDistributor; +import java.util.ArrayList; import java.util.Objects; @EventBusSubscriber @@ -91,7 +93,6 @@ public class LivingEventHandler { killIndication(event); handleGunPerksWhenDeath(event); handlePlayerKillEntity(event); - handlePlayerDeathDropAmmo(event.getEntity()); giveKillExpToWeapon(event); if (event.getEntity() instanceof Player player) { @@ -737,37 +738,6 @@ public class LivingEventHandler { data.save(); } - /** - * 开启死亡掉落时掉落一个弹药盒 - */ - private static void handlePlayerDeathDropAmmo(LivingEntity entity) { - if (!entity.level().getLevelData().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && entity instanceof Player player) { - var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); - if (cap == null) cap = new PlayerVariable(); - - boolean drop = cap.rifleAmmo + cap.handgunAmmo + cap.shotgunAmmo + cap.sniperAmmo + cap.heavyAmmo > 0; - - if (drop) { - ItemStack stack = new ItemStack(ModItems.AMMO_BOX.get()); - CompoundTag tag = NBTTool.getTag(stack); - - for (var type : AmmoType.values()) { - type.set(tag, type.get(cap)); - type.set(cap, 0); - } - tag.putBoolean("IsDrop", true); - NBTTool.saveTag(stack, tag); - cap.syncPlayerVariables(player); - - if (player.level() instanceof ServerLevel level) { - ItemEntity itemEntity = new ItemEntity(level, player.getX(), player.getY() + 1, player.getZ(), stack); - itemEntity.setPickUpDelay(10); - level.addFreshEntity(itemEntity); - } - } - } - } - @SubscribeEvent public static void onPickup(ItemEntityPickupEvent.Pre event) { if (!VehicleConfig.VEHICLE_ITEM_PICKUP.get()) return; @@ -782,26 +752,58 @@ public class LivingEventHandler { @SubscribeEvent public static void onLivingDrops(LivingDropsEvent event) { + // 死亡掉落弹药盒 + if (event.getEntity() instanceof Player player && !player.level().getLevelData().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)) { + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (cap == null) cap = new PlayerVariable(); + + boolean drop = cap.rifleAmmo + cap.handgunAmmo + cap.shotgunAmmo + cap.sniperAmmo + cap.heavyAmmo > 0; + + if (drop) { + var stack = new ItemStack(ModItems.AMMO_BOX.get()); + + for (var type : AmmoType.values()) { + type.set(stack, type.get(cap)); + type.set(cap, 0); + } + + var info = new AmmoBoxInfo("All", true); + stack.set(ModDataComponents.AMMO_BOX_INFO, info); + + cap.syncPlayerVariables(player); + + event.getDrops().add(new ItemEntity(player.level(), player.getX(), player.getY() + 1, player.getZ(), stack)); + } + } + DamageSource source = event.getSource(); Entity sourceEntity = source.getEntity(); if (!(sourceEntity instanceof Player player)) return; - ItemStack stack = player.getMainHandItem(); + ItemStack mainHandItem = player.getMainHandItem(); + // 创生物收集掉落物 if (player.getVehicle() instanceof ContainerMobileVehicleEntity containerMobileVehicleEntity && source.is(ModDamageTypes.VEHICLE_STRIKE)) { var drops = event.getDrops(); + var removed = new ArrayList(); + drops.forEach(itemEntity -> { - ItemStack item = itemEntity.getItem(); - if (!HopperBlockEntity.addItem(containerMobileVehicleEntity, itemEntity)) { - player.drop(item, false); + ItemStack stack = itemEntity.getItem(); + + InventoryTool.insertItem(containerMobileVehicleEntity.getItemStacks(), stack); + + if (stack.getCount() <= 0) { + player.drop(stack, false); + removed.add(itemEntity); } }); - event.setCanceled(true); + + drops.removeAll(removed); return; } - - final var tag = NBTTool.getTag(stack); - if (stack.is(ModTags.Items.GUN) && PerkHelper.getItemPerkLevel(ModPerks.POWERFUL_ATTRACTION.get(), tag) > 0 && (DamageTypeTool.isGunDamage(source) || DamageTypeTool.isExplosionDamage(source))) { + // 磁吸Perk + final var mainHandTag = NBTTool.getTag(mainHandItem); + if (mainHandItem.is(ModTags.Items.GUN) && PerkHelper.getItemPerkLevel(ModPerks.POWERFUL_ATTRACTION.get(), mainHandTag) > 0 && (DamageTypeTool.isGunDamage(source) || DamageTypeTool.isExplosionDamage(source))) { var drops = event.getDrops(); drops.forEach(itemEntity -> { ItemStack item = itemEntity.getItem(); diff --git a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBox.java b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBox.java index 7ac65730d..5c21d8f0e 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBox.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/common/ammo/box/AmmoBox.java @@ -37,32 +37,30 @@ public class AmmoBox extends Item { if (hand == InteractionHand.OFF_HAND) return InteractionResultHolder.fail(stack); player.getCooldowns().addCooldown(this, 10); + var info = stack.get(ModDataComponents.AMMO_BOX_INFO); if (info == null) info = new AmmoBoxInfo("All", false); - String type = info.type(); + String selectedType = info.type(); var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); - if (cap != null) { - var types = type.equals("All") ? AmmoType.values() : new AmmoType[]{AmmoType.getType(type)}; + if (cap != null && !level.isClientSide()) { + var types = selectedType.equals("All") ? AmmoType.values() : new AmmoType[]{AmmoType.getType(selectedType)}; - for (var ammoType : types) { - if (ammoType == null) continue; + for (var type : types) { + if (type == null) continue; if (player.isCrouching()) { // 存入弹药 - ammoType.add(stack, ammoType.get(cap)); - ammoType.set(cap, 0); + type.add(stack, type.get(cap)); + type.set(cap, 0); } else { // 取出弹药 - ammoType.add(cap, ammoType.get(stack)); - ammoType.set(stack, 0); + type.add(cap, type.get(stack)); + type.set(stack, 0); } } cap.syncPlayerVariables(player); - - if (!level.isClientSide()) { - level.playSound(null, player.blockPosition(), SoundEvents.ARROW_HIT_PLAYER, SoundSource.PLAYERS, 1, 1); - } + level.playSound(null, player.blockPosition(), SoundEvents.ARROW_HIT_PLAYER, SoundSource.PLAYERS, 1, 1); // 取出弹药时,若弹药盒为掉落物版本,则移除弹药盒物品 if (!player.isCrouching() && info.isDrop()) { @@ -122,7 +120,7 @@ public class AmmoBox extends Item { } @Override - public void appendHoverText(ItemStack stack, @NotNull TooltipContext context, List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { + public void appendHoverText(ItemStack stack, @NotNull TooltipContext context, @NotNull List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { var info = stack.get(ModDataComponents.AMMO_BOX_INFO); if (info == null) info = new AmmoBoxInfo("All", false); var type = AmmoType.getType(info.type()); diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/InventoryTool.java b/src/main/java/com/atsuishio/superbwarfare/tools/InventoryTool.java index 058d79bed..b6704c42c 100644 --- a/src/main/java/com/atsuishio/superbwarfare/tools/InventoryTool.java +++ b/src/main/java/com/atsuishio/superbwarfare/tools/InventoryTool.java @@ -119,4 +119,26 @@ public class InventoryTool { return count; } + + public static int insertItem(NonNullList itemList, ItemStack stack) { + var maxStackSize = stack.getItem().getMaxStackSize(stack); + var originalCount = stack.getCount(); + + for (int i = 0; i < itemList.size(); i++) { + var currentStack = itemList.get(i); + + if (ItemStack.isSameItemSameComponents(stack, currentStack) && currentStack.getCount() < maxStackSize) { + var countToAdd = Math.min(maxStackSize - currentStack.getCount(), stack.getCount()); + currentStack.grow(countToAdd); + stack.setCount(stack.getCount() - countToAdd); + } else if (currentStack.isEmpty()) { + itemList.set(i, stack); + return stack.getCount(); + } + + if (stack.getCount() <= 0) break; + } + + return originalCount - stack.getCount(); + } }