-
Notifications
You must be signed in to change notification settings - Fork 51
CTM Overrides in Models
CTM data can be overridden in the model json
when a texture is accessed, even if the texture does not have a ctm
data compound in its metadata mcmeta
file or even a mcmeta
file at all. This page documents how it's done and an example of an application.
Overrides to CTM data are targeted at faces with a specific tintindex
id. These are marked in the model json
in the elements as normal like would be normally done for trying to tint a face. These will work even regardless if the block does have tinting or not.
The improved Model structure is as follows, after the Vanilla Model json
tags:
The root tag
├─ ...
├─ ctm_version : Set this to 1. Just version checking.
└─ ctm_overrides : A compound for a list of tint indexes to override ctm datas.
└─ (a number corresponding to a tintindex) : new ctm data. (Essentially a copy of what'd you normally put in the texture mcmeta, minus the animation structure)
├─ proxy : A texture to use instead of this one. Used for resourcepacks/mods that want to use an entirely different texture when CTM is present.
│ If this is defined, nothing else (aside from ctm_version) can be defined.
├─ type : Sets the render type. See below for a list of possible render types.
├─ layer : Sets rendering layer for texture. Can be: SOLID, CUTOUT, CUTOUT_MIPPED, or TRANSLUCENT.
├─ texture : A texture location to use instead of the texture in the element. Like proxy, but only for the texture itself and not associated metadata.
├─ textures : This is for extra textures needed by the render type.
│ └─ An array of extra textures used.
└─ extra : Used for any additional information the render, or specific render type, may require.
The Twilight Forest had these blocks that were giant and took up 4 blocks cubed of space. Something similar in terms of block texture can be accomplished as seen below:
Click here to expand cobblestone.json
{
"parent": "block/block",
"textures": {
"particle": "#all",
"all": "blocks/cobblestone"
},
"elements": [{
"from": [ 0, 0, 0 ],
"to": [ 16, 16, 16 ],
"faces": {
"down": { "texture": "#all", "tintindex": 0, "cullface": "down" },
"up": { "texture": "#all", "tintindex": 0, "cullface": "up" },
"north": { "texture": "#all", "tintindex": 0, "cullface": "north" },
"south": { "texture": "#all", "tintindex": 0, "cullface": "south" },
"west": { "texture": "#all", "tintindex": 0, "cullface": "west" },
"east": { "texture": "#all", "tintindex": 0, "cullface": "east" }
}
}],
"ctm_version": 1,
"ctm_overrides": {
"0": {
"type": "pattern",
"extra": {
"size": 4
}
}
}
}
The benefits of this method instead of directly putting the mcmeta on the cobblestone.png
file itself is that the only specifically the Cobblestone block will be receiving this effect. Other blocks that use this texture like the Lever will not.
Click here to expand double_stone.json
{
"parent": "block/block",
"textures": {
"end": "blocks/stone_slab_top",
"side": "blocks/stone_slab_side",
"particle": "blocks/stone_slab_top"
},
"elements": [{
"from": [ 0, 0, 0 ],
"to": [ 16, 8, 16 ],
"faces": {
"down": { "texture": "#end" , "cullface": "down" , "tintindex": 2 },
"north": { "texture": "#side", "cullface": "north", "tintindex": 0 },
"south": { "texture": "#side", "cullface": "south", "tintindex": 0 },
"west": { "texture": "#side", "cullface": "west" , "tintindex": 0 },
"east": { "texture": "#side", "cullface": "east" , "tintindex": 0 }
}
}, {
"from": [ 0, 8, 0 ],
"to": [ 16, 16, 16 ],
"faces": {
"up": { "texture": "#end" , "cullface": "up" , "tintindex": 3 },
"north": { "texture": "#side", "cullface": "north", "tintindex": 1 },
"south": { "texture": "#side", "cullface": "south", "tintindex": 1 },
"west": { "texture": "#side", "cullface": "west" , "tintindex": 1 },
"east": { "texture": "#side", "cullface": "east" , "tintindex": 1 }
}
}
],
"ctm_version": 1,
"ctm_overrides": {
"0": {
"type": "ctm",
"textures": [ "blocks/stone_slab_side_ctm" ],
"extra": {
"connect_to": [
{
"block": "double_stone_slab",
"predicate": [
{"variant": "stone" },
{ "seamless": false }
]
}, {
"block": "stone_slab",
"predicate": [
{ "variant": "stone" },
{ "half": "bottom" }
]
}
]
}
},
"1": {
"type": "ctm",
"textures": [ "blocks/stone_slab_side_ctm" ],
"extra": {
"connect_to": [
{
"block": "double_stone_slab",
"predicate": [
{"variant": "stone" },
{ "seamless": false }
]
}, {
"block": "stone_slab",
"predicate": [
{ "variant": "stone" },
{ "half": "top" }
]
}
]
}
},
"2": {
"type": "ctm",
"textures": [ "blocks/stone_slab_side_ctm" ],
"extra": {
"connect_to": [
{
"block": "double_stone_slab",
"predicate": [
{"variant": "stone" },
{ "seamless": false }
]
}, {
"block": "stone_slab",
"predicate": [
{ "variant": "stone" },
{ "half": "bottom" }
]
}
]
}
},
"3": {
"type": "ctm",
"textures": [ "blocks/stone_slab_side_ctm" ],
"extra": {
"connect_to": [
{
"block": "double_stone_slab",
"predicate": [
{"variant": "stone" },
{ "seamless": false }
]
}, {
"block": "stone_slab",
"predicate": [
{ "variant": "stone" },
{ "half": "top" }
]
}
]
}
}
}
}
Ok, that's a bit much to look at, right? The cleaner version is below:
Cleaned version of double_stone.json
{
"parent": "block/block",
"textures": {
"end": "blocks/stone_slab_top",
"side": "blocks/stone_slab_side",
"particle": "blocks/stone_slab_top"
},
"elements": [{
"from": [ 0, 0, 0 ],
"to": [ 16, 8, 16 ],
"faces": {
"down": { "texture": "#end" , "cullface": "down" , "tintindex": 0 },
"north": { "texture": "#side", "cullface": "north", "tintindex": 2 },
"south": { "texture": "#side", "cullface": "south", "tintindex": 2 },
"west": { "texture": "#side", "cullface": "west" , "tintindex": 2 },
"east": { "texture": "#side", "cullface": "east" , "tintindex": 2 }
}
}, {
"from": [ 0, 8, 0 ],
"to": [ 16, 16, 16 ],
"faces": {
"up": { "texture": "#end" , "cullface": "up" , "tintindex": 1 },
"north": { "texture": "#side", "cullface": "north", "tintindex": 3 },
"south": { "texture": "#side", "cullface": "south", "tintindex": 3 },
"west": { "texture": "#side", "cullface": "west" , "tintindex": 3 },
"east": { "texture": "#side", "cullface": "east" , "tintindex": 3 }
}
}
],
"ctm_version": 1,
"ctm_overrides": {
"0": { "type": "ctm", "textures": [ "blocks/stone_slab_top_ctm" ], "extra": { "connect_to": [
{ "block": "double_stone_slab", "predicate": [{ "variant": "stone" }, { "seamless": false }]},
{ "block": "stone_slab" , "predicate": [{ "variant": "stone" }, { "half": "bottom" }]}
]}},
"1": { "type": "ctm", "textures": [ "blocks/stone_slab_top_ctm" ], "extra": { "connect_to": [
{ "block": "double_stone_slab", "predicate": [{ "variant": "stone" }, { "seamless": false }]},
{ "block": "stone_slab" , "predicate": [{ "variant": "stone" }, { "half": "top" }]}
]}},
"2": { "type": "ctm", "textures": [ "blocks/stone_slab_side_ctm" ], "extra": { "connect_to": [
{ "block": "double_stone_slab", "predicate": [{ "variant": "stone" }, { "seamless": false }]},
{ "block": "stone_slab" , "predicate": [{ "variant": "stone" }, { "half": "bottom" }]}
]}},
"3": { "type": "ctm", "textures": [ "blocks/stone_slab_side_ctm" ], "extra": { "connect_to": [
{ "block": "double_stone_slab", "predicate": [{ "variant": "stone" }, { "seamless": false }]},
{ "block": "stone_slab" , "predicate": [{ "variant": "stone" }, { "half": "top" }]}
]}}
}
}
Observe that the layout for the model is practically identical to the vanilla Double Stone Slabs model, except that there are two cuboids, one half-cube on top and other half-cube on bottom. They all use different tintindex
ids as well. These are pointed at by the ids inside the ctm_overrides
compound.
The specific override itself replaces the ctm data of the original texture target with the overriding data. There is no partial override, all of the old ctm data is wiped and replaced with the override.
These overrides contain the ctm
rendertype include conditional connections, allowing them to not only connect to itself but also the neighboring respective half-slab.