黎雨轩
本帖最后由 黎雨轩 于 2021-10-19 09:35 编辑

PlayerEvent.Clone的代码如下:
  1. public static void onPlayerCloned(PlayerEvent.Clone event) {
  2.         // 死亡或者转换维度时的能力处理
  3.         if (!event.getOriginal().world.isRemote() && !event.getPlayer().world.isRemote() && event.getOriginal() != null && event.getPlayer() != null) {
  4.             LazyOptional<IMindCapability> oldMindCap = event.getOriginal().getCapability(LibCapabilities.MIND_CAPABILITY);
  5.             LazyOptional<IMindCapability> newMindCap = event.getPlayer().getCapability(LibCapabilities.MIND_CAPABILITY);
  6.             if (oldMindCap.isPresent() && newMindCap.isPresent()) {
  7.                 newMindCap.ifPresent(capability -> {
  8.                     oldMindCap.ifPresent(capabilityOld -> {
  9.                         event.getPlayer().sendMessage(new StringTextComponent("Before: " + capability.getMindStrength()), CommonProxy.IN_GAME_UUID);
  10.                         capability.deserializeNBT(capabilityOld.serializeNBT());
  11.                         event.getPlayer().sendMessage(new StringTextComponent("After: " + capability.getMindStrength()), CommonProxy.IN_GAME_UUID);
  12.                     });
  13.                     SCPacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) event.getPlayer()), new MSGMindCapabilitySync(capability.getMindStrength()));
  14.                     // 这条代码可以解决问题,为什么要从客户端发送到服务端?
  15.                     // SCPacketHandler.INSTANCE.sendToServer(new MSGMindCapabilitySync(capability.getMindStrength()));
  16.                 });
  17.             }
  18.         }
  19.     }
复制代码
网络包的代码如下:
  1. public class MSGMindCapabilitySync {
  2.     private final int mindStrength;

  3.     public MSGMindCapabilitySync(int mindStrength) {
  4.         this.mindStrength = mindStrength;

  5.     }

  6.     public static void encodingMSG(MSGMindCapabilitySync msg, PacketBuffer buffer) {
  7.         buffer.writeInt(msg.mindStrength);
  8.     }

  9.     public static MSGMindCapabilitySync decodingMSG(PacketBuffer buffer) {
  10.         return new MSGMindCapabilitySync(buffer.readInt());
  11.     }

  12.     public static void handle(MSGMindCapabilitySync msg, Supplier<NetworkEvent.Context> ctx) {
  13.         ctx.get().enqueueWork(() -> {
  14.             // 从客户端发送到服务端
  15.             ServerPlayerEntity serverPlayer = ctx.get().getSender();
  16.             if (serverPlayer != null) {
  17.                 serverPlayer.getCapability(LibCapabilities.MIND_CAPABILITY).ifPresent((capability -> {
  18.                     capability.setMindStrength(msg.mindStrength);
  19.                 }));
  20.                 SaintChapter.LOGGER.info("客户端的内容已同步到服务端");
  21.             }
  22.             // 从服务端发送到客户端
  23.             DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
  24.                 if (Minecraft.getInstance().player == null) return;
  25.                 Minecraft.getInstance().player.getCapability(LibCapabilities.MIND_CAPABILITY).ifPresent((capability -> {
  26.                     capability.setMindStrength(msg.mindStrength);
  27.                 }));
  28.                 SaintChapter.LOGGER.info("服务端的内容已同步到客户端");
  29.             });
  30.         });
  31.         ctx.get().setPacketHandled(true);
  32.     }
  33. }
复制代码
然后描述一下我发现的问题:

我想知道:


github:https://github.com/LiYuxuanhaha/SaintChapter

o2072108706
因为客户端也有处理部分服务端的内容

黎雨轩
o2072108706 发表于 2021-10-19 10:30
因为客户端也有处理部分服务端的内容

或许我不太明白你想表达的意思?

youyihj
本帖最后由 youyihj 于 2021-10-19 18:41 编辑

DistExecutor 不是这么用的,它的参数不能是 () -> () -> ...,应该是 () -> Class::method,

所以你的服务端发过去的包在客户端未被处理。

emmm,unsafe 啥的貌似不需要,一直我用的是 safe 的那种,但是网络包也用不着 DistExecutor 吧。

我们只需要服务端向客户端发包,所以 message handler 也只在客户端处理。

黎雨轩
本帖最后由 黎雨轩 于 2021-10-19 18:40 编辑

。。。。。



黎雨轩
本帖最后由 黎雨轩 于 2021-10-19 18:52 编辑
youyihj 发表于 2021-10-19 16:13
DistExecutor 不是这么用的,它的参数不能是 () -> () -> ...,应该是 () -> Class::method,

  ...

网络包的用法没问题,我参考Forge文档做的,而且做出来之后已经使用物品和方块充分测试,没有问题。DistExecuter的用法。。传入静态方法和直接传入匿名函数应该是一样的叭

黎雨轩
本帖最后由 黎雨轩 于 2021-10-19 18:52 编辑
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.



问题已经解决啦,感谢回答