重写炮弹运动,优化瞄准算法

This commit is contained in:
Light_Quanta 2025-04-02 16:31:18 +08:00
parent a79327161c
commit 87f0c307bf
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
15 changed files with 219 additions and 211 deletions

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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<DataComponentType<?>> DATA_COMPONENT_TYPES =
DeferredRegister.createDataComponents(Registries.DATA_COMPONENT_TYPE, Mod.MODID);
public static final DeferredHolder<DataComponentType<?>, DataComponentType<BlockPos>> BLOCK_POS = register(
"coordinates",
builder -> builder.persistent(BlockPos.CODEC)
public static final DeferredHolder<DataComponentType<?>, DataComponentType<FiringParameters.Parameters>> 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<?>, DataComponentType<Integer>> ENERGY = register(

View file

@ -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) {

View file

@ -358,7 +358,7 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
@Override
protected double getDefaultGravity() {
return 0.05F;
return 0.2F;
}
@Override

View file

@ -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();
}

View file

@ -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));
}

View file

@ -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<ClientGamePacketListener> getAddEntityPacket(@NotNull ServerEntity entity) {
return super.getAddEntityPacket(entity);
}
// @Override
// public Packet<ClientGamePacketListener> getAddEntityPacket() {
// return NetworkHooks.getEntitySpawningPacket(this);
// }
@Override
public void positionRider(@NotNull Entity passenger, @NotNull MoveFunction callback) {
if (!this.hasPassenger(passenger)) {

View file

@ -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

View file

@ -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<Component> tooltipComponents, @NotNull TooltipFlag tooltipFlag) {
var pos = stack.get(ModDataComponents.BLOCK_POS);
if (pos == null) return;
@ParametersAreNonnullByDefault
public @NotNull InteractionResultHolder<ItemStack> 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<Component> 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));
}
}

View file

@ -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();

View file

@ -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<DroneFireMessage> 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);
}
}

View file

@ -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<SetFiringParametersMessage> 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

View file

@ -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",

View file

@ -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": "枪械重铸台",