From e94288bbb193360a8200b451172221ef7cde648a Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Tue, 16 Jun 2015 16:03:10 -0700 Subject: [PATCH] Fixup model loading errors not being printed by making ICustomModelLoader.loadModel propogate IOExceptions as needed. --- .../client/model/BlockStateLoader.java | 14 +- .../client/model/ICustomModelLoader.java | 4 +- .../client/model/ModelLoader.java | 134 +++++++++++++----- .../client/model/ModelLoaderRegistry.java | 27 ++-- .../client/model/b3d/B3DLoader.java | 5 +- 5 files changed, 136 insertions(+), 48 deletions(-) diff --git a/src/main/java/net/minecraftforge/client/model/BlockStateLoader.java b/src/main/java/net/minecraftforge/client/model/BlockStateLoader.java index 015372da3a..858c3a0623 100644 --- a/src/main/java/net/minecraftforge/client/model/BlockStateLoader.java +++ b/src/main/java/net/minecraftforge/client/model/BlockStateLoader.java @@ -14,6 +14,7 @@ import javax.vecmath.Matrix4f; import net.minecraft.client.renderer.block.model.ModelBlockDefinition; import net.minecraft.client.resources.model.ModelRotation; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.FMLLog; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; @@ -186,7 +187,18 @@ public class BlockStateLoader IModelState partState = new TRSRTransformation(matrix); if (part.isUVLock()) partState = new ModelLoader.UVLock(partState); - models.put(entry.getKey(), Pair.of(runModelHooks(loader.getModel(part.getModelLocation()), part.getTextures(), part.getCustomData()), partState)); + IModel model = null; + try + { + model = loader.getModel(part.getModelLocation()); + } + catch (IOException e) + { + FMLLog.warning("Unable to load block sub-model: \'" + part.getModelLocation() /*+ "\' for variant: \'" + parent*/ + "\': " + e.toString()); + model = loader.getMissingModel(); // Will make it look weird, but that is good. + } + + models.put(entry.getKey(), Pair.of(runModelHooks(model, part.getTextures(), part.getCustomData()), partState)); } return new MultiModel(hasBase ? base : null, baseRot, models.build()); diff --git a/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java b/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java index 6dd74668f9..beeaecbaae 100644 --- a/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java +++ b/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java @@ -1,5 +1,7 @@ package net.minecraftforge.client.model; +import java.io.IOException; + import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.util.ResourceLocation; @@ -14,5 +16,5 @@ public interface ICustomModelLoader extends IResourceManagerReloadListener /* * loads (or reloads) specified model */ - public IModel loadModel(ResourceLocation modelLocation); + public IModel loadModel(ResourceLocation modelLocation) throws IOException; } diff --git a/src/main/java/net/minecraftforge/client/model/ModelLoader.java b/src/main/java/net/minecraftforge/client/model/ModelLoader.java index 47ab1a713e..da4b7dab27 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelLoader.java +++ b/src/main/java/net/minecraftforge/client/model/ModelLoader.java @@ -58,6 +58,7 @@ import org.apache.logging.log4j.Level; import com.google.common.base.Function; import com.google.common.base.Functions; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -71,6 +72,7 @@ public class ModelLoader extends ModelBakery private final Set textures = new HashSet(); private final Set loadingModels = new HashSet(); private final Set missingVariants = Sets.newHashSet(); + private IModel missingModel = null; private boolean isLoading = false; public boolean isLoading() @@ -91,8 +93,16 @@ public class ModelLoader extends ModelBakery isLoading = true; loadBlocks(); loadItems(); - IModel missing = getModel(new ResourceLocation(MODEL_MISSING.getResourceDomain(), MODEL_MISSING.getResourcePath())); - stateModels.put(MODEL_MISSING, missing); + try + { + missingModel = getModel(new ResourceLocation(MODEL_MISSING.getResourceDomain(), MODEL_MISSING.getResourcePath())); + } + catch (IOException e) + { + // If this ever happens things are bad. Should never NOT be able to load the missing model. + Throwables.propagate(e); + } + stateModels.put(MODEL_MISSING, missingModel); textures.remove(TextureMap.LOCATION_MISSING_TEXTURE); textures.addAll(LOCATIONS_BUILTIN_TEXTURES); textureMap.loadSprites(resourceManager, new IIconCreator() @@ -107,8 +117,8 @@ public class ModelLoader extends ModelBakery }); sprites.put(new ResourceLocation("missingno"), textureMap.getMissingSprite()); Function textureGetter = Functions.forMap(sprites, textureMap.getMissingSprite()); - IFlexibleBakedModel missingBaked = missing.bake(missing.getDefaultState(), Attributes.DEFAULT_BAKED_FORMAT, textureGetter); - for(Entry e : stateModels.entrySet()) + IFlexibleBakedModel missingBaked = missingModel.bake(missingModel.getDefaultState(), Attributes.DEFAULT_BAKED_FORMAT, textureGetter); + for (Entry e : stateModels.entrySet()) { if(e.getValue() == getMissingModel()) { @@ -143,11 +153,11 @@ public class ModelLoader extends ModelBakery { missingVariants.add(location); } - if(variants != null && !variants.getVariants().isEmpty()) + if (variants != null && !variants.getVariants().isEmpty()) { try { - stateModels.put(location, new WeightedRandomModel(variants)); + stateModels.put(location, new WeightedRandomModel(location, variants)); } catch(Throwable e) { @@ -165,18 +175,29 @@ public class ModelLoader extends ModelBakery { ResourceLocation file = getItemLocation(s); ModelResourceLocation memory = new ModelResourceLocation(s, "inventory"); - IModel model = getModel(file); - if(model == null || model == getMissingModel()) + IModel model = null; + try { - FMLLog.fine("Item json isn't found for '" + memory + "', trying to load the variant from the blockstate json"); - registerVariant(getModelBlockDefinition(memory), memory); + model = getModel(file); + } + catch (IOException e) + { + // Handled by our finally block. + } + finally + { + if (model == null || model == getMissingModel()) + { + FMLLog.fine("Item json isn't found for '" + memory + "', trying to load the variant from the blockstate json"); + registerVariant(getModelBlockDefinition(memory), memory); + } + else stateModels.put(memory, model); } - else stateModels.put(memory, model); } } } - public IModel getModel(ResourceLocation location) + public IModel getModel(ResourceLocation location) throws IOException { if(!ModelLoaderRegistry.loaded(location)) loadAnyModel(location); return ModelLoaderRegistry.getModel(location); @@ -188,7 +209,7 @@ public class ModelLoader extends ModelBakery return new ResourceLocation(model.getResourceDomain(), model.getResourcePath() + ".json"); } - private void loadAnyModel(ResourceLocation location) + private void loadAnyModel(ResourceLocation location) throws IOException { if(loadingModels.contains(location)) { @@ -226,14 +247,30 @@ public class ModelLoader extends ModelBakery // setting parent here to make textures resolve properly if(model.getParentLocation() != null) { - IModel parent = getModel(model.getParentLocation()); - if(parent instanceof VanillaModelWrapper) + try { - model.parent = ((VanillaModelWrapper) parent).model; + IModel parent = getModel(model.getParentLocation()); + if(parent instanceof VanillaModelWrapper) + { + model.parent = ((VanillaModelWrapper) parent).model; + } + else + { + throw new IllegalStateException("vanilla model '" + model + "' can't have non-vanilla parent"); + } } - else + catch (IOException e) { - throw new IllegalStateException("vanilla model" + model + "can't have non-vanilla parent"); + FMLLog.warning("Could not load vanilla model parent '" + model.getParentLocation() + "' for '" + model + "': " + e.toString()); + IModel missing = ModelLoader.this.getMissingModel(); + if (missing instanceof VanillaModelWrapper) + { + model.parent = ((VanillaModelWrapper)missing).model; + } + else + { + throw new IllegalStateException("vanilla model '" + model + "' has missing parent, and missing model is not a vanilla model"); + } } } @@ -403,16 +440,32 @@ public class ModelLoader extends ModelBakery private final List models = new ArrayList(); private final IModelState defaultState; - public WeightedRandomModel(Variants variants) + @Deprecated public WeightedRandomModel(Variants variants){ this(null, variants); } // Remove 1.9 + public WeightedRandomModel(ModelResourceLocation parent, Variants variants) { this.variants = variants.getVariants(); ImmutableMap.Builder builder = ImmutableMap.builder(); - for(Variant v : (List)variants.getVariants()) + for (Variant v : (List)variants.getVariants()) { ResourceLocation loc = v.getModelLocation(); locations.add(loc); - IModel model = getModel(loc); + IModel model = null; + try + { + model = getModel(loc); + } + catch (Exception e) + { + /* + * Vanilla eats this, which makes it only show variants that have models. + * But that doesn't help debugging, so we maintain the missing model + * so that resource pack makers have a hint that their states are broken. + */ + FMLLog.warning("Unable to load block model: \'" + loc + "\' for variant: \'" + parent + "\': " + e.toString()); + model = getMissingModel(); + } + if (v instanceof ISmartVariant) { model = ((ISmartVariant)v).process(model, ModelLoader.this); @@ -423,7 +476,16 @@ public class ModelLoader extends ModelBakery models.add(model); builder.put(model, new TRSRTransformation(v.getRotation())); } + + if (models.size() == 0) //If all variants are missing, add one with the missing model and default rotation. + { + IModel missing = getMissingModel(); + models.add(missing); + builder.put(missing, new TRSRTransformation(ModelRotation.X0_Y0)); + } + defaultState = new MapModelState(builder.build()); + } public Collection getDependencies() @@ -495,7 +557,19 @@ public class ModelLoader extends ModelBakery public IModel getMissingModel() { - return getModel(new ResourceLocation(MODEL_MISSING.getResourceDomain(), MODEL_MISSING.getResourcePath())); + if (missingModel == null) + { + try + { + missingModel = getModel(new ResourceLocation(MODEL_MISSING.getResourceDomain(), MODEL_MISSING.getResourcePath())); + } + catch (IOException e) + { + // If this ever happens things are bad. Should never NOT be able to load the missing model. + Throwables.propagate(e); + } + } + return missingModel; } static enum VanillaLoader implements ICustomModelLoader @@ -524,21 +598,9 @@ public class ModelLoader extends ModelBakery return true; } - public IModel loadModel(ResourceLocation modelLocation) + public IModel loadModel(ResourceLocation modelLocation) throws IOException { - try - { - return loader.new VanillaModelWrapper(modelLocation, loader.loadModel(modelLocation)); - } - catch(IOException e) - { - if(loader.isLoading) //ToDo: Make this less gaging, hides missing models.. - { - // holding error until onPostBakeEvent - } - else FMLLog.log(Level.ERROR, e, "Exception loading model %s with vanilla loader, skipping", modelLocation); - return loader.getMissingModel(); - } + return loader.new VanillaModelWrapper(modelLocation, loader.loadModel(modelLocation)); } } diff --git a/src/main/java/net/minecraftforge/client/model/ModelLoaderRegistry.java b/src/main/java/net/minecraftforge/client/model/ModelLoaderRegistry.java index db24104728..3ee394811e 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelLoaderRegistry.java +++ b/src/main/java/net/minecraftforge/client/model/ModelLoaderRegistry.java @@ -1,5 +1,7 @@ package net.minecraftforge.client.model; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -15,6 +17,8 @@ import net.minecraftforge.fml.common.FMLLog; import org.apache.logging.log4j.Level; +import com.google.common.base.Throwables; + /* * Central hub for custom model loaders. */ @@ -50,7 +54,7 @@ public class ModelLoaderRegistry return new ResourceLocation(location.getResourceDomain(), "models/" + location.getResourcePath()); } - public static IModel getModel(ResourceLocation location) + public static IModel getModel(ResourceLocation location) throws IOException { ResourceLocation actual = getActualLocation(location); if(cache.containsKey(location)) return cache.get(location); @@ -87,14 +91,21 @@ public class ModelLoaderRegistry FMLLog.severe("no suitable loader found for the model %s, skipping", location); model = getMissingModel(); } - else try + else { - model = accepted.loadModel(actual); - } - catch(Exception e) - { - FMLLog.log(Level.ERROR, e, "Exception loading model %s with loader %s, skipping", location, accepted); - model = getMissingModel(); + try + { + model = accepted.loadModel(actual); + } + catch (IOException e) + { + throw e; + } + catch(Exception e) + { + FMLLog.log(Level.ERROR, e, "Exception loading model %s with loader %s, skipping", location, accepted); + model = getMissingModel(); + } } cache.put(location, model); return model; diff --git a/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java b/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java index 46f1c464ce..e8d4f111c2 100644 --- a/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java +++ b/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java @@ -104,7 +104,7 @@ public class B3DLoader implements ICustomModelLoader } @SuppressWarnings("unchecked") - public IModel loadModel(ResourceLocation modelLocation) + public IModel loadModel(ResourceLocation modelLocation) throws IOException { ResourceLocation file = new ResourceLocation(modelLocation.getResourceDomain(), modelLocation.getResourcePath()); if(!cache.containsKey(file)) @@ -130,8 +130,9 @@ public class B3DLoader implements ICustomModelLoader } catch(IOException e) { - FMLLog.log(Level.ERROR, e, "Exception loading model %s with B3D loader, skipping", modelLocation); + //FMLLog.log(Level.ERROR, e, "Exception loading model %s with B3D loader, skipping", modelLocation); cache.put(modelLocation, null); + throw e; } } B3DModel model = cache.get(file);