更新版本为1.0.4

修复了因为延迟取消骑乘逻辑导致的部分大炮发射玩家异常的问题
This commit is contained in:
叁玖领域 2025-06-05 10:57:29 +08:00
parent 33b463ef85
commit da4b98c21b
11 changed files with 91 additions and 27 deletions

View File

@ -167,7 +167,9 @@ dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
implementation 'org.spongepowered:mixin:0.8.5'
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
implementation fg.deobf("blank:jsonem-${minecraft_version}:${jsonem_version}")
implementation jarJar(fg.deobf("blank:jsonem-${minecraft_version}:${jsonem_version}")) {
jarJar.ranged(it, "[0.0,)")
}
// Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}")

View File

@ -38,7 +38,7 @@ mod_name=BlastTravel-Reborn
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT
# The mod version. See https://semver.org/
mod_version=1.0.3+1.20.1-forge
mod_version=1.0.4+1.20.1-forge
jsonem_version=0.2.1+1.20-fabrge
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.

View File

@ -8,10 +8,8 @@ import com.leisuretimedock.blasttravelreborn.client.screen.overlay.CannonOverlay
import com.leisuretimedock.blasttravelreborn.content.BTRParticleTypes;
import com.leisuretimedock.blasttravelreborn.content.entity.BTREntityTypes;
import com.leisuretimedock.blasttravelreborn.content.menu.BTRMenuTypes;
import com.leisuretimedock.blasttravelreborn.util.BTRUtil;
import com.leisuretimedock.jsonem.JsonEm;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.client.event.RegisterGuiOverlaysEvent;
@ -20,15 +18,10 @@ import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLConstructModEvent;
@Mod.EventBusSubscriber(modid = BlastTravelReborn.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public class BlastTravelClient {
@SubscribeEvent
public static void onClientInitPreInit(final FMLConstructModEvent event) {
onInitializeClient();
}
@SubscribeEvent
public static void onFmlClientSetup(final FMLClientSetupEvent event) {
event.enqueueWork(() -> MenuScreens.register(BTRMenuTypes.CANNON_CONTAINER_MENU.get(), CannonScreen::new));
@ -38,6 +31,10 @@ public class BlastTravelClient {
event.registerEntityRenderer(BTREntityTypes.CANNON_ENTITY.get(), CannonEntityRenderer::new);
}
@SubscribeEvent
public static void onRegisterLayerDefinitions(EntityRenderersEvent.RegisterLayerDefinitions event) {
JsonEm.registerModelLayer(CannonEntityRenderer.MODEL);
}
@SubscribeEvent
public static void onRegisterParticleProviders(RegisterParticleProvidersEvent event) {
event.registerSpriteSet(BTRParticleTypes.CANNON_BLAST.get(), CannonBlastParticle.Provider::new);
}
@ -48,8 +45,4 @@ public class BlastTravelClient {
new CannonOverlay()
);
}
public static void onInitializeClient() {
JsonEm.registerModelLayer(CannonEntityRenderer.MODEL);
}
}

View File

@ -56,9 +56,8 @@ public class CannonEntityRenderer extends EntityRenderer<CannonEntity> {
public CannonEntityRenderer(EntityRendererProvider.Context context) {
super(context);
this.root = context.bakeLayer(MODEL).getChild("main");
ModelPart modelPart = context.bakeLayer(MODEL);
this.root = modelPart.getChild("main");
this.leftWheel = this.root.getChild("left_wheel");
this.rightWheel = this.root.getChild("right_wheel");
this.cannon = this.root.getChild("cannon");

View File

@ -41,6 +41,7 @@ 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.loading.FMLEnvironment;
import net.minecraftforge.network.NetworkDirection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -279,14 +280,40 @@ public class CannonEntity extends Entity {
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.stopRiding();
((ServerPlayer) player).connection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
((ServerPlayer) player).connection.send(new ClientboundSetEntityMotionPacket(player));
player.setDeltaMovement(vel);
((ServerPlayer)player).connection.send(new ClientboundSetEntityMotionPacket(player));
((ServerPlayer)player).connection.send(new ClientboundTeleportEntityPacket(player));
player.hurtMarked = true;
player.hurtMarked = true;
((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;
}
this.level().playSound(null, this.blockPosition(), SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 1, 1);

View File

@ -65,19 +65,22 @@ public abstract class PlayerEntityMixin extends LivingEntity implements PlayerEn
this.blasttravel$vel = self.position().subtract(self.xo, self.yo, self.zo);
if (this.blasttravel$inCannonFlight()) {
if (!self.level().isClientSide()) {
this.noPhysics = true;
if (!self.level().isClientSide()) {
var vel = self.getDeltaMovement();
var frontBox = self.getBoundingBox().expandTowards(0.2, 0.2, 0.2);
for (var entity : self.level().getEntities(EntityTypeTest.forClass(LivingEntity.class), frontBox, entity -> entity != self)) {
if (!entity.isInvulnerable()) {
DamageSource source = self.damageSources().source(ResourceKey.create(Registries.DAMAGE_TYPE, BlastTravelReborn.id("cannon")), self);
DamageSource source = self.damageSources().source(
ResourceKey.create(Registries.DAMAGE_TYPE, BlastTravelReborn.id("cannon")), self);
entity.hurt(source, (float)(vel.length() * 4));
}
}
}
if (self.isLocalPlayer() &&
this.blasttravel$ticksFlying > 4 &&
this.blasttravel$ticksFlying > 8 &&
(self.onGround() || self.isFallFlying() || self.getAbilities().flying || self.isUnderWater())) {
this.blasttravel$setCannonFlight(false);
BTRNetwork.CHANNEL.sendToServer(new StopCannonFlightServerPayload(self.onGround()));
@ -86,11 +89,13 @@ public abstract class PlayerEntityMixin extends LivingEntity implements PlayerEn
this.blasttravel$ticksFlying++;
} else {
this.blasttravel$ticksFlying = 0;
this.noPhysics = false;
}
if (!self.isLocalPlayer()) {
this.blasttravel$trackingVel = this.blasttravel$trackingVel.add(
this.blasttravel$vel.subtract(this.blasttravel$trackingVel).scale(1f / self.getType().updateInterval()));
this.blasttravel$vel.subtract(this.blasttravel$trackingVel)
.scale(1f / self.getType().updateInterval()));
}
}

View File

@ -27,3 +27,10 @@ public abstract class PlayerEntityMixinClient extends LivingEntity implements Pl
}
}
}

View File

@ -2,11 +2,13 @@ package com.leisuretimedock.blasttravelreborn.network.toClient;
import com.leisuretimedock.blasttravelreborn.content.entity.CannonEntity;
import com.leisuretimedock.blasttravelreborn.util.PlayerEntityDuck;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.Nullable;
@ -43,9 +45,38 @@ public record FireCannonPayload(int cannonId, Optional<Integer> launchedId, doub
if(hasPlayer()) {
//noinspection OptionalGetWithoutIsPresent
if (clientPacketListener.getLevel().getEntity(launchedId.get()) instanceof Player launchedPlayer) {
launchedPlayer.getAbilities().flying = false;
launchedPlayer.setDeltaMovement(velocityX, velocityY, velocityZ);
((PlayerEntityDuck)launchedPlayer).blasttravel$setCannonFlight(true);
if (!FMLEnvironment.production) {
System.out.println(" - [B]Client: Is Passenger = " + launchedPlayer.isPassenger());
System.out.println(" - [B]Client: On Ground = " + launchedPlayer.onGround());
System.out.println(" - [B]Client: noPhysics =" + launchedPlayer.noPhysics);
System.out.println(" - [B]Client: Pose = " + launchedPlayer.getPose());
System.out.println(" - [B]Client: riding entity = " + launchedPlayer.getVehicle());
System.out.println(" - [B]Client: Bounding Box = " + launchedPlayer.getBoundingBox());
System.out.println(" - [B]Client: Delta Movement = " + launchedPlayer.getDeltaMovement());
}
if (launchedPlayer.isPassenger()) {
launchedPlayer.stopRiding();
}
// 延迟一个 tick 执行飞行初始化逻辑
Minecraft.getInstance().tell(() -> {
// 此时已脱离炮台设置速度
launchedPlayer.getAbilities().flying = false;
launchedPlayer.setPos(launchedPlayer.getX(), launchedPlayer.getY(), launchedPlayer.getZ());
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: On Ground = " + launchedPlayer.onGround());
System.out.println(" - [A]Client: noPhysics = " + launchedPlayer.noPhysics);
System.out.println(" - [A]Client: Pose = " + launchedPlayer.getPose());
System.out.println(" - [A]Client: riding entity = " + launchedPlayer.getVehicle());
System.out.println(" - [A]Client: Bounding Box = " + launchedPlayer.getBoundingBox());
System.out.println(" - [A]Client: Delta Movement = " + launchedPlayer.getDeltaMovement());
}
});
}
}
Entity entity = clientPacketListener.getLevel().getEntity(cannonId);

View File

@ -25,7 +25,7 @@ displayName = "${mod_name}" #mandatory
# A URL for the "homepage" for this mod, displayed in the mod UI
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
# A file name (in the root of the mod JAR) containing a logo for display
#logoFile="blasttravelreborn.png" #optional
logoFile="icon.png" #optional
# A text field displayed in the mod UI
#credits="Thanks for this example mod goes to Java" #optional
# A text field displayed in the mod UI

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB