正确处理载具座位数据同步
This commit is contained in:
parent
a9fddff258
commit
fb514ecfad
4 changed files with 109 additions and 13 deletions
|
@ -55,6 +55,7 @@ import org.joml.Vector4f;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
||||||
|
|
||||||
|
@ -98,24 +99,33 @@ public abstract class VehicleEntity extends Entity {
|
||||||
return orderedPassengers;
|
return orderedPassengers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 仅在客户端存在的实体顺序获取,用于在客户端正确同步实体座位顺序
|
||||||
|
public Function<Entity, Integer> entityIndexOverride = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addPassenger(Entity pPassenger) {
|
protected void addPassenger(@NotNull Entity newPassenger) {
|
||||||
if (pPassenger.getVehicle() != this) {
|
if (newPassenger.getVehicle() != this) {
|
||||||
throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)");
|
throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)");
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = 0;
|
int index;
|
||||||
|
|
||||||
|
if (entityIndexOverride != null && entityIndexOverride.apply(newPassenger) != -1) {
|
||||||
|
index = entityIndexOverride.apply(newPassenger);
|
||||||
|
} else {
|
||||||
|
index = 0;
|
||||||
for (Entity passenger : orderedPassengers) {
|
for (Entity passenger : orderedPassengers) {
|
||||||
if (passenger == null) {
|
if (passenger == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
if (index >= getMaxPassengers()) return;
|
}
|
||||||
|
if (index >= getMaxPassengers() || index < 0) return;
|
||||||
|
|
||||||
orderedPassengers.set(index, pPassenger);
|
orderedPassengers.set(index, newPassenger);
|
||||||
this.passengers = ImmutableList.copyOf(orderedPassengers.stream().filter(Objects::nonNull).toList());
|
this.passengers = ImmutableList.copyOf(orderedPassengers.stream().filter(Objects::nonNull).toList());
|
||||||
this.gameEvent(GameEvent.ENTITY_MOUNT, pPassenger);
|
this.gameEvent(GameEvent.ENTITY_MOUNT, newPassenger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,7 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.protocol.PacketUtils;
|
||||||
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
@ -19,7 +20,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
* Code based on @Luke100000's ImmersiveAircraft
|
* Code based on @Luke100000's ImmersiveAircraft
|
||||||
*/
|
*/
|
||||||
@Mixin(ClientPacketListener.class)
|
@Mixin(ClientPacketListener.class)
|
||||||
public class ClientPacketListenerMixin {
|
public abstract class ClientPacketListenerMixin {
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
|
@ -28,6 +29,53 @@ public class ClientPacketListenerMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
private ClientLevel level;
|
private ClientLevel level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正确处理VehicleEntity的带顺序乘客
|
||||||
|
*/
|
||||||
|
@Inject(method = "handleSetEntityPassengersPacket(Lnet/minecraft/network/protocol/game/ClientboundSetPassengersPacket;)V", at = @At("HEAD"), cancellable = true)
|
||||||
|
public void vehicleEntityUpdate(ClientboundSetPassengersPacket pPacket, CallbackInfo ci) {
|
||||||
|
PacketUtils.ensureRunningOnSameThread(pPacket, (ClientPacketListener) (Object) this, this.minecraft);
|
||||||
|
|
||||||
|
// 只处理VehicleEntity
|
||||||
|
Entity entity = this.level.getEntity(pPacket.getVehicle());
|
||||||
|
if (!(entity instanceof VehicleEntity vehicle)) return;
|
||||||
|
ci.cancel();
|
||||||
|
|
||||||
|
var player = this.minecraft.player;
|
||||||
|
assert player != null;
|
||||||
|
boolean hasIndirectPassenger = entity.hasIndirectPassenger(player);
|
||||||
|
|
||||||
|
entity.ejectPassengers();
|
||||||
|
|
||||||
|
// 获取排序后的Passengers
|
||||||
|
var passengers = pPacket.getPassengers();
|
||||||
|
vehicle.entityIndexOverride = (e) -> {
|
||||||
|
for (int i = 0; i < passengers.length; i++) {
|
||||||
|
if (passengers[i] == e.getId()) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i : passengers) {
|
||||||
|
if (i == -1) continue;
|
||||||
|
|
||||||
|
Entity passenger = this.level.getEntity(i);
|
||||||
|
if (passenger != null) {
|
||||||
|
passenger.startRiding(entity, true);
|
||||||
|
if (passenger == player && !hasIndirectPassenger) {
|
||||||
|
Component component = Component.translatable("mount.onboard", ModKeyMappings.DISMOUNT.getTranslatedKeyMessage());
|
||||||
|
this.minecraft.gui.setOverlayMessage(component, false);
|
||||||
|
this.minecraft.getNarrator().sayNow(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vehicle.entityIndexOverride = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Inject(method = "handleSetEntityPassengersPacket(Lnet/minecraft/network/protocol/game/ClientboundSetPassengersPacket;)V", at = @At("TAIL"))
|
@Inject(method = "handleSetEntityPassengersPacket(Lnet/minecraft/network/protocol/game/ClientboundSetPassengersPacket;)V", at = @At("TAIL"))
|
||||||
public void handleSetEntityPassengersPacket(ClientboundSetPassengersPacket pPacket, CallbackInfo ci) {
|
public void handleSetEntityPassengersPacket(ClientboundSetPassengersPacket pPacket, CallbackInfo ci) {
|
||||||
Entity entity = this.level.getEntity(pPacket.getVehicle());
|
Entity entity = this.level.getEntity(pPacket.getVehicle());
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.atsuishio.superbwarfare.mixins;
|
||||||
|
|
||||||
|
import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(ClientboundSetPassengersPacket.class)
|
||||||
|
public class ClientboundSetPassengersPacketMixin {
|
||||||
|
|
||||||
|
@Mutable
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private int[] passengers;
|
||||||
|
|
||||||
|
@Inject(method = "<init>(Lnet/minecraft/world/entity/Entity;)V", at = @At("RETURN"))
|
||||||
|
private void init(Entity entity, CallbackInfo ci) {
|
||||||
|
if (entity instanceof VehicleEntity vehicle) {
|
||||||
|
// 使用顺序乘客信息代替原乘客信息
|
||||||
|
List<Entity> list = vehicle.getOrderedPassengers();
|
||||||
|
passengers = new int[list.size()];
|
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); ++i) {
|
||||||
|
var passenger = list.get(i);
|
||||||
|
passengers[i] = passenger == null ? -1 : passenger.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
"refmap": "mixins.superbwarfare.refmap.json",
|
"refmap": "mixins.superbwarfare.refmap.json",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ClientboundSetEntityMotionPacketMixin",
|
"ClientboundSetEntityMotionPacketMixin",
|
||||||
|
"ClientboundSetPassengersPacketMixin",
|
||||||
"EntityMixin",
|
"EntityMixin",
|
||||||
"ExplosionMixin",
|
"ExplosionMixin",
|
||||||
"LivingEntityMixin",
|
"LivingEntityMixin",
|
||||||
|
|
Loading…
Add table
Reference in a new issue