正确实现弹药盒掉落逻辑,修复弹药盒数据同步问题

This commit is contained in:
Light_Quanta 2025-04-07 01:44:57 +08:00
parent 24479e203f
commit ddf078b41b
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
5 changed files with 82 additions and 58 deletions

View file

@ -3,6 +3,7 @@ package com.atsuishio.superbwarfare.client.overlay;
import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.Mod;
import com.atsuishio.superbwarfare.capability.ModCapabilities; import com.atsuishio.superbwarfare.capability.ModCapabilities;
import com.atsuishio.superbwarfare.capability.player.PlayerVariable; import com.atsuishio.superbwarfare.capability.player.PlayerVariable;
import com.atsuishio.superbwarfare.component.ModDataComponents;
import com.atsuishio.superbwarfare.config.client.DisplayConfig; import com.atsuishio.superbwarfare.config.client.DisplayConfig;
import com.atsuishio.superbwarfare.entity.vehicle.base.ArmedVehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.ArmedVehicleEntity;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
@ -290,8 +291,9 @@ public class AmmoBarOverlay {
boolean boxAmmoSelected = false; boolean boxAmmoSelected = false;
if (isAmmoBox) { if (isAmmoBox) {
var tag = NBTTool.getTag(stack); var data = stack.get(ModDataComponents.AMMO_BOX_INFO);
var ammoBoxType = tag.getString("Type"); var ammoBoxType = data == null ? "All" : data.type();
boxAmmoCount = type.get(stack); boxAmmoCount = type.get(stack);
if (ammoBoxType.equals("All") || ammoBoxType.equals(type.name)) { if (ammoBoxType.equals("All") || ammoBoxType.equals(type.name)) {
boxAnimator.forward(currentTime); boxAnimator.forward(currentTime);

View file

@ -42,7 +42,7 @@ public class ModDataComponents {
); );
public static final DeferredHolder<DataComponentType<?>, DataComponentType<AmmoBoxInfo>> AMMO_BOX_INFO = register( public static final DeferredHolder<DataComponentType<?>, DataComponentType<AmmoBoxInfo>> AMMO_BOX_INFO = register(
"ammo_box_type", "ammo_box_info",
builder -> builder.persistent(AmmoBoxInfo.CODEC) builder -> builder.persistent(AmmoBoxInfo.CODEC)
); );

View file

@ -2,6 +2,7 @@ package com.atsuishio.superbwarfare.event;
import com.atsuishio.superbwarfare.capability.ModCapabilities; import com.atsuishio.superbwarfare.capability.ModCapabilities;
import com.atsuishio.superbwarfare.capability.player.PlayerVariable; 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.common.GameplayConfig;
import com.atsuishio.superbwarfare.config.server.MiscConfig; import com.atsuishio.superbwarfare.config.server.MiscConfig;
import com.atsuishio.superbwarfare.config.server.VehicleConfig; 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.entity.vehicle.base.VehicleEntity;
import com.atsuishio.superbwarfare.event.events.PreKillEvent; import com.atsuishio.superbwarfare.event.events.PreKillEvent;
import com.atsuishio.superbwarfare.init.*; 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.GunItem;
import com.atsuishio.superbwarfare.item.gun.data.GunData; import com.atsuishio.superbwarfare.item.gun.data.GunData;
import com.atsuishio.superbwarfare.item.gun.data.ReloadState; 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.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper; import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.*; import com.atsuishio.superbwarfare.tools.*;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundStopSoundPacket; import net.minecraft.network.protocol.game.ClientboundStopSoundPacket;
import net.minecraft.resources.ResourceKey; 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.event.entity.player.ItemEntityPickupEvent;
import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
@EventBusSubscriber @EventBusSubscriber
@ -91,7 +93,6 @@ public class LivingEventHandler {
killIndication(event); killIndication(event);
handleGunPerksWhenDeath(event); handleGunPerksWhenDeath(event);
handlePlayerKillEntity(event); handlePlayerKillEntity(event);
handlePlayerDeathDropAmmo(event.getEntity());
giveKillExpToWeapon(event); giveKillExpToWeapon(event);
if (event.getEntity() instanceof Player player) { if (event.getEntity() instanceof Player player) {
@ -737,37 +738,6 @@ public class LivingEventHandler {
data.save(); 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 @SubscribeEvent
public static void onPickup(ItemEntityPickupEvent.Pre event) { public static void onPickup(ItemEntityPickupEvent.Pre event) {
if (!VehicleConfig.VEHICLE_ITEM_PICKUP.get()) return; if (!VehicleConfig.VEHICLE_ITEM_PICKUP.get()) return;
@ -782,26 +752,58 @@ public class LivingEventHandler {
@SubscribeEvent @SubscribeEvent
public static void onLivingDrops(LivingDropsEvent event) { 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(); DamageSource source = event.getSource();
Entity sourceEntity = source.getEntity(); Entity sourceEntity = source.getEntity();
if (!(sourceEntity instanceof Player player)) return; 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)) { if (player.getVehicle() instanceof ContainerMobileVehicleEntity containerMobileVehicleEntity && source.is(ModDamageTypes.VEHICLE_STRIKE)) {
var drops = event.getDrops(); var drops = event.getDrops();
var removed = new ArrayList<ItemEntity>();
drops.forEach(itemEntity -> { drops.forEach(itemEntity -> {
ItemStack item = itemEntity.getItem(); ItemStack stack = itemEntity.getItem();
if (!HopperBlockEntity.addItem(containerMobileVehicleEntity, itemEntity)) {
player.drop(item, false); InventoryTool.insertItem(containerMobileVehicleEntity.getItemStacks(), stack);
if (stack.getCount() <= 0) {
player.drop(stack, false);
removed.add(itemEntity);
} }
}); });
event.setCanceled(true);
drops.removeAll(removed);
return; return;
} }
// 磁吸Perk
final var tag = NBTTool.getTag(stack); final var mainHandTag = NBTTool.getTag(mainHandItem);
if (stack.is(ModTags.Items.GUN) && PerkHelper.getItemPerkLevel(ModPerks.POWERFUL_ATTRACTION.get(), tag) > 0 && (DamageTypeTool.isGunDamage(source) || DamageTypeTool.isExplosionDamage(source))) { if (mainHandItem.is(ModTags.Items.GUN) && PerkHelper.getItemPerkLevel(ModPerks.POWERFUL_ATTRACTION.get(), mainHandTag) > 0 && (DamageTypeTool.isGunDamage(source) || DamageTypeTool.isExplosionDamage(source))) {
var drops = event.getDrops(); var drops = event.getDrops();
drops.forEach(itemEntity -> { drops.forEach(itemEntity -> {
ItemStack item = itemEntity.getItem(); ItemStack item = itemEntity.getItem();

View file

@ -37,32 +37,30 @@ public class AmmoBox extends Item {
if (hand == InteractionHand.OFF_HAND) return InteractionResultHolder.fail(stack); if (hand == InteractionHand.OFF_HAND) return InteractionResultHolder.fail(stack);
player.getCooldowns().addCooldown(this, 10); player.getCooldowns().addCooldown(this, 10);
var info = stack.get(ModDataComponents.AMMO_BOX_INFO); var info = stack.get(ModDataComponents.AMMO_BOX_INFO);
if (info == null) info = new AmmoBoxInfo("All", false); if (info == null) info = new AmmoBoxInfo("All", false);
String type = info.type(); String selectedType = info.type();
var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null);
if (cap != null) { if (cap != null && !level.isClientSide()) {
var types = type.equals("All") ? AmmoType.values() : new AmmoType[]{AmmoType.getType(type)}; var types = selectedType.equals("All") ? AmmoType.values() : new AmmoType[]{AmmoType.getType(selectedType)};
for (var ammoType : types) { for (var type : types) {
if (ammoType == null) continue; if (type == null) continue;
if (player.isCrouching()) { if (player.isCrouching()) {
// 存入弹药 // 存入弹药
ammoType.add(stack, ammoType.get(cap)); type.add(stack, type.get(cap));
ammoType.set(cap, 0); type.set(cap, 0);
} else { } else {
// 取出弹药 // 取出弹药
ammoType.add(cap, ammoType.get(stack)); type.add(cap, type.get(stack));
ammoType.set(stack, 0); type.set(stack, 0);
} }
} }
cap.syncPlayerVariables(player); cap.syncPlayerVariables(player);
level.playSound(null, player.blockPosition(), SoundEvents.ARROW_HIT_PLAYER, SoundSource.PLAYERS, 1, 1);
if (!level.isClientSide()) {
level.playSound(null, player.blockPosition(), SoundEvents.ARROW_HIT_PLAYER, SoundSource.PLAYERS, 1, 1);
}
// 取出弹药时若弹药盒为掉落物版本则移除弹药盒物品 // 取出弹药时若弹药盒为掉落物版本则移除弹药盒物品
if (!player.isCrouching() && info.isDrop()) { if (!player.isCrouching() && info.isDrop()) {
@ -122,7 +120,7 @@ public class AmmoBox extends Item {
} }
@Override @Override
public void appendHoverText(ItemStack stack, @NotNull TooltipContext context, List<Component> tooltipComponents, @NotNull TooltipFlag tooltipFlag) { public void appendHoverText(ItemStack stack, @NotNull TooltipContext context, @NotNull List<Component> tooltipComponents, @NotNull TooltipFlag tooltipFlag) {
var info = stack.get(ModDataComponents.AMMO_BOX_INFO); var info = stack.get(ModDataComponents.AMMO_BOX_INFO);
if (info == null) info = new AmmoBoxInfo("All", false); if (info == null) info = new AmmoBoxInfo("All", false);
var type = AmmoType.getType(info.type()); var type = AmmoType.getType(info.type());

View file

@ -119,4 +119,26 @@ public class InventoryTool {
return count; return count;
} }
public static int insertItem(NonNullList<ItemStack> 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();
}
} }