From ae96635d1192784183e808c4223bcaeb51188d53 Mon Sep 17 00:00:00 2001 From: Light_Quanta Date: Wed, 26 Mar 2025 05:25:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=BB=8B=E5=B4=A9=E5=8F=91?= =?UTF-8?q?=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 + .../superbwarfare/item/BeamTest.java | 11 +- .../network/NetworkRegistry.java | 15 ++ .../network/message/LaserShootMessage.java | 69 +++++++++ .../network/message/ShakeClientMessage.java | 138 ++++++++++++++++++ .../superbwarfare/tools/EntityFindUtil.java | 9 +- .../templates/META-INF/accesstransformer.cfg | 1 + 7 files changed, 238 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/atsuishio/superbwarfare/network/message/LaserShootMessage.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/network/message/ShakeClientMessage.java create mode 100644 src/main/templates/META-INF/accesstransformer.cfg diff --git a/build.gradle b/build.gradle index 30ee8aac7..8fbd5de84 100644 --- a/build.gradle +++ b/build.gradle @@ -215,6 +215,11 @@ tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation } +tasks.named('createMinecraftArtifacts') { + dependsOn tasks.named('generateModMetadata') +} + + // IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior. idea { module { diff --git a/src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java b/src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java index 9eeac7cad..32a78a3e6 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/BeamTest.java @@ -4,6 +4,8 @@ import com.atsuishio.superbwarfare.capability.ModCapabilities; import com.atsuishio.superbwarfare.capability.laser.LaserHandler; import com.atsuishio.superbwarfare.entity.projectile.LaserEntity; import com.atsuishio.superbwarfare.init.ModSounds; +import com.atsuishio.superbwarfare.network.message.LaserShootMessage; +import com.atsuishio.superbwarfare.network.message.ShakeClientMessage; import com.atsuishio.superbwarfare.tools.TraceTool; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundStopSoundPacket; @@ -21,6 +23,7 @@ import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.network.PacketDistributor; import org.jetbrains.annotations.NotNull; import javax.annotation.ParametersAreNonnullByDefault; @@ -93,7 +96,8 @@ public class BeamTest extends Item { } @Override - public ItemStack finishUsingItem(ItemStack pStack, Level pLevel, LivingEntity pLivingEntity) { + @ParametersAreNonnullByDefault + public @NotNull ItemStack finishUsingItem(ItemStack pStack, Level pLevel, LivingEntity pLivingEntity) { if (pLivingEntity instanceof Player player) { var cap = player.getCapability(ModCapabilities.LASER_CAPABILITY); if (cap != null) { @@ -109,8 +113,7 @@ public class BeamTest extends Item { player.playSound(ModSounds.CHARGE_RIFLE_FIRE_BOOM_3P.get(), 4, 1); } if (player instanceof ServerPlayer serverPlayer) { - // TODO network -// ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new ShakeClientMessage(10, 10, 30, serverPlayer.getX(), serverPlayer.getEyeY(), serverPlayer.getZ())); + PacketDistributor.sendToPlayer(serverPlayer, new ShakeClientMessage(10, 10, 30, serverPlayer.getX(), serverPlayer.getEyeY(), serverPlayer.getZ())); } } return super.finishUsingItem(pStack, pLevel, pLivingEntity); @@ -127,7 +130,7 @@ public class BeamTest extends Item { && (!player.isAlliedTo(lookingEntity) || lookingEntity.getTeam() == null || lookingEntity.getTeam().getName().equals("TDM")); if (canAttack) { -// ModUtils.PACKET_HANDLER.sendToServer(new LaserShootMessage(45, lookingEntity.getUUID(), TraceTool.laserHeadshot)); + PacketDistributor.sendToServer(new LaserShootMessage(45, lookingEntity.getUUID(), TraceTool.laserHeadshot)); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java index dab93eac2..cf76e6731 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java @@ -1,6 +1,8 @@ package com.atsuishio.superbwarfare.network; +import com.atsuishio.superbwarfare.network.message.LaserShootMessage; import com.atsuishio.superbwarfare.network.message.PlayerVariablesSyncMessage; +import com.atsuishio.superbwarfare.network.message.ShakeClientMessage; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; import net.neoforged.neoforge.network.registration.PayloadRegistrar; @@ -13,5 +15,18 @@ public class NetworkRegistry { PlayerVariablesSyncMessage.STREAM_CODEC, PlayerVariablesSyncMessage::handler ); + + registrar.playToClient( + ShakeClientMessage.TYPE, + ShakeClientMessage.STREAM_CODEC, + ShakeClientMessage::handler + ); + + registrar.playToServer( + LaserShootMessage.TYPE, + LaserShootMessage.STREAM_CODEC, + LaserShootMessage::handler + ); + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/LaserShootMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/LaserShootMessage.java new file mode 100644 index 000000000..52493f086 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/LaserShootMessage.java @@ -0,0 +1,69 @@ +package com.atsuishio.superbwarfare.network.message; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.init.ModDamageTypes; +import com.atsuishio.superbwarfare.init.ModSounds; +import com.atsuishio.superbwarfare.tools.EntityFindUtil; +import io.netty.buffer.ByteBuf; +import net.minecraft.core.UUIDUtil; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + + +public record LaserShootMessage( + double damage, + UUID id, + boolean headshot +) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(ModUtils.loc("laser_shoot")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.DOUBLE, + LaserShootMessage::damage, + UUIDUtil.STREAM_CODEC, + LaserShootMessage::id, + ByteBufCodecs.BOOL, + LaserShootMessage::headshot, + LaserShootMessage::new + ); + + public static void handler(final LaserShootMessage message, final IPayloadContext context) { + pressAction((ServerPlayer) context.player(), message.damage, message.id, message.headshot); + } + + public static void pressAction(ServerPlayer player, double damage, UUID uuid, boolean headshot) { + Level level = player.level(); + + Entity entity = EntityFindUtil.findEntity(level, String.valueOf(uuid)); + + if (entity != null) { + if (headshot) { + entity.hurt(ModDamageTypes.causeLaserHeadshotDamage(level.registryAccess(), player, player), (float) (2 * damage)); + player.level().playSound(null, player.blockPosition(), ModSounds.HEADSHOT.get(), SoundSource.VOICE, 0.1f, 1); + + // TODO indicator +// ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> player), new ClientIndicatorMessage(1, 5)); + } else { + entity.hurt(ModDamageTypes.causeLaserDamage(level.registryAccess(), player, player), (float) damage); + player.level().playSound(null, player.blockPosition(), ModSounds.INDICATION.get(), SoundSource.VOICE, 0.1f, 1); + + // ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> player), new ClientIndicatorMessage(0, 5)); + } + entity.invulnerableTime = 0; + } + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/ShakeClientMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/ShakeClientMessage.java new file mode 100644 index 000000000..aa58ceece --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/ShakeClientMessage.java @@ -0,0 +1,138 @@ +package com.atsuishio.superbwarfare.network.message; + +import com.atsuishio.superbwarfare.ModUtils; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.ViewportEvent; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.GAME, value = Dist.CLIENT) +public record ShakeClientMessage( + double time, double radius, double amplitude, + double x, double y, double z +) implements CustomPacketPayload { + public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(ModUtils.loc("shake_client")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.DOUBLE, + ShakeClientMessage::time, + ByteBufCodecs.DOUBLE, + ShakeClientMessage::radius, + ByteBufCodecs.DOUBLE, + ShakeClientMessage::amplitude, + ByteBufCodecs.DOUBLE, + ShakeClientMessage::x, + ByteBufCodecs.DOUBLE, + ShakeClientMessage::y, + ByteBufCodecs.DOUBLE, + ShakeClientMessage::z, + ShakeClientMessage::new + ); + + public static void handler(final ShakeClientMessage message, final IPayloadContext context) { + Player player = Minecraft.getInstance().player; + if (player == null) return; + shakeTime = message.time; + shakeRadius = message.radius; + shakeAmplitude = message.amplitude * Mth.DEG_TO_RAD; + shakePos[0] = message.x; + shakePos[1] = message.y; + shakePos[2] = message.z; + shakeType = 2 * (Math.random() - 0.5); + } + + public static double shakeTime = 0; + public static double shakeRadius = 0; + public static double shakeAmplitude = 0; + public static double[] shakePos = {0, 0, 0}; + public static double shakeType = 0; + + @SubscribeEvent + public static void computeCameraAngles(ViewportEvent.ComputeCameraAngles event) { + ClientLevel level = Minecraft.getInstance().level; + Entity entity = event.getCamera().getEntity(); + + if (!(entity instanceof LivingEntity living)) return; + ItemStack stack = living.getMainHandItem(); + +// if (level != null && +// (stack.is(ModItems.MONITOR.get()) && stack.getOrCreateTag().getBoolean("Using") && stack.getOrCreateTag().getBoolean("Linked"))) { +// handleDroneCamera(event, living); +// } else { +// var effect = Minecraft.getInstance().gameRenderer.currentEffect(); +// if (effect != null && effect.getName().equals(ModUtils.MODID + ":shaders/post/scan_pincushion.json")) { +// Minecraft.getInstance().gameRenderer.shutdownEffect(); +// } +// } + + float times = Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(); + LocalPlayer player = Minecraft.getInstance().player; + + float yaw = event.getYaw(); + float pitch = event.getPitch(); + float roll = event.getRoll(); + + shakeTime = Mth.lerp(0.175 * times, shakeTime, 0); + + if (player != null && shakeTime > 0) { + float shakeRadiusAmplitude = (float) Mth.clamp(1 - player.position().distanceTo(new Vec3(shakePos[0], shakePos[1], shakePos[2])) / shakeRadius, 0, 1); + + boolean onVehicle = player.getVehicle() != null; + + if (shakeType > 0) { + event.setYaw((float) (yaw + (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * shakeType * (onVehicle ? 0.4 : 1)))); + event.setPitch((float) (pitch - (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * shakeType * (onVehicle ? 0.4 : 1)))); + event.setRoll((float) (roll - (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * (onVehicle ? 0.4 : 1)))); + } else { + event.setYaw((float) (yaw - (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * shakeType * (onVehicle ? 0.4 : 1)))); + event.setPitch((float) (pitch + (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * shakeType * (onVehicle ? 0.4 : 1)))); + event.setRoll((float) (roll + (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * (onVehicle ? 0.4 : 1)))); + } + } + + // TODO 完善事件处理 +// cameraPitch = event.getPitch(); +// cameraYaw = event.getYaw(); +// cameraRoll = event.getRoll(); +// +// if (player != null && player.getVehicle() instanceof ArmedVehicleEntity iArmedVehicle && iArmedVehicle.banHand(player)) { +// return; +// } +// +// if (level != null && stack.is(ModTags.Items.GUN)) { +// handleWeaponSway(living); +// handleWeaponMove(living); +// handleWeaponZoom(living); +// handlePlayerBreath(living); +// handleWeaponFire(event, living); +// handleWeaponShell(); +// handleGunRecoil(); +// handleBowPullAnimation(living); +// handleWeaponDraw(living); +// handlePlayerCamera(event); +// } +// +// handleShockCamera(event, living); + } + + + @Override + public @NotNull Type type() { + return TYPE; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/EntityFindUtil.java b/src/main/java/com/atsuishio/superbwarfare/tools/EntityFindUtil.java index 44056b40c..183e89544 100644 --- a/src/main/java/com/atsuishio/superbwarfare/tools/EntityFindUtil.java +++ b/src/main/java/com/atsuishio/superbwarfare/tools/EntityFindUtil.java @@ -22,9 +22,7 @@ public class EntityFindUtil { return serverLevel.getEntities(); } var clientLevel = (ClientLevel) level; -// return clientLevel.getEntities(); - // TODO getEntities - return null; + return clientLevel.getEntities(); } /** @@ -43,10 +41,9 @@ public class EntityFindUtil { target = serverLevel.getEntity(uuid); } else { var clientLevel = (ClientLevel) level; -// target = clientLevel.getEntities().get(uuid); + target = clientLevel.getEntities().get(uuid); } -// return target; - return null; + return target; } catch (Exception ignored) { } diff --git a/src/main/templates/META-INF/accesstransformer.cfg b/src/main/templates/META-INF/accesstransformer.cfg new file mode 100644 index 000000000..4ed160a4b --- /dev/null +++ b/src/main/templates/META-INF/accesstransformer.cfg @@ -0,0 +1 @@ +public net.minecraft.client.multiplayer.ClientLevel getEntities()Lnet/minecraft/world/level/entity/LevelEntityGetter; # getEntities