2018-12-24 16:29:06 +00:00
|
|
|
package net.shadowfacts.simplemultipart.client;
|
|
|
|
|
2018-12-29 18:36:29 +00:00
|
|
|
import net.fabricmc.fabric.api.client.model.ModelProviderContext;
|
2018-12-24 16:29:06 +00:00
|
|
|
import net.fabricmc.fabric.api.client.model.ModelProviderException;
|
2018-12-29 18:36:29 +00:00
|
|
|
import net.fabricmc.fabric.api.client.model.ModelVariantProvider;
|
2018-12-24 16:36:59 +00:00
|
|
|
import net.minecraft.client.render.block.BlockModels;
|
2018-12-29 18:36:29 +00:00
|
|
|
import net.minecraft.client.render.model.MultipartUnbakedModel;
|
2018-12-24 16:29:06 +00:00
|
|
|
import net.minecraft.client.render.model.UnbakedModel;
|
|
|
|
import net.minecraft.client.render.model.json.ModelVariantMap;
|
|
|
|
import net.minecraft.client.render.model.json.WeightedUnbakedModel;
|
|
|
|
import net.minecraft.client.util.ModelIdentifier;
|
|
|
|
import net.minecraft.resource.Resource;
|
2018-12-24 16:36:59 +00:00
|
|
|
import net.minecraft.resource.ResourceManager;
|
2018-12-24 16:29:06 +00:00
|
|
|
import net.minecraft.util.Identifier;
|
2018-12-24 16:36:59 +00:00
|
|
|
import net.shadowfacts.simplemultipart.SimpleMultipart;
|
|
|
|
import net.shadowfacts.simplemultipart.multipart.Multipart;
|
|
|
|
import net.shadowfacts.simplemultipart.multipart.MultipartState;
|
2018-12-24 16:29:06 +00:00
|
|
|
import org.apache.commons.io.IOUtils;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
import java.io.Reader;
|
|
|
|
import java.util.HashMap;
|
2018-12-24 16:36:59 +00:00
|
|
|
import java.util.HashSet;
|
2018-12-24 16:29:06 +00:00
|
|
|
import java.util.Map;
|
2018-12-24 16:36:59 +00:00
|
|
|
import java.util.Set;
|
|
|
|
import java.util.function.Consumer;
|
2018-12-24 16:29:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author shadowfacts
|
|
|
|
*/
|
2018-12-29 18:36:29 +00:00
|
|
|
public class MultipartVariantProvider implements ModelVariantProvider {
|
2018-12-24 16:29:06 +00:00
|
|
|
|
2018-12-24 16:36:59 +00:00
|
|
|
private static final Set<ModelIdentifier> multipartModels = new HashSet<>();
|
|
|
|
|
2018-12-29 18:36:29 +00:00
|
|
|
private final ResourceManager resourceManager;
|
2018-12-24 16:29:06 +00:00
|
|
|
private final Map<ModelIdentifier, UnbakedModel> unbakedModels = new HashMap<>();
|
|
|
|
|
2018-12-24 16:36:59 +00:00
|
|
|
static void registerMultipartModels(ResourceManager resourceManager, Consumer<ModelIdentifier> adder) {
|
|
|
|
for (Multipart part : SimpleMultipart.MULTIPART) {
|
|
|
|
Identifier partId = SimpleMultipart.MULTIPART.getId(part);
|
|
|
|
for (MultipartState state : part.getStateFactory().getStates()) {
|
|
|
|
String variant = BlockModels.propertyMapToString(state.getEntries());
|
|
|
|
ModelIdentifier id = new ModelIdentifier(partId, variant);
|
|
|
|
multipartModels.add(id);
|
|
|
|
adder.accept(id);
|
|
|
|
}
|
2018-12-24 16:47:50 +00:00
|
|
|
|
|
|
|
// TODO: should multiparts be able to control this?
|
|
|
|
multipartModels.add(new ModelIdentifier(partId, "inventory"));
|
2018-12-24 16:36:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-29 18:36:29 +00:00
|
|
|
public MultipartVariantProvider(ResourceManager resourceManager) {
|
|
|
|
this.resourceManager = resourceManager;
|
|
|
|
}
|
2018-12-24 16:29:06 +00:00
|
|
|
|
2018-12-29 18:36:29 +00:00
|
|
|
@Override
|
|
|
|
public UnbakedModel loadModelVariant(ModelIdentifier id, ModelProviderContext context) throws ModelProviderException {
|
|
|
|
if (!multipartModels.contains(id)) {
|
2018-12-24 16:29:06 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2018-12-29 18:36:29 +00:00
|
|
|
return getOrLoadPartModel(id);
|
2018-12-24 16:29:06 +00:00
|
|
|
} catch (IOException e) {
|
2018-12-29 18:36:29 +00:00
|
|
|
throw new ModelProviderException("Exception encountered while loading multipart model " + id, e);
|
2018-12-24 16:29:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-24 20:43:12 +00:00
|
|
|
private UnbakedModel getOrLoadPartModel(ModelIdentifier modelId) throws ModelProviderException, IOException {
|
|
|
|
UnbakedModel existing = unbakedModels.get(modelId);
|
2018-12-24 16:29:06 +00:00
|
|
|
if (existing != null) {
|
|
|
|
return existing;
|
|
|
|
}
|
|
|
|
|
2018-12-24 20:43:12 +00:00
|
|
|
return loadPartModel(modelId);
|
2018-12-24 16:29:06 +00:00
|
|
|
}
|
|
|
|
|
2018-12-24 20:43:12 +00:00
|
|
|
private UnbakedModel loadPartModel(ModelIdentifier modelId) throws ModelProviderException, IOException {
|
|
|
|
Identifier partId = new Identifier(modelId.getNamespace(), modelId.getPath());
|
|
|
|
Identifier partStateDefId = new Identifier(partId.getNamespace(), "multipartstates/" + partId.getPath() + ".json");
|
|
|
|
|
|
|
|
Multipart part = SimpleMultipart.MULTIPART.get(partId);
|
|
|
|
MultipartFakeBlock blockAdapter = new MultipartFakeBlock(part);
|
|
|
|
|
|
|
|
ModelVariantMap variantMap = loadPartVariantMap(blockAdapter, partStateDefId);
|
|
|
|
|
2018-12-29 18:36:29 +00:00
|
|
|
if (variantMap.hasMultipartModel()) {
|
|
|
|
MultipartUnbakedModel multipartUnbakedModel = variantMap.getMultipartMdoel();
|
2018-12-24 20:43:12 +00:00
|
|
|
part.getStateFactory().getStates().forEach(state -> {
|
|
|
|
ModelIdentifier stateModelId = new ModelIdentifier(partId, BlockModels.propertyMapToString(state.getEntries()));
|
|
|
|
unbakedModels.put(stateModelId, multipartUnbakedModel);
|
|
|
|
});
|
|
|
|
} else {
|
2018-12-29 18:36:29 +00:00
|
|
|
Map<String, WeightedUnbakedModel> variants = variantMap.getVariantMap();
|
2018-12-24 20:43:12 +00:00
|
|
|
variants.forEach((variant, model) -> {
|
|
|
|
unbakedModels.put(new ModelIdentifier(partId, variant), model);
|
|
|
|
});
|
|
|
|
}
|
2018-12-24 16:29:06 +00:00
|
|
|
|
2018-12-24 20:43:12 +00:00
|
|
|
UnbakedModel model = unbakedModels.get(modelId);
|
2018-12-24 16:29:06 +00:00
|
|
|
if (model == null) {
|
2018-12-24 20:43:12 +00:00
|
|
|
throw new ModelProviderException("Loaded multipart state " + partStateDefId + " for model " + modelId + " but still missing model");
|
2018-12-24 16:29:06 +00:00
|
|
|
}
|
|
|
|
return model;
|
|
|
|
}
|
|
|
|
|
2018-12-24 20:43:12 +00:00
|
|
|
private ModelVariantMap loadPartVariantMap(MultipartFakeBlock blockAdapter, Identifier partStateDefId) throws IOException {
|
2018-12-24 16:29:06 +00:00
|
|
|
Resource resource = null;
|
|
|
|
Reader reader = null;
|
|
|
|
try {
|
2018-12-29 18:36:29 +00:00
|
|
|
resource = resourceManager.getResource(partStateDefId);
|
2018-12-24 16:29:06 +00:00
|
|
|
reader = new InputStreamReader(resource.getInputStream());
|
|
|
|
|
2018-12-29 18:36:29 +00:00
|
|
|
ModelVariantMap.DeserializationContext context = new ModelVariantMap.DeserializationContext();
|
|
|
|
context.setStateFactory(blockAdapter.getStateFactory());
|
|
|
|
return ModelVariantMap.deserialize(context, reader);
|
2018-12-24 16:29:06 +00:00
|
|
|
} finally {
|
|
|
|
IOUtils.closeQuietly(reader);
|
|
|
|
IOUtils.closeQuietly(resource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|