更新版本为1.0.7
1. 添加便捷填充交互方法和相关提示 2. 添加了相关大炮发射事件
This commit is contained in:
parent
e3ba40f8ff
commit
b0f0c05e0b
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2025-11-22T19:25:06.9619789 Languages: zh_tw
|
// 1.20.1 2025-11-30T14:45:33.9013121 Languages: zh_tw
|
||||||
094e7efc852fc45d55f97c0976bf2453de88e219 assets/blasttravelreborn/lang/zh_tw.json
|
44b757dcddc2167ba3ed8fc339cee79e846f1584 assets/blasttravelreborn/lang/zh_tw.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2025-11-22T19:25:06.9619789 Languages: zh_cn
|
// 1.20.1 2025-11-30T14:45:33.8955012 Languages: zh_cn
|
||||||
03cccc87a6370bef5c6b95b1d76cd9d22547b86c assets/blasttravelreborn/lang/zh_cn.json
|
e74f7223f158133b80d3a926aface528b4bf7e2b assets/blasttravelreborn/lang/zh_cn.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2025-11-22T19:25:06.9619789 Languages: en_us
|
// 1.20.1 2025-11-30T14:45:33.8997715 Languages: en_us
|
||||||
c3f0d412d3d39f47d1dd4065782d0984a17ed4e7 assets/blasttravelreborn/lang/en_us.json
|
e8f3919eb4dcc1d7cf4176f3258bc19c6cf7a0b2 assets/blasttravelreborn/lang/en_us.json
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
{
|
{
|
||||||
"container.blasttravelreborn.cannon_container_menu": "Cannon",
|
"container.blasttravelreborn.cannon_container_menu": "Cannon",
|
||||||
"death.attack.blasttravelreborn.cannon": "%s was knocked out by a flying %s",
|
"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.full_cannon": "Cannon is full!",
|
||||||
"dialog.blasttravelreborn.no_gunpowder": "Cannon has no gunpowder!",
|
"dialog.blasttravelreborn.no_gunpowder": "Cannon has no gunpowder!",
|
||||||
|
"dialog.blasttravelreborn.remove_lock_chain_item": "Cannon Unlocked",
|
||||||
"entity.blasttravelreborn.cannon": "Cannon",
|
"entity.blasttravelreborn.cannon": "Cannon",
|
||||||
"item.blasttravelreborn.cannon": "Cannon",
|
"item.blasttravelreborn.cannon": "Cannon",
|
||||||
"mount.blasttravelreborn.cannon.onboard": "Press %s to Exit, or %s to Fire"
|
"mount.blasttravelreborn.cannon.onboard": "Press %s to Exit, or %s to Fire"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
{
|
{
|
||||||
"container.blasttravelreborn.cannon_container_menu": "大炮实体",
|
"container.blasttravelreborn.cannon_container_menu": "大炮实体",
|
||||||
"death.attack.blasttravelreborn.cannon": "%s被飞行的%s击倒了",
|
"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.full_cannon": "大炮已装满!",
|
||||||
"dialog.blasttravelreborn.no_gunpowder": "大炮没有火药了!",
|
"dialog.blasttravelreborn.no_gunpowder": "大炮没有火药了!",
|
||||||
|
"dialog.blasttravelreborn.remove_lock_chain_item": "移除大炮锁链",
|
||||||
"entity.blasttravelreborn.cannon": "大炮",
|
"entity.blasttravelreborn.cannon": "大炮",
|
||||||
"item.blasttravelreborn.cannon": "大炮",
|
"item.blasttravelreborn.cannon": "大炮",
|
||||||
"mount.blasttravelreborn.cannon.onboard": "按%s离开,或按%s发射"
|
"mount.blasttravelreborn.cannon.onboard": "按%s离开,或按%s发射"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
{
|
{
|
||||||
"container.blasttravelreborn.cannon_container_menu": "大砲實體",
|
"container.blasttravelreborn.cannon_container_menu": "大砲實體",
|
||||||
"death.attack.blasttravelreborn.cannon": "%s被飛行的%s擊倒了",
|
"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.full_cannon": "大砲已裝滿!",
|
||||||
"dialog.blasttravelreborn.no_gunpowder": "大砲沒有火藥了!",
|
"dialog.blasttravelreborn.no_gunpowder": "大砲沒有火藥了!",
|
||||||
|
"dialog.blasttravelreborn.remove_lock_chain_item": "移除大砲鎖鏈",
|
||||||
"entity.blasttravelreborn.cannon": "大砲",
|
"entity.blasttravelreborn.cannon": "大砲",
|
||||||
"item.blasttravelreborn.cannon": "大砲",
|
"item.blasttravelreborn.cannon": "大砲",
|
||||||
"mount.blasttravelreborn.cannon.onboard": "按%s離開,或按%s發射"
|
"mount.blasttravelreborn.cannon.onboard": "按%s離開,或按%s發射"
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.leisuretimedock.blasttravelreborn.content.entity;
|
package com.leisuretimedock.blasttravelreborn.content.entity;
|
||||||
|
|
||||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||||
|
import com.leisuretimedock.blasttravelreborn.api.events.CannonFireEvent;
|
||||||
import com.leisuretimedock.blasttravelreborn.content.BTRParticleTypes;
|
import com.leisuretimedock.blasttravelreborn.content.BTRParticleTypes;
|
||||||
import com.leisuretimedock.blasttravelreborn.content.entity.cannon.CannonBehavior;
|
import com.leisuretimedock.blasttravelreborn.content.entity.cannon.CannonBehavior;
|
||||||
import com.leisuretimedock.blasttravelreborn.content.entity.cannon.ConcretePowderCannonBehavior;
|
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.ChatFormatting;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.player.AbstractClientPlayer;
|
import net.minecraft.client.player.AbstractClientPlayer;
|
||||||
|
import net.minecraft.client.resources.language.I18n;
|
||||||
import net.minecraft.core.particles.ParticleTypes;
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.chat.Component;
|
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.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
|
|
||||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
|
||||||
import net.minecraftforge.network.NetworkDirection;
|
import net.minecraftforge.network.NetworkDirection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
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 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 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 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 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();
|
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);
|
handlerBehaviorItem(player, stack);
|
||||||
return true;
|
return true;
|
||||||
} else if (stack.is(Items.FLINT_AND_STEEL)) {
|
} else if (stack.is(Items.FLINT_AND_STEEL)) {
|
||||||
|
player.displayClientMessage(FIRE, true);
|
||||||
fireServer();
|
fireServer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -231,7 +237,7 @@ public class CannonEntity extends Entity {
|
||||||
// 设置新的火药到炮中
|
// 设置新的火药到炮中
|
||||||
ItemStack newGunpowder = stack.copy();
|
ItemStack newGunpowder = stack.copy();
|
||||||
newGunpowder.setCount(currentGunpowder.getCount() + 1); // 只放一个火药
|
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);
|
inventory.setItem(0, newGunpowder);
|
||||||
|
|
||||||
if (!player.isCreative()) {
|
if (!player.isCreative()) {
|
||||||
|
|
@ -252,6 +258,7 @@ public class CannonEntity extends Entity {
|
||||||
if (!player.isCreative()) {
|
if (!player.isCreative()) {
|
||||||
stack.shrink(1);
|
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);
|
level().playSound(null, this.blockPosition(), SoundEvents.CHAIN_PLACE, SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||||
} else {
|
} else {
|
||||||
inventory.setItem(1, ItemStack.EMPTY);
|
inventory.setItem(1, ItemStack.EMPTY);
|
||||||
|
|
@ -260,6 +267,7 @@ public class CannonEntity extends Entity {
|
||||||
player.drop(currentChain, false);
|
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);
|
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();
|
ItemStack stack1 = stack.copy();
|
||||||
stack1.setCount(currentBehaviorItem.getCount() + 1);
|
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);
|
inventory.setItem(2, stack1);
|
||||||
|
|
||||||
if (!player.isCreative()) {
|
if (!player.isCreative()) {
|
||||||
|
|
@ -300,6 +308,7 @@ public class CannonEntity extends Entity {
|
||||||
ItemStack copied = stack.copy();
|
ItemStack copied = stack.copy();
|
||||||
copied.setCount(1);
|
copied.setCount(1);
|
||||||
inventory.setItem(2, copied);
|
inventory.setItem(2, copied);
|
||||||
|
((ServerPlayer) player).sendSystemMessage(Component.translatable(ADD_BEHAVIOR_DIALOG, I18n.get(stack.getDescriptionId()), 1, stack.getMaxStackSize()), true);
|
||||||
if (!player.isCreative()) {
|
if (!player.isCreative()) {
|
||||||
stack.shrink(1);
|
stack.shrink(1);
|
||||||
}
|
}
|
||||||
|
|
@ -391,50 +400,32 @@ public class CannonEntity extends Entity {
|
||||||
if (this.level() instanceof ServerLevel world) {
|
if (this.level() instanceof ServerLevel world) {
|
||||||
var gunpowder = this.inventory.getItem(0);
|
var gunpowder = this.inventory.getItem(0);
|
||||||
if (gunpowder.is(Items.GUNPOWDER) && gunpowder.getCount() > 0) {
|
if (gunpowder.is(Items.GUNPOWDER) && gunpowder.getCount() > 0) {
|
||||||
|
CannonFireEvent.Pre pre;
|
||||||
Player firedPlayer = null;
|
Player firedPlayer = null;
|
||||||
var behaviorStack = this.getBehaviorStack();
|
var behaviorStack = this.getBehaviorStack();
|
||||||
var vel = getDeltaMovement().add(getLookAngle().scale(Math.sqrt(gunpowder.getCount()) * 0.6));
|
if(getFirstPassenger() instanceof Player player) {
|
||||||
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());
|
|
||||||
}
|
|
||||||
firedPlayer = 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);
|
this.level().playSound(null, this.blockPosition(), SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 1, 1);
|
||||||
for (var to : world.players()) {
|
for (var to : world.players()) {
|
||||||
BTRNetwork.CHANNEL.sendTo(new FireCannonPayload(this, firedPlayer, vel), to.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
|
BTRNetwork.CHANNEL.sendTo(new FireCannonPayload(this, firedPlayer, vel), to.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,22 @@
|
||||||
package com.leisuretimedock.blasttravelreborn.content.entity.cannon;
|
package com.leisuretimedock.blasttravelreborn.content.entity.cannon;
|
||||||
|
|
||||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||||
|
import com.leisuretimedock.blasttravelreborn.api.events.CannonFireEvent;
|
||||||
import com.leisuretimedock.blasttravelreborn.content.entity.CannonEntity;
|
import com.leisuretimedock.blasttravelreborn.content.entity.CannonEntity;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.sounds.SoundEvent;
|
import net.minecraft.sounds.SoundEvent;
|
||||||
import net.minecraft.sounds.SoundEvents;
|
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.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
|
@ -71,7 +76,7 @@ public class CannonBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public boolean displayHead(CannonEntity entity) {
|
public boolean displayHead(@NotNull CannonEntity entity) {
|
||||||
return entity.getClientPlayer() != null;
|
return entity.getClientPlayer() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +84,13 @@ public class CannonBehavior {
|
||||||
return false;
|
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) {
|
public static CannonBehavior byId(int id) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
import net.minecraft.world.level.block.ConcretePowderBlock;
|
import net.minecraft.world.level.block.ConcretePowderBlock;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ public class ConcretePowderCannonBehavior extends CannonBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean displayHead(CannonEntity entity) {
|
public boolean displayHead(@NotNull CannonEntity entity) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,7 +47,8 @@ public class ConcretePowderCannonBehavior extends CannonBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
if (cannon.level() instanceof ServerLevel world) {
|
||||||
var rot = cannon.getLookAngle();
|
var rot = cannon.getLookAngle();
|
||||||
var origin = cannon.position().add(0, 0.75, 0).add(rot.scale(1.8));
|
var origin = cannon.position().add(0, 0.75, 0).add(rot.scale(1.8));
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
|
@ -32,7 +33,8 @@ public class EntityCannonBehavior extends CannonBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 pos = cannon.position().add(0, 0.75, 0).add(cannon.getLookAngle().scale(1.8));
|
||||||
var entity = entityFactory.create(cannon.level(), pos, behaviorStack);
|
var entity = entityFactory.create(cannon.level(), pos, behaviorStack);
|
||||||
entity.setDeltaMovement(velocity);
|
entity.setDeltaMovement(velocity);
|
||||||
|
|
|
||||||
|
|
@ -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(
|
addLang(LangKeyValue.ofKey(
|
||||||
"mount.blasttravelreborn.cannon.onboard", ModPartEnum.MESSAGE,
|
"mount.blasttravelreborn.cannon.onboard", ModPartEnum.MESSAGE,
|
||||||
"Press %s to Exit, or %s to Fire",
|
"Press %s to Exit, or %s to Fire",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
package com.leisuretimedock.blasttravelreborn.mixin;
|
package com.leisuretimedock.blasttravelreborn.mixin;
|
||||||
|
|
||||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||||
|
import com.leisuretimedock.blasttravelreborn.api.events.PlayerCannonFlightTickEvent;
|
||||||
import com.leisuretimedock.blasttravelreborn.network.BTRNetwork;
|
import com.leisuretimedock.blasttravelreborn.network.BTRNetwork;
|
||||||
import com.leisuretimedock.blasttravelreborn.network.toClient.SyncFlightStatePayload;
|
import com.leisuretimedock.blasttravelreborn.network.toClient.SyncFlightStatePayload;
|
||||||
import com.leisuretimedock.blasttravelreborn.network.toServer.StopCannonFlightServerPayload;
|
import com.leisuretimedock.blasttravelreborn.network.toServer.StopCannonFlightServerPayload;
|
||||||
import com.leisuretimedock.blasttravelreborn.util.PlayerEntityDuck;
|
import com.leisuretimedock.blasttravelreborn.util.PlayerEntityDuck;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
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.Level;
|
||||||
import net.minecraft.world.level.entity.EntityTypeTest;
|
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||||
import net.minecraftforge.network.NetworkDirection;
|
import net.minecraftforge.network.NetworkDirection;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
@ -63,30 +66,6 @@ public abstract class PlayerEntityMixin extends LivingEntity implements PlayerEn
|
||||||
@Inject(method = "tick", at = @At("HEAD"))
|
@Inject(method = "tick", at = @At("HEAD"))
|
||||||
private void blasttravel$beginTick(CallbackInfo ci) {
|
private void blasttravel$beginTick(CallbackInfo ci) {
|
||||||
this.blasttravel$prevVel = this.isLocalPlayer() ? blasttravel$vel : blasttravel$trackingVel;
|
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"))
|
@Inject(method = "tick", at = @At("TAIL"))
|
||||||
|
|
@ -96,7 +75,7 @@ public abstract class PlayerEntityMixin extends LivingEntity implements PlayerEn
|
||||||
|
|
||||||
if (this.blasttravel$inCannonFlight()) {
|
if (this.blasttravel$inCannonFlight()) {
|
||||||
this.noPhysics = true;
|
this.noPhysics = true;
|
||||||
|
MinecraftForge.EVENT_BUS.post(new PlayerCannonFlightTickEvent(self, blasttravel$vel, self.position(), blasttravel$ticksFlying));
|
||||||
if (!self.level().isClientSide()) {
|
if (!self.level().isClientSide()) {
|
||||||
var vel = self.getDeltaMovement();
|
var vel = self.getDeltaMovement();
|
||||||
var frontBox = self.getBoundingBox().expandTowards(0.2, 0.2, 0.2);
|
var frontBox = self.getBoundingBox().expandTowards(0.2, 0.2, 0.2);
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,6 @@ public record FireCannonPayload(int cannonId, Optional<Integer> launchedId, doub
|
||||||
if (hasPlayer()) {
|
if (hasPlayer()) {
|
||||||
//noinspection OptionalGetWithoutIsPresent
|
//noinspection OptionalGetWithoutIsPresent
|
||||||
if (clientPacketListener.getLevel().getEntity(launchedId.get()) instanceof Player launchedPlayer) {
|
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()) {
|
if (launchedPlayer.isPassenger()) {
|
||||||
|
|
@ -59,11 +54,6 @@ public record FireCannonPayload(int cannonId, Optional<Integer> launchedId, doub
|
||||||
launchedPlayer.setDeltaMovement(velocityX, velocityY, velocityZ);
|
launchedPlayer.setDeltaMovement(velocityX, velocityY, velocityZ);
|
||||||
((PlayerEntityDuck) launchedPlayer).blasttravel$setCannonFlight(true);
|
((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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,14 +64,6 @@ public record SyncFlightStatePayload(
|
||||||
player.noPhysics = this.noPhysics;
|
player.noPhysics = this.noPhysics;
|
||||||
player.hurtMarked = true;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user