Only provide each mod its own model list in ModelBakeEvent
This commit is contained in:
parent
1b6880ed9f
commit
16d317af97
|
|
@ -1,22 +1,37 @@
|
|||
package org.embeddedt.modernfix.forge.dynresources;
|
||||
|
||||
import com.google.common.collect.ForwardingMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.graph.GraphBuilder;
|
||||
import com.google.common.graph.MutableGraph;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Stores a list of all known default block/item models in the game, and provides a namespaced version
|
||||
* of the model registry that emulates vanilla keySet behavior.
|
||||
*/
|
||||
public class ModelBakeEventHelper {
|
||||
public static Map<ResourceLocation, BakedModel> wrapRegistry(Map<ResourceLocation, BakedModel> modelRegistry) {
|
||||
Set<ResourceLocation> topLevelModelLocations = new HashSet<>(modelRegistry.keySet());
|
||||
private final Map<ResourceLocation, BakedModel> modelRegistry;
|
||||
private final Set<ResourceLocation> topLevelModelLocations;
|
||||
private final MutableGraph<String> dependencyGraph;
|
||||
public ModelBakeEventHelper(Map<ResourceLocation, BakedModel> modelRegistry) {
|
||||
this.modelRegistry = modelRegistry;
|
||||
this.topLevelModelLocations = new HashSet<>(modelRegistry.keySet());
|
||||
for(Block block : ForgeRegistries.BLOCKS) {
|
||||
for(BlockState state : block.getStateDefinition().getPossibleStates()) {
|
||||
topLevelModelLocations.add(ModelLocationCache.get(state));
|
||||
|
|
@ -25,6 +40,28 @@ public class ModelBakeEventHelper {
|
|||
for(Item item : ForgeRegistries.ITEMS) {
|
||||
topLevelModelLocations.add(ModelLocationCache.get(item));
|
||||
}
|
||||
this.dependencyGraph = GraphBuilder.undirected().build();
|
||||
ModList.get().forEachModContainer((id, mc) -> {
|
||||
this.dependencyGraph.addNode(id);
|
||||
});
|
||||
for(String id : this.dependencyGraph.nodes()) {
|
||||
Optional<? extends ModContainer> mContainer = ModList.get().getModContainerById(id);
|
||||
if(mContainer.isPresent()) {
|
||||
for(IModInfo.ModVersion version : mContainer.get().getModInfo().getDependencies()) {
|
||||
this.dependencyGraph.putEdge(id, version.getModId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<ResourceLocation, BakedModel> wrapRegistry(String modId) {
|
||||
final Set<String> modIdsToInclude = new HashSet<>();
|
||||
modIdsToInclude.add(modId);
|
||||
try {
|
||||
modIdsToInclude.addAll(this.dependencyGraph.adjacentNodes(modId));
|
||||
} catch(IllegalArgumentException ignored) { /* sanity check */ }
|
||||
modIdsToInclude.remove("minecraft");
|
||||
Set<ResourceLocation> ourModelLocations = Sets.filter(this.topLevelModelLocations, loc -> modIdsToInclude.contains(loc.getNamespace()));
|
||||
return new ForwardingMap<ResourceLocation, BakedModel>() {
|
||||
@Override
|
||||
protected Map<ResourceLocation, BakedModel> delegate() {
|
||||
|
|
@ -33,18 +70,12 @@ public class ModelBakeEventHelper {
|
|||
|
||||
@Override
|
||||
public Set<ResourceLocation> keySet() {
|
||||
return topLevelModelLocations;
|
||||
return ourModelLocations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(@Nullable Object key) {
|
||||
return topLevelModelLocations.contains(key) || super.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel put(ResourceLocation key, BakedModel value) {
|
||||
topLevelModelLocations.add(key);
|
||||
return super.put(key, value);
|
||||
return ourModelLocations.contains(key) || super.containsKey(key);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,18 @@ package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources;
|
|||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.event.ModelBakeEvent;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||
import org.embeddedt.modernfix.forge.dynresources.ModelBakeEventHelper;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(ForgeHooksClient.class)
|
||||
|
|
@ -15,8 +22,21 @@ public class ForgeHooksClientMixin {
|
|||
/**
|
||||
* Generate a more realistic keySet that contains every item and block model location, to help with mod compat.
|
||||
*/
|
||||
@ModifyVariable(method = "onModelBake", at = @At("HEAD"), ordinal = 0, argsOnly = true)
|
||||
private static Map<ResourceLocation, BakedModel> generateModelKeySet(Map<ResourceLocation, BakedModel> modelRegistry) {
|
||||
return ModelBakeEventHelper.wrapRegistry(modelRegistry);
|
||||
@Redirect(method = "onModelBake", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModLoader;postEvent(Lnet/minecraftforge/eventbus/api/Event;)V"))
|
||||
private static void postNamespacedKeySetEvent(ModLoader loader, Event event) {
|
||||
if(!ModLoader.isLoadingStateValid())
|
||||
return;
|
||||
ModelBakeEvent bakeEvent = ((ModelBakeEvent)event);
|
||||
ModelBakeEventHelper helper = new ModelBakeEventHelper(bakeEvent.getModelRegistry());
|
||||
Method acceptEv = ObfuscationReflectionHelper.findMethod(ModContainer.class, "acceptEvent", Event.class);
|
||||
ModList.get().forEachModContainer((id, mc) -> {
|
||||
Map<ResourceLocation, BakedModel> newRegistry = helper.wrapRegistry(id);
|
||||
ModelBakeEvent postedEvent = new ModelBakeEvent(bakeEvent.getModelManager(), newRegistry, bakeEvent.getModelLoader());
|
||||
try {
|
||||
acceptEv.invoke(mc, postedEvent);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user