QingyuOvO
本帖最后由 QingyuOvO 于 2022-1-7 00:31 编辑

在1.12.2中我们是这么做的:
  1. @SubscribeEvent
  2.     public void onPlayerClone(PlayerEvent.Clone event) {
  3.         Capability<SkillData> capability = SkillData.CAPABILITY_TYPE;
  4.         Capability.IStorage<SkillData> storage = capability.getStorage();

  5.         if (event.getOriginal().hasCapability(capability, null) && event.getEntityPlayer().hasCapability(capability, null)) {
  6.             NBTBase nbt = storage.writeNBT(capability, event.getOriginal().getCapability(capability, null), null);
  7.             storage.readNBT(capability, event.getEntityPlayer().getCapability(capability, null), null, nbt);
  8.         }
  9.     }
复制代码

原理大概就是把死前玩家的数据赋值给新的玩家,但是在1.14.3中使用类似的代码:

  1. @SubscribeEvent
  2.     public void cloneEvent(PlayerEvent.Clone event) {
  3.         Capability<ShikongData> capability = CapabilityProvider.CAPABILITY_TYPE;
  4.         Capability.IStorage<ShikongData> storage = capability.getStorage();

  5.         ShikongData stale = ShiKongInfoUtil.getPlayerShikongData(event.getOriginal());
  6.         ShikongData fresh = ShiKongInfoUtil.getPlayerShikongData(event.getEntityPlayer());

  7.         INBT nbt = storage.writeNBT(capability, stale, null);
  8.         storage.readNBT(capability, fresh, null, nbt);
  9.     }
复制代码

却失效了。经过查看源代码发现forge的net.minecraftforge.common.capabilities.CapabilityProvider类的获取cap信息的方法是这样的:
  1. @Override
  2.     @Nonnull
  3.     public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side)
  4.     {
  5.         final CapabilityDispatcher disp = getCapabilities();
  6.         return !valid || disp == null ? LazyOptional.empty() : disp.getCapability(cap, side);
  7.     }
复制代码
而valid字段在这个Clone方法被调用很久之前就已经标记了false(在玩家死的时候就调用了,但是Clone是要点击“重生”按钮才会触发),这样我们似乎永远都不可能获取到玩家以前的Capability信息了。下面贴出这个类的全部代码,valid和getCapabilities()全都是protected,没法访问,而且由于这是forge的代码,at也没法用(看来就只能反射了?)


如果各位大佬以前也遇到过这个问题麻烦解惑一下,没遇到的也欢迎讨论。我将继续寻找解决方式,直至问题解决,其间过程都直接更新在帖子里。


问题解决了,最好用1.14.4,如果非要用1.14.3,那就反射。


——————————————————————————————————————————————————————————
刚才看了一下1.14.4的代码,果然,1.14.4他们认识到了这问题,把valid删除了。毁灭吧,赶紧的,累了。
感觉就好像是1.14forge换人开发了,新来的人对原来的逻辑不了解,结果把数据控制流程写坏了似的

——————————————————————————————————————————————————————————
用了一下反射,结果:

——————————————————————————————————————————————————————————
奇怪了,我什么都没做,但是bug消失了,不管怎么调试都不会出现被踢出游戏的问题了.....= =蒙了,这种隐患太难受了

——————————————————————————————————————————————————————————

问题解决了,看了日志,被踢出游戏的原因是我用的是kill指令,但是手按tab按得有点快,自动补全出来的是 kick,我真是佛了,真想抽死自己