2014-12-28 04:10:54 +00:00
package net.minecraftforge.client.model ;
2015-04-01 13:06:03 +00:00
import java.awt.Color ;
import java.awt.Graphics2D ;
2015-02-17 00:36:08 +00:00
import java.awt.image.BufferedImage ;
2014-12-28 04:10:54 +00:00
import java.util.ArrayList ;
import java.util.Collection ;
import java.util.Collections ;
2016-03-16 02:00:44 +00:00
import java.util.Comparator ;
2015-05-20 09:54:33 +00:00
import java.util.Iterator ;
2014-12-28 04:10:54 +00:00
import java.util.List ;
import java.util.Map ;
import java.util.Map.Entry ;
import java.util.Set ;
2015-02-04 06:45:23 +00:00
import net.minecraft.block.Block ;
2014-12-28 04:10:54 +00:00
import net.minecraft.block.state.IBlockState ;
2015-02-17 00:36:08 +00:00
import net.minecraft.client.Minecraft ;
2014-12-28 04:10:54 +00:00
import net.minecraft.client.renderer.BlockModelShapes ;
2015-02-04 06:45:23 +00:00
import net.minecraft.client.renderer.ItemMeshDefinition ;
import net.minecraft.client.renderer.ItemModelMesher ;
2016-03-05 23:51:39 +00:00
import net.minecraft.client.renderer.block.model.BakedQuad ;
2015-05-20 09:54:33 +00:00
import net.minecraft.client.renderer.block.model.BlockPart ;
import net.minecraft.client.renderer.block.model.BlockPartFace ;
2016-01-01 15:15:48 +00:00
import net.minecraft.client.renderer.block.model.BlockPartRotation ;
2016-03-15 22:42:01 +00:00
import net.minecraft.client.renderer.block.model.BuiltInModel ;
import net.minecraft.client.renderer.block.model.IBakedModel ;
2014-12-28 04:10:54 +00:00
import net.minecraft.client.renderer.block.model.ItemCameraTransforms ;
2015-12-03 19:38:08 +00:00
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType ;
2014-12-28 04:10:54 +00:00
import net.minecraft.client.renderer.block.model.ItemModelGenerator ;
2016-03-21 06:15:39 +00:00
import net.minecraft.client.renderer.block.model.ItemOverrideList ;
2016-03-15 22:42:01 +00:00
import net.minecraft.client.renderer.block.model.ModelBakery ;
2014-12-28 04:10:54 +00:00
import net.minecraft.client.renderer.block.model.ModelBlock ;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition ;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition.MissingVariantException ;
2016-03-15 22:42:01 +00:00
import net.minecraft.client.renderer.block.model.ModelResourceLocation ;
import net.minecraft.client.renderer.block.model.ModelRotation ;
2016-03-13 13:16:25 +00:00
import net.minecraft.client.renderer.block.model.MultipartBakedModel ;
2016-03-15 22:42:01 +00:00
import net.minecraft.client.renderer.block.model.SimpleBakedModel ;
2016-03-05 02:02:34 +00:00
import net.minecraft.client.renderer.block.model.Variant ;
import net.minecraft.client.renderer.block.model.VariantList ;
2016-03-15 22:42:01 +00:00
import net.minecraft.client.renderer.block.model.WeightedBakedModel ;
import net.minecraft.client.renderer.block.model.multipart.Multipart ;
import net.minecraft.client.renderer.block.model.multipart.Selector ;
2016-03-16 02:00:44 +00:00
import net.minecraft.client.renderer.block.statemap.BlockStateMapper ;
2015-02-04 06:45:23 +00:00
import net.minecraft.client.renderer.block.statemap.IStateMapper ;
2014-12-28 04:10:54 +00:00
import net.minecraft.client.renderer.texture.IIconCreator ;
import net.minecraft.client.renderer.texture.TextureAtlasSprite ;
import net.minecraft.client.renderer.texture.TextureMap ;
2015-06-28 22:19:10 +00:00
import net.minecraft.client.renderer.vertex.DefaultVertexFormats ;
2014-12-28 04:10:54 +00:00
import net.minecraft.client.renderer.vertex.VertexFormat ;
import net.minecraft.client.resources.IResourceManager ;
2015-12-15 21:19:04 +00:00
import net.minecraft.init.Items ;
2014-12-28 04:10:54 +00:00
import net.minecraft.item.Item ;
2015-12-15 21:19:04 +00:00
import net.minecraft.item.ItemStack ;
2016-02-22 00:53:26 +00:00
import net.minecraft.launchwrapper.Launch ;
2015-05-20 09:54:33 +00:00
import net.minecraft.util.EnumFacing ;
2014-12-28 04:10:54 +00:00
import net.minecraft.util.ResourceLocation ;
2016-03-15 22:42:01 +00:00
import net.minecraft.util.registry.IRegistry ;
2016-03-21 06:15:39 +00:00
import net.minecraftforge.client.model.animation.AnimationItemOverrideList ;
2016-01-01 15:15:48 +00:00
import net.minecraftforge.client.model.animation.IAnimatedModel ;
import net.minecraftforge.client.model.animation.ModelBlockAnimation ;
2015-12-15 21:19:04 +00:00
import net.minecraftforge.common.ForgeModContainer ;
2016-03-21 07:01:30 +00:00
import net.minecraftforge.common.model.IModelPart ;
import net.minecraftforge.common.model.IModelState ;
import net.minecraftforge.common.model.TRSRTransformation ;
import net.minecraftforge.common.model.animation.IClip ;
2016-01-01 15:15:48 +00:00
import net.minecraftforge.common.property.IExtendedBlockState ;
import net.minecraftforge.common.property.Properties ;
2015-12-15 21:19:04 +00:00
import net.minecraftforge.fluids.Fluid ;
import net.minecraftforge.fluids.FluidContainerRegistry ;
import net.minecraftforge.fluids.FluidRegistry ;
import net.minecraftforge.fluids.FluidStack ;
2014-12-28 04:10:54 +00:00
import net.minecraftforge.fml.common.FMLLog ;
2016-01-06 19:53:34 +00:00
import net.minecraftforge.fml.common.ProgressManager ;
import net.minecraftforge.fml.common.ProgressManager.ProgressBar ;
2014-12-28 04:10:54 +00:00
import net.minecraftforge.fml.common.registry.GameData ;
2015-02-04 06:45:23 +00:00
import net.minecraftforge.fml.common.registry.RegistryDelegate ;
2014-12-28 04:10:54 +00:00
2015-02-04 06:45:23 +00:00
import org.apache.commons.lang3.tuple.Pair ;
2014-12-28 04:10:54 +00:00
import com.google.common.base.Function ;
2016-03-15 22:42:01 +00:00
import com.google.common.base.Joiner ;
2015-12-03 19:38:08 +00:00
import com.google.common.base.Optional ;
2016-03-15 22:42:01 +00:00
import com.google.common.collect.HashMultimap ;
import com.google.common.collect.ImmutableList ;
import com.google.common.collect.ImmutableMap ;
import com.google.common.collect.ImmutableSet ;
import com.google.common.collect.Lists ;
import com.google.common.collect.Maps ;
import com.google.common.collect.Multimap ;
2016-03-16 02:00:44 +00:00
import com.google.common.collect.Multimaps ;
2016-03-15 22:42:01 +00:00
import com.google.common.collect.Sets ;
public final class ModelLoader extends ModelBakery
2014-12-28 04:10:54 +00:00
{
2016-01-16 22:51:50 +00:00
private final Map < ModelResourceLocation , IModel > stateModels = Maps . newHashMap ( ) ;
2015-02-04 06:45:23 +00:00
private final Set < ModelResourceLocation > missingVariants = Sets . newHashSet ( ) ;
2016-01-19 22:19:38 +00:00
private final Map < ResourceLocation , Exception > loadingExceptions = Maps . newHashMap ( ) ;
2015-06-16 23:03:10 +00:00
private IModel missingModel = null ;
2015-02-04 06:45:23 +00:00
private boolean isLoading = false ;
public boolean isLoading ( )
{
return isLoading ;
}
2014-12-28 04:10:54 +00:00
2016-02-22 00:53:26 +00:00
private final boolean enableVerboseMissingInfo = ( Boolean ) Launch . blackboard . get ( " fml.deobfuscatedEnvironment " ) | | Boolean . parseBoolean ( System . getProperty ( " forge.verboseMissingModelLogging " , " false " ) ) ;
2014-12-28 04:10:54 +00:00
public ModelLoader ( IResourceManager manager , TextureMap map , BlockModelShapes shapes )
{
super ( manager , map , shapes ) ;
VanillaLoader . instance . setLoader ( this ) ;
2016-03-13 13:16:25 +00:00
VariantLoader . instance . setLoader ( this ) ;
2016-03-21 07:01:30 +00:00
ModelLoaderRegistry . clearModelCache ( manager ) ;
2014-12-28 04:10:54 +00:00
}
@Override
2015-11-13 14:23:37 +00:00
public IRegistry < ModelResourceLocation , IBakedModel > setupModelRegistry ( )
2014-12-28 04:10:54 +00:00
{
2015-02-04 06:45:23 +00:00
isLoading = true ;
2014-12-28 04:10:54 +00:00
loadBlocks ( ) ;
2016-03-13 09:10:50 +00:00
loadVariantItemModels ( ) ;
2016-03-15 22:42:01 +00:00
missingModel = ModelLoaderRegistry . getMissingModel ( ) ;
2015-06-16 23:03:10 +00:00
stateModels . put ( MODEL_MISSING , missingModel ) ;
2016-03-13 13:16:25 +00:00
final Set < ResourceLocation > textures = Sets . newHashSet ( ModelLoaderRegistry . getTextures ( ) ) ;
2014-12-28 04:10:54 +00:00
textures . remove ( TextureMap . LOCATION_MISSING_TEXTURE ) ;
textures . addAll ( LOCATIONS_BUILTIN_TEXTURES ) ;
2016-03-13 13:16:25 +00:00
2014-12-28 04:10:54 +00:00
textureMap . loadSprites ( resourceManager , new IIconCreator ( )
{
public void registerSprites ( TextureMap map )
{
for ( ResourceLocation t : textures )
{
2015-06-23 13:52:42 +00:00
map . registerSprite ( t ) ;
2014-12-28 04:10:54 +00:00
}
}
} ) ;
2016-03-13 13:16:25 +00:00
2016-03-05 02:02:34 +00:00
IBakedModel missingBaked = missingModel . bake ( missingModel . getDefaultState ( ) , DefaultVertexFormats . ITEM , DefaultTextureGetter . instance ) ;
2016-03-13 13:16:25 +00:00
Map < IModel , IBakedModel > bakedModels = Maps . newHashMap ( ) ;
2016-03-16 02:00:44 +00:00
HashMultimap < IModel , ModelResourceLocation > models = HashMultimap . create ( ) ;
Multimaps . invertFrom ( Multimaps . forMap ( stateModels ) , models ) ;
ProgressBar bakeBar = ProgressManager . push ( " ModelLoader: baking " , models . keySet ( ) . size ( ) ) ;
for ( IModel model : models . keySet ( ) )
2014-12-28 04:10:54 +00:00
{
2016-03-16 02:00:44 +00:00
bakeBar . step ( " [ " + Joiner . on ( " , " ) . join ( models . get ( model ) ) + " ] " ) ;
2016-03-13 13:16:25 +00:00
if ( model = = getMissingModel ( ) )
2015-06-04 15:07:03 +00:00
{
2016-03-13 13:16:25 +00:00
bakedModels . put ( model , missingBaked ) ;
2015-06-04 15:07:03 +00:00
}
else
{
2016-03-13 13:16:25 +00:00
bakedModels . put ( model , model . bake ( model . getDefaultState ( ) , DefaultVertexFormats . ITEM , DefaultTextureGetter . instance ) ) ;
2015-06-04 15:07:03 +00:00
}
2014-12-28 04:10:54 +00:00
}
2016-03-16 02:00:44 +00:00
ProgressManager . pop ( bakeBar ) ;
2016-03-13 13:16:25 +00:00
for ( Entry < ModelResourceLocation , IModel > e : stateModels . entrySet ( ) )
{
bakedRegistry . putObject ( e . getKey ( ) , bakedModels . get ( e . getValue ( ) ) ) ;
}
2014-12-28 04:10:54 +00:00
return bakedRegistry ;
}
2016-03-13 09:10:50 +00:00
// NOOP, replaced by dependency resolution
@Override
protected void loadVariantModels ( ) { }
// NOOP, replaced by dependency resolution
@Override
protected void loadMultipartVariantModels ( ) { }
2016-03-16 02:00:44 +00:00
@Override
protected void loadBlocks ( )
2014-12-28 04:10:54 +00:00
{
2016-03-16 02:00:44 +00:00
List < Block > blocks = Lists . newArrayList ( Block . blockRegistry ) ;
Collections . sort ( blocks , new Comparator < Block > ( )
2016-01-16 22:51:50 +00:00
{
2016-03-16 02:00:44 +00:00
public int compare ( Block b1 , Block b2 )
2016-01-16 22:51:50 +00:00
{
2016-03-16 02:00:44 +00:00
return b1 . getRegistryName ( ) . compareTo ( b2 . getRegistryName ( ) ) ;
2016-01-16 22:51:50 +00:00
}
} ) ;
2016-03-16 02:00:44 +00:00
ProgressBar blockBar = ProgressManager . push ( " ModelLoader: blocks " , blocks . size ( ) ) ;
BlockStateMapper mapper = this . blockModelShapes . getBlockStateMapper ( ) ;
for ( Block block : blocks )
2016-01-16 22:51:50 +00:00
{
2016-03-16 02:00:44 +00:00
blockBar . step ( block . getRegistryName ( ) ) ;
for ( ResourceLocation location : mapper . getBlockstateLocations ( block ) )
{
loadBlock ( mapper , block , location ) ;
}
2016-01-16 22:51:50 +00:00
}
2016-01-06 19:53:34 +00:00
ProgressManager . pop ( blockBar ) ;
2016-03-16 02:00:44 +00:00
}
2014-12-28 04:10:54 +00:00
2016-03-13 13:16:25 +00:00
@Override
protected void registerVariant ( ModelBlockDefinition definition , ModelResourceLocation location )
2016-03-05 23:51:39 +00:00
{
2016-03-15 22:42:01 +00:00
IModel model ;
try
{
model = ModelLoaderRegistry . getModel ( location ) ;
}
catch ( Exception e )
{
storeException ( location , e ) ;
model = getMissingModel ( ) ;
}
stateModels . put ( location , model ) ;
2016-03-05 23:51:39 +00:00
}
2014-12-28 04:10:54 +00:00
@Override
2016-03-13 13:16:25 +00:00
protected void registerMultipartVariant ( ModelBlockDefinition definition , Collection < ModelResourceLocation > locations )
2014-12-28 04:10:54 +00:00
{
2016-03-13 13:16:25 +00:00
for ( ModelResourceLocation location : locations )
2016-01-06 23:09:29 +00:00
{
2016-03-15 22:42:01 +00:00
registerVariant ( null , location ) ;
2016-03-13 09:10:50 +00:00
}
2014-12-28 04:10:54 +00:00
}
2016-01-19 22:19:38 +00:00
private void storeException ( ResourceLocation location , Exception exception )
2016-01-16 22:51:50 +00:00
{
loadingExceptions . put ( location , exception ) ;
}
2016-01-19 22:19:38 +00:00
@Override
protected ModelBlockDefinition getModelBlockDefinition ( ResourceLocation location )
{
try
{
return super . getModelBlockDefinition ( location ) ;
}
catch ( Exception exception )
{
storeException ( location , new Exception ( " Could not load model definition for variant " + location , exception ) ) ;
}
return new ModelBlockDefinition ( new ArrayList < ModelBlockDefinition > ( ) ) ;
}
2016-03-13 09:10:50 +00:00
@Override
protected void loadItemModels ( )
2014-12-28 04:10:54 +00:00
{
2016-01-02 13:38:18 +00:00
// register model for the universal bucket, if it exists
if ( FluidRegistry . isUniversalBucketEnabled ( ) )
{
setBucketModelDefinition ( ForgeModContainer . getInstance ( ) . universalBucket ) ;
}
2016-02-19 10:17:23 +00:00
registerVariantNames ( ) ;
2016-03-09 22:11:56 +00:00
2016-03-16 02:00:44 +00:00
List < Item > items = Lists . newArrayList ( GameData . getItemRegistry ( ) . typeSafeIterable ( ) ) ;
Collections . sort ( items , new Comparator < Item > ( )
2016-01-06 19:53:34 +00:00
{
2016-03-16 02:00:44 +00:00
public int compare ( Item i1 , Item i2 )
2014-12-28 04:10:54 +00:00
{
2016-03-16 02:00:44 +00:00
return i1 . getRegistryName ( ) . compareTo ( i2 . getRegistryName ( ) ) ;
2016-03-15 22:42:01 +00:00
}
2016-03-16 02:00:44 +00:00
} ) ;
ProgressBar itemBar = ProgressManager . push ( " ModelLoader: items " , items . size ( ) ) ;
for ( Item item : items )
{
itemBar . step ( item . getRegistryName ( ) ) ;
for ( String s : getVariantNames ( item ) )
2016-03-15 22:42:01 +00:00
{
2016-03-16 02:00:44 +00:00
ResourceLocation file = getItemLocation ( s ) ;
ModelResourceLocation memory = getInventoryVariant ( s ) ;
IModel model = ModelLoaderRegistry . getMissingModel ( ) ;
Exception exception = null ;
2016-03-15 22:42:01 +00:00
try
2015-02-04 06:45:23 +00:00
{
2016-03-16 02:00:44 +00:00
model = ModelLoaderRegistry . getModel ( file ) ;
2016-03-15 22:42:01 +00:00
}
2016-03-16 02:00:44 +00:00
catch ( Exception e )
2016-03-15 22:42:01 +00:00
{
2016-03-16 02:00:44 +00:00
// try blockstate json if the item model is missing
FMLLog . fine ( " Item json isn't found for ' " + memory + " ', trying to load the variant from the blockstate json " ) ;
try
{
model = ModelLoaderRegistry . getModel ( memory ) ;
}
catch ( Exception ex )
{
exception = new Exception ( " Could not load item model either from the normal location " + file + " or from the blockstate " , ex ) ;
}
}
stateModels . put ( memory , model ) ;
if ( exception ! = null )
{
storeException ( memory , exception ) ;
2015-06-16 23:03:10 +00:00
}
2016-01-16 22:51:50 +00:00
}
2014-12-28 04:10:54 +00:00
}
2016-01-06 19:53:34 +00:00
ProgressManager . pop ( itemBar ) ;
2015-12-15 21:19:04 +00:00
// replace vanilla bucket models if desired. done afterwards for performance reasons
if ( ForgeModContainer . replaceVanillaBucketModel )
{
2015-12-29 12:20:36 +00:00
// ensure the bucket model is loaded
if ( ! stateModels . containsKey ( ModelDynBucket . LOCATION ) )
{
// load forges blockstate json for it
2016-01-18 18:35:23 +00:00
try
{
registerVariant ( getModelBlockDefinition ( ModelDynBucket . LOCATION ) , ModelDynBucket . LOCATION ) ;
}
catch ( Exception exception )
{
FMLLog . getLogger ( ) . error ( " Could not load the forge bucket model from the blockstate " , exception ) ;
return ;
}
2015-12-29 12:20:36 +00:00
}
2015-12-15 21:19:04 +00:00
// empty bucket
for ( String s : getVariantNames ( Items . bucket ) )
{
2015-12-24 03:06:38 +00:00
ModelResourceLocation memory = getInventoryVariant ( s ) ;
2016-03-15 22:42:01 +00:00
IModel model = ModelLoaderRegistry . getModelOrMissing ( new ResourceLocation ( " forge " , " item/bucket " ) ) ;
2016-03-13 13:16:25 +00:00
// only on successful load, otherwise continue using the old model
if ( model ! = getMissingModel ( ) )
2015-12-15 21:19:04 +00:00
{
stateModels . put ( memory , model ) ;
}
}
setBucketModel ( Items . water_bucket ) ;
setBucketModel ( Items . lava_bucket ) ;
// milk bucket only replaced if some mod adds milk
if ( FluidRegistry . isFluidRegistered ( " milk " ) )
{
// can the milk be put into a bucket?
Fluid milk = FluidRegistry . getFluid ( " milk " ) ;
FluidStack milkStack = new FluidStack ( milk , FluidContainerRegistry . BUCKET_VOLUME ) ;
if ( FluidContainerRegistry . getContainerCapacity ( milkStack , new ItemStack ( Items . bucket ) ) = = FluidContainerRegistry . BUCKET_VOLUME )
{
setBucketModel ( Items . milk_bucket ) ;
}
}
else
{
// milk bucket if no milk fluid is present
for ( String s : getVariantNames ( Items . milk_bucket ) )
{
2015-12-24 03:06:38 +00:00
ModelResourceLocation memory = getInventoryVariant ( s ) ;
2016-03-15 22:42:01 +00:00
IModel model = ModelLoaderRegistry . getModelOrMissing ( new ResourceLocation ( " forge " , " item/bucket_milk " ) ) ;
2016-03-13 13:16:25 +00:00
// only on successful load, otherwise continue using the old model
if ( model ! = getMissingModel ( ) )
2015-12-15 21:19:04 +00:00
{
stateModels . put ( memory , model ) ;
}
}
}
}
}
private void setBucketModel ( Item item )
{
for ( String s : getVariantNames ( item ) )
{
2015-12-24 03:06:38 +00:00
ModelResourceLocation memory = getInventoryVariant ( s ) ;
2015-12-15 21:19:04 +00:00
IModel model = stateModels . get ( ModelDynBucket . LOCATION ) ;
2015-12-29 12:20:36 +00:00
if ( model ! = null )
{
stateModels . put ( memory , model ) ;
}
2015-12-15 21:19:04 +00:00
}
2014-12-28 04:10:54 +00:00
}
2016-03-16 02:17:33 +00:00
/ * *
* Hooked from ModelBakery , allows using MRLs that don ' t end with " inventory " for items .
* /
2015-12-24 03:06:38 +00:00
public static ModelResourceLocation getInventoryVariant ( String s )
{
if ( s . contains ( " # " ) )
{
return new ModelResourceLocation ( s ) ;
}
return new ModelResourceLocation ( s , " inventory " ) ;
}
2014-12-28 04:10:54 +00:00
@Override
protected ResourceLocation getModelLocation ( ResourceLocation model )
{
return new ResourceLocation ( model . getResourceDomain ( ) , model . getResourcePath ( ) + " .json " ) ;
}
2015-10-27 14:40:05 +00:00
2016-03-15 22:42:01 +00:00
private final class VanillaModelWrapper implements IRetexturableModel , IModelSimpleProperties , IModelUVLock , IAnimatedModel
2014-12-28 04:10:54 +00:00
{
private final ResourceLocation location ;
private final ModelBlock model ;
2016-03-05 23:51:39 +00:00
private final boolean uvlock ;
2016-01-01 15:15:48 +00:00
private final ModelBlockAnimation animation ;
2014-12-28 04:10:54 +00:00
2016-03-05 23:51:39 +00:00
public VanillaModelWrapper ( ResourceLocation location , ModelBlock model , boolean uvlock , ModelBlockAnimation animation )
2014-12-28 04:10:54 +00:00
{
this . location = location ;
this . model = model ;
2016-03-05 23:51:39 +00:00
this . uvlock = uvlock ;
2016-01-01 15:15:48 +00:00
this . animation = animation ;
2014-12-28 04:10:54 +00:00
}
public Collection < ResourceLocation > getDependencies ( )
{
2016-03-13 09:10:50 +00:00
Set < ResourceLocation > set = Sets . newHashSet ( ) ;
2016-03-13 13:16:25 +00:00
for ( ResourceLocation dep : model . getOverrideLocations ( ) )
{
if ( ! location . equals ( dep ) )
{
set . add ( dep ) ;
// TODO: check if this can go somewhere else, random access to global things is bad
2016-03-15 22:42:01 +00:00
stateModels . put ( getInventoryVariant ( dep . toString ( ) ) , ModelLoaderRegistry . getModelOrLogError ( dep , " Could not load override model " + dep + " for model " + location ) ) ;
2016-03-13 13:16:25 +00:00
}
}
2016-03-13 09:10:50 +00:00
if ( model . getParentLocation ( ) ! = null & & ! model . getParentLocation ( ) . getResourcePath ( ) . startsWith ( " builtin/ " ) )
{
set . add ( model . getParentLocation ( ) ) ;
}
return ImmutableSet . copyOf ( set ) ;
2014-12-28 04:10:54 +00:00
}
public Collection < ResourceLocation > getTextures ( )
{
// setting parent here to make textures resolve properly
if ( model . getParentLocation ( ) ! = null )
{
2015-10-27 15:34:25 +00:00
if ( model . getParentLocation ( ) . getResourcePath ( ) . equals ( " builtin/generated " ) )
2014-12-28 04:10:54 +00:00
{
2015-10-27 15:34:25 +00:00
model . parent = MODEL_GENERATED ;
2014-12-28 04:10:54 +00:00
}
2015-10-27 15:34:25 +00:00
else
2014-12-28 04:10:54 +00:00
{
2016-03-15 22:42:01 +00:00
IModel parent = ModelLoaderRegistry . getModelOrLogError ( model . getParentLocation ( ) , " Could not load vanilla model parent ' " + model . getParentLocation ( ) + " ' for ' " + model ) ;
2016-03-13 13:16:25 +00:00
if ( parent instanceof VanillaModelWrapper )
2015-06-16 23:03:10 +00:00
{
2016-03-13 13:16:25 +00:00
model . parent = ( ( VanillaModelWrapper ) parent ) . model ;
}
else
{
throw new IllegalStateException ( " vanilla model ' " + model + " ' can't have non-vanilla parent " ) ;
2015-06-16 23:03:10 +00:00
}
2014-12-28 04:10:54 +00:00
}
}
ImmutableSet . Builder < ResourceLocation > builder = ImmutableSet . builder ( ) ;
if ( hasItemModel ( model ) )
{
2016-02-22 00:53:26 +00:00
for ( String s : ItemModelGenerator . LAYERS )
2014-12-28 04:10:54 +00:00
{
String r = model . resolveTextureName ( s ) ;
ResourceLocation loc = new ResourceLocation ( r ) ;
if ( ! r . equals ( s ) )
{
builder . add ( loc ) ;
}
}
}
2016-02-22 00:53:26 +00:00
for ( String s : model . textures . values ( ) )
2014-12-28 04:10:54 +00:00
{
2015-02-08 12:24:30 +00:00
if ( ! s . startsWith ( " # " ) )
{
builder . add ( new ResourceLocation ( s ) ) ;
}
2014-12-28 04:10:54 +00:00
}
return builder . build ( ) ;
}
2016-03-05 23:51:39 +00:00
public IBakedModel bake ( IModelState state , final VertexFormat format , Function < ResourceLocation , TextureAtlasSprite > bakedTextureGetter )
2014-12-28 04:10:54 +00:00
{
if ( ! Attributes . moreSpecific ( format , Attributes . DEFAULT_BAKED_FORMAT ) )
{
throw new IllegalArgumentException ( " can't bake vanilla models to the format that doesn't fit into the default one: " + format ) ;
}
ModelBlock model = this . model ;
2015-12-03 19:38:08 +00:00
if ( model = = null ) return getMissingModel ( ) . bake ( getMissingModel ( ) . getDefaultState ( ) , format , bakedTextureGetter ) ;
List < TRSRTransformation > newTransforms = Lists . newArrayList ( ) ;
for ( int i = 0 ; i < model . getElements ( ) . size ( ) ; i + + )
{
2016-01-01 15:15:48 +00:00
BlockPart part = model . getElements ( ) . get ( i ) ;
newTransforms . add ( animation . getPartTransform ( state , part , i ) ) ;
2015-12-03 19:38:08 +00:00
}
2016-03-13 01:40:03 +00:00
ItemCameraTransforms transforms = model . getAllTransforms ( ) ;
2015-12-03 19:38:08 +00:00
Map < TransformType , TRSRTransformation > tMap = Maps . newHashMap ( ) ;
tMap . putAll ( IPerspectiveAwareModel . MapWrapper . getTransforms ( transforms ) ) ;
tMap . putAll ( IPerspectiveAwareModel . MapWrapper . getTransforms ( state ) ) ;
IModelState perState = new SimpleModelState ( ImmutableMap . copyOf ( tMap ) ) ;
2015-06-22 22:03:16 +00:00
if ( hasItemModel ( model ) )
{
return new ItemLayerModel ( model ) . bake ( perState , format , bakedTextureGetter ) ;
}
2016-03-13 01:40:03 +00:00
if ( isCustomRenderer ( model ) ) return new BuiltInModel ( transforms , model . createOverrides ( ) ) ;
2016-03-21 06:15:39 +00:00
return bakeNormal ( model , perState , state , newTransforms , format , bakedTextureGetter , uvlock ) ;
2015-06-23 13:52:42 +00:00
}
2016-03-21 06:15:39 +00:00
private IBakedModel bakeNormal ( ModelBlock model , IModelState perState , final IModelState modelState , List < TRSRTransformation > newTransforms , final VertexFormat format , final Function < ResourceLocation , TextureAtlasSprite > bakedTextureGetter , boolean uvLocked )
2015-06-23 13:52:42 +00:00
{
2016-03-21 06:15:39 +00:00
final TRSRTransformation baseState = modelState . apply ( Optional . < IModelPart > absent ( ) ) . or ( TRSRTransformation . identity ( ) ) ;
2015-06-23 13:52:42 +00:00
TextureAtlasSprite particle = bakedTextureGetter . apply ( new ResourceLocation ( model . resolveTextureName ( " particle " ) ) ) ;
2016-03-13 01:40:03 +00:00
SimpleBakedModel . Builder builder = ( new SimpleBakedModel . Builder ( model , model . createOverrides ( ) ) ) . setTexture ( particle ) ;
2015-12-03 19:38:08 +00:00
for ( int i = 0 ; i < model . getElements ( ) . size ( ) ; i + + )
2015-06-23 13:52:42 +00:00
{
2015-12-03 19:38:08 +00:00
BlockPart part = model . getElements ( ) . get ( i ) ;
2016-03-21 06:15:39 +00:00
TRSRTransformation transformation = baseState ;
2015-12-03 19:38:08 +00:00
if ( newTransforms . get ( i ) ! = null )
{
transformation = transformation . compose ( newTransforms . get ( i ) ) ;
2016-01-01 15:15:48 +00:00
BlockPartRotation rot = part . partRotation ;
if ( rot = = null ) rot = new BlockPartRotation ( new org . lwjgl . util . vector . Vector3f ( ) , EnumFacing . Axis . Y , 0 , false ) ;
part = new BlockPart ( part . positionFrom , part . positionTo , part . mapFaces , rot , part . shade ) ;
2015-12-03 19:38:08 +00:00
}
2016-02-22 00:53:26 +00:00
for ( Map . Entry < EnumFacing , BlockPartFace > e : part . mapFaces . entrySet ( ) )
2015-06-23 13:52:42 +00:00
{
TextureAtlasSprite textureatlassprite1 = bakedTextureGetter . apply ( new ResourceLocation ( model . resolveTextureName ( e . getValue ( ) . texture ) ) ) ;
2015-12-03 19:38:08 +00:00
if ( e . getValue ( ) . cullFace = = null | | ! TRSRTransformation . isInteger ( transformation . getMatrix ( ) ) )
2015-06-23 13:52:42 +00:00
{
2015-12-03 19:38:08 +00:00
builder . addGeneralQuad ( makeBakedQuad ( part , e . getValue ( ) , textureatlassprite1 , e . getKey ( ) , transformation , uvLocked ) ) ;
2015-06-23 13:52:42 +00:00
}
else
{
2016-03-21 06:15:39 +00:00
builder . addFaceQuad ( baseState . rotate ( e . getValue ( ) . cullFace ) , makeBakedQuad ( part , e . getValue ( ) , textureatlassprite1 , e . getKey ( ) , transformation , uvLocked ) ) ;
2015-06-23 13:52:42 +00:00
}
}
}
2016-03-05 23:51:39 +00:00
return new IPerspectiveAwareModel . MapWrapper ( builder . makeBakedModel ( ) , perState )
2016-01-01 15:15:48 +00:00
{
2016-03-21 06:15:39 +00:00
private final ItemOverrideList overrides = new AnimationItemOverrideList ( VanillaModelWrapper . this , modelState , format , bakedTextureGetter , super . getOverrides ( ) ) ;
2016-03-05 23:51:39 +00:00
@Override
2016-03-13 01:40:03 +00:00
public List < BakedQuad > getQuads ( IBlockState state , EnumFacing side , long rand )
2016-01-01 15:15:48 +00:00
{
2016-03-05 23:51:39 +00:00
if ( state instanceof IExtendedBlockState )
2016-01-01 15:15:48 +00:00
{
2016-03-05 23:51:39 +00:00
IExtendedBlockState exState = ( IExtendedBlockState ) state ;
if ( exState . getUnlistedNames ( ) . contains ( Properties . AnimationProperty ) )
{
IModelState newState = exState . getValue ( Properties . AnimationProperty ) ;
IExtendedBlockState newExState = exState . withProperty ( Properties . AnimationProperty , null ) ;
if ( newState ! = null )
{
2016-03-13 01:40:03 +00:00
return VanillaModelWrapper . this . bake ( new ModelStateComposition ( modelState , newState ) , format , bakedTextureGetter ) . getQuads ( newExState , side , rand ) ;
2016-03-05 23:51:39 +00:00
}
}
2016-01-01 15:15:48 +00:00
}
2016-03-13 01:40:03 +00:00
return super . getQuads ( state , side , rand ) ;
2016-03-05 23:51:39 +00:00
} ;
2016-03-21 06:15:39 +00:00
@Override
public ItemOverrideList getOverrides ( )
{
return overrides ;
}
2016-03-05 23:51:39 +00:00
} ;
2014-12-28 04:10:54 +00:00
}
2015-05-20 09:54:33 +00:00
@Override
2016-03-05 02:02:34 +00:00
public VanillaModelWrapper retexture ( ImmutableMap < String , String > textures )
2015-05-20 09:54:33 +00:00
{
if ( textures . isEmpty ( ) )
return this ;
2015-06-09 19:36:36 +00:00
2015-05-20 09:54:33 +00:00
List < BlockPart > elements = Lists . newArrayList ( ) ; //We have to duplicate this so we can edit it below.
2016-02-22 00:53:26 +00:00
for ( BlockPart part : this . model . getElements ( ) )
2015-05-20 09:54:33 +00:00
{
elements . add ( new BlockPart ( part . positionFrom , part . positionTo , Maps . newHashMap ( part . mapFaces ) , part . partRotation , part . shade ) ) ;
}
2016-02-22 00:53:26 +00:00
ModelBlock newModel = new ModelBlock ( this . model . getParentLocation ( ) , elements ,
2015-05-20 09:54:33 +00:00
Maps . newHashMap ( this . model . textures ) , this . model . isAmbientOcclusion ( ) , this . model . isGui3d ( ) , //New Textures man VERY IMPORTANT
2016-03-13 01:40:03 +00:00
model . getAllTransforms ( ) , Lists . newArrayList ( model . getOverrides ( ) ) ) ;
2016-02-22 00:53:26 +00:00
newModel . name = this . model . name ;
newModel . parent = this . model . parent ;
2015-05-20 09:54:33 +00:00
Set < String > removed = Sets . newHashSet ( ) ;
2015-06-09 19:36:36 +00:00
2015-05-20 09:54:33 +00:00
for ( Entry < String , String > e : textures . entrySet ( ) )
{
2015-06-09 19:36:36 +00:00
if ( " " . equals ( e . getValue ( ) ) )
2015-05-20 09:54:33 +00:00
{
removed . add ( e . getKey ( ) ) ;
2016-02-22 00:53:26 +00:00
newModel . textures . remove ( e . getKey ( ) ) ;
2015-05-20 09:54:33 +00:00
}
else
2016-02-22 00:53:26 +00:00
newModel . textures . put ( e . getKey ( ) , e . getValue ( ) ) ;
2015-05-20 09:54:33 +00:00
}
// Map the model's texture references as if it was the parent of a model with the retexture map as its textures.
Map < String , String > remapped = Maps . newHashMap ( ) ;
2015-06-09 19:36:36 +00:00
2016-02-22 00:53:26 +00:00
for ( Entry < String , String > e : newModel . textures . entrySet ( ) )
2015-05-20 09:54:33 +00:00
{
if ( e . getValue ( ) . startsWith ( " # " ) )
{
String key = e . getValue ( ) . substring ( 1 ) ;
2016-02-22 00:53:26 +00:00
if ( newModel . textures . containsKey ( key ) )
remapped . put ( e . getKey ( ) , newModel . textures . get ( key ) ) ;
2015-05-20 09:54:33 +00:00
}
}
2015-06-09 19:36:36 +00:00
2016-02-22 00:53:26 +00:00
newModel . textures . putAll ( remapped ) ;
2015-06-09 19:36:36 +00:00
2015-05-20 09:54:33 +00:00
//Remove any faces that use a null texture, this is for performance reasons, also allows some cool layering stuff.
2016-02-22 00:53:26 +00:00
for ( BlockPart part : newModel . getElements ( ) )
2015-05-20 09:54:33 +00:00
{
Iterator < Entry < EnumFacing , BlockPartFace > > itr = part . mapFaces . entrySet ( ) . iterator ( ) ;
while ( itr . hasNext ( ) )
{
Entry < EnumFacing , BlockPartFace > entry = itr . next ( ) ;
if ( removed . contains ( entry . getValue ( ) . texture ) )
itr . remove ( ) ;
}
}
2016-03-05 23:51:39 +00:00
return new VanillaModelWrapper ( location , newModel , uvlock , animation ) ;
2016-01-01 15:15:48 +00:00
}
@Override
public Optional < ? extends IClip > getClip ( String name )
{
if ( animation . getClips ( ) . containsKey ( name ) )
{
return Optional . < IClip > fromNullable ( animation . getClips ( ) . get ( name ) ) ;
}
return Optional . absent ( ) ;
2015-05-20 09:54:33 +00:00
}
2015-12-03 19:38:08 +00:00
public IModelState getDefaultState ( )
{
return ModelRotation . X0_Y0 ;
}
2016-02-02 09:22:06 +00:00
@Override
public VanillaModelWrapper smoothLighting ( boolean value )
{
if ( model . ambientOcclusion = = value )
{
return this ;
}
2016-03-13 01:40:03 +00:00
ModelBlock newModel = new ModelBlock ( model . getParentLocation ( ) , model . getElements ( ) , model . textures , value , model . isGui3d ( ) , model . getAllTransforms ( ) , Lists . newArrayList ( model . getOverrides ( ) ) ) ;
2016-02-02 09:22:06 +00:00
newModel . parent = model . parent ;
newModel . name = model . name ;
2016-03-05 23:51:39 +00:00
return new VanillaModelWrapper ( location , newModel , uvlock , animation ) ;
2016-02-02 09:22:06 +00:00
}
@Override
public VanillaModelWrapper gui3d ( boolean value )
{
if ( model . isGui3d ( ) = = value )
{
return this ;
}
2016-03-13 01:40:03 +00:00
ModelBlock newModel = new ModelBlock ( model . getParentLocation ( ) , model . getElements ( ) , model . textures , model . ambientOcclusion , value , model . getAllTransforms ( ) , Lists . newArrayList ( model . getOverrides ( ) ) ) ;
2016-02-02 09:22:06 +00:00
newModel . parent = model . parent ;
newModel . name = model . name ;
2016-03-05 23:51:39 +00:00
return new VanillaModelWrapper ( location , newModel , uvlock , animation ) ;
2015-02-03 07:33:32 +00:00
}
2016-03-05 23:51:39 +00:00
@Override
public IModel uvlock ( boolean value )
2015-02-03 07:33:32 +00:00
{
2016-03-05 23:51:39 +00:00
if ( uvlock = = value )
{
return this ;
}
return new VanillaModelWrapper ( location , model , value , animation ) ;
2015-02-03 07:33:32 +00:00
}
}
2016-03-15 22:42:01 +00:00
private static final class WeightedRandomModel implements IModel
2014-12-28 04:10:54 +00:00
{
private final List < Variant > variants ;
private final List < ResourceLocation > locations = new ArrayList < ResourceLocation > ( ) ;
2016-03-13 13:16:25 +00:00
private final Set < ResourceLocation > textures = Sets . newHashSet ( ) ;
2014-12-28 04:10:54 +00:00
private final List < IModel > models = new ArrayList < IModel > ( ) ;
private final IModelState defaultState ;
2016-03-15 22:42:01 +00:00
public WeightedRandomModel ( ResourceLocation parent , VariantList variants ) throws Exception
2014-12-28 04:10:54 +00:00
{
2016-03-13 01:40:03 +00:00
this . variants = variants . getVariantList ( ) ;
2016-01-06 19:00:43 +00:00
ImmutableList . Builder < Pair < IModel , IModelState > > builder = ImmutableList . builder ( ) ;
2016-03-05 02:02:34 +00:00
for ( Variant v : this . variants )
2014-12-28 04:10:54 +00:00
{
2016-03-13 01:40:03 +00:00
ResourceLocation loc = v . getModelLocation ( ) ;
2014-12-28 04:10:54 +00:00
locations . add ( loc ) ;
2015-05-20 09:54:33 +00:00
2016-03-15 22:42:01 +00:00
/ *
* Vanilla eats this , which makes it only show variants that have models .
* But that doesn ' t help debugging , so throw the exception
* /
IModel model = ModelLoaderRegistry . getModel ( loc ) ;
2015-06-16 23:03:10 +00:00
2016-03-13 13:16:25 +00:00
// FIXME: is this the place? messes up dependency and texture resolution
2015-05-20 09:54:33 +00:00
if ( v instanceof ISmartVariant )
{
2016-03-13 13:16:25 +00:00
model = ( ( ISmartVariant ) v ) . process ( model ) ;
for ( ResourceLocation location : model . getDependencies ( ) )
2015-12-17 01:40:34 +00:00
{
2016-03-15 22:42:01 +00:00
ModelLoaderRegistry . getModelOrMissing ( location ) ;
2015-12-17 01:40:34 +00:00
}
2016-03-13 13:16:25 +00:00
//FMLLog.getLogger().error("Exception resolving indirect dependencies for model" + loc, e);
2015-05-20 09:54:33 +00:00
textures . addAll ( model . getTextures ( ) ) ; // Kick this, just in case.
}
2014-12-28 04:10:54 +00:00
models . add ( model ) ;
2016-01-06 19:00:43 +00:00
builder . add ( Pair . of ( model , v . getState ( ) ) ) ;
2014-12-28 04:10:54 +00:00
}
2015-06-16 23:03:10 +00:00
if ( models . size ( ) = = 0 ) //If all variants are missing, add one with the missing model and default rotation.
{
2016-03-15 22:42:01 +00:00
// FIXME: log this?
2016-03-13 13:16:25 +00:00
IModel missing = ModelLoaderRegistry . getMissingModel ( ) ;
2015-06-16 23:03:10 +00:00
models . add ( missing ) ;
2016-01-06 19:00:43 +00:00
builder . add ( Pair . < IModel , IModelState > of ( missing , TRSRTransformation . identity ( ) ) ) ;
2015-06-16 23:03:10 +00:00
}
2016-01-06 19:00:43 +00:00
defaultState = new MultiModelState ( builder . build ( ) ) ;
2014-12-28 04:10:54 +00:00
}
public Collection < ResourceLocation > getDependencies ( )
{
return ImmutableList . copyOf ( locations ) ;
}
public Collection < ResourceLocation > getTextures ( )
{
2016-03-13 13:16:25 +00:00
return ImmutableSet . copyOf ( textures ) ;
2014-12-28 04:10:54 +00:00
}
2016-03-05 02:02:34 +00:00
public IBakedModel bake ( IModelState state , VertexFormat format , Function < ResourceLocation , TextureAtlasSprite > bakedTextureGetter )
2014-12-28 04:10:54 +00:00
{
if ( ! Attributes . moreSpecific ( format , Attributes . DEFAULT_BAKED_FORMAT ) )
{
throw new IllegalArgumentException ( " can't bake vanilla weighted models to the format that doesn't fit into the default one: " + format ) ;
}
if ( variants . size ( ) = = 1 )
{
IModel model = models . get ( 0 ) ;
2016-03-05 23:51:39 +00:00
return model . bake ( MultiModelState . getPartState ( state , model , 0 ) , format , bakedTextureGetter ) ;
2014-12-28 04:10:54 +00:00
}
WeightedBakedModel . Builder builder = new WeightedBakedModel . Builder ( ) ;
for ( int i = 0 ; i < variants . size ( ) ; i + + )
{
IModel model = models . get ( i ) ;
2016-03-13 01:40:03 +00:00
builder . add ( model . bake ( MultiModelState . getPartState ( state , model , i ) , format , bakedTextureGetter ) , variants . get ( i ) . getWeight ( ) ) ;
2014-12-28 04:10:54 +00:00
}
2016-03-05 02:02:34 +00:00
return builder . build ( ) ;
2014-12-28 04:10:54 +00:00
}
public IModelState getDefaultState ( )
{
return defaultState ;
}
}
2016-03-16 02:17:33 +00:00
protected IModel getMissingModel ( )
2014-12-28 04:10:54 +00:00
{
2015-06-16 23:03:10 +00:00
if ( missingModel = = null )
{
2016-03-15 22:42:01 +00:00
try
{
missingModel = VanillaLoader . instance . loadModel ( new ResourceLocation ( MODEL_MISSING . getResourceDomain ( ) , MODEL_MISSING . getResourcePath ( ) ) ) ;
}
catch ( Exception e )
{
throw new RuntimeException ( " Missing the missing model, this should never happen " ) ;
}
2015-06-16 23:03:10 +00:00
}
return missingModel ;
2014-12-28 04:10:54 +00:00
}
2016-03-15 22:42:01 +00:00
protected static enum VanillaLoader implements ICustomModelLoader
2014-12-28 04:10:54 +00:00
{
instance ;
private ModelLoader loader ;
void setLoader ( ModelLoader loader )
{
this . loader = loader ;
}
ModelLoader getLoader ( )
{
return loader ;
}
2016-03-16 02:17:33 +00:00
// NOOP, handled in loader
public void onResourceManagerReload ( IResourceManager resourceManager ) { }
2014-12-28 04:10:54 +00:00
public boolean accepts ( ResourceLocation modelLocation )
{
return true ;
}
2016-03-15 22:42:01 +00:00
public IModel loadModel ( ResourceLocation modelLocation ) throws Exception
2014-12-28 04:10:54 +00:00
{
2016-01-01 15:15:48 +00:00
String modelPath = modelLocation . getResourcePath ( ) ;
if ( modelLocation . getResourcePath ( ) . startsWith ( " models/ " ) )
{
modelPath = modelPath . substring ( " models/ " . length ( ) ) ;
}
ResourceLocation armatureLocation = new ResourceLocation ( modelLocation . getResourceDomain ( ) , " armatures/ " + modelPath + " .json " ) ;
2016-03-21 07:01:30 +00:00
ModelBlockAnimation animation = ModelBlockAnimation . loadVanillaAnimation ( loader . resourceManager , armatureLocation ) ;
2016-03-15 22:42:01 +00:00
ModelBlock model = loader . loadModel ( modelLocation ) ;
return loader . new VanillaModelWrapper ( modelLocation , model , false , animation ) ;
2016-03-13 13:16:25 +00:00
}
@Override
public String toString ( )
{
return " VanillaLoader.instance " ;
2014-12-28 04:10:54 +00:00
}
}
2015-02-04 06:45:23 +00:00
2016-03-16 02:17:33 +00:00
/ * *
* 16x16 pure white sprite .
* /
2016-03-15 22:42:01 +00:00
public static final class White extends TextureAtlasSprite
2015-02-17 00:36:08 +00:00
{
public static ResourceLocation loc = new ResourceLocation ( " white " ) ;
public static White instance = new White ( ) ;
2016-03-16 02:17:33 +00:00
private White ( )
2015-02-17 00:36:08 +00:00
{
super ( loc . toString ( ) ) ;
}
@Override
public boolean hasCustomLoader ( IResourceManager manager , ResourceLocation location )
{
return true ;
}
@Override
public boolean load ( IResourceManager manager , ResourceLocation location )
{
2015-04-01 13:06:03 +00:00
BufferedImage image = new BufferedImage ( 16 , 16 , BufferedImage . TYPE_INT_ARGB ) ;
Graphics2D graphics = image . createGraphics ( ) ;
graphics . setBackground ( Color . WHITE ) ;
graphics . clearRect ( 0 , 0 , 16 , 16 ) ;
2016-03-05 23:51:39 +00:00
int [ ] [ ] pixels = new int [ Minecraft . getMinecraft ( ) . gameSettings . mipmapLevels + 1 ] [ ] ;
pixels [ 0 ] = new int [ image . getWidth ( ) * image . getHeight ( ) ] ;
image . getRGB ( 0 , 0 , image . getWidth ( ) , image . getHeight ( ) , pixels [ 0 ] , 0 , image . getWidth ( ) ) ;
2016-03-15 22:42:01 +00:00
this . clearFramesTextureData ( ) ;
2016-03-05 23:51:39 +00:00
this . framesTextureData . add ( pixels ) ;
2015-02-17 00:36:08 +00:00
return false ;
}
2015-02-17 18:20:14 +00:00
public void register ( TextureMap map )
2015-02-17 00:36:08 +00:00
{
2015-02-17 18:20:14 +00:00
map . setTextureEntry ( White . loc . toString ( ) , White . instance ) ;
2015-02-17 00:36:08 +00:00
}
}
2016-03-16 02:17:33 +00:00
/ * *
* Internal , do not use .
* /
2015-11-13 14:23:37 +00:00
public void onPostBakeEvent ( IRegistry < ModelResourceLocation , IBakedModel > modelRegistry )
2015-02-04 06:45:23 +00:00
{
2015-11-13 14:23:37 +00:00
IBakedModel missingModel = modelRegistry . getObject ( MODEL_MISSING ) ;
2016-01-19 22:19:38 +00:00
Map < String , Integer > modelErrors = Maps . newHashMap ( ) ;
2016-02-22 00:53:26 +00:00
Multimap < ModelResourceLocation , IBlockState > reverseBlockMap = null ;
Multimap < ModelResourceLocation , String > reverseItemMap = null ;
if ( enableVerboseMissingInfo )
{
reverseBlockMap = HashMultimap . create ( ) ;
for ( Map . Entry < IBlockState , ModelResourceLocation > entry : blockModelShapes . getBlockStateMapper ( ) . putAllStateModelLocations ( ) . entrySet ( ) )
{
reverseBlockMap . put ( entry . getValue ( ) , entry . getKey ( ) ) ;
}
reverseItemMap = HashMultimap . create ( ) ;
for ( Item item : GameData . getItemRegistry ( ) . typeSafeIterable ( ) )
{
for ( String s : getVariantNames ( item ) )
{
ModelResourceLocation memory = getInventoryVariant ( s ) ;
reverseItemMap . put ( memory , item . getRegistryName ( ) ) ;
}
}
}
2016-01-19 22:19:38 +00:00
for ( Map . Entry < ResourceLocation , Exception > entry : loadingExceptions . entrySet ( ) )
2016-01-16 22:51:50 +00:00
{
2016-01-19 22:19:38 +00:00
// ignoring pure ResourceLocation arguments, all things we care about pass ModelResourceLocation
if ( entry . getKey ( ) instanceof ModelResourceLocation )
2016-01-16 22:51:50 +00:00
{
2016-01-19 22:19:38 +00:00
ModelResourceLocation location = ( ModelResourceLocation ) entry . getKey ( ) ;
IBakedModel model = modelRegistry . getObject ( location ) ;
if ( model = = null | | model = = missingModel )
{
String domain = entry . getKey ( ) . getResourceDomain ( ) ;
Integer errorCountBox = modelErrors . get ( domain ) ;
int errorCount = errorCountBox = = null ? 0 : errorCountBox ;
errorCount + + ;
if ( errorCount < 5 )
{
2016-02-22 00:53:26 +00:00
String errorMsg = " Exception loading model for variant " + entry . getKey ( ) ;
if ( enableVerboseMissingInfo )
{
Collection < IBlockState > blocks = reverseBlockMap . get ( location ) ;
if ( ! blocks . isEmpty ( ) )
{
if ( blocks . size ( ) = = 1 )
{
errorMsg + = " for blockstate \" " + blocks . iterator ( ) . next ( ) + " \" " ;
}
else
{
errorMsg + = " for blockstates [ \" " + Joiner . on ( " \" , \" " ) . join ( blocks ) + " \" ] " ;
}
}
Collection < String > items = reverseItemMap . get ( location ) ;
if ( ! items . isEmpty ( ) )
{
if ( ! blocks . isEmpty ( ) ) errorMsg + = " and " ;
if ( items . size ( ) = = 1 )
{
errorMsg + = " for item \" " + items . iterator ( ) . next ( ) + " \" " ;
}
else
{
errorMsg + = " for items [ \" " + Joiner . on ( " \" , \" " ) . join ( items ) + " \" ] " ;
}
}
}
FMLLog . getLogger ( ) . error ( errorMsg , entry . getValue ( ) ) ;
2016-01-19 22:19:38 +00:00
}
modelErrors . put ( domain , errorCount ) ;
}
if ( model = = null )
{
modelRegistry . putObject ( location , missingModel ) ;
}
2016-01-16 22:51:50 +00:00
}
}
2015-02-04 06:45:23 +00:00
for ( ModelResourceLocation missing : missingVariants )
{
2015-11-13 14:23:37 +00:00
IBakedModel model = modelRegistry . getObject ( missing ) ;
2015-06-04 15:07:03 +00:00
if ( model = = null | | model = = missingModel )
2015-02-04 06:45:23 +00:00
{
2016-01-19 22:19:38 +00:00
String domain = missing . getResourceDomain ( ) ;
Integer errorCountBox = modelErrors . get ( domain ) ;
int errorCount = errorCountBox = = null ? 0 : errorCountBox ;
errorCount + + ;
if ( errorCount < 5 )
{
FMLLog . severe ( " Model definition for location %s not found " , missing ) ;
}
modelErrors . put ( domain , errorCount ) ;
2015-02-04 06:45:23 +00:00
}
2016-01-16 22:51:50 +00:00
if ( model = = null )
{
modelRegistry . putObject ( missing , missingModel ) ;
}
2015-02-04 06:45:23 +00:00
}
2016-01-19 22:19:38 +00:00
for ( Map . Entry < String , Integer > e : modelErrors . entrySet ( ) )
{
if ( e . getValue ( ) > = 5 )
{
2016-02-22 00:53:26 +00:00
FMLLog . severe ( " Suppressed additional %s model loading errors for domain %s " , e . getValue ( ) , e . getKey ( ) ) ;
2016-01-19 22:19:38 +00:00
}
}
2015-02-04 06:45:23 +00:00
isLoading = false ;
}
private static final Map < RegistryDelegate < Block > , IStateMapper > customStateMappers = Maps . newHashMap ( ) ;
2015-12-24 03:06:38 +00:00
/ * *
* Adds a custom IBlockState - > model variant logic .
* /
2015-02-04 06:45:23 +00:00
public static void setCustomStateMapper ( Block block , IStateMapper mapper )
{
customStateMappers . put ( block . delegate , mapper ) ;
}
2016-03-16 02:17:33 +00:00
/ * *
* Internal , do not use .
* /
2015-02-04 06:45:23 +00:00
public static void onRegisterAllBlocks ( BlockModelShapes shapes )
{
for ( Entry < RegistryDelegate < Block > , IStateMapper > e : customStateMappers . entrySet ( ) )
{
shapes . registerBlockWithStateMapper ( e . getKey ( ) . get ( ) , e . getValue ( ) ) ;
}
}
private static final Map < RegistryDelegate < Item > , ItemMeshDefinition > customMeshDefinitions = com . google . common . collect . Maps . newHashMap ( ) ;
2015-02-09 14:18:18 +00:00
private static final Map < Pair < RegistryDelegate < Item > , Integer > , ModelResourceLocation > customModels = com . google . common . collect . Maps . newHashMap ( ) ;
2015-02-04 06:45:23 +00:00
2015-12-24 03:06:38 +00:00
/ * *
* Adds a simple mapping from Item + metadata to the model variant .
* Registers the variant with the ModelBakery too .
* /
2015-02-04 06:45:23 +00:00
public static void setCustomModelResourceLocation ( Item item , int metadata , ModelResourceLocation model )
{
2015-02-09 14:18:18 +00:00
customModels . put ( Pair . of ( item . delegate , metadata ) , model ) ;
2015-12-24 03:06:38 +00:00
ModelBakery . registerItemVariants ( item , model ) ;
2015-02-04 06:45:23 +00:00
}
2015-12-24 03:06:38 +00:00
/ * *
* Adds generic ItemStack - > model variant logic .
* You still need to manually call ModelBakery . registerItemVariants with all values that meshDefinition can return .
* /
2015-02-04 06:45:23 +00:00
public static void setCustomMeshDefinition ( Item item , ItemMeshDefinition meshDefinition )
{
customMeshDefinitions . put ( item . delegate , meshDefinition ) ;
}
2016-03-16 02:17:33 +00:00
/ * *
* Helper method for registering all itemstacks for given item to map to universal bucket model .
* /
2015-12-29 12:20:36 +00:00
public static void setBucketModelDefinition ( Item item ) {
ModelLoader . setCustomMeshDefinition ( item , new ItemMeshDefinition ( )
{
@Override
public ModelResourceLocation getModelLocation ( ItemStack stack )
{
return ModelDynBucket . LOCATION ;
}
} ) ;
ModelBakery . registerItemVariants ( item , ModelDynBucket . LOCATION ) ;
}
2016-03-16 02:17:33 +00:00
/ * *
* Internal , do not use .
* /
2015-02-04 06:45:23 +00:00
public static void onRegisterItems ( ItemModelMesher mesher )
{
for ( Map . Entry < RegistryDelegate < Item > , ItemMeshDefinition > e : customMeshDefinitions . entrySet ( ) )
{
mesher . register ( e . getKey ( ) . get ( ) , e . getValue ( ) ) ;
}
2015-02-09 14:18:18 +00:00
for ( Entry < Pair < RegistryDelegate < Item > , Integer > , ModelResourceLocation > e : customModels . entrySet ( ) )
2015-02-04 06:45:23 +00:00
{
2015-02-09 14:18:18 +00:00
mesher . register ( e . getKey ( ) . getLeft ( ) . get ( ) , e . getKey ( ) . getRight ( ) , e . getValue ( ) ) ;
2015-02-04 06:45:23 +00:00
}
}
2016-01-01 15:15:48 +00:00
private static enum DefaultTextureGetter implements Function < ResourceLocation , TextureAtlasSprite >
{
instance ;
public TextureAtlasSprite apply ( ResourceLocation location )
{
return Minecraft . getMinecraft ( ) . getTextureMapBlocks ( ) . getAtlasSprite ( location . toString ( ) ) ;
}
}
2016-03-16 02:17:33 +00:00
/ * *
* Get the default texture getter the models will be baked with .
* /
2016-01-01 15:15:48 +00:00
public static Function < ResourceLocation , TextureAtlasSprite > defaultTextureGetter ( )
{
return DefaultTextureGetter . instance ;
}
2016-03-13 13:16:25 +00:00
protected static enum VariantLoader implements ICustomModelLoader
{
instance ;
private ModelLoader loader ;
void setLoader ( ModelLoader loader )
{
this . loader = loader ;
}
2016-03-16 02:17:33 +00:00
// NOOP, handled in loader
2016-03-13 13:16:25 +00:00
@Override
2016-03-16 02:17:33 +00:00
public void onResourceManagerReload ( IResourceManager resourceManager ) { }
2016-03-13 13:16:25 +00:00
@Override
public boolean accepts ( ResourceLocation modelLocation )
{
return modelLocation instanceof ModelResourceLocation ;
}
@Override
2016-03-15 22:42:01 +00:00
public IModel loadModel ( ResourceLocation modelLocation ) throws Exception
2016-03-13 13:16:25 +00:00
{
ModelResourceLocation variant = ( ModelResourceLocation ) modelLocation ;
ModelBlockDefinition definition = loader . getModelBlockDefinition ( variant ) ;
try
{
VariantList variants = definition . getVariant ( variant . getVariant ( ) ) ;
return new WeightedRandomModel ( variant , variants ) ;
}
catch ( MissingVariantException e )
{
if ( definition . hasMultipartData ( ) )
{
return new MultipartModel ( new ResourceLocation ( variant . getResourceDomain ( ) , variant . getResourcePath ( ) ) , definition . getMultipartData ( ) ) ;
}
2016-03-15 22:42:01 +00:00
throw e ;
2016-03-13 13:16:25 +00:00
}
}
@Override
public String toString ( )
{
return " VariantLoader.instance " ;
}
}
private static class MultipartModel implements IModel
{
private final ResourceLocation location ;
private final Multipart multipart ;
private final ImmutableMap < Selector , IModel > partModels ;
2016-03-15 22:42:01 +00:00
public MultipartModel ( ResourceLocation location , Multipart multipart ) throws Exception
2016-03-13 13:16:25 +00:00
{
this . location = location ;
this . multipart = multipart ;
ImmutableMap . Builder < Selector , IModel > builder = ImmutableMap . builder ( ) ;
for ( Selector selector : multipart . getSelectors ( ) )
{
builder . put ( selector , new WeightedRandomModel ( location , selector . getVariantList ( ) ) ) ;
}
partModels = builder . build ( ) ;
}
// FIXME: represent selectors as dependencies?
@Override
public Collection < ResourceLocation > getDependencies ( )
{
return ImmutableSet . of ( ) ;
}
@Override
public Collection < ResourceLocation > getTextures ( )
{
return ImmutableSet . of ( ) ;
}
// FIXME
@Override
public IBakedModel bake ( IModelState state , VertexFormat format , Function < ResourceLocation , TextureAtlasSprite > bakedTextureGetter )
{
MultipartBakedModel . Builder builder = new MultipartBakedModel . Builder ( ) ;
for ( Selector selector : multipart . getSelectors ( ) )
{
builder . putModel ( selector . getPredicate ( multipart . getStateContainer ( ) ) , partModels . get ( selector ) . bake ( partModels . get ( selector ) . getDefaultState ( ) , format , bakedTextureGetter ) ) ;
}
IBakedModel bakedModel = builder . makeMultipartModel ( ) ;
return bakedModel ;
}
@Override
public IModelState getDefaultState ( )
{
return TRSRTransformation . identity ( ) ;
}
}
2014-12-28 04:10:54 +00:00
}