本帖最后由 黎雨轩 于 2021-10-19 09:35 编辑 
PlayerEvent.Clone的代码如下:
复制代码网络包的代码如下:
复制代码然后描述一下我发现的问题:
我想知道:
github:https://github.com/LiYuxuanhaha/SaintChapter
PlayerEvent.Clone的代码如下:
- public static void onPlayerCloned(PlayerEvent.Clone event) {
 
-         // 死亡或者转换维度时的能力处理
 
-         if (!event.getOriginal().world.isRemote() && !event.getPlayer().world.isRemote() && event.getOriginal() != null && event.getPlayer() != null) {
 
-             LazyOptional<IMindCapability> oldMindCap = event.getOriginal().getCapability(LibCapabilities.MIND_CAPABILITY);
 
-             LazyOptional<IMindCapability> newMindCap = event.getPlayer().getCapability(LibCapabilities.MIND_CAPABILITY);
 
-             if (oldMindCap.isPresent() && newMindCap.isPresent()) {
 
-                 newMindCap.ifPresent(capability -> {
 
-                     oldMindCap.ifPresent(capabilityOld -> {
 
-                         event.getPlayer().sendMessage(new StringTextComponent("Before: " + capability.getMindStrength()), CommonProxy.IN_GAME_UUID);
 
-                         capability.deserializeNBT(capabilityOld.serializeNBT());
 
-                         event.getPlayer().sendMessage(new StringTextComponent("After: " + capability.getMindStrength()), CommonProxy.IN_GAME_UUID);
 
-                     });
 
-                     SCPacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) event.getPlayer()), new MSGMindCapabilitySync(capability.getMindStrength()));
 
-                     // 这条代码可以解决问题,为什么要从客户端发送到服务端?
 
-                     // SCPacketHandler.INSTANCE.sendToServer(new MSGMindCapabilitySync(capability.getMindStrength()));
 
-                 });
 
-             }
 
-         }
 
- }
- public class MSGMindCapabilitySync {
 
-     private final int mindStrength;
 
 
-     public MSGMindCapabilitySync(int mindStrength) {
 
-         this.mindStrength = mindStrength;
 
 
-     }
 
 
-     public static void encodingMSG(MSGMindCapabilitySync msg, PacketBuffer buffer) {
 
-         buffer.writeInt(msg.mindStrength);
 
-     }
 
 
-     public static MSGMindCapabilitySync decodingMSG(PacketBuffer buffer) {
 
-         return new MSGMindCapabilitySync(buffer.readInt());
 
-     }
 
 
-     public static void handle(MSGMindCapabilitySync msg, Supplier<NetworkEvent.Context> ctx) {
 
-         ctx.get().enqueueWork(() -> {
 
-             // 从客户端发送到服务端
 
-             ServerPlayerEntity serverPlayer = ctx.get().getSender();
 
-             if (serverPlayer != null) {
 
-                 serverPlayer.getCapability(LibCapabilities.MIND_CAPABILITY).ifPresent((capability -> {
 
-                     capability.setMindStrength(msg.mindStrength);
 
-                 }));
 
-                 SaintChapter.LOGGER.info("客户端的内容已同步到服务端");
 
-             }
 
-             // 从服务端发送到客户端
 
-             DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
 
-                 if (Minecraft.getInstance().player == null) return;
 
-                 Minecraft.getInstance().player.getCapability(LibCapabilities.MIND_CAPABILITY).ifPresent((capability -> {
 
-                     capability.setMindStrength(msg.mindStrength);
 
-                 }));
 
-                 SaintChapter.LOGGER.info("服务端的内容已同步到客户端");
 
-             });
 
-         });
 
-         ctx.get().setPacketHandled(true);
 
-     }
 
- }
- 玩家死亡后,服务端的数据被同步,客户端的数据没有同步,虽然已经发包了。
- 使用上述被注释掉的代码,可以实现同步,但我不理解原理,因为测试的条件为单人模式,发包为逻辑服务端到物理客户端,实际上是物理客户端执行了MSGMindCapabilitySync#handle的所有代码,包括DistExecutor的代码。所以虽然这种方式可以解决单人游戏下的问题,也解决不了多人游戏下的同步。
 
我想知道:
- 为什么会出现上述现象,为什么我发包却不能同步。
- 为什么使用注释的代码就可以同步(虽然明显是bug,碰巧能运行而已)
- 我该如何解决??
 
github:https://github.com/LiYuxuanhaha/SaintChapter
因为客户端也有处理部分服务端的内容
o2072108706 发表于 2021-10-19 10:30
因为客户端也有处理部分服务端的内容
或许我不太明白你想表达的意思?
 本帖最后由 youyihj 于 2021-10-19 18:41 编辑 
DistExecutor 不是这么用的,它的参数不能是 () -> () -> ...,应该是 () -> Class::method,
所以你的服务端发过去的包在客户端未被处理。
emmm,unsafe 啥的貌似不需要,一直我用的是 safe 的那种,但是网络包也用不着 DistExecutor 吧。
我们只需要服务端向客户端发包,所以 message handler 也只在客户端处理。
emmm,unsafe 啥的貌似不需要,一直我用的是 safe 的那种,但是网络包也用不着 DistExecutor 吧。
我们只需要服务端向客户端发包,所以 message handler 也只在客户端处理。
 本帖最后由 黎雨轩 于 2021-10-19 18:40 编辑 
。。。。。
。。。。。
 本帖最后由 黎雨轩 于 2021-10-19 18:52 编辑 
网络包的用法没问题,我参考Forge文档做的,而且做出来之后已经使用物品和方块充分测试,没有问题。DistExecuter的用法。。传入静态方法和直接传入匿名函数应该是一样的叭
youyihj 发表于 2021-10-19 16:13
DistExecutor 不是这么用的,它的参数不能是 () -> () -> ...,应该是 () -> Class::method,
...
网络包的用法没问题,我参考Forge文档做的,而且做出来之后已经使用物品和方块充分测试,没有问题。DistExecuter的用法。。传入静态方法和直接传入匿名函数应该是一样的叭
 本帖最后由 黎雨轩 于 2021-10-19 18:52 编辑 
额,Forge论坛的版主回答了这个问题:https://forums.minecraftforge.ne ... n-playereventclone/
这是他的原话:PlayerEvent.Clone is only for copying data from the old player to the new player. It is not the place to send packets or do anything else.
To sync your capability to the client reliably, you need to send the data in PlayerLoggedInEvent, PlayerChangedDimensionEvent and PlayerRespawnEvent. As well as whenever the data changes.
问题已经解决啦,感谢回答
youyihj 发表于 2021-10-19 16:13
DistExecutor 不是这么用的,它的参数不能是 () -> () -> ...,应该是 () -> Class::method,
...
额,Forge论坛的版主回答了这个问题:https://forums.minecraftforge.ne ... n-playereventclone/
这是他的原话:PlayerEvent.Clone is only for copying data from the old player to the new player. It is not the place to send packets or do anything else.
To sync your capability to the client reliably, you need to send the data in PlayerLoggedInEvent, PlayerChangedDimensionEvent and PlayerRespawnEvent. As well as whenever the data changes.
问题已经解决啦,感谢回答