13
13
import org .spongepowered .asm .mixin .injection .ModifyArg ;
14
14
import org .spongepowered .asm .mixin .injection .callback .CallbackInfoReturnable ;
15
15
16
+ import java .io .IOException ;
16
17
import java .io .InputStream ;
17
- import java .util .ArrayList ;
18
- import java .util .List ;
18
+ import java .nio .file .Files ;
19
+ import java .nio .file .Path ;
20
+ import java .util .*;
21
+ import java .util .stream .Stream ;
19
22
20
23
@ Mixin (DefaultClientResourcePack .class )
21
- public abstract class DefaultResourcePackMixin {
22
-
24
+ public abstract class DefaultClientResourcePackMixin {
23
25
@ Unique
24
26
private static final boolean HAS_FABRIC_RESOURCE_LOADER = FabricLoader .getInstance ().isModLoaded ("fabric-resource-loader-v0" );
27
+ @ Unique
28
+ private static final Map <String , Set <ModContainer >> NAMESPACES_TO_MODS = new HashMap <>();
29
+
30
+ static {
31
+ for (ModContainer mod : FabricLoader .getInstance ().getAllMods ()) {
32
+ if (mod .getMetadata ().getType ().equals ("builtin" )) {
33
+ continue ;
34
+ }
35
+ mod .findPath ("assets" ).filter (Files ::isDirectory ).ifPresent (assets -> {
36
+ try (Stream <Path > stream = Files .list (assets )) {
37
+ // skip empty namespace directories
38
+ // some mods may have template directories left over
39
+ if (!stream .findFirst ().isPresent ()) {
40
+ return ;
41
+ }
42
+ } catch (IOException ignored ) {
43
+ }
44
+
45
+ Set <String > namespaces = new HashSet <>();
46
+ try (Stream <Path > stream = Files .list (assets )) {
47
+ stream .filter (Files ::isDirectory ).forEach (path -> namespaces .add (path .getFileName ().toString ()));
48
+ } catch (IOException e ) {
49
+ SpeedrunAPI .LOGGER .error ("SpeedrunAPI failed to check resources for mod: {}" , mod .getMetadata ().getId ());
50
+ }
51
+
52
+ for (String namespace : namespaces ) {
53
+ NAMESPACES_TO_MODS .computeIfAbsent (namespace , key -> new TreeSet <>(Comparator .comparing (m -> m .getMetadata ().getId (), String ::compareTo ))).add (mod );
54
+ }
55
+ });
56
+ }
57
+ }
25
58
26
59
@ ModifyArg (
27
60
method = "<init>" ,
@@ -30,36 +63,33 @@ public abstract class DefaultResourcePackMixin {
30
63
target = "Lnet/minecraft/resource/DefaultResourcePack;<init>([Ljava/lang/String;)V"
31
64
)
32
65
)
33
- private static String [] addModNamespaces (String [] namespaces ) {
66
+ private static String [] initModsToNamespaces (String [] namespaces ) {
34
67
if (HAS_FABRIC_RESOURCE_LOADER ) {
35
68
SpeedrunAPI .LOGGER .info ("Disabling SpeedrunAPI resource loader in favor of fabric-resource-loader." );
36
69
return namespaces ;
37
70
}
38
71
39
- List <ModContainer > mods = new ArrayList <>(FabricLoader .getInstance ().getAllMods ());
40
- mods .removeIf (mod -> mod .getMetadata ().getType ().equals ("builtin" ));
41
-
42
- String [] allNamespaces = new String [mods .size () + namespaces .length ];
43
- int i ;
44
- for (i = 0 ; i < namespaces .length ; i ++) {
45
- allNamespaces [i ] = namespaces [i ];
46
- }
47
- for (ModContainer mod : mods ) {
48
- allNamespaces [i ++] = mod .getMetadata ().getId ();
49
- }
50
- return allNamespaces ;
72
+ Set <String > combined = new LinkedHashSet <>();
73
+ combined .addAll (Arrays .asList (namespaces ));
74
+ combined .addAll (NAMESPACES_TO_MODS .keySet ());
75
+ return combined .toArray (new String [0 ]);
51
76
}
52
77
53
78
@ Inject (method = "findInputStream" , at = @ At ("HEAD" ), cancellable = true )
54
79
private void loadModResources (ResourceType type , Identifier id , CallbackInfoReturnable <InputStream > cir ) {
55
80
if (HAS_FABRIC_RESOURCE_LOADER ) {
56
81
return ;
57
82
}
58
- for (ModContainer mod : FabricLoader .getInstance ().getAllMods ()) {
59
- if (mod .getMetadata ().getType ().equals ("builtin" )) {
60
- continue ;
61
- }
62
- mod .findPath (type .getDirectory () + "/" + id .getNamespace () + "/" + id .getPath ()).ifPresent (path -> {
83
+ // make sure only client resources are loaded
84
+ if (type != ResourceType .CLIENT_RESOURCES ) {
85
+ return ;
86
+ }
87
+ Set <ModContainer > mods = NAMESPACES_TO_MODS .get (id .getNamespace ());
88
+ if (mods == null ) {
89
+ return ;
90
+ }
91
+ for (ModContainer mod : mods ) {
92
+ mod .findPath ("assets/" + id .getNamespace () + "/" + id .getPath ()).ifPresent (path -> {
63
93
try {
64
94
cir .setReturnValue (path .toUri ().toURL ().openStream ());
65
95
} catch (Exception e ) {
0 commit comments