diff --git a/src/main/java/com/atsuishio/superbwarfare/client/overlay/Type63InfoOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/overlay/Type63InfoOverlay.java index 1cc47386f..81dea02d0 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/overlay/Type63InfoOverlay.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/overlay/Type63InfoOverlay.java @@ -1,22 +1,33 @@ package com.atsuishio.superbwarfare.client.overlay; import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.component.ModDataComponents; import com.atsuishio.superbwarfare.entity.vehicle.Type63Entity; -import com.atsuishio.superbwarfare.tools.FormatTool; -import com.atsuishio.superbwarfare.tools.RangeTool; -import com.atsuishio.superbwarfare.tools.TraceTool; +import com.atsuishio.superbwarfare.item.FiringParameters; +import com.atsuishio.superbwarfare.tools.*; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Camera; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.LayeredDraw; +import net.minecraft.commands.arguments.EntityAnchorArgument; +import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.capabilities.Capabilities; import org.jetbrains.annotations.NotNull; import static com.atsuishio.superbwarfare.entity.vehicle.Type63Entity.SHOOT_PITCH; import static com.atsuishio.superbwarfare.entity.vehicle.Type63Entity.SHOOT_YAW; +import static com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity.getXRotFromVector; +import static com.atsuishio.superbwarfare.tools.RangeTool.calculateLaunchVector; public class Type63InfoOverlay implements LayeredDraw.Layer { @@ -26,23 +37,101 @@ public class Type63InfoOverlay implements LayeredDraw.Layer { public void render(GuiGraphics guiGraphics, @NotNull DeltaTracker deltaTracker) { Minecraft mc = Minecraft.getInstance(); Player player = mc.player; + Camera camera = mc.gameRenderer.getMainCamera(); + Vec3 cameraPos = camera.getPosition(); + Vec3 viewVec = new Vec3(camera.getLookVector()); + PoseStack poseStack = guiGraphics.pose(); + var screenWidth = guiGraphics.guiWidth(); var screenHeight = guiGraphics.guiHeight(); + var partialTick = deltaTracker.getGameTimeDeltaPartialTick(true); - Entity lookingEntity = null; + Entity lookingEntity; if (player != null) { - lookingEntity = TraceTool.findLookingEntity(player, 6); - } - if (lookingEntity instanceof Type63Entity type63Entity) { - guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.pitch") - .append(Component.literal(FormatTool.format2D(type63Entity.getEntityData().get(SHOOT_PITCH), "°"))), - screenWidth / 2 - 90, screenHeight / 2 - 26, -1, false); - guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.yaw") - .append(Component.literal(FormatTool.format2D(type63Entity.getEntityData().get(SHOOT_YAW), "°"))), - screenWidth / 2 - 90, screenHeight / 2 - 16, -1, false); - guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.range") - .append(Component.literal(FormatTool.format1D((int) RangeTool.getRange(type63Entity.getEntityData().get(SHOOT_PITCH), 10, 0.05), "m"))), - screenWidth / 2 - 90, screenHeight / 2 - 6, -1, false); + lookingEntity = TraceTool.findLookingEntity(player, player.entityInteractionRange()); + + if (lookingEntity instanceof Type63Entity type63Entity) { + guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.pitch") + .append(Component.literal(FormatTool.format2D(type63Entity.getEntityData().get(SHOOT_PITCH), "°"))), + screenWidth / 2 - 130, screenHeight / 2 - 26, -1, false); + guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.yaw") + .append(Component.literal(FormatTool.format2D(type63Entity.getEntityData().get(SHOOT_YAW), "°"))), + screenWidth / 2 - 130, screenHeight / 2 - 16, -1, false); + guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.range") + .append(Component.literal(FormatTool.format1D((int) RangeTool.getRange(type63Entity.getEntityData().get(SHOOT_PITCH), 10, 0.05), "m"))), + screenWidth / 2 - 130, screenHeight / 2 - 6, -1, false); + + var itemHandler = type63Entity.getCapability(Capabilities.ItemHandler.ENTITY); + + // TODO 正确读取item + + for (int i = 0; i < type63Entity.barrel.length; i++) { + if (OBB.getLookingObb(player, player.entityInteractionRange()) == type63Entity.barrel[i]) { + ItemStack stack = itemHandler.getStackInSlot(i); + + Vec3 pos = new Vec3(type63Entity.barrel[i].center()); + Vec3 point = VectorUtil.worldToScreen(pos, cameraPos); + if (point == null) return; + + poseStack.pushPose(); + float x = (float) point.x; + float y = (float) point.y; + poseStack.translate(x, y, 0); + + String info = stack.getDisplayName().getString(); + int width = Minecraft.getInstance().font.width(info); + + guiGraphics.drawString(Minecraft.getInstance().font, Component.literal(stack.getDisplayName().getString()), + -width / 2, -4, -1, false); + + poseStack.popPose(); + + + } + } + + ItemStack stack = player.getOffhandItem(); + if (stack.getItem() instanceof FiringParameters) { + var parameters = stack.get(ModDataComponents.FIRING_PARAMETERS); + if (parameters == null) { + parameters = new FiringParameters.Parameters(new BlockPos(0, 0, 0)); + } + double targetX = parameters.pos().getX(); + double targetY = parameters.pos().getY() - 1; + double targetZ = parameters.pos().getZ(); + boolean isDepressed = parameters.isDepressed(); + + Vec3 targetPos = new Vec3(targetX, targetY, targetZ); + Vec3 launchVector = calculateLaunchVector(type63Entity.getShootPos(partialTick), targetPos, 10, -0.05, isDepressed); + + Vec3 vec3 = EntityAnchorArgument.Anchor.EYES.apply(lookingEntity); + double d0 = (targetPos.x - vec3.x) * 0.2; + double d2 = (targetPos.z - vec3.z) * 0.2; + double targetYaw = Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875) - 90.0F); + + float angle = 0; + + if (launchVector != null) { + angle = (float) getXRotFromVector(launchVector); + } + + if (angle > -5 && angle < 60) { + guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.target.pitch") + .append(Component.literal(FormatTool.format2D(angle, "°"))), + screenWidth / 2 + 90, screenHeight / 2 - 26, -1, false); + guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.target.yaw") + .append(Component.literal(FormatTool.format2D(targetYaw, "°"))), + screenWidth / 2 + 90, screenHeight / 2 - 16, -1, false); + guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.target_pos") + .append(Component.literal(FormatTool.format0D(targetX) + " " + FormatTool.format0D(targetY) + " " + FormatTool.format0D(targetZ))), + screenWidth / 2 + 90, screenHeight / 2 - 6, -1, false); + } else { + guiGraphics.drawString(Minecraft.getInstance().font, Component.translatable("tips.superbwarfare.mortar.warn", lookingEntity.getDisplayName()).withStyle(ChatFormatting.RED), + screenWidth / 2 + 90, screenHeight / 2 - 26, -1, false); + } + } + } + } } } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Type63Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Type63Entity.java index 814ebce70..3ad769242 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Type63Entity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Type63Entity.java @@ -58,6 +58,7 @@ public class Type63Entity extends ContainerMobileVehicleEntity implements GeoEnt public static final EntityDataAccessor SHOOT_PITCH = SynchedEntityData.defineId(Type63Entity.class, EntityDataSerializers.FLOAT); public static final EntityDataAccessor SHOOT_YAW = SynchedEntityData.defineId(Type63Entity.class, EntityDataSerializers.FLOAT); + public static final EntityDataAccessor> LOADED_AMMO = SynchedEntityData.defineId(Type63Entity.class, ModSerializers.INT_LIST_SERIALIZER.get()); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); @@ -172,11 +173,14 @@ public class Type63Entity extends ContainerMobileVehicleEntity implements GeoEnt if (stack.getItem() instanceof MediumRocketItem) { for (int i = 0; i < this.barrel.length; i++) { - if (OBB.getLookingObb(player, player.entityInteractionRange()) == this.barrel[i] && items.get(i).isEmpty() && level() instanceof ServerLevel) { + if (OBB.getLookingObb(player, player.entityInteractionRange()) == this.barrel[i] && items.get(i).isEmpty() && level() instanceof ServerLevel serverLevel && cooldown == 0) { this.setItem(i, stack.copyWithCount(1)); if (!player.isCreative()) { stack.shrink(1); } + Vec3 vec3 = new Vec3(this.barrel[i].center()); + serverLevel.playSound(null, vec3.x, vec3.y, vec3.z, ModSounds.TYPE_63_RELOAD.get(), SoundSource.PLAYERS, 1f, random.nextFloat() * 0.1f + 0.9f); + cooldown = 5; setChanged(); } player.swing(InteractionHand.MAIN_HAND); @@ -215,8 +219,9 @@ public class Type63Entity extends ContainerMobileVehicleEntity implements GeoEnt if (level() instanceof ServerLevel serverLevel) { interactionTick++; interactionTick += 0.5; - if (tickCount % 2 == 0) { - serverLevel.playSound(null, vec3.x, vec3.y, vec3.z, ModSounds.HAND_WHEEL_ROT.get(), SoundSource.PLAYERS, 1f, random.nextFloat() * 0.1f + 0.9f); + if (cooldown == 0) { + cooldown = 6; + serverLevel.playSound(null, vec3.x, vec3.y, vec3.z, ModSounds.HAND_WHEEL_ROT.get(), SoundSource.PLAYERS, 1f, random.nextFloat() * 0.05f + 0.975f); } } } @@ -366,6 +371,12 @@ public class Type63Entity extends ContainerMobileVehicleEntity implements GeoEnt return new Vec3(rootPosition.x, rootPosition.y, rootPosition.z).vectorTo(new Vec3(targetPosition.x, targetPosition.y, targetPosition.z)); } + public Vec3 getShootPos(float pPartialTicks) { + Matrix4f transform = getBarrelTransform(pPartialTicks); + Vector4f rootPosition = transformPosition(transform, 0, 0.000625f, -0.44625f); + return new Vec3(rootPosition.x, rootPosition.y, rootPosition.z); + } + @Override public void registerControllers(AnimatableManager.ControllerRegistrar data) { } diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModSounds.java b/src/main/java/com/atsuishio/superbwarfare/init/ModSounds.java index a6a4b101d..94a18b248 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModSounds.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModSounds.java @@ -498,6 +498,7 @@ public class ModSounds { public static final DeferredHolder HAND_WHEEL_ROT = REGISTRY.register("hand_wheel_rot", () -> SoundEvent.createVariableRangeEvent(Mod.loc("hand_wheel_rot"))); public static final DeferredHolder MEDIUM_ROCKET_FIRE = REGISTRY.register("medium_rocket_fire", () -> SoundEvent.createVariableRangeEvent(Mod.loc("medium_rocket_fire"))); + public static final DeferredHolder TYPE_63_RELOAD = REGISTRY.register("ty63_reload", () -> SoundEvent.createVariableRangeEvent(Mod.loc("ty63_reload"))); } diff --git a/src/main/resources/assets/superbwarfare/lang/en_us.json b/src/main/resources/assets/superbwarfare/lang/en_us.json index acdf23fea..361bcbdb9 100644 --- a/src/main/resources/assets/superbwarfare/lang/en_us.json +++ b/src/main/resources/assets/superbwarfare/lang/en_us.json @@ -597,6 +597,9 @@ "tips.superbwarfare.mortar.target_pos.depressed_trajectory": "Depressed Trajectory", "tips.superbwarfare.mortar.target_pos.lofted_trajectory": "Lofted Trajectory", "tips.superbwarfare.mortar.warn": "%1$s cannot aim at this position", + "tips.superbwarfare.target.yaw": "Target Yaw: ", + "tips.superbwarfare.target.pitch": "Target Pitch: ", + "container.superbwarfare.reforging_table": "Gun Reforge Table", "container.superbwarfare.charging_station": "Charging Station", diff --git a/src/main/resources/assets/superbwarfare/lang/zh_cn.json b/src/main/resources/assets/superbwarfare/lang/zh_cn.json index abfc64c38..c5d8d5a93 100644 --- a/src/main/resources/assets/superbwarfare/lang/zh_cn.json +++ b/src/main/resources/assets/superbwarfare/lang/zh_cn.json @@ -590,13 +590,15 @@ "tips.superbwarfare.target.damage": "伤害:%1$s 距离:%2$s", "tips.superbwarfare.dps_generator.dps": "DPS: %1$s", "tips.superbwarfare.mortar.range": "射程:", - "tips.superbwarfare.mortar.yaw": "水平朝向:", - "tips.superbwarfare.mortar.pitch": "俯仰角度:", + "tips.superbwarfare.mortar.yaw": "偏航角:", + "tips.superbwarfare.mortar.pitch": "俯仰角:", "tips.superbwarfare.mortar.target_pos": "目标坐标:", "tips.superbwarfare.mortar.target_pos.radius": "打击半径:%1$s", "tips.superbwarfare.mortar.target_pos.depressed_trajectory": "低伸弹道", "tips.superbwarfare.mortar.target_pos.lofted_trajectory": "传统弹道", "tips.superbwarfare.mortar.warn": "%1$s无法瞄准该位置", + "tips.superbwarfare.target.yaw": "目标偏航角: ", + "tips.superbwarfare.target.pitch": "目标俯仰角: ", "container.superbwarfare.reforging_table": "枪械重铸台", "container.superbwarfare.charging_station": "充电站", diff --git a/src/main/resources/assets/superbwarfare/sounds.json b/src/main/resources/assets/superbwarfare/sounds.json index c14e3ba19..3ed708aa4 100644 --- a/src/main/resources/assets/superbwarfare/sounds.json +++ b/src/main/resources/assets/superbwarfare/sounds.json @@ -3400,10 +3400,6 @@ { "name": "superbwarfare:type63/rot1", "stream": true - }, - { - "name": "superbwarfare:type63/rot2", - "stream": true } ] }, @@ -3426,5 +3422,13 @@ "stream": false } ] + }, + "ty63_reload": { + "sounds": [ + { + "name": "superbwarfare:type63/ty63_reload", + "stream": false + } + ] } } \ No newline at end of file diff --git a/src/main/resources/assets/superbwarfare/sounds/type63/rot1.ogg b/src/main/resources/assets/superbwarfare/sounds/type63/rot1.ogg index 08076e505..8967fbe20 100644 Binary files a/src/main/resources/assets/superbwarfare/sounds/type63/rot1.ogg and b/src/main/resources/assets/superbwarfare/sounds/type63/rot1.ogg differ diff --git a/src/main/resources/assets/superbwarfare/sounds/type63/rot2.ogg b/src/main/resources/assets/superbwarfare/sounds/type63/rot2.ogg deleted file mode 100644 index 02fbd3166..000000000 Binary files a/src/main/resources/assets/superbwarfare/sounds/type63/rot2.ogg and /dev/null differ diff --git a/src/main/resources/assets/superbwarfare/sounds/type63/type_63_reload.ogg b/src/main/resources/assets/superbwarfare/sounds/type63/type_63_reload.ogg new file mode 100644 index 000000000..111dd3305 Binary files /dev/null and b/src/main/resources/assets/superbwarfare/sounds/type63/type_63_reload.ogg differ