From b0f0c05e0bba9e8b94986afa94f627a9001af922 Mon Sep 17 00:00:00 2001 From: 3944Realms Date: Sun, 30 Nov 2025 14:47:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC=E4=B8=BA1.?= =?UTF-8?q?0.7=201.=20=E6=B7=BB=E5=8A=A0=E4=BE=BF=E6=8D=B7=E5=A1=AB?= =?UTF-8?q?=E5=85=85=E4=BA=A4=E4=BA=92=E6=96=B9=E6=B3=95=E5=92=8C=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8F=90=E7=A4=BA=202.=20=E6=B7=BB=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=A4=A7=E7=82=AE=E5=8F=91=E5=B0=84=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1de3d2ee724999f84a11b20b51c37030049be277 | 4 +- .../2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac | 4 +- .../c622617f6fabf890a00b9275cd5f643584a8a2c8 | 4 +- .../assets/blasttravelreborn/lang/en_us.json | 5 ++ .../assets/blasttravelreborn/lang/zh_cn.json | 5 ++ .../assets/blasttravelreborn/lang/zh_tw.json | 5 ++ .../api/events/CannonFireEvent.java | 62 +++++++++++++++ .../events/PlayerCannonFlightTickEvent.java | 43 +++++++++++ .../content/entity/CannonEntity.java | 77 ++++++++----------- .../content/entity/cannon/CannonBehavior.java | 15 +++- .../cannon/ConcretePowderCannonBehavior.java | 6 +- .../entity/cannon/EntityCannonBehavior.java | 4 +- .../datagen/value/BTRLangKeys.java | 34 ++++++++ .../mixin/PlayerEntityMixin.java | 29 +------ .../network/toClient/FireCannonPayload.java | 10 --- .../toClient/SyncFlightStatePayload.java | 8 -- 16 files changed, 218 insertions(+), 97 deletions(-) create mode 100644 src/main/java/com/leisuretimedock/blasttravelreborn/api/events/CannonFireEvent.java create mode 100644 src/main/java/com/leisuretimedock/blasttravelreborn/api/events/PlayerCannonFlightTickEvent.java diff --git a/src/generated/resources/.cache/1de3d2ee724999f84a11b20b51c37030049be277 b/src/generated/resources/.cache/1de3d2ee724999f84a11b20b51c37030049be277 index 6089908..8789f1c 100644 --- a/src/generated/resources/.cache/1de3d2ee724999f84a11b20b51c37030049be277 +++ b/src/generated/resources/.cache/1de3d2ee724999f84a11b20b51c37030049be277 @@ -1,2 +1,2 @@ -// 1.20.1 2025-11-22T19:25:06.9619789 Languages: zh_tw -094e7efc852fc45d55f97c0976bf2453de88e219 assets/blasttravelreborn/lang/zh_tw.json +// 1.20.1 2025-11-30T14:45:33.9013121 Languages: zh_tw +44b757dcddc2167ba3ed8fc339cee79e846f1584 assets/blasttravelreborn/lang/zh_tw.json diff --git a/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac b/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac index b90a52e..918f5dc 100644 --- a/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac +++ b/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac @@ -1,2 +1,2 @@ -// 1.20.1 2025-11-22T19:25:06.9619789 Languages: zh_cn -03cccc87a6370bef5c6b95b1d76cd9d22547b86c assets/blasttravelreborn/lang/zh_cn.json +// 1.20.1 2025-11-30T14:45:33.8955012 Languages: zh_cn +e74f7223f158133b80d3a926aface528b4bf7e2b assets/blasttravelreborn/lang/zh_cn.json diff --git a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 index fa5f335..2c0134e 100644 --- a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 +++ b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 @@ -1,2 +1,2 @@ -// 1.20.1 2025-11-22T19:25:06.9619789 Languages: en_us -c3f0d412d3d39f47d1dd4065782d0984a17ed4e7 assets/blasttravelreborn/lang/en_us.json +// 1.20.1 2025-11-30T14:45:33.8997715 Languages: en_us +e8f3919eb4dcc1d7cf4176f3258bc19c6cf7a0b2 assets/blasttravelreborn/lang/en_us.json diff --git a/src/generated/resources/assets/blasttravelreborn/lang/en_us.json b/src/generated/resources/assets/blasttravelreborn/lang/en_us.json index 77fdfd7..a406cff 100644 --- a/src/generated/resources/assets/blasttravelreborn/lang/en_us.json +++ b/src/generated/resources/assets/blasttravelreborn/lang/en_us.json @@ -1,8 +1,13 @@ { "container.blasttravelreborn.cannon_container_menu": "Cannon", "death.attack.blasttravelreborn.cannon": "%s was knocked out by a flying %s", + "dialog.blasttravelreborn.add_behavior_item": "Added %s", + "dialog.blasttravelreborn.add_gunpowder_item": "Added Gunpowder", + "dialog.blasttravelreborn.add_lock_chain_item": "Cannon Locked", + "dialog.blasttravelreborn.fire": "Fire", "dialog.blasttravelreborn.full_cannon": "Cannon is full!", "dialog.blasttravelreborn.no_gunpowder": "Cannon has no gunpowder!", + "dialog.blasttravelreborn.remove_lock_chain_item": "Cannon Unlocked", "entity.blasttravelreborn.cannon": "Cannon", "item.blasttravelreborn.cannon": "Cannon", "mount.blasttravelreborn.cannon.onboard": "Press %s to Exit, or %s to Fire" diff --git a/src/generated/resources/assets/blasttravelreborn/lang/zh_cn.json b/src/generated/resources/assets/blasttravelreborn/lang/zh_cn.json index a93dcf3..95d0208 100644 --- a/src/generated/resources/assets/blasttravelreborn/lang/zh_cn.json +++ b/src/generated/resources/assets/blasttravelreborn/lang/zh_cn.json @@ -1,8 +1,13 @@ { "container.blasttravelreborn.cannon_container_menu": "大炮实体", "death.attack.blasttravelreborn.cannon": "%s被飞行的%s击倒了", + "dialog.blasttravelreborn.add_behavior_item": "填充%s (当前/最大): %d / %d", + "dialog.blasttravelreborn.add_gunpowder_item": "填充火药 (当前/最大): %d / %d", + "dialog.blasttravelreborn.add_lock_chain_item": "添加大炮锁链", + "dialog.blasttravelreborn.fire": "发射", "dialog.blasttravelreborn.full_cannon": "大炮已装满!", "dialog.blasttravelreborn.no_gunpowder": "大炮没有火药了!", + "dialog.blasttravelreborn.remove_lock_chain_item": "移除大炮锁链", "entity.blasttravelreborn.cannon": "大炮", "item.blasttravelreborn.cannon": "大炮", "mount.blasttravelreborn.cannon.onboard": "按%s离开,或按%s发射" diff --git a/src/generated/resources/assets/blasttravelreborn/lang/zh_tw.json b/src/generated/resources/assets/blasttravelreborn/lang/zh_tw.json index cdfb023..afd0049 100644 --- a/src/generated/resources/assets/blasttravelreborn/lang/zh_tw.json +++ b/src/generated/resources/assets/blasttravelreborn/lang/zh_tw.json @@ -1,8 +1,13 @@ { "container.blasttravelreborn.cannon_container_menu": "大砲實體", "death.attack.blasttravelreborn.cannon": "%s被飛行的%s擊倒了", + "dialog.blasttravelreborn.add_behavior_item": "填充%s (當前/最大): %d / %d", + "dialog.blasttravelreborn.add_gunpowder_item": "填充火藥 (當前/最大): %d / %d", + "dialog.blasttravelreborn.add_lock_chain_item": "添加大砲鎖鏈", + "dialog.blasttravelreborn.fire": "發射", "dialog.blasttravelreborn.full_cannon": "大砲已裝滿!", "dialog.blasttravelreborn.no_gunpowder": "大砲沒有火藥了!", + "dialog.blasttravelreborn.remove_lock_chain_item": "移除大砲鎖鏈", "entity.blasttravelreborn.cannon": "大砲", "item.blasttravelreborn.cannon": "大砲", "mount.blasttravelreborn.cannon.onboard": "按%s離開,或按%s發射" diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/api/events/CannonFireEvent.java b/src/main/java/com/leisuretimedock/blasttravelreborn/api/events/CannonFireEvent.java new file mode 100644 index 0000000..4ef8c48 --- /dev/null +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/api/events/CannonFireEvent.java @@ -0,0 +1,62 @@ +package com.leisuretimedock.blasttravelreborn.api.events; + +import com.leisuretimedock.blasttravelreborn.content.entity.CannonEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.eventbus.api.Cancelable; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.IModBusEvent; + +import javax.annotation.Nullable; + +public abstract class CannonFireEvent extends Event implements IModBusEvent { + private final CannonEntity cannonEntity; + @Nullable + private final Player firePlayer; + @Nullable + private final ItemStack fireStack; + public CannonFireEvent(CannonEntity cannonEntity, @Nullable Player firePlayer, @Nullable ItemStack fireStack) { + this.cannonEntity = cannonEntity; + this.firePlayer = firePlayer; + this.fireStack = fireStack; + } + + public CannonEntity getCannonEntity() { + return cannonEntity; + } + + @Nullable + public Player getFirePlayer() { + return firePlayer; + } + + @Nullable + public ItemStack getFireStack() { + return fireStack; + } + + @Cancelable + public static class Pre extends CannonFireEvent { + + public Pre(CannonEntity cannonEntity, Player firePlayer, ItemStack fireStack) { + super(cannonEntity, firePlayer, fireStack); + } + } + public static class Post extends CannonFireEvent { + private final Vec3 firePos; + private final Vec3 fireVel; + public Post(CannonEntity cannonEntity, Player firePlayer, ItemStack fireStack, Vec3 firePos, Vec3 fireVel) { + super(cannonEntity, firePlayer, fireStack); + this.firePos = firePos; + this.fireVel = fireVel; + } + public Vec3 getFirePos() { + return firePos; + } + + public Vec3 getFireVel() { + return fireVel; + } + } +} diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/api/events/PlayerCannonFlightTickEvent.java b/src/main/java/com/leisuretimedock/blasttravelreborn/api/events/PlayerCannonFlightTickEvent.java new file mode 100644 index 0000000..6fc1eea --- /dev/null +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/api/events/PlayerCannonFlightTickEvent.java @@ -0,0 +1,43 @@ +package com.leisuretimedock.blasttravelreborn.api.events; + +import com.leisuretimedock.blasttravelreborn.util.PlayerEntityDuck; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.IModBusEvent; + +public class PlayerCannonFlightTickEvent extends Event implements IModBusEvent { + + private final Entity player; + private final Vec3 velocity; + private final Vec3 pos; + private final long flightTick; + + public PlayerCannonFlightTickEvent(Entity player, Vec3 velocity, Vec3 pos, long flightTick) { + this.player = player; + this.velocity = velocity; + this.pos = pos; + this.flightTick = flightTick; + } + public void cancelFlightState() { + if(player instanceof PlayerEntityDuck playerDuck) { + playerDuck.blasttravel$setCannonFlight(false); + } + } + + public Vec3 getVelocity() { + return velocity; + } + + public Vec3 getPos() { + return pos; + } + + public Entity getPlayer() { + return player; + } + + public long getFlightTick() { + return flightTick; + } +} diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/CannonEntity.java b/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/CannonEntity.java index 180bc49..5990437 100644 --- a/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/CannonEntity.java +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/CannonEntity.java @@ -1,6 +1,7 @@ package com.leisuretimedock.blasttravelreborn.content.entity; import com.leisuretimedock.blasttravelreborn.BlastTravelReborn; +import com.leisuretimedock.blasttravelreborn.api.events.CannonFireEvent; import com.leisuretimedock.blasttravelreborn.content.BTRParticleTypes; import com.leisuretimedock.blasttravelreborn.content.entity.cannon.CannonBehavior; import com.leisuretimedock.blasttravelreborn.content.entity.cannon.ConcretePowderCannonBehavior; @@ -14,6 +15,7 @@ import com.leisuretimedock.blasttravelreborn.util.PlayerEntityDuck; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.resources.language.I18n; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -39,8 +41,6 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.javafmlmod.FMLModContainer; -import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.network.NetworkDirection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -50,6 +50,11 @@ public class CannonEntity extends Entity { public static final Component UI_TITLE = Component.translatable("container.blasttravelreborn.cannon_container_menu"); public static final Component NO_GUNPOWDER_DIALOG = Component.translatable("dialog.blasttravelreborn.no_gunpowder").withStyle(ChatFormatting.RED); public static final Component FULL_CANNON_DIALOG = Component.translatable("dialog.blasttravelreborn.full_cannon").withStyle(ChatFormatting.RED); + public static final String ADD_GUNPOWDER_DIALOG = "dialog.blasttravelreborn.add_gunpowder_item"; + public static final String ADD_BEHAVIOR_DIALOG = "dialog.blasttravelreborn.add_behavior_item"; + public static final String ADD_LOCK_CHAIN_DIALOG = "dialog.blasttravelreborn.add_lock_chain_item"; + public static final String REMOVE_LOCK_CHAIN_DIALOG = "dialog.blasttravelreborn.remove_lock_chain_item"; + public static final Component FIRE = Component.translatable("dialog.blasttravelreborn.fire").withStyle(ChatFormatting.RED); public static final CannonBehavior NONE = new CannonBehavior(Items.AIR, stack -> false).register(); public static final CannonBehavior GOLDEN = new CannonBehavior(Items.GOLD_BLOCK, BlastTravelReborn.id("textures/entity/cannon/golden.png")).register(); @@ -212,6 +217,7 @@ public class CannonEntity extends Entity { handlerBehaviorItem(player, stack); return true; } else if (stack.is(Items.FLINT_AND_STEEL)) { + player.displayClientMessage(FIRE, true); fireServer(); return true; } @@ -231,7 +237,7 @@ public class CannonEntity extends Entity { // 设置新的火药到炮中 ItemStack newGunpowder = stack.copy(); newGunpowder.setCount(currentGunpowder.getCount() + 1); // 只放一个火药 - ((ServerPlayer) player).sendSystemMessage(Component.literal(String.format("%d / %d", currentGunpowder.getCount() + 1, currentGunpowder.getMaxStackSize())), true); + ((ServerPlayer) player).sendSystemMessage(Component.translatable(ADD_GUNPOWDER_DIALOG, Math.min(currentGunpowder.getCount() + 1, currentGunpowder.getMaxStackSize()), currentGunpowder.getMaxStackSize()), true); inventory.setItem(0, newGunpowder); if (!player.isCreative()) { @@ -252,6 +258,7 @@ public class CannonEntity extends Entity { if (!player.isCreative()) { stack.shrink(1); } + ((ServerPlayer) player).sendSystemMessage(Component.translatable(ADD_LOCK_CHAIN_DIALOG).withStyle(ChatFormatting.GREEN), true); level().playSound(null, this.blockPosition(), SoundEvents.CHAIN_PLACE, SoundSource.BLOCKS, 1.0f, 1.0f); } else { inventory.setItem(1, ItemStack.EMPTY); @@ -260,6 +267,7 @@ public class CannonEntity extends Entity { player.drop(currentChain, false); } } + ((ServerPlayer) player).sendSystemMessage(Component.translatable(REMOVE_LOCK_CHAIN_DIALOG).withStyle(ChatFormatting.RED), true); level().playSound(null, this.blockPosition(), SoundEvents.CHAIN_FALL, SoundSource.BLOCKS, 1.0f, 1.0f); } } @@ -285,7 +293,7 @@ public class CannonEntity extends Entity { } ItemStack stack1 = stack.copy(); stack1.setCount(currentBehaviorItem.getCount() + 1); - ((ServerPlayer) player).sendSystemMessage(Component.literal(String.format("%d / %d", currentBehaviorItem.getCount() + 1, currentBehaviorItem.getMaxStackSize())), true); + ((ServerPlayer) player).sendSystemMessage(Component.translatable(ADD_BEHAVIOR_DIALOG, I18n.get(currentBehaviorItem.getDescriptionId()),Math.min(currentBehaviorItem.getCount() + 1, currentBehaviorItem.getMaxStackSize()), currentBehaviorItem.getMaxStackSize()), true); inventory.setItem(2, stack1); if (!player.isCreative()) { @@ -300,6 +308,7 @@ public class CannonEntity extends Entity { ItemStack copied = stack.copy(); copied.setCount(1); inventory.setItem(2, copied); + ((ServerPlayer) player).sendSystemMessage(Component.translatable(ADD_BEHAVIOR_DIALOG, I18n.get(stack.getDescriptionId()), 1, stack.getMaxStackSize()), true); if (!player.isCreative()) { stack.shrink(1); } @@ -391,50 +400,32 @@ public class CannonEntity extends Entity { if (this.level() instanceof ServerLevel world) { var gunpowder = this.inventory.getItem(0); if (gunpowder.is(Items.GUNPOWDER) && gunpowder.getCount() > 0) { + CannonFireEvent.Pre pre; Player firedPlayer = null; var behaviorStack = this.getBehaviorStack(); - var vel = getDeltaMovement().add(getLookAngle().scale(Math.sqrt(gunpowder.getCount()) * 0.6)); - this.getBehavior().onFired(this, behaviorStack, vel); - - if (this.getFirstPassenger() instanceof Player player) { - if (!FMLEnvironment.production) { - System.out.println("Firing cannon:"); - System.out.println(" - Gunpowder: " + gunpowder.getCount()); - System.out.println(" - Look Angle: " + getLookAngle()); - System.out.println(" - Final Velocity: " + vel); - System.out.println(" - Pitch: " + this.getXRot() + ", Yaw: " + this.getYRot()); - System.out.println(" - Behavior: " + getBehavior().getClass().getSimpleName()); - System.out.println(" - [B]Server: Is Passenger = " + player.isPassenger()); - System.out.println(" - [B]Server: On Ground = " + player.onGround()); - System.out.println(" - [B]Server: noPhysics =" + player.noPhysics); - System.out.println(" - [B]Server: Pose =" + player.getPose()); - System.out.println(" - [B]Server: riding entity =" + player.getVehicle()); - System.out.println(" - [B]Server: Bounding Box = " + player.getBoundingBox()); - System.out.println(" - [B]Server: Delta Movement = " + player.getDeltaMovement()); - } - - // 关键修改:先设置速度,再停止乘坐 - player.setDeltaMovement(vel); - player.hurtMarked = true; // 强制同步运动状态 - - // 然后停止乘坐 - player.stopRiding(); - - // 设置飞行状态 - ((PlayerEntityDuck)player).blasttravel$setCannonFlight(true); - - if (!FMLEnvironment.production) { - System.out.println(" - [A]Server: Is Passenger = " + player.isPassenger()); - System.out.println(" - [A]Server: On Ground = " + player.onGround()); - System.out.println(" - [A]Server: noPhysics =" + player.noPhysics); - System.out.println(" - [A]Server: Pose =" + player.getPose()); - System.out.println(" - [A]Server: riding entity =" + player.getVehicle()); - System.out.println(" - [A]Server: Bounding Box = " + player.getBoundingBox()); - System.out.println(" - [A]Server: Delta Movement = " + player.getDeltaMovement()); - } + if(getFirstPassenger() instanceof Player player) { firedPlayer = player; } + pre = new CannonFireEvent.Pre(this, firedPlayer, behaviorStack); + if(pre.isCanceled()) return; + var vel = getDeltaMovement().add(getLookAngle().scale(Math.sqrt(gunpowder.getCount()) * 0.6)); + CannonBehavior behavior = this.getBehavior(); + if (firedPlayer != null) { + + // 关键修改:先设置速度,再停止乘坐 + firedPlayer.setDeltaMovement(vel); + firedPlayer.hurtMarked = true; // 强制同步运动状态 + + // 然后停止乘坐 + firedPlayer.stopRiding(); + + // 设置飞行状态 + ((PlayerEntityDuck)firedPlayer).blasttravel$setCannonFlight(true); + + } + if(pre.isCanceled()) return; + behavior.onFired(this, behaviorStack, vel); this.level().playSound(null, this.blockPosition(), SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 1, 1); for (var to : world.players()) { BTRNetwork.CHANNEL.sendTo(new FireCannonPayload(this, firedPlayer, vel), to.connection.connection, NetworkDirection.PLAY_TO_CLIENT); diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/CannonBehavior.java b/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/CannonBehavior.java index dd50053..bd16b0d 100644 --- a/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/CannonBehavior.java +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/CannonBehavior.java @@ -1,17 +1,22 @@ package com.leisuretimedock.blasttravelreborn.content.entity.cannon; import com.leisuretimedock.blasttravelreborn.BlastTravelReborn; +import com.leisuretimedock.blasttravelreborn.api.events.CannonFireEvent; import com.leisuretimedock.blasttravelreborn.content.entity.CannonEntity; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; @@ -71,7 +76,7 @@ public class CannonBehavior { } @OnlyIn(Dist.CLIENT) - public boolean displayHead(CannonEntity entity) { + public boolean displayHead(@NotNull CannonEntity entity) { return entity.getClientPlayer() != null; } @@ -79,7 +84,13 @@ public class CannonBehavior { return false; } - public void onFired(CannonEntity cannon, ItemStack behaviorStack, Vec3 velocity) { + public void onFired(@NotNull CannonEntity cannon, ItemStack behaviorStack, Vec3 velocity) { + Entity firstPassenger = cannon.getFirstPassenger(); + Player player = null; + if (firstPassenger instanceof Player player1) { + player = player1; + } + MinecraftForge.EVENT_BUS.post(new CannonFireEvent.Post(cannon, player, behaviorStack, cannon.position(), velocity)); } public static CannonBehavior byId(int id) { diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/ConcretePowderCannonBehavior.java b/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/ConcretePowderCannonBehavior.java index 10bd233..5213756 100644 --- a/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/ConcretePowderCannonBehavior.java +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/ConcretePowderCannonBehavior.java @@ -12,6 +12,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.ConcretePowderBlock; import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; @@ -28,7 +29,7 @@ public class ConcretePowderCannonBehavior extends CannonBehavior { } @Override - public boolean displayHead(CannonEntity entity) { + public boolean displayHead(@NotNull CannonEntity entity) { return true; } @@ -46,7 +47,8 @@ public class ConcretePowderCannonBehavior extends CannonBehavior { } @Override - public void onFired(CannonEntity cannon, ItemStack behaviorStack, Vec3 velocity) { + public void onFired(@NotNull CannonEntity cannon, ItemStack behaviorStack, Vec3 velocity) { + super.onFired(cannon, behaviorStack, velocity); if (cannon.level() instanceof ServerLevel world) { var rot = cannon.getLookAngle(); var origin = cannon.position().add(0, 0.75, 0).add(rot.scale(1.8)); diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/EntityCannonBehavior.java b/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/EntityCannonBehavior.java index 8ef0f49..2152bf7 100644 --- a/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/EntityCannonBehavior.java +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/content/entity/cannon/EntityCannonBehavior.java @@ -11,6 +11,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; import java.util.function.Predicate; @@ -32,7 +33,8 @@ public class EntityCannonBehavior extends CannonBehavior { } @Override - public void onFired(CannonEntity cannon, ItemStack behaviorStack, Vec3 velocity) { + public void onFired(@NotNull CannonEntity cannon, ItemStack behaviorStack, Vec3 velocity) { + super.onFired(cannon, behaviorStack, velocity); var pos = cannon.position().add(0, 0.75, 0).add(cannon.getLookAngle().scale(1.8)); var entity = entityFactory.create(cannon.level(), pos, behaviorStack); entity.setDeltaMovement(velocity); diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/datagen/value/BTRLangKeys.java b/src/main/java/com/leisuretimedock/blasttravelreborn/datagen/value/BTRLangKeys.java index a489636..1b64092 100644 --- a/src/main/java/com/leisuretimedock/blasttravelreborn/datagen/value/BTRLangKeys.java +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/datagen/value/BTRLangKeys.java @@ -56,6 +56,40 @@ public enum BTRLangKeys implements ILangKeyValueCollection { "大炮没有火药了!", "大砲沒有火藥了!" )); + addLang(LangKeyValue.ofKey( + "dialog.blasttravelreborn.add_gunpowder_item", ModPartEnum.MESSAGE, + "Added Gunpowder", + "填充火药 (当前/最大): %d / %d", + "填充火藥 (當前/最大): %d / %d" + )); + + addLang(LangKeyValue.ofKey( + "dialog.blasttravelreborn.add_behavior_item", ModPartEnum.MESSAGE, + "Added %s", + "填充%s (当前/最大): %d / %d", + "填充%s (當前/最大): %d / %d" + )); + + addLang(LangKeyValue.ofKey( + "dialog.blasttravelreborn.add_lock_chain_item", ModPartEnum.MESSAGE, + "Cannon Locked", + "添加大炮锁链", + "添加大砲鎖鏈" + )); + + addLang(LangKeyValue.ofKey( + "dialog.blasttravelreborn.remove_lock_chain_item", ModPartEnum.MESSAGE, + "Cannon Unlocked", + "移除大炮锁链", + "移除大砲鎖鏈" + )); + + addLang(LangKeyValue.ofKey( + "dialog.blasttravelreborn.fire", ModPartEnum.MESSAGE, + "Fire", + "发射", + "發射" + )); addLang(LangKeyValue.ofKey( "mount.blasttravelreborn.cannon.onboard", ModPartEnum.MESSAGE, "Press %s to Exit, or %s to Fire", diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/mixin/PlayerEntityMixin.java b/src/main/java/com/leisuretimedock/blasttravelreborn/mixin/PlayerEntityMixin.java index 06a1369..a38888b 100644 --- a/src/main/java/com/leisuretimedock/blasttravelreborn/mixin/PlayerEntityMixin.java +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/mixin/PlayerEntityMixin.java @@ -1,10 +1,12 @@ package com.leisuretimedock.blasttravelreborn.mixin; import com.leisuretimedock.blasttravelreborn.BlastTravelReborn; +import com.leisuretimedock.blasttravelreborn.api.events.PlayerCannonFlightTickEvent; import com.leisuretimedock.blasttravelreborn.network.BTRNetwork; import com.leisuretimedock.blasttravelreborn.network.toClient.SyncFlightStatePayload; import com.leisuretimedock.blasttravelreborn.network.toServer.StopCannonFlightServerPayload; import com.leisuretimedock.blasttravelreborn.util.PlayerEntityDuck; +import net.minecraft.client.Minecraft; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerPlayer; @@ -19,6 +21,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.entity.EntityTypeTest; import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.network.NetworkDirection; import org.spongepowered.asm.mixin.Mixin; @@ -63,30 +66,6 @@ public abstract class PlayerEntityMixin extends LivingEntity implements PlayerEn @Inject(method = "tick", at = @At("HEAD")) private void blasttravel$beginTick(CallbackInfo ci) { this.blasttravel$prevVel = this.isLocalPlayer() ? blasttravel$vel : blasttravel$trackingVel; - if(!FMLEnvironment.production) { - if (blasttravel$inCannonFlight) { - // 获取当前速度 - Vec3 currentVelocity = this.getDeltaMovement(); - double speed = currentVelocity.length(); - - // 记录到对应的速度列表 - if (this.isLocalPlayer()) { - // 客户端本地玩家 - blasttravel$vel = currentVelocity; - System.out.println("[Client-Local] Tick: " + this.level().getGameTime() + - ", Velocity: " + currentVelocity + - ", Speed: " + String.format("%.3f", speed) + - ", Position: " + this.position()); - } else { - System.out.println("[Server] Tick: " + this.level().getGameTime() + - ", Velocity: " + currentVelocity + - ", Speed: " + String.format("%.3f", speed) + - ", Position: " + String.format("(%.1f, %.1f, %.1f)", this.getX(), this.getY(), this.getZ()) + - ", OnGround: " + this.onGround() + - ", noPhysics: " + this.noPhysics); - } - } - } } @Inject(method = "tick", at = @At("TAIL")) @@ -96,7 +75,7 @@ public abstract class PlayerEntityMixin extends LivingEntity implements PlayerEn if (this.blasttravel$inCannonFlight()) { this.noPhysics = true; - + MinecraftForge.EVENT_BUS.post(new PlayerCannonFlightTickEvent(self, blasttravel$vel, self.position(), blasttravel$ticksFlying)); if (!self.level().isClientSide()) { var vel = self.getDeltaMovement(); var frontBox = self.getBoundingBox().expandTowards(0.2, 0.2, 0.2); diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/network/toClient/FireCannonPayload.java b/src/main/java/com/leisuretimedock/blasttravelreborn/network/toClient/FireCannonPayload.java index d73b46a..d7d406f 100644 --- a/src/main/java/com/leisuretimedock/blasttravelreborn/network/toClient/FireCannonPayload.java +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/network/toClient/FireCannonPayload.java @@ -44,11 +44,6 @@ public record FireCannonPayload(int cannonId, Optional launchedId, doub if (hasPlayer()) { //noinspection OptionalGetWithoutIsPresent if (clientPacketListener.getLevel().getEntity(launchedId.get()) instanceof Player launchedPlayer) { - // 记录发射前状态 - if (!FMLEnvironment.production) { - System.out.println(" - [B]Client: Is Passenger = " + launchedPlayer.isPassenger()); - System.out.println(" - [B]Client: Delta Movement = " + launchedPlayer.getDeltaMovement()); - } // 立即停止乘坐并设置速度 if (launchedPlayer.isPassenger()) { @@ -59,11 +54,6 @@ public record FireCannonPayload(int cannonId, Optional launchedId, doub launchedPlayer.setDeltaMovement(velocityX, velocityY, velocityZ); ((PlayerEntityDuck) launchedPlayer).blasttravel$setCannonFlight(true); - // 记录发射后状态 - if (!FMLEnvironment.production) { - System.out.println(" - [A]Client: Is Passenger = " + launchedPlayer.isPassenger()); - System.out.println(" - [A]Client: Delta Movement = " + launchedPlayer.getDeltaMovement()); - } } } diff --git a/src/main/java/com/leisuretimedock/blasttravelreborn/network/toClient/SyncFlightStatePayload.java b/src/main/java/com/leisuretimedock/blasttravelreborn/network/toClient/SyncFlightStatePayload.java index 04c1a40..66e107b 100644 --- a/src/main/java/com/leisuretimedock/blasttravelreborn/network/toClient/SyncFlightStatePayload.java +++ b/src/main/java/com/leisuretimedock/blasttravelreborn/network/toClient/SyncFlightStatePayload.java @@ -64,14 +64,6 @@ public record SyncFlightStatePayload( player.noPhysics = this.noPhysics; player.hurtMarked = true; - // 调试输出 - if (!FMLEnvironment.production) { - System.out.println("[Client] Received flight sync: " + - "Vel=" + this.velocity + ", " + - "Pos=" + this.position + ", " + - "Flight=" + this.inCannonFlight + ", " + - "NoPhysics=" + this.noPhysics); - } } } });