diff --git a/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java b/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java index 5560fbe52..2b62bb088 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java @@ -327,7 +327,7 @@ public class ClickHandler { ClientEventHandler.holdFire = true; } - if (stack.getItem() instanceof GunItem gunItem && !(player.getVehicle() != null + if (stack.getItem() instanceof GunItem && !(player.getVehicle() != null && player.getVehicle() instanceof CannonEntity) && clientTimer.getProgress() == 0 && !notInGame() @@ -339,7 +339,7 @@ public class ClickHandler { handTimer = 0; } - if (!gunItem.useBackpackAmmo(stack) && data.ammo.get() <= 0 && data.reload.time() == 0) { + if (!data.useBackpackAmmo() && data.ammo.get() <= 0 && data.reload.time() == 0) { if (ReloadConfig.LEFT_CLICK_RELOAD.get()) { PacketDistributor.sendToServer(new ReloadMessage(0)); ClientEventHandler.burstFireAmount = 0; 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 824e740f0..12980c5ee 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoBarOverlay.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/overlay/AmmoBarOverlay.java @@ -42,28 +42,15 @@ public class AmmoBarOverlay implements LayeredDraw.Layer { return player.isCreative() || InventoryTool.hasCreativeAmmoBox(player); } - private static int getGunAmmoCount(Player player) { - ItemStack stack = player.getMainHandItem(); - - if (stack.getItem() == ModItems.MINIGUN.get()) { - return GunData.from(stack).countBackupAmmo(player); - } - return GunData.from(stack).ammo.get(); + private static String getGunAmmoString(GunData data, Player player) { + if (data.useBackpackAmmo() && hasCreativeAmmo()) return "∞"; + return data.useBackpackAmmo() ? data.countBackupAmmo(player) + "" : data.ammo.get() + ""; } - private static String getPlayerAmmoCount(Player player) { - ItemStack stack = player.getMainHandItem(); + private static String getBackupAmmoString(GunData data, Player player) { + if (data.useBackpackAmmo()) return ""; - if (stack.getItem() == ModItems.MINIGUN.get()) { - return ""; - } - - if (!hasCreativeAmmo()) { - var data = GunData.from(stack); - return data.countBackupAmmo(player) + ""; - } - - return "∞"; + return hasCreativeAmmo() ? "∞" : data.countBackupAmmo(player) + ""; } @Override @@ -79,8 +66,8 @@ public class AmmoBarOverlay implements LayeredDraw.Layer { if (player.isSpectator()) return; ItemStack stack = player.getMainHandItem(); - final var tag = NBTTool.getTag(stack); if (stack.getItem() instanceof GunItem gunItem && !(player.getVehicle() instanceof ArmedVehicleEntity vehicle && vehicle.banHand(player))) { + final var tag = NBTTool.getTag(stack); PoseStack poseStack = guiGraphics.pose(); var data = GunData.from(stack); @@ -174,32 +161,21 @@ public class AmmoBarOverlay implements LayeredDraw.Layer { poseStack.pushPose(); poseStack.scale(1.5f, 1.5f, 1f); - if (stack.getItem() == ModItems.MINIGUN.get() && hasCreativeAmmo()) { - guiGraphics.drawString( - Minecraft.getInstance().font, - "∞", - w / 1.5f - 64 / 1.5f, - h / 1.5f - 48 / 1.5f, - 0xFFFFFF, - true - ); - } else { - guiGraphics.drawString( - Minecraft.getInstance().font, - getGunAmmoCount(player) + "", - w / 1.5f - 64 / 1.5f, - h / 1.5f - 48 / 1.5f, - 0xFFFFFF, - true - ); - } + guiGraphics.drawString( + Minecraft.getInstance().font, + getGunAmmoString(data, player), + w / 1.5f - 64 / 1.5f, + h / 1.5f - 48 / 1.5f, + 0xFFFFFF, + true + ); poseStack.popPose(); // 渲染备弹量 guiGraphics.drawString( Minecraft.getInstance().font, - getPlayerAmmoCount(player), + getBackupAmmoString(data, player), w - 64, h - 35, 0xCCCCCC, diff --git a/src/main/java/com/atsuishio/superbwarfare/client/overlay/JavelinHudOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/overlay/JavelinHudOverlay.java index 16616cb50..68c430442 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/overlay/JavelinHudOverlay.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/overlay/JavelinHudOverlay.java @@ -82,7 +82,7 @@ public class JavelinHudOverlay implements LayeredDraw.Layer { float j1 = l + j; preciseBlit(guiGraphics, Mod.loc("textures/screens/javelin/javelin_hud.png"), k, l, 0, 0.0F, i, j, i, j); preciseBlit(guiGraphics, Mod.loc(tag.getBoolean("TopMode") ? "textures/screens/javelin/top.png" : "textures/screens/javelin/dir.png"), k, l, 0, 0.0F, i, j, i, j); - preciseBlit(guiGraphics, Mod.loc(data.ammo.get() > 0 ? "textures/screens/javelin/missile_green.png" : "textures/screens/javelin/missile_red.png"), k, l, 0, 0.0F, i, j, i, j); + preciseBlit(guiGraphics, Mod.loc(data.hasEnoughAmmoToShoot(player) ? "textures/screens/javelin/missile_green.png" : "textures/screens/javelin/missile_red.png"), k, l, 0, 0.0F, i, j, i, j); if (tag.getInt("SeekTime") > 1 && tag.getInt("SeekTime") < 20) { preciseBlit(guiGraphics, Mod.loc("textures/screens/javelin/seek.png"), k, l, 0, 0.0F, i, j, i, j); } diff --git a/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java index 776d0ae43..79e63e8ef 100644 --- a/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java @@ -582,7 +582,7 @@ public class ClientEventHandler { && (!(data.reload.normal() || data.reload.empty()) && !data.reloading() && !data.charging() - && data.ammo.get() > 0 + && data.hasEnoughAmmoToShoot(player) && !player.getCooldowns().isOnCooldown(stack.getItem()) && !data.bolt.needed.get() && revolverPre(data)) @@ -659,67 +659,66 @@ public class ClientEventHandler { ItemStack stack = player.getMainHandItem(); if (!(stack.getItem() instanceof GunItem)) return; var data = GunData.from(stack); + if (!data.hasEnoughAmmoToShoot(player)) return; + if (stack.is(ModTags.Items.NORMAL_GUN)) { - if (data.ammo.get() > 0) { - int mode = data.fireMode.get(); - if (mode != 2) { - holdFire = false; - } - - if (mode == 1) { - if (data.ammo.get() == 1) { - burstFireAmount = 1; - } - if (burstFireAmount == 1) { - cantFireTime = 30; - } - } - - if (burstFireAmount > 0) { - burstFireAmount--; - } - - if (stack.is(ModItems.DEVOTION.get())) { - int perkLevel = data.perk.getLevel(ModPerks.TURBO_CHARGER); - customRpm = Math.min(customRpm + 15 + ((perkLevel > 0 ? 5 : 0) + 3 * perkLevel), 500); - } - - if (stack.getItem() == ModItems.SENTINEL.get()) { - chamberRot = 1; - } - - if (stack.getItem() == ModItems.NTW_20.get()) { - actionMove = 1; - } - - // 判断是否为栓动武器(BoltActionTime > 0),并在开火后给一个需要上膛的状态 - if (data.defaultActionTime() > 0 && data.ammo.get() > (stack.is(ModTags.Items.REVOLVER) ? 0 : 1)) { - data.bolt.needed.set(true); - } - - revolverPreTime = 0; - revolverWheelPreTime = 0; - - playGunClientSounds(player); - handleClientShoot(); + int mode = data.fireMode.get(); + if (mode != 2) { + holdFire = false; } + + if (mode == 1) { + if (data.ammo.get() == 1) { + burstFireAmount = 1; + } + if (burstFireAmount == 1) { + cantFireTime = 30; + } + } + + if (burstFireAmount > 0) { + burstFireAmount--; + } + + if (stack.is(ModItems.DEVOTION.get())) { + int perkLevel = data.perk.getLevel(ModPerks.TURBO_CHARGER); + customRpm = Math.min(customRpm + 15 + ((perkLevel > 0 ? 5 : 0) + 3 * perkLevel), 500); + } + + if (stack.getItem() == ModItems.SENTINEL.get()) { + chamberRot = 1; + } + + if (stack.getItem() == ModItems.NTW_20.get()) { + actionMove = 1; + } + + // 判断是否为栓动武器(BoltActionTime > 0),并在开火后给一个需要上膛的状态 + if (data.defaultActionTime() > 0 && data.ammo.get() > (stack.is(ModTags.Items.REVOLVER) ? 0 : 1)) { + data.bolt.needed.set(true); + } + + revolverPreTime = 0; + revolverWheelPreTime = 0; + + playGunClientSounds(player); + handleClientShoot(); } else if (stack.is(ModItems.MINIGUN.get())) { - if (data.hasBackupAmmo(player)) { - var perk = data.perk.get(Perk.Type.AMMO); - float pitch = tag.getDouble("heat") <= 40 ? 1 : (float) (1 - 0.025 * Math.abs(40 - tag.getDouble("heat"))); + // TODO 提取通用处理方法 + var perk = data.perk.get(Perk.Type.AMMO); + float pitch = tag.getDouble("heat") <= 40 ? 1 : (float) (1 - 0.025 * Math.abs(40 - tag.getDouble("heat"))); - player.playSound(ModSounds.MINIGUN_FIRE_1P.get(), 1f, pitch); + player.playSound(ModSounds.MINIGUN_FIRE_1P.get(), 1f, pitch); - if (perk == ModPerks.BEAST_BULLET.get()) { - player.playSound(ModSounds.HENG.get(), 1f, 1f); - } - - double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)), - ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))); - - Mod.queueClientWork((int) (1 + 1.5 * shooterHeight), () -> player.playSound(ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1)); + if (perk == ModPerks.BEAST_BULLET.get()) { + player.playSound(ModSounds.HENG.get(), 1f, 1f); } + double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)), + ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))); + + Mod.queueClientWork((int) (1 + 1.5 * shooterHeight), () -> player.playSound(ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1)); + handleClientShoot(); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java index c8d886304..5fd016522 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java @@ -246,15 +246,6 @@ public abstract class GunItem extends Item implements CustomRendererItem { return false; } - /** - * 武器是否直接使用背包内的弹药物品进行发射,而不是使用玩家存储的弹药 - * - * @param stack 武器物品 - */ - public boolean useBackpackAmmo(ItemStack stack) { - return false; - } - /** * 武器是否能进行改装 * @@ -512,15 +503,19 @@ public abstract class GunItem extends Item implements CustomRendererItem { data.bolt.needed.set(true); } - data.ammo.set(data.ammo.get() - 1); - data.isEmpty.set(true); + if (!data.useBackpackAmmo()) { + data.ammo.set(data.ammo.get() - 1); + data.isEmpty.set(true); + } else { + data.consumeBackupAmmo(player, 1); + } } /** * 服务端处理开火 */ public void onShoot(GunData data, Player player, double spread, boolean zoom) { - if (data.ammo.get() <= 0) return; + if (!data.hasEnoughAmmoToShoot(player)) return; // 开火前事件 data.item.beforeShoot(data, player, spread, zoom); @@ -574,7 +569,7 @@ public abstract class GunItem extends Item implements CustomRendererItem { * 服务端处理按下开火按键时的额外行为 */ public void onFireKeyPress(final GunData data, Player player, boolean zoom) { - if (data.reload.prepareTimer.get() == 0 && data.reloading() && data.ammo.get() > 0) { + if (data.reload.prepareTimer.get() == 0 && data.reloading() && data.hasEnoughAmmoToShoot(player)) { data.forceStop.set(true); } diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/data/GunData.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/data/GunData.java index f71e7e4d5..4d1717eb2 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/data/GunData.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/data/GunData.java @@ -171,6 +171,13 @@ public class GunData { return defaultGunData().magazine + item.getCustomMagazine(stack); } + /** + * 武器是否直接使用背包内弹药 + */ + public boolean useBackpackAmmo() { + return magazine() <= 0; + } + public int projectileAmount() { return defaultGunData().projectileAmount; } @@ -362,11 +369,20 @@ public class GunData { } } + /** + * 是否拥有足够的弹药进行开火 + */ + public boolean hasEnoughAmmoToShoot(Player player) { + return useBackpackAmmo() ? hasBackupAmmo(player) : this.ammo.get() > 0; + } + public void reload(Player player) { reload(player, false); } public void reload(Player player, boolean extraOne) { + if (useBackpackAmmo()) return; + int mag = magazine(); int ammo = this.ammo.get(); int ammoNeeded = mag - ammo + (extraOne ? 1 : 0); diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/machinegun/MinigunItem.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/machinegun/MinigunItem.java index 363c7addc..23252ee0b 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/machinegun/MinigunItem.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/machinegun/MinigunItem.java @@ -215,8 +215,4 @@ public class MinigunItem extends GunItem implements GeoItem { return true; } - @Override - public boolean useBackpackAmmo(ItemStack stack) { - return true; - } } \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/special/BocekItem.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/special/BocekItem.java index cf2dca577..8bac06712 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/special/BocekItem.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/special/BocekItem.java @@ -133,11 +133,6 @@ public class BocekItem extends GunItem implements GeoItem { return Optional.of(new BocekImageComponent(pStack)); } - @Override - public boolean useBackpackAmmo(ItemStack stack) { - return true; - } - @Override public String getAmmoDisplayName(GunData data) { return "Arrow"; diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/send/ReloadMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/send/ReloadMessage.java index 4f2946fcd..278242052 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/message/send/ReloadMessage.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/send/ReloadMessage.java @@ -28,15 +28,17 @@ public record ReloadMessage(int msgType) implements CustomPacketPayload { public static void pressAction(Player player, int type) { if (type != 0) return; + ItemStack stack = player.getMainHandItem(); + if (!(stack.getItem() instanceof GunItem gunItem)) return; + + var data = GunData.from(stack); + if (data.useBackpackAmmo()) return; + var cap = player.getData(ModAttachments.PLAYER_VARIABLE).watch(); cap.edit = false; player.setData(ModAttachments.PLAYER_VARIABLE, cap); cap.sync(player); - ItemStack stack = player.getMainHandItem(); - if (!(stack.getItem() instanceof GunItem gunItem)) return; - - var data = GunData.from(stack); if (!player.isSpectator() && !data.charging()