Model loader improvements: adding custom data/textures to models that don't need them doesn't cause a error now, since it's common to put those in the defaults section of the blockstate json; you can get IModel associated with the variant now - using ModelLoaderRegistry.getModel; MultiLayerModel should now respect transformations applied to it, and respect part transformations.
This commit is contained in:
parent
632d8e553d
commit
949e77b46a
|
@ -134,20 +134,14 @@ public class BlockStateLoader
|
|||
|
||||
protected IModel runModelHooks(IModel base, ImmutableMap<String, String> textureMap, ImmutableMap<String, String> customData)
|
||||
{
|
||||
if (!customData.isEmpty())
|
||||
if (!customData.isEmpty() && base instanceof IModelCustomData)
|
||||
{
|
||||
if (base instanceof IModelCustomData)
|
||||
base = ((IModelCustomData)base).process(customData);
|
||||
else
|
||||
throw new RuntimeException("Attempted to add custom data to a model that doesn't need it: " + base);
|
||||
base = ((IModelCustomData)base).process(customData);
|
||||
}
|
||||
|
||||
if (!textureMap.isEmpty())
|
||||
if (!textureMap.isEmpty() && base instanceof IRetexturableModel)
|
||||
{
|
||||
if (base instanceof IRetexturableModel)
|
||||
base = ((IRetexturableModel)base).retexture(textureMap);
|
||||
else
|
||||
throw new RuntimeException("Attempted to retexture a non-retexturable model: " + base);
|
||||
base = ((IRetexturableModel)base).retexture(textureMap);
|
||||
}
|
||||
|
||||
return base;
|
||||
|
|
|
@ -17,6 +17,7 @@ public interface IModel
|
|||
/*
|
||||
* Returns all model locations that this model depends on.
|
||||
* Assume that returned collection is immutable.
|
||||
* See ModelLoaderRegistry.getModel for dependency loading.
|
||||
*/
|
||||
Collection<ResourceLocation> getDependencies();
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.google.common.collect.ImmutableMap;
|
|||
|
||||
/*
|
||||
* Simple implementation of IModelState via a map and a default value. Provides a full state for each part.
|
||||
* You probably don't want to use this.
|
||||
*/
|
||||
public class MapModelState implements IModelState
|
||||
{
|
||||
|
|
|
@ -330,13 +330,21 @@ public class ModelLoader extends ModelBakery
|
|||
}
|
||||
}
|
||||
|
||||
private IModel getVariantModel(ModelResourceLocation location)
|
||||
{
|
||||
loadVariants(ImmutableList.of(location));
|
||||
IModel model = stateModels.get(location);
|
||||
if(model == null) model = getMissingModel();
|
||||
return model;
|
||||
}
|
||||
|
||||
private void resolveDependencies(IModel model) throws IOException
|
||||
{
|
||||
for (ResourceLocation dep : model.getDependencies())
|
||||
{
|
||||
if(dep instanceof ModelResourceLocation)
|
||||
{
|
||||
loadVariants(ImmutableList.of((ModelResourceLocation)dep));
|
||||
getVariantModel((ModelResourceLocation)dep);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -598,37 +606,6 @@ public class ModelLoader extends ModelBakery
|
|||
}
|
||||
}
|
||||
|
||||
// Weighted models can contain multiple copies of 1 model with different rotations - this is to make it work with IModelState (different copies will be different objects).
|
||||
private static class WeightedPartWrapper implements IModel
|
||||
{
|
||||
private final IModel model;
|
||||
|
||||
public WeightedPartWrapper(IModel model)
|
||||
{
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
{
|
||||
return model.getDependencies();
|
||||
}
|
||||
|
||||
public Collection<ResourceLocation> getTextures()
|
||||
{
|
||||
return model.getTextures();
|
||||
}
|
||||
|
||||
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
|
||||
{
|
||||
return model.bake(state, format, bakedTextureGetter);
|
||||
}
|
||||
|
||||
public IModelState getDefaultState()
|
||||
{
|
||||
return model.getDefaultState();
|
||||
}
|
||||
}
|
||||
|
||||
private class WeightedRandomModel implements IModel
|
||||
{
|
||||
private final List<Variant> variants;
|
||||
|
@ -636,11 +613,10 @@ public class ModelLoader extends ModelBakery
|
|||
private final List<IModel> models = new ArrayList<IModel>();
|
||||
private final IModelState defaultState;
|
||||
|
||||
@Deprecated @SuppressWarnings("unused") public WeightedRandomModel(Variants variants){ this(null, variants); } // Remove 1.9
|
||||
public WeightedRandomModel(ModelResourceLocation parent, Variants variants)
|
||||
{
|
||||
this.variants = variants.getVariants();
|
||||
ImmutableMap.Builder<MapModelState.Wrapper, IModelState> builder = ImmutableMap.builder();
|
||||
ImmutableList.Builder<Pair<IModel, IModelState>> builder = ImmutableList.builder();
|
||||
for (Variant v : (List<Variant>)variants.getVariants())
|
||||
{
|
||||
ResourceLocation loc = v.getModelLocation();
|
||||
|
@ -676,20 +652,18 @@ public class ModelLoader extends ModelBakery
|
|||
textures.addAll(model.getTextures()); // Kick this, just in case.
|
||||
}
|
||||
|
||||
model = new WeightedPartWrapper(model);
|
||||
models.add(model);
|
||||
builder.put(MapModelState.wrap(model), v.getState());
|
||||
builder.add(Pair.of(model, v.getState()));
|
||||
}
|
||||
|
||||
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(MapModelState.wrap(missing), TRSRTransformation.identity());
|
||||
builder.add(Pair.<IModel, IModelState>of(missing, TRSRTransformation.identity()));
|
||||
}
|
||||
|
||||
defaultState = new MapModelState(builder.build());
|
||||
|
||||
defaultState = new MultiModelState(builder.build());
|
||||
}
|
||||
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
|
@ -708,15 +682,6 @@ public class ModelLoader extends ModelBakery
|
|||
return state;
|
||||
}
|
||||
|
||||
private IModelState getState(IModelState state, IModel model)
|
||||
{
|
||||
if(state instanceof MapModelState)
|
||||
{
|
||||
return ((MapModelState)state).getState(model);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
|
||||
{
|
||||
if(!Attributes.moreSpecific(format, Attributes.DEFAULT_BAKED_FORMAT))
|
||||
|
@ -727,14 +692,14 @@ public class ModelLoader extends ModelBakery
|
|||
{
|
||||
Variant v = variants.get(0);
|
||||
IModel model = models.get(0);
|
||||
return model.bake(addUV(v.isUvLocked(), getState(state, model)), format, bakedTextureGetter);
|
||||
return model.bake(addUV(v.isUvLocked(), MultiModelState.getPartState(state, model, 0)), format, bakedTextureGetter);
|
||||
}
|
||||
WeightedBakedModel.Builder builder = new WeightedBakedModel.Builder();
|
||||
for(int i = 0; i < variants.size(); i++)
|
||||
{
|
||||
IModel model = models.get(i);
|
||||
Variant v = variants.get(i);
|
||||
builder.add(model.bake(addUV(v.isUvLocked(), getState(state, model)), format, bakedTextureGetter), variants.get(i).getWeight());
|
||||
builder.add(model.bake(addUV(v.isUvLocked(), MultiModelState.getPartState(state, model, i)), format, bakedTextureGetter), variants.get(i).getWeight());
|
||||
}
|
||||
return new FlexibleWeightedBakedModel(builder.build(), Attributes.DEFAULT_BAKED_FORMAT);
|
||||
}
|
||||
|
@ -747,14 +712,11 @@ public class ModelLoader extends ModelBakery
|
|||
|
||||
private static class FlexibleWeightedBakedModel extends WeightedBakedModel implements IFlexibleBakedModel
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
private final WeightedBakedModel parent;
|
||||
private final VertexFormat format;
|
||||
|
||||
public FlexibleWeightedBakedModel(WeightedBakedModel parent, VertexFormat format)
|
||||
{
|
||||
super(parent.models);
|
||||
this.parent = parent;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
|
@ -764,12 +726,6 @@ public class ModelLoader extends ModelBakery
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private boolean isBuiltinModel(ModelBlock model)
|
||||
{
|
||||
return model == MODEL_GENERATED || model == MODEL_COMPASS || model == MODEL_CLOCK || model == MODEL_ENTITY;
|
||||
}
|
||||
|
||||
public IModel getMissingModel()
|
||||
{
|
||||
if (missingModel == null)
|
||||
|
|
|
@ -10,6 +10,7 @@ import net.minecraft.client.Minecraft;
|
|||
import net.minecraft.client.resources.IReloadableResourceManager;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.client.resources.IResourceManagerReloadListener;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.ModelLoader.VanillaLoader;
|
||||
import net.minecraftforge.client.model.b3d.B3DLoader;
|
||||
|
@ -64,58 +65,79 @@ public class ModelLoaderRegistry
|
|||
return new ResourceLocation(location.getResourceDomain(), "models/" + location.getResourcePath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary method to get IModel instances.
|
||||
* ResourceLocation argument will be passed directly to the custom model loaders,
|
||||
* ModelResourceLocation argument will be loaded through the blockstate system.
|
||||
*/
|
||||
public static IModel getModel(ResourceLocation location) throws IOException
|
||||
{
|
||||
if(cache.containsKey(location)) return cache.get(location);
|
||||
ResourceLocation actual = getActualLocation(location);
|
||||
ICustomModelLoader accepted = null;
|
||||
for(ICustomModelLoader loader : loaders)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(loader.accepts(actual))
|
||||
{
|
||||
if(accepted != null)
|
||||
{
|
||||
FMLLog.severe("2 loaders (%s and %s) want to load the same model %s", accepted, loader, location);
|
||||
throw new IllegalStateException("2 loaders want to load the same model");
|
||||
}
|
||||
accepted = loader;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "Exception checking if model %s can be loaded with loader %s, skipping", location, loader);
|
||||
}
|
||||
}
|
||||
|
||||
// no custom loaders found, try vanilla one
|
||||
if(accepted == null)
|
||||
{
|
||||
if(VanillaLoader.instance.accepts(actual)) accepted = VanillaLoader.instance;
|
||||
}
|
||||
|
||||
IModel model;
|
||||
if(accepted == null)
|
||||
if(location instanceof ModelResourceLocation)
|
||||
{
|
||||
FMLLog.severe("no suitable loader found for the model %s, skipping", location);
|
||||
model = getMissingModel();
|
||||
ModelLoader loader = ModelLoader.VanillaLoader.instance.getLoader();
|
||||
if(loader != null)
|
||||
{
|
||||
model = loader.getVariantModel((ModelResourceLocation)location);
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.log(Level.ERROR, "Loading model too early, skipping: %s", location);
|
||||
model = getMissingModel();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
if(cache.containsKey(location)) return cache.get(location);
|
||||
ResourceLocation actual = getActualLocation(location);
|
||||
ICustomModelLoader accepted = null;
|
||||
for(ICustomModelLoader loader : loaders)
|
||||
{
|
||||
model = accepted.loadModel(actual);
|
||||
try
|
||||
{
|
||||
if(loader.accepts(actual))
|
||||
{
|
||||
if(accepted != null)
|
||||
{
|
||||
FMLLog.severe("2 loaders (%s and %s) want to load the same model %s", accepted, loader, location);
|
||||
throw new IllegalStateException("2 loaders want to load the same model");
|
||||
}
|
||||
accepted = loader;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "Exception checking if model %s can be loaded with loader %s, skipping", location, loader);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
|
||||
// no custom loaders found, try vanilla one
|
||||
if(accepted == null)
|
||||
{
|
||||
throw e;
|
||||
if(VanillaLoader.instance.accepts(actual)) accepted = VanillaLoader.instance;
|
||||
}
|
||||
catch(Exception e)
|
||||
|
||||
if(accepted == null)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "Exception loading model %s with loader %s, skipping", location, accepted);
|
||||
FMLLog.severe("no suitable loader found for the model %s, skipping", location);
|
||||
model = getMissingModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minecraftforge.client.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -14,7 +15,6 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
|||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.client.resources.model.IBakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumWorldBlockLayer;
|
||||
|
@ -23,6 +23,7 @@ import net.minecraftforge.client.MinecraftForgeClient;
|
|||
import net.minecraftforge.fml.common.FMLLog;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
|
@ -54,10 +55,36 @@ public class MultiLayerModel implements IModelCustomData
|
|||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
private static ImmutableMap<Optional<EnumWorldBlockLayer>, IFlexibleBakedModel> buildModels(ImmutableMap<Optional<EnumWorldBlockLayer>, ModelResourceLocation> models, IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
|
||||
{
|
||||
ImmutableMap.Builder<Optional<EnumWorldBlockLayer>, IFlexibleBakedModel> builder = ImmutableMap.builder();
|
||||
for(Optional<EnumWorldBlockLayer> key : models.keySet())
|
||||
{
|
||||
IModel model;
|
||||
try
|
||||
{
|
||||
model = ModelLoaderRegistry.getModel(models.get(key));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "Couldn't load MultiLayerModel dependency: %s", models.get(key));
|
||||
model = ModelLoaderRegistry.getMissingModel();
|
||||
}
|
||||
builder.put(key, model.bake(new ModelStateComposition(state, model.getDefaultState()), format, bakedTextureGetter));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
|
||||
{
|
||||
return new MultiLayerBakedModel(models, format, IPerspectiveAwareModel.MapWrapper.getTransforms(state));
|
||||
IModel missing = ModelLoaderRegistry.getMissingModel();
|
||||
return new MultiLayerBakedModel(
|
||||
buildModels(models, state, format, bakedTextureGetter),
|
||||
missing.bake(missing.getDefaultState(), format, bakedTextureGetter),
|
||||
format,
|
||||
IPerspectiveAwareModel.MapWrapper.getTransforms(state)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,63 +129,59 @@ public class MultiLayerModel implements IModelCustomData
|
|||
|
||||
public static class MultiLayerBakedModel implements IFlexibleBakedModel, ISmartBlockModel, IPerspectiveAwareModel
|
||||
{
|
||||
private final ImmutableMap<Optional<EnumWorldBlockLayer>, ModelResourceLocation> models;
|
||||
private final ImmutableMap<Optional<EnumWorldBlockLayer>, IFlexibleBakedModel> models;
|
||||
private final VertexFormat format;
|
||||
private final ImmutableMap<TransformType, TRSRTransformation> cameraTransforms;;
|
||||
private IBakedModel missing;
|
||||
private IBakedModel base;
|
||||
private ImmutableMap<EnumWorldBlockLayer, IBakedModel> bakedModels;
|
||||
private ImmutableMap<Optional<EnumFacing>, ImmutableList<BakedQuad>> quads;
|
||||
private final IFlexibleBakedModel base;
|
||||
private final IFlexibleBakedModel missing;
|
||||
private final ImmutableMap<Optional<EnumFacing>, ImmutableList<BakedQuad>> quads;
|
||||
|
||||
private static final Function<ResourceLocation, TextureAtlasSprite> defaultTextureGetter = new Function<ResourceLocation, TextureAtlasSprite>()
|
||||
{
|
||||
public TextureAtlasSprite apply(ResourceLocation location)
|
||||
{
|
||||
return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString());
|
||||
}
|
||||
};
|
||||
|
||||
@Deprecated // remove 1.9
|
||||
public MultiLayerBakedModel(ImmutableMap<Optional<EnumWorldBlockLayer>, ModelResourceLocation> models, VertexFormat format, ImmutableMap<TransformType, TRSRTransformation> cameraTransforms)
|
||||
{
|
||||
this(
|
||||
buildModels(models, TRSRTransformation.identity(), format, defaultTextureGetter),
|
||||
ModelLoaderRegistry.getMissingModel().bake(ModelLoaderRegistry.getMissingModel().getDefaultState(), format, defaultTextureGetter),
|
||||
format,
|
||||
cameraTransforms
|
||||
);
|
||||
}
|
||||
|
||||
public MultiLayerBakedModel(ImmutableMap<Optional<EnumWorldBlockLayer>, IFlexibleBakedModel> models, IFlexibleBakedModel missing, VertexFormat format, ImmutableMap<TransformType, TRSRTransformation> cameraTransforms)
|
||||
{
|
||||
this.models = models;
|
||||
this.format = format;
|
||||
this.cameraTransforms = cameraTransforms;
|
||||
}
|
||||
|
||||
private void compute()
|
||||
{
|
||||
if(base == null)
|
||||
this.missing = missing;
|
||||
if(models.containsKey(Optional.absent()))
|
||||
{
|
||||
ModelManager manager = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelManager();
|
||||
missing = manager.getMissingModel();
|
||||
base = getModel(manager, Optional.<EnumWorldBlockLayer>absent());
|
||||
|
||||
ImmutableMap.Builder<EnumWorldBlockLayer, IBakedModel> builder = ImmutableMap.builder();
|
||||
for(EnumWorldBlockLayer layer : EnumWorldBlockLayer.values())
|
||||
{
|
||||
if(models.containsKey(Optional.of(layer)))
|
||||
{
|
||||
builder.put(layer, getModel(manager, Optional.of(layer)));
|
||||
}
|
||||
}
|
||||
bakedModels = builder.build();
|
||||
|
||||
ImmutableMap.Builder<Optional<EnumFacing>, ImmutableList<BakedQuad>> quadBuilder = ImmutableMap.builder();
|
||||
quadBuilder.put(Optional.<EnumFacing>absent(), buildQuads(Optional.<EnumFacing>absent()));
|
||||
for(EnumFacing side: EnumFacing.values())
|
||||
{
|
||||
quadBuilder.put(Optional.of(side), buildQuads(Optional.of(side)));
|
||||
}
|
||||
quads = quadBuilder.build();
|
||||
base = models.get(Optional.absent());
|
||||
}
|
||||
}
|
||||
|
||||
private IBakedModel getModel(ModelManager manager, Optional<EnumWorldBlockLayer> layer)
|
||||
{
|
||||
ModelResourceLocation loc = models.get(layer);
|
||||
if(loc == null)
|
||||
else
|
||||
{
|
||||
loc = new ModelResourceLocation("builtin/missing", "missing");
|
||||
base = missing;
|
||||
}
|
||||
return manager.getModel(loc);
|
||||
ImmutableMap.Builder<Optional<EnumFacing>, ImmutableList<BakedQuad>> quadBuilder = ImmutableMap.builder();
|
||||
quadBuilder.put(Optional.<EnumFacing>absent(), buildQuads(models, Optional.<EnumFacing>absent()));
|
||||
for(EnumFacing side: EnumFacing.values())
|
||||
{
|
||||
quadBuilder.put(Optional.of(side), buildQuads(models, Optional.of(side)));
|
||||
}
|
||||
quads = quadBuilder.build();
|
||||
}
|
||||
|
||||
private ImmutableList<BakedQuad> buildQuads(Optional<EnumFacing> side)
|
||||
private static ImmutableList<BakedQuad> buildQuads(ImmutableMap<Optional<EnumWorldBlockLayer>, IFlexibleBakedModel> models, Optional<EnumFacing> side)
|
||||
{
|
||||
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
||||
for(IBakedModel model : bakedModels.values())
|
||||
for(IBakedModel model : models.values())
|
||||
{
|
||||
if(side.isPresent())
|
||||
{
|
||||
|
@ -175,42 +198,36 @@ public class MultiLayerModel implements IModelCustomData
|
|||
@Override
|
||||
public List<BakedQuad> getFaceQuads(EnumFacing side)
|
||||
{
|
||||
compute();
|
||||
return quads.get(Optional.of(side));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getGeneralQuads()
|
||||
{
|
||||
compute();
|
||||
return quads.get(Optional.absent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
compute();
|
||||
return base.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
compute();
|
||||
return base.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
compute();
|
||||
return base.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
compute();
|
||||
return base.getParticleTexture();
|
||||
}
|
||||
|
||||
|
@ -223,13 +240,12 @@ public class MultiLayerModel implements IModelCustomData
|
|||
@Override
|
||||
public IBakedModel handleBlockState(IBlockState state)
|
||||
{
|
||||
compute();
|
||||
EnumWorldBlockLayer layer = MinecraftForgeClient.getRenderLayer();
|
||||
if(!bakedModels.containsKey(layer))
|
||||
Optional<EnumWorldBlockLayer> layer = Optional.of(MinecraftForgeClient.getRenderLayer());
|
||||
if(!models.containsKey(layer))
|
||||
{
|
||||
return missing;
|
||||
}
|
||||
return bakedModels.get(layer);
|
||||
return models.get(layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,15 +4,20 @@
|
|||
"model": "forge:multi-layer",
|
||||
"custom": {
|
||||
// base is used for model properties - camera transforms, isGui3d, e.t.c.
|
||||
"base": "minecraft:stone_slab#half=bottom",
|
||||
"base": "forgedebugmultilayermodel:test_layer_block#aux",
|
||||
// per-layer models
|
||||
"Solid": "minecraft:stone_slab#half=bottom",
|
||||
"Solid": "forgedebugmultilayermodel:test_layer_block#aux",
|
||||
"Translucent": "minecraft:pink_stained_glass_pane#east=true,north=false,south=false,west=true"
|
||||
},
|
||||
"transform": "forge:default-block"
|
||||
},
|
||||
"variants": {
|
||||
"normal": [{}],
|
||||
"inventory": [{}]
|
||||
"inventory": [{}],
|
||||
"aux": [{
|
||||
"model": "cube_all",
|
||||
"textures": { "all": "blocks/slime" },
|
||||
"transform": { "scale": .5 }
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue