parent
9511f0074c
commit
e3ba40f8ff
|
|
@ -147,6 +147,10 @@ repositories {
|
|||
includeGroup("maven.modrinth")
|
||||
}
|
||||
}
|
||||
maven {
|
||||
name = "KosmX"
|
||||
url = "https://maven.kosmx.dev/"
|
||||
}
|
||||
maven {
|
||||
name = "Fuzs Mod Resources"
|
||||
url = "https://raw.githubusercontent.com/Fuzss/modresources/main/maven/"
|
||||
|
|
@ -176,6 +180,7 @@ dependencies {
|
|||
implementation jarJar(fg.deobf("com.leisuretimedock:jsonem-forge-${minecraft_version}:${jsonem_version}")) {
|
||||
jarJar.ranged(it, "[${jsonem_version},)")
|
||||
}
|
||||
implementation fg.deobf ("dev.kosmx.player-anim:player-animation-lib-forge:${player_anim_version}")
|
||||
|
||||
|
||||
// Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ mod_license=MIT
|
|||
mod_version=1.0.7
|
||||
jsonem_version=0.2.4
|
||||
lib39_version=1.20.1-0.0.17
|
||||
player_anim_version=1.0.2-rc1+1.20
|
||||
mod_source=https://github.com/LeisureTimeDock/BlastTravel_Neo_Forge
|
||||
# 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.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,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.javafmlmod.FMLModContainer;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
@ -207,9 +208,12 @@ public class CannonEntity extends Entity {
|
|||
} else if (stack.is(Items.CHAIN)) {
|
||||
handlerChain(player, stack);
|
||||
return true;
|
||||
} else if (CannonBehavior.isValidBehaviorStack(stack)) {
|
||||
} else if (CannonBehavior.isValidBehaviorStack(stack) && this.getPassengers().isEmpty()) {
|
||||
handlerBehaviorItem(player, stack);
|
||||
return true;
|
||||
} else if (stack.is(Items.FLINT_AND_STEEL)) {
|
||||
fireServer();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -217,7 +221,6 @@ public class CannonEntity extends Entity {
|
|||
private void handlerGunPower(Player player, ItemStack stack) {
|
||||
if (!level().isClientSide()) {
|
||||
ItemStack currentGunpowder = inventory.getItem(0);
|
||||
|
||||
// 如果炮内已有火药,先还给玩家
|
||||
if (currentGunpowder.getCount() >= currentGunpowder.getMaxStackSize()) {
|
||||
if (!player.isCreative() && !player.getInventory().add(currentGunpowder)) {
|
||||
|
|
@ -225,11 +228,10 @@ public class CannonEntity extends Entity {
|
|||
player.drop(currentGunpowder, false);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置新的火药到炮中
|
||||
ItemStack newGunpowder = stack.copy();
|
||||
newGunpowder.setCount(currentGunpowder.getCount() + 1); // 只放一个火药
|
||||
((ServerPlayer) player).sendSystemMessage(Component.literal(String.format("%d / %d", currentGunpowder.getCount(), currentGunpowder.getMaxStackSize())), true);
|
||||
((ServerPlayer) player).sendSystemMessage(Component.literal(String.format("%d / %d", currentGunpowder.getCount() + 1, currentGunpowder.getMaxStackSize())), true);
|
||||
inventory.setItem(0, newGunpowder);
|
||||
|
||||
if (!player.isCreative()) {
|
||||
|
|
@ -242,17 +244,17 @@ public class CannonEntity extends Entity {
|
|||
|
||||
private void handlerChain(Player player, ItemStack stack) {
|
||||
if (!level().isClientSide()) {
|
||||
ItemStack currentChain = inventory.getItem(2);
|
||||
if (currentChain.isEmpty()) { // 添加锁链
|
||||
ItemStack currentChain = inventory.getItem(1);
|
||||
if (currentChain.isEmpty()) { // 添加锁链Pl
|
||||
ItemStack item = stack.copy();
|
||||
item.setCount(1);
|
||||
inventory.setItem(2, item);
|
||||
inventory.setItem(1, item);
|
||||
if (!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
level().playSound(null, this.blockPosition(), SoundEvents.CHAIN_PLACE, SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||
} else {
|
||||
inventory.setItem(2, ItemStack.EMPTY);
|
||||
inventory.setItem(1, ItemStack.EMPTY);
|
||||
if (!player.isCreative()) { // 移除锁链
|
||||
if (!player.getInventory().add(currentChain)) {
|
||||
player.drop(currentChain, false);
|
||||
|
|
@ -267,18 +269,41 @@ public class CannonEntity extends Entity {
|
|||
if (!level().isClientSide()) {
|
||||
ItemStack currentBehaviorItem = inventory.getItem(2);
|
||||
if (currentBehaviorItem.isEmpty()) { // 添加物品
|
||||
ItemStack item = stack.copy();
|
||||
item.setCount(1);
|
||||
inventory.setItem(2, item);
|
||||
ItemStack copied = stack.copy();
|
||||
copied.setCount(1);
|
||||
inventory.setItem(2, copied);
|
||||
if (!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
level().playSound(null, this.blockPosition(), getBehavior().getPlaceInSound(), SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||
} else {
|
||||
if (stack.is(currentBehaviorItem.getItem())) { //同类物品 +1
|
||||
if (stack.getCount() >= currentBehaviorItem.getMaxStackSize()) {
|
||||
if (!player.isCreative() && !player.getInventory().add(currentBehaviorItem)) {
|
||||
player.drop(currentBehaviorItem, false);
|
||||
}
|
||||
}
|
||||
ItemStack stack1 = stack.copy();
|
||||
stack1.setCount(currentBehaviorItem.getCount() + 1);
|
||||
((ServerPlayer) player).sendSystemMessage(Component.literal(String.format("%d / %d", currentBehaviorItem.getCount() + 1, currentBehaviorItem.getMaxStackSize())), true);
|
||||
inventory.setItem(2, stack1);
|
||||
|
||||
if (!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
|
||||
level().playSound(null, this.blockPosition(), getBehavior().getPlaceInSound(), SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||
} else { //不同类替换
|
||||
|
||||
if (!player.isCreative() && !player.getInventory().add(currentBehaviorItem)) {
|
||||
player.drop(currentBehaviorItem, false);
|
||||
}
|
||||
ItemStack copied = stack.copy();
|
||||
copied.setCount(1);
|
||||
inventory.setItem(2, copied);
|
||||
if (!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
level().playSound(null, this.blockPosition(), getBehavior().getPlaceInSound(), SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -545,6 +570,7 @@ public class CannonEntity extends Entity {
|
|||
return super.getPassengersRidingOffset();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
this.entityData.define(BEHAVIOR, 0);
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ package com.leisuretimedock.blasttravelreborn.mixin;
|
|||
|
||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||
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.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
|
|
@ -17,6 +19,8 @@ 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.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
|
@ -59,6 +63,30 @@ 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"))
|
||||
|
|
@ -79,6 +107,10 @@ public abstract class PlayerEntityMixin extends LivingEntity implements PlayerEn
|
|||
entity.hurt(source, (float)(vel.length() * 4));
|
||||
}
|
||||
}
|
||||
try {
|
||||
ServerPlayer cast = ServerPlayer.class.cast(self);
|
||||
BTRNetwork.CHANNEL.sendTo(new SyncFlightStatePayload(self.getId(), vel, self.position(), true, noPhysics), cast.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
|
||||
} catch(Exception ignored){}
|
||||
}
|
||||
|
||||
if (self.isLocalPlayer() &&
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.leisuretimedock.blasttravelreborn.network;
|
|||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||
import com.leisuretimedock.blasttravelreborn.network.toClient.FireCannonPayload;
|
||||
import com.leisuretimedock.blasttravelreborn.network.toClient.StopCannonFlightClientPayload;
|
||||
import com.leisuretimedock.blasttravelreborn.network.toClient.SyncFlightStatePayload;
|
||||
import com.leisuretimedock.blasttravelreborn.network.toServer.RequestFirePayload;
|
||||
import com.leisuretimedock.blasttravelreborn.network.toServer.StopCannonFlightServerPayload;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
|
|
@ -43,6 +44,13 @@ public class BTRNetwork {
|
|||
.decoder(RequestFirePayload::read)
|
||||
.consumerNetworkThread(RequestFirePayload::handle)
|
||||
.add();
|
||||
CHANNEL
|
||||
.messageBuilder(SyncFlightStatePayload.class, getIDAndIncrease(), NetworkDirection.PLAY_TO_CLIENT)
|
||||
.encoder(SyncFlightStatePayload::write)
|
||||
.decoder(SyncFlightStatePayload::read)
|
||||
.consumerNetworkThread(SyncFlightStatePayload::handle)
|
||||
.add();
|
||||
|
||||
}
|
||||
private static int getIDAndIncrease() {
|
||||
return ++ID;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public record FireCannonPayload(int cannonId, Optional<Integer> launchedId, doub
|
|||
if (context.getNetworkManager().getPacketListener() instanceof ClientPacketListener clientPacketListener) {
|
||||
context.enqueueWork(() -> {
|
||||
if (hasPlayer()) {
|
||||
//noinspection OptionalGetWithoutIsPresent
|
||||
if (clientPacketListener.getLevel().getEntity(launchedId.get()) instanceof Player launchedPlayer) {
|
||||
// 记录发射前状态
|
||||
if (!FMLEnvironment.production) {
|
||||
|
|
@ -56,7 +57,6 @@ public record FireCannonPayload(int cannonId, Optional<Integer> launchedId, doub
|
|||
|
||||
// 直接设置速度,不要延迟
|
||||
launchedPlayer.setDeltaMovement(velocityX, velocityY, velocityZ);
|
||||
launchedPlayer.hurtMarked = true; // 强制同步运动
|
||||
((PlayerEntityDuck) launchedPlayer).blasttravel$setCannonFlight(true);
|
||||
|
||||
// 记录发射后状态
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
package com.leisuretimedock.blasttravelreborn.network.toClient;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public record SyncFlightStatePayload(
|
||||
int playerId,
|
||||
Vec3 velocity,
|
||||
Vec3 position,
|
||||
boolean inCannonFlight,
|
||||
boolean noPhysics
|
||||
) {
|
||||
|
||||
public SyncFlightStatePayload(@NotNull FriendlyByteBuf buf) {
|
||||
this(
|
||||
buf.readInt(),
|
||||
new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()),
|
||||
new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()),
|
||||
buf.readBoolean(),
|
||||
buf.readBoolean()
|
||||
);
|
||||
}
|
||||
|
||||
public void write(@NotNull FriendlyByteBuf buf) {
|
||||
buf.writeInt(playerId);
|
||||
buf.writeDouble(velocity.x);
|
||||
buf.writeDouble(velocity.y);
|
||||
buf.writeDouble(velocity.z);
|
||||
buf.writeDouble(position.x);
|
||||
buf.writeDouble(position.y);
|
||||
buf.writeDouble(position.z);
|
||||
buf.writeBoolean(inCannonFlight);
|
||||
buf.writeBoolean(noPhysics);
|
||||
}
|
||||
public static SyncFlightStatePayload read(FriendlyByteBuf buf) {
|
||||
return new SyncFlightStatePayload(buf);
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().enqueueWork(() -> {
|
||||
// 客户端处理逻辑
|
||||
net.minecraft.client.Minecraft client = net.minecraft.client.Minecraft.getInstance();
|
||||
if (client.level != null) {
|
||||
net.minecraft.world.entity.Entity entity = client.level.getEntity(this.playerId);
|
||||
if (entity instanceof net.minecraft.world.entity.player.Player player) {
|
||||
// 同步速度
|
||||
player.setDeltaMovement(this.velocity);
|
||||
|
||||
// 同步位置(如果差异较大)
|
||||
if (player.position().distanceTo(this.position) > 0.1) {
|
||||
player.setPos(this.position);
|
||||
}
|
||||
|
||||
// 同步飞行状态
|
||||
if (player instanceof com.leisuretimedock.blasttravelreborn.util.PlayerEntityDuck duck) {
|
||||
duck.blasttravel$setCannonFlight(this.inCannonFlight);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
context.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user