From 87f0c307bf70d0058e2eaff04ed117b488740706 Mon Sep 17 00:00:00 2001 From: Light_Quanta Date: Wed, 2 Apr 2025 16:31:18 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E5=86=99=E7=82=AE=E5=BC=B9=E8=BF=90?= =?UTF-8?q?=E5=8A=A8=EF=BC=8C=E4=BC=98=E5=8C=96=E7=9E=84=E5=87=86=E7=AE=97?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../superbwarfare/client/gui/RangeHelper.java | 169 +++++------------- .../client/overlay/MortarInfoOverlay.java | 2 +- .../component/ModDataComponents.java | 13 +- .../superbwarfare/entity/MortarEntity.java | 33 ++-- .../entity/projectile/CannonShellEntity.java | 2 +- .../projectile/FastThrowableProjectile.java | 20 +++ .../entity/vehicle/AnnihilatorEntity.java | 13 +- .../entity/vehicle/Mk42Entity.java | 42 ++--- .../entity/vehicle/Mle1934Entity.java | 27 ++- .../superbwarfare/item/FiringParameters.java | 45 ++++- .../superbwarfare/menu/FuMO25Menu.java | 6 +- .../message/send/DroneFireMessage.java | 26 +-- .../send/SetFiringParametersMessage.java | 28 +-- .../assets/superbwarfare/lang/en_us.json | 2 + .../assets/superbwarfare/lang/zh_cn.json | 2 + 15 files changed, 219 insertions(+), 211 deletions(-) diff --git a/src/main/java/com/atsuishio/superbwarfare/client/gui/RangeHelper.java b/src/main/java/com/atsuishio/superbwarfare/client/gui/RangeHelper.java index 1b979a1d8..04439a4c8 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/gui/RangeHelper.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/gui/RangeHelper.java @@ -1,149 +1,66 @@ package com.atsuishio.superbwarfare.client.gui; +import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; public class RangeHelper { - public static final int MAX_RANGE = 1145; - /** * 计算迫击炮理论水平射程 * * @param thetaDegrees 发射角度(以度为单位),需要根据实际情况修改 + * @param v 初始速度 + * @param g 重力加速度 */ - public static double getRange(double thetaDegrees) { - double initialVelocity = 11.4; // 初始速度 11.4 m/s - double thetaRadians = Math.toRadians(thetaDegrees); // 将角度转换为弧度 - double gravity = 0.146; // 重力加速度 - double velocityDecay = 0.99; // 速度衰减系数 - - // 计算射程 - return calculateRange(initialVelocity, thetaRadians, gravity, velocityDecay); + public static double getRange(double thetaDegrees, double v, double g) { + double t = v * Math.sin(thetaDegrees * Mth.DEG_TO_RAD) / g * 2; + return t * v * Math.cos(thetaDegrees * Mth.DEG_TO_RAD); } - public static double calculateRange(double initialVelocity, double theta, double gravity, double velocityDecay) { - double vx = initialVelocity * Math.cos(theta); // 水平速度 - double vy = initialVelocity * Math.sin(theta); // 垂直速度 + // 谢谢DeepSeek - double x = 0.0; // 水平位置 - double y = 1.0; // 垂直位置 + /** + * 判断按指定参数发射是否可以击中目标 + * + * @param v 初始速度 + * @param g 重力加速度 + * @param startPos 起始位置 + * @param endPos 目标位置 + * @param minAngle 最小仰角 + * @param maxAngle 最大仰角 + * @param isDepressedTrajectory 是否使用低伸弹道 + */ + public static boolean canReach(double v, double g, Vec3 startPos, Vec3 endPos, double minAngle, double maxAngle, boolean isDepressedTrajectory) { + if (getD(v, g, startPos, endPos) < 0) return false; - // 当炮弹还未触地时,继续计算飞行轨迹 - while (y >= 0) { - // 更新位置 - x += vx; - y += vy; - - // 更新速度 - vx *= velocityDecay; - vy = vy * velocityDecay - gravity; - - // 如果炮弹触地,则跳出循环 - if (y < 0) { - break; - } - } - - // 返回最终水平距离 - return x; + var targetAngle = calculateAngle(v, g, startPos, endPos, isDepressedTrajectory); + return targetAngle >= minAngle && targetAngle <= maxAngle; } - public static double calculateRangeWithDeltaY(double initialVelocity, double theta, double gravity, double velocityDecay, double deltaY) { - double vx = initialVelocity * Math.cos(theta); // 水平速度 - double vy = initialVelocity * Math.sin(theta); // 垂直速度 - - double range = 0.0; // 水平距离 - double y = 1.0; // 垂直位置 - - double commonRange = calculateRange(initialVelocity, theta, gravity, velocityDecay); - - // 当炮弹还未触地时,继续计算飞行轨迹 - while (range < commonRange / 2 || (range >= commonRange / 2 && y >= deltaY)) { - // 更新位置 - range += vx; - y += vy; - - // 更新速度 - vx *= velocityDecay; - vy = vy * velocityDecay - gravity; - - if (range >= commonRange / 2 && y < deltaY) { - break; - } - } - - // 返回最终水平距离 - return range; + /** + * 计算按指定参数发射所需的仰角 + * + * @param v 初始速度 + * @param g 重力加速度 + * @param startPos 起始位置 + * @param endPos 目标位置 + * @param isDepressedTrajectory 是否使用低伸弹道 + */ + public static double calculateAngle(double v, double g, Vec3 startPos, Vec3 endPos, boolean isDepressedTrajectory) { + var xDiff = startPos.x - endPos.x; + var zDiff = startPos.z - endPos.z; + var x = Math.sqrt(Math.pow(xDiff, 2) + Math.pow(zDiff, 2)); + double d = getD(v, g, startPos, endPos); + return Math.atan((v * v + (isDepressedTrajectory ? -d : d)) / (g * x)) * Mth.RAD_TO_DEG; } - public static boolean canReachTarget(double initialVelocity, double gravity, double velocityDecay, Vec3 startPos, Vec3 targetPos, double[] angles) { - if (startPos.equals(targetPos)) { - return false; - } + private static double getD(double v, double g, Vec3 startPos, Vec3 endPos) { + var xDiff = startPos.x - endPos.x; + var zDiff = startPos.z - endPos.z; + var x = Math.sqrt(Math.pow(xDiff, 2) + Math.pow(zDiff, 2)); + var y = startPos.y - endPos.y; - double startX = startPos.x; - double startY = startPos.y; - double startZ = startPos.z; - - double targetX = targetPos.x; - double targetY = targetPos.y; - double targetZ = targetPos.z; - - double distanceXZ = Math.sqrt(Math.pow(targetX - startX, 2) + Math.pow(targetZ - startZ, 2)); - if (distanceXZ > MAX_RANGE) { - return false; - } - - double theta = calculateLaunchAngle(initialVelocity, gravity, velocityDecay, distanceXZ, targetY - startY); - - if (theta < 20 || theta > 90) { - return false; - } - - angles[0] = Math.atan2(targetZ, targetX); // 水平角度 - angles[1] = theta; // 炮口抬升角度 - return true; + return Math.sqrt(Math.pow(v, 4) - g * g * x * x - 2 * g * y * v * v); } - public static double calculateLaunchAngle(double initialVelocity, double gravity, double velocityDecay, double distanceXZ, double targetY) { - double left = 20; // 最小角度 - double right = 30; // 最大角度 - double tolerance = 0.5; // 允许的误差范围 - - // 在 20 到 30 之间搜索 - while (right - left > tolerance) { - double mid = (left + right) / 2; - double radian = Math.toRadians(mid); - double range = calculateRangeWithDeltaY(initialVelocity, radian, gravity, velocityDecay, targetY); - - if (Math.abs(range - distanceXZ) < tolerance * 8) { - return mid; - } else if (range < distanceXZ) { - left = mid; - } else { - right = mid; - } - } - - // 如果在 20 到 30 之间没有找到合适的角度,则在 30 到 90 之间搜索 - left = 30; - right = 90; - - while (right - left > tolerance) { - double mid = (left + right) / 2; - double radian = Math.toRadians(mid); - double range = calculateRangeWithDeltaY(initialVelocity, radian, gravity, velocityDecay, targetY); - - if (Math.abs(range - distanceXZ) < tolerance * 8) { - return mid; - } else if (range < distanceXZ) { - right = mid; - } else { - left = mid; - } - } - - // 如果仍然没有找到合适的角度,则返回 -1 - return -1; - } } diff --git a/src/main/java/com/atsuishio/superbwarfare/client/overlay/MortarInfoOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/overlay/MortarInfoOverlay.java index 82e22d1db..9ec88e854 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/overlay/MortarInfoOverlay.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/overlay/MortarInfoOverlay.java @@ -33,7 +33,7 @@ public class MortarInfoOverlay { .append(Component.literal(FormatTool.format1D(mortar.getYRot(), "°"))), w / 2 - 90, h / 2 - 16, -1, false); event.getGuiGraphics().drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.range") - .append(Component.literal(FormatTool.format1D((int) RangeHelper.getRange(-mortar.getXRot()), "m"))), + .append(Component.literal(FormatTool.format1D((int) RangeHelper.getRange(-mortar.getXRot(), 11.4, 0.146), "m"))), w / 2 - 90, h / 2 - 6, -1, false); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java index 03d8c0a51..d3dd5a2a9 100644 --- a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java +++ b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java @@ -1,10 +1,12 @@ package com.atsuishio.superbwarfare.component; import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.item.FiringParameters; import com.atsuishio.superbwarfare.item.common.ammo.box.AmmoBoxInfo; import com.atsuishio.superbwarfare.tools.AmmoType; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.BlockPos; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; @@ -19,9 +21,14 @@ public class ModDataComponents { public static final DeferredRegister> DATA_COMPONENT_TYPES = DeferredRegister.createDataComponents(Registries.DATA_COMPONENT_TYPE, Mod.MODID); - public static final DeferredHolder, DataComponentType> BLOCK_POS = register( - "coordinates", - builder -> builder.persistent(BlockPos.CODEC) + public static final DeferredHolder, DataComponentType> FIRING_PARAMETERS = register( + "firing_parameters", + builder -> builder.persistent(RecordCodecBuilder.create(instance -> + instance.group( + BlockPos.CODEC.fieldOf("pos").forGetter(FiringParameters.Parameters::pos), + Codec.BOOL.fieldOf("is_depressed").forGetter(FiringParameters.Parameters::isDepressed) + ).apply(instance, FiringParameters.Parameters::new) + )) ); public static final DeferredHolder, DataComponentType> ENERGY = register( diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/MortarEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/MortarEntity.java index aa0d88788..32257c373 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/MortarEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/MortarEntity.java @@ -2,13 +2,13 @@ package com.atsuishio.superbwarfare.entity; import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.client.gui.RangeHelper; +import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.entity.projectile.MortarShellEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity; import com.atsuishio.superbwarfare.init.ModEntities; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.item.common.ammo.MortarShell; -import com.atsuishio.superbwarfare.tools.NBTTool; import net.minecraft.ChatFormatting; import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.core.particles.ParticleTypes; @@ -168,24 +168,29 @@ public class MortarEntity extends VehicleEntity implements GeoEntity { } public boolean setTarget(ItemStack stack) { - var tag = NBTTool.getTag(stack); - double targetX = tag.getDouble("TargetX"); - double targetY = tag.getDouble("TargetY"); - double targetZ = tag.getDouble("TargetZ"); + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + if (parameters == null) return false; + + var pos = parameters.pos(); + double targetX = pos.getX(); + double targetY = pos.getY(); + double targetZ = pos.getZ(); + var isDepressed = parameters.isDepressed(); + + if (!RangeHelper.canReach(11.4, 0.146, this.getEyePosition(), new Vec3(targetX, targetY, targetZ), 20, 89, isDepressed)) { + return false; + } this.look(new Vec3(targetX, targetY, targetZ)); - double[] angles = new double[2]; - boolean flag = RangeHelper.canReachTarget(11.4, 0.146, 0.99, - new Vec3(this.getX(), this.getEyeY(), this.getZ()), + entityData.set(PITCH, (float) -RangeHelper.calculateAngle( + 11.4, 0.146, + this.getEyePosition(), new Vec3(targetX, targetY, targetZ), - angles); + parameters.isDepressed() + )); - if (flag) { - entityData.set(PITCH, (float) -angles[1]); - } - - return flag; + return true; } private void look(Vec3 pTarget) { diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/projectile/CannonShellEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/projectile/CannonShellEntity.java index a27d57c97..1d22072bb 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/projectile/CannonShellEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/projectile/CannonShellEntity.java @@ -358,7 +358,7 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt @Override protected double getDefaultGravity() { - return 0.05F; + return 0.2F; } @Override diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/projectile/FastThrowableProjectile.java b/src/main/java/com/atsuishio/superbwarfare/entity/projectile/FastThrowableProjectile.java index 1144f0eb1..a540101e2 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/projectile/FastThrowableProjectile.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/projectile/FastThrowableProjectile.java @@ -6,6 +6,7 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.projectile.ThrowableItemProjectile; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.entity.IEntityWithComplexSpawn; import net.neoforged.neoforge.network.PacketDistributor; @@ -32,6 +33,25 @@ public abstract class FastThrowableProjectile extends ThrowableItemProjectile im @Override public void tick() { super.tick(); + + Vec3 vec3 = this.getDeltaMovement(); + float friction; + if (this.isInWater()) { + friction = 0.8F; + } else { + friction = 0.99F; + } + // 撤销重力影响 + vec3 = vec3.add(0, this.getGravity(), 0); + // 重新计算动量 + this.setDeltaMovement(vec3.scale(1 / friction)); + // 重新应用重力 + this.applyGravity(); + + // + System.out.println(this.getDeltaMovement()); + + // 同步动量 this.syncMotion(); } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/AnnihilatorEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/AnnihilatorEntity.java index 8cba31313..5ae971263 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/AnnihilatorEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/AnnihilatorEntity.java @@ -1,6 +1,7 @@ package com.atsuishio.superbwarfare.entity.vehicle; import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.config.server.ExplosionConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.entity.projectile.C4Entity; @@ -147,10 +148,14 @@ public class AnnihilatorEntity extends EnergyVehicleEntity implements GeoEntity, } public void setTarget(ItemStack stack) { - var tag = NBTTool.getTag(stack); - int targetX = tag.getInt("TargetX"); - int targetY = tag.getInt("TargetY"); - int targetZ = tag.getInt("TargetZ"); + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + if (parameters == null) return; + + var pos = parameters.pos(); + int targetX = pos.getX(); + int targetY = pos.getY(); + int targetZ = pos.getZ(); + this.look(new Vec3(targetX, targetY, targetZ)); } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Mk42Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Mk42Entity.java index ef27c02d9..0baad78f1 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Mk42Entity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Mk42Entity.java @@ -1,6 +1,8 @@ package com.atsuishio.superbwarfare.entity.vehicle; import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.client.gui.RangeHelper; +import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.config.server.ExplosionConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.entity.vehicle.base.CannonEntity; @@ -15,16 +17,16 @@ import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.init.ModTags; import com.atsuishio.superbwarfare.item.common.ammo.CannonShellItem; import com.atsuishio.superbwarfare.network.message.receive.ShakeClientMessage; -import com.atsuishio.superbwarfare.tools.*; +import com.atsuishio.superbwarfare.tools.CustomExplosion; +import com.atsuishio.superbwarfare.tools.InventoryTool; +import com.atsuishio.superbwarfare.tools.ParticleTool; +import com.atsuishio.superbwarfare.tools.SoundTool; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerEntity; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundSource; @@ -144,36 +146,28 @@ public class Mk42Entity extends VehicleEntity implements GeoEntity, CannonEntity } public void setTarget(ItemStack stack) { - var tag = NBTTool.getTag(stack); - int targetX = tag.getInt("TargetX"); - int targetY = tag.getInt("TargetY"); - int targetZ = tag.getInt("TargetZ"); + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + if (parameters == null) return; + + var pos = parameters.pos(); + int targetX = pos.getX(); + int targetY = pos.getY(); + int targetZ = pos.getZ(); + + if (!RangeHelper.canReach(15, 0.2F, this.getEyePosition(), new Vec3(targetX, targetY, targetZ), -14.9, 85, parameters.isDepressed())) + return; + this.look(new Vec3(targetX, targetY, targetZ)); + entityData.set(PITCH, (float) -RangeHelper.calculateAngle(15, 0.2F, this.getEyePosition(), new Vec3(targetX, targetY, targetZ), parameters.isDepressed())); } private void look(Vec3 pTarget) { Vec3 vec3 = this.getEyePosition(); double d0 = pTarget.x - vec3.x; - double d1 = pTarget.y - vec3.y; double d2 = pTarget.z - vec3.z; - double d3 = Math.sqrt(d0 * d0 + d2 * d2); - double distance = pTarget.distanceTo(vec3); entityData.set(YAW, Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875) - 90.0F)); - entityData.set(PITCH, Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875))) - (float) (distance * 0.008f)); } - // TODO addEntityPacket - @Override - public @NotNull Packet getAddEntityPacket(@NotNull ServerEntity entity) { - return super.getAddEntityPacket(entity); - } - -// @Override -// public Packet getAddEntityPacket() { -// return NetworkHooks.getEntitySpawningPacket(this); -// } - - @Override public void positionRider(@NotNull Entity passenger, @NotNull MoveFunction callback) { if (!this.hasPassenger(passenger)) { diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Mle1934Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Mle1934Entity.java index 1a9e7c87d..b642d6c53 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Mle1934Entity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Mle1934Entity.java @@ -1,6 +1,8 @@ package com.atsuishio.superbwarfare.entity.vehicle; import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.client.gui.RangeHelper; +import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.config.server.ExplosionConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.entity.vehicle.base.CannonEntity; @@ -15,7 +17,10 @@ import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.init.ModTags; import com.atsuishio.superbwarfare.item.common.ammo.CannonShellItem; import com.atsuishio.superbwarfare.network.message.receive.ShakeClientMessage; -import com.atsuishio.superbwarfare.tools.*; +import com.atsuishio.superbwarfare.tools.CustomExplosion; +import com.atsuishio.superbwarfare.tools.InventoryTool; +import com.atsuishio.superbwarfare.tools.ParticleTool; +import com.atsuishio.superbwarfare.tools.SoundTool; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.Packet; @@ -147,22 +152,26 @@ public class Mle1934Entity extends VehicleEntity implements GeoEntity, CannonEnt } public void setTarget(ItemStack stack) { - var tag = NBTTool.getTag(stack); - int targetX = tag.getInt("TargetX"); - int targetY = tag.getInt("TargetY"); - int targetZ = tag.getInt("TargetZ"); + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + if (parameters == null) return; + + var pos = parameters.pos(); + int targetX = pos.getX(); + int targetY = pos.getY(); + int targetZ = pos.getZ(); + + if (!RangeHelper.canReach(15, 0.2F, this.getEyePosition(), new Vec3(targetX, targetY, targetZ), -2.7, 30, parameters.isDepressed())) + return; + this.look(new Vec3(targetX, targetY, targetZ)); + entityData.set(PITCH, (float) -RangeHelper.calculateAngle(15, 0.2F, this.getEyePosition(), new Vec3(targetX, targetY, targetZ), parameters.isDepressed())); } private void look(Vec3 pTarget) { Vec3 vec3 = this.getEyePosition(); double d0 = pTarget.x - vec3.x; - double d1 = pTarget.y - vec3.y; double d2 = pTarget.z - vec3.z; - double d3 = Math.sqrt(d0 * d0 + d2 * d2); - double distance = pTarget.distanceTo(vec3); entityData.set(YAW, Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875) - 90.0F)); - entityData.set(PITCH, Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875))) - (float) (distance * 0.008f)); } @Override diff --git a/src/main/java/com/atsuishio/superbwarfare/item/FiringParameters.java b/src/main/java/com/atsuishio/superbwarfare/item/FiringParameters.java index d6a65570a..29dd6d742 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/FiringParameters.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/FiringParameters.java @@ -4,18 +4,25 @@ import com.atsuishio.superbwarfare.component.ModDataComponents; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; +import javax.annotation.ParametersAreNonnullByDefault; import java.util.List; public class FiringParameters extends Item { + public record Parameters(BlockPos pos, boolean isDepressed) { + } + public FiringParameters() { super(new Properties().stacksTo(1)); } @@ -29,15 +36,39 @@ public class FiringParameters extends Item { BlockPos pos = pContext.getClickedPos(); pos = pos.relative(pContext.getClickedFace()); - stack.set(ModDataComponents.BLOCK_POS, pos); + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + var isDepressed = parameters != null && parameters.isDepressed(); + + stack.set(ModDataComponents.FIRING_PARAMETERS, new Parameters(pos, isDepressed)); return InteractionResult.SUCCESS; } @Override - public void appendHoverText(ItemStack stack, @NotNull TooltipContext context, @NotNull List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { - var pos = stack.get(ModDataComponents.BLOCK_POS); - if (pos == null) return; + @ParametersAreNonnullByDefault + public @NotNull InteractionResultHolder use(Level level, Player player, InteractionHand usedHand) { + if (!player.isCrouching()) return InteractionResultHolder.pass(player.getItemInHand(usedHand)); + var stack = player.getItemInHand(usedHand); + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + if (parameters == null) return InteractionResultHolder.fail(stack); + + var isDepressed = !parameters.isDepressed(); + stack.set(ModDataComponents.FIRING_PARAMETERS, new Parameters(parameters.pos(), isDepressed)); + player.displayClientMessage(Component.translatable( + isDepressed + ? "tips.superbwarfare.mortar.target_pos.depressed_trajectory" + : "tips.superbwarfare.mortar.target_pos.lofted_trajectory" + ).withStyle(ChatFormatting.GREEN), true); + + return InteractionResultHolder.success(stack); + } + + @Override + public void appendHoverText(ItemStack stack, @NotNull TooltipContext context, @NotNull List tooltipComponents, @NotNull TooltipFlag tooltipFlag) { + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + if (parameters == null) return; + + var pos = parameters.pos(); tooltipComponents.add(Component.translatable("tips.superbwarfare.mortar.target_pos") .withStyle(ChatFormatting.GRAY) .append(Component.literal("[" @@ -46,5 +77,11 @@ public class FiringParameters extends Item { + pos.getZ() + "]") ) ); + + tooltipComponents.add(Component.translatable( + parameters.isDepressed + ? "tips.superbwarfare.mortar.target_pos.depressed_trajectory" + : "tips.superbwarfare.mortar.target_pos.lofted_trajectory" + ).withStyle(ChatFormatting.GRAY)); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/menu/FuMO25Menu.java b/src/main/java/com/atsuishio/superbwarfare/menu/FuMO25Menu.java index e3a9b0d06..be41b5e3a 100644 --- a/src/main/java/com/atsuishio/superbwarfare/menu/FuMO25Menu.java +++ b/src/main/java/com/atsuishio/superbwarfare/menu/FuMO25Menu.java @@ -5,6 +5,7 @@ import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.init.ModBlocks; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModMenuTypes; +import com.atsuishio.superbwarfare.item.FiringParameters; import com.atsuishio.superbwarfare.network.dataslot.ContainerEnergyData; import com.atsuishio.superbwarfare.network.dataslot.SimpleEnergyData; import net.minecraft.core.BlockPos; @@ -80,7 +81,10 @@ public class FuMO25Menu extends EnergyMenu { ItemStack stack = this.container.getItem(0); if (stack.isEmpty()) return; - stack.set(ModDataComponents.BLOCK_POS, new BlockPos(this.posX, this.posY, this.posZ)); + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + var isDepressed = parameters != null && parameters.isDepressed(); + + stack.set(ModDataComponents.FIRING_PARAMETERS, new FiringParameters.Parameters(new BlockPos(this.posX, this.posY, this.posZ), isDepressed)); this.resetPos(); this.container.setChanged(); diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/send/DroneFireMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/send/DroneFireMessage.java index 5aaff1339..edcaea308 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/message/send/DroneFireMessage.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/send/DroneFireMessage.java @@ -1,13 +1,16 @@ package com.atsuishio.superbwarfare.network.message.send; import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.entity.vehicle.DroneEntity; import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.item.FiringParameters; import com.atsuishio.superbwarfare.tools.EntityFindUtil; import com.atsuishio.superbwarfare.tools.NBTTool; import com.atsuishio.superbwarfare.tools.SeekTool; import io.netty.buffer.ByteBuf; import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; @@ -21,6 +24,8 @@ import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.network.handling.IPayloadContext; import org.jetbrains.annotations.NotNull; +import java.util.Objects; + public record DroneFireMessage(int msgType) implements CustomPacketPayload { public static final Type TYPE = new Type<>(Mod.loc("drone_fire")); @@ -55,24 +60,23 @@ public record DroneFireMessage(int msgType) implements CustomPacketPayload { } ItemStack offStack = player.getOffhandItem(); - var offTag = NBTTool.getTag(offStack); + var parameters = offStack.get(ModDataComponents.FIRING_PARAMETERS); + var isDepressed = parameters != null && parameters.isDepressed(); + if (lookAtEntity) { - offTag.putDouble("TargetX", lookingEntity.getX()); - offTag.putDouble("TargetY", lookingEntity.getY()); - offTag.putDouble("TargetZ", lookingEntity.getZ()); + offStack.set(ModDataComponents.FIRING_PARAMETERS, new FiringParameters.Parameters(lookingEntity.blockPosition(), isDepressed)); } else { - offTag.putDouble("TargetX", hitPos.x()); - offTag.putDouble("TargetY", hitPos.y()); - offTag.putDouble("TargetZ", hitPos.z()); + offStack.set(ModDataComponents.FIRING_PARAMETERS, new FiringParameters.Parameters(new BlockPos((int) hitPos.x, (int) hitPos.y, (int) hitPos.z), isDepressed)); } - NBTTool.saveTag(offStack, offTag); + + var pos = Objects.requireNonNull(offStack.get(ModDataComponents.FIRING_PARAMETERS)).pos(); player.displayClientMessage(Component.translatable("tips.superbwarfare.mortar.target_pos") .withStyle(ChatFormatting.GRAY) .append(Component.literal("[" - + offTag.getInt("TargetX") - + "," + offTag.getInt("TargetY") - + "," + offTag.getInt("TargetZ") + + pos.getX() + + "," + pos.getY() + + "," + pos.getZ() + "]")), true); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/send/SetFiringParametersMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/send/SetFiringParametersMessage.java index c49e42800..a3387cfe0 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/message/send/SetFiringParametersMessage.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/send/SetFiringParametersMessage.java @@ -1,10 +1,12 @@ package com.atsuishio.superbwarfare.network.message.send; import com.atsuishio.superbwarfare.Mod; -import com.atsuishio.superbwarfare.tools.NBTTool; +import com.atsuishio.superbwarfare.component.ModDataComponents; +import com.atsuishio.superbwarfare.item.FiringParameters; import com.atsuishio.superbwarfare.tools.TraceTool; import io.netty.buffer.ByteBuf; import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; @@ -18,6 +20,8 @@ import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.network.handling.IPayloadContext; import org.jetbrains.annotations.NotNull; +import java.util.Objects; + public record SetFiringParametersMessage(int msgType) implements CustomPacketPayload { public static final Type TYPE = new Type<>(Mod.loc("set_firing_parameters")); @@ -41,25 +45,23 @@ public record SetFiringParametersMessage(int msgType) implements CustomPacketPay lookAtEntity = true; } - var tag = NBTTool.getTag(stack); + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + var isDepressed = parameters != null && parameters.isDepressed(); + if (lookAtEntity) { - tag.putDouble("TargetX", lookingEntity.getX()); - tag.putDouble("TargetY", lookingEntity.getY()); - tag.putDouble("TargetZ", lookingEntity.getZ()); + stack.set(ModDataComponents.FIRING_PARAMETERS, new FiringParameters.Parameters(lookingEntity.blockPosition(), isDepressed)); } else { - tag.putDouble("TargetX", hitPos.x()); - tag.putDouble("TargetY", hitPos.y()); - tag.putDouble("TargetZ", hitPos.z()); + stack.set(ModDataComponents.FIRING_PARAMETERS, new FiringParameters.Parameters(new BlockPos((int) hitPos.x, (int) hitPos.y, (int) hitPos.z), isDepressed)); } - NBTTool.saveTag(stack, tag); + + var pos = Objects.requireNonNull(stack.get(ModDataComponents.FIRING_PARAMETERS)).pos(); player.displayClientMessage(Component.translatable("tips.superbwarfare.mortar.target_pos") .withStyle(ChatFormatting.GRAY) - .append(Component.literal("[" + tag.getInt("TargetX") - + "," + tag.getInt("TargetY") - + "," + tag.getInt("TargetZ") + .append(Component.literal("[" + pos.getX() + + "," + pos.getY() + + "," + pos.getZ() + "]")), true); - } @Override diff --git a/src/main/resources/assets/superbwarfare/lang/en_us.json b/src/main/resources/assets/superbwarfare/lang/en_us.json index 440446f4d..698c40c5a 100644 --- a/src/main/resources/assets/superbwarfare/lang/en_us.json +++ b/src/main/resources/assets/superbwarfare/lang/en_us.json @@ -502,6 +502,8 @@ "tips.superbwarfare.mortar.yaw": "Yaw: ", "tips.superbwarfare.mortar.pitch": "Pitch: ", "tips.superbwarfare.mortar.target_pos": "Target Position: ", + "tips.superbwarfare.mortar.target_pos.depressed_trajectory": "Depressed Trajectory", + "tips.superbwarfare.mortar.target_pos.lofted_trajectory": "Lofted Trajectory", "tips.superbwarfare.mortar.warn": "The mortar cannot aim at this position", "container.superbwarfare.reforging_table": "Gun Reforge Table", diff --git a/src/main/resources/assets/superbwarfare/lang/zh_cn.json b/src/main/resources/assets/superbwarfare/lang/zh_cn.json index 327cc7ef0..e0c4b644f 100644 --- a/src/main/resources/assets/superbwarfare/lang/zh_cn.json +++ b/src/main/resources/assets/superbwarfare/lang/zh_cn.json @@ -500,6 +500,8 @@ "tips.superbwarfare.mortar.yaw": "水平朝向:", "tips.superbwarfare.mortar.pitch": "俯仰角度:", "tips.superbwarfare.mortar.target_pos": "目标坐标:", + "tips.superbwarfare.mortar.target_pos.depressed_trajectory": "低伸弹道", + "tips.superbwarfare.mortar.target_pos.lofted_trajectory": "传统弹道", "tips.superbwarfare.mortar.warn": "迫击炮无法瞄准该位置", "container.superbwarfare.reforging_table": "枪械重铸台",