• IceSunCN
  • BBS

Navigation

  • Home
  • Style Guide
  • Getting Started
    • Home
    • Structuring Your Mod
    • Forge Update Checker
    • Dependency Management
    • Debug Profiler
  • Concepts
    • Sides
    • Resources
    • Registries
    • The Fingerprint Violation Event
    • Internationalization and localization
  • Blocks
    • Home
    • Intro to Blockstates
    • Interaction
  • Animation API
    • Intro to the Animation API
    • Armatures
    • Animation State Machines
    • Using the API
  • Tile Entities
    • Home
    • Special Renderer
  • Items
    • Home
    • Loot Tables
  • Models
    • Intro to Models
    • Model Files
    • Blockstates
      • Intro to Blockstate JSONs
      • Forge Blockstate JSON
    • Connecting Blocks and Items to Models
    • Coloring Textures
    • Item Property Overrides
    • Advanced Models
      • Intro to Advanced Models
      • IModel
        • getDependencies
        • getTextures
        • bake
        • process
        • smoothLighting
        • gui3D
        • retexture
        • uvlock
      • IModelState and IModelPart
      • IBakedModel
      • Extended Blockstates
      • Perspective
      • ItemOverrideList
      • ICustomModelLoader
  • Rendering
    • TileEntityItemStackRenderer
  • Events
    • Basic Usage
  • Networking
    • Home
    • Overview
    • SimpleImpl
    • Entities
  • Data Storage
    • Capabilities
    • World Saved Data
    • Extended Entity Properties
    • Config Annotations
  • Utilities
    • Recipes
    • OreDictionary
    • PermissionAPI
  • Effects
    • Sounds
  • Conventions
    • Versioning
    • Locations
    • Loading Stages
  • Contributing to Forge
    • Getting Started
    • PR Guidelines

IModel

IModel is a type that represents a model in its raw state. This is how a model is represented right after it has been loaded. Usually this directly represents the source of the model (e.g. an object deserialized from JSON, or an OBJ container).

At this high level, a model has no concept of items, blocks, or anything of that sort; it purely represents a shape.

Important

IModel is immutable. Methods such as process that alter the model should never mutate the IModel, as they should construct new IModels instead.

getDependencies

This is a collection of the ResourceLocations of all the models this model depends on. These models are guaranteed to be loaded before this one is baked. For example, a model deserialized from a blockstate JSON will depend on the models defined within. Only models that are directly mapped to a block/item are loaded normally; to ensure loading of other models, they must be declared as dependencies of another. Cyclic dependencies will cause a LoaderException to be thrown.

getTextures

This is a collection of the ResourceLocations of all the textures this model depends on. These textures are guaranteed to be loaded before this model is baked. For example, a vanilla JSON model depends on all the textures defined within.

bake

This is the main method of IModel. It takes an IModelState, a VertexFormat, and a function ResourceLocation → TextureAtlasSprite, to return an IBakedModel. IBakedModel is less abstract than IModel, and it is what interacts with blocks and items. The function ResourceLocation → TextureAtlasSprite is used to get textures from ResourceLocations (i.e. the ResourceLocations of textures are passed to this function and the returned TextureAtlasSprite contains the texture).

process

This method allows a model to process extra data from external sources. The Forge blockstate variant format provides a way to define this data in the resource pack. Within the Forge blockstate format, the property that is used to pass this data is called custom. First, an example:

{
  "forge_marker": 1,
  "defaults": {
    "custom": {
      "__comment": "These can be any JSON primitives with any names, but models should only use what they understand.",
      "meaningOfLife": 42,
      "showQuestion": false
    },
    "model": "examplemod:life_meaning"
  },
  "variants": {
    "dying": {
      "true": {
        "__comment": "Custom data is inherited. Therefore, here `meaningOfLife` is inherited but `showQuestion` is overriden. The model itself remains inherited.",
        "custom": {
          "showQuestion": true
        }
      },
      "false": {}
    }
  }
}

As seen above, custom data can be of any type. Additionally, it is inherited from the defaults into the variants. The custom data is passed in as an ImmutableMap<String, String>. This is a map where the keys are the property names (in the above example, “meaningOfLife”, “showQuestion”, and “title”). Astute observers may notice that numeric and boolean data were defined in within the blockstate but this method only receives Strings. This is because all data is converted into strings before being processed. If a model does not understand what a property means, it should just ignore it.

smoothLighting

In vanilla, smooth lighting enables ambient occlusion. This flag can be controlled by the smooth_lighting property in a Forge blockstate (which can appear wherever a model property can and is inherited). The default implementation does nothing.

gui3D

gui3D controls whether a model looks “flat” in certain positions (e.g. with gui3d set to true, EntityItem renders a stack with multiple items as several layers of the model. With gui3d set to false, the item is always one layer), and also controls lighting inside GUIs. This flag can be controlled by the gui3d property in a Forge blockstate. The default implementation does nothing.

retexture

This method is used to change the textures a model might use. This is similar to how texture variables in vanilla JSON models work. A model can start out with certain faces with certain textures, and then by setting/overriding texture variables these faces can be changed. An example:

{
  "forge_marker": 1,
  "defaults": {
    "textures": {
      "varA": "examplemod:items/hgttg",
      "varB": "examplemod:blocks/earth",
      "varC": "#varA",
      "varZ": null
    },
    "model": "examplemod:universe"
  }
}

In this example, the textures block will be deserialized as-is into an ImmutableMap with the exception that nulls are turned into "" (i.e. the final result is "varA" → "examplemod:items/hgttg", "varB" → "examplemod:blocks/earth", "varC" → "#varA", "varZ" → ""). Then, retexture is called to change the textures as needed. How this is done is up to the model. It may be advisable, however, to support resolving texture variables such as “#var” (like vanilla JSON models) instead of taking them literally. The default implementation does nothing.

uvlock

This method is used to toggle UV lock. UV lock means that when the model itself rotates, the textures applied to the model do not rotate with it. The default implementation does nothing. This can be controlled with the uvlock property in a Forge blockstate. An example:

{
  "forge_marker": 1,
  "defaults": {
    "model": "minecraft:half_slab",
    "textures": {
      "__comment": "Texture definitions here..."
    }
  },
  "variants": {
    "a": [{ "__comment": "No change" }],
    "b": [{
      "__comment": "This is like literally taking the slab and flipping it upside down. The 'side' texture on the side faces is cropped to the bottom half and rotated 180 degrees, just as if a real object were turned upside down.",
      "x": 180
    }],
    "c": [{
      "__comment": "Now this is more interesting. The UV vertices are altered so that the texture won't rotate with the model, so that the side faces have the side texture rightside up and cropped to the top half.",
      "x": 180,
      "uvlock": true
    }]
  }
}
Built with MkDocs using a custom theme. Hosted by Read the Docs.
Enable Dark Theme