fix: 修复已存在的NPC在登陆后看不见、状态不对的问题
This commit is contained in:
parent
872c69f4fe
commit
4ddcb53ea0
|
|
@ -0,0 +1,353 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025-2026 R3944Realms
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package top.r3944realms.eroticdungeongame.client;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.client.multiplayer.PlayerInfo;
|
||||||
|
import net.minecraft.network.protocol.Packet;
|
||||||
|
import net.minecraft.network.protocol.game.*;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
||||||
|
import top.r3944realms.eroticdungeongame.content.entity.npc.INPCPlayer;
|
||||||
|
import top.r3944realms.eroticdungeongame.util.IEDGClientPacketListener;
|
||||||
|
import top.r3944realms.superleadrope.util.riding.RidingFinder;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantValue")
|
||||||
|
public class ClientNPCManager {
|
||||||
|
|
||||||
|
// 缓存待处理的 NPC 玩家包
|
||||||
|
private static final Set<ClientboundAddPlayerPacket> pendingNPCs = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的实体包(坐骑、宠物等)
|
||||||
|
// private static final Set<ClientboundAddEntityPacket> pendingEntities = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的实体数据包
|
||||||
|
private static final Set<ClientboundSetEntityDataPacket> pendingEntityData = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的属性包
|
||||||
|
private static final Set<ClientboundUpdateAttributesPacket> pendingAttributes = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的装备包
|
||||||
|
private static final Set<ClientboundSetEquipmentPacket> pendingEquipment = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的乘客包
|
||||||
|
private static final Set<ClientboundSetPassengersPacket> pendingPassengers = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的链接包(拴绳)
|
||||||
|
private static final Set<ClientboundSetEntityLinkPacket> pendingLinks = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的头部旋转包
|
||||||
|
private static final Set<ClientboundRotateHeadPacket> pendingHeadRotations = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的移动包
|
||||||
|
private static final Set<Packet<?>> pendingMovements = new HashSet<>();
|
||||||
|
|
||||||
|
// 缓存待处理的运动包
|
||||||
|
private static final Set<ClientboundSetEntityMotionPacket> pendingMotions = new HashSet<>();
|
||||||
|
|
||||||
|
public static void reset() {
|
||||||
|
pendingNPCs.clear();
|
||||||
|
// pendingEntities.clear();
|
||||||
|
pendingEntityData.clear();
|
||||||
|
pendingAttributes.clear();
|
||||||
|
pendingEquipment.clear();
|
||||||
|
pendingPassengers.clear();
|
||||||
|
pendingLinks.clear();
|
||||||
|
pendingHeadRotations.clear();
|
||||||
|
pendingMovements.clear();
|
||||||
|
pendingMotions.clear();
|
||||||
|
EroticDungeon.LOGGER.debug("ClientNPCManager reset");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 缓存方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存 NPC 玩家包
|
||||||
|
*/
|
||||||
|
public static void cacheNPCIfNeeded(ClientboundAddPlayerPacket packet) {
|
||||||
|
ClientPacketListener connection = Minecraft.getInstance().getConnection();
|
||||||
|
if (connection instanceof IEDGClientPacketListener iedgListener) {
|
||||||
|
UUID playerId = packet.getPlayerId();
|
||||||
|
PlayerInfo info = iedgListener.getNPCPlayerInfoMap().get(playerId);
|
||||||
|
if (info == null && !iedgListener.getNPCPlayerInfoMap().containsKey(playerId)) {
|
||||||
|
pendingNPCs.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached AddPlayer packet for NPC: {} (entityId: {})",
|
||||||
|
playerId, packet.getEntityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 缓存实体包
|
||||||
|
// */
|
||||||
|
// public static void cacheEntityIfNeeded(@NotNull ClientboundAddEntityPacket packet) {
|
||||||
|
// pendingEntities.add(packet);
|
||||||
|
// EroticDungeon.LOGGER.debug("Cached AddEntity packet {}", packet);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存实体数据包
|
||||||
|
*/
|
||||||
|
public static void cacheEntityDataIfNeeded(@NotNull ClientboundSetEntityDataPacket packet) {
|
||||||
|
pendingEntityData.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached SetEntityData packet {}, ID: {}", packet, packet.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存属性包
|
||||||
|
*/
|
||||||
|
public static void cacheAttributesIfNeeded(@NotNull ClientboundUpdateAttributesPacket packet) {
|
||||||
|
pendingAttributes.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached UpdateAttributes packet {}, ID: {}", packet, packet.getEntityId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存装备包
|
||||||
|
*/
|
||||||
|
public static void cacheEquipmentIfNeeded(@NotNull ClientboundSetEquipmentPacket packet) {
|
||||||
|
pendingEquipment.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached SetEquipment packet{}, ID: {}", packet, packet.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存乘客包
|
||||||
|
*/
|
||||||
|
public static void cachePassengersIfNeeded(@NotNull ClientboundSetPassengersPacket packet) {
|
||||||
|
pendingPassengers.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached SetPassengers packet {}, (as vehicle) ID: {}", packet, packet.getVehicle());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存链接包(拴绳)
|
||||||
|
*/
|
||||||
|
public static void cacheLinkIfNeeded(@NotNull ClientboundSetEntityLinkPacket packet) {
|
||||||
|
pendingLinks.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached SetEntityLink packet {}, (as source) ID: {}", packet, packet.getSourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存头部旋转包
|
||||||
|
*/
|
||||||
|
public static void cacheHeadRotationIfNeeded(ClientboundRotateHeadPacket packet) {
|
||||||
|
pendingHeadRotations.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached RotateHead packet {}", packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存移动包
|
||||||
|
*/
|
||||||
|
public static void cacheMoveEntityIfNeeded(ClientboundMoveEntityPacket packet) {
|
||||||
|
pendingMovements.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached MoveEntity packet {}", packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存传送包
|
||||||
|
*/
|
||||||
|
public static void cacheTeleportEntityIfNeeded(ClientboundTeleportEntityPacket packet) {
|
||||||
|
EroticDungeon.LOGGER.debug("Cached TeleportEntity packet {}", packet);
|
||||||
|
pendingMovements.add(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存运动包
|
||||||
|
*/
|
||||||
|
public static void cacheMotionIfNeeded(ClientboundSetEntityMotionPacket packet) {
|
||||||
|
pendingMotions.add(packet);
|
||||||
|
EroticDungeon.LOGGER.debug("Cached SetEntityMotion packet {}, ID: {}", packet, packet.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 处理方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理缓存的 NPC 包(当 NPCInfo 到达时调用)
|
||||||
|
*/
|
||||||
|
public static void processPendingNPCs(@NotNull PlayerInfo npcInfo) {
|
||||||
|
UUID uuid = npcInfo.getProfile().getId();
|
||||||
|
ClientPacketListener connection = Minecraft.getInstance().getConnection();
|
||||||
|
|
||||||
|
if (!(connection instanceof IEDGClientPacketListener iedgListener)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理缓存的 AddPlayer 包
|
||||||
|
Iterator<ClientboundAddPlayerPacket> playerIterator = pendingNPCs.iterator();
|
||||||
|
while (playerIterator.hasNext()) {
|
||||||
|
ClientboundAddPlayerPacket packet = playerIterator.next();
|
||||||
|
if (packet.getPlayerId().equals(uuid)) {
|
||||||
|
PlayerInfo npcPlayerInfo = iedgListener.getNPCPlayerInfo(uuid);
|
||||||
|
if (npcPlayerInfo != null) {
|
||||||
|
// 创建 NPC 玩家实体
|
||||||
|
iedgListener.edg$createNPCPlayer(packet, npcPlayerInfo);
|
||||||
|
playerIterator.remove();
|
||||||
|
EroticDungeon.LOGGER.debug("Processed AddPlayer packet for NPC: {}", uuid);
|
||||||
|
|
||||||
|
// 处理所有缓存的包
|
||||||
|
processAllCachedPackets(iedgListener);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
EroticDungeon.LOGGER.warn("NPC Player {} not found", uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理所有缓存的包
|
||||||
|
*/
|
||||||
|
private static void processAllCachedPackets(IEDGClientPacketListener iedgListener) {
|
||||||
|
Level level = Minecraft.getInstance().level;
|
||||||
|
if (level == null) return;
|
||||||
|
|
||||||
|
// // 处理实体包
|
||||||
|
// Iterator<ClientboundAddEntityPacket> entityIterator = pendingEntities.iterator();
|
||||||
|
// while (entityIterator.hasNext()) {
|
||||||
|
// ClientboundAddEntityPacket packet = entityIterator.next();
|
||||||
|
// Entity entity = level.getEntity(packet.getId());
|
||||||
|
// if (entity != null) {
|
||||||
|
// iedgListener.edg$createEntity(packet);
|
||||||
|
// entityIterator.remove();
|
||||||
|
// EroticDungeon.LOGGER.debug("Processed AddEntity packet: {}", entity.getUUID());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 处理实体数据包
|
||||||
|
Iterator<ClientboundSetEntityDataPacket> dataIterator = pendingEntityData.iterator();
|
||||||
|
while (dataIterator.hasNext()) {
|
||||||
|
ClientboundSetEntityDataPacket packet = dataIterator.next();
|
||||||
|
Entity entity = level.getEntity(packet.id());
|
||||||
|
if (entity != null) {
|
||||||
|
iedgListener.edg$setEntityData(packet);
|
||||||
|
dataIterator.remove();
|
||||||
|
EroticDungeon.LOGGER.debug("Processed SetEntityData packet: {}", entity.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理属性包
|
||||||
|
Iterator<ClientboundUpdateAttributesPacket> attrIterator = pendingAttributes.iterator();
|
||||||
|
while (attrIterator.hasNext()) {
|
||||||
|
ClientboundUpdateAttributesPacket packet = attrIterator.next();
|
||||||
|
Entity entity = level.getEntity(packet.getEntityId());
|
||||||
|
if (entity != null) {
|
||||||
|
iedgListener.edg$updateAttributes(packet);
|
||||||
|
attrIterator.remove();
|
||||||
|
EroticDungeon.LOGGER.debug("Processed UpdateAttributes packet: {}", entity.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理装备包
|
||||||
|
Iterator<ClientboundSetEquipmentPacket> equipIterator = pendingEquipment.iterator();
|
||||||
|
while (equipIterator.hasNext()) {
|
||||||
|
ClientboundSetEquipmentPacket packet = equipIterator.next();
|
||||||
|
Entity entity = level.getEntity(packet.getEntity());
|
||||||
|
if (entity != null) {
|
||||||
|
iedgListener.edg$setEquipment(packet);
|
||||||
|
equipIterator.remove();
|
||||||
|
EroticDungeon.LOGGER.debug("Processed SetEquipment packet for: {}", entity.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理乘客包
|
||||||
|
Iterator<ClientboundSetPassengersPacket> passengerIterator = pendingPassengers.iterator();
|
||||||
|
while (passengerIterator.hasNext()) {
|
||||||
|
ClientboundSetPassengersPacket packet = passengerIterator.next();
|
||||||
|
Entity vehicle = level.getEntity(packet.getVehicle());
|
||||||
|
if (vehicle != null) {
|
||||||
|
boolean flag = true;
|
||||||
|
for (int passengerId : packet.getPassengers()) {
|
||||||
|
Entity passenger = level.getEntity(passengerId);
|
||||||
|
if (passenger == null) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flag) {
|
||||||
|
iedgListener.edg$setPassengers(packet);
|
||||||
|
passengerIterator.remove();
|
||||||
|
EroticDungeon.LOGGER.debug("Processed SetPassengers packet: {}", vehicle.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理链接包
|
||||||
|
Iterator<ClientboundSetEntityLinkPacket> linkIterator = pendingLinks.iterator();
|
||||||
|
while (linkIterator.hasNext()) {
|
||||||
|
ClientboundSetEntityLinkPacket packet = linkIterator.next();
|
||||||
|
Entity source = level.getEntity(packet.getSourceId());
|
||||||
|
Entity dest = level.getEntity(packet.getDestId());
|
||||||
|
if (source != null && dest != null) {
|
||||||
|
iedgListener.edg$setEntityLink(packet);
|
||||||
|
linkIterator.remove();
|
||||||
|
EroticDungeon.LOGGER.debug("Processed SetEntityLink packet: {}", source.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理头部旋转包
|
||||||
|
Iterator<ClientboundRotateHeadPacket> headIterator = pendingHeadRotations.iterator();
|
||||||
|
while (headIterator.hasNext()) {
|
||||||
|
ClientboundRotateHeadPacket packet = headIterator.next();
|
||||||
|
Entity entity = packet.getEntity(level);
|
||||||
|
if (entity != null){
|
||||||
|
iedgListener.edg$rotateHead(packet);
|
||||||
|
headIterator.remove();
|
||||||
|
}
|
||||||
|
EroticDungeon.LOGGER.debug("Processed RotateHead packet for NPC: {}", entity.getUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理移动包
|
||||||
|
Iterator<Packet<?>> moveIterator = pendingMovements.iterator();
|
||||||
|
while (moveIterator.hasNext()) {
|
||||||
|
Packet<?> packet = moveIterator.next();
|
||||||
|
Entity entity = null;
|
||||||
|
|
||||||
|
if (packet instanceof ClientboundMoveEntityPacket movePacket) {
|
||||||
|
entity = movePacket.getEntity(level);
|
||||||
|
} else if (packet instanceof ClientboundTeleportEntityPacket teleportPacket) {
|
||||||
|
entity = level.getEntity(teleportPacket.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity != null) {
|
||||||
|
if (packet instanceof ClientboundMoveEntityPacket movePacket) {
|
||||||
|
iedgListener.edg$moveEntity(movePacket);
|
||||||
|
} else if (packet instanceof ClientboundTeleportEntityPacket teleportPacket) {
|
||||||
|
iedgListener.edg$teleportEntity(teleportPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveIterator.remove();
|
||||||
|
EroticDungeon.LOGGER.debug("Processed movement packet for NPC: {}", entity.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理运动包
|
||||||
|
Iterator<ClientboundSetEntityMotionPacket> motionIterator = pendingMotions.iterator();
|
||||||
|
while (motionIterator.hasNext()) {
|
||||||
|
ClientboundSetEntityMotionPacket packet = motionIterator.next();
|
||||||
|
Entity entity = level.getEntity(packet.getId());
|
||||||
|
if (entity != null) {
|
||||||
|
iedgListener.edg$setEntityMotion(packet);
|
||||||
|
motionIterator.remove();
|
||||||
|
EroticDungeon.LOGGER.debug("Processed SetEntityMotion packet for NPC: {}", entity.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,9 @@ package top.r3944realms.eroticdungeongame.content.animation;
|
||||||
import io.zershyan.sccore.animation.AnimationApi;
|
import io.zershyan.sccore.animation.AnimationApi;
|
||||||
import io.zershyan.sccore.animation.helper.AnimationHelper;
|
import io.zershyan.sccore.animation.helper.AnimationHelper;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import org.apache.logging.log4j.core.jmx.Server;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
||||||
|
|
@ -50,14 +52,14 @@ public interface IEDGAnimation {
|
||||||
|
|
||||||
|
|
||||||
default void play(Player player) {
|
default void play(Player player) {
|
||||||
if (player != null && !player.level().isClientSide) {
|
if (player != null) {
|
||||||
AnimationHelper helper = AnimationApi.getHelper(player);
|
AnimationHelper helper = AnimationApi.getHelper(player);
|
||||||
helper.playAnimation(IEDGAnimation.LAYER, getBaseId().withSuffix("01"));
|
helper.playAnimation(IEDGAnimation.LAYER, getBaseId().withSuffix("01"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default void play(Player player, int varNumber) {
|
default void play(Player player, int varNumber) {
|
||||||
if (player != null && !player.level().isClientSide) {
|
if (player != null) {
|
||||||
AnimationHelper helper = AnimationApi.getHelper(player);
|
AnimationHelper helper = AnimationApi.getHelper(player);
|
||||||
helper.playAnimation(IEDGAnimation.LAYER, getBaseId().withSuffix(String.format("%02d", Math.max(1, Math.min(99, varNumber)))));
|
helper.playAnimation(IEDGAnimation.LAYER, getBaseId().withSuffix(String.format("%02d", Math.max(1, Math.min(99, varNumber)))));
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +67,7 @@ public interface IEDGAnimation {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static ResourceLocation getPlayingAnimation(Player player) {
|
static ResourceLocation getPlayingAnimation(Player player) {
|
||||||
if (player != null && !player.level().isClientSide) {
|
if (player != null) {
|
||||||
AnimationHelper helper = AnimationApi.getHelper(player);
|
AnimationHelper helper = AnimationApi.getHelper(player);
|
||||||
return helper.getAnimationPlaying(IEDGAnimation.LAYER);
|
return helper.getAnimationPlaying(IEDGAnimation.LAYER);
|
||||||
}
|
}
|
||||||
|
|
@ -81,9 +83,16 @@ public interface IEDGAnimation {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stop(Player player) {
|
static void stop(Player player) {
|
||||||
if (player != null && !player.level().isClientSide) {
|
if (player != null) {
|
||||||
AnimationHelper helper = AnimationApi.getHelper(player);
|
AnimationHelper helper = AnimationApi.getHelper(player);
|
||||||
helper.removeAnimation(IEDGAnimation.LAYER);
|
helper.removeAnimation(IEDGAnimation.LAYER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void refresh(ServerPlayer target, Player receiver) {
|
||||||
|
if (target != null) {
|
||||||
|
AnimationHelper helper = AnimationApi.getHelper(target);
|
||||||
|
helper.playAnimation(LAYER, helper.getAnimationPlaying(IEDGAnimation.LAYER));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ public abstract class BaseSeatBlockEntity extends BlockEntity {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void playAnimation(Player player, ISeatType ISeatType) {
|
public final void playAnimation(Player player, ISeatType ISeatType) {
|
||||||
if (getPlayerAnimationNumber() == 1) {
|
if (getPlayerAnimationNumber() == 1) {
|
||||||
SeatService.playBindingAnimation(player, ISeatType);
|
SeatService.playBindingAnimation(player, ISeatType);
|
||||||
} else SeatService.playBindingAnimation(player, ISeatType, getPlayerAnimationNumber());
|
} else SeatService.playBindingAnimation(player, ISeatType, getPlayerAnimationNumber());
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ public class SeatEntity extends Entity {
|
||||||
if (!this.level().isClientSide) {
|
if (!this.level().isClientSide) {
|
||||||
// 简化的检查逻辑
|
// 简化的检查逻辑
|
||||||
if (shouldRemove() && linkedBlockPos != null) {
|
if (shouldRemove() && linkedBlockPos != null) {
|
||||||
SeatService.releasePlayerFromBlock(this.level(), this.linkedBlockPos);
|
|
||||||
this.discard();
|
this.discard();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -234,7 +233,7 @@ public class SeatEntity extends Entity {
|
||||||
@Override
|
@Override
|
||||||
public void remove(@NotNull RemovalReason reason) {
|
public void remove(@NotNull RemovalReason reason) {
|
||||||
if (!level().isClientSide && this.linkedBlockPos != null) {
|
if (!level().isClientSide && this.linkedBlockPos != null) {
|
||||||
SeatService.releasePlayerFromBlock(level(), this.linkedBlockPos);
|
SeatService.releasePlayerFromBlock(level(), this.linkedBlockPos, this);
|
||||||
}
|
}
|
||||||
super.remove(reason);
|
super.remove(reason);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
import net.minecraft.server.players.GameProfileCache;
|
import net.minecraft.server.players.GameProfileCache;
|
||||||
import net.minecraft.server.players.PlayerList;
|
import net.minecraft.server.players.PlayerList;
|
||||||
import net.minecraft.stats.Stats;
|
|
||||||
import net.minecraft.tags.TagNetworkSerialization;
|
import net.minecraft.tags.TagNetworkSerialization;
|
||||||
import net.minecraft.world.effect.MobEffectInstance;
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
|
@ -139,7 +138,6 @@ public class NPCPlayerList {
|
||||||
servergamepacketlistenerimpl.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()));
|
servergamepacketlistenerimpl.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()));
|
||||||
servergamepacketlistenerimpl.send(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries)));
|
servergamepacketlistenerimpl.send(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries)));
|
||||||
this.sendPlayerPermissionLevel(npc);
|
this.sendPlayerPermissionLevel(npc);
|
||||||
npc.getStats().markAllDirty();
|
|
||||||
npc.getRecipeBook().sendInitialRecipeBook(npc);
|
npc.getRecipeBook().sendInitialRecipeBook(npc);
|
||||||
this.updateEntireScoreboard(serverlevel1.getScoreboard(), npc);
|
this.updateEntireScoreboard(serverlevel1.getScoreboard(), npc);
|
||||||
this.server.invalidateStatus();
|
this.server.invalidateStatus();
|
||||||
|
|
@ -364,11 +362,11 @@ public class NPCPlayerList {
|
||||||
protected void save(NPCServerPlayer npcServerPlayer) {
|
protected void save(NPCServerPlayer npcServerPlayer) {
|
||||||
this.npcIo.save(npcServerPlayer);
|
this.npcIo.save(npcServerPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAll() {
|
public void removeAll() {
|
||||||
for (NPCServerPlayer npc : this.npcs) {
|
for (NPCServerPlayer npc : this.npcs) {
|
||||||
npc.connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
|
npc.connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete(NPCServerPlayer npc) {
|
public void delete(NPCServerPlayer npc) {
|
||||||
|
|
@ -379,15 +377,14 @@ public class NPCPlayerList {
|
||||||
public void remove(NPCServerPlayer npc) {
|
public void remove(NPCServerPlayer npc) {
|
||||||
net.minecraftforge.event.ForgeEventFactory.firePlayerLoggedOut(npc);
|
net.minecraftforge.event.ForgeEventFactory.firePlayerLoggedOut(npc);
|
||||||
ServerLevel serverlevel = npc.serverLevel();
|
ServerLevel serverlevel = npc.serverLevel();
|
||||||
npc.awardStat(Stats.LEAVE_GAME);
|
|
||||||
this.save(npc);
|
this.save(npc);
|
||||||
if (npc.isPassenger()) {
|
if (npc.isPassenger()) {
|
||||||
Entity entity = npc.getRootVehicle();
|
Entity entity = npc.getRootVehicle();
|
||||||
if (entity.hasExactlyOnePlayerPassenger()) {
|
if (entity.hasExactlyOnePlayerPassenger()) {
|
||||||
LOGGER.debug("Removing player mount");
|
LOGGER.debug("Removing player mount");
|
||||||
npc.stopRiding();
|
npc.stopRiding();
|
||||||
entity.getPassengersAndSelf().forEach((p_215620_) -> {
|
entity.getPassengersAndSelf().forEach((entity1) -> {
|
||||||
p_215620_.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
entity1.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -508,6 +505,7 @@ public class NPCPlayerList {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinecraftServer getServer() {
|
public MinecraftServer getServer() {
|
||||||
return this.server;
|
return this.server;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ public class NPCServerPlayer extends ServerPlayer implements INPCPlayer {
|
||||||
};
|
};
|
||||||
public NPCServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile) {
|
public NPCServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile) {
|
||||||
super(server, level, gameProfile);
|
super(server, level, gameProfile);
|
||||||
|
getAdvancements().stopListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable NPCServerPlayer createNPC(String username, @NotNull MinecraftServer server, double x, double y, double z, double yaw, double pitch, ResourceKey<Level> dimensionId, GameType gamemode, boolean isflying) {
|
public static @Nullable NPCServerPlayer createNPC(String username, @NotNull MinecraftServer server, double x, double y, double z, double yaw, double pitch, ResourceKey<Level> dimensionId, GameType gamemode, boolean isflying) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ import top.r3944realms.eroticdungeongame.content.animation.IEDGAnimation;
|
||||||
import top.r3944realms.eroticdungeongame.content.block.ISeatBlock;
|
import top.r3944realms.eroticdungeongame.content.block.ISeatBlock;
|
||||||
import top.r3944realms.eroticdungeongame.content.block.blockentity.BaseSeatBlockEntity;
|
import top.r3944realms.eroticdungeongame.content.block.blockentity.BaseSeatBlockEntity;
|
||||||
import top.r3944realms.eroticdungeongame.content.util.FurnitureHelper;
|
import top.r3944realms.eroticdungeongame.content.util.FurnitureHelper;
|
||||||
|
import top.r3944realms.eroticdungeongame.core.device.ISeatType;
|
||||||
|
import top.r3944realms.eroticdungeongame.core.network.EDGNetworkHandler;
|
||||||
|
import top.r3944realms.eroticdungeongame.core.network.toServer.RefreshPlayerAnimationPacket;
|
||||||
import top.r3944realms.eroticdungeongame.util.IEDGEntity;
|
import top.r3944realms.eroticdungeongame.util.IEDGEntity;
|
||||||
import top.r3944realms.lib39.core.sync.CachedSyncManager;
|
import top.r3944realms.lib39.core.sync.CachedSyncManager;
|
||||||
|
|
||||||
|
|
@ -39,12 +42,15 @@ public class DungeonDataSyncManager extends CachedSyncManager<Capability<Abstrac
|
||||||
public Map<Capability<AbstractPlayerDungeonData>, AbstractPlayerDungeonData> getSyncMap() {
|
public Map<Capability<AbstractPlayerDungeonData>, AbstractPlayerDungeonData> getSyncMap() {
|
||||||
return playerDungeonData;
|
return playerDungeonData;
|
||||||
}
|
}
|
||||||
|
static int cooldown = 0;
|
||||||
public static void tick(@NotNull Player player) {
|
public static void tick(@NotNull Player player) {
|
||||||
|
if (cooldown > 0) {
|
||||||
|
cooldown--;
|
||||||
|
}
|
||||||
player.getCapability(PlayerDungeonDataProvider.PLAYER_DUNGEON_DATA_CAP).ifPresent(
|
player.getCapability(PlayerDungeonDataProvider.PLAYER_DUNGEON_DATA_CAP).ifPresent(
|
||||||
cap -> {
|
cap -> {
|
||||||
if (player.level().isClientSide) {
|
if (player.level().isClientSide) {
|
||||||
clientTick(player);
|
clientTick(player, cap);
|
||||||
} else if (cap.getDeviceMainBlockPos() != null) {
|
} else if (cap.getDeviceMainBlockPos() != null) {
|
||||||
if (cap.getEyeHeight() != -1.0 && cap.getEyeHeight() >= 0.0) {
|
if (cap.getEyeHeight() != -1.0 && cap.getEyeHeight() >= 0.0) {
|
||||||
EntityDimensions dimensions = player.getDimensions(player.getPose());
|
EntityDimensions dimensions = player.getDimensions(player.getPose());
|
||||||
|
|
@ -57,8 +63,16 @@ public class DungeonDataSyncManager extends CachedSyncManager<Capability<Abstrac
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public static void clientTick(@NotNull Player player) {
|
public static void clientTick(@NotNull Player player, AbstractPlayerDungeonData dungeonData) {
|
||||||
|
if (IEDGAnimation.getPlayingAnimation(player) == null) {
|
||||||
|
if (dungeonData.getDeviceMainBlockPos() != null && player.level().getBlockEntity(dungeonData.getDeviceMainBlockPos()) instanceof BaseSeatBlockEntity baseSeatBlockEntity) {
|
||||||
|
ISeatType seatType = FurnitureHelper.getSeatType(baseSeatBlockEntity.getBlockState().getBlock());
|
||||||
|
if (seatType != null && cooldown == 0) {
|
||||||
|
EDGNetworkHandler.sendToServer(new RefreshPlayerAnimationPacket(player.getUUID()));
|
||||||
|
cooldown = 100; //5s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void login(@NotNull Player player) {
|
public static void login(@NotNull Player player) {
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
||||||
import top.r3944realms.eroticdungeongame.api.workspace.Services;
|
import top.r3944realms.eroticdungeongame.api.workspace.Services;
|
||||||
|
import top.r3944realms.eroticdungeongame.client.ClientNPCManager;
|
||||||
import top.r3944realms.eroticdungeongame.client.EDGKeyBindings;
|
import top.r3944realms.eroticdungeongame.client.EDGKeyBindings;
|
||||||
import top.r3944realms.eroticdungeongame.client.gui.screens.DungeonCraftingScreen;
|
import top.r3944realms.eroticdungeongame.client.gui.screens.DungeonCraftingScreen;
|
||||||
import top.r3944realms.eroticdungeongame.client.model.EDGArmPose;
|
import top.r3944realms.eroticdungeongame.client.model.EDGArmPose;
|
||||||
|
|
@ -58,6 +59,7 @@ import top.r3944realms.eroticdungeongame.content.item.DeviceKeyItem;
|
||||||
import top.r3944realms.eroticdungeongame.content.particle.VerticalWhipSweepParticle;
|
import top.r3944realms.eroticdungeongame.content.particle.VerticalWhipSweepParticle;
|
||||||
import top.r3944realms.eroticdungeongame.content.particle.WhipScarParticle;
|
import top.r3944realms.eroticdungeongame.content.particle.WhipScarParticle;
|
||||||
import top.r3944realms.eroticdungeongame.core.network.EDGNetworkHandler;
|
import top.r3944realms.eroticdungeongame.core.network.EDGNetworkHandler;
|
||||||
|
import top.r3944realms.eroticdungeongame.core.network.NPCEmptyClientConnection;
|
||||||
import top.r3944realms.eroticdungeongame.core.network.toServer.RequestQuitDevicePacket;
|
import top.r3944realms.eroticdungeongame.core.network.toServer.RequestQuitDevicePacket;
|
||||||
import top.r3944realms.eroticdungeongame.core.register.EDGBlockEntities;
|
import top.r3944realms.eroticdungeongame.core.register.EDGBlockEntities;
|
||||||
import top.r3944realms.eroticdungeongame.core.register.EDGEntities;
|
import top.r3944realms.eroticdungeongame.core.register.EDGEntities;
|
||||||
|
|
@ -74,6 +76,19 @@ import java.util.Optional;
|
||||||
public class ClientHandler {
|
public class ClientHandler {
|
||||||
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = EroticDungeon.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT)
|
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = EroticDungeon.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT)
|
||||||
public static class Game extends ClientHandler {
|
public static class Game extends ClientHandler {
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onLoginIn(ClientPlayerNetworkEvent.LoggingIn event) {
|
||||||
|
if (!(event.getConnection() instanceof NPCEmptyClientConnection)) {
|
||||||
|
ClientNPCManager.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onLoginOut(ClientPlayerNetworkEvent.LoggingOut event) {
|
||||||
|
if (!(event.getConnection() instanceof NPCEmptyClientConnection)) {
|
||||||
|
ClientNPCManager.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onSpanishDonkeyTremble(RenderPlayerEvent event) {
|
public static void onSpanishDonkeyTremble(RenderPlayerEvent event) {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import net.minecraftforge.event.RegisterCommandsEvent;
|
||||||
import net.minecraftforge.event.TickEvent;
|
import net.minecraftforge.event.TickEvent;
|
||||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||||
import net.minecraftforge.event.server.ServerStartedEvent;
|
import net.minecraftforge.event.server.ServerStartedEvent;
|
||||||
|
import net.minecraftforge.event.server.ServerStoppingEvent;
|
||||||
import net.minecraftforge.eventbus.api.IEventBus;
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
|
@ -78,6 +79,10 @@ public class CommonHandler {
|
||||||
iedgMinecraftServer.getNPCPlayerList().loadAllNPCs();
|
iedgMinecraftServer.getNPCPlayerList().loadAllNPCs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onServerStopping(@NotNull ServerStoppingEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void syncCapabilities(SyncManagerRegisterEvent event) {
|
public static void syncCapabilities(SyncManagerRegisterEvent event) {
|
||||||
|
|
@ -85,6 +90,7 @@ public class CommonHandler {
|
||||||
event.registerSyncManager(DUNGEON_SYNC, dungeonDataSyncManager, PlayerDungeonDataProvider.PLAYER_DUNGEON_DATA_CAP);
|
event.registerSyncManager(DUNGEON_SYNC, dungeonDataSyncManager, PlayerDungeonDataProvider.PLAYER_DUNGEON_DATA_CAP);
|
||||||
event.addAllowEntityClass(DUNGEON_SYNC, Player.class);
|
event.addAllowEntityClass(DUNGEON_SYNC, Player.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static char ticks = 0;
|
private static char ticks = 0;
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPlayerTick (TickEvent.PlayerTickEvent event) {
|
public static void onPlayerTick (TickEvent.PlayerTickEvent event) {
|
||||||
|
|
@ -103,7 +109,6 @@ public class CommonHandler {
|
||||||
DungeonDataSyncManager.login(player);
|
DungeonDataSyncManager.login(player);
|
||||||
if (player.getServer() instanceof IEDGMinecraftServer iedgMinecraftServer && player instanceof ServerPlayer serverPlayer && !(player instanceof INPCPlayer)) {
|
if (player.getServer() instanceof IEDGMinecraftServer iedgMinecraftServer && player instanceof ServerPlayer serverPlayer && !(player instanceof INPCPlayer)) {
|
||||||
EDGNetworkHandler.sendToPlayer(NPCInfoUpdatePacket.createNPCPlayerInitializing(iedgMinecraftServer.getNPCPlayerList().getPlayers()), serverPlayer);
|
EDGNetworkHandler.sendToPlayer(NPCInfoUpdatePacket.createNPCPlayerInitializing(iedgMinecraftServer.getNPCPlayerList().getPlayers()), serverPlayer);
|
||||||
serverPlayer.serverLevel().getChunkSource().removeEntity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import top.r3944realms.eroticdungeongame.EroticDungeon;
|
||||||
import top.r3944realms.eroticdungeongame.core.network.toClient.NPCInfoRemovePacket;
|
import top.r3944realms.eroticdungeongame.core.network.toClient.NPCInfoRemovePacket;
|
||||||
import top.r3944realms.eroticdungeongame.core.network.toClient.NPCInfoUpdatePacket;
|
import top.r3944realms.eroticdungeongame.core.network.toClient.NPCInfoUpdatePacket;
|
||||||
import top.r3944realms.eroticdungeongame.core.network.toServer.LoveMachineConfigPacket;
|
import top.r3944realms.eroticdungeongame.core.network.toServer.LoveMachineConfigPacket;
|
||||||
|
import top.r3944realms.eroticdungeongame.core.network.toServer.RefreshPlayerAnimationPacket;
|
||||||
import top.r3944realms.eroticdungeongame.core.network.toServer.RequestQuitDevicePacket;
|
import top.r3944realms.eroticdungeongame.core.network.toServer.RequestQuitDevicePacket;
|
||||||
import top.r3944realms.eroticdungeongame.util.IEDGMinecraftServer;
|
import top.r3944realms.eroticdungeongame.util.IEDGMinecraftServer;
|
||||||
|
|
||||||
|
|
@ -64,11 +65,16 @@ public class EDGNetworkHandler {
|
||||||
.decoder(NPCInfoRemovePacket::new)
|
.decoder(NPCInfoRemovePacket::new)
|
||||||
.consumerMainThread(NPCInfoRemovePacket::handle)
|
.consumerMainThread(NPCInfoRemovePacket::handle)
|
||||||
.add();
|
.add();
|
||||||
CHANNEL.messageBuilder(NPCInfoUpdatePacket.class, getIndex(), NetworkDirection.PLAY_TO_CLIENT)
|
CHANNEL.messageBuilder(NPCInfoUpdatePacket.class, getIndex())
|
||||||
.encoder(NPCInfoUpdatePacket::write)
|
.encoder(NPCInfoUpdatePacket::write)
|
||||||
.decoder(NPCInfoUpdatePacket::new)
|
.decoder(NPCInfoUpdatePacket::new)
|
||||||
.consumerMainThread(NPCInfoUpdatePacket::handle)
|
.consumerMainThread(NPCInfoUpdatePacket::handle)
|
||||||
.add();
|
.add();
|
||||||
|
CHANNEL.messageBuilder(RefreshPlayerAnimationPacket.class, getIndex(), NetworkDirection.PLAY_TO_SERVER)
|
||||||
|
.encoder(RefreshPlayerAnimationPacket::encode)
|
||||||
|
.decoder(RefreshPlayerAnimationPacket::new)
|
||||||
|
.consumerMainThread(RefreshPlayerAnimationPacket::handle)
|
||||||
|
.add();
|
||||||
}
|
}
|
||||||
public static int getIndex() {
|
public static int getIndex() {
|
||||||
return cid.getAndIncrement();
|
return cid.getAndIncrement();
|
||||||
|
|
@ -81,4 +87,7 @@ public class EDGNetworkHandler {
|
||||||
public static <MSG> void sendToAllPlayer(MSG message){
|
public static <MSG> void sendToAllPlayer(MSG message){
|
||||||
CHANNEL.send(ALL_PLAYER.noArg(), message);
|
CHANNEL.send(ALL_PLAYER.noArg(), message);
|
||||||
}
|
}
|
||||||
|
public static <MSG> void sendToServer(MSG message){
|
||||||
|
CHANNEL.sendToServer(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
||||||
|
import top.r3944realms.eroticdungeongame.client.ClientNPCManager;
|
||||||
import top.r3944realms.eroticdungeongame.content.entity.npc.NPCServerPlayer;
|
import top.r3944realms.eroticdungeongame.content.entity.npc.NPCServerPlayer;
|
||||||
import top.r3944realms.eroticdungeongame.util.IEDGClientPacketListener;
|
import top.r3944realms.eroticdungeongame.util.IEDGClientPacketListener;
|
||||||
|
|
||||||
|
|
@ -96,6 +97,7 @@ public final class NPCInfoUpdatePacket {
|
||||||
for (Entry entry : packet.newEntries()) {
|
for (Entry entry : packet.newEntries()) {
|
||||||
PlayerInfo npcInfo = new PlayerInfo(entry.profile, false);
|
PlayerInfo npcInfo = new PlayerInfo(entry.profile, false);
|
||||||
iedgClientPacketListener.getNPCPlayerInfoMap().putIfAbsent(entry.uuid(), npcInfo);
|
iedgClientPacketListener.getNPCPlayerInfoMap().putIfAbsent(entry.uuid(), npcInfo);
|
||||||
|
ClientNPCManager.processPendingNPCs(npcInfo);
|
||||||
}
|
}
|
||||||
for (Entry entry : packet.entries) {
|
for (Entry entry : packet.entries) {
|
||||||
PlayerInfo npcInfo = iedgClientPacketListener.getNPCPlayerInfoMap().get(entry.uuid);
|
PlayerInfo npcInfo = iedgClientPacketListener.getNPCPlayerInfoMap().get(entry.uuid);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025-2026 R3944Realms
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package top.r3944realms.eroticdungeongame.core.network.toServer;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraftforge.network.NetworkEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import top.r3944realms.eroticdungeongame.content.animation.IEDGAnimation;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public record RefreshPlayerAnimationPacket(UUID uuid) {
|
||||||
|
public RefreshPlayerAnimationPacket(@NotNull FriendlyByteBuf buf) {
|
||||||
|
this(buf.readUUID());
|
||||||
|
}
|
||||||
|
public void encode(@NotNull FriendlyByteBuf buf) {
|
||||||
|
buf.writeUUID(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(@NotNull Supplier<NetworkEvent.Context> contextSupplier) {
|
||||||
|
NetworkEvent.Context context = contextSupplier.get();
|
||||||
|
ServerPlayer sender = context.getSender();
|
||||||
|
context.enqueueWork(() -> {
|
||||||
|
if (sender != null) {
|
||||||
|
if (sender.serverLevel().getEntity(uuid) instanceof ServerPlayer target) {
|
||||||
|
IEDGAnimation.refresh(target, sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
context.setPacketHandled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,6 +28,7 @@ import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
import top.r3944realms.eroticdungeongame.EroticDungeon;
|
||||||
import top.r3944realms.eroticdungeongame.api.event.RideDeviceEvent;
|
import top.r3944realms.eroticdungeongame.api.event.RideDeviceEvent;
|
||||||
import top.r3944realms.eroticdungeongame.api.event.UnRideDeviceEvent;
|
import top.r3944realms.eroticdungeongame.api.event.UnRideDeviceEvent;
|
||||||
|
|
@ -125,6 +126,17 @@ public class SeatService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从方块位置释放玩家(但会检查是否为目标座椅,避免释放错座椅)
|
||||||
|
*/
|
||||||
|
public static boolean releasePlayerFromBlock(@NotNull Level level, @NotNull BlockPos blockPos, SeatEntity seat) {
|
||||||
|
BaseSeatBlockEntity blockEntity = FurnitureHelper.getSeatBlockEntity(level, blockPos);
|
||||||
|
if (blockEntity != null) {
|
||||||
|
return releasePlayer(level, blockPos, seat);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static @NotNull Optional<SeatEntity> getPlayerSeat(@NotNull Player player) {
|
public static @NotNull Optional<SeatEntity> getPlayerSeat(@NotNull Player player) {
|
||||||
return player.getCapability(PlayerDungeonDataProvider.PLAYER_DUNGEON_DATA_CAP).resolve().map(cap -> {
|
return player.getCapability(PlayerDungeonDataProvider.PLAYER_DUNGEON_DATA_CAP).resolve().map(cap -> {
|
||||||
BlockPos deviceMainBlockPos = cap.getDeviceMainBlockPos();
|
BlockPos deviceMainBlockPos = cap.getDeviceMainBlockPos();
|
||||||
|
|
@ -241,14 +253,29 @@ public class SeatService {
|
||||||
*/
|
*/
|
||||||
public static boolean releasePlayer(@NotNull Level level, BlockPos blockPos) {
|
public static boolean releasePlayer(@NotNull Level level, BlockPos blockPos) {
|
||||||
BaseSeatBlockEntity seatBlockEntity = FurnitureHelper.getSeatBlockEntity(level, blockPos);
|
BaseSeatBlockEntity seatBlockEntity = FurnitureHelper.getSeatBlockEntity(level, blockPos);
|
||||||
return releasePlayerInternal(seatBlockEntity, level, blockPos);
|
BlockState blockState = level.getBlockState(blockPos);
|
||||||
|
boolean flag = releasePlayerInternal(seatBlockEntity, level, blockState, blockPos);
|
||||||
|
if (flag) {
|
||||||
|
FurnitureHelper.setSeatOccupied(level, blockPos, false);
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
public static boolean releasePlayer(@NotNull Level level, BlockPos blockPos,@NotNull SeatEntity seat) {
|
||||||
|
BaseSeatBlockEntity seatBe = FurnitureHelper.getSeatBlockEntity(level, blockPos);
|
||||||
|
BlockState blockState = level.getBlockState(blockPos);
|
||||||
|
boolean flag = releasePlayerInternal(seatBe, level, blockPos, blockState, seat);
|
||||||
|
if (flag) {
|
||||||
|
FurnitureHelper.setSeatOccupied(level, blockPos, false);
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean releasePlayerInternal(BaseSeatBlockEntity be, @NotNull Level level, BlockPos blockPos) {
|
private static boolean releasePlayerInternal(BaseSeatBlockEntity be, @NotNull Level level, BlockState blockState, BlockPos blockPos) {
|
||||||
BlockState blockState = level.getBlockState(blockPos);
|
return releasePlayerInternal(be, level, blockPos, blockState, null);
|
||||||
// 1. 更新方块状态
|
}
|
||||||
FurnitureHelper.setSeatOccupied(level, blockPos, false);
|
|
||||||
|
|
||||||
|
//检查是否与释放预期座椅一致
|
||||||
|
private static boolean releasePlayerInternal(BaseSeatBlockEntity be, @NotNull Level level, BlockPos blockPos, BlockState blockState, @Nullable SeatEntity seat) {
|
||||||
// 2. 处理实体(只在服务端)
|
// 2. 处理实体(只在服务端)
|
||||||
if (level instanceof ServerLevel) {
|
if (level instanceof ServerLevel) {
|
||||||
Player playerByUUID;
|
Player playerByUUID;
|
||||||
|
|
@ -256,13 +283,16 @@ public class SeatService {
|
||||||
if (be.getBoundPlayerUUID() != null) {
|
if (be.getBoundPlayerUUID() != null) {
|
||||||
playerByUUID = level.getPlayerByUUID(be.getBoundPlayerUUID());
|
playerByUUID = level.getPlayerByUUID(be.getBoundPlayerUUID());
|
||||||
if (playerByUUID != null) {
|
if (playerByUUID != null) {
|
||||||
SeatEntity seat = null;
|
SeatEntity seat_ = null;
|
||||||
if (playerByUUID.isPassenger() && playerByUUID.getVehicle() instanceof SeatEntity seatEntity) {
|
if (playerByUUID.isPassenger() && playerByUUID.getVehicle() instanceof SeatEntity seatEntity) {
|
||||||
seat = seatEntity;
|
seat_ = seatEntity;
|
||||||
|
if (seat != null && seat_ != seat) {
|
||||||
|
return false; //预期座椅不一致
|
||||||
}
|
}
|
||||||
isCancelled = EroticDungeon.EVENT_BUS.post(new UnRideDeviceEvent.Pre(playerByUUID, blockPos, blockState, be, seat));
|
}
|
||||||
|
isCancelled = EroticDungeon.EVENT_BUS.post(new UnRideDeviceEvent.Pre(playerByUUID, blockPos, blockState, be, seat_));
|
||||||
if (!isCancelled) {
|
if (!isCancelled) {
|
||||||
if(seat != null) ((IEDGEntity)(playerByUUID)).releaseEntityFromEDGDevice(true);
|
if(seat_ != null) ((IEDGEntity)(playerByUUID)).releaseEntityFromEDGDevice(true);
|
||||||
playerByUUID.getCapability(PlayerDungeonDataProvider.PLAYER_DUNGEON_DATA_CAP)
|
playerByUUID.getCapability(PlayerDungeonDataProvider.PLAYER_DUNGEON_DATA_CAP)
|
||||||
.ifPresent(i -> i.clearDungeonData(playerByUUID));
|
.ifPresent(i -> i.clearDungeonData(playerByUUID));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025-2026 R3944Realms
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
package top.r3944realms.eroticdungeongame.datagen;
|
package top.r3944realms.eroticdungeongame.datagen;
|
||||||
|
|
||||||
import net.minecraft.core.RegistrySetBuilder;
|
import net.minecraft.core.RegistrySetBuilder;
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,18 @@ import com.google.common.collect.Maps;
|
||||||
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
||||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
|
import com.mojang.brigadier.ParseResults;
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
||||||
import net.minecraft.client.Minecraft;
|
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.client.multiplayer.PlayerInfo;
|
import net.minecraft.client.multiplayer.PlayerInfo;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.protocol.PacketUtils;
|
import net.minecraft.network.protocol.PacketUtils;
|
||||||
import net.minecraft.network.protocol.game.ClientboundAddPlayerPacket;
|
import net.minecraft.network.protocol.game.*;
|
||||||
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.vehicle.Boat;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
@ -40,6 +42,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||||
|
import top.r3944realms.eroticdungeongame.client.ClientNPCManager;
|
||||||
import top.r3944realms.eroticdungeongame.client.EDGKeyBindings;
|
import top.r3944realms.eroticdungeongame.client.EDGKeyBindings;
|
||||||
import top.r3944realms.eroticdungeongame.content.entity.SeatEntity;
|
import top.r3944realms.eroticdungeongame.content.entity.SeatEntity;
|
||||||
import top.r3944realms.eroticdungeongame.content.entity.npc.NPCRemotePlayer;
|
import top.r3944realms.eroticdungeongame.content.entity.npc.NPCRemotePlayer;
|
||||||
|
|
@ -50,6 +53,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantValue")
|
||||||
@Mixin(ClientPacketListener.class)
|
@Mixin(ClientPacketListener.class)
|
||||||
public abstract class MixinClientPacketListener implements IEDGClientPacketListener {
|
public abstract class MixinClientPacketListener implements IEDGClientPacketListener {
|
||||||
@Unique
|
@Unique
|
||||||
|
|
@ -66,6 +70,27 @@ public abstract class MixinClientPacketListener implements IEDGClientPacketListe
|
||||||
|
|
||||||
@Shadow @Final private Set<PlayerInfo> listedPlayers;
|
@Shadow @Final private Set<PlayerInfo> listedPlayers;
|
||||||
@Shadow private ClientLevel level;
|
@Shadow private ClientLevel level;
|
||||||
|
|
||||||
|
@Shadow public abstract void handleSetEntityMotion(ClientboundSetEntityMotionPacket packet);
|
||||||
|
|
||||||
|
@Shadow public abstract void handleSetEntityData(ClientboundSetEntityDataPacket packet);
|
||||||
|
|
||||||
|
@Shadow public abstract void handleUpdateAttributes(ClientboundUpdateAttributesPacket packet);
|
||||||
|
|
||||||
|
@Shadow public abstract void handleSetEquipment(ClientboundSetEquipmentPacket packet);
|
||||||
|
|
||||||
|
@Shadow public abstract void handleSetEntityPassengersPacket(ClientboundSetPassengersPacket packet);
|
||||||
|
|
||||||
|
@Shadow public abstract void handleEntityLinkPacket(ClientboundSetEntityLinkPacket packet);
|
||||||
|
|
||||||
|
@Shadow protected abstract ParseResults<SharedSuggestionProvider> parseCommand(String command);
|
||||||
|
|
||||||
|
@Shadow public abstract void handleRotateMob(ClientboundRotateHeadPacket packet);
|
||||||
|
|
||||||
|
@Shadow public abstract void handleMoveEntity(ClientboundMoveEntityPacket packet);
|
||||||
|
|
||||||
|
@Shadow public abstract void handleTeleportEntity(ClientboundTeleportEntityPacket packet);
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private Entity edg$cachedMount = null;
|
private Entity edg$cachedMount = null;
|
||||||
|
|
||||||
|
|
@ -91,8 +116,133 @@ public abstract class MixinClientPacketListener implements IEDGClientPacketListe
|
||||||
if (playerinfo == null) {
|
if (playerinfo == null) {
|
||||||
PlayerInfo npcPlayerInfo = getNPCPlayerInfo(packet.getPlayerId());
|
PlayerInfo npcPlayerInfo = getNPCPlayerInfo(packet.getPlayerId());
|
||||||
if (npcPlayerInfo == null) {
|
if (npcPlayerInfo == null) {
|
||||||
|
ClientNPCManager.cacheNPCIfNeeded(packet);
|
||||||
original.call(packet);
|
original.call(packet);
|
||||||
} else {
|
} else {
|
||||||
|
edg$createNPCPlayer(packet, npcPlayerInfo);
|
||||||
|
}
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleSetEntityData"
|
||||||
|
)
|
||||||
|
private void edg$handleSetEntityData(ClientboundSetEntityDataPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = this.level.getEntity(packet.id());
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cacheEntityDataIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleSetEntityMotion"
|
||||||
|
)
|
||||||
|
private void edg$handleSetEntityMotion(ClientboundSetEntityMotionPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = this.level.getEntity(packet.getId());
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cacheMotionIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleTeleportEntity"
|
||||||
|
)
|
||||||
|
private void edg$handleTeleportEntity(ClientboundTeleportEntityPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = this.level.getEntity(packet.getId());
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cacheTeleportEntityIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleMoveEntity"
|
||||||
|
)
|
||||||
|
private void edg$handleMoveEntity(ClientboundMoveEntityPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = packet.getEntity(this.level);
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cacheMoveEntityIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleUpdateAttributes"
|
||||||
|
)
|
||||||
|
private void edg$handleUpdateAttributes(ClientboundUpdateAttributesPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = this.level.getEntity(packet.getEntityId());
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cacheAttributesIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleSetEntityPassengersPacket"
|
||||||
|
)
|
||||||
|
private void edg$handleSetEntityPassengersPacket(ClientboundSetPassengersPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = this.level.getEntity(packet.getVehicle());
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cachePassengersIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else {
|
||||||
|
for(int i : packet.getPassengers()) {
|
||||||
|
Entity entity1 = this.level.getEntity(i);
|
||||||
|
if (entity1 == null) {
|
||||||
|
ClientNPCManager.cachePassengersIfNeeded(packet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
original.call(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleSetEquipment"
|
||||||
|
)
|
||||||
|
private void edg$handleSetEquipment(ClientboundSetEquipmentPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = this.level.getEntity(packet.getEntity());
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cacheEquipmentIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleEntityLinkPacket"
|
||||||
|
)
|
||||||
|
private void edg$handleEntityLinkPacket(ClientboundSetEntityLinkPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = this.level.getEntity(packet.getSourceId());
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cacheLinkIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapMethod(
|
||||||
|
method = "handleRotateMob"
|
||||||
|
)
|
||||||
|
private void edg$handleRotateMob(ClientboundRotateHeadPacket packet, Operation<Void> original){
|
||||||
|
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
|
||||||
|
Entity entity = packet.getEntity(this.level);
|
||||||
|
if (entity == null) {
|
||||||
|
ClientNPCManager.cacheHeadRotationIfNeeded(packet);
|
||||||
|
original.call(packet);
|
||||||
|
} else original.call(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$createNPCPlayer(@NotNull ClientboundAddPlayerPacket packet, @NotNull PlayerInfo npcPlayerInfo) {
|
||||||
double d0 = packet.getX();
|
double d0 = packet.getX();
|
||||||
double d1 = packet.getY();
|
double d1 = packet.getY();
|
||||||
double d2 = packet.getZ();
|
double d2 = packet.getZ();
|
||||||
|
|
@ -108,8 +258,6 @@ public abstract class MixinClientPacketListener implements IEDGClientPacketListe
|
||||||
npcRemotePlayer.setOldPosAndRot();
|
npcRemotePlayer.setOldPosAndRot();
|
||||||
this.level.addPlayer(i, npcRemotePlayer);
|
this.level.addPlayer(i, npcRemotePlayer);
|
||||||
}
|
}
|
||||||
} else original.call(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "SuspiciousMethodCalls"})
|
@SuppressWarnings({"unchecked", "SuspiciousMethodCalls"})
|
||||||
@WrapOperation(
|
@WrapOperation(
|
||||||
|
|
@ -138,4 +286,49 @@ public abstract class MixinClientPacketListener implements IEDGClientPacketListe
|
||||||
public Set<PlayerInfo> getListedNPCPlayers() {
|
public Set<PlayerInfo> getListedNPCPlayers() {
|
||||||
return listedPlayers;
|
return listedPlayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$setEntityMotion(ClientboundSetEntityMotionPacket packet) {
|
||||||
|
handleSetEntityMotion(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$setEntityData(ClientboundSetEntityDataPacket packet) {
|
||||||
|
handleSetEntityData(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$updateAttributes(ClientboundUpdateAttributesPacket packet) {
|
||||||
|
handleUpdateAttributes(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$setEquipment(ClientboundSetEquipmentPacket packet) {
|
||||||
|
handleSetEquipment(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$setPassengers(ClientboundSetPassengersPacket packet) {
|
||||||
|
handleSetEntityPassengersPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$setEntityLink(ClientboundSetEntityLinkPacket packet) {
|
||||||
|
handleEntityLinkPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$rotateHead(ClientboundRotateHeadPacket packet) {
|
||||||
|
handleRotateMob(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$moveEntity(ClientboundMoveEntityPacket packet) {
|
||||||
|
handleMoveEntity(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edg$teleportEntity(ClientboundTeleportEntityPacket packet) {
|
||||||
|
handleTeleportEntity(packet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public abstract class MixinGameTestServer implements IEDGMinecraftServer {
|
||||||
@WrapOperation(
|
@WrapOperation(
|
||||||
method = "initServer",
|
method = "initServer",
|
||||||
at = @At(
|
at = @At(
|
||||||
value = "HEAD",
|
value = "INVOKE",
|
||||||
target = "Lnet/minecraft/gametest/framework/GameTestServer;setPlayerList(Lnet/minecraft/server/players/PlayerList;)V"
|
target = "Lnet/minecraft/gametest/framework/GameTestServer;setPlayerList(Lnet/minecraft/server/players/PlayerList;)V"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025-2026 R3944Realms
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
package top.r3944realms.eroticdungeongame.mixin.minecraft;
|
package top.r3944realms.eroticdungeongame.mixin.minecraft;
|
||||||
|
|
||||||
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
||||||
|
|
|
||||||
|
|
@ -83,8 +83,7 @@ public abstract class MixinServerPlayer extends Player implements IEDGEntity {
|
||||||
if (data.getDeviceMainBlockPos() != null && level().getBlockEntity(data.getDeviceMainBlockPos()) instanceof BaseSeatBlockEntity seatBe) {
|
if (data.getDeviceMainBlockPos() != null && level().getBlockEntity(data.getDeviceMainBlockPos()) instanceof BaseSeatBlockEntity seatBe) {
|
||||||
if (isCreative() || forced || (seatBe.hasLockCode() && Objects.equals(seatBe.getLockCode(), lock)) || !seatBe.hasLockCode()) {
|
if (isCreative() || forced || (seatBe.hasLockCode() && Objects.equals(seatBe.getLockCode(), lock)) || !seatBe.hasLockCode()) {
|
||||||
Entity entity = this.getVehicle();
|
Entity entity = this.getVehicle();
|
||||||
this.removeVehicle();
|
if (entity != null && !this.level().isClientSide) {
|
||||||
if (entity != null && entity != this.getVehicle() && !this.level().isClientSide) {
|
|
||||||
Vec3 vec3;
|
Vec3 vec3;
|
||||||
if (this.isRemoved()) {
|
if (this.isRemoved()) {
|
||||||
vec3 = this.position();
|
vec3 = this.position();
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package top.r3944realms.eroticdungeongame.util;
|
package top.r3944realms.eroticdungeongame.util;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.PlayerInfo;
|
import net.minecraft.client.multiplayer.PlayerInfo;
|
||||||
|
import net.minecraft.network.protocol.game.*;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -26,17 +27,22 @@ import java.util.UUID;
|
||||||
|
|
||||||
public interface IEDGClientPacketListener {
|
public interface IEDGClientPacketListener {
|
||||||
Map<UUID, PlayerInfo> getNPCPlayerInfoMap();
|
Map<UUID, PlayerInfo> getNPCPlayerInfoMap();
|
||||||
|
|
||||||
Set<PlayerInfo> getListedNPCPlayers();
|
Set<PlayerInfo> getListedNPCPlayers();
|
||||||
|
|
||||||
default Collection<PlayerInfo> getOnlineNPCPlayers() {
|
default Collection<PlayerInfo> getOnlineNPCPlayers() {
|
||||||
return getNPCPlayerInfoMap().values();
|
return getNPCPlayerInfoMap().values();
|
||||||
}
|
}
|
||||||
|
|
||||||
default Collection<UUID> getOnlineNPCPlayerIds() {
|
default Collection<UUID> getOnlineNPCPlayerIds() {
|
||||||
return getNPCPlayerInfoMap().keySet();
|
return getNPCPlayerInfoMap().keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
default PlayerInfo getNPCPlayerInfo(UUID uniqueId) {
|
default PlayerInfo getNPCPlayerInfo(UUID uniqueId) {
|
||||||
return getNPCPlayerInfoMap().get(uniqueId);
|
return getNPCPlayerInfoMap().get(uniqueId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
default PlayerInfo getNPCPlayerInfo(String name) {
|
default PlayerInfo getNPCPlayerInfo(String name) {
|
||||||
for(PlayerInfo playerinfo : getNPCPlayerInfoMap().values()) {
|
for(PlayerInfo playerinfo : getNPCPlayerInfoMap().values()) {
|
||||||
|
|
@ -46,4 +52,26 @@ public interface IEDGClientPacketListener {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void edg$createNPCPlayer(ClientboundAddPlayerPacket packet, PlayerInfo playerInfo);
|
||||||
|
|
||||||
|
// void edg$createEntity(ClientboundAddEntityPacket packet);
|
||||||
|
|
||||||
|
void edg$setEntityMotion(ClientboundSetEntityMotionPacket packet);
|
||||||
|
|
||||||
|
void edg$setEntityData(ClientboundSetEntityDataPacket packet);
|
||||||
|
|
||||||
|
void edg$updateAttributes(ClientboundUpdateAttributesPacket packet);
|
||||||
|
|
||||||
|
void edg$setEquipment(ClientboundSetEquipmentPacket packet);
|
||||||
|
|
||||||
|
void edg$setPassengers(ClientboundSetPassengersPacket packet);
|
||||||
|
|
||||||
|
void edg$setEntityLink(ClientboundSetEntityLinkPacket packet);
|
||||||
|
|
||||||
|
void edg$rotateHead(ClientboundRotateHeadPacket packet);
|
||||||
|
|
||||||
|
void edg$moveEntity(ClientboundMoveEntityPacket movePacket);
|
||||||
|
|
||||||
|
void edg$teleportEntity(ClientboundTeleportEntityPacket teleportPacket);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user