minecraft-src/net/minecraft/client/resources/model/ModelDiscovery.java
2025-07-04 03:15:13 +03:00

92 lines
3.1 KiB
Java

package net.minecraft.client.resources.model;
import com.google.common.collect.Sets;
import com.mojang.logging.LogUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.block.model.ItemModelGenerator;
import net.minecraft.resources.ResourceLocation;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class ModelDiscovery {
static final Logger LOGGER = LogUtils.getLogger();
private final Map<ResourceLocation, UnbakedModel> inputModels;
final UnbakedModel missingModel;
private final List<ResolvableModel> topModels = new ArrayList();
private final Map<ResourceLocation, UnbakedModel> referencedModels = new HashMap();
public ModelDiscovery(Map<ResourceLocation, UnbakedModel> inputModels, UnbakedModel missingModel) {
this.inputModels = inputModels;
this.missingModel = missingModel;
this.referencedModels.put(MissingBlockModel.LOCATION, missingModel);
}
public void registerSpecialModels() {
this.referencedModels.put(ItemModelGenerator.GENERATED_ITEM_MODEL_ID, new ItemModelGenerator());
}
public void addRoot(ResolvableModel model) {
this.topModels.add(model);
}
public void discoverDependencies() {
this.topModels.forEach(resolvableModel -> resolvableModel.resolveDependencies(new ModelDiscovery.ResolverImpl()));
}
public Map<ResourceLocation, UnbakedModel> getReferencedModels() {
return this.referencedModels;
}
public Set<ResourceLocation> getUnreferencedModels() {
return Sets.<ResourceLocation>difference(this.inputModels.keySet(), this.referencedModels.keySet());
}
UnbakedModel getBlockModel(ResourceLocation modelLocation) {
return (UnbakedModel)this.referencedModels.computeIfAbsent(modelLocation, this::loadBlockModel);
}
private UnbakedModel loadBlockModel(ResourceLocation modelLocation) {
UnbakedModel unbakedModel = (UnbakedModel)this.inputModels.get(modelLocation);
if (unbakedModel == null) {
LOGGER.warn("Missing block model: '{}'", modelLocation);
return this.missingModel;
} else {
return unbakedModel;
}
}
@Environment(EnvType.CLIENT)
class ResolverImpl implements ResolvableModel.Resolver {
private final List<ResourceLocation> stack = new ArrayList();
private final Set<ResourceLocation> resolvedModels = new HashSet();
@Override
public UnbakedModel resolve(ResourceLocation model) {
if (this.stack.contains(model)) {
ModelDiscovery.LOGGER.warn("Detected model loading loop: {}->{}", this.stacktraceToString(), model);
return ModelDiscovery.this.missingModel;
} else {
UnbakedModel unbakedModel = ModelDiscovery.this.getBlockModel(model);
if (this.resolvedModels.add(model)) {
this.stack.add(model);
unbakedModel.resolveDependencies(this);
this.stack.remove(model);
}
return unbakedModel;
}
}
private String stacktraceToString() {
return (String)this.stack.stream().map(ResourceLocation::toString).collect(Collectors.joining("->"));
}
}
}