1919import com .mojang .serialization .Codec ;
2020import net .fabricmc .fabric .api .attachment .v1 .AttachmentRegistry ;
2121import net .fabricmc .fabric .api .attachment .v1 .AttachmentSyncPredicate ;
22+ import net .fabricmc .fabric .api .attachment .v1 .AttachmentTarget ;
2223import net .fabricmc .fabric .api .attachment .v1 .AttachmentType ;
23- import net .fabricmc .fabric .impl .attachment .sync .AttachmentSync ;
2424import net .fabricmc .fabric .mixin .attachment .BaseMappedRegistryAccessor ;
2525import net .minecraft .core .HolderLookup ;
2626import net .minecraft .core .Registry ;
3131import net .neoforged .neoforge .attachment .IAttachmentHolder ;
3232import net .neoforged .neoforge .attachment .IAttachmentSerializer ;
3333import net .neoforged .neoforge .registries .NeoForgeRegistries ;
34+ import net .neoforged .neoforge .registries .RegisterEvent ;
3435import org .jetbrains .annotations .Nullable ;
3536
3637import java .util .*;
3940
4041public final class AttachmentRegistryImpl {
4142 private static final Map <net .neoforged .neoforge .attachment .AttachmentType <?>, AttachmentType <?>> FABRIC_ATTACHMENT_TYPES = new ConcurrentHashMap <>();
42- private static final Set <ResourceLocation > syncableAttachments = Collections .synchronizedSet (new HashSet <>());
43- private static final Set <ResourceLocation > syncableView = Collections .unmodifiableSet (syncableAttachments );
44-
45- public static <A > net .neoforged .neoforge .attachment .AttachmentType <A > register (ResourceLocation id , net .neoforged .neoforge .attachment .AttachmentType <A > attachmentType ) {
46- ((BaseMappedRegistryAccessor ) NeoForgeRegistries .ATTACHMENT_TYPES ).invokeUnfreeze ();
47- Registry .register (NeoForgeRegistries .ATTACHMENT_TYPES , id , attachmentType );
48- NeoForgeRegistries .ATTACHMENT_TYPES .freeze ();
43+ private static final Map <ResourceLocation , net .neoforged .neoforge .attachment .AttachmentType <?>> NEO_ATTACHMENT_TYPES = new ConcurrentHashMap <>();
44+ private static boolean deferRegistration = true ;
45+
46+ public static <A > net .neoforged .neoforge .attachment .AttachmentType <A > registerNeoForgeAttachment (ResourceLocation id , net .neoforged .neoforge .attachment .AttachmentType <A > attachmentType ) {
47+ if (deferRegistration ) {
48+ NEO_ATTACHMENT_TYPES .put (id , attachmentType );
49+ } else {
50+ ((BaseMappedRegistryAccessor ) NeoForgeRegistries .ATTACHMENT_TYPES ).invokeUnfreeze ();
51+ Registry .register (NeoForgeRegistries .ATTACHMENT_TYPES , id , attachmentType );
52+ NeoForgeRegistries .ATTACHMENT_TYPES .freeze ();
53+ }
4954 return attachmentType ;
5055 }
5156
57+ public static void registerNeoTypes (RegisterEvent .RegisterHelper <net .neoforged .neoforge .attachment .AttachmentType <?>> helper ) {
58+ deferRegistration = false ;
59+ NEO_ATTACHMENT_TYPES .forEach (helper ::register );
60+ }
61+
5262 public static <A > AttachmentRegistry .Builder <A > builder () {
5363 return new BuilderImpl <>();
5464 }
@@ -58,24 +68,20 @@ public static <A> AttachmentType<A> getFabricAttachmentType(net.neoforged.neofor
5868 return (AttachmentType <A >) FABRIC_ATTACHMENT_TYPES .get (neoType );
5969 }
6070
61- public static <A > net .neoforged .neoforge .attachment .AttachmentType <A > getNeoForgeAttachmentType (AttachmentType <A > fabricType ) {
62- return ((AttachmentTypeImpl <A >) fabricType ).internalType ();
63- }
64-
65- public static Set <ResourceLocation > getSyncableAttachments () {
66- return syncableView ;
67- }
71+ public static <A > net .neoforged .neoforge .attachment .AttachmentType <A > getNeoForgeAttachmentType (AttachmentType <A > fabricType ) {
72+ return ((AttachmentTypeImpl <A >) fabricType ).internalType ();
73+ }
6874
6975 public static class BuilderImpl <A > implements AttachmentRegistry .Builder <A > {
7076 @ Nullable
7177 private Supplier <A > defaultInitializer = null ;
7278 @ Nullable
7379 private Codec <A > persistenceCodec = null ;
7480 private boolean copyOnDeath = false ;
75- @ Nullable
76- private StreamCodec <? super RegistryFriendlyByteBuf , A > packetCodec = null ;
77- @ Nullable
78- private AttachmentSyncPredicate syncPredicate = null ;
81+ @ Nullable
82+ private StreamCodec <? super RegistryFriendlyByteBuf , A > packetCodec = null ;
83+ @ Nullable
84+ private AttachmentSyncPredicate syncPredicate = null ;
7985
8086 @ Override
8187 public AttachmentRegistry .Builder <A > persistent (Codec <A > codec ) {
@@ -99,42 +105,30 @@ public AttachmentRegistry.Builder<A> initializer(Supplier<A> initializer) {
99105 return this ;
100106 }
101107
102- @ Deprecated
103- public AttachmentRegistry .Builder <A > syncWith (StreamCodec <? super RegistryFriendlyByteBuf , A > packetCodec , AttachmentSyncPredicate syncPredicate ) {
104- Objects .requireNonNull (packetCodec , "packet codec cannot be null" );
105- Objects .requireNonNull (syncPredicate , "sync predicate cannot be null" );
108+ @ Deprecated
109+ public AttachmentRegistry .Builder <A > syncWith (StreamCodec <? super RegistryFriendlyByteBuf , A > packetCodec , AttachmentSyncPredicate syncPredicate ) {
110+ Objects .requireNonNull (packetCodec , "packet codec cannot be null" );
111+ Objects .requireNonNull (syncPredicate , "sync predicate cannot be null" );
106112
107- this .packetCodec = packetCodec ;
108- this .syncPredicate = syncPredicate ;
109- return this ;
110- }
113+ this .packetCodec = packetCodec ;
114+ this .syncPredicate = syncPredicate ;
115+ return this ;
116+ }
111117
112118 @ Override
113119 public AttachmentType <A > buildAndRegister (ResourceLocation id ) {
114- Objects .requireNonNull (id , "identifier cannot be null" );
115-
116- if (syncPredicate != null && id .toString ().length () > AttachmentSync .MAX_IDENTIFIER_SIZE ) {
117- throw new IllegalArgumentException (
118- "Identifier length is too long for a synced attachment type (was %d, maximum is %d)" .formatted (
119- id .toString ().length (),
120- AttachmentSync .MAX_IDENTIFIER_SIZE
121- )
122- );
123- }
124-
125- net .neoforged .neoforge .attachment .AttachmentType <A > neoType = register (id , toNeoForgeAttachmentType ());
120+ Objects .requireNonNull (id , "identifier cannot be null" );
121+
122+ net .neoforged .neoforge .attachment .AttachmentType <A > neoType = registerNeoForgeAttachment (id , toNeoForgeAttachmentType ());
126123 AttachmentType <A > attachmentType = new AttachmentTypeImpl <>(
127- neoType ,
128- id ,
129- defaultInitializer ,
130- persistenceCodec ,
131- packetCodec ,
132- syncPredicate ,
133- copyOnDeath
134- );
135- if (attachmentType .isSynced ()) {
136- syncableAttachments .add (id );
137- }
124+ neoType ,
125+ id ,
126+ defaultInitializer ,
127+ persistenceCodec ,
128+ packetCodec ,
129+ syncPredicate ,
130+ copyOnDeath
131+ );
138132 FABRIC_ATTACHMENT_TYPES .put (neoType , attachmentType );
139133 return attachmentType ;
140134 }
@@ -150,10 +144,14 @@ private net.neoforged.neoforge.attachment.AttachmentType<A> toNeoForgeAttachment
150144 builder .serialize ((IAttachmentSerializer <?, A >) DummyAttachmentSerializer .INSTANCE );
151145 builder .copyHandler ((value , holder , provider ) -> value );
152146 }
147+ if (this .packetCodec != null ) {
148+ Objects .requireNonNull (this .syncPredicate , "sync predicate cannot be null" );
149+ builder .sync ((holder , player ) -> this .syncPredicate .test ((AttachmentTarget ) holder , player ), this .packetCodec );
150+ }
153151 return builder .build ();
154152 }
155153 }
156-
154+
157155 private static class DummyAttachmentSerializer implements IAttachmentSerializer <Tag , Object > {
158156 private static final DummyAttachmentSerializer INSTANCE = new DummyAttachmentSerializer ();
159157
0 commit comments