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.io.IOException ;
import java.util.ArrayList ;
2015-02-17 00:36:08 +00:00
import java.util.Arrays ;
2014-12-28 04:10:54 +00:00
import java.util.Collection ;
import java.util.Collections ;
import java.util.HashMap ;
import java.util.HashSet ;
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 ;
2015-05-20 09:54:33 +00:00
import net.minecraft.client.renderer.block.model.BlockPart ;
import net.minecraft.client.renderer.block.model.BlockPartFace ;
2014-12-28 04:10:54 +00:00
import net.minecraft.client.renderer.block.model.ItemCameraTransforms ;
import net.minecraft.client.renderer.block.model.ItemModelGenerator ;
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 ;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition.Variant ;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition.Variants ;
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 ;
import net.minecraft.client.renderer.vertex.VertexFormat ;
import net.minecraft.client.resources.IResourceManager ;
import net.minecraft.client.resources.model.BuiltInModel ;
import net.minecraft.client.resources.model.ModelBakery ;
import net.minecraft.client.resources.model.ModelResourceLocation ;
import net.minecraft.client.resources.model.ModelRotation ;
2015-06-23 13:52:42 +00:00
import net.minecraft.client.resources.model.SimpleBakedModel ;
2014-12-28 04:10:54 +00:00
import net.minecraft.client.resources.model.WeightedBakedModel ;
import net.minecraft.item.Item ;
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.IRegistry ;
import net.minecraft.util.ResourceLocation ;
2015-02-17 00:36:08 +00:00
import net.minecraftforge.client.event.TextureStitchEvent ;
import net.minecraftforge.common.MinecraftForge ;
2014-12-28 04:10:54 +00:00
import net.minecraftforge.fml.common.FMLLog ;
2015-02-17 00:36:08 +00:00
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent ;
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 org.apache.logging.log4j.Level ;
import com.google.common.base.Function ;
import com.google.common.base.Functions ;
2015-06-16 23:03:10 +00:00
import com.google.common.base.Throwables ;
2014-12-28 04:10:54 +00:00
import com.google.common.collect.ImmutableList ;
import com.google.common.collect.ImmutableMap ;
import com.google.common.collect.ImmutableSet ;
import com.google.common.collect.Lists ;
2015-02-04 06:45:23 +00:00
import com.google.common.collect.Maps ;
import com.google.common.collect.Sets ;
2014-12-28 04:10:54 +00:00
public class ModelLoader extends ModelBakery
{
private final Map < ModelResourceLocation , IModel > stateModels = new HashMap < ModelResourceLocation , IModel > ( ) ;
private final Set < ResourceLocation > textures = new HashSet < ResourceLocation > ( ) ;
private final Set < ResourceLocation > loadingModels = new HashSet < ResourceLocation > ( ) ;
2015-02-04 06:45:23 +00:00
private final Set < ModelResourceLocation > missingVariants = Sets . newHashSet ( ) ;
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
public ModelLoader ( IResourceManager manager , TextureMap map , BlockModelShapes shapes )
{
super ( manager , map , shapes ) ;
VanillaLoader . instance . setLoader ( this ) ;
ModelLoaderRegistry . clearModelCache ( ) ;
}
@Override
public IRegistry setupModelRegistry ( )
{
2015-02-04 06:45:23 +00:00
isLoading = true ;
2014-12-28 04:10:54 +00:00
loadBlocks ( ) ;
loadItems ( ) ;
2015-06-16 23:03:10 +00:00
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 ) ;
2014-12-28 04:10:54 +00:00
textures . remove ( TextureMap . LOCATION_MISSING_TEXTURE ) ;
textures . addAll ( LOCATIONS_BUILTIN_TEXTURES ) ;
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
}
}
} ) ;
2015-06-18 11:14:46 +00:00
Function < ResourceLocation , TextureAtlasSprite > textureGetter = new Function < ResourceLocation , TextureAtlasSprite > ( )
{
public TextureAtlasSprite apply ( ResourceLocation location )
{
return Minecraft . getMinecraft ( ) . getTextureMapBlocks ( ) . getAtlasSprite ( location . toString ( ) ) ;
}
} ;
2015-06-16 23:03:10 +00:00
IFlexibleBakedModel missingBaked = missingModel . bake ( missingModel . getDefaultState ( ) , Attributes . DEFAULT_BAKED_FORMAT , textureGetter ) ;
for ( Entry < ModelResourceLocation , IModel > e : stateModels . entrySet ( ) )
2014-12-28 04:10:54 +00:00
{
2015-06-04 15:07:03 +00:00
if ( e . getValue ( ) = = getMissingModel ( ) )
{
bakedRegistry . putObject ( e . getKey ( ) , missingBaked ) ;
}
else
{
bakedRegistry . putObject ( e . getKey ( ) , e . getValue ( ) . bake ( e . getValue ( ) . getDefaultState ( ) , Attributes . DEFAULT_BAKED_FORMAT , textureGetter ) ) ;
}
2014-12-28 04:10:54 +00:00
}
return bakedRegistry ;
}
private void loadBlocks ( )
{
Map < IBlockState , ModelResourceLocation > stateMap = blockModelShapes . getBlockStateMapper ( ) . putAllStateModelLocations ( ) ;
2015-02-02 21:06:57 +00:00
Collection < ModelResourceLocation > variants = Lists . newArrayList ( stateMap . values ( ) ) ;
variants . add ( new ModelResourceLocation ( " minecraft:item_frame " , " normal " ) ) ; //Vanilla special cases item_frames so must we
variants . add ( new ModelResourceLocation ( " minecraft:item_frame " , " map " ) ) ;
loadVariants ( variants ) ;
2014-12-28 04:10:54 +00:00
}
@Override
protected void registerVariant ( ModelBlockDefinition definition , ModelResourceLocation location )
{
Variants variants = null ;
try
{
variants = definition . getVariants ( location . getVariant ( ) ) ;
}
2015-02-04 06:45:23 +00:00
catch ( MissingVariantException e )
2014-12-28 04:10:54 +00:00
{
2015-02-04 06:45:23 +00:00
missingVariants . add ( location ) ;
2014-12-28 04:10:54 +00:00
}
2015-06-16 23:03:10 +00:00
if ( variants ! = null & & ! variants . getVariants ( ) . isEmpty ( ) )
2014-12-28 04:10:54 +00:00
{
try
{
2015-06-16 23:03:10 +00:00
stateModels . put ( location , new WeightedRandomModel ( location , variants ) ) ;
2014-12-28 04:10:54 +00:00
}
catch ( Throwable e )
{
throw new RuntimeException ( e ) ;
}
}
}
private void loadItems ( )
{
registerVariantNames ( ) ;
for ( Item item : GameData . getItemRegistry ( ) . typeSafeIterable ( ) )
{
for ( String s : ( List < String > ) getVariantNames ( item ) )
{
ResourceLocation file = getItemLocation ( s ) ;
ModelResourceLocation memory = new ModelResourceLocation ( s , " inventory " ) ;
2015-06-16 23:03:10 +00:00
IModel model = null ;
try
2015-02-04 06:45:23 +00:00
{
2015-06-16 23:03:10 +00:00
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 ) ;
2015-02-04 06:45:23 +00:00
}
2014-12-28 04:10:54 +00:00
}
}
}
2015-06-16 23:03:10 +00:00
public IModel getModel ( ResourceLocation location ) throws IOException
2014-12-28 04:10:54 +00:00
{
if ( ! ModelLoaderRegistry . loaded ( location ) ) loadAnyModel ( location ) ;
return ModelLoaderRegistry . getModel ( location ) ;
}
@Override
protected ResourceLocation getModelLocation ( ResourceLocation model )
{
return new ResourceLocation ( model . getResourceDomain ( ) , model . getResourcePath ( ) + " .json " ) ;
}
2015-06-16 23:03:10 +00:00
private void loadAnyModel ( ResourceLocation location ) throws IOException
2014-12-28 04:10:54 +00:00
{
if ( loadingModels . contains ( location ) )
{
throw new IllegalStateException ( " circular model dependencies involving model " + location ) ;
}
loadingModels . add ( location ) ;
IModel model = ModelLoaderRegistry . getModel ( location ) ;
for ( ResourceLocation dep : model . getDependencies ( ) )
{
getModel ( dep ) ;
}
textures . addAll ( model . getTextures ( ) ) ;
loadingModels . remove ( location ) ;
}
2015-05-20 09:54:33 +00:00
private class VanillaModelWrapper implements IRetexturableModel
2014-12-28 04:10:54 +00:00
{
private final ResourceLocation location ;
private final ModelBlock model ;
public VanillaModelWrapper ( ResourceLocation location , ModelBlock model )
{
this . location = location ;
this . model = model ;
}
public Collection < ResourceLocation > getDependencies ( )
{
if ( model . getParentLocation ( ) = = null | | model . getParentLocation ( ) . getResourcePath ( ) . startsWith ( " builtin/ " ) ) return Collections . emptyList ( ) ;
return Collections . singletonList ( model . getParentLocation ( ) ) ;
}
public Collection < ResourceLocation > getTextures ( )
{
// setting parent here to make textures resolve properly
if ( model . getParentLocation ( ) ! = null )
{
2015-06-16 23:03:10 +00:00
try
2014-12-28 04:10:54 +00:00
{
2015-06-16 23:03:10 +00:00
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 " ) ;
}
2014-12-28 04:10:54 +00:00
}
2015-06-16 23:03:10 +00:00
catch ( IOException e )
2014-12-28 04:10:54 +00:00
{
2015-06-16 23:03:10 +00:00
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 " ) ;
}
2014-12-28 04:10:54 +00:00
}
}
ImmutableSet . Builder < ResourceLocation > builder = ImmutableSet . builder ( ) ;
if ( hasItemModel ( model ) )
{
for ( String s : ( List < String > ) ItemModelGenerator . LAYERS )
{
String r = model . resolveTextureName ( s ) ;
ResourceLocation loc = new ResourceLocation ( r ) ;
if ( ! r . equals ( s ) )
{
builder . add ( loc ) ;
}
// mojang hardcode
if ( model . getRootModel ( ) = = MODEL_COMPASS & & ! loc . equals ( TextureMap . LOCATION_MISSING_TEXTURE ) )
{
TextureAtlasSprite . setLocationNameCompass ( loc . toString ( ) ) ;
}
else if ( model . getRootModel ( ) = = MODEL_CLOCK & & ! loc . equals ( TextureMap . LOCATION_MISSING_TEXTURE ) )
{
TextureAtlasSprite . setLocationNameClock ( loc . toString ( ) ) ;
}
}
}
2015-02-08 12:24:30 +00:00
for ( String s : ( Iterable < String > ) 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 ( ) ;
}
public IFlexibleBakedModel bake ( IModelState state , VertexFormat format , Function < ResourceLocation , TextureAtlasSprite > bakedTextureGetter )
{
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-02-23 13:02:10 +00:00
if ( model = = null ) return getMissingModel ( ) . bake ( state , format , bakedTextureGetter ) ;
2015-06-23 12:55:58 +00:00
ItemCameraTransforms transforms = new ItemCameraTransforms ( model . getThirdPersonTransform ( ) , model . getFirstPersonTransform ( ) , model . getHeadTransform ( ) , model . getInGuiTransform ( ) ) ;
2015-06-22 22:03:16 +00:00
if ( hasItemModel ( model ) )
{
IPerspectiveState perState = state instanceof IPerspectiveState ? ( IPerspectiveState ) state : new IPerspectiveState . Impl ( state , transforms ) ;
return new ItemLayerModel ( model ) . bake ( perState , format , bakedTextureGetter ) ;
}
2015-06-23 12:55:58 +00:00
if ( isCustomRenderer ( model ) ) return new IFlexibleBakedModel . Wrapper ( new BuiltInModel ( transforms ) , format ) ;
2015-06-23 13:52:42 +00:00
return bakeNormal ( model , state . apply ( this ) , format , bakedTextureGetter , state instanceof UVLock ) ;
}
private IFlexibleBakedModel bakeNormal ( ModelBlock model , TRSRTransformation state , VertexFormat format , Function < ResourceLocation , TextureAtlasSprite > bakedTextureGetter , boolean uvLocked )
{
TextureAtlasSprite particle = bakedTextureGetter . apply ( new ResourceLocation ( model . resolveTextureName ( " particle " ) ) ) ;
SimpleBakedModel . Builder builder = ( new SimpleBakedModel . Builder ( model ) ) . setTexture ( particle ) ;
for ( BlockPart part : ( Iterable < BlockPart > ) model . getElements ( ) )
{
for ( Map . Entry < EnumFacing , BlockPartFace > e : ( Iterable < Map . Entry < EnumFacing , BlockPartFace > > ) part . mapFaces . entrySet ( ) )
{
TextureAtlasSprite textureatlassprite1 = bakedTextureGetter . apply ( new ResourceLocation ( model . resolveTextureName ( e . getValue ( ) . texture ) ) ) ;
if ( e . getValue ( ) . cullFace = = null | | ! TRSRTransformation . isInteger ( state . getMatrix ( ) ) )
{
builder . addGeneralQuad ( makeBakedQuad ( part , e . getValue ( ) , textureatlassprite1 , e . getKey ( ) , state , uvLocked ) ) ;
}
else
{
builder . addFaceQuad ( state . rotate ( e . getValue ( ) . cullFace ) , makeBakedQuad ( part , e . getValue ( ) , textureatlassprite1 , e . getKey ( ) , state , uvLocked ) ) ;
}
}
}
return new IFlexibleBakedModel . Wrapper ( builder . makeBakedModel ( ) , format ) ;
2014-12-28 04:10:54 +00:00
}
public IModelState getDefaultState ( )
{
return ModelRotation . X0_Y0 ;
}
2015-05-20 09:54:33 +00:00
@Override
public IModel retexture ( ImmutableMap < String , String > textures )
{
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.
for ( BlockPart part : ( List < BlockPart > ) this . model . getElements ( ) )
{
elements . add ( new BlockPart ( part . positionFrom , part . positionTo , Maps . newHashMap ( part . mapFaces ) , part . partRotation , part . shade ) ) ;
}
ModelBlock neweModel = new ModelBlock ( this . model . getParentLocation ( ) , elements ,
Maps . newHashMap ( this . model . textures ) , this . model . isAmbientOcclusion ( ) , this . model . isGui3d ( ) , //New Textures man VERY IMPORTANT
new ItemCameraTransforms ( this . model . getThirdPersonTransform ( ) , this . model . getFirstPersonTransform ( ) , this . model . getHeadTransform ( ) , this . model . getInGuiTransform ( ) ) ) ;
neweModel . name = this . model . name ;
neweModel . parent = this . model . parent ;
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 ( ) ) ;
neweModel . textures . remove ( e . getKey ( ) ) ;
}
else
neweModel . textures . put ( e . getKey ( ) , e . getValue ( ) ) ;
}
// 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
2015-05-20 09:54:33 +00:00
for ( Entry < String , String > e : ( Set < Entry < String , String > > ) neweModel . textures . entrySet ( ) )
{
if ( e . getValue ( ) . startsWith ( " # " ) )
{
String key = e . getValue ( ) . substring ( 1 ) ;
if ( neweModel . textures . containsKey ( key ) )
remapped . put ( e . getKey ( ) , ( String ) neweModel . textures . get ( key ) ) ;
}
}
2015-06-09 19:36:36 +00:00
2015-05-20 09:54:33 +00:00
neweModel . 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.
for ( BlockPart part : ( List < BlockPart > ) neweModel . getElements ( ) )
{
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 ( ) ;
}
}
return new VanillaModelWrapper ( location , neweModel ) ;
}
2014-12-28 04:10:54 +00:00
}
2015-02-03 07:33:32 +00:00
public static class UVLock implements IModelState
{
private final IModelState state ;
public UVLock ( IModelState state )
{
this . state = state ;
}
public TRSRTransformation apply ( IModelPart part )
{
return state . apply ( part ) ;
}
}
2014-12-28 04:10:54 +00:00
// 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 ;
private final List < ResourceLocation > locations = new ArrayList < ResourceLocation > ( ) ;
private final List < IModel > models = new ArrayList < IModel > ( ) ;
private final IModelState defaultState ;
2015-06-16 23:03:10 +00:00
@Deprecated public WeightedRandomModel ( Variants variants ) { this ( null , variants ) ; } // Remove 1.9
public WeightedRandomModel ( ModelResourceLocation parent , Variants variants )
2014-12-28 04:10:54 +00:00
{
this . variants = variants . getVariants ( ) ;
2015-06-22 22:03:16 +00:00
ImmutableMap . Builder < IModelPart , IModelState > builder = ImmutableMap . builder ( ) ;
2015-06-16 23:03:10 +00:00
for ( Variant v : ( List < Variant > ) variants . getVariants ( ) )
2014-12-28 04:10:54 +00:00
{
ResourceLocation loc = v . getModelLocation ( ) ;
locations . add ( loc ) ;
2015-05-20 09:54:33 +00:00
2015-06-16 23:03:10 +00:00
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 ( ) ;
}
2015-05-20 09:54:33 +00:00
if ( v instanceof ISmartVariant )
{
model = ( ( ISmartVariant ) v ) . process ( model , ModelLoader . this ) ;
textures . addAll ( model . getTextures ( ) ) ; // Kick this, just in case.
}
model = new WeightedPartWrapper ( model ) ;
2014-12-28 04:10:54 +00:00
models . add ( model ) ;
2015-06-22 22:03:16 +00:00
builder . put ( 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.
{
IModel missing = getMissingModel ( ) ;
models . add ( missing ) ;
2015-06-22 22:03:16 +00:00
builder . put ( missing , TRSRTransformation . identity ( ) ) ;
2015-06-16 23:03:10 +00:00
}
2014-12-28 04:10:54 +00:00
defaultState = new MapModelState ( builder . build ( ) ) ;
2015-06-16 23:03:10 +00:00
2014-12-28 04:10:54 +00:00
}
public Collection < ResourceLocation > getDependencies ( )
{
return ImmutableList . copyOf ( locations ) ;
}
public Collection < ResourceLocation > getTextures ( )
{
return Collections . emptyList ( ) ;
}
2015-02-03 07:33:32 +00:00
private IModelState addUV ( boolean uv , IModelState state )
{
if ( uv ) return new UVLock ( state ) ;
return state ;
}
2015-06-22 22:03:16 +00:00
private IModelState getState ( IModelState state , IModelPart part )
{
if ( state instanceof MapModelState )
{
return ( ( MapModelState ) state ) . getState ( part ) ;
}
return state ;
}
2014-12-28 04:10:54 +00:00
public IFlexibleBakedModel bake ( IModelState state , VertexFormat format , Function < ResourceLocation , TextureAtlasSprite > bakedTextureGetter )
{
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 )
{
Variant v = variants . get ( 0 ) ;
IModel model = models . get ( 0 ) ;
2015-06-22 22:03:16 +00:00
return model . bake ( addUV ( v . isUvLocked ( ) , getState ( state , model ) ) , 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 ) ;
2015-02-03 07:33:32 +00:00
Variant v = variants . get ( i ) ;
2015-06-22 22:03:16 +00:00
builder . add ( model . bake ( addUV ( v . isUvLocked ( ) , getState ( state , model ) ) , format , bakedTextureGetter ) , variants . get ( i ) . getWeight ( ) ) ;
2014-12-28 04:10:54 +00:00
}
2015-02-13 21:23:03 +00:00
return new FlexibleWeightedBakedModel ( builder . build ( ) , Attributes . DEFAULT_BAKED_FORMAT ) ;
2014-12-28 04:10:54 +00:00
}
public IModelState getDefaultState ( )
{
return defaultState ;
}
}
2015-02-13 21:23:03 +00:00
private static class FlexibleWeightedBakedModel extends WeightedBakedModel implements IFlexibleBakedModel
{
private final WeightedBakedModel parent ;
private final VertexFormat format ;
public FlexibleWeightedBakedModel ( WeightedBakedModel parent , VertexFormat format )
{
super ( parent . models ) ;
this . parent = parent ;
this . format = format ;
}
public VertexFormat getFormat ( )
{
return format ;
}
}
2014-12-28 04:10:54 +00:00
private boolean isBuiltinModel ( ModelBlock model )
{
return model = = MODEL_GENERATED | | model = = MODEL_COMPASS | | model = = MODEL_CLOCK | | model = = MODEL_ENTITY ;
}
public IModel getMissingModel ( )
{
2015-06-16 23:03:10 +00:00
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 ;
2014-12-28 04:10:54 +00:00
}
static enum VanillaLoader implements ICustomModelLoader
{
instance ;
private ModelLoader loader ;
void setLoader ( ModelLoader loader )
{
this . loader = loader ;
}
ModelLoader getLoader ( )
{
return loader ;
}
public void onResourceManagerReload ( IResourceManager resourceManager )
{
// do nothing, cause loader will store the reference to the resourceManager
}
public boolean accepts ( ResourceLocation modelLocation )
{
return true ;
}
2015-06-16 23:03:10 +00:00
public IModel loadModel ( ResourceLocation modelLocation ) throws IOException
2014-12-28 04:10:54 +00:00
{
2015-06-16 23:03:10 +00:00
return loader . new VanillaModelWrapper ( modelLocation , loader . loadModel ( modelLocation ) ) ;
2014-12-28 04:10:54 +00:00
}
}
2015-02-04 06:45:23 +00:00
2015-02-17 00:36:08 +00:00
public static class White extends TextureAtlasSprite
{
public static ResourceLocation loc = new ResourceLocation ( " white " ) ;
public static White instance = new White ( ) ;
protected White ( )
{
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 ) ;
2015-02-17 00:36:08 +00:00
BufferedImage [ ] images = new BufferedImage [ Minecraft . getMinecraft ( ) . gameSettings . mipmapLevels + 1 ] ;
images [ 0 ] = image ;
loadSprite ( images , null ) ;
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
}
}
2015-02-04 06:45:23 +00:00
public void onPostBakeEvent ( IRegistry modelRegistry )
{
2015-06-04 15:07:03 +00:00
Object missingModel = modelRegistry . getObject ( MODEL_MISSING ) ;
2015-02-04 06:45:23 +00:00
for ( ModelResourceLocation missing : missingVariants )
{
2015-06-04 15:07:03 +00:00
Object model = modelRegistry . getObject ( missing ) ;
if ( model = = null | | model = = missingModel )
2015-02-04 06:45:23 +00:00
{
FMLLog . severe ( " Model definition for location %s not found " , missing ) ;
}
}
isLoading = false ;
}
private static final Map < RegistryDelegate < Block > , IStateMapper > customStateMappers = Maps . newHashMap ( ) ;
public static void setCustomStateMapper ( Block block , IStateMapper mapper )
{
customStateMappers . put ( block . delegate , mapper ) ;
}
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
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-02-04 06:45:23 +00:00
}
public static void setCustomMeshDefinition ( Item item , ItemMeshDefinition meshDefinition )
{
customMeshDefinitions . put ( item . delegate , meshDefinition ) ;
}
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
}
}
2014-12-28 04:10:54 +00:00
}