Modding:Basic Block: Difference between revisions
(Add links to more details for the block attributes) |
|||
(31 intermediate revisions by 12 users not shown) | |||
Line 1: | Line 1: | ||
<languages/> | |||
<translate> | |||
<!--T:1--> | |||
{{GameVersion|1.19}} | |||
__FORCETOC__ | __FORCETOC__ | ||
{{PageOutdated|lookat={{ll|Modding:Content_Tutorial_Simple_Block|the simple block tutorial|nsp=0}}}} | |||
Please read the | <!--T:2--> | ||
Please read about the {{ll|Modding:Asset System|nsp=1}} first, if you haven't done it already. This tutorial should introduce you into the basic of adding a block to the game using JSON files. If you want to add a block with functionality you should check out the tutorial for [[Advanced Blocks]]. There is a full list of all properties which can be defined inside the json file [[Block Json Properties|here]]. | |||
= A Simple Block = | = A Simple Block = <!--T:3--> | ||
<!--T:4--> | |||
To get started let's create something simple. In our example we will add an ordinary gold block to the game (will be for decorative use only). So let's call this mod '''MyGoldBlock'''. | To get started let's create something simple. In our example we will add an ordinary gold block to the game (will be for decorative use only). So let's call this mod '''MyGoldBlock'''. | ||
== Workspace == | == Workspace == <!--T:5--> | ||
First of all | <!--T:6--> | ||
First of all it is useful to create a new folder to keep everything nice and clean. Inside this '''workspace''' we will create the mod itself, and later on put it into a zip file, so we can test it and distribute it to other people. | |||
== The Texture == | == The Texture == <!--T:7--> | ||
We will use this texture for our block: [[File:Gold block.png]]. | <!--T:8--> | ||
We will use this texture for our block: [[File:Gold block.png]]. <br> | |||
(To create your own textures, you can use programs like [https://www.dotpdn.com/downloads/pdn.html/ PaintDotNet(free)], [https://www.piskelapp.com/ Piskel(free)], or [https://github.com/aseprite/aseprite/ Aseprite(free open source, or pay for precompiled)]) | |||
<!--T:9--> | |||
Now we need to put the texture at the right place so we can use it later on. Therefore you have to rename the texture to <code>mygoldtexture.png</code> and put it inside <code>assets/mygoldblock/textures/block/</code> in your workspace (you have to create those folders first). <code>mygoldblock</code> will be our domain. | Now we need to put the texture at the right place so we can use it later on. Therefore you have to rename the texture to <code>mygoldtexture.png</code> and put it inside <code>assets/mygoldblock/textures/block/</code> in your workspace (you have to create those folders first). <code>mygoldblock</code> will be our domain. | ||
== The Block File == | == The Block File == <!--T:10--> | ||
<!--T:11--> | |||
The next thing we are going to need is a json file which will determine the properties of the block. For now we will keep it simple and will work with simple properties only. If you want to do some more advanced stuff you can take a look at the [[Block Json Properties|Block Properties Overview]]. | The next thing we are going to need is a json file which will determine the properties of the block. For now we will keep it simple and will work with simple properties only. If you want to do some more advanced stuff you can take a look at the [[Block Json Properties|Block Properties Overview]]. | ||
Now you need to create a new json file in your editor (we recommend to use an editor with syntax highlighting, such as [https://notepad-plus-plus.org/ Notepad++] or Visual Studio). | <!--T:12--> | ||
Now you need to create a new json file in your editor (we recommend to use an editor with syntax highlighting, such as [https://notepad-plus-plus.org/ Notepad++] or [https://www.sublimetext.com/ Sublime Text]. If you are going to have many json files or some C#, then [https://code.visualstudio.com/ Visual Studio Code] is also a good pick). | |||
<!--T:13--> | |||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
{ | { | ||
code: "mygoldblock", | "code": "mygoldblock", | ||
creativeinventory: { "general": ["*"] }, | "creativeinventory": { "general": ["*"] }, | ||
blockmaterial: "Stone", | "blockmaterial": "Stone", | ||
drawtype: "Cube", | "drawtype": "Cube", | ||
textures: { | "textures": { | ||
all: { base: "block/mygoldtexture" } | "all": { "base": "block/mygoldtexture" } | ||
}, | }, | ||
resistance: 3.5, | "resistance": 3.5, | ||
sounds: { | "sounds": { | ||
"place": "game:block/anvil", | "place": "game:block/anvil", | ||
"walk": "game:walk/stone" | "walk": "game:walk/stone" | ||
Line 40: | Line 54: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:14--> | |||
Short explanation of each line: | Short explanation of each line: | ||
* | <!--T:15--> | ||
* | * [[Modding:Block_Json_Properties#p_code|code]]: A unique identifier for your block. | ||
* | * [[Modding:Block_Json_Properties#p_creativeinventory|creativeinventory]]: The creative inventory tabs the block should be shown in (currently only 1 tab available) | ||
* | * [[Modding:Block_Json_Properties#p_shape|shape]]: Which model the block should use | ||
* | * [[Modding:Block_Json_Properties#p_drawtype|drawtype]]: Determines the drawing system, e.g. use 'cube' for normal full cubes or 'json' for custom created shapes. | ||
* | * [[Modding:Block_Json_Properties#p_textures|textures]]: What textures to apply. For simple blocks you can define one single texture for 'all' faces or define one for every facing ('north', 'east', 'west', 'south', 'up', 'down') | ||
* | * [[Modding:Block_Json_Properties#p_resistance|resistance]]: How many seconds of real life time it takes to break the block without tools | ||
* [[Modding:Block_Json_Properties#p_sounds|sounds]]: The sounds to be played when placing/breaking or walking on the block. The prefix <code>game</code> has to be added, since our block has the domain <code>mygoldblock</code>. Otherwise it would try to find those sounds inside our domain. | |||
<!--T:16--> | |||
Now save the file in your workspace inside <code>assets/mygoldblock/blocktypes/</code> and name it <code>mygoldblock.json</code>. | Now save the file in your workspace inside <code>assets/mygoldblock/blocktypes/</code> and name it <code>mygoldblock.json</code>. | ||
== Naming the Block == | == Naming the Block == <!--T:17--> | ||
<!--T:18--> | |||
To give the block a proper name, we need to create another json file and save it with the following path: <code>assets/mygoldblock/lang/en.json</code> | To give the block a proper name, we need to create another json file and save it with the following path: <code>assets/mygoldblock/lang/en.json</code> | ||
<!--T:19--> | |||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
{ | { | ||
Line 62: | Line 81: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Testing/ Distribution == | == Testing/ Distribution == <!--T:20--> | ||
<!--T:21--> | |||
The last thing we need to do is to create a zip file of the assets folder inside our workspace. Either you use an external program (such as WinRAR or 7Zip) or you right-click the <code>assets</code> folder and hit '''Send To''' -> '''Compressed (zipped) folder'''. Eventually you can rename the zip file to <code>MyGoldBlockMod.zip</code>. The zip file can be either used for testing purposes or you can send it to other people so they can use it as well. | The last thing we need to do is to create a zip file of the assets folder inside our workspace. Either you use an external program (such as WinRAR or 7Zip) or you right-click the <code>assets</code> folder and hit '''Send To''' -> '''Compressed (zipped) folder'''. Eventually you can rename the zip file to <code>MyGoldBlockMod.zip</code>. The zip file can be either used for testing purposes or you can send it to other people so they can use it as well. | ||
<!--T:22--> | |||
Furthermore you need to add a <code>modinfo.json</code> file, check out [[Game_Content_Mod|this tutorial]]. | Furthermore you need to add a <code>modinfo.json</code> file, check out [[Game_Content_Mod|this tutorial]]. | ||
To install the mod, navigate to the [[ | <!--T:23--> | ||
To install the mod, navigate to the [[VintagestoryData folder]] and place it inside the mods folder. | |||
<!--T:24--> | |||
[https://wiki.vintagestory.at/images/4/4c/MyGoldBlockMod.zip MyGoldBlockMod.zip] | [https://wiki.vintagestory.at/images/4/4c/MyGoldBlockMod.zip MyGoldBlockMod.zip] | ||
<!--T:25--> | |||
[[File:2017-01-10 12-33-45.png|700px]]. | [[File:2017-01-10 12-33-45.png|700px]]. | ||
<!--T:26--> | |||
'''Hint''': Use the client command <code>.tfedit</code> if you want to adjust the block position, rotation and scale in Hands, in GUI, when dropped on the ground or in third person mode. | '''Hint''': Use the client command <code>.tfedit</code> if you want to adjust the block position, rotation and scale in Hands, in GUI, when dropped on the ground or in third person mode. | ||
= Advanced Properties = | = Advanced Properties = <!--T:27--> | ||
<!--T:28--> | |||
Now we do some more advanced stuff with our lovely gold block. We will add random textures, different variants and custom shapes. So let's get started. | Now we do some more advanced stuff with our lovely gold block. We will add random textures, different variants and custom shapes. So let's get started. | ||
== Random Textures == | == Random Textures == <!--T:29--> | ||
<!--T:30--> | |||
So first of all we need some more textures. I have created some variants of the gold block [[File:Gold block.png]] [[File:mygoldtexture1.png]] [[File:mygoldtexture2.png]] [[File:mygoldtexture3.png]]. | So first of all we need some more textures. I have created some variants of the gold block [[File:Gold block.png]] [[File:mygoldtexture1.png]] [[File:mygoldtexture2.png]] [[File:mygoldtexture3.png]]. | ||
To keep the name of the textures simple I added a number to each texture name (<code>mygoldtexture.png</code>,<code>mygoldtexture1.png</code>,<code>mygoldtexture2.png</code>,<code>mygoldtexture3.png</code>) | To keep the name of the textures simple I added a number to each texture name (<code>mygoldtexture.png</code>,<code>mygoldtexture1.png</code>,<code>mygoldtexture2.png</code>,<code>mygoldtexture3.png</code>) | ||
<!--T:31--> | |||
Now we need to add those new textures to the json file. | Now we need to add those new textures to the json file. | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
textures: { | "textures": { | ||
all: { | "all": { | ||
base: "block/mygoldtexture", | "base": "block/mygoldtexture", | ||
alternates: [{base: "block/mygoldtexture1" }, {base: "block/mygoldtexture2" }, {base: "block/mygoldtexture3" }], | "alternates": [{"base": "block/mygoldtexture1" }, {"base": "block/mygoldtexture2" }, {"base": "block/mygoldtexture3" }], | ||
}, | }, | ||
}, | }, | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:32--> | |||
Eventually save it and run Vintagestory again. Now you should see a result like this: | Eventually save it and run Vintagestory again. Now you should see a result like this: | ||
<!--T:33--> | |||
[[File:2017-01-10 14-05-03.png|700px]] | [[File:2017-01-10 14-05-03.png|700px]] | ||
<!--T:34--> | |||
Of course you can add more texture if you would like to. | Of course you can add more texture if you would like to. | ||
== Variants == | == Variants == <!--T:35--> | ||
<!--T:36--> | |||
Gold is the best, but iron is awesome too ... so what shall we do? Let's add another variant of this block, because we all love iron. | Gold is the best, but iron is awesome too ... so what shall we do? Let's add another variant of this block, because we all love iron. | ||
<!--T:37--> | |||
You could duplicate the blocktype file and rename silver to gold in all the places, or you can simply add another variant to the existing blocktype. | You could duplicate the blocktype file and rename silver to gold in all the places, or you can simply add another variant to the existing blocktype. | ||
=== Variantgroup: Type === | === Variantgroup: Type === <!--T:38--> | ||
<!--T:39--> | |||
So first of all we need some new textures again: [[File:Myirontexture.png]] [[File:Myirontexture1.png]] [[File:Myirontexture2.png]] [[File:Myirontexture3.png]] | So first of all we need some new textures again: [[File:Myirontexture.png]] [[File:Myirontexture1.png]] [[File:Myirontexture2.png]] [[File:Myirontexture3.png]] | ||
Now we need to change a few things in our json file. We can add all kinds of different groups, but for now we keep it simple. We are adding group called <code>type</code>, with the states <code>gold</code> and <code>iron</code>. You can use any group code you want. | <!--T:40--> | ||
Now we need to change a few things in our json file. We can add all kinds of different groups, but for now we keep it simple. We are adding a [[Modding:Registry_Object_JSON_Parsing|variant group]] called <code>type</code>, with the states <code>gold</code> and <code>iron</code>. You can use any group code you want. | |||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
variantgroups: [ | "variantgroups": [ | ||
{ code: "type", states: ["gold", "iron"] } | { "code": "type", "states": ["gold", "iron"] } | ||
], | ], | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:41--> | |||
The next thing we need to do is set textures by type. So we remove our <code>texture</code> property and replace it with a new property <code>texturesbytype</code>, which will allow us to set different textures for each type. | The next thing we need to do is set textures by type. So we remove our <code>texture</code> property and replace it with a new property <code>texturesbytype</code>, which will allow us to set different textures for each type. | ||
<!--T:42--> | |||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
texturesbytype: { | "texturesbytype": { | ||
"*-gold": { | "*-gold": { | ||
all: { | "all": { | ||
base: "block/mygoldtexture", | "base": "block/mygoldtexture", | ||
alternates: [{base: "block/mygoldtexture1" }, {base: "block/mygoldtexture2" }, {base: "block/mygoldtexture3" }], | "alternates": [{"base": "block/mygoldtexture1" }, {"base": "block/mygoldtexture2" }, {"base": "block/mygoldtexture3" }], | ||
}, | }, | ||
}, | }, | ||
"*-iron": { | "*-iron": { | ||
all: { | "all": { | ||
base: "block/myirontexture", | "base": "block/myirontexture", | ||
alternates: [{base: "block/myirontexture1" }, {base: "block/myirontexture2" }, {base: "block/myirontexture3" }], | "alternates": [{"base": "block/myirontexture1" }, {"base": "block/myirontexture2" }, {"base": "block/myirontexture3" }], | ||
}, | }, | ||
} | } | ||
Line 138: | Line 175: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:43--> | |||
Every group will be added after each other to the blocks code <code>myblockname-mygroup-mysecondgroup</code>. In our example we can save ourselves writing a few extra letters by using the wild card <code>*</code>. | Every group will be added after each other to the blocks code <code>myblockname-mygroup-mysecondgroup</code>. In our example we can save ourselves writing a few extra letters by using the wild card <code>*</code>. | ||
<!--T:44--> | |||
You can also use a more compact definition. Due to way we named our textures we can use the placeholder {type} to determine the texture name, so instead of handling every case individually we can write it like this: | You can also use a more compact definition. Due to way we named our textures we can use the placeholder {type} to determine the texture name, so instead of handling every case individually we can write it like this: | ||
<!--T:45--> | |||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
textures: { | "textures": { | ||
all: { | "all": { | ||
base: "block/my{type}texture", | "base": "block/my{type}texture", | ||
alternates: [{base: "block/my{type}texture1" }, {base: "block/my{type}texture2" }, {base: "block/my{type}texture3" }], | "alternates": [{"base": "block/my{type}texture1" }, {"base": "block/my{type}texture2" }, {"base": "block/my{type}texture3" }], | ||
}, | }, | ||
}, | }, | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:46--> | |||
The full blocktype definition could then look like this: | The full blocktype definition could then look like this: | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
{ | { | ||
code: "myshinyblock", | "code": "myshinyblock", | ||
creativeinventory: { "general": ["*"] }, | "creativeinventory": { "general": ["*"] }, | ||
variantgroups: [ | "variantgroups": [ | ||
{ code: "type", states: ["gold", "iron"] } | { "code": "type", "states": ["gold", "iron"] } | ||
], | ], | ||
blockmaterial: "Stone", | "blockmaterial": "Stone", | ||
drawtype: "cube", | "drawtype": "cube", | ||
textures: { | "textures": { | ||
all: { | "all": { | ||
base: "block/my{type}texture", | "base": "block/my{type}texture", | ||
alternates: [{base: "block/my{type}texture1" }, {base: "block/my{type}texture2" }, {base: "block/my{type}texture3" }], | "alternates": [{"base": "block/my{type}texture1" }, {"base": "block/my{type}texture2" }, {"base": "block/my{type}texture3" }], | ||
}, | }, | ||
}, | }, | ||
resistance: 3.5, | "resistance": 3.5, | ||
sounds: { | "sounds": { | ||
"place": "game:block/anvil", | "place": "game:block/anvil", | ||
"walk": "game:walk/stone" | "walk": "game:walk/stone" | ||
Line 175: | Line 216: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:47--> | |||
[[File:2017-01-10 14-36-58.png|700px]] | [[File:2017-01-10 14-36-58.png|700px]] | ||
=== Variantgroup: Condition === | === Variantgroup: Condition === <!--T:48--> | ||
<!--T:49--> | |||
Let's at another group to our block, which will determine the condition of this block. There will be two states <code>good</code> and <code>used</code>. We can add this group by adding another property inside <code>variantgroups[]</code>. | Let's at another group to our block, which will determine the condition of this block. There will be two states <code>good</code> and <code>used</code>. We can add this group by adding another property inside <code>variantgroups[]</code>. | ||
<!--T:50--> | |||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
variantgroups: [ | "variantgroups": [ | ||
{ code: "type", states: ["gold", "iron"] }, | { "code": "type", "states": ["gold", "iron"] }, | ||
{ code: "condition", states: ["good", "used"]} | { "code": "condition", "states": ["good", "used"]} | ||
], | ], | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:51--> | |||
To finish implementing this second group we need to take care of every case. We want the <code>good</code> blocks to only use the base texture and the <code>used</code> blocks to also use their random textures: | To finish implementing this second group we need to take care of every case. We want the <code>good</code> blocks to only use the base texture and the <code>used</code> blocks to also use their random textures: | ||
<!--T:52--> | |||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
texturesbytype: { | "texturesbytype": { | ||
"*-good": { | "*-good": { | ||
all: { | "all": { | ||
base: "block/my{type}texture", | "base": "block/my{type}texture", | ||
}, | }, | ||
}, | }, | ||
"*-used": { | "*-used": { | ||
all: { | "all": { | ||
base: "block/my{type}texture", | "base": "block/my{type}texture", | ||
alternates: [{base: "block/my{type}texture1" }, {base: "block/my{type}texture2" }, {base: "block/my{type}texture3" }], | "alternates": [{"base": "block/my{type}texture1" }, {"base": "block/my{type}texture2" }, {"base": "block/my{type}texture3" }], | ||
}, | }, | ||
}, | }, | ||
Line 206: | Line 252: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:53--> | |||
The blocks in a good condition or on the left side, while the used ones are on the right: | The blocks in a good condition or on the left side, while the used ones are on the right: | ||
<!--T:54--> | |||
[[File:2017-01-10 15-02-38.png|700px]] | [[File:2017-01-10 15-02-38.png|700px]] | ||
== Custom Shapes == | == Custom Shapes == <!--T:55--> | ||
<!--T:56--> | |||
In order to use a custom shape we need to create one first. The engine only supports the model/shape format that's created by the [[VS Model Creator]]. | In order to use a custom shape we need to create one first. The engine only supports the model/shape format that's created by the [[VS Model Creator]]. | ||
<!--T:57--> | |||
Once you have created your own shape you need to export it as a json file, create a new folder <code>assets/myshinyblock/shapes/block/</code> and save the file in there. In our example we will use this model [https://wiki.vintagestory.at/images/3/38/Myshinymodel.json Myshinymodel.json] and move it to <code>assets/myshinyblock/shapes/block/myshinymodel.json</code>. | Once you have created your own shape you need to export it as a json file, create a new folder <code>assets/myshinyblock/shapes/block/</code> and save the file in there. In our example we will use this model [https://wiki.vintagestory.at/images/3/38/Myshinymodel.json Myshinymodel.json] and move it to <code>assets/myshinyblock/shapes/block/myshinymodel.json</code>. | ||
Now we need to specify the model inside our block type json file. | Now we need to specify the model inside our block type json file. | ||
<!--T:58--> | |||
Therefore we will change the drawtype from <code>cube</code> to <code>json</code>: | Therefore we will change the drawtype from <code>cube</code> to <code>json</code>: | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
drawtype: "json", | "drawtype": "json", | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:59--> | |||
and the shape to <code>myshinymodel</code> | and the shape to <code>myshinymodel</code> | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
shape: { base: "block/myshinymodel" }, | "shape": { base: "block/myshinymodel" }, | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:60--> | |||
Although this would be enough theoretically, we also should determine this block as being non-solid, to prevent graphical glitches. | Although this would be enough theoretically, we also should determine this block as being non-solid, to prevent graphical glitches. | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
sidesolid: { | "sidesolid": { | ||
all: "false" | "all": "false" | ||
}, | }, | ||
sideopaque: { | "sideopaque": { | ||
all: "false" | "all": "false" | ||
}, | }, | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:61--> | |||
So let's run the game. This is how it should look like: | So let's run the game. This is how it should look like: | ||
<!--T:62--> | |||
[[File:2017-01-12 14-06-27.png|700px]] | [[File:2017-01-12 14-06-27.png|700px]] | ||
== Variants of Custom Shapes == | == Variants of Custom Shapes == <!--T:63--> | ||
<!--T:64--> | |||
I created another model for the blocks in good condition ([https://wiki.vintagestory.at/images/f/fa/Myshinymodel1.json myshinymodel1.json]), because they should look more awesome, than the ones in used conditions. Therefore we need to copy the json file to <code>assets/myshinyblock/shapes/block/</code> as well. | I created another model for the blocks in good condition ([https://wiki.vintagestory.at/images/f/fa/Myshinymodel1.json myshinymodel1.json]), because they should look more awesome, than the ones in used conditions. Therefore we need to copy the json file to <code>assets/myshinyblock/shapes/block/</code> as well. | ||
<!--T:65--> | |||
In order to specify the shape by type we need to remove the property <code>shape</code> and replace it with <code>shapebytype</code>: | In order to specify the shape by type we need to remove the property <code>shape</code> and replace it with <code>shapebytype</code>: | ||
<syntaxhighlight lang="json"> | <syntaxhighlight lang="json"> | ||
shapebytype: { | "shapebytype": { | ||
"*-good": { | "*-good": { | ||
base: "block/myshinymodel1", | "base": "block/myshinymodel1", | ||
}, | }, | ||
"*-used": { | "*-used": { | ||
base: "block/myshinymodel", | "base": "block/myshinymodel", | ||
}, | }, | ||
}, | }, | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<!--T:66--> | |||
[[File:2017-01-12 14-51-45.png|700px]] | [[File:2017-01-12 14-51-45.png|700px]] | ||
= Mod Download = <!--T:67--> | |||
You can find the complete mod here for reference: | |||
<!--T:68--> | |||
[https://wiki.vintagestory.at/images/4/42/MyShinyBlockMod.zip MyShinyBlockMod] | [https://wiki.vintagestory.at/images/4/42/MyShinyBlockMod.zip MyShinyBlockMod] | ||
= Moving Forward = <!--T:69--> | |||
<!--T:70--> | |||
The example shown here, while seemingly complex, only scratches the surface of what blocktypes are capable of in Vintage Story. It's highly suggested that you experiment with or at least familiarize yourself with all the known block properties before moving onto code mods. The best way to do this is to peruse the '''[[Modding:Block Json Properties | Block Properties]]''' page, which contains an ongoing list of all the usable JSON block properties currently incorporated into the game. Most properties in the list also have referenced files you can search for in the Vintage Story Assets folder. If you don't know where this is, you can find tutorials for each operating system at the {{ll|Modding:Asset System|nsp=0}} page. | |||
<!--T:71--> | |||
If you haven't yet, it's suggested you also check out the '''[[Modding:Basic Item | Basic Item]]''' and '''[[Modding:Basic Entity | Basic Entity]]''' pages to learn how simple JSON items and entities are added to the game. | |||
<!--T:72--> | |||
However, if you're feeling like making the jump to code mods then you'll want to start by setting up your '''[[Modding: Setting up your Development Environment | Development Environment]]'''. | |||
= Tutorial Video: How make mod without programming (in Russian) = <!--T:73--> | |||
Thanks to ZigTheHedge for great detailed video | |||
<br><youtube>BAr7etxj-1o</youtube> <youtube>fnFFh_enXiA</youtube> | |||
{{Navbox/ | <!--T:74--> | ||
{{Navbox/contentmodding}} | |||
</translate> |
Latest revision as of 17:10, 3 August 2024
This page was last verified for Vintage Story version 1.19.
This page is outdated!
Some details may not be accurate, so use with caution! Please view the simple block tutorial for an up-to-date page!
Please read about the Asset System first, if you haven't done it already. This tutorial should introduce you into the basic of adding a block to the game using JSON files. If you want to add a block with functionality you should check out the tutorial for Advanced Blocks. There is a full list of all properties which can be defined inside the json file here.
A Simple Block
To get started let's create something simple. In our example we will add an ordinary gold block to the game (will be for decorative use only). So let's call this mod MyGoldBlock.
Workspace
First of all it is useful to create a new folder to keep everything nice and clean. Inside this workspace we will create the mod itself, and later on put it into a zip file, so we can test it and distribute it to other people.
The Texture
We will use this texture for our block: .
(To create your own textures, you can use programs like PaintDotNet(free), Piskel(free), or Aseprite(free open source, or pay for precompiled))
Now we need to put the texture at the right place so we can use it later on. Therefore you have to rename the texture to mygoldtexture.png
and put it inside assets/mygoldblock/textures/block/
in your workspace (you have to create those folders first). mygoldblock
will be our domain.
The Block File
The next thing we are going to need is a json file which will determine the properties of the block. For now we will keep it simple and will work with simple properties only. If you want to do some more advanced stuff you can take a look at the Block Properties Overview.
Now you need to create a new json file in your editor (we recommend to use an editor with syntax highlighting, such as Notepad++ or Sublime Text. If you are going to have many json files or some C#, then Visual Studio Code is also a good pick).
{
"code": "mygoldblock",
"creativeinventory": { "general": ["*"] },
"blockmaterial": "Stone",
"drawtype": "Cube",
"textures": {
"all": { "base": "block/mygoldtexture" }
},
"resistance": 3.5,
"sounds": {
"place": "game:block/anvil",
"walk": "game:walk/stone"
}
}
Short explanation of each line:
- code: A unique identifier for your block.
- creativeinventory: The creative inventory tabs the block should be shown in (currently only 1 tab available)
- shape: Which model the block should use
- drawtype: Determines the drawing system, e.g. use 'cube' for normal full cubes or 'json' for custom created shapes.
- textures: What textures to apply. For simple blocks you can define one single texture for 'all' faces or define one for every facing ('north', 'east', 'west', 'south', 'up', 'down')
- resistance: How many seconds of real life time it takes to break the block without tools
- sounds: The sounds to be played when placing/breaking or walking on the block. The prefix
game
has to be added, since our block has the domainmygoldblock
. Otherwise it would try to find those sounds inside our domain.
Now save the file in your workspace inside assets/mygoldblock/blocktypes/
and name it mygoldblock.json
.
Naming the Block
To give the block a proper name, we need to create another json file and save it with the following path: assets/mygoldblock/lang/en.json
{
"block-mygoldblock": "Block of Gold"
}
Testing/ Distribution
The last thing we need to do is to create a zip file of the assets folder inside our workspace. Either you use an external program (such as WinRAR or 7Zip) or you right-click the assets
folder and hit Send To -> Compressed (zipped) folder. Eventually you can rename the zip file to MyGoldBlockMod.zip
. The zip file can be either used for testing purposes or you can send it to other people so they can use it as well.
Furthermore you need to add a modinfo.json
file, check out this tutorial.
To install the mod, navigate to the VintagestoryData folder and place it inside the mods folder.
Hint: Use the client command .tfedit
if you want to adjust the block position, rotation and scale in Hands, in GUI, when dropped on the ground or in third person mode.
Advanced Properties
Now we do some more advanced stuff with our lovely gold block. We will add random textures, different variants and custom shapes. So let's get started.
Random Textures
So first of all we need some more textures. I have created some variants of the gold block .
To keep the name of the textures simple I added a number to each texture name (mygoldtexture.png
,mygoldtexture1.png
,mygoldtexture2.png
,mygoldtexture3.png
)
Now we need to add those new textures to the json file.
"textures": {
"all": {
"base": "block/mygoldtexture",
"alternates": [{"base": "block/mygoldtexture1" }, {"base": "block/mygoldtexture2" }, {"base": "block/mygoldtexture3" }],
},
},
Eventually save it and run Vintagestory again. Now you should see a result like this:
Of course you can add more texture if you would like to.
Variants
Gold is the best, but iron is awesome too ... so what shall we do? Let's add another variant of this block, because we all love iron.
You could duplicate the blocktype file and rename silver to gold in all the places, or you can simply add another variant to the existing blocktype.
Variantgroup: Type
So first of all we need some new textures again:
Now we need to change a few things in our json file. We can add all kinds of different groups, but for now we keep it simple. We are adding a variant group called type
, with the states gold
and iron
. You can use any group code you want.
"variantgroups": [
{ "code": "type", "states": ["gold", "iron"] }
],
The next thing we need to do is set textures by type. So we remove our texture
property and replace it with a new property texturesbytype
, which will allow us to set different textures for each type.
"texturesbytype": {
"*-gold": {
"all": {
"base": "block/mygoldtexture",
"alternates": [{"base": "block/mygoldtexture1" }, {"base": "block/mygoldtexture2" }, {"base": "block/mygoldtexture3" }],
},
},
"*-iron": {
"all": {
"base": "block/myirontexture",
"alternates": [{"base": "block/myirontexture1" }, {"base": "block/myirontexture2" }, {"base": "block/myirontexture3" }],
},
}
},
Every group will be added after each other to the blocks code myblockname-mygroup-mysecondgroup
. In our example we can save ourselves writing a few extra letters by using the wild card *
.
You can also use a more compact definition. Due to way we named our textures we can use the placeholder {type} to determine the texture name, so instead of handling every case individually we can write it like this:
"textures": {
"all": {
"base": "block/my{type}texture",
"alternates": [{"base": "block/my{type}texture1" }, {"base": "block/my{type}texture2" }, {"base": "block/my{type}texture3" }],
},
},
The full blocktype definition could then look like this:
{
"code": "myshinyblock",
"creativeinventory": { "general": ["*"] },
"variantgroups": [
{ "code": "type", "states": ["gold", "iron"] }
],
"blockmaterial": "Stone",
"drawtype": "cube",
"textures": {
"all": {
"base": "block/my{type}texture",
"alternates": [{"base": "block/my{type}texture1" }, {"base": "block/my{type}texture2" }, {"base": "block/my{type}texture3" }],
},
},
"resistance": 3.5,
"sounds": {
"place": "game:block/anvil",
"walk": "game:walk/stone"
}
}
Variantgroup: Condition
Let's at another group to our block, which will determine the condition of this block. There will be two states good
and used
. We can add this group by adding another property inside variantgroups[]
.
"variantgroups": [
{ "code": "type", "states": ["gold", "iron"] },
{ "code": "condition", "states": ["good", "used"]}
],
To finish implementing this second group we need to take care of every case. We want the good
blocks to only use the base texture and the used
blocks to also use their random textures:
"texturesbytype": {
"*-good": {
"all": {
"base": "block/my{type}texture",
},
},
"*-used": {
"all": {
"base": "block/my{type}texture",
"alternates": [{"base": "block/my{type}texture1" }, {"base": "block/my{type}texture2" }, {"base": "block/my{type}texture3" }],
},
},
},
The blocks in a good condition or on the left side, while the used ones are on the right:
Custom Shapes
In order to use a custom shape we need to create one first. The engine only supports the model/shape format that's created by the VS Model Creator.
Once you have created your own shape you need to export it as a json file, create a new folder assets/myshinyblock/shapes/block/
and save the file in there. In our example we will use this model Myshinymodel.json and move it to assets/myshinyblock/shapes/block/myshinymodel.json
.
Now we need to specify the model inside our block type json file.
Therefore we will change the drawtype from cube
to json
:
"drawtype": "json",
and the shape to myshinymodel
"shape": { base: "block/myshinymodel" },
Although this would be enough theoretically, we also should determine this block as being non-solid, to prevent graphical glitches.
"sidesolid": {
"all": "false"
},
"sideopaque": {
"all": "false"
},
So let's run the game. This is how it should look like:
Variants of Custom Shapes
I created another model for the blocks in good condition (myshinymodel1.json), because they should look more awesome, than the ones in used conditions. Therefore we need to copy the json file to assets/myshinyblock/shapes/block/
as well.
In order to specify the shape by type we need to remove the property shape
and replace it with shapebytype
:
"shapebytype": {
"*-good": {
"base": "block/myshinymodel1",
},
"*-used": {
"base": "block/myshinymodel",
},
},
Mod Download
You can find the complete mod here for reference:
Moving Forward
The example shown here, while seemingly complex, only scratches the surface of what blocktypes are capable of in Vintage Story. It's highly suggested that you experiment with or at least familiarize yourself with all the known block properties before moving onto code mods. The best way to do this is to peruse the Block Properties page, which contains an ongoing list of all the usable JSON block properties currently incorporated into the game. Most properties in the list also have referenced files you can search for in the Vintage Story Assets folder. If you don't know where this is, you can find tutorials for each operating system at the Asset System page.
If you haven't yet, it's suggested you also check out the Basic Item and Basic Entity pages to learn how simple JSON items and entities are added to the game.
However, if you're feeling like making the jump to code mods then you'll want to start by setting up your Development Environment.
Tutorial Video: How make mod without programming (in Russian)
Thanks to ZigTheHedge for great detailed video
Content Modding | |||||||||
---|---|---|---|---|---|---|---|---|---|
Basics | Content Mods • Developing a Content Mod • Packaging & Release | ||||||||
Tutorials |
|
||||||||
Concepts | Modding Concepts • Modinfo • Variants • Domains • Patching • Remapping • World Properties | ||||||||
Moddable Assets |
|
||||||||
Uncategorized |
|
Wondering where some links have gone?
The modding navbox is going through some changes! Check out Navigation Box Updates for more info and help finding specific pages.
Modding | |
---|---|
Modding Introduction | Getting Started • Theme Pack |
Content Modding | Content Mods • Developing a Content Mod • Basic Tutorials • Intermediate Tutorials • Advanced Tutorials • Content Mod Concepts |
Code Modding | Code Mods • Setting up your Development Environment |
Property Overview | Item • Entity • Entity Behaviors • Block • Block Behaviors • Block Classes • Block Entities • Block Entity Behaviors • Collectible Behaviors • World properties |
Workflows & Infrastructure | Modding Efficiency Tips • Mod-engine compatibility • Mod Extensibility • VS Engine |
Additional Resources | Community Resources • Modding API Updates • Programming Languages • List of server commands • List of client commands • Client startup parameters • Server startup parameters Example Mods • API Docs • GitHub Repository |