Skip to content

Commit 16d317a

Browse files
committed
Only provide each mod its own model list in ModelBakeEvent
1 parent 1b6880e commit 16d317a

File tree

2 files changed

+65
-14
lines changed

2 files changed

+65
-14
lines changed

forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,37 @@
11
package org.embeddedt.modernfix.forge.dynresources;
22

33
import com.google.common.collect.ForwardingMap;
4+
import com.google.common.collect.Sets;
5+
import com.google.common.graph.GraphBuilder;
6+
import com.google.common.graph.MutableGraph;
47
import net.minecraft.client.resources.model.BakedModel;
58
import net.minecraft.resources.ResourceLocation;
69
import net.minecraft.world.item.Item;
710
import net.minecraft.world.level.block.Block;
811
import net.minecraft.world.level.block.state.BlockState;
12+
import net.minecraftforge.fml.ModContainer;
13+
import net.minecraftforge.fml.ModList;
14+
import net.minecraftforge.forgespi.language.IModInfo;
915
import net.minecraftforge.registries.ForgeRegistries;
1016
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
1117
import org.jetbrains.annotations.Nullable;
1218

1319
import java.util.HashSet;
1420
import java.util.Map;
21+
import java.util.Optional;
1522
import java.util.Set;
1623

24+
/**
25+
* Stores a list of all known default block/item models in the game, and provides a namespaced version
26+
* of the model registry that emulates vanilla keySet behavior.
27+
*/
1728
public class ModelBakeEventHelper {
18-
public static Map<ResourceLocation, BakedModel> wrapRegistry(Map<ResourceLocation, BakedModel> modelRegistry) {
19-
Set<ResourceLocation> topLevelModelLocations = new HashSet<>(modelRegistry.keySet());
29+
private final Map<ResourceLocation, BakedModel> modelRegistry;
30+
private final Set<ResourceLocation> topLevelModelLocations;
31+
private final MutableGraph<String> dependencyGraph;
32+
public ModelBakeEventHelper(Map<ResourceLocation, BakedModel> modelRegistry) {
33+
this.modelRegistry = modelRegistry;
34+
this.topLevelModelLocations = new HashSet<>(modelRegistry.keySet());
2035
for(Block block : ForgeRegistries.BLOCKS) {
2136
for(BlockState state : block.getStateDefinition().getPossibleStates()) {
2237
topLevelModelLocations.add(ModelLocationCache.get(state));
@@ -25,6 +40,28 @@ public static Map<ResourceLocation, BakedModel> wrapRegistry(Map<ResourceLocatio
2540
for(Item item : ForgeRegistries.ITEMS) {
2641
topLevelModelLocations.add(ModelLocationCache.get(item));
2742
}
43+
this.dependencyGraph = GraphBuilder.undirected().build();
44+
ModList.get().forEachModContainer((id, mc) -> {
45+
this.dependencyGraph.addNode(id);
46+
});
47+
for(String id : this.dependencyGraph.nodes()) {
48+
Optional<? extends ModContainer> mContainer = ModList.get().getModContainerById(id);
49+
if(mContainer.isPresent()) {
50+
for(IModInfo.ModVersion version : mContainer.get().getModInfo().getDependencies()) {
51+
this.dependencyGraph.putEdge(id, version.getModId());
52+
}
53+
}
54+
}
55+
}
56+
57+
public Map<ResourceLocation, BakedModel> wrapRegistry(String modId) {
58+
final Set<String> modIdsToInclude = new HashSet<>();
59+
modIdsToInclude.add(modId);
60+
try {
61+
modIdsToInclude.addAll(this.dependencyGraph.adjacentNodes(modId));
62+
} catch(IllegalArgumentException ignored) { /* sanity check */ }
63+
modIdsToInclude.remove("minecraft");
64+
Set<ResourceLocation> ourModelLocations = Sets.filter(this.topLevelModelLocations, loc -> modIdsToInclude.contains(loc.getNamespace()));
2865
return new ForwardingMap<ResourceLocation, BakedModel>() {
2966
@Override
3067
protected Map<ResourceLocation, BakedModel> delegate() {
@@ -33,18 +70,12 @@ protected Map<ResourceLocation, BakedModel> delegate() {
3370

3471
@Override
3572
public Set<ResourceLocation> keySet() {
36-
return topLevelModelLocations;
73+
return ourModelLocations;
3774
}
3875

3976
@Override
4077
public boolean containsKey(@Nullable Object key) {
41-
return topLevelModelLocations.contains(key) || super.containsKey(key);
42-
}
43-
44-
@Override
45-
public BakedModel put(ResourceLocation key, BakedModel value) {
46-
topLevelModelLocations.add(key);
47-
return super.put(key, value);
78+
return ourModelLocations.contains(key) || super.containsKey(key);
4879
}
4980
};
5081
}

forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ForgeHooksClientMixin.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,40 @@
33
import net.minecraft.client.resources.model.BakedModel;
44
import net.minecraft.resources.ResourceLocation;
55
import net.minecraftforge.client.ForgeHooksClient;
6+
import net.minecraftforge.client.event.ModelBakeEvent;
7+
import net.minecraftforge.eventbus.api.Event;
8+
import net.minecraftforge.fml.ModContainer;
9+
import net.minecraftforge.fml.ModList;
10+
import net.minecraftforge.fml.ModLoader;
11+
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
612
import org.embeddedt.modernfix.forge.dynresources.ModelBakeEventHelper;
713
import org.spongepowered.asm.mixin.Mixin;
814
import org.spongepowered.asm.mixin.injection.At;
9-
import org.spongepowered.asm.mixin.injection.ModifyVariable;
15+
import org.spongepowered.asm.mixin.injection.Redirect;
1016

17+
import java.lang.reflect.Method;
1118
import java.util.Map;
1219

1320
@Mixin(ForgeHooksClient.class)
1421
public class ForgeHooksClientMixin {
1522
/**
1623
* Generate a more realistic keySet that contains every item and block model location, to help with mod compat.
1724
*/
18-
@ModifyVariable(method = "onModelBake", at = @At("HEAD"), ordinal = 0, argsOnly = true)
19-
private static Map<ResourceLocation, BakedModel> generateModelKeySet(Map<ResourceLocation, BakedModel> modelRegistry) {
20-
return ModelBakeEventHelper.wrapRegistry(modelRegistry);
25+
@Redirect(method = "onModelBake", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModLoader;postEvent(Lnet/minecraftforge/eventbus/api/Event;)V"))
26+
private static void postNamespacedKeySetEvent(ModLoader loader, Event event) {
27+
if(!ModLoader.isLoadingStateValid())
28+
return;
29+
ModelBakeEvent bakeEvent = ((ModelBakeEvent)event);
30+
ModelBakeEventHelper helper = new ModelBakeEventHelper(bakeEvent.getModelRegistry());
31+
Method acceptEv = ObfuscationReflectionHelper.findMethod(ModContainer.class, "acceptEvent", Event.class);
32+
ModList.get().forEachModContainer((id, mc) -> {
33+
Map<ResourceLocation, BakedModel> newRegistry = helper.wrapRegistry(id);
34+
ModelBakeEvent postedEvent = new ModelBakeEvent(bakeEvent.getModelManager(), newRegistry, bakeEvent.getModelLoader());
35+
try {
36+
acceptEv.invoke(mc, postedEvent);
37+
} catch(ReflectiveOperationException e) {
38+
e.printStackTrace();
39+
}
40+
});
2141
}
2242
}

0 commit comments

Comments
 (0)