我使用Forge的Capablity自定义了一个Capabiltity和一个CapabilityProvider并进行了注册,将其附加到玩家身上,然后在玩家死亡重生后将重生前的Capability同步到重生后的玩家实体上,但是这个同步操作无法成功,各部分代码如下:
PlayerThrist.java(自己构造的Capability)
public class PlayerThirst {
private int thirst;
private final int MIN_THIRST = 0;
private final int MAX_THIRST = 10;
public int getThirst() {
return thirst;
}
public void addThirst(int add) {
this.thirst = Math.min(this.thirst + add, this.MAX_THIRST);
}
public void subThirst(int sub) {
this.thirst = Math.max(this.thirst - sub, this.MIN_THIRST);
}
public void copyFrom(PlayerThirst source) {
this.thirst = source.thirst;
}
public void saveData(CompoundTag nbt) {
nbt.putInt("thirst", this.thirst);
}
public void loadData(CompoundTag nbt) {
this.thirst = nbt.getInt("thirst");
}
}复制代码
PlayerThirstyProvider.java(自己构造的CapabilityProvider)
public class PlayerThirstProvider implements ICapabilityProvider, INBTSerializable {
public static Capability PLAYER_THIRST = CapabilityManager.get(new CapabilityToken
});
private PlayerThirst thirst = null;
private final LazyOptional thirstHandler = LazyOptional.of(this::createPlayerThirst);
private PlayerThirst createPlayerThirst() {
if (this.thirst == null) {
this.thirst = new PlayerThirst();
}
return this.thirst;
}
@Override
public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) {
if (cap == PLAYER_THIRST) {
return thirstHandler.cast();
}
return LazyOptional.empty();
}
@Override
public CompoundTag serializeNBT() {
CompoundTag nbt = new CompoundTag();
createPlayerThirst().saveData(nbt);
return nbt;
}复制代码
ThirstyEvent.java(用于将PlayerThirsty添加到玩家上、同步死亡前的PlayerThirsty到重生后的玩家实体和注册能力)
@Mod.EventBusSubscriber
public class ThirstEvent {
@SubscribeEvent
public static void onAttachPlayer(AttachCapabilitiesEvent event) {
if (event.getObject() instanceof Player player) {
if (!event.getObject().getCapability(PlayerThirstProvider.PLAYER_THIRST).isPresent()) {
event.addCapability(new ResourceLocation(Utils.MODID, "properties"), new PlayerThirstProvider());
}
}
}
@SubscribeEvent
public static void onPlayerClone(PlayerEvent.Clone event) {
if (event.isWasDeath()) {
event.getEntity().sendSystemMessage(Component.literal("You dead!!"));
event.getEntity().getCapability(PlayerThirstProvider.PLAYER_THIRST).ifPresent(newState -> {
event.getEntity().sendSystemMessage(Component.literal("You dead!!2"));
event.getOriginal().getCapability(PlayerThirstProvider.PLAYER_THIRST).ifPresent(oldState -> {
event.getEntity().sendSystemMessage(Component.literal("Data copy!"));
newState.copyFrom(oldState);
// event.getEntity().sendSystemMessage(Component.literal("You dead, but you are cloned!"));
});
});
}复制代码
如果玩家死亡并且同步成功,玩家会在聊天框中收到"You dead!!" 、"You dead!!2" 和 "Data copy!" 三条信息,然而实际上玩家死亡重生后(使用/kill和从高空掉落摔死)只收到了前两条信息,这意味着event.getOriginal().getCapability(PlayerThirstProvider.PLAYER_THIRST).ifPresent(Lambda表达式) 没有执行其中的Lambda表达式,通过阅读源代码我发现如果event.getOriginal().getCapability(PlayerThirstProvider.PLAYER_THIRST).isPresent() 为false就会出现这种情况,我输出了后者发现确实是false,为什么我的代码会导致这种情况?
PlayerThrist.java(自己构造的Capability)
public class PlayerThirst {
private int thirst;
private final int MIN_THIRST = 0;
private final int MAX_THIRST = 10;
public int getThirst() {
return thirst;
}
public void addThirst(int add) {
this.thirst = Math.min(this.thirst + add, this.MAX_THIRST);
}
public void subThirst(int sub) {
this.thirst = Math.max(this.thirst - sub, this.MIN_THIRST);
}
public void copyFrom(PlayerThirst source) {
this.thirst = source.thirst;
}
public void saveData(CompoundTag nbt) {
nbt.putInt("thirst", this.thirst);
}
public void loadData(CompoundTag nbt) {
this.thirst = nbt.getInt("thirst");
}
}复制代码
PlayerThirstyProvider.java(自己构造的CapabilityProvider)
public class PlayerThirstProvider implements ICapabilityProvider, INBTSerializable {
public static Capability PLAYER_THIRST = CapabilityManager.get(new CapabilityToken
});
private PlayerThirst thirst = null;
private final LazyOptional thirstHandler = LazyOptional.of(this::createPlayerThirst);
private PlayerThirst createPlayerThirst() {
if (this.thirst == null) {
this.thirst = new PlayerThirst();
}
return this.thirst;
}
@Override
public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) {
if (cap == PLAYER_THIRST) {
return thirstHandler.cast();
}
return LazyOptional.empty();
}
@Override
public CompoundTag serializeNBT() {
CompoundTag nbt = new CompoundTag();
createPlayerThirst().saveData(nbt);
return nbt;
}复制代码
ThirstyEvent.java(用于将PlayerThirsty添加到玩家上、同步死亡前的PlayerThirsty到重生后的玩家实体和注册能力)
@Mod.EventBusSubscriber
public class ThirstEvent {
@SubscribeEvent
public static void onAttachPlayer(AttachCapabilitiesEvent event) {
if (event.getObject() instanceof Player player) {
if (!event.getObject().getCapability(PlayerThirstProvider.PLAYER_THIRST).isPresent()) {
event.addCapability(new ResourceLocation(Utils.MODID, "properties"), new PlayerThirstProvider());
}
}
}
@SubscribeEvent
public static void onPlayerClone(PlayerEvent.Clone event) {
if (event.isWasDeath()) {
event.getEntity().sendSystemMessage(Component.literal("You dead!!"));
event.getEntity().getCapability(PlayerThirstProvider.PLAYER_THIRST).ifPresent(newState -> {
event.getEntity().sendSystemMessage(Component.literal("You dead!!2"));
event.getOriginal().getCapability(PlayerThirstProvider.PLAYER_THIRST).ifPresent(oldState -> {
event.getEntity().sendSystemMessage(Component.literal("Data copy!"));
newState.copyFrom(oldState);
// event.getEntity().sendSystemMessage(Component.literal("You dead, but you are cloned!"));
});
});
}复制代码
如果玩家死亡并且同步成功,玩家会在聊天框中收到"You dead!!" 、"You dead!!2" 和 "Data copy!" 三条信息,然而实际上玩家死亡重生后(使用/kill和从高空掉落摔死)只收到了前两条信息,这意味着event.getOriginal().getCapability(PlayerThirstProvider.PLAYER_THIRST).ifPresent(Lambda表达式) 没有执行其中的Lambda表达式,通过阅读源代码我发现如果event.getOriginal().getCapability(PlayerThirstProvider.PLAYER_THIRST).isPresent() 为false就会出现这种情况,我输出了后者发现确实是false,为什么我的代码会导致这种情况?