From d5756d6e09bc4216720eae4ba0297ef0663285de Mon Sep 17 00:00:00 2001 From: LostInLinearPast <1283411677@qq.com> Date: Sat, 18 Oct 2025 17:43:22 +0800 Subject: [PATCH] fix something bug and add "void attachInit(T entity)" in ICapabilitySync version 0.0.2 --- gradle.properties | 2 +- .../sccore/capability/CapabilityUtils.java | 76 ++++++++++++------- .../capability/data/ICapabilitySync.java | 12 ++- .../data/entity/EntityCapabilityHandler.java | 2 +- .../data/entity/EntityCapabilityProvider.java | 3 +- .../data/entity/EntityCapabilityRegistry.java | 2 +- .../entity/EntityCapabilityRemainder.java | 9 ++- .../entity/SimpleEntityCapabilitySync.java | 9 ++- .../data/player/PlayerCapabilityHandler.java | 2 +- .../data/player/PlayerCapabilityProvider.java | 2 +- .../data/player/PlayerCapabilityRegistry.java | 3 +- .../player/PlayerCapabilityRemainder.java | 15 ++-- .../player/SimplePlayerCapabilitySync.java | 8 +- .../network/SimpleCapabilityPacket.java | 10 ++- .../linearpast/sccore/example/ModCaps.java | 4 +- .../sccore/example/cap/ISheepData.java | 3 +- .../example/cap/SheepDataCapability.java | 13 +++- 17 files changed, 115 insertions(+), 60 deletions(-) diff --git a/gradle.properties b/gradle.properties index c7a96b7..2d6005c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ mapping_version=2023.09.03-1.20.1 mod_id=sccore mod_name=SnowyCrescentCore mod_license=GNU AGPL 3.0 -mod_version=1.20.1-0.0.1 +mod_version=1.20.1-0.0.2 mod_group_id=com.linearpast mod_authors=LostInLinearPast mod_description=A lib. diff --git a/src/main/java/com/linearpast/sccore/capability/CapabilityUtils.java b/src/main/java/com/linearpast/sccore/capability/CapabilityUtils.java index 73aef12..d5251e7 100644 --- a/src/main/java/com/linearpast/sccore/capability/CapabilityUtils.java +++ b/src/main/java/com/linearpast/sccore/capability/CapabilityUtils.java @@ -35,7 +35,7 @@ public class CapabilityUtils { * @param handler 网络包的handle */ public static > void registerPlayerCapabilityWithNetwork( - ResourceLocation key, PlayerCapabilityRegistry.CapabilityRecord capabilityRecord, + ResourceLocation key, PlayerCapabilityRegistry.CapabilityRecord> capabilityRecord, CapabilityChannel channelRegister, int cid, Class clazz, @@ -59,7 +59,7 @@ public class CapabilityUtils { * @param handler 网络包的handle */ public static > void registerEntityCapabilityWithNetwork( - ResourceLocation key, EntityCapabilityRegistry.CapabilityRecord capabilityRecord, + ResourceLocation key, EntityCapabilityRegistry.CapabilityRecord> capabilityRecord, CapabilityChannel channelRegister, int cid, Class clazz, @@ -77,7 +77,7 @@ public class CapabilityUtils { * @param key capability的唯一name * @param capabilityRecord 使用record存储了应该注册的capability的各项数据,参阅:{@link PlayerCapabilityRegistry.CapabilityRecord} */ - public static void registerPlayerCapability(ResourceLocation key, PlayerCapabilityRegistry.CapabilityRecord capabilityRecord){ + public static > void registerPlayerCapability(ResourceLocation key, PlayerCapabilityRegistry.CapabilityRecord capabilityRecord){ PlayerCapabilityRegistry.registerCapability(key, capabilityRecord); } @@ -87,7 +87,7 @@ public class CapabilityUtils { * @param key capability的唯一name * @param capabilityRecord 使用record存储了应该注册的capability的各项数据,参阅:{@link PlayerCapabilityRegistry.CapabilityRecord} */ - public static void registerEntityCapability(ResourceLocation key, EntityCapabilityRegistry.CapabilityRecord capabilityRecord){ + public static > void registerEntityCapability(ResourceLocation key, EntityCapabilityRegistry.CapabilityRecord capabilityRecord){ EntityCapabilityRegistry.registerCapability(key, capabilityRecord); } @@ -119,48 +119,72 @@ public class CapabilityUtils { } /** - * 请通过该方法获取玩家的capability - * @param player 目标玩家 - * @param key capability key - * @param clazz 应返回的capability类型 + * 请通过该方法获取capability + * @param entity 目标实体,类型 {@code } + * @param key capability的唯一名 + * @param clazz 应返回的capability类型,若为null则会返回 {@code ICapabilitySync} * @return 返回对应的capability */ + @SuppressWarnings("unchecked") @Nullable - public static T getPlayerCapability(Player player, ResourceLocation key, Class clazz) { - if(player == null) return null; - ICapabilitySync capabilitySync = player.getCapability( - PlayerCapabilityRegistry.getCapabilityMap().get(key).capability() - ).resolve().orElse(null); - if(capabilitySync == null) return null; + public static > T getEntityCapability(E entity, ResourceLocation key, @Nullable Class clazz) { try { + ICapabilitySync capabilitySync = entity.getCapability( + EntityCapabilityRegistry.getCapabilityMap().get(key).capability() + ).resolve().orElse(null); + if(clazz == null) return (T) capabilitySync; if(clazz.isInstance(capabilitySync)) return clazz.cast(capabilitySync); else return null; - }catch(ClassCastException e){ + }catch(Exception e){ return null; } } /** - * 请通过该方法获取实体的capability - * @param entity 目标实体 - * @param key capability key - * @param clazz 应返回的capability类型 + * 请通过该方法获取capability + * @param entity 目标实体,类型 {@code } + * @param key capability的唯一名 + * @param clazz 应返回的capability类型,若为null则会返回 {@code ICapabilitySync} * @return 返回对应的capability */ + @SuppressWarnings("unchecked") @Nullable - public static T getEntityCapability(Entity entity, ResourceLocation key, Class clazz) { - if(entity == null) return null; - ICapabilitySync capabilitySync = entity.getCapability( - EntityCapabilityRegistry.getCapabilityMap().get(key).capability() - ).resolve().orElse(null); - if(capabilitySync == null) return null; + public static > T getPlayerCapability(E entity, ResourceLocation key, @Nullable Class clazz) { try { + ICapabilitySync capabilitySync = entity.getCapability( + PlayerCapabilityRegistry.getCapabilityMap().get(key).capability() + ).resolve().orElse(null); + if(clazz == null) return (T) capabilitySync; if(clazz.isInstance(capabilitySync)) return clazz.cast(capabilitySync); else return null; - }catch(ClassCastException e){ + }catch(Exception e){ return null; } } + + /** + * 获取一个未转换类型的Cap + * @param entity 目标 + * @param key cap的唯一名 + * @return 未转换类型的cap + */ + @Nullable + public static ICapabilitySync getCapability(Entity entity, ResourceLocation key) { + if(entity == null) return null; + try { + if(entity instanceof Player) { + return entity.getCapability( + PlayerCapabilityRegistry.getCapabilityMap().get(key).capability() + ).resolve().orElse(null); + } + return entity.getCapability( + EntityCapabilityRegistry.getCapabilityMap().get(key).capability() + ).resolve().orElse(null); + }catch(Exception e){ + return null; + } + + } } diff --git a/src/main/java/com/linearpast/sccore/capability/data/ICapabilitySync.java b/src/main/java/com/linearpast/sccore/capability/data/ICapabilitySync.java index d791962..7c03d9c 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/ICapabilitySync.java +++ b/src/main/java/com/linearpast/sccore/capability/data/ICapabilitySync.java @@ -7,7 +7,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraftforge.common.util.INBTSerializable; -public interface ICapabilitySync extends INBTSerializable { +public interface ICapabilitySync extends INBTSerializable { void setDirty(boolean dirty); boolean isDirty(); @@ -19,7 +19,7 @@ public interface ICapabilitySync extends INBTSerializable { * @param oldData 旧数据 * @param listenDone 最后是否执行完成方法 {@link ICapabilitySync#onCopyDone()} */ - default void copyFrom(ICapabilitySync oldData, boolean listenDone) { + default void copyFrom(ICapabilitySync oldData, boolean listenDone) { this.setDirty(oldData.isDirty()); if(listenDone) onCopyDone(); } @@ -53,6 +53,12 @@ public interface ICapabilitySync extends INBTSerializable { * 一般情况下,你应该extends SimpleCapabilityPacket然后重写该方法返回你的子类 * @return 网络包类SimpleCapabilityPacket */ - SimpleCapabilityPacket getDefaultPacket(); + SimpleCapabilityPacket getDefaultPacket(); + /** + * 当玩家登录 / 实体加入世界时的cao初始化时会调用
+ * 必须实现,但可为空方法 + * @param entity 目标 + */ + void attachInit(T entity); } diff --git a/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityHandler.java b/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityHandler.java index 3f1cba9..f45ca5f 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityHandler.java +++ b/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityHandler.java @@ -45,7 +45,7 @@ public class EntityCapabilityHandler { EntityCapabilityRegistry.getCapabilityMap().forEach((key, record) -> { if(record.target().isInstance(entity)) { try { - ICapabilitySync capabilitySync = (ICapabilitySync) record.aClass().getDeclaredConstructor().newInstance(); + ICapabilitySync capabilitySync = (ICapabilitySync) record.aClass().getDeclaredConstructor().newInstance(); event.addCapability(key, new EntityCapabilityProvider<>(key, capabilitySync)); } catch (Exception e) { log.error("Failed to instantiate capability sync class {}. Your capability register is wrong.", record.aClass(), e); diff --git a/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityProvider.java b/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityProvider.java index 3066ff0..c1c69e3 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityProvider.java +++ b/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityProvider.java @@ -4,6 +4,7 @@ import com.linearpast.sccore.capability.data.ICapabilitySync; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; import net.minecraftforge.common.capabilities.AutoRegisterCapability; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilitySerializable; @@ -16,7 +17,7 @@ import org.jetbrains.annotations.Nullable; * @param 继承 {@link ICapabilitySync} */ @AutoRegisterCapability -public class EntityCapabilityProvider implements ICapabilitySerializable { +public class EntityCapabilityProvider> implements ICapabilitySerializable { private final C instance; private final ResourceLocation resourceLocation; public EntityCapabilityProvider(ResourceLocation resourceLocation, C instance) { diff --git a/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityRegistry.java b/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityRegistry.java index 316c522..547a6ec 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityRegistry.java +++ b/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityRegistry.java @@ -46,7 +46,7 @@ public class EntityCapabilityRegistry { * @param interfaceClass instance类对应的实例对应的接口类,比如ICapabilitySync.class * @param target capability附加的目标类型 */ - public record CapabilityRecord(Class aClass, Capability capability, Class interfaceClass, Class target) { + public record CapabilityRecord>(Class aClass, Capability capability, Class interfaceClass, Class target) { } } diff --git a/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityRemainder.java b/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityRemainder.java index 5667495..9936631 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityRemainder.java +++ b/src/main/java/com/linearpast/sccore/capability/data/entity/EntityCapabilityRemainder.java @@ -20,7 +20,7 @@ public class EntityCapabilityRemainder { public static void onEntityBeTracked(PlayerEvent.StartTracking event) { if (event.getEntity() instanceof ServerPlayer attacker) { PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getEntityCapability(event.getTarget(), key, ICapabilitySync.class); + ICapabilitySync data = CapabilityUtils.getCapability(event.getTarget(), key); if(data == null) return; data.sendToClient(attacker); }); @@ -38,7 +38,7 @@ public class EntityCapabilityRemainder { if(!entity.level().isClientSide){ if (entity.tickCount % 20 == 0) { PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getEntityCapability(entity, key, ICapabilitySync.class); + ICapabilitySync data = CapabilityUtils.getCapability(entity, key); if(data == null) return; if(data.isDirty()) { data.setDirty(false); @@ -57,11 +57,12 @@ public class EntityCapabilityRemainder { Entity entity = event.getEntity(); if(entity.level().isClientSide) return; EntityCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getEntityCapability(entity, key, ICapabilitySync.class); + ICapabilitySync data = CapabilityUtils.getEntityCapability(entity, key, null); if(data == null) return; - if(data instanceof SimpleEntityCapabilitySync capabilitySync){ + if(data instanceof SimpleEntityCapabilitySync capabilitySync){ capabilitySync.setId(entity.getId()); } + data.attachInit(entity); data.setDirty(false); data.sendToClient(); }); diff --git a/src/main/java/com/linearpast/sccore/capability/data/entity/SimpleEntityCapabilitySync.java b/src/main/java/com/linearpast/sccore/capability/data/entity/SimpleEntityCapabilitySync.java index 5f2de1b..1eb0dd5 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/entity/SimpleEntityCapabilitySync.java +++ b/src/main/java/com/linearpast/sccore/capability/data/entity/SimpleEntityCapabilitySync.java @@ -2,6 +2,7 @@ package com.linearpast.sccore.capability.data.entity; import com.linearpast.sccore.capability.data.ICapabilitySync; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; /** * 实现时建议手动添加:
@@ -21,7 +22,7 @@ import net.minecraft.nbt.CompoundTag; * * */ -public abstract class SimpleEntityCapabilitySync implements ICapabilitySync { +public abstract class SimpleEntityCapabilitySync implements ICapabilitySync { public static final String Id = "Id"; private boolean dirty; @@ -57,8 +58,8 @@ public abstract class SimpleEntityCapabilitySync implements ICapabilitySync { * @param listenDone 最后是否执行完成方法 {@link ICapabilitySync#onCopyDone()} */ @Override - public void copyFrom(ICapabilitySync oldData, boolean listenDone) { - SimpleEntityCapabilitySync data = (SimpleEntityCapabilitySync) oldData; + public void copyFrom(ICapabilitySync oldData, boolean listenDone) { + SimpleEntityCapabilitySync data = (SimpleEntityCapabilitySync) oldData; this.setId(data.getId()); copyFrom(data); ICapabilitySync.super.copyFrom(oldData, listenDone); @@ -68,7 +69,7 @@ public abstract class SimpleEntityCapabilitySync implements ICapabilitySync { * 触发数据复制时会执行的方法 * @param oldData 从这个数据中复制到当前实例 */ - public abstract void copyFrom(ICapabilitySync oldData); + public abstract void copyFrom(ICapabilitySync oldData); /** * 序列化为tag
diff --git a/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityHandler.java b/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityHandler.java index acaccb6..5f58d25 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityHandler.java +++ b/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityHandler.java @@ -46,7 +46,7 @@ public class PlayerCapabilityHandler { if(event.getObject() instanceof Player) { PlayerCapabilityRegistry.getCapabilityMap().forEach((key, record) -> { try { - ICapabilitySync capabilitySync = (ICapabilitySync) record.aClass().getDeclaredConstructor().newInstance(); + ICapabilitySync capabilitySync = (ICapabilitySync) record.aClass().getDeclaredConstructor().newInstance(); event.addCapability(key, new PlayerCapabilityProvider<>(key, capabilitySync)); } catch (Exception e) { log.error("Failed to instantiate capability sync class {}. Your capability register is wrong.", record.aClass(), e); diff --git a/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityProvider.java b/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityProvider.java index 8f14265..607f40d 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityProvider.java +++ b/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityProvider.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @AutoRegisterCapability -public class PlayerCapabilityProvider implements ICapabilitySerializable { +public class PlayerCapabilityProvider> implements ICapabilitySerializable { private final C instance; private final ResourceLocation resourceLocation; public PlayerCapabilityProvider(ResourceLocation resourceLocation, C instance) { diff --git a/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityRegistry.java b/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityRegistry.java index 9be5f71..8a5c85a 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityRegistry.java +++ b/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityRegistry.java @@ -2,6 +2,7 @@ package com.linearpast.sccore.capability.data.player; import com.linearpast.sccore.capability.data.ICapabilitySync; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; import net.minecraftforge.common.capabilities.Capability; import java.util.HashMap; @@ -40,5 +41,5 @@ public class PlayerCapabilityRegistry { * @param capability 一般情况下不需要初始化它,默认:CapabilityManager.get(new CapabilityToken<>(){}) * @param interfaceClass instance实例对应的接口类,比如ICapabilitySync.class */ - public record CapabilityRecord(Class aClass, Capability capability, Class interfaceClass) { } + public record CapabilityRecord>(Class aClass, Capability capability, Class interfaceClass) { } } diff --git a/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityRemainder.java b/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityRemainder.java index e1353c7..d1dad4a 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityRemainder.java +++ b/src/main/java/com/linearpast/sccore/capability/data/player/PlayerCapabilityRemainder.java @@ -25,8 +25,8 @@ public class PlayerCapabilityRemainder { Player original = event.getOriginal(); original.reviveCaps(); PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync originData = CapabilityUtils.getPlayerCapability(original, key, ICapabilitySync.class); - ICapabilitySync newData = CapabilityUtils.getPlayerCapability(newPlayer, key, ICapabilitySync.class); + ICapabilitySync originData = CapabilityUtils.getCapability(original, key); + ICapabilitySync newData = CapabilityUtils.getCapability(newPlayer, key); if(originData != null && newData != null) { newData.copyFrom(originData, true); newData.sendToClient(); @@ -43,7 +43,7 @@ public class PlayerCapabilityRemainder { public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) { if(event.getEntity() instanceof ServerPlayer newPlayer){ PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getPlayerCapability(newPlayer, key, ICapabilitySync.class); + ICapabilitySync data = CapabilityUtils.getCapability(newPlayer, key); if(data == null) return; data.sendToClient(newPlayer); }); @@ -59,7 +59,7 @@ public class PlayerCapabilityRemainder { public static void onEntityBeTracked(PlayerEvent.StartTracking event) { if (event.getTarget() instanceof Player target && event.getEntity() instanceof ServerPlayer attacker) { PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getPlayerCapability(target, key, ICapabilitySync.class); + ICapabilitySync data = CapabilityUtils.getCapability(target, key); if(data == null) return; data.sendToClient(attacker); }); @@ -74,7 +74,7 @@ public class PlayerCapabilityRemainder { public static void capabilitySync(TickEvent.PlayerTickEvent event) { if(!event.player.level().isClientSide){ PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getPlayerCapability(event.player, key, ICapabilitySync.class); + ICapabilitySync data = CapabilityUtils.getCapability(event.player, key); if(data == null) return; if(data.isDirty()) { data.setDirty(false); @@ -94,11 +94,12 @@ public class PlayerCapabilityRemainder { Player player = event.getEntity(); if(!(player instanceof ServerPlayer serverPlayer)) return; PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getPlayerCapability(player, key, ICapabilitySync.class); + ICapabilitySync data = CapabilityUtils.getPlayerCapability(player, key, null); if(data == null) return; if(data instanceof SimplePlayerCapabilitySync capabilitySync) { capabilitySync.setOwnerUUID(serverPlayer.getUUID()); } + data.attachInit(serverPlayer); data.setDirty(false); data.sendToClient(); }); @@ -106,7 +107,7 @@ public class PlayerCapabilityRemainder { serverPlayers -> serverPlayers.forEach(p -> { if(!p.getUUID().equals(serverPlayer.getUUID())) { PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getPlayerCapability(player, key, ICapabilitySync.class); + ICapabilitySync data = CapabilityUtils.getCapability(player, key); if(data == null) return; data.sendToClient(serverPlayer); }); diff --git a/src/main/java/com/linearpast/sccore/capability/data/player/SimplePlayerCapabilitySync.java b/src/main/java/com/linearpast/sccore/capability/data/player/SimplePlayerCapabilitySync.java index a643aa1..f47e826 100644 --- a/src/main/java/com/linearpast/sccore/capability/data/player/SimplePlayerCapabilitySync.java +++ b/src/main/java/com/linearpast/sccore/capability/data/player/SimplePlayerCapabilitySync.java @@ -2,6 +2,7 @@ package com.linearpast.sccore.capability.data.player; import com.linearpast.sccore.capability.data.ICapabilitySync; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.player.Player; import java.util.UUID; @@ -23,7 +24,7 @@ import java.util.UUID; * * */ -public abstract class SimplePlayerCapabilitySync implements ICapabilitySync { +public abstract class SimplePlayerCapabilitySync implements ICapabilitySync { public static final String OwnerUUID = "OwnerUUID"; private boolean dirty; @@ -55,9 +56,10 @@ public abstract class SimplePlayerCapabilitySync implements ICapabilitySync { * @param listenDone 最后是否执行完成方法 {@link ICapabilitySync#onCopyDone()} */ @Override - public void copyFrom(ICapabilitySync oldData, boolean listenDone) { + public void copyFrom(ICapabilitySync oldData, boolean listenDone) { SimplePlayerCapabilitySync data = (SimplePlayerCapabilitySync) oldData; this.setOwnerUUID(data.getOwnerUUID()); + copyFrom(data); ICapabilitySync.super.copyFrom(oldData, listenDone); } @@ -65,7 +67,7 @@ public abstract class SimplePlayerCapabilitySync implements ICapabilitySync { * 触发数据复制时会执行的方法 * @param oldData 从这个数据中复制到当前实例 */ - public abstract void copyFrom(ICapabilitySync oldData); + public abstract void copyFrom(ICapabilitySync oldData); /** * 序列化为tag
diff --git a/src/main/java/com/linearpast/sccore/capability/network/SimpleCapabilityPacket.java b/src/main/java/com/linearpast/sccore/capability/network/SimpleCapabilityPacket.java index adc762d..67ab9d2 100644 --- a/src/main/java/com/linearpast/sccore/capability/network/SimpleCapabilityPacket.java +++ b/src/main/java/com/linearpast/sccore/capability/network/SimpleCapabilityPacket.java @@ -2,6 +2,7 @@ package com.linearpast.sccore.capability.network; import com.linearpast.sccore.capability.data.ICapabilitySync; import com.linearpast.sccore.capability.data.entity.SimpleEntityCapabilitySync; +import com.linearpast.sccore.capability.data.player.SimplePlayerCapabilitySync; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.nbt.CompoundTag; @@ -33,7 +34,14 @@ public abstract class SimpleCapabilityPacket implements ICapab ClientLevel level = instance.level; if (level == null) return; CompoundTag nbt = getData(); - Entity entity = level.getEntity(nbt.getInt(SimpleEntityCapabilitySync.Id)); + Entity entity = null; + if(nbt.contains(SimpleEntityCapabilitySync.Id)){ + entity = level.getEntity(nbt.getInt(SimpleEntityCapabilitySync.Id)); + } + if(nbt.contains(SimplePlayerCapabilitySync.OwnerUUID)){ + entity = level.getPlayerByUUID(nbt.getUUID(SimplePlayerCapabilitySync.OwnerUUID)); + } + if(entity == null) return; try { ICapabilitySync data = getCapability((T) entity); syncData(nbt, data); diff --git a/src/main/java/com/linearpast/sccore/example/ModCaps.java b/src/main/java/com/linearpast/sccore/example/ModCaps.java index 61a467d..174622e 100644 --- a/src/main/java/com/linearpast/sccore/example/ModCaps.java +++ b/src/main/java/com/linearpast/sccore/example/ModCaps.java @@ -14,7 +14,8 @@ import net.minecraftforge.eventbus.api.IEventBus; public class ModCaps { /** - * 注册capability的示例
+ * 注册实体capability的示例
+ * 请参阅 {@link CapabilityUtils} */ public static void register(){ //如果你想将网络包注册到你自己的mod中,createChannel(INSTANCE) @@ -23,6 +24,7 @@ public class ModCaps { //不可与其他网络包重复的任意整数 int cid = Channel.getCid(); //注册实体cap和它的网络包 + //若注册玩家的请用registerPlayerCapabilityWithNetwork CapabilityUtils.registerEntityCapabilityWithNetwork( //一个resourceLocation,任意命名,不重复即可 SheepDataCapability.key, diff --git a/src/main/java/com/linearpast/sccore/example/cap/ISheepData.java b/src/main/java/com/linearpast/sccore/example/cap/ISheepData.java index 0a641a1..b2e1846 100644 --- a/src/main/java/com/linearpast/sccore/example/cap/ISheepData.java +++ b/src/main/java/com/linearpast/sccore/example/cap/ISheepData.java @@ -1,12 +1,13 @@ package com.linearpast.sccore.example.cap; import com.linearpast.sccore.capability.data.ICapabilitySync; +import net.minecraft.world.entity.animal.Sheep; /** * 接口继承ICapabilitySync是必需的,但是接口是非必需的(你可以在注册时直接使用cap类本身)
* 用于共享一些可能会用到的cap的公共方法 */ -public interface ISheepData extends ICapabilitySync { +public interface ISheepData extends ICapabilitySync { Integer getValue(); void setValue(Integer value); } diff --git a/src/main/java/com/linearpast/sccore/example/cap/SheepDataCapability.java b/src/main/java/com/linearpast/sccore/example/cap/SheepDataCapability.java index e575fe5..d71f435 100644 --- a/src/main/java/com/linearpast/sccore/example/cap/SheepDataCapability.java +++ b/src/main/java/com/linearpast/sccore/example/cap/SheepDataCapability.java @@ -18,7 +18,7 @@ import java.util.Optional; * 继承SimpleEntityCapabilitySync意味着自动托管一个id的同步
* 实现的IsheepData仅含有属性value的getter和setter
*/ -public class SheepDataCapability extends SimpleEntityCapabilitySync implements ISheepData { +public class SheepDataCapability extends SimpleEntityCapabilitySync implements ISheepData { //代表cap的key,注册、获取时都需要它 public static final ResourceLocation key = new ResourceLocation(SnowyCrescentCore.MODID, "sheep_data"); @@ -59,7 +59,7 @@ public class SheepDataCapability extends SimpleEntityCapabilitySync implements I //从旧实例中复制数据到新实例的方法 @Override - public void copyFrom(ICapabilitySync oldData) { + public void copyFrom(ICapabilitySync oldData) { SheepDataCapability data = (SheepDataCapability) oldData; this.value = data.getValue(); } @@ -82,7 +82,7 @@ public class SheepDataCapability extends SimpleEntityCapabilitySync implements I //仅用在网络包内部的getCap @Override - public @Nullable ICapabilitySync getCapability(Sheep entity) { + public @Nullable SheepDataCapability getCapability(Sheep entity) { return SheepDataCapability.getCapability(entity).orElse(null); } } @@ -93,6 +93,13 @@ public class SheepDataCapability extends SimpleEntityCapabilitySync implements I return new SheepCapabilityPacket(serializeNBT()); } + //该方法会在cap初始化时调用,比如玩家登录 + //该例中,当羊加入level时会调用该方法以初始化cap + @Override + public void attachInit(Sheep entity) { + + } + //在其他地方需要用到cap的时候调用这个 //目的是为了简化cap utils的方法 public static Optional getCapability(Sheep sheep){