Co-authored-by: Ruling-0 <47913168+Ruling-0@users.noreply.github.com>
4.7 KiB
Model API
In general, it is designed to mimic the latest version.
Intentional deviations
Texture references are assumed to be in assets/<domain>/blocks by
default, to match 7.10 conventions. However, textures specified by
domain:block/whatever are remapped to domain:whatever, to support
importing models from modern.
Resource packs can now replace most blocks, similarly to modern. Note that this primarily works on blocks with ISBRHS - if the block has a TESR registered in code, that should result in both the model and the TESR rendering.
Examples
BlockColor
Use to color to TintIndex
Example: using BlockColor register
BlockColor.registerBlockColors(new IBlockColor() {
@Override
public int colorMultiplier(IBlockAccess world, int x, int y, int z, int tintIndex) {
// Return red for main layer, green for secondary
return tintIndex == 0 ? 0xFF0000 : 0x00FF00;
}
@Override
public int colorMultiplier(ItemStack stack, int tintIndex) {
// Return blue for main layer, yellow for secondary
return tintIndex == 0 ? 0x0000FF : 0xFFFF00;
}
}, ModBlocks.MY_CUSTOM_BLOCK);
Example: implement IBlockColor directly in a block
public class BlockTestTint extends Block implements IBlockColor {
public BlockTestTint() {
super(Material.wood);
}
@Override
public int colorMultiplier(IBlockAccess world, int x, int y, int z, int tintIndex) {
return switch(tintIndex) {
case 0 -> 0xFF0000; // red
case 1 -> 0x00FF00; // green
case 2 -> 0x0000FF; // blue
case 3 -> 0xFFFF00; // yellow
case 4 -> 0xFF00FF; // magenta
case 5 -> 0x00FFFF; // cyan
default -> 0xFFFFFF; // white
};
}
@Override
public int colorMultiplier(ItemStack stack, int tintIndex) {
return colorMultiplier(null, 0, 0, 0, tintIndex);
}
}
BlockState Api
Instead of relying on 4-bit metadata, model selection can resolved from full block state data via registered BlockProperty.
This allows:
- Unlimited logical states (no 16-meta restriction)
- Model variants based on TileEntity data
- ItemStack-aware state resolution
- Dynamic rendering behavior
BlockState resolution works in three steps:
- A
BlockPropertyis registered to a block (and optionally its item). - The property provides values from:
- World + TileEntity
- ItemStack
- The JsonModel loader resolves model variants using those property values.
1.Creating a BlockProperty
Example: Direction property backed by TileEntity.
DirectionBlockProperty property = new DirectionBlockProperty() {
@Override
public String getName() {
return "facing";
}
@Override
public boolean hasTrait(BlockPropertyTrait trait) {
return switch (trait) {
case SupportsWorld, WorldMutable, StackMutable, SupportsStacks -> true;
default -> false;
};
}
@Override
public ForgeDirection getValue(IBlockAccess world, int x, int y, int z) {
TileEntity te = world.getTileEntity(x, y, z);
if (te instanceof TileTestTintMul tile) {
return tile.getFacing();
}
return ForgeDirection.NORTH;
}
@Override
public void setValue(World world, int x, int y, int z, ForgeDirection value) {
TileEntity te = world.getTileEntity(x, y, z);
if (te instanceof TileTestTintMul tile) {
tile.setFacing(value);
}
}
@Override
public ForgeDirection getValue(ItemStack stack) {
return ForgeDirection.NORTH;
}
};
2.Registering the Property
BlockPropertyRegistry.registerProperty(block, property); BlockPropertyRegistry.registerProperty(Item.getItemFromBlock(block), property);
You must register:
- On the block (world state)
- On the item (inventory rendering)
3.Defining blockstate JSON
Example:
{
"variants": {
"facing=north": { "model": "modid:block/machine_north" },
"facing=south": { "model": "modid:block/machine_south" },
"facing=west": { "model": "modid:block/machine_west" },
"facing=east": { "model": "modid:block/machine_east" }
}
}
The loader will:
- Query property.getValue(...)
- Build a state string like: facing=north
- Resolve the correct model variant
Supported Traits
BlockPropertyTrait controls where the property works:
SupportsWorld→ usable in world renderingSupportsStacks→ usable in item renderingWorldMutable→ value can be changed in worldStackMutable→ value can be changed in ItemStack
Only implement the traits you need.
TODO
- Autoload item textures too.
- Add smooth shading to ModelISBRH.
- Add face culling to models.
- Implement UV locking.