https://wiki.vintagestory.at/api.php?action=feedcontributions&user=CreativeMD&feedformat=atomVintage Story Wiki - User contributions [en]2024-03-29T08:05:42ZUser contributionsMediaWiki 1.38.2https://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4922Modding:Setting up your Development Environment2019-06-12T14:06:27Z<p>CreativeMD: /* Get the Modtemplate */</p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.5.4/VSModTemplate-v1.5.4.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (Compiled Zip) =<br />
<br />
Both dll and zip mods have their advantages and disadvantages, so why not combine them together? This project setup is very similar to zip. Instead of adding the source code to the zip file, it uses the compiled dll. This allows you to have all the dll benefits while still having the zip mod asset structure.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid> compiled</code>''<br />
<br />
Adds a compiled zip mod template to your workspace. The difference is that it uses a compiled dll instead of the actual source code. All other commands are equal to the zip ones.<br />
<br />
== Set Mod ==<br />
<br />
''Syntax: <code>set <modid> <source|compiled></code>''<br />
<br />
Sets the given zip mod either to source or compiled. This can be useful if you want to change the type of your mod later on.<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Entity_Json_Properties&diff=4921Modding:Entity Json Properties2019-06-05T14:21:39Z<p>CreativeMD: </p>
<hr />
<div>__NOTOC__<br />
== Overview ==<br />
A complete list of all available properties<br />
<br />
<table id="treeviewtable" class="table table-bordered tt-table" style='table-layout: fixed'><br />
<tr style='background-color: rgba(0,0,0,0.2);'><br />
<th width='300' align='left'>Property</th><br />
<th width='200' align='left'>Type</th><br />
<th width='150' align='left'>Default</th><br />
<th align='left'>Usage</th><br />
</tr><br />
<tr><br />
<td><div class="tt" data-tt-id="root">json</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Core (no byType available)</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code" data-tt-parent="root">code</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>A unique identifier for the entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code_info" data-tt-parent="p_code" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''domain prefix''' will be added dynamically depending on the location of the file. Every mod and VintageStory itself have a unique prefix.<br />
<br />
For example the code '''<code>rabbit</code>''' turns into '''<code>game:rabbit</code>'''. <br />
<br />
The code identifier has to be unique inside its domain. In theory there could be equal identifiers with different domain prefixes.<br />
Find out more about [[Basic Modding#Domains|Domains]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_enabled" data-tt-parent="root">enabled</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the entity will be loaded or not. Can be used to temporarily remove the entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups" data-tt-parent="root">variantgroups</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Allows you define multiple variants of the same entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups_info" data-tt-parent="p_variantgroups" data-invisible="true"></div></td><br />
<td colspan="3"><br />
The variantgroups property allows you to define multiple variants of this entity. All of them will have their unique pattern, which will be added to the entity code.<br />
<br />
An easy example would be a sheep, which can either be small or tall:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"size", states: ["small", "tall"] },<br />
],<br />
</syntaxhighlight><br />
<br />
Meaning there will be two blocks <code>sheep-small</code> and <code>sheep-tall</code>.<br />
<br />
----<br />
<br />
It's also possible to define multiple groups. <br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"size", states: ["small", "tall"] },<br />
{ code:"color", states: ["white", "black"] },<br />
],<br />
</syntaxhighlight><br />
<br />
As a result you will have 2x2 groups, which will be added one after each other: <code>sheep-small-white</code>, <code>sheep-tall-white</code>, <code>sheep-small-black</code> and <code>sheep-tall-black</code>.<br />
<br />
----<br />
<br />
Additionally it is possible to refer to external lists that are found in the worldproperties folder, such as <code>block/rock</code>, which contains all states of all rock types. This used for <code>gravel</code>, <code>sand</code> and <code>rock</code>. It's a good way to keep everything organized:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ loadFromProperties: "block/rock" },<br />
],<br />
</syntaxhighlight><br />
<br />
Here is a full list of all groups and their variants (you can also find them in the <code>assets/worldproperties</code> folder):<br />
{{:json:block:worldvariantgroups}}<br />
<br />
----<br />
<br />
Futhermore there are two ways of combining groups together. So far we covered the default combination mode, which is <code>multiplicative</code> (the total count of variants is the product of all states).<br />
<br />
Imagine you want to implement a living tree, were either flowers, mushrooms or saplings or on it. You can use the <code>additive</code> combination mode for that:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", loadFromProperties: "block/wood" },<br />
{ code: "flower", loadFromProperties: "block/flower", combine: "additive" },<br />
{ code: "mushroom", loadFromProperties: "block/mushroom", combine: "additive" },<br />
{ code: "sapling", loadFromProperties: "block/wood", combine: "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
The living trees exists for every wood type (birch, oak, maple, pine, acacia, kapok) and can either have a flower, mushroom or a sapling suffix: <code>livingtree-{wood type}-{flower}</code>, <code>livingtree-{wood type}-{all flowers}</code>, <code>livingtree-{wood type}-{all mushrooms}</code> and <code>livingtree-{wood type}-{all saplings}</code>.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType" data-tt-parent="root">(any) bytype</div></td><br />
<td>key: string; value: object</td><br />
<td>-</td><br />
<td>You can create properties for certain variants of the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType_info" data-tt-parent="p_byType" data-invisible="true"></div></td><br />
<td colspan="3"><br />
In order to define properties for specific variants you can add '''byType''' to the property name. This allows you to define it depending on the type and always follows the same syntax:<br />
<syntaxhighlight lang="json"><br />
(property)ByType: {<br />
"selector": property,<br />
"selector2": property2,<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
If the selector matches the name of the variant the given property will be used. Keep in mind that only the first matching one will be used (everything below will be ignored).<br />
<br />
An entity for example has two variants ('''big''', '''small'''):<br />
<syntaxhighlight lang="json"><br />
falldamagebyType: {<br />
"*-big": true,<br />
"*-small": false<br />
},<br />
</syntaxhighlight><br />
<br />
Since Vintagestory v1.8 it is also possible to use the variantgroup as a placeholder:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["normal", "bamboo"] },<br />
],<br />
texture: { base: "entity/fish/{type}" }<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Common</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class" data-tt-parent="root">class</div></td><br />
<td>string</td><br />
<td>&quot;entity&quot;</td><br />
<td>The entity class can add special functionalities for the entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class_info" data-tt-parent="p_class" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Can be used to add interaction to the entity or other special functionalities. Example uses are <code>EntityItem</code> and <code>EntityPlayer</code>.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_habitat" data-tt-parent="root">habitat</div></td><br />
<td>string</td><br />
<td>&quot;land&quot;</td><br />
<td>There is <code>sea</code>, <code>land</code> and <code>air</code></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_hitboxsize" data-tt-parent="root">hitboxsize</div></td><br />
<td>object</td><br />
<td>x: 0.125, y: 0.125</td><br />
<td>The size of the hitbox, either to hit the entity or to interact with it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_eyeheight" data-tt-parent="root">eyeheight</div></td><br />
<td>decimal number</td><br />
<td>0.1</td><br />
<td>Height of the eyes, measured from the bottom of the hitbox in meters. Used for camera angle and various other things.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_canclimb" data-tt-parent="root">canclimb</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>Whether the entity can climb on ladders or other blocks which are climbable.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_canclimbanywhere" data-tt-parent="root">canclimbanywhere</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>Whether the entity can climb on any block, doesn't matter if it's a ladder or not.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_falldamage" data-tt-parent="root">falldamage</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>Whether the entity will take fall damage.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_climbtouchdistance" data-tt-parent="root">climbtouchdistance</div></td><br />
<td>decimal number</td><br />
<td>0.5</td><br />
<td>Distance at which the entity can climb on something.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotatemodelonclimb" data-tt-parent="root">rotatemodelonclimb</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If true the entity model will be rotated to face the block its climbing on.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_knockbackresistance" data-tt-parent="root">knockbackresistance</div></td><br />
<td>decimal number</td><br />
<td>0.0</td><br />
<td>The higher the number is the less knockback will be applied. Useful for heavy entities.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes" data-tt-parent="root">attributes</div></td><br />
<td>key: string, value: object</td><br />
<td>-</td><br />
<td>Custom Attributes associated with this entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_info" data-tt-parent="p_attributes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Extra attributes added to the entity. Those are final and cannot be modified. It's a good way to keep things organized and and modifiable. These can be used by behaviors or the entity class:<br />
<syntaxhighlight lang="json"><br />
attributes: {<br />
"attackPower": 10<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds" data-tt-parent="root">sounds</div></td><br />
<td>key: string, value: string</td><br />
<td>-</td><br />
<td>Sounds of the entity, you can also add your own sounds and play them, but here is a list of default sounds used <code>death</code>, <code>hurt</code>, <code>idle</code>, <code>jump</code>, <code>swim</code> and <code>eat</code></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_idlesoundchance" data-tt-parent="root">idlesoundchance</div></td><br />
<td>decimal number</td><br />
<td>0.3</td><br />
<td>How likely it is for the entity to play an idle sound.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_idlesoundrange" data-tt-parent="root">idlesoundrange</div></td><br />
<td>decimal number</td><br />
<td>24</td><br />
<td>How far the idle sound played by the entity can be heard.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drops" data-tt-parent="root">drops</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>The items that should drop from breaking this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drops_info" data-tt-parent="p_drops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<br />
'''No drop'''<br />
<br />
By default an entity does not drop anything at all:<br />
<syntaxhighlight lang="json"><br />
drops: [],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Drop'''<br />
<br />
You can also specify an item or block to drop. Therefore you need to define an '''ItemStack''', with the given properties:<br />
<br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">Property</th><br />
<th style="background-color: rgba(0,0,0,0.2);">Default</th><br />
<th style="background-color: rgba(0,0,0,0.2);">Explanation</th><br />
</tr><br />
<tr><br />
<td>'''type'''</td><br />
<td>''block''</td><br />
<td>Can either be '''''block''''' or '''''item'''''.</td><br />
</tr><br />
<tr><br />
<td>'''code''' (required)</td><br />
<td>-</td><br />
<td>The complete code (can also include domain) of the item or block.</td><br />
</tr><br />
<tr><br />
<td>'''lastdrop'''</td><br />
<td>false</td><br />
<td>If true and the quantity dropped is >=1 any subsequent drop in the list will be ignored.</td><br />
</tr><br />
<tr><br />
<td>'''attributes'''</td><br />
<td>-</td><br />
<td>Tree Attributes that will be attached to the resulting itemstack.</td><br />
</tr><br />
<tr><br />
<td>'''tool'''</td><br />
<td>-</td><br />
<td>If specified then given tool is required to break this block.</td><br />
</tr><br />
<tr><br />
<td>'''quantity'''</td><br />
<td>- (one)</td><br />
<td>Determines the quantity of items which will be dropped.</td><br />
</tr><br />
</table><br />
<br />
For example, if the entity should drop '''charcoalpile''':<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "charcoal" }<br />
],<br />
</syntaxhighlight><br />
<br />
You can also specify drop special itemstack if the entity is killed by certain tool, similar to '''Tallgrass''' which only drops something if it's mined by a knife:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "drygrass", tool: "knife" },<br />
],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Chance drops'''<br />
<br />
Let's take a look at an example. This is the drop property of rock:<br />
<br />
<syntaxhighlight lang="json"> <br />
drops: [<br />
{<br />
type: "item", <br />
code: "stone-{rock}", <br />
quantity: { avg: 2.5, var: 0.5 } <br />
},<br />
]<br />
</syntaxhighlight><br />
<br />
This will drop 2-3 blocks.<br />
<br />
'''''avg''''': Stands for the default drop quantity. If var is 0 or not specified it will always drop the given average.<br />
<br />
'''''var''''': How much the drop rate can vary. Meaning the drop rate can be <code>avg - var</code> at minimum and <code>age + var</code> at maximum.<br />
<br />
Furthermore you can also switch between different distribution modes using the '''''dist''''' property.<br />
<br />
<table class="wikitable mw-collapsible mw-collapsed"><br />
<tr><br />
<th colspan="2">Overview - Distribution modes</th><br />
</tr><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">Name</th><br />
<th style="background-color: rgba(0,0,0,0.2);">Explanation</th><br />
</tr><br />
<tr><br />
<td>'''uniform'''</td><br />
<td>''Select completely random numbers within avg-var until avg+var.''</td><br />
</tr><br />
<tr><br />
<td>'''triangle'''</td><br />
<td>''Select random numbers with numbers near avg being the most commonly selected ones, following a triangle curve.''</td><br />
</tr><br />
<tr><br />
<td>'''gaussian'''</td><br />
<td>''Select random numbers with numbers near avg being the most commonly selected ones, following a gaussian curve.''</td><br />
</tr><br />
<tr><br />
<td>'''narrowgaussian'''</td><br />
<td>''Select random numbers with numbers near avg being the most commonly selected ones, following a narrow gaussian curve.''</td><br />
</tr><br />
<tr><br />
<td>'''inversegaussian'''</td><br />
<td>''Select random numbers with numbers near avg being the least commonly selected ones, following an upside down gaussian curve.''</td><br />
</tr><br />
<tr><br />
<td>'''narrowinversegaussian'''</td><br />
<td>''Select random numbers with numbers near avg being the least commonly selected ones, following an upside down gaussian curve.''</td><br />
</tr><br />
<tr><br />
<td>'''invexp'''</td><br />
<td>''Select numbers in the form of avg + var, wheras low value of var are preferred.''</td><br />
</tr><br />
<tr><br />
<td>'''stronginvexp'''</td><br />
<td>''Select numbers in the form of avg + var, wheras low value of var are strongly preferred.''</td><br />
</tr><br />
<tr><br />
<td>'''strongerinvexp'''</td><br />
<td>''Select numbers in the form of avg + var, wheras low value of var are very strongly preferred.''</td><br />
</tr><br />
<tr><br />
<td>'''dirac'''</td><br />
<td>''Select completely random numbers within avg-var until avg+var only ONCE and then always 0.''</td><br />
</tr><br />
</table><br />
<br />
----<br />
<br />
'''Multiple Drops'''<br />
<br />
Of course you can also define multiple drops at once. A '''Sapling''' for example can drop a sapling and a stick:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ <br />
type: "block", <br />
code: "sapling-{wood}",<br />
quantity: { avg: 0.02, var: 0 },<br />
},<br />
{ <br />
type: "item", <br />
code: "stick",<br />
quantity: { avg: 0.02, var: 0 },<br />
}<br />
],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Last Drop'''<br />
<br />
In order to add a special drop, which (if dropped) prevents all other drops, you can use the lastDrop property:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "stick", quantity: { avg: 0.2, var: 0 }, lastDrop: true },<br />
{ type: "item", code: "sapling", quantity: { avg: 1.25, var: 0 } }<br />
],<br />
</syntaxhighlight><br />
<br />
The entity will either drop a stick with a chance of 20% or an average of 1.25 saplings.<br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>client: {</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_renderer" data-tt-parent="root">renderer</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>Name of there renderer system that draws this entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_texture" data-tt-parent="root">texture</div></td><br />
<td>object</td><br />
<td></td><br />
<td>The texture of the entity. It will overwrite all textures of the shape.</td><br />
</tr><br />
<tr><br />
<td scope="row" valign="top"><div class="tt" data-tt-id="p_texture_base" data-tt-parent="p_texture">base</div><br><br><div class="tt" data-tt-id="p_texture_overlays" data-tt-parent="p_texture">overlays</div><br><br><div class="tt" data-tt-id="p_texture_base" data-tt-parent="p_texture">alternates</div></td><br />
<td colspan="3">Default example (player model): <syntaxhighlight lang='json'>texture: {<br />
base: "entity/humanoid/player"<br />
}</syntaxhighlight><br />
Using variantgroups (rock):<syntaxhighlight lang='json'>texture: {<br />
base: "entity/humanoid/player-{type}"<br />
}</syntaxhighlight><br />
Overlay texutre: <syntaxhighlight lang='json'><br />
texture: {<br />
base: "entity/humanoid/player-{type}",<br />
overlays: [ "entity/humanoid/player-{type}-overlay" ],<br />
}</syntaxhighlight><br />
Random textures: <br />
<syntaxhighlight lang='json'><br />
texture: {<br />
base: "entity/humanoid/player-{type}",<br />
alternates: [<br />
{ base: "entity/humanoid/player-{type}2" },<br />
{ base: "entity/humanoid/player-{type}3"}<br />
]<br />
}</syntaxhighlight><br />
Random textures and overlays combined:<br />
<syntaxhighlight lang='json'><br />
texture: {<br />
base: "entity/humanoid/player-{type}",<br />
overlays: [ "entity/humanoid/player-{type}-overlay" ],<br />
alternates: [<br />
{ base: "entity/humanoid/player-{type}2", overlays: [ "entity/humanoid/player-{type}2-overlay" ] },<br />
{ base: "entity/humanoid/player-{type}3", overlays: [ "entity/humanoid/player-{type}3-overlay" ] }<br />
]<br />
}</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_textures" data-tt-parent="root">textures</div></td><br />
<td>key: string, value: object</td><br />
<td></td><br />
<td>Can be used to replace specific textures of the shape.</td><br />
</tr><br />
<tr><br />
<td scope="row" valign="top"><div class="tt" data-tt-id="p_textures_base" data-tt-parent="p_textures">base</div><br><br><div class="tt" data-tt-id="p_textures_overlays" data-tt-parent="p_textures">overlays</div><br><br><div class="tt" data-tt-id="p_textures_base" data-tt-parent="p_textures">alternates</div></td><br />
<td colspan="3">Replace <code>arrow</code> texture of the shape, the <code>stick</code> texture remains untouched: <syntaxhighlight lang='json'> textures: {<br />
"arrow": { <br />
base: "entity/arrow/stone"<br />
}<br />
}</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shape" data-tt-parent="root">shape</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>The shape of the entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_base" data-tt-parent="p_shape">base</div></td><br />
<td></td><br />
<td></td><br />
<td>The path to the shape json file, the base dir is <code>assets/shapes/</code>. <syntaxhighlight lang='json'>shape: { base: "entity/arrow" }</syntaxhighlight></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_glowlevel" data-tt-parent="root">glowlevel</div></td><br />
<td>0 ... 255</td><br />
<td>0</td><br />
<td>Causes the entity to visually glow if Bloom is enabled.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_size" data-tt-parent="root">size</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>Can be used to scale the entity up or down.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors_client" data-tt-parent="root">behaviors</div></td><br />
<td>array of object</td><br />
<td></td><br />
<td>A behavior adds custom abilities to the entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors_client_info" data-tt-parent="p_behaviors_client" data-invisible="true"></div></td><br />
<td colspan="3"><br />
{{:json:entity:behavior}}<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations" data-tt-parent="root">animations</div></td><br />
<td>array of object</td><br />
<td></td><br />
<td>WIP</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_code" data-tt-parent="p_animations">code</div></td><br />
<td>string</td><br />
<td></td><br />
<td>The identifier of the animation.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_animation" data-tt-parent="p_animations">animation</div></td><br />
<td>string</td><br />
<td></td><br />
<td>The animation code identifier to play.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_weight" data-tt-parent="p_animations">weight</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>Animations with a high weight value will be prioritized over the other animations when the animations are combined.<br />
For example if the player aims with a bow while jumping around, the aiming animation has a higher weight (for the upper body) so the jumping animation will be reduced.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_code" data-tt-parent="p_animations">elementweight</div></td><br />
<td>key: string, value: decimal number</td><br />
<td></td><br />
<td>Allows you to specify a weight for each element individually.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_animationspeed" data-tt-parent="p_animations">animationspeed</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>The speed of the animation.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_mulwithwalkspeed" data-tt-parent="p_animations">mulwithwalkspeed</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>Whether the animation should be affected by the walk speed.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_easeinspeed" data-tt-parent="p_animations">easeinspeed</div></td><br />
<td>decimal number</td><br />
<td>10</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_easeoutspeed" data-tt-parent="p_animations">easeoutspeed</div></td><br />
<td>decimal number</td><br />
<td>10</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby" data-tt-parent="p_animations">triggeredby</div></td><br />
<td></td><br />
<td></td><br />
<td>Specifies by what the animation is triggered.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols" data-tt-parent="p_animations_triggeredby">oncontrols</div></td><br />
<td>array of object</td><br />
<td></td><br />
<td>An array of activities.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_none" data-tt-parent="p_animations_triggeredby_oncontrols">none</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_idle" data-tt-parent="p_animations_triggeredby_oncontrols">idle</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_move" data-tt-parent="p_animations_triggeredby_oncontrols">move</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_sprintmode" data-tt-parent="p_animations_triggeredby_oncontrols">sprintmode</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_sneakmode" data-tt-parent="p_animations_triggeredby_oncontrols">sneakmode</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_fly" data-tt-parent="p_animations_triggeredby_oncontrols">fly</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_swim" data-tt-parent="p_animations_triggeredby_oncontrols">swim</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_jump" data-tt-parent="p_animations_triggeredby_oncontrols">jump</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_fall" data-tt-parent="p_animations_triggeredby_oncontrols">fall</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_climb" data-tt-parent="p_animations_triggeredby_oncontrols">climb</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_floorsitting" data-tt-parent="p_animations_triggeredby_oncontrols">floorsitting</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_dead" data-tt-parent="p_animations_triggeredby_oncontrols">dead</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_break" data-tt-parent="p_animations_triggeredby_oncontrols">break</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_oncontrols_place" data-tt-parent="p_animations_triggeredby_oncontrols">place</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_matchexact" data-tt-parent="p_animations_triggeredby">matchexact</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_triggeredby_defaultanim" data-tt-parent="p_animations_triggeredby">defaultanim</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_blendmode" data-tt-parent="p_animations">blendmode</div></td><br />
<td>string</td><br />
<td></td><br />
<td>Animation blend mode for all elements.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_blendmode_add" data-tt-parent="p_animations_blendmode">add</div></td><br />
<td></td><br />
<td></td><br />
<td>Add the animation without taking other animations into considerations.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_blendmode_average" data-tt-parent="p_animations_blendmode">average</div></td><br />
<td></td><br />
<td></td><br />
<td>Add the pose and average it together with all other running animations with blendmode Average or AddAverage.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_blendmode_addaverage" data-tt-parent="p_animations_blendmode">addaverage</div></td><br />
<td></td><br />
<td></td><br />
<td>Add the animation without taking other animations into consideration, but add it's weight for averaging.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_animations_elementblendmode" data-tt-parent="p_animations">elementblendmode</div></td><br />
<td>key: string, value: string</td><br />
<td></td><br />
<td>Allows you to specify a blend mode for each element individually.</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>}</b></td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>server: {</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_server" data-tt-parent="root">attributes</div></td><br />
<td>key: string, value: object</td><br />
<td>-</td><br />
<td>Custom Attributes associated with this entity only known by the server. They will not be send to the client.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_server_info" data-tt-parent="p_attributes_server" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Extra attributes added to the entity for server use only. Those are final and cannot be modified. It's a good way to keep things organized and and modifiable. These can be used by behaviors or the entity class:<br />
<syntaxhighlight lang="json"><br />
attributes: {<br />
"attackPower": 10<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors_server" data-tt-parent="root">behaviors</div></td><br />
<td>array of object</td><br />
<td></td><br />
<td>A behavior adds custom abilities to the entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors_server_info" data-tt-parent="p_behaviors_server" data-invisible="true"></div></td><br />
<td colspan="3"><br />
{{:json:entity:behavior}}<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions" data-tt-parent="root">spawnConditions</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Specifies the circumstances of the entity spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime" data-tt-parent="p_spawnconditions">runtime</div></td><br />
<td>object</td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_group" data-tt-parent="p_spawnconditions_runtime">group</div></td><br />
<td>string</td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_chance" data-tt-parent="p_spawnconditions_runtime">chance</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>How long it takes to make an attempt to spawn the entity: 1.0 -> 4 seconds, 0.1 -> 40 seconds.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_maxquantity" data-tt-parent="p_spawnconditions_runtime">maxquantity</div></td><br />
<td>integer</td><br />
<td>20</td><br />
<td>Maximum number of entities inside the chunk, if this is exceeded the entity will not spawn there.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_mindistancetoplayer" data-tt-parent="p_spawnconditions_runtime">mindistancetoplayer</div></td><br />
<td>integer</td><br />
<td>18</td><br />
<td>Minimum distance the entity can spawn away from the player.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_minlightlevel" data-tt-parent="p_spawnconditions_runtime">minlightlevel</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_maxlightlevel" data-tt-parent="p_spawnconditions_runtime">maxlightlevel</div></td><br />
<td>integer</td><br />
<td>32</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_lightleveltype" data-tt-parent="p_spawnconditions_runtime" data-hide="true">lightleveltype</div></td><br />
<td>string</td><br />
<td>&quot;MaxLight&quot;</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_group_onlyblocklight" data-tt-parent="p_spawnconditions_runtime_lightleveltype">onlyblocklight</div></td><br />
<td></td><br />
<td></td><br />
<td>Will get you just the block light</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_group_onlysunLight" data-tt-parent="p_spawnconditions_runtime_lightleveltype">onlysunlight</div></td><br />
<td></td><br />
<td></td><br />
<td>Will get you just the sun light unaffected by the day/night cycle</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_group_maxlight" data-tt-parent="p_spawnconditions_runtime_lightleveltype">maxlight</div></td><br />
<td></td><br />
<td></td><br />
<td>Will get you max(onlysunlight, onlyblocklight)</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_group_maxtimeofdaylight" data-tt-parent="p_spawnconditions_runtime_lightleveltype">maxtimeofdaylight</div></td><br />
<td></td><br />
<td></td><br />
<td>Will get you max(sunlight * sunbrightness, blocklight)</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_groupsize" data-tt-parent="p_spawnconditions_runtime">groupsize</div></td><br />
<td>object</td><br />
<td><code>{ avg: 1, var: 0 } </code></td><br />
<td>Determines the size of the group. By default the size of the group is always one. Find out more about the [[Json Random Generator|random generator]].</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_companions" data-tt-parent="p_spawnconditions_runtime">companions</div></td><br />
<td>array of string</td><br />
<td>-</td><br />
<td>Codes of all possible companions.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_insideblockcodes" data-tt-parent="p_spawnconditions_runtime">insideblockcodes</div></td><br />
<td>array of string</td><br />
<td><code>[ "game:air" ]</code></td><br />
<td>The block codes in which the entity can spawn. Entities which can spawn underwater might use <code>[ "game:water" ]</code> instead.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_requiresolidground" data-tt-parent="p_spawnconditions_runtime">requiresolidground</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the entity requires a solid block below it. For example birds and fishes do not require it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_tryonlysurface" data-tt-parent="p_spawnconditions_runtime">tryonlysurface</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If false the game will also try to spawn the entity below the surface (in a cave for example). For ordinary animals this should be true so they only spawn on the surface.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_mintemp" data-tt-parent="p_spawnconditions_runtime">mintemp</div></td><br />
<td>integer</td><br />
<td>-40</td><br />
<td>Minimum temperature at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_maxtemp" data-tt-parent="p_spawnconditions_runtime">maxtemp</div></td><br />
<td>integer</td><br />
<td>40</td><br />
<td>Maximum temperature at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_minrain" data-tt-parent="p_spawnconditions_runtime">minrain</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>Minimum rain average at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_maxrain" data-tt-parent="p_spawnconditions_runtime">maxrain</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>Maximum rain average at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_minforest" data-tt-parent="p_spawnconditions_runtime">minforest</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>Minimum forest density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_maxforest" data-tt-parent="p_spawnconditions_runtime">maxforest</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>Maximum forest density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_minshrubs" data-tt-parent="p_spawnconditions_runtime">minshrubs</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>Minimum shrubs density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_maxshrubs" data-tt-parent="p_spawnconditions_runtime">maxshrubs</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>Maximum shrubs density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_runtime_minforestorshrubs" data-tt-parent="p_spawnconditions_runtime">minforestorshrubs</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>Minimum shrubs or forest density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen" data-tt-parent="p_spawnconditions">worldgen</div></td><br />
<td>object</td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_group" data-tt-parent="p_spawnconditions_worldgen">group</div></td><br />
<td>string</td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_triesperchunk" data-tt-parent="p_spawnconditions_worldgen">triesperchunk</div></td><br />
<td>object</td><br />
<td>zero</td><br />
<td>How many tries per chunk the entity has to spawn. Find out more about the [[Json Random Generator|random generator]].</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_minlightlevel" data-tt-parent="p_spawnconditions_worldgen">minlightlevel</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_maxlightlevel" data-tt-parent="p_spawnconditions_worldgen">maxlightlevel</div></td><br />
<td>integer</td><br />
<td>32</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_lightleveltype" data-tt-parent="p_spawnconditions_worldgen" data-hide="true">lightleveltype</div></td><br />
<td>string</td><br />
<td>&quot;MaxLight&quot;</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_group_onlyblocklight" data-tt-parent="p_spawnconditions_worldgen_lightleveltype">onlyblocklight</div></td><br />
<td></td><br />
<td></td><br />
<td>Will get you just the block light</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_group_onlysunLight" data-tt-parent="p_spawnconditions_worldgen_lightleveltype">onlysunlight</div></td><br />
<td></td><br />
<td></td><br />
<td>Will get you just the sun light unaffected by the day/night cycle</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_group_maxlight" data-tt-parent="p_spawnconditions_worldgen_lightleveltype">maxlight</div></td><br />
<td></td><br />
<td></td><br />
<td>Will get you max(onlysunlight, onlyblocklight)</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_group_maxtimeofdaylight" data-tt-parent="p_spawnconditions_worldgen_lightleveltype">maxtimeofdaylight</div></td><br />
<td></td><br />
<td></td><br />
<td>Will get you max(sunlight * sunbrightness, blocklight)</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_groupsize" data-tt-parent="p_spawnconditions_worldgen">groupsize</div></td><br />
<td>object</td><br />
<td><code>{ avg: 1, var: 0 } </code></td><br />
<td>Determines the size of the group. By default the size of the group is always one. Find out more about the [[Json Random Generator|random generator]].</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_companions" data-tt-parent="p_spawnconditions_worldgen">companions</div></td><br />
<td>array of string</td><br />
<td>-</td><br />
<td>Codes of all possible companions.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_insideblockcodes" data-tt-parent="p_spawnconditions_worldgen">insideblockcodes</div></td><br />
<td>array of string</td><br />
<td><code>[ "game:air" ]</code></td><br />
<td>The block codes in which the entity can spawn. Entities which can spawn underwater might use <code>[ "game:water" ]</code> instead.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_requiresolidground" data-tt-parent="p_spawnconditions_worldgen">requiresolidground</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the entity requires a solid block below it. For example birds and fishes do not require it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_tryonlysurface" data-tt-parent="p_spawnconditions_worldgen">tryonlysurface</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If false the game will also try to spawn the entity below the surface (in a cave for example). For ordinary animals this should be true so they only spawn on the surface.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_mintemp" data-tt-parent="p_spawnconditions_worldgen">mintemp</div></td><br />
<td>integer</td><br />
<td>-40</td><br />
<td>Minimum temperature at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_maxtemp" data-tt-parent="p_spawnconditions_worldgen">maxtemp</div></td><br />
<td>integer</td><br />
<td>40</td><br />
<td>Maximum temperature at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_minrain" data-tt-parent="p_spawnconditions_worldgen">minrain</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>Minimum rain average at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_maxrain" data-tt-parent="p_spawnconditions_worldgen">maxrain</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>Maximum rain average at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_minforest" data-tt-parent="p_spawnconditions_worldgen">minforest</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>Minimum forest density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_maxforest" data-tt-parent="p_spawnconditions_worldgen">maxforest</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>Maximum forest density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_minshrubs" data-tt-parent="p_spawnconditions_worldgen">minshrubs</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>Minimum shrubs density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_maxshrubs" data-tt-parent="p_spawnconditions_worldgen">maxshrubs</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>Maximum shrubs density at which the entity can spawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_spawnconditions_worldgen_minforestorshrubs" data-tt-parent="p_spawnconditions_worldgen">minforestorshrubs</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>Minimum shrubs or forest density at which the entity can spawn.</td><br />
</tr><br />
<br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>}</b></td><br />
</tr><br />
</table><br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Item_Json_Properties&diff=4920Modding:Item Json Properties2019-06-05T14:12:27Z<p>CreativeMD: </p>
<hr />
<div>__NOTOC__<br />
== Overview ==<br />
A complete list of all available properties<br />
<br />
<table id="treeviewtable" class="table table-bordered tt-table" style='table-layout: fixed'><br />
<tr style='background-color: rgba(0,0,0,0.2);'><br />
<th width='300' align='left'>Property</th><br />
<th width='200' align='left'>Type</th><br />
<th width='120' align='left'>Default</th><br />
<th align='left'>Usage</th><br />
</tr><br />
<tr><br />
<td><div class="tt" data-tt-id="root">json</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Core (no byType available)</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code" data-tt-parent="root">code</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>A unique identifier for the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code_info" data-tt-parent="p_code" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''domain prefix''' will be added dynamically depending on the location of the file. Every mod and VintageStory itself have a unique prefix.<br />
<br />
For example the code '''<code>stone</code>''' turns into '''<code>game:stone</code>'''. <br />
<br />
The code identifier has to be unique inside its domain. In theory there could be equal identifiers with different domain prefixes.<br />
Find out more about [[Basic Modding#Domains|Domains]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_enabled" data-tt-parent="root">enabled</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the item will be loaded or not. Can be used to temporarily remove the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups" data-tt-parent="root">variantgroups</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Allows you define multiple variants of the same item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups_info" data-tt-parent="p_variantgroups" data-invisible="true"></div></td><br />
<td colspan="3"><br />
The variantgroups property allows you to define multiple variants of this item. All of them will have their unique pattern, which will be added to the item code.<br />
<br />
An easy example would be a bowl, which can either be raw or burned:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"type", states: ["raw", "burned"] },<br />
],<br />
</syntaxhighlight><br />
<br />
Meaning there will be two variants <code>bowl-raw</code> and <code>bowl-burned</code>.<br />
<br />
----<br />
<br />
It's also possible to define multiple groups. <br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"state", states: ["closed", "opened"] },<br />
{ code:"contents", states: ["empty", "cabbage"] },<br />
],<br />
</syntaxhighlight><br />
<br />
As a result you will have 2x2 groups, which will be added one after each other: <code>barrel-closed-empty</code>, <code>barrel-closed-cabbage</code>, <code>barrel-opened-empty</code> and <code>barrel-opened-cabbage</code>.<br />
<br />
----<br />
<br />
Additionally it is possible to refer to external lists (used for blocks) that are found in the worldproperties folder, such as <code>block/rock</code>, which contains all states of all rock types. This used for <code>gravel</code>, <code>sand</code> and <code>rock</code>. It's a good way to keep everything organized:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ loadFromProperties: "block/rock" },<br />
],<br />
</syntaxhighlight><br />
<br />
Here is a full list of all groups and their variants (you can also find them in the <code>assets/worldproperties</code> folder):<br />
{{:json:block:worldvariantgroups}}<br />
<br />
----<br />
<br />
Furthermore there are two ways of combining groups together. So far we covered the default combination mode, which is <code>multiplicative</code> (the total count of variants is the product of all states).<br />
<br />
Let's take a look at a different example (flowerpot), which uses the <code>additive</code> combination mode:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["raw"] },<br />
{ code: "empty", states: ["empty"], combine: "additive" },<br />
{ code: "flower", loadFromProperties: "block/flower", combine: "additive" },<br />
{ code: "mushroom", loadFromProperties: "block/mushroom", combine: "additive" },<br />
{ code: "sapling", loadFromProperties: "block/wood", combine: "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
The variants are <code>flowerpot-raw</code>, <code>flowerpot-empty</code>, <code>flowerpot-{all flowers}</code>, <code>flowerpot-{all mushrooms}</code> and <code>flowerpot-{all saplings}</code>.<br />
<br />
<code>Additive</code> mode could also be called separate, since it defines a variant separate from all the other groups:<br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "something", states: ["same", "different"] },<br />
{ code: "type", states: ["raw", "baked"] },<br />
{ code: "empty", states: ["red", "green"], "combine": "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
In this case, the result would be <code>same-raw</code>, <code>same-baked</code>, <code>different-raw</code>, <code>different-baked</code>, <code>red</code> and <code>green</code><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType" data-tt-parent="root">(any) bytype</div></td><br />
<td>key: string; value: object</td><br />
<td>-</td><br />
<td>You can create properties for certain variants of the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType_info" data-tt-parent="p_byType" data-invisible="true"></div></td><br />
<td colspan="3"><br />
In order to define properties for specific variants you can add '''byType''' to the property name. This allows you to define it depending on the type and always follows the same syntax:<br />
<syntaxhighlight lang="json"><br />
(property)ByType: {<br />
"selector": property,<br />
"selector2": property2,<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
If the selector matches the name of the variant the given property will be used. Keep in mind that only the first matching one will be used (everything below will be ignored).<br />
<br />
A slab for example has two variants ('''up''', '''down'''), which have different collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
The char '''<code>*</code>''' stands for anything. In this case it ignores the code of the item.<br />
<br />
Furthermore this opens up even more possbilities for more advanced selectors like this one for doors:<br />
<code>*-north-*-opened-left</code>. This will ignore the second variantgroup. Additionally ByType can also be used for child properties:<br />
<syntaxhighlight lang="json"><br />
collisionboxnbox: { <br />
x1: 0, y1: 0, z1: 0.875, x2: 1, y2: 1, z2: 1,<br />
rotateYByType: {<br />
"*-north-*-opened-left": 90,<br />
"*-north-*-closed-left": 0,<br />
"*-west-*-opened-left": 180,<br />
"*-west-*-closed-left": 90,<br />
<br />
"*-east-*-opened-left": 0,<br />
"*-east-*-closed-left": 270,<br />
"*-south-*-opened-left": 270,<br />
"*-south-*-closed-left": 180,<br />
<br />
"*-north-*-opened-right": 270,<br />
"*-north-*-closed-right": 0,<br />
"*-west-*-opened-right": 0,<br />
"*-west-*-closed-right": 90,<br />
<br />
"*-east-*-opened-right": 180,<br />
"*-east-*-closed-right": 270,<br />
"*-south-*-opened-right": 90,<br />
"*-south-*-closed-right": 180<br />
}<br />
},<br />
</syntaxhighlight><br />
<br />
Since Vintagestory v1.8 it is also possible to use the variantgroup as a placeholder:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "metal", states: ["copper", "tinbronze", "bismuthbronze", "blackbronze", "gold", "silver", "iron" ] },<br />
],<br />
textures: {<br />
"metal": { base: "block/metal/ingot/{metal}" },<br />
"wood": { base: "item/tool/material/wood" } <br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Specific</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class" data-tt-parent="root">class</div></td><br />
<td>string</td><br />
<td>&quot;item&quot;</td><br />
<td>The item class can add special functionalities for the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class_info" data-tt-parent="p_class" data-invisible="true"></div></td><br />
<td colspan="3"><br />
It can be used to open guis or adding other extra functionality to the item. A complete tutorial of how to add your own class to the game can be found [[Advanced Items|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_durability" data-tt-parent="root">durability</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>How many uses does this item has when being used. Item disappears at durability 0.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby" data-tt-parent="root">damagedby</div></td><br />
<td>array of string</td><br />
<td>-</td><br />
<td>From which damage sources does the item takes durability damage.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_blockbreaking" data-tt-parent="p_damagedby">blockbreaking</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Mining a block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_attacking" data-tt-parent="p_damagedby">attacking</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_fire" data-tt-parent="p_damagedby">fire</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Currently not used.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool" data-tt-parent="root">tool</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>If set, this item will be classified as given tool.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_knife" data-tt-parent="p_tool">Knife</div></td><br />
<td></td><br />
<td>0</td><br />
<td>USed to break grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_pickaxe" data-tt-parent="p_tool">Pickaxe</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Can mine rock and other stone materials</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_axe" data-tt-parent="p_tool">Axe</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Useful for chopping trees.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_sword" data-tt-parent="p_tool">Sword</div></td><br />
<td></td><br />
<td>3</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_shovel" data-tt-parent="p_tool">Shovel</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Mines dirt, sand and gravel really fast.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_hammer" data-tt-parent="p_tool">Hammer</div></td><br />
<td></td><br />
<td>5</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_mallet" data-tt-parent="p_tool">Mallet</div></td><br />
<td></td><br />
<td>6</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_spear" data-tt-parent="p_tool">Spear</div></td><br />
<td></td><br />
<td>7</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_bow" data-tt-parent="p_tool">Bow</div></td><br />
<td></td><br />
<td>8</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_sickle" data-tt-parent="p_tool">Sickle</div></td><br />
<td></td><br />
<td>9</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_hoe" data-tt-parent="p_tool">Hoe</div></td><br />
<td></td><br />
<td>10</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_saw" data-tt-parent="p_tool">Saw</div></td><br />
<td></td><br />
<td>11</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Common</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory" data-tt-parent="root">creativeinventory</div></td><br />
<td>key: string, value: string[]</td><br />
<td>-</td><br />
<td>In which creative inventory tabs the item should be visible in.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory_info" data-tt-parent="p_creativeinventory" data-invisible="true"></div></td><br />
<td colspan="3"><br />
There are several tabs to you can add your stuff. Note that general should always be included, since it should contain everything.<br />
<br />
*general<br />
*terrain<br />
*flora<br />
*construction<br />
*decorative<br />
*items<br />
<br />
'''Rock''' adds all of it's variantions to general, terrain and construction:<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*"], "terrain": ["*"], "construction": ["*"] },<br />
</syntaxhighlight><br />
<br />
'''<code>*</code>''' reprents the variants which will be added. You can specify multiple and separate them with a comma. It follows the same way as the '''byType''' property.<br />
<br />
A '''Torch''' on the other hand only adds the variation '''<code>up</code>''':<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*-up"], "decorative": ["*-up"] },<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_maxstacksize" data-tt-parent="root">maxstacksize</div></td><br />
<td>integer</td><br />
<td>64</td><br />
<td>Determines the maximum amount you can stack the item in one slot.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackpower" data-tt-parent="root">attackpower</div></td><br />
<td>decimal number</td><br />
<td>0.5</td><br />
<td>The damage the deals when hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackrange" data-tt-parent="root">attackrange</div></td><br />
<td>decimal number</td><br />
<td>1.5</td><br />
<td>The maximum distance you can hit an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity" data-tt-parent="root">materialdensity</div></td><br />
<td>integer</td><br />
<td>9999</td><br />
<td>Determines on whether an object floats on liquids or not.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity_info" data-tt-parent="p_materialdensity" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Water has a density of 1000, meaning everything below or equal will float on water. The same goes for lava which has a density of 5000.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable" data-tt-parent="root">liquidselectable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If the item can select a liquid while holding it in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable_info" data-tt-parent="p_liquidselectable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Used for buckets in order to fill it with water and to place waterlily on top of water.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningspeed</div></td><br />
<td>key: string, value: decimal number</td><br />
<td>-</td><br />
<td>The mining speed for each material.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningtier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Determines which blocks it can break. If the required miningtier is above the defined one there will be no drop from it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes" data-tt-parent="root">attributes</div></td><br />
<td>key: string, value: object</td><br />
<td>-</td><br />
<td>Custom Attributes associated with this item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_info" data-tt-parent="p_attributes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Extra attributes added to a item or block. Those are final and cannot be modified. It's a good way to keep things organized and and modifiable. The '''oreblastingbomb''' for example has attributes, which define its radius and type. These can be used by behaviors and blockentities:<br />
<syntaxhighlight lang="json"><br />
attributes: {<br />
"blastRadius": 4,<br />
"blastType": 0,<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops" data-tt-parent="root">combustibleprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the items burnable states.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burntemperature" data-tt-parent="p_combustibleprops">burntemperature</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>The temperature at which it burns in degrees celsius.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burnduration" data-tt-parent="p_combustibleprops">burnduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how long it burns in seconds.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_heatresistance" data-tt-parent="p_combustibleprops">heatresistance</div></td><br />
<td>integer</td><br />
<td>500</td><br />
<td>How many degrees celsius it can resists before it ignites (not implemented yet).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingpoint" data-tt-parent="p_combustibleprops">meltingpoint</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>How many degrees celsius it takes to smelt/transform this into another. Only used when put in a stove and Melted is set.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingduration" data-tt-parent="p_combustibleprops">meltingduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how many seconds the temperature has to be above the melting point until the item is smelted.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smokelevel" data-tt-parent="p_combustibleprops">smokelevel</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>How much smoke this item produces when being used as fuel.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smeltedratio" data-tt-parent="p_combustibleprops">smeltedratio</div></td><br />
<td>integer</td><br />
<td>1</td><br />
<td>How many ores are required to produce one output stack.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="p_combustibleprops">smeltedstack</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>If set, the block/item is smeltable in a furnace and this is the resulting itemstack once the MeltingPoint has been reached for the supplied duration.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requirescontainer" data-tt-parent="p_combustibleprops">requirescontainer</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If set to true, the block/item requires a smelting/cooking/baking container such as the Crucible. If false, it can be directly baked/melted without smelting/cooking/baking container.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops_info" data-tt-parent="p_combustibleprops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
This property can be used to define a burning material. '''Plank''' for example can get on fire:<br />
<syntaxhighlight lang="json"><br />
combustibleProps: {<br />
burnTemperature: 800,<br />
burnDuration: 12,<br />
},<br />
</syntaxhighlight><br />
<br />
Furthermore it can be used to define smelting processes. An example would be an '''ingotmold''' which turns into an ingotmold-burned:<br />
<syntaxhighlight lang="json"><br />
combustiblePropsByType: {<br />
"ingotmold-raw": {<br />
meltingPoint: 600,<br />
meltingDuration: 30,<br />
smeltedRatio: 1,<br />
smeltedStack: { type: "block", code: "ingotmold-burned" },<br />
requiresContainer: false<br />
}<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops" data-tt-parent="root">nutritionprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the items nutrients.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_foodcategory" data-tt-parent="p_nutritionprops">foodcategory</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>Defines the type of food. It can be '''''fruit''''', '''''vegetable''''', '''''protein''''', '''''grain''''' and '''''dairy'''''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_saturation" data-tt-parent="p_nutritionprops">saturation</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much saturation it can restore.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_health" data-tt-parent="p_nutritionprops">health</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much health it can restore.</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Rendering</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_textures" data-tt-parent="root">textures</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>The texture definitions for the item held in hand or dropped on the ground.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shape" data-tt-parent="root">shape</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>The items shape. Empty for automatic shape based on the texture.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shapeinventory" data-tt-parent="root">shapeinventory</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>The items shape in inventory.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_guitransform" data-tt-parent="root">guiTransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in guis.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fphandtransform" data-tt-parent="root">fphandtransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in the first person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tphandtransform" data-tt-parent="root">tphandtransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in the third person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_groundtransform" data-tt-parent="root">groundtransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the rendered as a dropped item on the ground.</td><br />
</tr><br />
</table><br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Item_Json_Properties&diff=4919Modding:Item Json Properties2019-06-05T14:11:57Z<p>CreativeMD: </p>
<hr />
<div>__NOTOC__<br />
== Overview ==<br />
A complete list of all available properties<br />
<br />
<table id="treeviewtable" class="table table-bordered tt-table" style='table-layout: fixed'><br />
<tr style='background-color: rgba(0,0,0,0.2);'><br />
<th width='300' align='left'>Property</th><br />
<th width='200' align='left'>Type</th><br />
<th width='120' align='left'>Default</th><br />
<th align='left'>Usage</th><br />
</tr><br />
<tr><br />
<td><div class="tt" data-tt-id="root">json</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Core (no byType available)</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code" data-tt-parent="root">code</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>A unique identifier for the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code_info" data-tt-parent="p_code" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''domain prefix''' will be added dynamically depending on the location of the file. Every mod and VintageStory itself have a unique prefix.<br />
<br />
For example the code '''<code>stone</code>''' turns into '''<code>game:stone</code>'''. <br />
<br />
The code identifier has to be unique inside its domain. In theory there could be equal identifiers with different domain prefixes.<br />
Find out more about [[Basic Modding#Domains|Domains]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_enabled" data-tt-parent="root">enabled</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the item will be loaded or not. Can be used to temporarily remove the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups" data-tt-parent="root">variantGroups</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Allows you define multiple variants of the same item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups_info" data-tt-parent="p_variantgroups" data-invisible="true"></div></td><br />
<td colspan="3"><br />
The variantgroups property allows you to define multiple variants of this item. All of them will have their unique pattern, which will be added to the item code.<br />
<br />
An easy example would be a bowl, which can either be raw or burned:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"type", states: ["raw", "burned"] },<br />
],<br />
</syntaxhighlight><br />
<br />
Meaning there will be two variants <code>bowl-raw</code> and <code>bowl-burned</code>.<br />
<br />
----<br />
<br />
It's also possible to define multiple groups. <br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"state", states: ["closed", "opened"] },<br />
{ code:"contents", states: ["empty", "cabbage"] },<br />
],<br />
</syntaxhighlight><br />
<br />
As a result you will have 2x2 groups, which will be added one after each other: <code>barrel-closed-empty</code>, <code>barrel-closed-cabbage</code>, <code>barrel-opened-empty</code> and <code>barrel-opened-cabbage</code>.<br />
<br />
----<br />
<br />
Additionally it is possible to refer to external lists (used for blocks) that are found in the worldproperties folder, such as <code>block/rock</code>, which contains all states of all rock types. This used for <code>gravel</code>, <code>sand</code> and <code>rock</code>. It's a good way to keep everything organized:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ loadFromProperties: "block/rock" },<br />
],<br />
</syntaxhighlight><br />
<br />
Here is a full list of all groups and their variants (you can also find them in the <code>assets/worldproperties</code> folder):<br />
{{:json:block:worldvariantgroups}}<br />
<br />
----<br />
<br />
Furthermore there are two ways of combining groups together. So far we covered the default combination mode, which is <code>multiplicative</code> (the total count of variants is the product of all states).<br />
<br />
Let's take a look at a different example (flowerpot), which uses the <code>additive</code> combination mode:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["raw"] },<br />
{ code: "empty", states: ["empty"], combine: "additive" },<br />
{ code: "flower", loadFromProperties: "block/flower", combine: "additive" },<br />
{ code: "mushroom", loadFromProperties: "block/mushroom", combine: "additive" },<br />
{ code: "sapling", loadFromProperties: "block/wood", combine: "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
The variants are <code>flowerpot-raw</code>, <code>flowerpot-empty</code>, <code>flowerpot-{all flowers}</code>, <code>flowerpot-{all mushrooms}</code> and <code>flowerpot-{all saplings}</code>.<br />
<br />
<code>Additive</code> mode could also be called separate, since it defines a variant separate from all the other groups:<br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "something", states: ["same", "different"] },<br />
{ code: "type", states: ["raw", "baked"] },<br />
{ code: "empty", states: ["red", "green"], "combine": "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
In this case, the result would be <code>same-raw</code>, <code>same-baked</code>, <code>different-raw</code>, <code>different-baked</code>, <code>red</code> and <code>green</code><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType" data-tt-parent="root">(any) bytype</div></td><br />
<td>key: string; value: object</td><br />
<td>-</td><br />
<td>You can create properties for certain variants of the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType_info" data-tt-parent="p_byType" data-invisible="true"></div></td><br />
<td colspan="3"><br />
In order to define properties for specific variants you can add '''byType''' to the property name. This allows you to define it depending on the type and always follows the same syntax:<br />
<syntaxhighlight lang="json"><br />
(property)ByType: {<br />
"selector": property,<br />
"selector2": property2,<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
If the selector matches the name of the variant the given property will be used. Keep in mind that only the first matching one will be used (everything below will be ignored).<br />
<br />
A slab for example has two variants ('''up''', '''down'''), which have different collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
The char '''<code>*</code>''' stands for anything. In this case it ignores the code of the item.<br />
<br />
Furthermore this opens up even more possbilities for more advanced selectors like this one for doors:<br />
<code>*-north-*-opened-left</code>. This will ignore the second variantgroup. Additionally ByType can also be used for child properties:<br />
<syntaxhighlight lang="json"><br />
collisionboxnbox: { <br />
x1: 0, y1: 0, z1: 0.875, x2: 1, y2: 1, z2: 1,<br />
rotateYByType: {<br />
"*-north-*-opened-left": 90,<br />
"*-north-*-closed-left": 0,<br />
"*-west-*-opened-left": 180,<br />
"*-west-*-closed-left": 90,<br />
<br />
"*-east-*-opened-left": 0,<br />
"*-east-*-closed-left": 270,<br />
"*-south-*-opened-left": 270,<br />
"*-south-*-closed-left": 180,<br />
<br />
"*-north-*-opened-right": 270,<br />
"*-north-*-closed-right": 0,<br />
"*-west-*-opened-right": 0,<br />
"*-west-*-closed-right": 90,<br />
<br />
"*-east-*-opened-right": 180,<br />
"*-east-*-closed-right": 270,<br />
"*-south-*-opened-right": 90,<br />
"*-south-*-closed-right": 180<br />
}<br />
},<br />
</syntaxhighlight><br />
<br />
Since Vintagestory v1.8 it is also possible to use the variantgroup as a placeholder:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "metal", states: ["copper", "tinbronze", "bismuthbronze", "blackbronze", "gold", "silver", "iron" ] },<br />
],<br />
textures: {<br />
"metal": { base: "block/metal/ingot/{metal}" },<br />
"wood": { base: "item/tool/material/wood" } <br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Specific</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class" data-tt-parent="root">class</div></td><br />
<td>string</td><br />
<td>&quot;item&quot;</td><br />
<td>The item class can add special functionalities for the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class_info" data-tt-parent="p_class" data-invisible="true"></div></td><br />
<td colspan="3"><br />
It can be used to open guis or adding other extra functionality to the item. A complete tutorial of how to add your own class to the game can be found [[Advanced Items|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_durability" data-tt-parent="root">durability</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>How many uses does this item has when being used. Item disappears at durability 0.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby" data-tt-parent="root">damagedby</div></td><br />
<td>array of string</td><br />
<td>-</td><br />
<td>From which damage sources does the item takes durability damage.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_blockbreaking" data-tt-parent="p_damagedby">blockbreaking</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Mining a block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_attacking" data-tt-parent="p_damagedby">attacking</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_fire" data-tt-parent="p_damagedby">fire</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Currently not used.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool" data-tt-parent="root">tool</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>If set, this item will be classified as given tool.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_knife" data-tt-parent="p_tool">Knife</div></td><br />
<td></td><br />
<td>0</td><br />
<td>USed to break grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_pickaxe" data-tt-parent="p_tool">Pickaxe</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Can mine rock and other stone materials</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_axe" data-tt-parent="p_tool">Axe</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Useful for chopping trees.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_sword" data-tt-parent="p_tool">Sword</div></td><br />
<td></td><br />
<td>3</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_shovel" data-tt-parent="p_tool">Shovel</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Mines dirt, sand and gravel really fast.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_hammer" data-tt-parent="p_tool">Hammer</div></td><br />
<td></td><br />
<td>5</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_mallet" data-tt-parent="p_tool">Mallet</div></td><br />
<td></td><br />
<td>6</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_spear" data-tt-parent="p_tool">Spear</div></td><br />
<td></td><br />
<td>7</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_bow" data-tt-parent="p_tool">Bow</div></td><br />
<td></td><br />
<td>8</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_sickle" data-tt-parent="p_tool">Sickle</div></td><br />
<td></td><br />
<td>9</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_hoe" data-tt-parent="p_tool">Hoe</div></td><br />
<td></td><br />
<td>10</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_saw" data-tt-parent="p_tool">Saw</div></td><br />
<td></td><br />
<td>11</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Common</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory" data-tt-parent="root">creativeinventory</div></td><br />
<td>key: string, value: string[]</td><br />
<td>-</td><br />
<td>In which creative inventory tabs the item should be visible in.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory_info" data-tt-parent="p_creativeinventory" data-invisible="true"></div></td><br />
<td colspan="3"><br />
There are several tabs to you can add your stuff. Note that general should always be included, since it should contain everything.<br />
<br />
*general<br />
*terrain<br />
*flora<br />
*construction<br />
*decorative<br />
*items<br />
<br />
'''Rock''' adds all of it's variantions to general, terrain and construction:<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*"], "terrain": ["*"], "construction": ["*"] },<br />
</syntaxhighlight><br />
<br />
'''<code>*</code>''' reprents the variants which will be added. You can specify multiple and separate them with a comma. It follows the same way as the '''byType''' property.<br />
<br />
A '''Torch''' on the other hand only adds the variation '''<code>up</code>''':<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*-up"], "decorative": ["*-up"] },<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_maxstacksize" data-tt-parent="root">maxstacksize</div></td><br />
<td>integer</td><br />
<td>64</td><br />
<td>Determines the maximum amount you can stack the item in one slot.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackpower" data-tt-parent="root">attackpower</div></td><br />
<td>decimal number</td><br />
<td>0.5</td><br />
<td>The damage the deals when hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackrange" data-tt-parent="root">attackrange</div></td><br />
<td>decimal number</td><br />
<td>1.5</td><br />
<td>The maximum distance you can hit an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity" data-tt-parent="root">materialdensity</div></td><br />
<td>integer</td><br />
<td>9999</td><br />
<td>Determines on whether an object floats on liquids or not.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity_info" data-tt-parent="p_materialdensity" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Water has a density of 1000, meaning everything below or equal will float on water. The same goes for lava which has a density of 5000.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable" data-tt-parent="root">liquidselectable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If the item can select a liquid while holding it in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable_info" data-tt-parent="p_liquidselectable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Used for buckets in order to fill it with water and to place waterlily on top of water.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningspeed</div></td><br />
<td>key: string, value: decimal number</td><br />
<td>-</td><br />
<td>The mining speed for each material.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningtier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Determines which blocks it can break. If the required miningtier is above the defined one there will be no drop from it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes" data-tt-parent="root">attributes</div></td><br />
<td>key: string, value: object</td><br />
<td>-</td><br />
<td>Custom Attributes associated with this item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_info" data-tt-parent="p_attributes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Extra attributes added to a item or block. Those are final and cannot be modified. It's a good way to keep things organized and and modifiable. The '''oreblastingbomb''' for example has attributes, which define its radius and type. These can be used by behaviors and blockentities:<br />
<syntaxhighlight lang="json"><br />
attributes: {<br />
"blastRadius": 4,<br />
"blastType": 0,<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops" data-tt-parent="root">combustibleprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the items burnable states.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burntemperature" data-tt-parent="p_combustibleprops">burntemperature</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>The temperature at which it burns in degrees celsius.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burnduration" data-tt-parent="p_combustibleprops">burnduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how long it burns in seconds.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_heatresistance" data-tt-parent="p_combustibleprops">heatresistance</div></td><br />
<td>integer</td><br />
<td>500</td><br />
<td>How many degrees celsius it can resists before it ignites (not implemented yet).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingpoint" data-tt-parent="p_combustibleprops">meltingpoint</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>How many degrees celsius it takes to smelt/transform this into another. Only used when put in a stove and Melted is set.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingduration" data-tt-parent="p_combustibleprops">meltingduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how many seconds the temperature has to be above the melting point until the item is smelted.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smokelevel" data-tt-parent="p_combustibleprops">smokelevel</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>How much smoke this item produces when being used as fuel.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smeltedratio" data-tt-parent="p_combustibleprops">smeltedratio</div></td><br />
<td>integer</td><br />
<td>1</td><br />
<td>How many ores are required to produce one output stack.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="p_combustibleprops">smeltedstack</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>If set, the block/item is smeltable in a furnace and this is the resulting itemstack once the MeltingPoint has been reached for the supplied duration.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requirescontainer" data-tt-parent="p_combustibleprops">requirescontainer</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If set to true, the block/item requires a smelting/cooking/baking container such as the Crucible. If false, it can be directly baked/melted without smelting/cooking/baking container.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops_info" data-tt-parent="p_combustibleprops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
This property can be used to define a burning material. '''Plank''' for example can get on fire:<br />
<syntaxhighlight lang="json"><br />
combustibleProps: {<br />
burnTemperature: 800,<br />
burnDuration: 12,<br />
},<br />
</syntaxhighlight><br />
<br />
Furthermore it can be used to define smelting processes. An example would be an '''ingotmold''' which turns into an ingotmold-burned:<br />
<syntaxhighlight lang="json"><br />
combustiblePropsByType: {<br />
"ingotmold-raw": {<br />
meltingPoint: 600,<br />
meltingDuration: 30,<br />
smeltedRatio: 1,<br />
smeltedStack: { type: "block", code: "ingotmold-burned" },<br />
requiresContainer: false<br />
}<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops" data-tt-parent="root">nutritionprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the items nutrients.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_foodcategory" data-tt-parent="p_nutritionprops">foodcategory</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>Defines the type of food. It can be '''''fruit''''', '''''vegetable''''', '''''protein''''', '''''grain''''' and '''''dairy'''''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_saturation" data-tt-parent="p_nutritionprops">saturation</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much saturation it can restore.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_health" data-tt-parent="p_nutritionprops">health</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much health it can restore.</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Rendering</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_textures" data-tt-parent="root">textures</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>The texture definitions for the item held in hand or dropped on the ground.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shape" data-tt-parent="root">shape</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>The items shape. Empty for automatic shape based on the texture.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shapeinventory" data-tt-parent="root">shapeinventory</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>The items shape in inventory.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_guitransform" data-tt-parent="root">guiTransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in guis.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fphandtransform" data-tt-parent="root">fphandtransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in the first person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tphandtransform" data-tt-parent="root">tphandtransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in the third person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_groundtransform" data-tt-parent="root">groundtransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the rendered as a dropped item on the ground.</td><br />
</tr><br />
</table><br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Block_Json_Properties&diff=4918Modding:Block Json Properties2019-06-05T14:07:25Z<p>CreativeMD: </p>
<hr />
<div>__NOTOC__<br />
== Overview ==<br />
A complete list of all available properties<br />
<br />
<table id="treeviewtable" class="table table-bordered tt-table" style='table-layout: fixed'><br />
<tr><br />
<th width='300' align='left'>Property</th><br />
<th width='200' align='left'>Type</th><br />
<th width='120' align='left'>Default</th><br />
<th align='left'>Usage</th><br />
</tr><br />
<tr><br />
<td><div class="tt" data-tt-id="root">json</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Core (no byType available)</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code" data-tt-parent="root">code</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>A unique identifier for the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code_info" data-tt-parent="p_code" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''domain prefix''' will be added dynamically depending on the location of the file. Every mod and VintageStory itself have a unique prefix.<br />
<br />
For example the code '''<code>stone</code>''' turns into '''<code>game:stone</code>'''. <br />
<br />
The code identifier has to be unique inside its domain. In theory there could be equal identifiers with different domain prefixes.<br />
Find out more about [[Basic Modding#Domains|Domains]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_enabled" data-tt-parent="root">enabled</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the block will be loaded or not. Can be used to temporarily remove the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups" data-tt-parent="root">variantgroups</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Allows you define multiple variants of the same block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups_info" data-tt-parent="p_variantgroups" data-invisible="true"></div></td><br />
<td colspan="3"><br />
The variantgroups property allows you to define multiple variants of this block. All of them will have their unique pattern, which will be added to the block code.<br />
<br />
An easy example would be a bowl, which can either be raw or burned:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"type", states: ["raw", "burned"] },<br />
],<br />
</syntaxhighlight><br />
<br />
Meaning there will be two blocks <code>bowl-raw</code> and <code>bowl-burned</code>.<br />
<br />
----<br />
<br />
It's also possible to define multiple groups. <br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"state", states: ["closed", "opened"] },<br />
{ code:"contents", states: ["empty", "cabbage"] },<br />
],<br />
</syntaxhighlight><br />
<br />
As a result you will have 2x2 groups, which will be added one after each other: <code>barrel-closed-empty</code>, <code>barrel-closed-cabbage</code>, <code>barrel-opened-empty</code> and <code>barrel-opened-cabbage</code>.<br />
<br />
----<br />
<br />
Additionally it is possible to refer to external lists that are found in the worldproperties folder, such as <code>block/rock</code>, which contains all states of all rock types. This used for <code>gravel</code>, <code>sand</code> and <code>rock</code>. It's a good way to keep everything organized:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ loadFromProperties: "block/rock" },<br />
],<br />
</syntaxhighlight><br />
<br />
Here is a full list of all groups and their variants (you can also find them in the <code>assets/worldproperties</code> folder):<br />
{{:json:block:worldvariantgroups}}<br />
<br />
----<br />
<br />
Furthermore there are two ways of combining groups together. So far we covered the default combination mode, which is <code>multiplicative</code> (the total count of variants is the product of all states).<br />
<br />
Let's take a look at a different example (flowerpot), which uses the <code>additive</code> combination mode:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["raw"] },<br />
{ code: "empty", states: ["empty"], combine: "additive" },<br />
{ code: "flower", loadFromProperties: "block/flower", combine: "additive" },<br />
{ code: "mushroom", loadFromProperties: "block/mushroom", combine: "additive" },<br />
{ code: "sapling", loadFromProperties: "block/wood", combine: "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
The variants are <code>flowerpot-raw</code>, <code>flowerpot-empty</code>, <code>flowerpot-{all flowers}</code>, <code>flowerpot-{all mushrooms}</code> and <code>flowerpot-{all saplings}</code>.<br />
<br />
<code>Additive</code> mode could also be called separate, since it defines a variant separate from all the other groups:<br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "something", states: ["same", "different"] },<br />
{ code: "type", states: ["raw", "baked"] },<br />
{ code: "empty", states: ["red", "green"], "combine": "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
In this case, the result would be <code>same-raw</code>, <code>same-baked</code>, <code>different-raw</code>, <code>different-baked</code>, <code>red</code> and <code>green</code><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType" data-tt-parent="root">(any) bytype</div></td><br />
<td>key: string; value: object</td><br />
<td>-</td><br />
<td>You can create properties for certain variants of the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType_info" data-tt-parent="p_byType" data-invisible="true"></div></td><br />
<td colspan="3"><br />
In order to define properties for specific variants you can add '''byType''' to the property name. This allows you to define it depending on the type and always follows the same syntax:<br />
<syntaxhighlight lang="json"><br />
(property)ByType: {<br />
"selector": property,<br />
"selector2": property2,<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
If the selector matches the name of the variant the given property will be used. Keep in mind that only the first matching one will be used (everything below will be ignored).<br />
<br />
A slab for example has two variants ('''up''', '''down'''), which have different collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
The char '''<code>*</code>''' stands for anything. In this case it ignores the code of the block.<br />
<br />
Furthermore this opens up even more possbilities for more advanced selectors like this one for doors:<br />
<code>*-north-*-opened-left</code>. This will ignore the second variantgroup. Additionally ByType can also be used for child properties:<br />
<syntaxhighlight lang="json"><br />
collisionboxnbox: { <br />
x1: 0, y1: 0, z1: 0.875, x2: 1, y2: 1, z2: 1,<br />
rotateYByType: {<br />
"*-north-*-opened-left": 90,<br />
"*-north-*-closed-left": 0,<br />
"*-west-*-opened-left": 180,<br />
"*-west-*-closed-left": 90,<br />
<br />
"*-east-*-opened-left": 0,<br />
"*-east-*-closed-left": 270,<br />
"*-south-*-opened-left": 270,<br />
"*-south-*-closed-left": 180,<br />
<br />
"*-north-*-opened-right": 270,<br />
"*-north-*-closed-right": 0,<br />
"*-west-*-opened-right": 0,<br />
"*-west-*-closed-right": 90,<br />
<br />
"*-east-*-opened-right": 180,<br />
"*-east-*-closed-right": 270,<br />
"*-south-*-opened-right": 90,<br />
"*-south-*-closed-right": 180<br />
}<br />
},<br />
</syntaxhighlight><br />
<br />
Since Vintagestory v1.8 it is also possible to use the variantgroup as a placeholder:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["normal", "bamboo"] },<br />
],<br />
textures: {<br />
horizontals: { base: "block/hay/{type}-side" },<br />
verticals: { base: "block/hay/{type}-top" },<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Specific</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class" data-tt-parent="root">class</div></td><br />
<td>string</td><br />
<td>&quot;block&quot;</td><br />
<td>The block class can add special functionalities for the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class_info" data-tt-parent="p_class" data-invisible="true"></div></td><br />
<td colspan="3"><br />
It can be used to open guis or adding other extra functionality to the block. A complete tutorial of how to add your own class to the game can be found [[Advanced Blocks|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_entityclass" data-tt-parent="root">entityclass</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>The block entity class is able to tick and to store extra data.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_entityclass_info" data-tt-parent="p_entityclass" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A chest for example uses the BlockEntity to store the inventory. A tutorial of creating your own entityclass can be found [[Block Entity|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors" data-tt-parent="root">behaviors</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>A behavior adds custom abilities such as falling block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors_info" data-tt-parent="p_behaviors" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Here is an overview of most exisiting behaviors, if you want to create your own custom behavior you can read [[Adding Block Behavior]].<br />
To see all of the current behaviors in the game see [[Json:block:behaviors|All Block Behaviors]]<br />
{{:json:block:behavior}}<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockmaterial" data-tt-parent="root">blockmaterial</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>A behavior adds custom abilities such as falling block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_blockmaterial_soil" data-tt-parent="p_blockmaterial">Soil</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_gravel" data-tt-parent="p_blockmaterial">Gravel</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_sand" data-tt-parent="p_blockmaterial">Sand</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_wood" data-tt-parent="p_blockmaterial">Wood</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_leaves" data-tt-parent="p_blockmaterial">Leaves</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_stone" data-tt-parent="p_blockmaterial">Stone</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_liquid" data-tt-parent="p_blockmaterial">Liquid</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_snow" data-tt-parent="p_blockmaterial">Snow</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_ice" data-tt-parent="p_blockmaterial">Ice</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_metal" data-tt-parent="p_blockmaterial">Metal</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_mantle" data-tt-parent="p_blockmaterial">Mantle</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_plant" data-tt-parent="p_blockmaterial">Plant</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_glass" data-tt-parent="p_blockmaterial">Glass</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_ceramic" data-tt-parent="p_blockmaterial">Ceramic</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_cloth" data-tt-parent="p_blockmaterial">Cloth</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_lava" data-tt-parent="p_blockmaterial">Lava</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_brick" data-tt-parent="p_blockmaterial">Brick</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_fire" data-tt-parent="p_blockmaterial">Fire</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_other" data-tt-parent="p_blockmaterial">Other</div><br />
</td><br />
<td colspan="3" valign="top"><br />
Materials are hardcoded and currently only used to determine mining speed with a specific tool.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_matterstate" data-tt-parent="root">matterstate</div></td><br />
<td>array of object</td><br />
<td>&quot;block&quot;</td><br />
<td>Determines whether the block is in a '''''solid''''', a '''''liquid''''', a '''''gas''''' or a '''''plasma''''' state.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_matterstate_solid" data-tt-parent="p_matterstate">solid</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_liquid" data-tt-parent="p_matterstate">liquid</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_gas" data-tt-parent="p_matterstate">gas</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_plasma" data-tt-parent="p_matterstate">plasma</div><br><br><br />
</td><br />
<td colspan="3"><br />
Used for special collision behavior and rendering. Currently used for:<br />
<br />
Liquid:<br />
*Lava<br />
*Water<br />
*Water with particles<br />
<br />
Gas/Plasma:<br />
none added yet<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_resistance" data-tt-parent="root">resistance</div></td><br />
<td>decimal number</td><br />
<td>6</td><br />
<td>How long it takes to break this block in seconds (with a mining speed of 1).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_resistance_info" data-tt-parent="p_resistance" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Same examples of resistance's values used in VintageStory:<br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">block</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>'''leave'''</td><br />
<td>''0.5''</td><br />
</tr><br />
<tr><br />
<td>'''wool'''</td><br />
<td>''1.0''</td><br />
</tr><br />
<tr><br />
<td>'''bowl'''</td><br />
<td>''1.5''</td><br />
</tr><br />
<tr><br />
<td>'''obsidian'''</td><br />
<td>''2''</td><br />
</tr><br />
<tr><br />
<td>'''plank'''</td><br />
<td>''3.5''</td><br />
</tr><br />
<tr><br />
<td>'''log'''</td><br />
<td>''4.5''</td><br />
</tr><br />
<tr><br />
<td>'''rock'''</td><br />
<td>''6''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requiredminingtier" data-tt-parent="root">requiredminingtier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Minimum required mining tier to get the drop out of the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requiredminingtier_info" data-tt-parent="p_requiredminingtier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">Tier</th><br />
<th style="background-color: rgba(0,0,0,0.2);">Ores</th><br />
</tr><br />
<tr><br />
<td>'''1'''</td><br />
<td>'''''gelena''''' and '''''rocksalt_sylvite'''''</td><br />
</tr><br />
<tr><br />
<td>'''2'''</td><br />
<td>'''''lignite''''', '''''cassiterite''''', '''''sphalerite''''', '''''rocksalt''''', '''''sulfur''''' and '''''nativecopper'''''</td><br />
</tr><br />
<tr><br />
<td>'''3'''</td><br />
<td>'''''bituminouscoal''''', '''''quartz_nativegold''''', '''''quartz_nativesilver''''', '''''lapislazuli''''', '''''bismuthinite''''', '''''quartz''''', '''''magnetite''''' and '''''limonite'''''</td><br />
</tr><br />
<tr><br />
<td>'''4'''</td><br />
<td>'''''diamond''''' and '''''emerald'''''</td><br />
</tr><br />
<tr><br />
<td>'''5'''</td><br />
<td>'''''chromite''''', '''''platinum''''' and '''''ilmenite'''''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_climbable" data-tt-parent="root">climbable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If true, walking against this block will make the player climb (used for ladders).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rainpermeable" data-tt-parent="root">rainpermeable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If rain can fall through this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_snowcoverage" data-tt-parent="root">snowcoverage</div></td><br />
<td>boolean</td><br />
<td>-</td><br />
<td>Whether snow may rest on top of this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_snowcoverage_info" data-tt-parent="p_snowcoverage" data-invisible="true"></div></td><br />
<td colspan="3"><br />
All none solid blocks can't be covered by snow unless it's defined different:<br />
*Leaves (also branchy): '''true''',<br />
*Water with particles, Lakeice: '''false'''<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionbox" data-tt-parent="root">collisionbox</div></td><br />
<td>object</td><br />
<td>box (0,0,0 -> 1,1,1)</td><br />
<td>Defines a box with which the player collides with.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionbox_info" data-tt-parent="p_collisionbox" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''half slab''' for example, has either a box going from 0,0,0 to 1,0.5,1 or going from 0,0.5,0 to 1,1,1, depending on whether it is a slab is down or up:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
Collision and selection boxes are most likely equal.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionboxes" data-tt-parent="root">collisionboxes</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Defines multiple boxes with which the player collides with.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionboxes_info" data-tt-parent="p_collisionboxes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''crate''' for example requires multiple collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxesByType: {<br />
"*-opened": [ <br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.0625, z2: 1 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 90 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 180 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 270 },<br />
]<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionbox" data-tt-parent="root">selectionbox</div></td><br />
<td>object</td><br />
<td>box (0,0,0 -> 1,1,1)</td><br />
<td>Defines a box which the player's mouse pointer collides with for selection.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionbox_info" data-tt-parent="p_selectionbox" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''half slab''' for example, has either a box going from 0,0,0 to 1,0.5,1 or going from 0,0.5,0 to 1,1,1, depending on whether it is a slab is down or up:<br />
<syntaxhighlight lang="json"><br />
selectionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
Collision and selection boxes are most likely equal.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionboxes" data-tt-parent="root">selectionboxes</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Defines multiple boxes which the player's mouse pointer collides with for selection.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionboxes_info" data-tt-parent="p_selectionboxes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''crate''' for example requires multiple selection boxes:<br />
<syntaxhighlight lang="json"><br />
selectionboxesByType: {<br />
"*-opened": [ <br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.0625, z2: 1 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 90 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 180 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 270 },<br />
]<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_replaceable" data-tt-parent="root">replaceable</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>A value usually between 0-9999 that indicates which blocks may be replaced with others.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_replaceable_info" data-tt-parent="p_replaceable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
<th style="background-color: rgba(0,0,0,0.2);">effect (blocks)</th><br />
</tr><br />
<tr><br />
<td>'''0'''</td><br />
<td>'''''ordinary blocks''''' (stone for example)</td><br />
</tr><br />
<tr><br />
<td>'''5000'''</td><br />
<td>Everything equal or above will be washed away by water (such as '''''Fruit''''').</td><br />
</tr><br />
<tr><br />
<td>'''6000'''</td><br />
<td>Everything equal or above wwill replaced when the player tries to place a block (such as '''''Tallgrass''''').</td><br />
</tr><br />
<tr><br />
<td>'''9000'''</td><br />
<td>'''''Lava'''''</td><br />
</tr><br />
<tr><br />
<td>'''9500'''</td><br />
<td>'''''Water'''''</td><br />
</tr><br />
<tr><br />
<td>'''9999'''</td><br />
<td>'''''Air'''''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fertility" data-tt-parent="root">fertility</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Which plants can grow on top of this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fertility_info" data-tt-parent="p_fertility" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
<th style="background-color: rgba(0,0,0,0.2);">effect</th><br />
</tr><br />
<tr><br />
<td>'''0'''</td><br />
<td>''nothing can grow.''</td><br />
</tr><br />
<tr><br />
<td>'''10'''</td><br />
<td>''some tallgrass and small trees can be grow on it.''</td><br />
</tr><br />
<tr><br />
<td>'''100'''</td><br />
<td>''all grass and trees can grow on it.''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_glowlevel" data-tt-parent="root">glowLevel</div></td><br />
<td>0 ... 255</td><br />
<td>0</td><br />
<td>Causes the block to visually glow if Bloom is enabled. Basic glow level for all the blocks model elements.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_glowlevel_info" data-tt-parent="p_glowlevel" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Glacierice''</td><br />
<td>'''8'''</td><br />
</tr><br />
<tr><br />
<td>''Paperlantern''</td><br />
<td>'''32'''</td><br />
</tr><br />
<tr><br />
<td>''Ember''</td><br />
<td>'''48'''</td><br />
</tr><br />
<tr><br />
<td>''Fire'', ''Firepit'', ''Oillamp'', ''Torch''</td><br />
<td>'''64'''</td><br />
</tr><br />
<tr><br />
<td>''Lava''</td><br />
<td>'''128'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lightabsorption" data-tt-parent="root">lightabsorption</div></td><br />
<td>0 ... 32</td><br />
<td>0</td><br />
<td>For light blocking blocks. Any value above 32 will completely block all light.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_walkspeedmultiplier" data-tt-parent="root">walkspeedmultiplier</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>Percentage walk-speed when standing on or inside this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_walkspeedmultiplier_info" data-tt-parent="p_walkspeedmultiplier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Spiderweb''</td><br />
<td>'''0.25'''</td><br />
</tr><br />
<tr><br />
<td>''Stonepath''</td><br />
<td>'''1.15'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_dragmultiplier" data-tt-parent="root">dragmultiplier</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>Drag multiplier applied to entities standing on it (slipperiness factor).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_dragmultiplier_info" data-tt-parent="p_dragmultiplier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Glacierice'', ''Lakeice''</td><br />
<td>'''0.02'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drops" data-tt-parent="root">drops</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>The items that should drop from breaking this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drops_info" data-tt-parent="p_drops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<br />
'''Drop itself'''<br />
<br />
If this property does not exist the block will drop itself.<br />
<br />
----<br />
<br />
'''No drop'''<br />
<br />
A '''firepit''' for example doesn't drop anything. You can do so if you specify an empty array:<br />
<syntaxhighlight lang="json"><br />
drops: [],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Special drop'''<br />
<br />
You can also specify a special item/ block. Therefore you need to define an '''ItemStack''', with the given properties:<br />
<br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">property</th><br />
<th style="background-color: rgba(0,0,0,0.2);">default</th><br />
<th style="background-color: rgba(0,0,0,0.2);">explanation</th><br />
</tr><br />
<tr><br />
<td>'''type'''</td><br />
<td>''block''</td><br />
<td>Can either be '''''block''''' or '''''item'''''.</td><br />
</tr><br />
<tr><br />
<td>'''code''' (required)</td><br />
<td>-</td><br />
<td>The complete code (can also include domain) of the item or block.</td><br />
</tr><br />
<tr><br />
<td>'''lastdrop'''</td><br />
<td>false</td><br />
<td>If true and the quantity dropped is >=1 any subsequent drop in the list will be ignored.</td><br />
</tr><br />
<tr><br />
<td>'''attributes'''</td><br />
<td>-</td><br />
<td>Tree Attributes that will be attached to the resulting itemstack.</td><br />
</tr><br />
<tr><br />
<td>'''tool'''</td><br />
<td>-</td><br />
<td>If specified then given tool is required to break this block.</td><br />
</tr><br />
<tr><br />
<td>'''quantity'''</td><br />
<td>- (one)</td><br />
<td>Determines the quantity of items which will be dropped.</td><br />
</tr><br />
</table><br />
<br />
For example, the drop of a '''charcoalpile''' looks like this:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "charcoal" }<br />
],<br />
</syntaxhighlight><br />
<br />
'''Tallgrass''' will only drop something if it's mined by a knife:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "drygrass", tool: "knife" },<br />
],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Chance drops'''<br />
<br />
Let's take a look at an example. This is the drop property of rock:<br />
<br />
<syntaxhighlight lang="json"> <br />
drops: [<br />
{<br />
type: "item", <br />
code: "stone-{rock}", <br />
quantity: { avg: 2.5, var: 0.5 } <br />
},<br />
]<br />
</syntaxhighlight><br />
<br />
This will drop 2-3 blocks.<br />
<br />
'''''avg''''': Stands for the default drop quantity. If var is 0 or not specified it will always drop the given average.<br />
<br />
'''''var''''': How much the drop rate can vary. Meaning the drop rate can be <code>avg - var</code> at minimum and <code>age + var</code> at maximum.<br />
<br />
For more information see [[NatFloat]] page.<br />
<br />
----<br />
<br />
'''Multiple Drops'''<br />
<br />
Of course you can also define multiple drops at once. '''Sapling''' can drop a sapling and a stick:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ <br />
type: "block", <br />
code: "sapling-{wood}",<br />
quantity: { avg: 0.02, var: 0 },<br />
},<br />
{ <br />
type: "item", <br />
code: "stick",<br />
quantity: { avg: 0.02, var: 0 },<br />
}<br />
],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Last Drop'''<br />
<br />
In order to add a special drop, which (if dropped) prevents all other drops, you can use the lastDrop property:<br />
<br />
<syntaxhighlight lang="json"><br />
dropsByType: {<br />
"ore-quartz-*": [<br />
{ type: "item", code: "clearquartz", quantity: { avg: 0.2, var: 0 }, lastDrop: true },<br />
{ type: "item", code: "ore-{ore}", quantity: { avg: 1.25, var: 0 } }<br />
],<br />
"*": [ <br />
{ type: "item", code: "ore-{ore}", quantity: { avg: 1.25, var: 0 } }<br />
],<br />
}<br />
</syntaxhighlight><br />
<br />
Quartz ore will drop with a 20% chance clearquartz, if not it will drop the regular ore. If lastDrop wouldn't be true it could drop both at the same time.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_particleproperties" data-tt-parent="root">particleproperties</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Particles that should spawn in regular intervals from this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_particleproperties_info" data-tt-parent="p_particleproperties" data-invisible="true"></div></td><br />
<td colspan="3"><br />
{{:json:block:particle}}<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="root">liquidlevel</div></td><br />
<td>0 ... 7</td><br />
<td>0</td><br />
<td>Value between 0...7 for Liquids to determine the height of the liquid.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cropprops" data-tt-parent="root">cropprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the block as a crop.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds" data-tt-parent="root">sounds</div></td><br />
<td>key: string, value: string</td><br />
<td>-</td><br />
<td>The sounds played for this block during step, break, build and walk.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_walk" data-tt-parent="p_sounds">walk</div></td><br />
<td colspan="3">An entity walks over it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_inside" data-tt-parent="p_sounds">inside</div></td><br />
<td colspan="3">The player is inside the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_break" data-tt-parent="p_sounds">break</div></td><br />
<td colspan="3">Breaking the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_place" data-tt-parent="p_sounds">place</div></td><br />
<td colspan="3">Placing the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_hit" data-tt-parent="p_sounds">hit</div></td><br />
<td colspan="3">While mining the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_ambient" data-tt-parent="p_sounds">ambient</div></td><br />
<td colspan="3">Played from time to time if the player is close to it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_info" data-tt-parent="p_sounds" data-invisible="true"></div></td><br />
<td colspan="3"><br />
'''Anvil''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
"place": "block/anvil",<br />
"break": "block/anvil"<br />
}<br />
</syntaxhighlight><br />
<br />
'''Rails''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
place": "block/planks",<br />
"walk": "walk/wood"<br />
}<br />
</syntaxhighlight><br />
<br />
'''Water''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
place: "block/water",<br />
inside: "walk/water",<br />
ambient: "environment/creek"<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Common</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory" data-tt-parent="root">creativeinventory</div></td><br />
<td>key: string, value: string[]</td><br />
<td>-</td><br />
<td>In which creative inventory tabs the block should be visible in.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory_info" data-tt-parent="p_creativeinventory" data-invisible="true"></div></td><br />
<td colspan="3"><br />
There are several tabs to you can add your stuff. Note that general should always be included, since it should contain everything.<br />
<br />
*general<br />
*terrain<br />
*flora<br />
*construction<br />
*decorative<br />
*items<br />
<br />
'''Rock''' adds all of it's variantions to general, terrain and construction:<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*"], "terrain": ["*"], "construction": ["*"] },<br />
</syntaxhighlight><br />
<br />
'''<code>*</code>''' reprents the variants which will be added. You can specify multiple and separate them with a comma. It follows the same way as the '''byType''' property.<br />
<br />
A '''Torch''' on the other hand only adds the variation '''<code>up</code>''':<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*-up"], "decorative": ["*-up"] },<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_maxstacksize" data-tt-parent="root">maxstacksize</div></td><br />
<td>integer</td><br />
<td>64</td><br />
<td>Determines the maximum amount you can stack the block in one slot.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackpower" data-tt-parent="root">attackpower</div></td><br />
<td>decimal number</td><br />
<td>0.5</td><br />
<td>The damage the deals when hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackrange" data-tt-parent="root">attackrange</div></td><br />
<td>decimal number</td><br />
<td>1.5</td><br />
<td>The maximum distance you can hit an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity" data-tt-parent="root">materialdensity</div></td><br />
<td>integer</td><br />
<td>9999</td><br />
<td>Determines on whether an object floats on liquids or not.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity_info" data-tt-parent="p_materialdensity" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Water has a density of 1000, meaning everything below or equal will float on water. The same goes for lava which has a density of 5000.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable" data-tt-parent="root">liquidselectable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If the block can select a liquid while holding it in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable_info" data-tt-parent="p_liquidselectable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Used for buckets in order to fill it with water and to place waterlily on top of water.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningSpeed</div></td><br />
<td>key: string, value: decimal number</td><br />
<td>-</td><br />
<td>The mining speed for each material.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningTier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Determines which blocks it can break. If the required miningtier is above the defined one there will be no drop from it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes" data-tt-parent="root">attributes</div></td><br />
<td>key: string, value: object</td><br />
<td>-</td><br />
<td>Custom Attributes associated with this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_info" data-tt-parent="p_attributes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Extra attributes added to a block. Those are final and cannot be modified. It's a good way to keep things organized and and modifiable. The '''oreblastingbomb''' for example has attributes, which define its radius and type. These can be used by behaviors and blockentities:<br />
<syntaxhighlight lang="json"><br />
attributes: {<br />
"blastRadius": 4,<br />
"blastType": 0,<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops" data-tt-parent="root">combustibleprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the blocks burnable states.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burntemperature" data-tt-parent="p_combustibleprops">burntemperature</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>The temperature at which it burns in degrees Celsius.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burnduration" data-tt-parent="p_combustibleprops">burnduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how long it burns in seconds.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_heatresistance" data-tt-parent="p_combustibleprops">heatresistance</div></td><br />
<td>integer</td><br />
<td>500</td><br />
<td>How many degrees celsius it can resists before it ignites (not implemented yet).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingpoint" data-tt-parent="p_combustibleprops">meltingpoint</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>How many degrees celsius it takes to smelt/transform this into another. Only used when put in a stove and SmeltedStack is set.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingduration" data-tt-parent="p_combustibleprops">meltingduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how many seconds the temperature has to be above the melting point until the item is smelted.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smokelevel" data-tt-parent="p_combustibleprops">smokelevel</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>How much smoke this item produces when being used as fuel.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smeltedratio" data-tt-parent="p_combustibleprops">smeltedratio</div></td><br />
<td>integer</td><br />
<td>1</td><br />
<td>How many ores are required to produce one output stack.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="p_combustibleprops">smeltedstack</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>If set, the block/item is smeltable in a furnace and this is the resulting itemstack once the MeltingPoint has been reached for the supplied duration.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requirescontainer" data-tt-parent="p_combustibleprops">requirescontainer</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If set to true, the block/item requires a smelting/cooking/baking container such as the Crucible. If false, it can be directly baked/melted without smelting/cooking/baking container.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops_info" data-tt-parent="p_combustibleprops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
This property can be used to define a burning material. '''Plank''' for example can get on fire:<br />
<syntaxhighlight lang="json"><br />
combustibleProps: {<br />
burnTemperature: 800,<br />
burnDuration: 12,<br />
},<br />
</syntaxhighlight><br />
<br />
Furthermore it can be used to define smelting processes. An example would be an '''ingotmold''' which turns into an ingotmold-burned:<br />
<syntaxhighlight lang="json"><br />
combustiblePropsByType: {<br />
"ingotmold-raw": {<br />
meltingPoint: 600,<br />
meltingDuration: 30,<br />
smeltedRatio: 1,<br />
smeltedStack: { type: "block", code: "ingotmold-burned" },<br />
requiresContainer: false<br />
}<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops" data-tt-parent="root">nutritionprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the blocks nutrients.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_foodcategory" data-tt-parent="p_nutritionprops">foodcategory</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>Defines the type of food. It can be '''''fruit''''', '''''vegetable''''', '''''protein''''', '''''grain''''' and '''''dairy'''''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_saturation" data-tt-parent="p_nutritionprops">saturation</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much saturation it can restore.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_health" data-tt-parent="p_nutritionprops">health</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much health it can restore.</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Rendering</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_textures" data-tt-parent="root">textures</div></td><br />
<td>key: string, value: object</td><br />
<td></td><br />
<td>The texture definitions for the block as seen in the world, when dropped on the ground or held in the hand. Within a mod, to refer to a texture from the base game, prefix the path with "game:" (i.e. base: "game:path/to/texture") </td><br />
</tr><br />
<tr><br />
<td scope="row" valign="top"><div class="tt" data-tt-id="p_textures_base" data-tt-parent="p_textures">base</div><br><br><div class="tt" data-tt-id="p_textures_overlays" data-tt-parent="p_textures">overlays</div><br><br><div class="tt" data-tt-id="p_textures_base" data-tt-parent="p_textures">alternates</div></td><br />
<td colspan="3">{{:json:block:texture}}</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_texturesinventory" data-tt-parent="root">texturesinventory</div></td><br />
<td>key: string, value: object</td><br />
<td></td><br />
<td>The texture definitions for the block as seen in the player inventory. Overrides the textures.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shape" data-tt-parent="root">shape</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>For the json drawtype, the shape definition of the block as shown in the world, dropped on the ground or held in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_base" data-tt-parent="p_shape">base</div></td><br />
<td></td><br />
<td></td><br />
<td>The path to the shape json file, the base dir is ''assets/shapes/''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateX" data-tt-parent="p_shape">rotatex</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateY" data-tt-parent="p_shape">rotatey</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateZ" data-tt-parent="p_shape">rotatez</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shapeinventory" data-tt-parent="root">shapeinventory</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>For the json drawtype, the shape definition of the block as shown in the players inventory.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drawtype" data-tt-parent="root">drawtype</div></td><br />
<td>string</td><br />
<td>&quot;cube&quot;</td><br />
<td>Determines how the block is tesselated, select JSON for being able to use custom JSON Models. The other values are hardcoded methods of tesselating the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_1" data-tt-parent="p_drawtype">blockLayer_1</div></td><br />
<td></td><br />
<td>0</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_2" data-tt-parent="p_drawtype">blockLayer_2</div></td><br />
<td></td><br />
<td>1</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_3" data-tt-parent="p_drawtype">blockLayer_3</div></td><br />
<td></td><br />
<td>2</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_4" data-tt-parent="p_drawtype">blockLayer_4</div></td><br />
<td></td><br />
<td>3</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_5" data-tt-parent="p_drawtype">blockLayer_5</div></td><br />
<td></td><br />
<td>4</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_6" data-tt-parent="p_drawtype">blockLayer_6</div></td><br />
<td></td><br />
<td>5</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_7" data-tt-parent="p_drawtype">blockLayer_7</div></td><br />
<td></td><br />
<td>6</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_json" data-tt-parent="p_drawtype">json</div></td><br />
<td></td><br />
<td>7</td><br />
<td>Will draw a json model.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_empty" data-tt-parent="p_drawtype">empty</div></td><br />
<td></td><br />
<td>8</td><br />
<td>Nothing will be drawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cube" data-tt-parent="p_drawtype">cube</div></td><br />
<td></td><br />
<td>9</td><br />
<td>Draws an ordinary cube.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cross" data-tt-parent="p_drawtype">cross</div></td><br />
<td></td><br />
<td>10</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_transparent" data-tt-parent="p_drawtype">transparent</div></td><br />
<td></td><br />
<td>11</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquid" data-tt-parent="p_drawtype">liquid</div></td><br />
<td></td><br />
<td>12</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_crossandsnowlayer" data-tt-parent="p_drawtype">crossandsnowlayer</div></td><br />
<td></td><br />
<td>13</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_renderpass" data-tt-parent="root">renderpass</div></td><br />
<td>string</td><br />
<td>&quot;opaque&quot;</td><br />
<td>Determines how the block will be drawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_opaque" data-tt-parent="p_renderpass">opaque</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Used for solid blocks with no half transparency.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_opaquenocull" data-tt-parent="p_renderpass">opaquenocull</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Used for non-solid single faced blocks, such as tall grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_transparent" data-tt-parent="p_renderpass">transparent</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Use for solid halftransparent blocks, such as glass</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquid" data-tt-parent="p_renderpass">liquid</div></td><br />
<td></td><br />
<td>3</td><br />
<td>Used for liquids, produces waves.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_topsoil" data-tt-parent="p_renderpass">topsoil</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Used for grass covered blocks. Allows for a smooth transition from grass to soil, while still allowing climate tinting of grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_ambientocclusion" data-tt-parent="root">ambientocclusion</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If ambient occlusion will be applied to the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tintindex" data-tt-parent="root">tintindex</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>'''''0''''' for no tint, '''''1''''' for plant climate tint, '''''2''''' for water climate tint.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_renderflags" data-tt-parent="root">renderflags</div></td><br />
<td>0 ... 255</td><br />
<td>0</td><br />
<td>8 bits that are sent to the graphics card for each vertex of the blocks shape. The lower 3 bits are currently used for altering the vertexes z-depth to fix a bunch of z-fighting issues.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode" data-tt-parent="root">facecullmode</div></td><br />
<td>string</td><br />
<td>&quot;default&quot;</td><br />
<td>Determines which sides of the blocks should be rendered.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">default</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Culls faces if they are opaque faces adjacent to opaque faces.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">nevercull</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Never culls any faces.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">merge</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Culls all faces that are adjacent to opaque faces and faces adjacent to blocks of the same id (Example usage: Ice blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">collapse</div></td><br />
<td></td><br />
<td>3</td><br />
<td>Culls all faces that are adjacent to opaque faces and the bottom, east or south faces adjacent to blocks of the same id. This causes to still leave one single face in between instead of 2, eliminating any z-fighting.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">mergematerial</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Same as Merge but checks for equal material (Example usage: Plain glass and all colored glass blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">collapsematerial</div></td><br />
<td></td><br />
<td>5</td><br />
<td>Same as Collapse but checks for equal material (Example usage: All leaves blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">liquid</div></td><br />
<td></td><br />
<td>6</td><br />
<td>Same as CollapseMaterial but also culls faces towards opaque blocks.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sideopaque" data-tt-parent="root">sideopaque</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>Determines if given block face is fully opaque. If yes, the opposite face of the adjacent block will not be drawn for efficiency reasons.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sideopaque_all" data-tt-parent="p_sideopaque">all</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_horizontals" data-tt-parent="p_sideopaque">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_verticals" data-tt-parent="p_sideopaque">verticals</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_east" data-tt-parent="p_sideopaque">east</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_west" data-tt-parent="p_sideopaque">west</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_up" data-tt-parent="p_sideopaque">up</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_down" data-tt-parent="p_sideopaque">down</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_north" data-tt-parent="p_sideopaque">north</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_south" data-tt-parent="p_sideopaque">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sideao" data-tt-parent="root">sideao</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>If AmbientOcclusion will be applied for each side.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sideao_all" data-tt-parent="p_sideao">all</div><br><br />
<div class="tt" data-tt-id="p_sideao_horizontals" data-tt-parent="p_sideao">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sideao_verticals" data-tt-parent="p_sideao">verticals</div><br><br />
<div class="tt" data-tt-id="p_sideao_east" data-tt-parent="p_sideao">east</div><br><br />
<div class="tt" data-tt-id="p_sideao_west" data-tt-parent="p_sideao">west</div><br><br />
<div class="tt" data-tt-id="p_sideao_up" data-tt-parent="p_sideao">up</div><br><br />
<div class="tt" data-tt-id="p_sideao_down" data-tt-parent="p_sideao">down</div><br><br />
<div class="tt" data-tt-id="p_sideao_north" data-tt-parent="p_sideao">north</div><br><br />
<div class="tt" data-tt-id="p_sideao_south" data-tt-parent="p_sideao">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sidesolid" data-tt-parent="root">sidesolid</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>Determins if given block side is solid. If true, other blocks like torches can be attached to it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sidesolid_all" data-tt-parent="p_sidesolid">all</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_horizontals" data-tt-parent="p_sidesolid">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_verticals" data-tt-parent="p_sidesolid">verticals</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_east" data-tt-parent="p_sidesolid">east</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_west" data-tt-parent="p_sidesolid">west</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_up" data-tt-parent="p_sidesolid">up</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_down" data-tt-parent="p_sidesolid">down</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_north" data-tt-parent="p_sidesolid">north</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_south" data-tt-parent="p_sidesolid">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomdrawoffset" data-tt-parent="root">randomdrawoffset</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If true then the block will be randomly offseted by 1/3 of a block when placed.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lighthsv" data-tt-parent="root">lighthsv</div></td><br />
<td>byte array with 3 elements. See http://tyron.at/vs/vslightwheel.html for valid values</td><br />
<td>-</td><br />
<td>For light emitting blocks: hue, saturation and brightness value.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lightabsorption" data-tt-parent="root">lightabsorption</div></td><br />
<td>0 ... 255</td><br />
<td>99</td><br />
<td>For light blocking blocks. Any value above 32 will completely block all light.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_guitransform" data-tt-parent="root">guitransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in guis.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fphandtransform" data-tt-parent="root">fphandtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in the first person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tphandtransform" data-tt-parent="root">tphandtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in the third person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_groundtransform" data-tt-parent="root">groundtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the rendered as a dropped item on the ground.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes" data-tt-parent="root">randomizeaxes</div></td><br />
<td>string</td><br />
<td>&quot;xyz&quot;</td><br />
<td>Random texture selection - whether or not to use the Y axis during randomization (for multiblock plants).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes_xyz" data-tt-parent="p_randomizeaxes">xyz</div></td><br />
<td></td><br />
<td>0</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes_xz" data-tt-parent="p_randomizeaxes">xz</div></td><br />
<td></td><br />
<td>1</td><br />
<td></td><br />
</tr><br />
</table><br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Block_Json_Properties&diff=4917Modding:Block Json Properties2019-06-05T14:06:05Z<p>CreativeMD: </p>
<hr />
<div>__NOTOC__<br />
== Overview ==<br />
A complete list of all available properties<br />
<br />
<table id="treeviewtable" class="table table-bordered tt-table" style='table-layout: fixed'><br />
<tr><br />
<th width='300' align='left'>Property</th><br />
<th width='200' align='left'>Type</th><br />
<th width='120' align='left'>Default</th><br />
<th align='left'>Usage</th><br />
</tr><br />
<tr><br />
<td><div class="tt" data-tt-id="root">json</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Core (no byType available)</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code" data-tt-parent="root">code</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>A unique identifier for the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code_info" data-tt-parent="p_code" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''domain prefix''' will be added dynamically depending on the location of the file. Every mod and VintageStory itself have a unique prefix.<br />
<br />
For example the code '''<code>stone</code>''' turns into '''<code>game:stone</code>'''. <br />
<br />
The code identifier has to be unique inside its domain. In theory there could be equal identifiers with different domain prefixes.<br />
Find out more about [[Basic Modding#Domains|Domains]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_enabled" data-tt-parent="root">enabled</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the block will be loaded or not. Can be used to temporarily remove the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups" data-tt-parent="root">variantgroups</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Allows you define multiple variants of the same block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups_info" data-tt-parent="p_variantgroups" data-invisible="true"></div></td><br />
<td colspan="3"><br />
The variantgroups property allows you to define multiple variants of this block. All of them will have their unique pattern, which will be added to the block code.<br />
<br />
An easy example would be a bowl, which can either be raw or burned:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"type", states: ["raw", "burned"] },<br />
],<br />
</syntaxhighlight><br />
<br />
Meaning there will be two blocks <code>bowl-raw</code> and <code>bowl-burned</code>.<br />
<br />
----<br />
<br />
It's also possible to define multiple groups. <br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"state", states: ["closed", "opened"] },<br />
{ code:"contents", states: ["empty", "cabbage"] },<br />
],<br />
</syntaxhighlight><br />
<br />
As a result you will have 2x2 groups, which will be added one after each other: <code>barrel-closed-empty</code>, <code>barrel-closed-cabbage</code>, <code>barrel-opened-empty</code> and <code>barrel-opened-cabbage</code>.<br />
<br />
----<br />
<br />
Additionally it is possible to refer to external lists that are found in the worldproperties folder, such as <code>block/rock</code>, which contains all states of all rock types. This used for <code>gravel</code>, <code>sand</code> and <code>rock</code>. It's a good way to keep everything organized:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ loadFromProperties: "block/rock" },<br />
],<br />
</syntaxhighlight><br />
<br />
Here is a full list of all groups and their variants (you can also find them in the <code>assets/worldproperties</code> folder):<br />
{{:json:block:worldvariantgroups}}<br />
<br />
----<br />
<br />
Furthermore there are two ways of combining groups together. So far we covered the default combination mode, which is <code>multiplicative</code> (the total count of variants is the product of all states).<br />
<br />
Let's take a look at a different example (flowerpot), which uses the <code>additive</code> combination mode:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["raw"] },<br />
{ code: "empty", states: ["empty"], combine: "additive" },<br />
{ code: "flower", loadFromProperties: "block/flower", combine: "additive" },<br />
{ code: "mushroom", loadFromProperties: "block/mushroom", combine: "additive" },<br />
{ code: "sapling", loadFromProperties: "block/wood", combine: "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
The variants are <code>flowerpot-raw</code>, <code>flowerpot-empty</code>, <code>flowerpot-{all flowers}</code>, <code>flowerpot-{all mushrooms}</code> and <code>flowerpot-{all saplings}</code>.<br />
<br />
<code>Additive</code> mode could also be called separate, since it defines a variant separate from all the other groups:<br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "something", states: ["same", "different"] },<br />
{ code: "type", states: ["raw", "baked"] },<br />
{ code: "empty", states: ["red", "green"], "combine": "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
In this case, the result would be <code>same-raw</code>, <code>same-baked</code>, <code>different-raw</code>, <code>different-baked</code>, <code>red</code> and <code>green</code><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType" data-tt-parent="root">(any) bytype</div></td><br />
<td>key: string; value: object</td><br />
<td>-</td><br />
<td>You can create properties for certain variants of the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType_info" data-tt-parent="p_byType" data-invisible="true"></div></td><br />
<td colspan="3"><br />
In order to define properties for specific variants you can add '''byType''' to the property name. This allows you to define it depending on the type and always follows the same syntax:<br />
<syntaxhighlight lang="json"><br />
(property)ByType: {<br />
"selector": property,<br />
"selector2": property2,<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
If the selector matches the name of the variant the given property will be used. Keep in mind that only the first matching one will be used (everything below will be ignored).<br />
<br />
A slab for example has two variants ('''up''', '''down'''), which have different collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
The char '''<code>*</code>''' stands for anything. In this case it ignores the code of the block.<br />
<br />
Furthermore this opens up even more possbilities for more advanced selectors like this one for doors:<br />
<code>*-north-*-opened-left</code>. This will ignore the second variantgroup. Additionally ByType can also be used for child properties:<br />
<syntaxhighlight lang="json"><br />
collisionboxnbox: { <br />
x1: 0, y1: 0, z1: 0.875, x2: 1, y2: 1, z2: 1,<br />
rotateYByType: {<br />
"*-north-*-opened-left": 90,<br />
"*-north-*-closed-left": 0,<br />
"*-west-*-opened-left": 180,<br />
"*-west-*-closed-left": 90,<br />
<br />
"*-east-*-opened-left": 0,<br />
"*-east-*-closed-left": 270,<br />
"*-south-*-opened-left": 270,<br />
"*-south-*-closed-left": 180,<br />
<br />
"*-north-*-opened-right": 270,<br />
"*-north-*-closed-right": 0,<br />
"*-west-*-opened-right": 0,<br />
"*-west-*-closed-right": 90,<br />
<br />
"*-east-*-opened-right": 180,<br />
"*-east-*-closed-right": 270,<br />
"*-south-*-opened-right": 90,<br />
"*-south-*-closed-right": 180<br />
}<br />
},<br />
</syntaxhighlight><br />
<br />
Since Vintagestory v1.8 it is also possible to use the variantgroup as a placeholder:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["normal", "bamboo"] },<br />
],<br />
textures: {<br />
horizontals: { base: "block/hay/{type}-side" },<br />
verticals: { base: "block/hay/{type}-top" },<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Specific</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class" data-tt-parent="root">class</div></td><br />
<td>string</td><br />
<td>&quot;block&quot;</td><br />
<td>The block class can add special functionalities for the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class_info" data-tt-parent="p_class" data-invisible="true"></div></td><br />
<td colspan="3"><br />
It can be used to open guis or adding other extra functionality to the block. A complete tutorial of how to add your own class to the game can be found [[Advanced Blocks|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_entityclass" data-tt-parent="root">entityclass</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>The block entity class is able to tick and to store extra data.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_entityclass_info" data-tt-parent="p_entityclass" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A chest for example uses the BlockEntity to store the inventory. A tutorial of creating your own entityclass can be found [[Block Entity|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors" data-tt-parent="root">behaviors</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>A behavior adds custom abilities such as falling block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors_info" data-tt-parent="p_behaviors" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Here is an overview of most exisiting behaviors, if you want to create your own custom behavior you can read [[Adding Block Behavior]].<br />
To see all of the current behaviors in the game see [[Json:block:behaviors|All Block Behaviors]]<br />
{{:json:block:behavior}}<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockmaterial" data-tt-parent="root">blockmaterial</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>A behavior adds custom abilities such as falling block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_blockmaterial_soil" data-tt-parent="p_blockmaterial">Soil</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_gravel" data-tt-parent="p_blockmaterial">Gravel</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_sand" data-tt-parent="p_blockmaterial">Sand</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_wood" data-tt-parent="p_blockmaterial">Wood</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_leaves" data-tt-parent="p_blockmaterial">Leaves</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_stone" data-tt-parent="p_blockmaterial">Stone</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_liquid" data-tt-parent="p_blockmaterial">Liquid</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_snow" data-tt-parent="p_blockmaterial">Snow</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_ice" data-tt-parent="p_blockmaterial">Ice</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_metal" data-tt-parent="p_blockmaterial">Metal</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_mantle" data-tt-parent="p_blockmaterial">Mantle</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_plant" data-tt-parent="p_blockmaterial">Plant</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_glass" data-tt-parent="p_blockmaterial">Glass</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_ceramic" data-tt-parent="p_blockmaterial">Ceramic</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_cloth" data-tt-parent="p_blockmaterial">Cloth</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_lava" data-tt-parent="p_blockmaterial">Lava</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_brick" data-tt-parent="p_blockmaterial">Brick</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_fire" data-tt-parent="p_blockmaterial">Fire</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_other" data-tt-parent="p_blockmaterial">Other</div><br />
</td><br />
<td colspan="3" valign="top"><br />
Materials are hardcoded and currently only used to determine mining speed with a specific tool.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_matterstate" data-tt-parent="root">matterstate</div></td><br />
<td>array of object</td><br />
<td>&quot;block&quot;</td><br />
<td>Determines whether the block is in a '''''solid''''', a '''''liquid''''', a '''''gas''''' or a '''''plasma''''' state.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_matterstate_solid" data-tt-parent="p_matterstate">solid</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_liquid" data-tt-parent="p_matterstate">liquid</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_gas" data-tt-parent="p_matterstate">gas</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_plasma" data-tt-parent="p_matterstate">plasma</div><br><br><br />
</td><br />
<td colspan="3"><br />
Used for special collision behavior and rendering. Currently used for:<br />
<br />
Liquid:<br />
*Lava<br />
*Water<br />
*Water with particles<br />
<br />
Gas/Plasma:<br />
none added yet<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_resistance" data-tt-parent="root">resistance</div></td><br />
<td>decimal number</td><br />
<td>6</td><br />
<td>How long it takes to break this block in seconds (with a mining speed of 1).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_resistance_info" data-tt-parent="p_resistance" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Same examples of resistance's values used in VintageStory:<br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">Block</th><br />
<th style="background-color: rgba(0,0,0,0.2);">Value</th><br />
</tr><br />
<tr><br />
<td>'''leave'''</td><br />
<td>''0.5''</td><br />
</tr><br />
<tr><br />
<td>'''wool'''</td><br />
<td>''1.0''</td><br />
</tr><br />
<tr><br />
<td>'''bowl'''</td><br />
<td>''1.5''</td><br />
</tr><br />
<tr><br />
<td>'''obsidian'''</td><br />
<td>''2''</td><br />
</tr><br />
<tr><br />
<td>'''plank'''</td><br />
<td>''3.5''</td><br />
</tr><br />
<tr><br />
<td>'''log'''</td><br />
<td>''4.5''</td><br />
</tr><br />
<tr><br />
<td>'''rock'''</td><br />
<td>''6''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requiredminingtier" data-tt-parent="root">requiredminingtier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Minimum required mining tier to get the drop out of the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requiredminingtier_info" data-tt-parent="p_requiredminingtier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">Tier</th><br />
<th style="background-color: rgba(0,0,0,0.2);">Ores</th><br />
</tr><br />
<tr><br />
<td>'''1'''</td><br />
<td>'''''gelena''''' and '''''rocksalt_sylvite'''''</td><br />
</tr><br />
<tr><br />
<td>'''2'''</td><br />
<td>'''''lignite''''', '''''cassiterite''''', '''''sphalerite''''', '''''rocksalt''''', '''''sulfur''''' and '''''nativecopper'''''</td><br />
</tr><br />
<tr><br />
<td>'''3'''</td><br />
<td>'''''bituminouscoal''''', '''''quartz_nativegold''''', '''''quartz_nativesilver''''', '''''lapislazuli''''', '''''bismuthinite''''', '''''quartz''''', '''''magnetite''''' and '''''limonite'''''</td><br />
</tr><br />
<tr><br />
<td>'''4'''</td><br />
<td>'''''diamond''''' and '''''emerald'''''</td><br />
</tr><br />
<tr><br />
<td>'''5'''</td><br />
<td>'''''chromite''''', '''''platinum''''' and '''''ilmenite'''''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_climbable" data-tt-parent="root">climbable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If true, walking against this block will make the player climb (used for ladders).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rainpermeable" data-tt-parent="root">rainpermeable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If rain can fall through this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_snowcoverage" data-tt-parent="root">snowcoverage</div></td><br />
<td>boolean</td><br />
<td>-</td><br />
<td>Whether snow may rest on top of this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_snowcoverage_info" data-tt-parent="p_snowcoverage" data-invisible="true"></div></td><br />
<td colspan="3"><br />
All none solid blocks can't be covered by snow unless it's defined different:<br />
*Leaves (also branchy): '''true''',<br />
*Water with particles, Lakeice: '''false'''<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionbox" data-tt-parent="root">collisionbox</div></td><br />
<td>object</td><br />
<td>box (0,0,0 -> 1,1,1)</td><br />
<td>Defines a box with which the player collides with.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionbox_info" data-tt-parent="p_collisionbox" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''half slab''' for example, has either a box going from 0,0,0 to 1,0.5,1 or going from 0,0.5,0 to 1,1,1, depending on whether it is a slab is down or up:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
Collision and selection boxes are most likely equal.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionboxes" data-tt-parent="root">collisionboxes</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Defines multiple boxes with which the player collides with.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionboxes_info" data-tt-parent="p_collisionboxes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''crate''' for example requires multiple collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxesByType: {<br />
"*-opened": [ <br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.0625, z2: 1 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 90 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 180 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 270 },<br />
]<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionbox" data-tt-parent="root">selectionbox</div></td><br />
<td>object</td><br />
<td>box (0,0,0 -> 1,1,1)</td><br />
<td>Defines a box which the player's mouse pointer collides with for selection.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionbox_info" data-tt-parent="p_selectionbox" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''half slab''' for example, has either a box going from 0,0,0 to 1,0.5,1 or going from 0,0.5,0 to 1,1,1, depending on whether it is a slab is down or up:<br />
<syntaxhighlight lang="json"><br />
selectionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
Collision and selection boxes are most likely equal.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionboxes" data-tt-parent="root">selectionboxes</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Defines multiple boxes which the player's mouse pointer collides with for selection.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionboxes_info" data-tt-parent="p_selectionboxes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''crate''' for example requires multiple selection boxes:<br />
<syntaxhighlight lang="json"><br />
selectionboxesByType: {<br />
"*-opened": [ <br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.0625, z2: 1 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 90 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 180 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 270 },<br />
]<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_replaceable" data-tt-parent="root">replaceable</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>A value usually between 0-9999 that indicates which blocks may be replaced with others.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_replaceable_info" data-tt-parent="p_replaceable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
<th style="background-color: rgba(0,0,0,0.2);">effect (blocks)</th><br />
</tr><br />
<tr><br />
<td>'''0'''</td><br />
<td>'''''ordinary blocks''''' (stone for example)</td><br />
</tr><br />
<tr><br />
<td>'''5000'''</td><br />
<td>Everything equal or above will be washed away by water (such as '''''Fruit''''').</td><br />
</tr><br />
<tr><br />
<td>'''6000'''</td><br />
<td>Everything equal or above wwill replaced when the player tries to place a block (such as '''''Tallgrass''''').</td><br />
</tr><br />
<tr><br />
<td>'''9000'''</td><br />
<td>'''''Lava'''''</td><br />
</tr><br />
<tr><br />
<td>'''9500'''</td><br />
<td>'''''Water'''''</td><br />
</tr><br />
<tr><br />
<td>'''9999'''</td><br />
<td>'''''Air'''''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fertility" data-tt-parent="root">fertility</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Which plants can grow on top of this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fertility_info" data-tt-parent="p_fertility" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
<th style="background-color: rgba(0,0,0,0.2);">effect</th><br />
</tr><br />
<tr><br />
<td>'''0'''</td><br />
<td>''nothing can grow.''</td><br />
</tr><br />
<tr><br />
<td>'''10'''</td><br />
<td>''some tallgrass and small trees can be grow on it.''</td><br />
</tr><br />
<tr><br />
<td>'''100'''</td><br />
<td>''all grass and trees can grow on it.''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_glowlevel" data-tt-parent="root">glowLevel</div></td><br />
<td>0 ... 255</td><br />
<td>0</td><br />
<td>Causes the block to visually glow if Bloom is enabled. Basic glow level for all the blocks model elements.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_glowlevel_info" data-tt-parent="p_glowlevel" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Glacierice''</td><br />
<td>'''8'''</td><br />
</tr><br />
<tr><br />
<td>''Paperlantern''</td><br />
<td>'''32'''</td><br />
</tr><br />
<tr><br />
<td>''Ember''</td><br />
<td>'''48'''</td><br />
</tr><br />
<tr><br />
<td>''Fire'', ''Firepit'', ''Oillamp'', ''Torch''</td><br />
<td>'''64'''</td><br />
</tr><br />
<tr><br />
<td>''Lava''</td><br />
<td>'''128'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lightabsorption" data-tt-parent="root">lightabsorption</div></td><br />
<td>0 ... 32</td><br />
<td>0</td><br />
<td>For light blocking blocks. Any value above 32 will completely block all light.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_walkspeedmultiplier" data-tt-parent="root">walkspeedmultiplier</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>Percentage walk-speed when standing on or inside this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_walkspeedmultiplier_info" data-tt-parent="p_walkspeedmultiplier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Spiderweb''</td><br />
<td>'''0.25'''</td><br />
</tr><br />
<tr><br />
<td>''Stonepath''</td><br />
<td>'''1.15'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_dragmultiplier" data-tt-parent="root">dragmultiplier</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>Drag multiplier applied to entities standing on it (slipperiness factor).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_dragmultiplier_info" data-tt-parent="p_dragmultiplier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Glacierice'', ''Lakeice''</td><br />
<td>'''0.02'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drops" data-tt-parent="root">drops</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>The items that should drop from breaking this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drops_info" data-tt-parent="p_drops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<br />
'''Drop itself'''<br />
<br />
If this property does not exist the block will drop itself.<br />
<br />
----<br />
<br />
'''No drop'''<br />
<br />
A '''firepit''' for example doesn't drop anything. You can do so if you specify an empty array:<br />
<syntaxhighlight lang="json"><br />
drops: [],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Special drop'''<br />
<br />
You can also specify a special item/ block. Therefore you need to define an '''ItemStack''', with the given properties:<br />
<br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">property</th><br />
<th style="background-color: rgba(0,0,0,0.2);">default</th><br />
<th style="background-color: rgba(0,0,0,0.2);">explanation</th><br />
</tr><br />
<tr><br />
<td>'''type'''</td><br />
<td>''block''</td><br />
<td>Can either be '''''block''''' or '''''item'''''.</td><br />
</tr><br />
<tr><br />
<td>'''code''' (required)</td><br />
<td>-</td><br />
<td>The complete code (can also include domain) of the item or block.</td><br />
</tr><br />
<tr><br />
<td>'''lastdrop'''</td><br />
<td>false</td><br />
<td>If true and the quantity dropped is >=1 any subsequent drop in the list will be ignored.</td><br />
</tr><br />
<tr><br />
<td>'''attributes'''</td><br />
<td>-</td><br />
<td>Tree Attributes that will be attached to the resulting itemstack.</td><br />
</tr><br />
<tr><br />
<td>'''tool'''</td><br />
<td>-</td><br />
<td>If specified then given tool is required to break this block.</td><br />
</tr><br />
<tr><br />
<td>'''quantity'''</td><br />
<td>- (one)</td><br />
<td>Determines the quantity of items which will be dropped.</td><br />
</tr><br />
</table><br />
<br />
For example, the drop of a '''charcoalpile''' looks like this:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "charcoal" }<br />
],<br />
</syntaxhighlight><br />
<br />
'''Tallgrass''' will only drop something if it's mined by a knife:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "drygrass", tool: "knife" },<br />
],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Chance drops'''<br />
<br />
Let's take a look at an example. This is the drop property of rock:<br />
<br />
<syntaxhighlight lang="json"> <br />
drops: [<br />
{<br />
type: "item", <br />
code: "stone-{rock}", <br />
quantity: { avg: 2.5, var: 0.5 } <br />
},<br />
]<br />
</syntaxhighlight><br />
<br />
This will drop 2-3 blocks.<br />
<br />
'''''avg''''': Stands for the default drop quantity. If var is 0 or not specified it will always drop the given average.<br />
<br />
'''''var''''': How much the drop rate can vary. Meaning the drop rate can be <code>avg - var</code> at minimum and <code>age + var</code> at maximum.<br />
<br />
For more information see [[NatFloat]] page.<br />
<br />
----<br />
<br />
'''Multiple Drops'''<br />
<br />
Of course you can also define multiple drops at once. '''Sapling''' can drop a sapling and a stick:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ <br />
type: "block", <br />
code: "sapling-{wood}",<br />
quantity: { avg: 0.02, var: 0 },<br />
},<br />
{ <br />
type: "item", <br />
code: "stick",<br />
quantity: { avg: 0.02, var: 0 },<br />
}<br />
],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Last Drop'''<br />
<br />
In order to add a special drop, which (if dropped) prevents all other drops, you can use the lastDrop property:<br />
<br />
<syntaxhighlight lang="json"><br />
dropsByType: {<br />
"ore-quartz-*": [<br />
{ type: "item", code: "clearquartz", quantity: { avg: 0.2, var: 0 }, lastDrop: true },<br />
{ type: "item", code: "ore-{ore}", quantity: { avg: 1.25, var: 0 } }<br />
],<br />
"*": [ <br />
{ type: "item", code: "ore-{ore}", quantity: { avg: 1.25, var: 0 } }<br />
],<br />
}<br />
</syntaxhighlight><br />
<br />
Quartz ore will drop with a 20% chance clearquartz, if not it will drop the regular ore. If lastDrop wouldn't be true it could drop both at the same time.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_particleproperties" data-tt-parent="root">particleproperties</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Particles that should spawn in regular intervals from this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_particleproperties_info" data-tt-parent="p_particleproperties" data-invisible="true"></div></td><br />
<td colspan="3"><br />
{{:json:block:particle}}<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="root">liquidlevel</div></td><br />
<td>0 ... 7</td><br />
<td>0</td><br />
<td>Value between 0...7 for Liquids to determine the height of the liquid.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cropprops" data-tt-parent="root">cropprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the block as a crop.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds" data-tt-parent="root">sounds</div></td><br />
<td>key: string, value: string</td><br />
<td>-</td><br />
<td>The sounds played for this block during step, break, build and walk.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_walk" data-tt-parent="p_sounds">walk</div></td><br />
<td colspan="3">An entity walks over it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_inside" data-tt-parent="p_sounds">inside</div></td><br />
<td colspan="3">The player is inside the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_break" data-tt-parent="p_sounds">break</div></td><br />
<td colspan="3">Breaking the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_place" data-tt-parent="p_sounds">place</div></td><br />
<td colspan="3">Placing the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_hit" data-tt-parent="p_sounds">hit</div></td><br />
<td colspan="3">While mining the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_ambient" data-tt-parent="p_sounds">ambient</div></td><br />
<td colspan="3">Played from time to time if the player is close to it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_info" data-tt-parent="p_sounds" data-invisible="true"></div></td><br />
<td colspan="3"><br />
'''Anvil''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
"place": "block/anvil",<br />
"break": "block/anvil"<br />
}<br />
</syntaxhighlight><br />
<br />
'''Rails''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
place": "block/planks",<br />
"walk": "walk/wood"<br />
}<br />
</syntaxhighlight><br />
<br />
'''Water''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
place: "block/water",<br />
inside: "walk/water",<br />
ambient: "environment/creek"<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Common</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory" data-tt-parent="root">creativeinventory</div></td><br />
<td>key: string, value: string[]</td><br />
<td>-</td><br />
<td>In which creative inventory tabs the block should be visible in.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory_info" data-tt-parent="p_creativeinventory" data-invisible="true"></div></td><br />
<td colspan="3"><br />
There are several tabs to you can add your stuff. Note that general should always be included, since it should contain everything.<br />
<br />
*general<br />
*terrain<br />
*flora<br />
*construction<br />
*decorative<br />
*items<br />
<br />
'''Rock''' adds all of it's variantions to general, terrain and construction:<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*"], "terrain": ["*"], "construction": ["*"] },<br />
</syntaxhighlight><br />
<br />
'''<code>*</code>''' reprents the variants which will be added. You can specify multiple and separate them with a comma. It follows the same way as the '''byType''' property.<br />
<br />
A '''Torch''' on the other hand only adds the variation '''<code>up</code>''':<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*-up"], "decorative": ["*-up"] },<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_maxstacksize" data-tt-parent="root">maxstacksize</div></td><br />
<td>integer</td><br />
<td>64</td><br />
<td>Determines the maximum amount you can stack the block in one slot.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackpower" data-tt-parent="root">attackpower</div></td><br />
<td>decimal number</td><br />
<td>0.5</td><br />
<td>The damage the deals when hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackrange" data-tt-parent="root">attackrange</div></td><br />
<td>decimal number</td><br />
<td>1.5</td><br />
<td>The maximum distance you can hit an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity" data-tt-parent="root">materialdensity</div></td><br />
<td>integer</td><br />
<td>9999</td><br />
<td>Determines on whether an object floats on liquids or not.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity_info" data-tt-parent="p_materialdensity" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Water has a density of 1000, meaning everything below or equal will float on water. The same goes for lava which has a density of 5000.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable" data-tt-parent="root">liquidselectable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If the block can select a liquid while holding it in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable_info" data-tt-parent="p_liquidselectable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Used for buckets in order to fill it with water and to place waterlily on top of water.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningSpeed</div></td><br />
<td>key: string, value: decimal number</td><br />
<td>-</td><br />
<td>The mining speed for each material.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningTier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Determines which blocks it can break. If the required miningtier is above the defined one there will be no drop from it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes" data-tt-parent="root">attributes</div></td><br />
<td>key: string, value: object</td><br />
<td>-</td><br />
<td>Custom Attributes associated with this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_info" data-tt-parent="p_attributes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Extra attributes added to a block. Those are final and cannot be modified. It's a good way to keep things organized and and modifiable. The '''oreblastingbomb''' for example has attributes, which define its radius and type. These can be used by behaviors and blockentities:<br />
<syntaxhighlight lang="json"><br />
attributes: {<br />
"blastRadius": 4,<br />
"blastType": 0,<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops" data-tt-parent="root">combustibleprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the blocks burnable states.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burntemperature" data-tt-parent="p_combustibleprops">burntemperature</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>The temperature at which it burns in degrees Celsius.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burnduration" data-tt-parent="p_combustibleprops">burnduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how long it burns in seconds.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_heatresistance" data-tt-parent="p_combustibleprops">heatresistance</div></td><br />
<td>integer</td><br />
<td>500</td><br />
<td>How many degrees celsius it can resists before it ignites (not implemented yet).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingpoint" data-tt-parent="p_combustibleprops">meltingpoint</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>How many degrees celsius it takes to smelt/transform this into another. Only used when put in a stove and SmeltedStack is set.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingduration" data-tt-parent="p_combustibleprops">meltingduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how many seconds the temperature has to be above the melting point until the item is smelted.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smokelevel" data-tt-parent="p_combustibleprops">smokelevel</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>How much smoke this item produces when being used as fuel.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smeltedratio" data-tt-parent="p_combustibleprops">smeltedratio</div></td><br />
<td>integer</td><br />
<td>1</td><br />
<td>How many ores are required to produce one output stack.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="p_combustibleprops">smeltedstack</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>If set, the block/item is smeltable in a furnace and this is the resulting itemstack once the MeltingPoint has been reached for the supplied duration.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requirescontainer" data-tt-parent="p_combustibleprops">requirescontainer</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If set to true, the block/item requires a smelting/cooking/baking container such as the Crucible. If false, it can be directly baked/melted without smelting/cooking/baking container.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops_info" data-tt-parent="p_combustibleprops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
This property can be used to define a burning material. '''Plank''' for example can get on fire:<br />
<syntaxhighlight lang="json"><br />
combustibleProps: {<br />
burnTemperature: 800,<br />
burnDuration: 12,<br />
},<br />
</syntaxhighlight><br />
<br />
Furthermore it can be used to define smelting processes. An example would be an '''ingotmold''' which turns into an ingotmold-burned:<br />
<syntaxhighlight lang="json"><br />
combustiblePropsByType: {<br />
"ingotmold-raw": {<br />
meltingPoint: 600,<br />
meltingDuration: 30,<br />
smeltedRatio: 1,<br />
smeltedStack: { type: "block", code: "ingotmold-burned" },<br />
requiresContainer: false<br />
}<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops" data-tt-parent="root">nutritionprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the blocks nutrients.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_foodcategory" data-tt-parent="p_nutritionprops">foodcategory</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>Defines the type of food. It can be '''''fruit''''', '''''vegetable''''', '''''protein''''', '''''grain''''' and '''''dairy'''''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_saturation" data-tt-parent="p_nutritionprops">saturation</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much saturation it can restore.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_health" data-tt-parent="p_nutritionprops">health</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much health it can restore.</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Rendering</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_textures" data-tt-parent="root">textures</div></td><br />
<td>key: string, value: object</td><br />
<td></td><br />
<td>The texture definitions for the block as seen in the world, when dropped on the ground or held in the hand. Within a mod, to refer to a texture from the base game, prefix the path with "game:" (i.e. base: "game:path/to/texture") </td><br />
</tr><br />
<tr><br />
<td scope="row" valign="top"><div class="tt" data-tt-id="p_textures_base" data-tt-parent="p_textures">base</div><br><br><div class="tt" data-tt-id="p_textures_overlays" data-tt-parent="p_textures">overlays</div><br><br><div class="tt" data-tt-id="p_textures_base" data-tt-parent="p_textures">alternates</div></td><br />
<td colspan="3">{{:json:block:texture}}</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_texturesinventory" data-tt-parent="root">texturesinventory</div></td><br />
<td>key: string, value: object</td><br />
<td></td><br />
<td>The texture definitions for the block as seen in the player inventory. Overrides the textures.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shape" data-tt-parent="root">shape</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>For the json drawtype, the shape definition of the block as shown in the world, dropped on the ground or held in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_base" data-tt-parent="p_shape">base</div></td><br />
<td></td><br />
<td></td><br />
<td>The path to the shape json file, the base dir is ''assets/shapes/''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateX" data-tt-parent="p_shape">rotatex</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateY" data-tt-parent="p_shape">rotatey</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateZ" data-tt-parent="p_shape">rotatez</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shapeinventory" data-tt-parent="root">shapeinventory</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>For the json drawtype, the shape definition of the block as shown in the players inventory.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drawtype" data-tt-parent="root">drawtype</div></td><br />
<td>string</td><br />
<td>&quot;cube&quot;</td><br />
<td>Determines how the block is tesselated, select JSON for being able to use custom JSON Models. The other values are hardcoded methods of tesselating the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_1" data-tt-parent="p_drawtype">blockLayer_1</div></td><br />
<td></td><br />
<td>0</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_2" data-tt-parent="p_drawtype">blockLayer_2</div></td><br />
<td></td><br />
<td>1</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_3" data-tt-parent="p_drawtype">blockLayer_3</div></td><br />
<td></td><br />
<td>2</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_4" data-tt-parent="p_drawtype">blockLayer_4</div></td><br />
<td></td><br />
<td>3</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_5" data-tt-parent="p_drawtype">blockLayer_5</div></td><br />
<td></td><br />
<td>4</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_6" data-tt-parent="p_drawtype">blockLayer_6</div></td><br />
<td></td><br />
<td>5</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_7" data-tt-parent="p_drawtype">blockLayer_7</div></td><br />
<td></td><br />
<td>6</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_json" data-tt-parent="p_drawtype">json</div></td><br />
<td></td><br />
<td>7</td><br />
<td>Will draw a json model.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_empty" data-tt-parent="p_drawtype">empty</div></td><br />
<td></td><br />
<td>8</td><br />
<td>Nothing will be drawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cube" data-tt-parent="p_drawtype">cube</div></td><br />
<td></td><br />
<td>9</td><br />
<td>Draws an ordinary cube.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cross" data-tt-parent="p_drawtype">cross</div></td><br />
<td></td><br />
<td>10</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_transparent" data-tt-parent="p_drawtype">transparent</div></td><br />
<td></td><br />
<td>11</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquid" data-tt-parent="p_drawtype">liquid</div></td><br />
<td></td><br />
<td>12</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_crossandsnowlayer" data-tt-parent="p_drawtype">crossandsnowlayer</div></td><br />
<td></td><br />
<td>13</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_renderpass" data-tt-parent="root">renderpass</div></td><br />
<td>string</td><br />
<td>&quot;opaque&quot;</td><br />
<td>Determines how the block will be drawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_opaque" data-tt-parent="p_renderpass">opaque</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Used for solid blocks with no half transparency.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_opaquenocull" data-tt-parent="p_renderpass">opaquenocull</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Used for non-solid single faced blocks, such as tall grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_transparent" data-tt-parent="p_renderpass">transparent</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Use for solid halftransparent blocks, such as glass</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquid" data-tt-parent="p_renderpass">liquid</div></td><br />
<td></td><br />
<td>3</td><br />
<td>Used for liquids, produces waves.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_topsoil" data-tt-parent="p_renderpass">topsoil</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Used for grass covered blocks. Allows for a smooth transition from grass to soil, while still allowing climate tinting of grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_ambientocclusion" data-tt-parent="root">ambientocclusion</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If ambient occlusion will be applied to the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tintindex" data-tt-parent="root">tintindex</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>'''''0''''' for no tint, '''''1''''' for plant climate tint, '''''2''''' for water climate tint.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_renderflags" data-tt-parent="root">renderflags</div></td><br />
<td>0 ... 255</td><br />
<td>0</td><br />
<td>8 bits that are sent to the graphics card for each vertex of the blocks shape. The lower 3 bits are currently used for altering the vertexes z-depth to fix a bunch of z-fighting issues.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode" data-tt-parent="root">facecullmode</div></td><br />
<td>string</td><br />
<td>&quot;default&quot;</td><br />
<td>Determines which sides of the blocks should be rendered.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">default</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Culls faces if they are opaque faces adjacent to opaque faces.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">nevercull</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Never culls any faces.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">merge</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Culls all faces that are adjacent to opaque faces and faces adjacent to blocks of the same id (Example usage: Ice blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">collapse</div></td><br />
<td></td><br />
<td>3</td><br />
<td>Culls all faces that are adjacent to opaque faces and the bottom, east or south faces adjacent to blocks of the same id. This causes to still leave one single face in between instead of 2, eliminating any z-fighting.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">mergematerial</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Same as Merge but checks for equal material (Example usage: Plain glass and all colored glass blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">collapsematerial</div></td><br />
<td></td><br />
<td>5</td><br />
<td>Same as Collapse but checks for equal material (Example usage: All leaves blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">liquid</div></td><br />
<td></td><br />
<td>6</td><br />
<td>Same as CollapseMaterial but also culls faces towards opaque blocks.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sideopaque" data-tt-parent="root">sideopaque</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>Determines if given block face is fully opaque. If yes, the opposite face of the adjacent block will not be drawn for efficiency reasons.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sideopaque_all" data-tt-parent="p_sideopaque">all</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_horizontals" data-tt-parent="p_sideopaque">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_verticals" data-tt-parent="p_sideopaque">verticals</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_east" data-tt-parent="p_sideopaque">east</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_west" data-tt-parent="p_sideopaque">west</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_up" data-tt-parent="p_sideopaque">up</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_down" data-tt-parent="p_sideopaque">down</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_north" data-tt-parent="p_sideopaque">north</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_south" data-tt-parent="p_sideopaque">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sideao" data-tt-parent="root">sideao</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>If AmbientOcclusion will be applied for each side.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sideao_all" data-tt-parent="p_sideao">all</div><br><br />
<div class="tt" data-tt-id="p_sideao_horizontals" data-tt-parent="p_sideao">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sideao_verticals" data-tt-parent="p_sideao">verticals</div><br><br />
<div class="tt" data-tt-id="p_sideao_east" data-tt-parent="p_sideao">east</div><br><br />
<div class="tt" data-tt-id="p_sideao_west" data-tt-parent="p_sideao">west</div><br><br />
<div class="tt" data-tt-id="p_sideao_up" data-tt-parent="p_sideao">up</div><br><br />
<div class="tt" data-tt-id="p_sideao_down" data-tt-parent="p_sideao">down</div><br><br />
<div class="tt" data-tt-id="p_sideao_north" data-tt-parent="p_sideao">north</div><br><br />
<div class="tt" data-tt-id="p_sideao_south" data-tt-parent="p_sideao">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sidesolid" data-tt-parent="root">sidesolid</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>Determins if given block side is solid. If true, other blocks like torches can be attached to it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sidesolid_all" data-tt-parent="p_sidesolid">all</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_horizontals" data-tt-parent="p_sidesolid">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_verticals" data-tt-parent="p_sidesolid">verticals</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_east" data-tt-parent="p_sidesolid">east</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_west" data-tt-parent="p_sidesolid">west</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_up" data-tt-parent="p_sidesolid">up</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_down" data-tt-parent="p_sidesolid">down</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_north" data-tt-parent="p_sidesolid">north</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_south" data-tt-parent="p_sidesolid">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomdrawoffset" data-tt-parent="root">randomdrawoffset</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If true then the block will be randomly offseted by 1/3 of a block when placed.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lighthsv" data-tt-parent="root">lighthsv</div></td><br />
<td>byte array with 3 elements. See http://tyron.at/vs/vslightwheel.html for valid values</td><br />
<td>-</td><br />
<td>For light emitting blocks: hue, saturation and brightness value.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lightabsorption" data-tt-parent="root">lightabsorption</div></td><br />
<td>0 ... 255</td><br />
<td>99</td><br />
<td>For light blocking blocks. Any value above 32 will completely block all light.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_guitransform" data-tt-parent="root">guitransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in guis.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fphandtransform" data-tt-parent="root">fphandtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in the first person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tphandtransform" data-tt-parent="root">tphandtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in the third person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_groundtransform" data-tt-parent="root">groundtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the rendered as a dropped item on the ground.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes" data-tt-parent="root">randomizeaxes</div></td><br />
<td>string</td><br />
<td>&quot;xyz&quot;</td><br />
<td>Random texture selection - whether or not to use the Y axis during randomization (for multiblock plants).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes_xyz" data-tt-parent="p_randomizeaxes">xyz</div></td><br />
<td></td><br />
<td>0</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes_xz" data-tt-parent="p_randomizeaxes">xz</div></td><br />
<td></td><br />
<td>1</td><br />
<td></td><br />
</tr><br />
</table><br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Block_Json_Properties&diff=4916Modding:Block Json Properties2019-06-05T14:05:05Z<p>CreativeMD: </p>
<hr />
<div>__NOTOC__<br />
== Overview ==<br />
A complete list of all available properties<br />
<br />
<table id="treeviewtable" class="table table-bordered tt-table" style='table-layout: fixed'><br />
<tr><br />
<th width='300' align='left'>Property</th><br />
<th width='200' align='left'>Type</th><br />
<th width='120' align='left'>Default</th><br />
<th align='left'>Usage</th><br />
</tr><br />
<tr><br />
<td><div class="tt" data-tt-id="root">json</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Core (no byType available)</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code" data-tt-parent="root">code</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>A unique identifier for the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code_info" data-tt-parent="p_code" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''domain prefix''' will be added dynamically depending on the location of the file. Every mod and VintageStory itself have a unique prefix.<br />
<br />
For example the code '''<code>stone</code>''' turns into '''<code>game:stone</code>'''. <br />
<br />
The code identifier has to be unique inside its domain. In theory there could be equal identifiers with different domain prefixes.<br />
Find out more about [[Basic Modding#Domains|Domains]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_enabled" data-tt-parent="root">enabled</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the block will be loaded or not. Can be used to temporarily remove the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups" data-tt-parent="root">variantgroups</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Allows you define multiple variants of the same block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups_info" data-tt-parent="p_variantgroups" data-invisible="true"></div></td><br />
<td colspan="3"><br />
The variantgroups property allows you to define multiple variants of this block. All of them will have their unique pattern, which will be added to the block code.<br />
<br />
An easy example would be a bowl, which can either be raw or burned:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"type", states: ["raw", "burned"] },<br />
],<br />
</syntaxhighlight><br />
<br />
Meaning there will be two blocks <code>bowl-raw</code> and <code>bowl-burned</code>.<br />
<br />
----<br />
<br />
It's also possible to define multiple groups. <br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"state", states: ["closed", "opened"] },<br />
{ code:"contents", states: ["empty", "cabbage"] },<br />
],<br />
</syntaxhighlight><br />
<br />
As a result you will have 2x2 groups, which will be added one after each other: <code>barrel-closed-empty</code>, <code>barrel-closed-cabbage</code>, <code>barrel-opened-empty</code> and <code>barrel-opened-cabbage</code>.<br />
<br />
----<br />
<br />
Additionally it is possible to refer to external lists that are found in the worldproperties folder, such as <code>block/rock</code>, which contains all states of all rock types. This used for <code>gravel</code>, <code>sand</code> and <code>rock</code>. It's a good way to keep everything organized:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ loadFromProperties: "block/rock" },<br />
],<br />
</syntaxhighlight><br />
<br />
Here is a full list of all groups and their variants (you can also find them in the <code>assets/worldproperties</code> folder):<br />
{{:json:block:worldvariantgroups}}<br />
<br />
----<br />
<br />
Furthermore there are two ways of combining groups together. So far we covered the default combination mode, which is <code>multiplicative</code> (the total count of variants is the product of all states).<br />
<br />
Let's take a look at a different example (flowerpot), which uses the <code>additive</code> combination mode:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["raw"] },<br />
{ code: "empty", states: ["empty"], combine: "additive" },<br />
{ code: "flower", loadFromProperties: "block/flower", combine: "additive" },<br />
{ code: "mushroom", loadFromProperties: "block/mushroom", combine: "additive" },<br />
{ code: "sapling", loadFromProperties: "block/wood", combine: "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
The variants are <code>flowerpot-raw</code>, <code>flowerpot-empty</code>, <code>flowerpot-{all flowers}</code>, <code>flowerpot-{all mushrooms}</code> and <code>flowerpot-{all saplings}</code>.<br />
<br />
<code>Additive</code> mode could also be called separate, since it defines a variant separate from all the other groups:<br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "something", states: ["same", "different"] },<br />
{ code: "type", states: ["raw", "baked"] },<br />
{ code: "empty", states: ["red", "green"], "combine": "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
In this case, the result would be <code>same-raw</code>, <code>same-baked</code>, <code>different-raw</code>, <code>different-baked</code>, <code>red</code> and <code>green</code><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType" data-tt-parent="root">(any) bytype</div></td><br />
<td>key: string; value: object</td><br />
<td>-</td><br />
<td>You can create properties for certain variants of the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType_info" data-tt-parent="p_byType" data-invisible="true"></div></td><br />
<td colspan="3"><br />
In order to define properties for specific variants you can add '''byType''' to the property name. This allows you to define it depending on the type and always follows the same syntax:<br />
<syntaxhighlight lang="json"><br />
(property)ByType: {<br />
"selector": property,<br />
"selector2": property2,<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
If the selector matches the name of the variant the given property will be used. Keep in mind that only the first matching one will be used (everything below will be ignored).<br />
<br />
A slab for example has two variants ('''up''', '''down'''), which have different collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
The char '''<code>*</code>''' stands for anything. In this case it ignores the code of the block.<br />
<br />
Furthermore this opens up even more possbilities for more advanced selectors like this one for doors:<br />
<code>*-north-*-opened-left</code>. This will ignore the second variantgroup. Additionally ByType can also be used for child properties:<br />
<syntaxhighlight lang="json"><br />
collisionboxnbox: { <br />
x1: 0, y1: 0, z1: 0.875, x2: 1, y2: 1, z2: 1,<br />
rotateYByType: {<br />
"*-north-*-opened-left": 90,<br />
"*-north-*-closed-left": 0,<br />
"*-west-*-opened-left": 180,<br />
"*-west-*-closed-left": 90,<br />
<br />
"*-east-*-opened-left": 0,<br />
"*-east-*-closed-left": 270,<br />
"*-south-*-opened-left": 270,<br />
"*-south-*-closed-left": 180,<br />
<br />
"*-north-*-opened-right": 270,<br />
"*-north-*-closed-right": 0,<br />
"*-west-*-opened-right": 0,<br />
"*-west-*-closed-right": 90,<br />
<br />
"*-east-*-opened-right": 180,<br />
"*-east-*-closed-right": 270,<br />
"*-south-*-opened-right": 90,<br />
"*-south-*-closed-right": 180<br />
}<br />
},<br />
</syntaxhighlight><br />
<br />
Since Vintagestory v1.8 it is also possible to use the variantgroup as a placeholder:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["normal", "bamboo"] },<br />
],<br />
textures: {<br />
horizontals: { base: "block/hay/{type}-side" },<br />
verticals: { base: "block/hay/{type}-top" },<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Specific</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class" data-tt-parent="root">class</div></td><br />
<td>string</td><br />
<td>&quot;block&quot;</td><br />
<td>The block class can add special functionalities for the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class_info" data-tt-parent="p_class" data-invisible="true"></div></td><br />
<td colspan="3"><br />
It can be used to open guis or adding other extra functionality to the block. A complete tutorial of how to add your own class to the game can be found [[Advanced Blocks|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_entityclass" data-tt-parent="root">entityclass</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>The block entity class is able to tick and to store extra data.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_entityclass_info" data-tt-parent="p_entityclass" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A chest for example uses the BlockEntity to store the inventory. A tutorial of creating your own entityclass can be found [[Block Entity|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors" data-tt-parent="root">behaviors</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>A behavior adds custom abilities such as falling block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_behaviors_info" data-tt-parent="p_behaviors" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Here is an overview of most exisiting behaviors, if you want to create your own custom behavior you can read [[Adding Block Behavior]].<br />
To see all of the current behaviors in the game see [[Json:block:behaviors|All Block Behaviors]]<br />
{{:json:block:behavior}}<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockmaterial" data-tt-parent="root">blockmaterial</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>A behavior adds custom abilities such as falling block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_blockmaterial_soil" data-tt-parent="p_blockmaterial">Soil</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_gravel" data-tt-parent="p_blockmaterial">Gravel</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_sand" data-tt-parent="p_blockmaterial">Sand</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_wood" data-tt-parent="p_blockmaterial">Wood</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_leaves" data-tt-parent="p_blockmaterial">Leaves</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_stone" data-tt-parent="p_blockmaterial">Stone</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_liquid" data-tt-parent="p_blockmaterial">Liquid</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_snow" data-tt-parent="p_blockmaterial">Snow</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_ice" data-tt-parent="p_blockmaterial">Ice</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_metal" data-tt-parent="p_blockmaterial">Metal</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_mantle" data-tt-parent="p_blockmaterial">Mantle</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_plant" data-tt-parent="p_blockmaterial">Plant</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_glass" data-tt-parent="p_blockmaterial">Glass</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_ceramic" data-tt-parent="p_blockmaterial">Ceramic</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_cloth" data-tt-parent="p_blockmaterial">Cloth</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_lava" data-tt-parent="p_blockmaterial">Lava</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_brick" data-tt-parent="p_blockmaterial">Brick</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_fire" data-tt-parent="p_blockmaterial">Fire</div><br><br />
<div class="tt" data-tt-id="p_blockmaterial_other" data-tt-parent="p_blockmaterial">Other</div><br />
</td><br />
<td colspan="3" valign="top"><br />
Materials are hardcoded and currently only used to determine mining speed with a specific tool.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_matterstate" data-tt-parent="root">matterstate</div></td><br />
<td>array of object</td><br />
<td>&quot;block&quot;</td><br />
<td>Determines whether the block is in a '''''solid''''', a '''''liquid''''', a '''''gas''''' or a '''''plasma''''' state.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_matterstate_solid" data-tt-parent="p_matterstate">solid</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_liquid" data-tt-parent="p_matterstate">liquid</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_gas" data-tt-parent="p_matterstate">gas</div><br><br><br />
<div class="tt" data-tt-id="p_matterstate_plasma" data-tt-parent="p_matterstate">plasma</div><br><br><br />
</td><br />
<td colspan="3"><br />
Used for special collision behavior and rendering. Currently used for:<br />
<br />
Liquid:<br />
*Lava<br />
*Water<br />
*Water with particles<br />
<br />
Gas/Plasma:<br />
none added yet<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_resistance" data-tt-parent="root">resistance</div></td><br />
<td>decimal number</td><br />
<td>6</td><br />
<td>How long it takes to break this block in seconds (with a mining speed of 1).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_resistance_info" data-tt-parent="p_resistance" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Same examples of resistance's values used in VintageStory:<br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">Block</th><br />
<th style="background-color: rgba(0,0,0,0.2);">Value</th><br />
</tr><br />
<tr><br />
<td>'''leave'''</td><br />
<td>''0.5''</td><br />
</tr><br />
<tr><br />
<td>'''wool'''</td><br />
<td>''1.0''</td><br />
</tr><br />
<tr><br />
<td>'''bowl'''</td><br />
<td>''1.5''</td><br />
</tr><br />
<tr><br />
<td>'''obsidian'''</td><br />
<td>''2''</td><br />
</tr><br />
<tr><br />
<td>'''plank'''</td><br />
<td>''3.5''</td><br />
</tr><br />
<tr><br />
<td>'''log'''</td><br />
<td>''4.5''</td><br />
</tr><br />
<tr><br />
<td>'''rock'''</td><br />
<td>''6''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requiredminingtier" data-tt-parent="root">requiredminingtier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Minimum required mining tier to get the drop out of the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requiredminingtier_info" data-tt-parent="p_requiredminingtier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">Tier</th><br />
<th style="background-color: rgba(0,0,0,0.2);">Ores</th><br />
</tr><br />
<tr><br />
<td>'''1'''</td><br />
<td>'''''gelena''''' and '''''rocksalt_sylvite'''''</td><br />
</tr><br />
<tr><br />
<td>'''2'''</td><br />
<td>'''''lignite''''', '''''cassiterite''''', '''''sphalerite''''', '''''rocksalt''''', '''''sulfur''''' and '''''nativecopper'''''</td><br />
</tr><br />
<tr><br />
<td>'''3'''</td><br />
<td>'''''bituminouscoal''''', '''''quartz_nativegold''''', '''''quartz_nativesilver''''', '''''lapislazuli''''', '''''bismuthinite''''', '''''quartz''''', '''''magnetite''''' and '''''limonite'''''</td><br />
</tr><br />
<tr><br />
<td>'''4'''</td><br />
<td>'''''diamond''''' and '''''emerald'''''</td><br />
</tr><br />
<tr><br />
<td>'''5'''</td><br />
<td>'''''chromite''''', '''''platinum''''' and '''''ilmenite'''''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_climbable" data-tt-parent="root">climbable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If true, walking against this block will make the player climb (used for ladders).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rainpermeable" data-tt-parent="root">rainpermeable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If rain can fall through this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_snowcoverage" data-tt-parent="root">snowcoverage</div></td><br />
<td>boolean</td><br />
<td>-</td><br />
<td>Whether snow may rest on top of this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_snowcoverage_info" data-tt-parent="p_snowcoverage" data-invisible="true"></div></td><br />
<td colspan="3"><br />
All none solid blocks can't be covered by snow unless it's defined different:<br />
*Leaves (also branchy): '''true''',<br />
*Water with particles, Lakeice: '''false'''<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionbox" data-tt-parent="root">collisionbox</div></td><br />
<td>object</td><br />
<td>box (0,0,0 -> 1,1,1)</td><br />
<td>Defines a box with which the player collides with.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionbox_info" data-tt-parent="p_collisionbox" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''half slab''' for example, has either a box going from 0,0,0 to 1,0.5,1 or going from 0,0.5,0 to 1,1,1, depending on whether it is a slab is down or up:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
Collision and selection boxes are most likely equal.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionboxes" data-tt-parent="root">collisionboxes</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Defines multiple boxes with which the player collides with.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_collisionboxes_info" data-tt-parent="p_collisionboxes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''crate''' for example requires multiple collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxesByType: {<br />
"*-opened": [ <br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.0625, z2: 1 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 90 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 180 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 270 },<br />
]<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionbox" data-tt-parent="root">selectionbox</div></td><br />
<td>object</td><br />
<td>box (0,0,0 -> 1,1,1)</td><br />
<td>Defines a box which the player's mouse pointer collides with for selection.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionbox_info" data-tt-parent="p_selectionbox" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''half slab''' for example, has either a box going from 0,0,0 to 1,0.5,1 or going from 0,0.5,0 to 1,1,1, depending on whether it is a slab is down or up:<br />
<syntaxhighlight lang="json"><br />
selectionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
Collision and selection boxes are most likely equal.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionboxes" data-tt-parent="root">selectionboxes</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Defines multiple boxes which the player's mouse pointer collides with for selection.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_selectionboxes_info" data-tt-parent="p_selectionboxes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''crate''' for example requires multiple selection boxes:<br />
<syntaxhighlight lang="json"><br />
selectionboxesByType: {<br />
"*-opened": [ <br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.0625, z2: 1 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 90 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 180 },<br />
{ x1: 0, y1: 0, z1: 0, x2: 1, y2: 1, z2: 0.0625, rotateY: 270 },<br />
]<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_replaceable" data-tt-parent="root">replaceable</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>A value usually between 0-9999 that indicates which blocks may be replaced with others.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_replaceable_info" data-tt-parent="p_replaceable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
<th style="background-color: rgba(0,0,0,0.2);">effect (blocks)</th><br />
</tr><br />
<tr><br />
<td>'''0'''</td><br />
<td>'''''ordinary blocks''''' (stone for example)</td><br />
</tr><br />
<tr><br />
<td>'''5000'''</td><br />
<td>Everything equal or above will be washed away by water (such as '''''Fruit''''').</td><br />
</tr><br />
<tr><br />
<td>'''6000'''</td><br />
<td>Everything equal or above wwill replaced when the player tries to place a block (such as '''''Tallgrass''''').</td><br />
</tr><br />
<tr><br />
<td>'''9000'''</td><br />
<td>'''''Lava'''''</td><br />
</tr><br />
<tr><br />
<td>'''9500'''</td><br />
<td>'''''Water'''''</td><br />
</tr><br />
<tr><br />
<td>'''9999'''</td><br />
<td>'''''Air'''''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fertility" data-tt-parent="root">fertility</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Which plants can grow on top of this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fertility_info" data-tt-parent="p_fertility" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
<th style="background-color: rgba(0,0,0,0.2);">effect</th><br />
</tr><br />
<tr><br />
<td>'''0'''</td><br />
<td>''nothing can grow.''</td><br />
</tr><br />
<tr><br />
<td>'''10'''</td><br />
<td>''some tallgrass and small trees can be grow on it.''</td><br />
</tr><br />
<tr><br />
<td>'''100'''</td><br />
<td>''all grass and trees can grow on it.''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_glowlevel" data-tt-parent="root">glowLevel</div></td><br />
<td>0 ... 255</td><br />
<td>0</td><br />
<td>Causes the block to visually glow if Bloom is enabled. Basic glow level for all the blocks model elements.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_glowlevel_info" data-tt-parent="p_glowlevel" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Glacierice''</td><br />
<td>'''8'''</td><br />
</tr><br />
<tr><br />
<td>''Paperlantern''</td><br />
<td>'''32'''</td><br />
</tr><br />
<tr><br />
<td>''Ember''</td><br />
<td>'''48'''</td><br />
</tr><br />
<tr><br />
<td>''Fire'', ''Firepit'', ''Oillamp'', ''Torch''</td><br />
<td>'''64'''</td><br />
</tr><br />
<tr><br />
<td>''Lava''</td><br />
<td>'''128'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lightabsorption" data-tt-parent="root">lightabsorption</div></td><br />
<td>0 ... 32</td><br />
<td>0</td><br />
<td>For light blocking blocks. Any value above 32 will completely block all light.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_walkspeedmultiplier" data-tt-parent="root">walkspeedmultiplier</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>Percentage walk-speed when standing on or inside this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_walkspeedmultiplier_info" data-tt-parent="p_walkspeedmultiplier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Spiderweb''</td><br />
<td>'''0.25'''</td><br />
</tr><br />
<tr><br />
<td>''Stonepath''</td><br />
<td>'''1.15'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_dragmultiplier" data-tt-parent="root">dragmultiplier</div></td><br />
<td>decimal number</td><br />
<td>1.0</td><br />
<td>Drag multiplier applied to entities standing on it (slipperiness factor).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_dragmultiplier_info" data-tt-parent="p_dragmultiplier" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">blocks</th><br />
<th style="background-color: rgba(0,0,0,0.2);">value</th><br />
</tr><br />
<tr><br />
<td>''Glacierice'', ''Lakeice''</td><br />
<td>'''0.02'''</td><br />
</tr><br />
</table><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drops" data-tt-parent="root">drops</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>The items that should drop from breaking this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drops_info" data-tt-parent="p_drops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
<br />
'''Drop itself'''<br />
<br />
If this property does not exist the block will drop itself.<br />
<br />
----<br />
<br />
'''No drop'''<br />
<br />
A '''firepit''' for example doesn't drop anything. You can do so if you specify an empty array:<br />
<syntaxhighlight lang="json"><br />
drops: [],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Special drop'''<br />
<br />
You can also specify a special item/ block. Therefore you need to define an '''ItemStack''', with the given properties:<br />
<br />
<table class="wikitable"><br />
<tr style="background-color: rgba(0,0,0,0.2);"><br />
<th style="background-color: rgba(0,0,0,0.2);">property</th><br />
<th style="background-color: rgba(0,0,0,0.2);">default</th><br />
<th style="background-color: rgba(0,0,0,0.2);">explanation</th><br />
</tr><br />
<tr><br />
<td>'''type'''</td><br />
<td>''block''</td><br />
<td>Can either be '''''block''''' or '''''item'''''.</td><br />
</tr><br />
<tr><br />
<td>'''code''' (required)</td><br />
<td>-</td><br />
<td>The complete code (can also include domain) of the item or block.</td><br />
</tr><br />
<tr><br />
<td>'''lastdrop'''</td><br />
<td>false</td><br />
<td>If true and the quantity dropped is >=1 any subsequent drop in the list will be ignored.</td><br />
</tr><br />
<tr><br />
<td>'''attributes'''</td><br />
<td>-</td><br />
<td>Tree Attributes that will be attached to the resulting itemstack.</td><br />
</tr><br />
<tr><br />
<td>'''tool'''</td><br />
<td>-</td><br />
<td>If specified then given tool is required to break this block.</td><br />
</tr><br />
<tr><br />
<td>'''quantity'''</td><br />
<td>- (one)</td><br />
<td>Determines the quantity of items which will be dropped.</td><br />
</tr><br />
</table><br />
<br />
For example, the drop of a '''charcoalpile''' looks like this:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "charcoal" }<br />
],<br />
</syntaxhighlight><br />
<br />
'''Tallgrass''' will only drop something if it's mined by a knife:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ type: "item", code: "drygrass", tool: "knife" },<br />
],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Chance drops'''<br />
<br />
Let's take a look at an example. This is the drop property of rock:<br />
<br />
<syntaxhighlight lang="json"> <br />
drops: [<br />
{<br />
type: "item", <br />
code: "stone-{rock}", <br />
quantity: { avg: 2.5, var: 0.5 } <br />
},<br />
]<br />
</syntaxhighlight><br />
<br />
This will drop 2-3 blocks.<br />
<br />
'''''avg''''': Stands for the default drop quantity. If var is 0 or not specified it will always drop the given average.<br />
<br />
'''''var''''': How much the drop rate can vary. Meaning the drop rate can be <code>avg - var</code> at minimum and <code>age + var</code> at maximum.<br />
<br />
For more information see [[NatFloat]] page.<br />
<br />
----<br />
<br />
'''Multiple Drops'''<br />
<br />
Of course you can also define multiple drops at once. '''Sapling''' can drop a sapling and a stick:<br />
<br />
<syntaxhighlight lang="json"><br />
drops: [<br />
{ <br />
type: "block", <br />
code: "sapling-{wood}",<br />
quantity: { avg: 0.02, var: 0 },<br />
},<br />
{ <br />
type: "item", <br />
code: "stick",<br />
quantity: { avg: 0.02, var: 0 },<br />
}<br />
],<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
'''Last Drop'''<br />
<br />
In order to add a special drop, which (if dropped) prevents all other drops, you can use the lastDrop property:<br />
<br />
<syntaxhighlight lang="json"><br />
dropsByType: {<br />
"ore-quartz-*": [<br />
{ type: "item", code: "clearquartz", quantity: { avg: 0.2, var: 0 }, lastDrop: true },<br />
{ type: "item", code: "ore-{ore}", quantity: { avg: 1.25, var: 0 } }<br />
],<br />
"*": [ <br />
{ type: "item", code: "ore-{ore}", quantity: { avg: 1.25, var: 0 } }<br />
],<br />
}<br />
</syntaxhighlight><br />
<br />
Quartz ore will drop with a 20% chance clearquartz, if not it will drop the regular ore. If lastDrop wouldn't be true it could drop both at the same time.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_particleproperties" data-tt-parent="root">particleproperties</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Particles that should spawn in regular intervals from this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_particleproperties_info" data-tt-parent="p_particleproperties" data-invisible="true"></div></td><br />
<td colspan="3"><br />
{{:json:block:particle}}<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="root">liquidlevel</div></td><br />
<td>0 ... 7</td><br />
<td>0</td><br />
<td>Value between 0...7 for Liquids to determine the height of the liquid.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cropprops" data-tt-parent="root">cropprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the block as a crop.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds" data-tt-parent="root">sounds</div></td><br />
<td>key: string, value: string</td><br />
<td>-</td><br />
<td>The sounds played for this block during step, break, build and walk.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_walk" data-tt-parent="p_sounds">walk</div></td><br />
<td colspan="3">An entity walks over it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_inside" data-tt-parent="p_sounds">inside</div></td><br />
<td colspan="3">The player is inside the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_break" data-tt-parent="p_sounds">break</div></td><br />
<td colspan="3">Breaking the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_place" data-tt-parent="p_sounds">place</div></td><br />
<td colspan="3">Placing the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_hit" data-tt-parent="p_sounds">hit</div></td><br />
<td colspan="3">While mining the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_ambient" data-tt-parent="p_sounds">ambient</div></td><br />
<td colspan="3">Played from time to time if the player is close to it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sounds_info" data-tt-parent="p_sounds" data-invisible="true"></div></td><br />
<td colspan="3"><br />
'''Anvil''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
"place": "block/anvil",<br />
"break": "block/anvil"<br />
}<br />
</syntaxhighlight><br />
<br />
'''Rails''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
place": "block/planks",<br />
"walk": "walk/wood"<br />
}<br />
</syntaxhighlight><br />
<br />
'''Water''':<br />
<syntaxhighlight lang="json"><br />
sounds: {<br />
place: "block/water",<br />
inside: "walk/water",<br />
ambient: "environment/creek"<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Common</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory" data-tt-parent="root">creativeinventory</div></td><br />
<td>key: string, value: string[]</td><br />
<td>-</td><br />
<td>In which creative inventory tabs the block should be visible in.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory_info" data-tt-parent="p_creativeinventory" data-invisible="true"></div></td><br />
<td colspan="3"><br />
There are several tabs to you can add your stuff. Note that general should always be included, since it should contain everything.<br />
<br />
*general<br />
*terrain<br />
*flora<br />
*construction<br />
*decorative<br />
*items<br />
<br />
'''Rock''' adds all of it's variantions to general, terrain and construction:<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*"], "terrain": ["*"], "construction": ["*"] },<br />
</syntaxhighlight><br />
<br />
'''<code>*</code>''' reprents the variants which will be added. You can specify multiple and separate them with a comma. It follows the same way as the '''byType''' property.<br />
<br />
A '''Torch''' on the other hand only adds the variation '''<code>up</code>''':<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*-up"], "decorative": ["*-up"] },<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_maxstacksize" data-tt-parent="root">maxstacksize</div></td><br />
<td>integer</td><br />
<td>64</td><br />
<td>Determines the maximum amount you can stack the block in one slot.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackpower" data-tt-parent="root">attackpower</div></td><br />
<td>decimal number</td><br />
<td>0.5</td><br />
<td>The damage the deals when hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackrange" data-tt-parent="root">attackrange</div></td><br />
<td>decimal number</td><br />
<td>1.5</td><br />
<td>The maximum distance you can hit an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity" data-tt-parent="root">materialdensity</div></td><br />
<td>integer</td><br />
<td>9999</td><br />
<td>Determines on whether an object floats on liquids or not.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity_info" data-tt-parent="p_materialdensity" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Water has a density of 1000, meaning everything below or equal will float on water. The same goes for lava which has a density of 5000.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable" data-tt-parent="root">liquidselectable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If the block can select a liquid while holding it in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable_info" data-tt-parent="p_liquidselectable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Used for buckets in order to fill it with water and to place waterlily on top of water.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningSpeed</div></td><br />
<td>key: string, value: decimal number</td><br />
<td>-</td><br />
<td>The mining speed for each material.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">miningTier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Determines which blocks it can break. If the required miningtier is above the defined one there will be no drop from it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes" data-tt-parent="root">attributes</div></td><br />
<td>key: string, value: object</td><br />
<td>-</td><br />
<td>Custom Attributes associated with this block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_info" data-tt-parent="p_attributes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Extra attributes added to a block. Those are final and cannot be modified. It's a good way to keep things organized and and modifiable. The '''oreblastingbomb''' for example has attributes, which define its radius and type. These can be used by behaviors and blockentities:<br />
<syntaxhighlight lang="json"><br />
attributes: {<br />
"blastRadius": 4,<br />
"blastType": 0,<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops" data-tt-parent="root">combustibleprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the blocks burnable states.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burntemperature" data-tt-parent="p_combustibleprops">burntemperature</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>The temperature at which it burns in degrees Celsius.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burnduration" data-tt-parent="p_combustibleprops">burnduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how long it burns in seconds.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_heatresistance" data-tt-parent="p_combustibleprops">heatresistance</div></td><br />
<td>integer</td><br />
<td>500</td><br />
<td>How many degrees celsius it can resists before it ignites (not implemented yet).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingpoint" data-tt-parent="p_combustibleprops">meltingpoint</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>How many degrees celsius it takes to smelt/transform this into another. Only used when put in a stove and SmeltedStack is set.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingduration" data-tt-parent="p_combustibleprops">meltingduration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how many seconds the temperature has to be above the melting point until the item is smelted.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smokelevel" data-tt-parent="p_combustibleprops">smokelevel</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>How much smoke this item produces when being used as fuel.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smeltedratio" data-tt-parent="p_combustibleprops">smeltedratio</div></td><br />
<td>integer</td><br />
<td>1</td><br />
<td>How many ores are required to produce one output stack.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="p_combustibleprops">smeltedstack</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>If set, the block/item is smeltable in a furnace and this is the resulting itemstack once the MeltingPoint has been reached for the supplied duration.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requirescontainer" data-tt-parent="p_combustibleprops">requirescontainer</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If set to true, the block/item requires a smelting/cooking/baking container such as the Crucible. If false, it can be directly baked/melted without smelting/cooking/baking container.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops_info" data-tt-parent="p_combustibleprops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
This property can be used to define a burning material. '''Plank''' for example can get on fire:<br />
<syntaxhighlight lang="json"><br />
combustibleProps: {<br />
burnTemperature: 800,<br />
burnDuration: 12,<br />
},<br />
</syntaxhighlight><br />
<br />
Furthermore it can be used to define smelting processes. An example would be an '''ingotmold''' which turns into an ingotmold-burned:<br />
<syntaxhighlight lang="json"><br />
combustiblePropsByType: {<br />
"ingotmold-raw": {<br />
meltingPoint: 600,<br />
meltingDuration: 30,<br />
smeltedRatio: 1,<br />
smeltedStack: { type: "block", code: "ingotmold-burned" },<br />
requiresContainer: false<br />
}<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops" data-tt-parent="root">nutritionprops</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the blocks nutrients.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_foodcategory" data-tt-parent="p_nutritionprops">foodcategory</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>Defines the type of food. It can be '''''fruit''''', '''''vegetable''''', '''''protein''''', '''''grain''''' and '''''dairy'''''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_saturation" data-tt-parent="p_nutritionprops">saturation</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much saturation it can restore.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_health" data-tt-parent="p_nutritionprops">health</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much health it can restore.</td><br />
</tr><br />
<tr><br />
<td colspan="4" class="propHeader"><b>Rendering</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_textures" data-tt-parent="root">textures</div></td><br />
<td>key: string, value: object</td><br />
<td></td><br />
<td>The texture definitions for the block as seen in the world, when dropped on the ground or held in the hand. Within a mod, to refer to a texture from the base game, prefix the path with "game:" (i.e. base: "game:path/to/texture") </td><br />
</tr><br />
<tr><br />
<td scope="row" valign="top"><div class="tt" data-tt-id="p_textures_base" data-tt-parent="p_textures">base</div><br><br><div class="tt" data-tt-id="p_textures_overlays" data-tt-parent="p_textures">overlays</div><br><br><div class="tt" data-tt-id="p_textures_base" data-tt-parent="p_textures">alternates</div></td><br />
<td colspan="3">{{:json:block:texture}}</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_texturesinventory" data-tt-parent="root">texturesinventory</div></td><br />
<td>key: string, value: object</td><br />
<td></td><br />
<td>The texture definitions for the block as seen in the player inventory. Overrides the textures.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shape" data-tt-parent="root">shape</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>For the json drawtype, the shape definition of the block as shown in the world, dropped on the ground or held in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_base" data-tt-parent="p_shape">base</div></td><br />
<td></td><br />
<td></td><br />
<td>The path to the shape json file, the base dir is ''assets/shapes/''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateX" data-tt-parent="p_shape">rotatex</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateY" data-tt-parent="p_shape">rotatey</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_rotateZ" data-tt-parent="p_shape">rotatez</div></td><br />
<td>float</td><br />
<td>0</td><br />
<td>Only 90 degree rotations are possible.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shapeinventory" data-tt-parent="root">shapeinventory</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>For the json drawtype, the shape definition of the block as shown in the players inventory.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_drawtype" data-tt-parent="root">drawtype</div></td><br />
<td>string</td><br />
<td>&quot;cube&quot;</td><br />
<td>Determines how the block is tesselated, select JSON for being able to use custom JSON Models. The other values are hardcoded methods of tesselating the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_1" data-tt-parent="p_drawtype">blockLayer_1</div></td><br />
<td></td><br />
<td>0</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_2" data-tt-parent="p_drawtype">blockLayer_2</div></td><br />
<td></td><br />
<td>1</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_3" data-tt-parent="p_drawtype">blockLayer_3</div></td><br />
<td></td><br />
<td>2</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_4" data-tt-parent="p_drawtype">blockLayer_4</div></td><br />
<td></td><br />
<td>3</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_5" data-tt-parent="p_drawtype">blockLayer_5</div></td><br />
<td></td><br />
<td>4</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_6" data-tt-parent="p_drawtype">blockLayer_6</div></td><br />
<td></td><br />
<td>5</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_blockLayer_7" data-tt-parent="p_drawtype">blockLayer_7</div></td><br />
<td></td><br />
<td>6</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_json" data-tt-parent="p_drawtype">json</div></td><br />
<td></td><br />
<td>7</td><br />
<td>Will draw a json model.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_empty" data-tt-parent="p_drawtype">empty</div></td><br />
<td></td><br />
<td>8</td><br />
<td>Nothing will be drawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cube" data-tt-parent="p_drawtype">cube</div></td><br />
<td></td><br />
<td>9</td><br />
<td>Draws an ordinary cube.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_cross" data-tt-parent="p_drawtype">cross</div></td><br />
<td></td><br />
<td>10</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_transparent" data-tt-parent="p_drawtype">transparent</div></td><br />
<td></td><br />
<td>11</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquid" data-tt-parent="p_drawtype">liquid</div></td><br />
<td></td><br />
<td>12</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_crossandsnowlayer" data-tt-parent="p_drawtype">crossandsnowlayer</div></td><br />
<td></td><br />
<td>13</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_renderpass" data-tt-parent="root">renderPass</div></td><br />
<td>string</td><br />
<td>&quot;opaque&quot;</td><br />
<td>Determines how the block will be drawn.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_opaque" data-tt-parent="p_renderpass">opaque</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Used for solid blocks with no half transparency.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_opaquenocull" data-tt-parent="p_renderpass">opaquenocull</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Used for non-solid single faced blocks, such as tall grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_transparent" data-tt-parent="p_renderpass">transparent</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Use for solid halftransparent blocks, such as glass</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquid" data-tt-parent="p_renderpass">liquid</div></td><br />
<td></td><br />
<td>3</td><br />
<td>Used for liquids, produces waves.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_topsoil" data-tt-parent="p_renderpass">topsoil</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Used for grass covered blocks. Allows for a smooth transition from grass to soil, while still allowing climate tinting of grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_ambientocclusion" data-tt-parent="root">AmbientOcclusion</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If ambient occlusion will be applied to the block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tintindex" data-tt-parent="root">tintindex</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>'''''0''''' for no tint, '''''1''''' for plant climate tint, '''''2''''' for water climate tint.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_renderflags" data-tt-parent="root">renderflags</div></td><br />
<td>0 ... 255</td><br />
<td>0</td><br />
<td>8 bits that are sent to the graphics card for each vertex of the blocks shape. The lower 3 bits are currently used for altering the vertexes z-depth to fix a bunch of z-fighting issues.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode" data-tt-parent="root">facecullmode</div></td><br />
<td>string</td><br />
<td>&quot;default&quot;</td><br />
<td>Determines which sides of the blocks should be rendered.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">default</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Culls faces if they are opaque faces adjacent to opaque faces.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">nevercull</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Never culls any faces.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">merge</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Culls all faces that are adjacent to opaque faces and faces adjacent to blocks of the same id (Example usage: Ice blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">collapse</div></td><br />
<td></td><br />
<td>3</td><br />
<td>Culls all faces that are adjacent to opaque faces and the bottom, east or south faces adjacent to blocks of the same id. This causes to still leave one single face in between instead of 2, eliminating any z-fighting.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">mergematerial</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Same as Merge but checks for equal material (Example usage: Plain glass and all colored glass blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">collapsematerial</div></td><br />
<td></td><br />
<td>5</td><br />
<td>Same as Collapse but checks for equal material (Example usage: All leaves blocks).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_facecullmode_default" data-tt-parent="p_facecullmode">liquid</div></td><br />
<td></td><br />
<td>6</td><br />
<td>Same as CollapseMaterial but also culls faces towards opaque blocks.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sideopaque" data-tt-parent="root">sideopaque</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>Determines if given block face is fully opaque. If yes, the opposite face of the adjacent block will not be drawn for efficiency reasons.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sideopaque_all" data-tt-parent="p_sideopaque">all</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_horizontals" data-tt-parent="p_sideopaque">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_verticals" data-tt-parent="p_sideopaque">verticals</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_east" data-tt-parent="p_sideopaque">east</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_west" data-tt-parent="p_sideopaque">west</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_up" data-tt-parent="p_sideopaque">up</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_down" data-tt-parent="p_sideopaque">down</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_north" data-tt-parent="p_sideopaque">north</div><br><br />
<div class="tt" data-tt-id="p_sideopaque_south" data-tt-parent="p_sideopaque">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sideao" data-tt-parent="root">sideao</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>If AmbientOcclusion will be applied for each side.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sideao_all" data-tt-parent="p_sideao">all</div><br><br />
<div class="tt" data-tt-id="p_sideao_horizontals" data-tt-parent="p_sideao">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sideao_verticals" data-tt-parent="p_sideao">verticals</div><br><br />
<div class="tt" data-tt-id="p_sideao_east" data-tt-parent="p_sideao">east</div><br><br />
<div class="tt" data-tt-id="p_sideao_west" data-tt-parent="p_sideao">west</div><br><br />
<div class="tt" data-tt-id="p_sideao_up" data-tt-parent="p_sideao">up</div><br><br />
<div class="tt" data-tt-id="p_sideao_down" data-tt-parent="p_sideao">down</div><br><br />
<div class="tt" data-tt-id="p_sideao_north" data-tt-parent="p_sideao">north</div><br><br />
<div class="tt" data-tt-id="p_sideao_south" data-tt-parent="p_sideao">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_sidesolid" data-tt-parent="root">sidesolid</div></td><br />
<td>key: string, value: boolean</td><br />
<td>-</td><br />
<td>Determins if given block side is solid. If true, other blocks like torches can be attached to it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><br />
<div class="tt" data-tt-id="p_sidesolid_all" data-tt-parent="p_sidesolid">all</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_horizontals" data-tt-parent="p_sidesolid">horizontals</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_verticals" data-tt-parent="p_sidesolid">verticals</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_east" data-tt-parent="p_sidesolid">east</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_west" data-tt-parent="p_sidesolid">west</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_up" data-tt-parent="p_sidesolid">up</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_down" data-tt-parent="p_sidesolid">down</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_north" data-tt-parent="p_sidesolid">north</div><br><br />
<div class="tt" data-tt-id="p_sidesolid_south" data-tt-parent="p_sidesolid">south</div><br />
</td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomdrawoffset" data-tt-parent="root">randomdrawoffset</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If true then the block will be randomly offseted by 1/3 of a block when placed.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lighthsv" data-tt-parent="root">LightHsv</div></td><br />
<td>byte array with 3 elements. See http://tyron.at/vs/vslightwheel.html for valid values</td><br />
<td>-</td><br />
<td>For light emitting blocks: hue, saturation and brightness value.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_lightabsorption" data-tt-parent="root">lightabsorption</div></td><br />
<td>0 ... 255</td><br />
<td>99</td><br />
<td>For light blocking blocks. Any value above 32 will completely block all light.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_guitransform" data-tt-parent="root">guitransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in guis.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fphandtransform" data-tt-parent="root">fphandtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in the first person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tphandtransform" data-tt-parent="root">tphandtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the block when rendered in the third person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_groundtransform" data-tt-parent="root">groundtransform</div></td><br />
<td>object</td><br />
<td>block default</td><br />
<td>Used for scaling, rotation or offseting the rendered as a dropped item on the ground.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes" data-tt-parent="root">randomizeaxes</div></td><br />
<td>string</td><br />
<td>&quot;xyz&quot;</td><br />
<td>Random texture selection - whether or not to use the Y axis during randomization (for multiblock plants).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes_xyz" data-tt-parent="p_randomizeaxes">xyz</div></td><br />
<td></td><br />
<td>0</td><br />
<td></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_randomizeaxes_xz" data-tt-parent="p_randomizeaxes">xz</div></td><br />
<td></td><br />
<td>1</td><br />
<td></td><br />
</tr><br />
</table><br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Item_Json_Properties&diff=4889Modding:Item Json Properties2019-05-27T10:37:29Z<p>CreativeMD: </p>
<hr />
<div>__NOTOC__<br />
== Overview ==<br />
A complete list of all available properties<br />
<br />
<table id="treeviewtable" class="table table-bordered tt-table" style='table-layout: fixed'><br />
<tr style='background-color: rgba(0,0,0,0.2);'><br />
<th width='300' align='left'>Property</th><br />
<th width='200' align='left'>Type</th><br />
<th width='120' align='left'>Default</th><br />
<th align='left'>Usage</th><br />
</tr><br />
<tr><br />
<td><div class="tt" data-tt-id="root">json</div></td><br />
<td></td><br />
<td></td><br />
<td></td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Core (no byType available)</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code" data-tt-parent="root">Code</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>A unique identifier for the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_code_info" data-tt-parent="p_code" data-invisible="true"></div></td><br />
<td colspan="3"><br />
A '''domain prefix''' will be added dynamically depending on the location of the file. Every mod and VintageStory itself have a unique prefix.<br />
<br />
For example the code '''<code>stone</code>''' turns into '''<code>game:stone</code>'''. <br />
<br />
The code identifier has to be unique inside its domain. In theory there could be equal identifiers with different domain prefixes.<br />
Find out more about [[Basic Modding#Domains|Domains]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_enabled" data-tt-parent="root">Enabled</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If the item will be loaded or not. Can be used to temporarily remove the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups" data-tt-parent="root">VariantGroups</div></td><br />
<td>array of object</td><br />
<td>-</td><br />
<td>Allows you define multiple variants of the same item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_variantgroups_info" data-tt-parent="p_variantgroups" data-invisible="true"></div></td><br />
<td colspan="3"><br />
The variantgroups property allows you to define multiple variants of this item. All of them will have their unique pattern, which will be added to the item code.<br />
<br />
An easy example would be a bowl, which can either be raw or burned:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"type", states: ["raw", "burned"] },<br />
],<br />
</syntaxhighlight><br />
<br />
Meaning there will be two variants <code>bowl-raw</code> and <code>bowl-burned</code>.<br />
<br />
----<br />
<br />
It's also possible to define multiple groups. <br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code:"state", states: ["closed", "opened"] },<br />
{ code:"contents", states: ["empty", "cabbage"] },<br />
],<br />
</syntaxhighlight><br />
<br />
As a result you will have 2x2 groups, which will be added one after each other: <code>barrel-closed-empty</code>, <code>barrel-closed-cabbage</code>, <code>barrel-opened-empty</code> and <code>barrel-opened-cabbage</code>.<br />
<br />
----<br />
<br />
Additionally it is possible to refer to external lists (used for blocks) that are found in the worldproperties folder, such as <code>block/rock</code>, which contains all states of all rock types. This used for <code>gravel</code>, <code>sand</code> and <code>rock</code>. It's a good way to keep everything organized:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ loadFromProperties: "block/rock" },<br />
],<br />
</syntaxhighlight><br />
<br />
Here is a full list of all groups and their variants (you can also find them in the <code>assets/worldproperties</code> folder):<br />
{{:json:block:worldvariantgroups}}<br />
<br />
----<br />
<br />
Furthermore there are two ways of combining groups together. So far we covered the default combination mode, which is <code>multiplicative</code> (the total count of variants is the product of all states).<br />
<br />
Let's take a look at a different example (flowerpot), which uses the <code>additive</code> combination mode:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "type", states: ["raw"] },<br />
{ code: "empty", states: ["empty"], combine: "additive" },<br />
{ code: "flower", loadFromProperties: "block/flower", combine: "additive" },<br />
{ code: "mushroom", loadFromProperties: "block/mushroom", combine: "additive" },<br />
{ code: "sapling", loadFromProperties: "block/wood", combine: "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
The variants are <code>flowerpot-raw</code>, <code>flowerpot-empty</code>, <code>flowerpot-{all flowers}</code>, <code>flowerpot-{all mushrooms}</code> and <code>flowerpot-{all saplings}</code>.<br />
<br />
<code>Additive</code> mode could also be called separate, since it defines a variant separate from all the other groups:<br />
<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "something", states: ["same", "different"] },<br />
{ code: "type", states: ["raw", "baked"] },<br />
{ code: "empty", states: ["red", "green"], "combine": "additive" },<br />
],<br />
</syntaxhighlight><br />
<br />
In this case, the result would be <code>same-raw</code>, <code>same-baked</code>, <code>different-raw</code>, <code>different-baked</code>, <code>red</code> and <code>green</code><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType" data-tt-parent="root">(any) byType</div></td><br />
<td>key: string; value: object</td><br />
<td>-</td><br />
<td>You can create properties for certain variants of the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_byType_info" data-tt-parent="p_byType" data-invisible="true"></div></td><br />
<td colspan="3"><br />
In order to define properties for specific variants you can add '''byType''' to the property name. This allows you to define it depending on the type and always follows the same syntax:<br />
<syntaxhighlight lang="json"><br />
(property)ByType: {<br />
"selector": property,<br />
"selector2": property2,<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
If the selector matches the name of the variant the given property will be used. Keep in mind that only the first matching one will be used (everything below will be ignored).<br />
<br />
A slab for example has two variants ('''up''', '''down'''), which have different collision boxes:<br />
<syntaxhighlight lang="json"><br />
collisionboxByType: {<br />
"*-down": { x1: 0, y1: 0, z1: 0, x2: 1, y2: 0.5, z2: 1 },<br />
"*-up": { x1: 0, y1: 0.5, z1: 0, x2: 1, y2: 1, z2: 1 }<br />
},<br />
</syntaxhighlight><br />
<br />
The char '''<code>*</code>''' stands for anything. In this case it ignores the code of the item.<br />
<br />
Furthermore this opens up even more possbilities for more advanced selectors like this one for doors:<br />
<code>*-north-*-opened-left</code>. This will ignore the second variantgroup. Additionally ByType can also be used for child properties:<br />
<syntaxhighlight lang="json"><br />
collisionboxnbox: { <br />
x1: 0, y1: 0, z1: 0.875, x2: 1, y2: 1, z2: 1,<br />
rotateYByType: {<br />
"*-north-*-opened-left": 90,<br />
"*-north-*-closed-left": 0,<br />
"*-west-*-opened-left": 180,<br />
"*-west-*-closed-left": 90,<br />
<br />
"*-east-*-opened-left": 0,<br />
"*-east-*-closed-left": 270,<br />
"*-south-*-opened-left": 270,<br />
"*-south-*-closed-left": 180,<br />
<br />
"*-north-*-opened-right": 270,<br />
"*-north-*-closed-right": 0,<br />
"*-west-*-opened-right": 0,<br />
"*-west-*-closed-right": 90,<br />
<br />
"*-east-*-opened-right": 180,<br />
"*-east-*-closed-right": 270,<br />
"*-south-*-opened-right": 90,<br />
"*-south-*-closed-right": 180<br />
}<br />
},<br />
</syntaxhighlight><br />
<br />
Since Vintagestory v1.8 it is also possible to use the variantgroup as a placeholder:<br />
<syntaxhighlight lang="json"><br />
variantgroups: [<br />
{ code: "metal", states: ["copper", "tinbronze", "bismuthbronze", "blackbronze", "gold", "silver", "iron" ] },<br />
],<br />
textures: {<br />
"metal": { base: "block/metal/ingot/{metal}" },<br />
"wood": { base: "item/tool/material/wood" } <br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Specific</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class" data-tt-parent="root">Class</div></td><br />
<td>string</td><br />
<td>&quot;item&quot;</td><br />
<td>The item class can add special functionalities for the item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_class_info" data-tt-parent="p_class" data-invisible="true"></div></td><br />
<td colspan="3"><br />
It can be used to open guis or adding other extra functionality to the item. A complete tutorial of how to add your own class to the game can be found [[Advanced Items|here]].<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_durability" data-tt-parent="root">Durability</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>How many uses does this item has when being used. Item disappears at durability 0.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby" data-tt-parent="root">DamagedBy</div></td><br />
<td>array of string</td><br />
<td>-</td><br />
<td>From which damage sources does the item takes durability damage.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_blockbreaking" data-tt-parent="p_damagedby">BlockBreaking</div></td><br />
<td></td><br />
<td>0</td><br />
<td>Mining a block.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_attacking" data-tt-parent="p_damagedby">Attacking</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_damagedby_fire" data-tt-parent="p_damagedby">Fire</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Currently not used.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool" data-tt-parent="root">Tool</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>If set, this item will be classified as given tool.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_knife" data-tt-parent="p_tool">Knife</div></td><br />
<td></td><br />
<td>0</td><br />
<td>USed to break grass.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_pickaxe" data-tt-parent="p_tool">Pickaxe</div></td><br />
<td></td><br />
<td>1</td><br />
<td>Can mine rock and other stone materials</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_axe" data-tt-parent="p_tool">Axe</div></td><br />
<td></td><br />
<td>2</td><br />
<td>Useful for chopping trees.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_sword" data-tt-parent="p_tool">Sword</div></td><br />
<td></td><br />
<td>3</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_shovel" data-tt-parent="p_tool">Shovel</div></td><br />
<td></td><br />
<td>4</td><br />
<td>Mines dirt, sand and gravel really fast.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_hammer" data-tt-parent="p_tool">Hammer</div></td><br />
<td></td><br />
<td>5</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_mallet" data-tt-parent="p_tool">Mallet</div></td><br />
<td></td><br />
<td>6</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_spear" data-tt-parent="p_tool">Spear</div></td><br />
<td></td><br />
<td>7</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_bow" data-tt-parent="p_tool">Bow</div></td><br />
<td></td><br />
<td>8</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_sickle" data-tt-parent="p_tool">Sickle</div></td><br />
<td></td><br />
<td>9</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_hoe" data-tt-parent="p_tool">Hoe</div></td><br />
<td></td><br />
<td>10</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tool_saw" data-tt-parent="p_tool">Saw</div></td><br />
<td></td><br />
<td>11</td><br />
<td>No special abilities yet.</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Common</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory" data-tt-parent="root">CreativeInventory</div></td><br />
<td>key: string, value: string[]</td><br />
<td>-</td><br />
<td>In which creative inventory tabs the item should be visible in.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_creativeinventory_info" data-tt-parent="p_creativeinventory" data-invisible="true"></div></td><br />
<td colspan="3"><br />
There are several tabs to you can add your stuff. Note that general should always be included, since it should contain everything.<br />
<br />
*general<br />
*terrain<br />
*flora<br />
*construction<br />
*decorative<br />
*items<br />
<br />
'''Rock''' adds all of it's variantions to general, terrain and construction:<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*"], "terrain": ["*"], "construction": ["*"] },<br />
</syntaxhighlight><br />
<br />
'''<code>*</code>''' reprents the variants which will be added. You can specify multiple and separate them with a comma. It follows the same way as the '''byType''' property.<br />
<br />
A '''Torch''' on the other hand only adds the variation '''<code>up</code>''':<br />
<syntaxhighlight lang="json"><br />
creativeinventory: { "general": ["*-up"], "decorative": ["*-up"] },<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_maxstacksize" data-tt-parent="root">MaxStackSize</div></td><br />
<td>integer</td><br />
<td>64</td><br />
<td>Determines the maximum amount you can stack the item in one slot.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackpower" data-tt-parent="root">AttackPower</div></td><br />
<td>decimal number</td><br />
<td>0.5</td><br />
<td>The damage the deals when hitting an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attackrange" data-tt-parent="root">AttackRange</div></td><br />
<td>decimal number</td><br />
<td>1.5</td><br />
<td>The maximum distance you can hit an entity.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity" data-tt-parent="root">MaterialDensity</div></td><br />
<td>integer</td><br />
<td>9999</td><br />
<td>Determines on whether an object floats on liquids or not.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_materialdensity_info" data-tt-parent="p_materialdensity" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Water has a density of 1000, meaning everything below or equal will float on water. The same goes for lava which has a density of 5000.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable" data-tt-parent="root">LiquidSelectable</div></td><br />
<td>boolean</td><br />
<td>false</td><br />
<td>If the item can select a liquid while holding it in hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidselectable_info" data-tt-parent="p_liquidselectable" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Used for buckets in order to fill it with water and to place waterlily on top of water.<br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">MiningSpeed</div></td><br />
<td>key: string, value: decimal number</td><br />
<td>-</td><br />
<td>The mining speed for each material.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_miningspeed" data-tt-parent="root">MiningTier</div></td><br />
<td>integer</td><br />
<td>0</td><br />
<td>Determines which blocks it can break. If the required miningtier is above the defined one there will be no drop from it.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes" data-tt-parent="root">Attributes</div></td><br />
<td>key: string, value: object</td><br />
<td>-</td><br />
<td>Custom Attributes associated with this item.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_attributes_info" data-tt-parent="p_attributes" data-invisible="true"></div></td><br />
<td colspan="3"><br />
Extra attributes added to a item or block. Those are final and cannot be modified. It's a good way to keep things organized and and modifiable. The '''oreblastingbomb''' for example has attributes, which define its radius and type. These can be used by behaviors and blockentities:<br />
<syntaxhighlight lang="json"><br />
attributes: {<br />
"blastRadius": 4,<br />
"blastType": 0,<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops" data-tt-parent="root">CombustibleProps</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the items burnable states.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burntemperature" data-tt-parent="p_combustibleprops">BurnTemperature</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>The temperature at which it burns in degrees celsius.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_burnduration" data-tt-parent="p_combustibleprops">BurnDuration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how long it burns in seconds.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_heatresistance" data-tt-parent="p_combustibleprops">HeatResistance</div></td><br />
<td>integer</td><br />
<td>500</td><br />
<td>How many degrees celsius it can resists before it ignites (not implemented yet).</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingpoint" data-tt-parent="p_combustibleprops">MeltingPoint</div></td><br />
<td>integer</td><br />
<td>-</td><br />
<td>How many degrees celsius it takes to smelt/transform this into another. Only used when put in a stove and Melted is set.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_meltingduration" data-tt-parent="p_combustibleprops">MeltingDuration</div></td><br />
<td>decimal number</td><br />
<td>-</td><br />
<td>For how many seconds the temperature has to be above the melting point until the item is smelted.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smokelevel" data-tt-parent="p_combustibleprops">SmokeLevel</div></td><br />
<td>decimal number</td><br />
<td>1</td><br />
<td>How much smoke this item produces when being used as fuel.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_smeltedratio" data-tt-parent="p_combustibleprops">SmeltedRatio</div></td><br />
<td>integer</td><br />
<td>1</td><br />
<td>How many ores are required to produce one output stack.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_liquidlevel" data-tt-parent="p_combustibleprops">SmeltedStack</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>If set, the block/item is smeltable in a furnace and this is the resulting itemstack once the MeltingPoint has been reached for the supplied duration.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_requirescontainer" data-tt-parent="p_combustibleprops">RequiresContainer</div></td><br />
<td>boolean</td><br />
<td>true</td><br />
<td>If set to true, the block/item requires a smelting/cooking/baking container such as the Crucible. If false, it can be directly baked/melted without smelting/cooking/baking container.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_combustibleprops_info" data-tt-parent="p_combustibleprops" data-invisible="true"></div></td><br />
<td colspan="3"><br />
This property can be used to define a burning material. '''Plank''' for example can get on fire:<br />
<syntaxhighlight lang="json"><br />
combustibleProps: {<br />
burnTemperature: 800,<br />
burnDuration: 12,<br />
},<br />
</syntaxhighlight><br />
<br />
Furthermore it can be used to define smelting processes. An example would be an '''ingotmold''' which turns into an ingotmold-burned:<br />
<syntaxhighlight lang="json"><br />
combustiblePropsByType: {<br />
"ingotmold-raw": {<br />
meltingPoint: 600,<br />
meltingDuration: 30,<br />
smeltedRatio: 1,<br />
smeltedStack: { type: "block", code: "ingotmold-burned" },<br />
requiresContainer: false<br />
}<br />
},<br />
</syntaxhighlight><br />
</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops" data-tt-parent="root">NutritionProps</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>Information about the items nutrients.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_foodcategory" data-tt-parent="p_nutritionprops">FoodCategory</div></td><br />
<td>string</td><br />
<td>-</td><br />
<td>Defines the type of food. It can be '''''fruit''''', '''''vegetable''''', '''''protein''''', '''''grain''''' and '''''dairy'''''.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_saturation" data-tt-parent="p_nutritionprops">Saturation</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much saturation it can restore.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_nutritionprops_health" data-tt-parent="p_nutritionprops">Health</div></td><br />
<td>decimal number</td><br />
<td>0</td><br />
<td>How much health it can restore.</td><br />
</tr><br />
<tr><br />
<td colspan="4" style='font-size: 14pt; border-bottom: 2pt solid black; padding-left: 100px;'><b>Rendering</b></td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_textures" data-tt-parent="root">Textures</div></td><br />
<td>string</td><br />
<td>required</td><br />
<td>The texture definitions for the item held in hand or dropped on the ground.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shape" data-tt-parent="root">Shape</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>The items shape. Empty for automatic shape based on the texture.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_shapeinventory" data-tt-parent="root">ShapeInventory</div></td><br />
<td>object</td><br />
<td>-</td><br />
<td>The items shape in inventory.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_guitransform" data-tt-parent="root">GuiTransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in guis.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_fphandtransform" data-tt-parent="root">FpHandTransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in the first person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_tphandtransform" data-tt-parent="root">TpHandTransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the item when rendered in the third person mode hand.</td><br />
</tr><br />
<tr><br />
<td scope="row"><div class="tt" data-tt-id="p_groundtransform" data-tt-parent="root">GroundTransform</div></td><br />
<td>object</td><br />
<td>item default</td><br />
<td>Used for scaling, rotation or offseting the rendered as a dropped item on the ground.</td><br />
</tr><br />
</table><br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=WorldGen&diff=4859WorldGen2019-05-21T08:56:13Z<p>CreativeMD: </p>
<hr />
<div><br />
== Intro ==<br />
<br />
We will be walking through how plug in and add your own features to the world generation code of Vintage Story by looking at a demo mod called VSTreasureChest. The code for this project can be found here [https://github.com/anegostudios/VSTreasureChest] but we are going to walk through coding it from scratch. Please note that it is assumed that you are familiar with basic C# concepts. This document is strictly intended to familiarize you with the basic world gen api.<br />
<br />
== VSTreasureChest ==<br />
This mod places treasure chests around the world for the user to find. Each treasure chest has a random number of ingots in them. The mod only places treasure chests beside trees. It also adds a server command that can be run in the chat window called /treasure that places a treasure chest in front of the player. This can be useful for testing in case you want to change what items are in the chest and you don't want to bother looking for the chest for verification.<br />
<br />
<br />
== Getting started ==<br />
Please follow the instructions here[http://wiki.vintagestory.at/index.php?title=Setting_up_a_dev_environment] for setting up your development environment. We named our project VSTreasureChest but you can choose any name you like. We will do one different thing. When you get to the debug command line arguments instead of passing /flatworld we are going to pass /stdworld:test. The reason we are doing this is because we are going to be placing our chest beside a tree. The /flatworld generates a flat world with no trees so that won't help us much in this scenario. However, depending on the specific terrain gen features you are doing you may want to use /flatworld in the future.<br />
<br />
<br />
== The mod class ==<br />
The main class and the starting point of our mod will be VSTreasureChestMod.<br />
<br />
<syntaxhighlight lang="c#"><br />
using System;<br />
using System.Collections.Generic;<br />
using Vintagestory.API;<br />
using Vintagestory.API.Datastructures;<br />
using Vintagestory.API.Interfaces;<br />
<br />
namespace Vintagestory.Mods.TreasureChest<br />
{<br />
public class VSTreasureChestMod : ModSystem<br />
{<br />
private ICoreServerAPI api;<br />
<br />
public override void StartServerSide(ICoreServerAPI api)<br />
{<br />
this.api = api;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
The first thing to note is the '''using''' directives at the top. Those that start with Vintagestory will allow us to access classes in the Vintagestory api. Next the '''StartServerSide''' is a method we are overriding from '''ModSystem''' that is called once when the server is start up. Here we start by just storing a reference to the '''ICoreServerAPI''' for convenient access later. We will also be registering call backs for other events here.<br />
<br />
== The /treasure command ==<br />
Next we are going to add the /treasure command. To do this we must register a delegate so that we can be notified when the user types our command. We do this with the ICoreServerAPI.RegisterCommand method.<br />
<br />
In StartServerSide add the following line:<br />
<syntaxhighlight lang="c#"><br />
this.api.RegisterCommand("treasure", "Place a treasure chest with random items", "", PlaceTreasureChestInFrontOfPlayer, Privilege.controlserver);<br />
</syntaxhighlight><br />
This is registering a '''treasure''' command with the server with a brief description that is used to describe the command for when the user types '''/help'''. The other important argument is the '''PlaceTreasureChestInFrontOfPlayer''' argument which is a reference to a method we haven't written yet. So lets add the following method below '''StartServerSide'''.<br />
<syntaxhighlight lang="c#"><br />
private void PlaceTreasureChestInFrontOfPlayer(IServerPlayer player, int groupId, CmdArgs args)<br />
{<br />
}<br />
</syntaxhighlight><br />
This method will now be called when the user types /treasure command in the chat window. Wasn't that easy!!! Now we need to write the code to place our chest in that method.<br />
<br />
<br />
== Placing our chest ==<br />
The first thing we need to do is figure out how to tell the API that we want a chest and not grass or stone or some other block. Every Block has a numerical ID that gets assigned when the server starts but this ID may change. Luckily there is a property of the Block class that identifies it and does not change. This is the Code property. Block codes can be found in '''Vintagestory\assets\blocktypes''' in json files. The one for chest is '''Vintagestory\assets\blocktypes\wood\generic\chest.json'''. If you open that file you will see at the very top the code property is set to "chest". We also need to append the type of the shape that basically tells the system which way the chest is facing. So for simplicity we are going to pick south. So the resulting block code we will be using is "chest-south". Ok lets see some code.<br />
<syntaxhighlight lang="c#"><br />
private void PlaceTreasureChestInFrontOfPlayer(IServerPlayer player, int groupId, CmdArgs args)<br />
{<br />
ushort blockID = api.WorldManager.GetBlockId("chest-south");<br />
Block chest = api.WorldManager.GetBlockType(blockID);<br />
chest.TryPlaceBlockForWorldGen(api.World.BlockAccessor, player.Entity.Pos.HorizontalAheadCopy(2).AsBlockPos, BlockFacing.UP);<br />
}<br />
</syntaxhighlight><br />
The first line of code asks the '''IWorldManagerAPI''' to get the numeric block id for the block code "chest-south". Next we get the '''Block''' class that represents that chest. And finally we call a method called '''TryPlaceBlockForWorldGen''' and pass in an IBlockAccessor. There are many implementations of '''IBlockAccessor''' and we will cover that in a little more detail later. For now we are using this one. The second argument just calculates the world coordinates for 2 blocks in front of the player.<br />
<br />
Now if you run the mod from Visual Studio by pressing "Start" at the top you should be able to execute the '''/treasure''' command in the game. Once you do that you will have a fancy new chest appear in front of you with no items. Well I guess it's time for us to add some items.<br />
<br />
<br />
== Adding items to our chest ==<br />
We want to add some items to the chest since after all it is a "treasure" chest. For now we are going to add various ingots to the chest. However there are lots of items in Vintagestory and I encourage you to play with this and feel free to add other items. We also want to add items at random. Not only the type of items should be random but also the ingots we add should be random. There are all kinds of ways to do this but lets write a data structure that represents a grab bag full of items and lets pull items out of that bag and place them in the chest like Santa Claus! We will create a ShuffleBag class so in Visual Studio right click on your project and go to Add->Class. Call it ShuffleBag.cs and press Add. Here's the code to place in the ShuffleBag class.<br />
<syntaxhighlight lang="c#"><br />
using System;<br />
using System.Collections.Generic;<br />
<br />
namespace Vintagestory.Mods.TreasureChest<br />
{<br />
/// <summary><br />
/// Data structure for picking random items<br />
/// </summary><br />
public class ShuffleBag<T><br />
{<br />
private Random random = new Random();<br />
private List<T> data;<br />
<br />
private T currentItem;<br />
private int currentPosition = -1;<br />
<br />
private int Capacity { get { return data.Capacity; } }<br />
public int Size { get { return data.Count; } }<br />
<br />
public ShuffleBag(int initCapacity)<br />
{<br />
this.data = new List<T>(initCapacity);<br />
this.random = new Random();<br />
}<br />
<br />
public ShuffleBag(int initCapacity, Random random)<br />
{<br />
this.random = random;<br />
this.data = new List<T>(initCapacity);<br />
}<br />
<br />
/// <summary><br />
/// Adds the specified number of the given item to the bag<br />
/// </summary><br />
public void Add(T item, int amount)<br />
{<br />
for (int i = 0; i < amount; i++)<br />
data.Add(item);<br />
<br />
currentPosition = Size - 1;<br />
}<br />
<br />
/// <summary><br />
/// Returns the next random item from the bag<br />
/// </summary><br />
public T Next()<br />
{<br />
if (currentPosition < 1)<br />
{<br />
currentPosition = Size - 1;<br />
currentItem = data[0];<br />
<br />
return currentItem;<br />
}<br />
<br />
var pos = random.Next(currentPosition);<br />
<br />
currentItem = data[pos];<br />
data[pos] = data[currentPosition];<br />
data[currentPosition] = currentItem;<br />
currentPosition--;<br />
<br />
return currentItem;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
This is all basic C# stuff but the idea is that we are going to call Add on our ShuffleBag several times to load it up, then we are going to call Next to pull items out of it. This will let us kind of control the probability or rarity of items placed in chests. Items that are more rare will have fewer items in the bag.<br />
<br />
Lets add a couple of class variables to control the minimum and maximum number of items that will go in our chest.<br />
<syntaxhighlight lang="c#"><br />
private const int MIN_ITEMS = 3;<br />
private const int MAX_ITEMS = 10;<br />
</syntaxhighlight><br />
Since we will want to create a new ShuffleBag with each chest we place lets go ahead and create a MakeShuffleBag method.<br />
<syntaxhighlight lang="c#"><br />
private ShuffleBag<string> MakeShuffleBag()<br />
{<br />
ShuffleBag<string> shuffleBag = new ShuffleBag<string>(100, api.World.Rand);<br />
shuffleBag.Add("ingot-iron", 10);<br />
shuffleBag.Add("ingot-bismuth", 5);<br />
shuffleBag.Add("ingot-silver", 5);<br />
shuffleBag.Add("ingot-zinc", 5);<br />
shuffleBag.Add("ingot-titanium", 5);<br />
shuffleBag.Add("ingot-platinum", 5);<br />
shuffleBag.Add("ingot-chromium", 5);<br />
shuffleBag.Add("ingot-tin", 5);<br />
shuffleBag.Add("ingot-lead", 5);<br />
shuffleBag.Add("ingot-gold", 5);<br />
return shuffleBag;<br />
}<br />
</syntaxhighlight><br />
This loads up our ShuffleBag with various ingots. The only more common item is iron. Feel free to change the item counts as you see fit. One thing to note here is the API does give us an instance of Random that we can use so we pass it in to our ShuffleBag.<br />
<br />
We are almost ready to place these items in the chest but we need to create an ItemStack for each slot we will be taking up in the chest. The chest is an instance of IBlockEntityContainer which has an Inventory property. An Inventory is made up of several IItemSlot instances. We need a utility method to create a list of ItemStacks to place in those slots.<br />
<syntaxhighlight lang="c#"><br />
private IEnumerable<ItemStack> MakeItemStacks()<br />
{<br />
ShuffleBag<string> shuffleBag = MakeShuffleBag();<br />
Dictionary<string, ItemStack> itemStacks = new Dictionary<string, ItemStack>();<br />
int grabCount = api.World.Rand.Next(MIN_ITEMS, MAX_ITEMS);<br />
for (int i = 0; i < grabCount; i++)<br />
{<br />
string nextItem = shuffleBag.Next();<br />
Item item = api.World.GetItem(nextItem);<br />
if (itemStacks.ContainsKey(nextItem))<br />
{<br />
itemStacks[nextItem].StackSize++;<br />
}<br />
else<br />
{<br />
itemStacks.Add(nextItem, new ItemStack(item));<br />
}<br />
}<br />
return itemStacks.Values;<br />
}<br />
</syntaxhighlight><br />
Here we make our ShuffleBag by calling MakeShuffleBag. We calculate a grabCount which is random number between MIN_ITEMS and MAX_ITEMS that controls the number of times Santa is going to reach into his bag. We don't want to create an ItemStack for each item because we may get 3 iron ingots for example. We don't want 3 slots with one iron ingot, we want one slot with 3 iron ingots. So we create a Dictionary and add items of the same type to the same ItemStack. This method returns an IEnumerable that we can loop over so we need to add a method that can loop over a list of ItemStacks and add them to our chest.<br />
<syntaxhighlight lang="c#"><br />
private void AddItemStacks(IBlockEntityContainer chest, IEnumerable<ItemStack> itemStacks)<br />
{<br />
int slotNumber = 0;<br />
foreach (ItemStack itemStack in itemStacks)<br />
{<br />
slotNumber = Math.Min(slotNumber, chest.Inventory.QuantitySlots - 1);<br />
IItemSlot slot = chest.Inventory.GetSlot(slotNumber);<br />
slot.Itemstack = itemStack;<br />
slotNumber++;<br />
}<br />
}<br />
</syntaxhighlight><br />
This method does just that. It advances the IItemSlot number each time, ensuring not to place more ItemStacks than there are IItemSlots, and sets the IItemSlot.ItemStack value to the current ItemStack in the loop. We are almost there! We have all the pieces. Now we just need to get a reference to our chest that we have already placed and pass it to this method along with the ItemStacks.<br />
<br />
Lets go back to our PlaceTreasureChest method and replace the last line with the following code snippet.<br />
<syntaxhighlight lang="c#"><br />
BlockPos pos = player.Entity.Pos.HorizontalAheadCopy(2).AsBlockPos;<br />
chest.TryPlaceBlockForWorldGen(api.World.BlockAccessor, pos, BlockFacing.UP);<br />
IBlockEntityContainer chestEntity = (IBlockEntityContainer)api.World.BlockAccessor.GetBlockEntity(pos);<br />
AddItemStacks(chestEntity, MakeItemStacks());<br />
</syntaxhighlight><br />
The first line is just capturing the BlockPos position object so that we can use it in two places. The next is the same as before, just placing the chest in the world. Next we go back to the IBlockAccessor to get the block entity at that position. It's important to call GetBlockEntity here because a chest is an Entity. An Entity is something that has extra behavior attached to it as opposed to a normal block. This method returns an IBlockEntity which is a generic interface for all block entities. However we specifically need a block entity that has an Inventory. Since we know the block entity we just placed is a chest then it's safe to to cast the returned IBlockEntity to an IBlockEntityContainer which is a specialized version of IBlockEntity that provides access to an Inventory. Now that we have that we pass it along to our AddItemStacks method we created earlier and additionally pass in the list of ItemStacks that are created by our MakeItemStacks method that we also created earlier. Now if you run the code again and type /treasure you should have random items in there! Try it several times and you will see them change.<br />
<br />
That's really cool and all but not real fun for a game play experience. We want the player to find these chests and encourage them to explore the world! So lets plug in to world gen next!<br />
<br />
== Hooking in to the world gen API ==<br />
The IServerEventAPI has a method called ChunkColumnGeneration that allows you to pass a delegate just like we did for our /treasure command. However, the method signature for this is different.<br />
TODO:<br />
<br />
<br />
== Finding where to place the chest ==<br />
TODO<br />
<br />
<br />
== Excercises ==<br />
A few things could be done to improve this code and it's left as an exercise for the reader. Doing this will help you get familiar with the API without overwhelming you.<br />
<ul><br />
<li>Make chests a more rare item to find.</li><br />
<li>Currently the code will place chests over water or air. Change TryGetChestLocation to only place chests over solid blocks.</li><br />
<li>Chests should have more interesting items. Modify the code to put some more useful things in there. Maybe tools or weapons that can't be crafted.</li><br />
<li>A harder exercise might be to only place chests in caves.</li><br />
</ul><br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:WorldGen_API&diff=4858Modding:WorldGen API2019-05-21T08:55:45Z<p>CreativeMD: </p>
<hr />
<div><br />
== Intro ==<br />
<br />
We will be walking through how to plug in and add your own features to the world generation code of Vintage Story by looking at a demo mod called VSTreasureChest. The full source code for this project can be found [https://github.com/anegostudios/VSTreasureChest on Github]. We are going to walk through coding it from scratch.<br />
<br />
== VSTreasureChest Mod==<br />
This mod places treasure chests around the world for the user to find. Each treasure chest has a random number of ingots in them. The mod only places treasure chests beside trees. It also adds a server command that can be run in the chat window called /treasure that places a treasure chest in front of the player. This can be useful for testing in case you want to change what items are in the chest and you don't want to bother looking for the chest for verification.<br />
<br />
[[File:treasure chest.png|thumb]]<br />
<br />
== Getting started ==<br />
Please follow the instructions [[Setting up your Development Environment|here]] for setting up your development environment. We named our project VSTreasureChest but you can choose any name you like. We will do one different thing. When you get to the debug command line arguments instead of passing /flatworld we are going to pass /stdworld:test. The reason we are doing this is because we are going to be placing our chest beside a tree. The /flatworld generates a flat world with no trees so that won't help us much in this scenario. However, depending on the specific terrain gen features you are doing you may want to use /flatworld in the future.<br />
<br />
<br />
== The VSTreasureChestMod class ==<br />
The main class and the starting point of our mod will be VSTreasureChestMod.<br />
<br />
<syntaxhighlight lang="c#"><br />
using System;<br />
using System.Collections.Generic;<br />
using Vintagestory.API;<br />
using Vintagestory.API.Datastructures;<br />
using Vintagestory.API.Interfaces;<br />
<br />
namespace Vintagestory.Mods.TreasureChest<br />
{<br />
public class VSTreasureChestMod : ModSystem<br />
{<br />
private ICoreServerAPI api;<br />
<br />
public override void StartServerSide(ICoreServerAPI api)<br />
{<br />
this.api = api;<br />
}<br />
<br />
public override bool ShouldLoad(EnumAppSide side)<br />
{<br />
return side == EnumAppSide.Server;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
The first thing to note is the '''using''' directives at the top. Those that start with Vintagestory will allow us to access classes in the Vintagestory api. Next the '''StartServerSide''' is a method we are overriding from '''ModSystem''' that is called once when the server is start up. Here we start by just storing a reference to the '''ICoreServerAPI''' for convenient access later. We will also be registering call backs for other events here. We also override '''ShouldLoad''' to tell the system to only load this on the server side and not the client side. It would work without this but it's not necessary for the client to load this mod since all our code happens server side.<br />
<br />
== The /treasure command ==<br />
Next we are going to add the '''/treasure''' command. To do this we must register a delegate so that we can be notified when the user types our command. We do this with the '''ICoreServerAPI.RegisterCommand''' method.<br />
<br />
In '''StartServerSide''' add the following line:<br />
<syntaxhighlight lang="c#"><br />
this.api.RegisterCommand("treasure", "Place a treasure chest with random items", "", PlaceTreasureChestInFrontOfPlayer, Privilege.controlserver);<br />
</syntaxhighlight><br />
This is registering a '''treasure''' command with the server with a brief description that is used to describe the command for when the user types '''/help'''. The other important argument is the '''PlaceTreasureChestInFrontOfPlayer''' argument which is a reference to a method we haven't written yet. So lets add the following method below '''StartServerSide'''.<br />
<syntaxhighlight lang="c#"><br />
private void PlaceTreasureChestInFrontOfPlayer(IServerPlayer player, int groupId, CmdArgs args)<br />
{<br />
}<br />
</syntaxhighlight><br />
This method will now be called when the user types '''/treasure''' command in the chat window. Wasn't that easy!!! Now we need to write the code to place our chest in that method.<br />
<br />
== Placing our chest ==<br />
The first thing we need to do is figure out how to tell the API that we want a chest and not grass or stone or some other block. Every Block has a numerical ID that gets assigned when the server starts but this ID may change. Luckily there is a property of the Block class that identifies it and does not change. This is the Code property. Block codes can be found in '''Vintagestory\assets\blocktypes''' in json files. The one for chest is '''Vintagestory\assets\blocktypes\wood\generic\chest.json'''. If you open that file you will see at the very top the code property is set to "chest". We also need to append the type of the shape that basically tells the system which way the chest is facing. So for simplicity we are going to pick south. So the resulting block code we will be using is "chest-south". Ok lets see some code.<br />
<syntaxhighlight lang="c#"><br />
private void PlaceTreasureChestInFrontOfPlayer(IServerPlayer player, int groupId, CmdArgs args)<br />
{<br />
ushort blockID = api.WorldManager.GetBlockId("chest-south");<br />
Block chest = api.WorldManager.GetBlockType(blockID);<br />
chest.TryPlaceBlockForWorldGen(api.World.BlockAccessor, player.Entity.Pos.HorizontalAheadCopy(2).AsBlockPos, BlockFacing.UP);<br />
}<br />
</syntaxhighlight><br />
The first line of code asks the '''IWorldManagerAPI''' to get the numeric block id for the block code "chest-south". Next we get the '''Block''' class that represents that chest. And finally we call a method called '''TryPlaceBlockForWorldGen''' and pass in an IBlockAccessor. There are many implementations of '''IBlockAccessor''' and we will cover that in a little more detail later. For now we are using this one. The second argument just calculates the world coordinates for 2 blocks in front of the player.<br />
<br />
Now if you run the mod from Visual Studio by pressing "Start" at the top you should be able to execute the '''/treasure''' command in the game. Once you do that you will have a fancy new chest appear in front of you with no items. Well I guess it's time for us to add some items.<br />
<br />
<br />
== Adding items to our chest ==<br />
We want to add some items to the chest since after all it is a "treasure" chest. For now we are going to add various ingots to the chest. However there are lots of items in Vintagestory and I encourage you to play with this and feel free to add other items. We also want to add items at random. Not only the type of items should be random but also the ingots we add should be random. There are all kinds of ways to do this but lets write a data structure that represents a grab bag full of items and lets pull items out of that bag and place them in the chest like Santa Claus! We will create a '''ShuffleBag''' class so in Visual Studio right click on your project and go to Add->Class. Call it '''ShuffleBag.cs''' and press Add. Here's the code to place in the '''ShuffleBag''' class.<br />
<syntaxhighlight lang="c#"><br />
using System;<br />
using System.Collections.Generic;<br />
<br />
namespace Vintagestory.Mods.TreasureChest<br />
{<br />
/// <summary><br />
/// Data structure for picking random items<br />
/// </summary><br />
public class ShuffleBag<T><br />
{<br />
private Random random = new Random();<br />
private List<T> data;<br />
<br />
private T currentItem;<br />
private int currentPosition = -1;<br />
<br />
private int Capacity { get { return data.Capacity; } }<br />
public int Size { get { return data.Count; } }<br />
<br />
public ShuffleBag(int initCapacity)<br />
{<br />
this.data = new List<T>(initCapacity);<br />
this.random = new Random();<br />
}<br />
<br />
public ShuffleBag(int initCapacity, Random random)<br />
{<br />
this.random = random;<br />
this.data = new List<T>(initCapacity);<br />
}<br />
<br />
/// <summary><br />
/// Adds the specified number of the given item to the bag<br />
/// </summary><br />
public void Add(T item, int amount)<br />
{<br />
for (int i = 0; i < amount; i++)<br />
data.Add(item);<br />
<br />
currentPosition = Size - 1;<br />
}<br />
<br />
/// <summary><br />
/// Returns the next random item from the bag<br />
/// </summary><br />
public T Next()<br />
{<br />
if (currentPosition < 1)<br />
{<br />
currentPosition = Size - 1;<br />
currentItem = data[0];<br />
<br />
return currentItem;<br />
}<br />
<br />
var pos = random.Next(currentPosition);<br />
<br />
currentItem = data[pos];<br />
data[pos] = data[currentPosition];<br />
data[currentPosition] = currentItem;<br />
currentPosition--;<br />
<br />
return currentItem;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
This is all basic C# stuff but the idea is that we are going to call '''Add''' on our '''ShuffleBag''' several times to load it up, then we are going to call '''Next''' to pull items out of it. This will let us kind of control the probability or rarity of items placed in chests. Items that are more rare will have fewer items in the bag.<br />
<br />
Lets add a couple of class variables to control the minimum and maximum number of items that will go in our chest.<br />
<syntaxhighlight lang="c#"><br />
private const int MIN_ITEMS = 3;<br />
private const int MAX_ITEMS = 10;<br />
</syntaxhighlight><br />
Since we will want to create a new ShuffleBag with each chest we place lets go ahead and create a MakeShuffleBag method.<br />
<syntaxhighlight lang="c#"><br />
private ShuffleBag<string> MakeShuffleBag()<br />
{<br />
ShuffleBag<string> shuffleBag = new ShuffleBag<string>(100, api.World.Rand);<br />
shuffleBag.Add("ingot-iron", 10);<br />
shuffleBag.Add("ingot-bismuth", 5);<br />
shuffleBag.Add("ingot-silver", 5);<br />
shuffleBag.Add("ingot-zinc", 5);<br />
shuffleBag.Add("ingot-titanium", 5);<br />
shuffleBag.Add("ingot-platinum", 5);<br />
shuffleBag.Add("ingot-chromium", 5);<br />
shuffleBag.Add("ingot-tin", 5);<br />
shuffleBag.Add("ingot-lead", 5);<br />
shuffleBag.Add("ingot-gold", 5);<br />
return shuffleBag;<br />
}<br />
</syntaxhighlight><br />
This loads up our '''ShuffleBag''' with various ingots. The only more common item is iron. Feel free to change the item counts as you see fit. One thing to note here is the API does give us an instance of Random that we can use so we pass it in to our ShuffleBag.<br />
<br />
We are almost ready to place these items in the chest but we need to create an '''ItemStack''' for each slot we will be taking up in the chest. The chest is an instance of '''IBlockEntityContainer''' which has an '''Inventory''' property. An '''Inventory''' is made up of several '''IItemSlot''' instances. We need a utility method to create a list of '''ItemStacks''' to place in those slots.<br />
<syntaxhighlight lang="c#"><br />
private IEnumerable<ItemStack> MakeItemStacks()<br />
{<br />
ShuffleBag<string> shuffleBag = MakeShuffleBag();<br />
Dictionary<string, ItemStack> itemStacks = new Dictionary<string, ItemStack>();<br />
int grabCount = api.World.Rand.Next(MIN_ITEMS, MAX_ITEMS);<br />
for (int i = 0; i < grabCount; i++)<br />
{<br />
string nextItem = shuffleBag.Next();<br />
Item item = api.World.GetItem(nextItem);<br />
if (itemStacks.ContainsKey(nextItem))<br />
{<br />
itemStacks[nextItem].StackSize++;<br />
}<br />
else<br />
{<br />
itemStacks.Add(nextItem, new ItemStack(item));<br />
}<br />
}<br />
return itemStacks.Values;<br />
}<br />
</syntaxhighlight><br />
Here we make our '''ShuffleBag''' by calling '''MakeShuffleBag'''. We calculate a '''grabCount''' which is random number between '''MIN_ITEMS''' and '''MAX_ITEMS''' that controls the number of times Santa is going to reach into his bag. We don't want to create an '''ItemStack''' for each item because we may get 3 iron ingots for example. We don't want 3 slots with one iron ingot, we want one slot with 3 iron ingots. So we create a '''Dictionary''' and add items of the same type to the same '''ItemStack'''. This method returns an '''IEnumerable''' that we can loop over so we need to add a method that can loop over a list of '''ItemStacks''' and add them to our chest.<br />
<syntaxhighlight lang="c#"><br />
private void AddItemStacks(IBlockEntityContainer chest, IEnumerable<ItemStack> itemStacks)<br />
{<br />
int slotNumber = 0;<br />
foreach (ItemStack itemStack in itemStacks)<br />
{<br />
slotNumber = Math.Min(slotNumber, chest.Inventory.QuantitySlots - 1);<br />
IItemSlot slot = chest.Inventory.GetSlot(slotNumber);<br />
slot.Itemstack = itemStack;<br />
slotNumber++;<br />
}<br />
}<br />
</syntaxhighlight><br />
This method does just that. It advances the '''IItemSlot''' number each time, ensuring not to place more '''ItemStacks''' than there are '''IItemSlots''', and sets the '''IItemSlot.ItemStack''' value to the current '''ItemStack''' in the loop. We are almost there! We have all the pieces. Now we just need to get a reference to our chest that we have already placed and pass it to this method along with the '''ItemStacks'''.<br />
<br />
Lets go back to our '''PlaceTreasureChest''' method and replace the last line with the following code snippet.<br />
<syntaxhighlight lang="c#"><br />
BlockPos pos = player.Entity.Pos.HorizontalAheadCopy(2).AsBlockPos;<br />
chest.TryPlaceBlockForWorldGen(api.World.BlockAccessor, pos, BlockFacing.UP);<br />
IBlockEntityContainer chestEntity = (IBlockEntityContainer)api.World.BlockAccessor.GetBlockEntity(pos);<br />
AddItemStacks(chestEntity, MakeItemStacks());<br />
</syntaxhighlight><br />
The first line is just capturing the '''BlockPos''' position object so that we can use it in two places. The next is the same as before, just placing the chest in the world. Next we go back to the '''IBlockAccessor''' to get the block entity at that position. It's important to call '''GetBlockEntity''' here because a chest is an '''Entity'''. An '''Entity''' is something that has extra behavior attached to it as opposed to a normal block. This method returns an '''IBlockEntity''' which is a generic interface for all block entities. However we specifically need a block entity that has an Inventory. Since we know the block entity we just placed is a chest then it's safe to to cast the returned '''IBlockEntity''' to an '''IBlockEntityContainer''' which is a specialized version of '''IBlockEntity''' that provides access to an '''Inventory'''. Now that we have that we pass it along to our '''AddItemStacks''' method we created earlier and additionally pass in the list of '''ItemStacks''' that are created by our '''MakeItemStacks''' method that we also created earlier. Now if you run the code again and type '''/treasure''' you should have random items in there! Try it several times and you will see them change.<br />
<br />
That's really cool and all but not real fun for a game play experience. We want the player to find these chests and encourage them to explore the world! So lets plug in to world gen next!<br />
<br />
== Hooking in to the world gen API ==<br />
Hooking into the world gen api is very similar to how we registered our command. We will pass a delegate callback that gets called when a chunk column is generated.<br />
<br />
Add the following to '''StartServerSide'''<br />
<syntaxhighlight lang="c#"><br />
this.api.Event.ChunkColumnGeneration(OnChunkColumnGeneration, EnumWorldGenPass.Vegetation);<br />
</syntaxhighlight><br />
<br />
The first argument is a delegate, which is a reference to a method. You will get a compiler error after adding that line because we have not yet created the '''OnChunkColumnGeneration''' method. We will create that next. The second argument is an Enum that indicates which world generation pass we need to hook into. Vintage story uses several passes to generate the world. Different features are available during different world gen passes. Since we will be placing chests next to trees, we need trees to be in the world so we choose to be notified during the '''EnumWorldGenPass.Vegetation''' which tells the engine that we need neighbor chunks, block layers, tall grass, bushes and trees to be available.<br />
<syntaxhighlight lang="c#"><br />
private void OnChunkColumnGeneration(IServerChunk[] chunks, int chunkX, int chunkZ)<br />
{<br />
}<br />
</syntaxhighlight><br />
The above code is our empty '''OnChunkColumnGeneration''' which will be called when a chunk is generated. Now we need to look at how to place blocks in this method. We have already seen the '''IBlockAccessor''' interface and we will be using that to place our blocks but we can't use the implementation we used before. In the next section we will see how to get the '''IBlockAccessor''' we need and use it to place our chest.<br />
<br />
== Placing blocks during world gen ==<br />
The server does not generate chunks on the main game thread because the game's frame rate would drop significantly and it would really be disruptive to game play. The server spawns a separate thread for this and there is a special '''IBlockAccessor''' that is used in that thread that we need to get a reference to in order to place our chest. First lets add two variables at the top of our class of type '''IBlockAccessor'''. One to hold our game thread '''IBlockAccessor''' and one to hold the one used by the server world gen thread.<br />
<syntaxhighlight lang="c#"><br />
private IBlockAccessor chunkGenBlockAccessor;<br />
private IBlockAccessor worldBlockAccessor;<br />
</syntaxhighlight><br />
<br />
Let's initialize '''worldBlockAccessor''' at the top of '''StartServerSide'''. This is the '''IBlockAccessor''' we used in our '''/treasure''' command. Later we will refactor that code to use this variable.<br />
<syntaxhighlight lang="c#"><br />
this.worldBlockAccessor = api.World.BlockAccessor;<br />
</syntaxhighlight><br />
Next we will register a call back delegate to be passed the '''IBlockAccessor''' we need. Place this in '''StartServerSide'''.<br />
<syntaxhighlight lang="c#"><br />
this.api.Event.GetWorldgenBlockAccessor(OnWorldGenBlockAccessor);<br />
</syntaxhighlight><br />
Then add this method to your class:<br />
<syntaxhighlight lang="c#"><br />
private void OnWorldGenBlockAccessor(IChunkProviderThread chunkProvider)<br />
{<br />
chunkGenBlockAccessor = chunkProvider.GetBlockAccessor(true);<br />
}<br />
</syntaxhighlight><br />
Let's do a quick refactoring before we move on. Remember our '''PlaceTreasureChestInFrontOfPlayer''' method? The code in that to place the chest is going to be reused by our world gen code but we won't have a player in that case and we will also need to use a different '''IBlockAccessor''' to place our block. So let's refactor that to use a new method we call '''PlaceTreasureChest'''. So replace '''PlaceTreasureChestInFrontOfPlayer''' with the following.<br />
<syntaxhighlight lang="c#"><br />
private void PlaceTreasureChestInFrontOfPlayer(IServerPlayer player, int groupId, CmdArgs args)<br />
{<br />
PlaceTreasureChest(worldBlockAccessor, player.Entity.Pos.HorizontalAheadCopy(2).AsBlockPos);<br />
}<br />
<br />
private bool PlaceTreasureChest(IBlockAccessor blockAccessor, BlockPos pos)<br />
{<br />
ushort blockID = api.WorldManager.GetBlockId("chest-south");<br />
Block chest = api.WorldManager.GetBlockType(blockID);<br />
chest.TryPlaceBlockForWorldGen(blockAccessor, pos, BlockFacing.UP);<br />
IBlockEntityContainer chestEntity = (IBlockEntityContainer)blockAccessor.GetBlockEntity(pos);<br />
if (chestEntity != null)<br />
{<br />
AddItemStacks(chestEntity, MakeItemStacks());<br />
System.Diagnostics.Debug.WriteLine("Placed treasure chest at " + pos.ToString(), new object[] { });<br />
return true;<br />
}<br />
else<br />
{<br />
System.Diagnostics.Debug.WriteLine("FAILED TO PLACE TREASURE CHEST AT " + pos.ToString(), new object[] { });<br />
return false;<br />
}<br />
}<br />
</syntaxhighlight><br />
So what we did is make a '''PlaceTreasureChest''' that takes an '''IBlockAccessor''' and a '''BlockPos''' for placing the chest. The null check on '''chestEntity''' is probably not necessary however while developing this I found I was misusing the API by using the wrong IBlockAccessor so the null check helps detect this scenario and provides a more meaningful message than just a NullReferenceException so I suggest leaving this in. Also notice that we are printing a message to the console when a chest is placed. This is also optional however it's helpful for finding chests in the world when testing. Our '''PlaceTreasureChestInFrontOfPlayer''' method now calls our new method passing it the appropriate '''IBlockAccessor''' and the '''BlockPos''' 2 blocks in front of the player. Now that this refactoring has been done, we are ready to find a suitable spot to place our chests.<br />
<br />
== Finding where to place the chest ==<br />
Now we are ready to place code in our '''OnChunkColumnGeneration''' to find a suitable spot for our chest. We are going to set up a nested for loop to loop through each x,y,z location in the chunk and see if that spot is beside a tree. Before we set up our loop we are going to add a few more variables at the top of our class. <br />
<syntaxhighlight lang="c#"><br />
private const int MAX_CHESTS_PER_CHUNK = 1;<br />
private const float CHEST_SPAWN_PROBABILITY = 0.80f;<br />
private int chunkSize;<br />
private ISet<string> treeTypes;<br />
</syntaxhighlight><br />
They are mostly self explanatory. The first one indicates how many chests we are going to allow to be placed per chunk. '''CHEST_SPAWN_PROBABILITY''' is a probability of placing a chest in the current chunk at all. '''chunkSize''' is just stored as a convenient way to access the chunk size. To initialize it we need the following in '''StartServerSide''':<br />
<syntaxhighlight lang="c#"><br />
this.chunkSize = worldBlockAccessor.ChunkSize;<br />
</syntaxhighlight><br />
Make sure to add this after you set '''worldBlockAccessor'''!<br />
<br />
I'll explain the '''treeTypes''' variable in a bit. Just add it for now.<br />
<br />
Replace the empty '''OnChunkColumnGeneration''' with the following:<br />
<syntaxhighlight lang="c#"><br />
private void OnChunkColumnGeneration(IServerChunk[] chunks, int chunkX, int chunkZ)<br />
{<br />
int chestsPlacedCount = 0;<br />
for (int i = 0; i < chunks.Length; i++)<br />
{<br />
if (ShouldPlaceChest())<br />
{<br />
BlockPos blockPos = new BlockPos();<br />
for (int x = 0; x < chunkSize; x++)<br />
{<br />
for (int z = 0; z < chunkSize; z++)<br />
{<br />
for (int y = 0; y < worldBlockAccessor.MapSizeY; y++)<br />
{<br />
if (chestsPlacedCount < MAX_CHESTS_PER_CHUNK)<br />
{<br />
blockPos.X = chunkX * chunkSize + x;<br />
blockPos.Y = y;<br />
blockPos.Z = chunkZ * chunkSize + z;<br />
<br />
BlockPos chestLocation = TryGetChestLocation(blockPos);<br />
if (chestLocation != null)<br />
{<br />
bool chestWasPlaced = PlaceTreasureChest(chunkGenBlockAccessor, chestLocation);<br />
if (chestWasPlaced)<br />
{<br />
chestsPlacedCount++;<br />
}<br />
}<br />
}<br />
else//Max chests have been placed for this chunk<br />
{<br />
return;<br />
}<br />
}<br />
}<br />
}<br />
}<br />
}<br />
}<br />
<br />
private bool ShouldPlaceChest()<br />
{<br />
int randomNumber = api.World.Rand.Next(0, 100);<br />
return randomNumber > 0 && randomNumber <= CHEST_SPAWN_PROBABILITY * 100;<br />
}<br />
<br />
private BlockPos TryGetChestLocation(BlockPos pos)<br />
{<br />
return null;<br />
}<br />
</syntaxhighlight><br />
We've added a couple of methods here that I'll explain first. The '''ShouldPlaceChest''' method simply generates a random number between 0 and 100. If the number is between 0 and our '''CHEST_SPAWN_PROBABILITY''' multiplied by 100 then it returns true. This is called before we do our loop to see whether we should proceed in placing our chest. We will fill in the details of '''TryGetChestLocation''' in the next section so just leave it for now. The loop goes through each x, z then y coordinate and converts the coordinates to world coordinates by multiplying the '''chunkX''' coordinate by the '''chunkSize''' and adding our x coordinate in the loop. The same goes for Z. This is very important! Our '''IBlockAccessor''' expects world coordinates. World coordinates start at the beginning of the world whereas chunk coordinates start at the beginning of the chunk. Always keep your coordinate system in mind. Another thing to note here is that '''BlockPos''' is created outside our loop and reused to cut down on object creation. You don't want to create a ton of objects and cause garbage collection because this will negatively impact performance. Try to create as few objects as you can in code that will be executed frequently. The meat of the code calls our '''TryGetChestLocation''' to get a '''BlockPos'''. If the method returns null that means the current x,y,z is not a suitable location. However if it is then it moves on to our '''PlaceTreasureChest''' and increments the '''chestsPlaced''' counter which is used to check and make sure we aren't placing more chests in the chunk than '''MAX_CHESTS_PER_CHUNK'''.<br />
<br />
Our loop and main logic is finished. Now it's time to implement '''TryGetChestLocation''' to detect trees.<br />
<br />
== Detecting trees ==<br />
Remember the '''treeTypes''' variable we created at the top of our class? Now it's time to populate that with the block codes of the tree logs we will be looking for. Let's add a method called '''LoadTreeTypes'''.<br />
<syntaxhighlight lang="c#"><br />
private void LoadTreeTypes(ISet<string> treeTypes)<br />
{<br />
WorldProperty treeTypesFromFile = api.Assets.TryGet("worldproperties/block/wood.json").ToObject<WorldProperty>();<br />
foreach (WorldPropertyVariant variant in treeTypesFromFile.Variants)<br />
{<br />
treeTypes.Add("log-" + variant.Code + "-ud");<br />
}<br />
}<br />
</syntaxhighlight><br />
This method reads the log types from '''worldproperties/block/wood.json''' and adds them to our '''treeTypes''' set. Since we are looking for logs we prepend "log-" and we pick the variant "-ud" which means "Up/Down" since that's the variant of the tree log that is at the base of trees. Now to initialize our '''treeTypes''' set just add the following to '''StartServerSide''':<br />
<syntaxhighlight lang="c#"><br />
this.treeTypes = new HashSet<string>();<br />
LoadTreeTypes(treeTypes);<br />
</syntaxhighlight><br />
<br />
Now to detect our logs we can simply compare the '''Block.Code''' property to values in our '''treeTypes''' set. Lets write a quick helper method for this:<br />
<syntaxhighlight lang="c#"><br />
private bool IsTreeLog(Block block)<br />
{<br />
return treeTypes.Contains(block.Code);<br />
}<br />
</syntaxhighlight><br />
<br />
The algorithm we will use to detect the tree log is pretty simple. We will see if the current block is a tree log, if so we will iterate downward to find the bottom log by detecting the first non-log type. Once we find it we simply find an adjacent air Block. Air blocks have a '''Block.Id''' value of 0. Here's the code:<br />
<syntaxhighlight lang="c#"><br />
private BlockPos TryGetChestLocation(BlockPos pos)<br />
{<br />
Block block = chunkGenBlockAccessor.GetBlock(pos);<br />
if (IsTreeLog(block))<br />
{<br />
for (int posY = pos.Y; posY >= 0; posY--)<br />
{<br />
while (pos.Y-- > 0)<br />
{<br />
Block underBlock = chunkGenBlockAccessor.GetBlock(pos);<br />
if (IsTreeLog(underBlock)) continue;<br />
<br />
foreach (BlockFacing facing in BlockFacing.HORIZONTALS)<br />
{<br />
BlockPos adjacentPos = pos.AddCopy(facing).Up();<br />
if (chunkGenBlockAccessor.GetBlock(adjacentPos).Id == 0)<br />
{<br />
return adjacentPos;<br />
}<br />
}<br />
}<br />
}<br />
}<br />
return null;<br />
}<br />
</syntaxhighlight><br />
There are some improvements that could be made to this algorithm. I list them in the Exercises below. However, now you should be able to run the code and find treasure chests in your world!!<br />
<br />
<br />
== Summary ==<br />
You should now have an idea of how to register commands and place blocks during world gen. There's plenty more to explore. If you want to take this code further please see the suggested exercises below.<br />
<br />
== Excercises ==<br />
A few things could be done to improve this code and it's left as an exercise for the reader. Doing this will help you get familiar with the API without overwhelming you.<br />
<ul><br />
<li>Currently the code will place chests over water or air. Change '''TryGetChestLocation''' to only place chests over solid blocks.</li><br />
<li>Make the chest face away from the tree log(and player) correctly. Currently it always faces south. Hint: use chest-north, chest-east, chest-west.</li><br />
<li>Make chests a more rare item to find.</li><br />
<li>Chests should have more interesting items. Modify the code to put some more useful things in there. Maybe tools or weapons that can't be crafted.</li><br />
<li>A harder exercise might be to only place chests in caves.</li><br />
</ul><br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=WorldGen&diff=4857WorldGen2019-05-21T08:55:23Z<p>CreativeMD: </p>
<hr />
<div><br />
== Intro ==<br />
<br />
We will be walking through how plug in and add your own features to the world generation code of Vintage Story by looking at a demo mod called VSTreasureChest. The code for this project can be found here [https://github.com/anegostudios/VSTreasureChest] but we are going to walk through coding it from scratch. Please note that it is assumed that you are familiar with basic C# concepts. This document is strictly intended to familiarize you with the basic world gen api.<br />
<br />
== VSTreasureChest ==<br />
This mod places treasure chests around the world for the user to find. Each treasure chest has a random number of ingots in them. The mod only places treasure chests beside trees. It also adds a server command that can be run in the chat window called /treasure that places a treasure chest in front of the player. This can be useful for testing in case you want to change what items are in the chest and you don't want to bother looking for the chest for verification.<br />
<br />
<br />
== Getting started ==<br />
Please follow the instructions here[http://wiki.vintagestory.at/index.php?title=Setting_up_a_dev_environment] for setting up your development environment. We named our project VSTreasureChest but you can choose any name you like. We will do one different thing. When you get to the debug command line arguments instead of passing /flatworld we are going to pass /stdworld:test. The reason we are doing this is because we are going to be placing our chest beside a tree. The /flatworld generates a flat world with no trees so that won't help us much in this scenario. However, depending on the specific terrain gen features you are doing you may want to use /flatworld in the future.<br />
<br />
<br />
== The mod class ==<br />
The main class and the starting point of our mod will be VSTreasureChestMod.<br />
<br />
<syntaxhighlight lang="c#"><br />
using System;<br />
using System.Collections.Generic;<br />
using Vintagestory.API;<br />
using Vintagestory.API.Datastructures;<br />
using Vintagestory.API.Interfaces;<br />
<br />
namespace Vintagestory.Mods.TreasureChest<br />
{<br />
public class VSTreasureChestMod : ModSystem<br />
{<br />
private ICoreServerAPI api;<br />
<br />
public override void StartServerSide(ICoreServerAPI api)<br />
{<br />
this.api = api;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
The first thing to note is the '''using''' directives at the top. Those that start with Vintagestory will allow us to access classes in the Vintagestory api. Next the '''StartServerSide''' is a method we are overriding from '''ModBase''' that is called once when the server is start up. Here we start by just storing a reference to the '''ICoreServerAPI''' for convenient access later. We will also be registering call backs for other events here.<br />
<br />
== The /treasure command ==<br />
Next we are going to add the /treasure command. To do this we must register a delegate so that we can be notified when the user types our command. We do this with the ICoreServerAPI.RegisterCommand method.<br />
<br />
In StartServerSide add the following line:<br />
<syntaxhighlight lang="c#"><br />
this.api.RegisterCommand("treasure", "Place a treasure chest with random items", "", PlaceTreasureChestInFrontOfPlayer, Privilege.controlserver);<br />
</syntaxhighlight><br />
This is registering a '''treasure''' command with the server with a brief description that is used to describe the command for when the user types '''/help'''. The other important argument is the '''PlaceTreasureChestInFrontOfPlayer''' argument which is a reference to a method we haven't written yet. So lets add the following method below '''StartServerSide'''.<br />
<syntaxhighlight lang="c#"><br />
private void PlaceTreasureChestInFrontOfPlayer(IServerPlayer player, int groupId, CmdArgs args)<br />
{<br />
}<br />
</syntaxhighlight><br />
This method will now be called when the user types /treasure command in the chat window. Wasn't that easy!!! Now we need to write the code to place our chest in that method.<br />
<br />
<br />
== Placing our chest ==<br />
The first thing we need to do is figure out how to tell the API that we want a chest and not grass or stone or some other block. Every Block has a numerical ID that gets assigned when the server starts but this ID may change. Luckily there is a property of the Block class that identifies it and does not change. This is the Code property. Block codes can be found in '''Vintagestory\assets\blocktypes''' in json files. The one for chest is '''Vintagestory\assets\blocktypes\wood\generic\chest.json'''. If you open that file you will see at the very top the code property is set to "chest". We also need to append the type of the shape that basically tells the system which way the chest is facing. So for simplicity we are going to pick south. So the resulting block code we will be using is "chest-south". Ok lets see some code.<br />
<syntaxhighlight lang="c#"><br />
private void PlaceTreasureChestInFrontOfPlayer(IServerPlayer player, int groupId, CmdArgs args)<br />
{<br />
ushort blockID = api.WorldManager.GetBlockId("chest-south");<br />
Block chest = api.WorldManager.GetBlockType(blockID);<br />
chest.TryPlaceBlockForWorldGen(api.World.BlockAccessor, player.Entity.Pos.HorizontalAheadCopy(2).AsBlockPos, BlockFacing.UP);<br />
}<br />
</syntaxhighlight><br />
The first line of code asks the '''IWorldManagerAPI''' to get the numeric block id for the block code "chest-south". Next we get the '''Block''' class that represents that chest. And finally we call a method called '''TryPlaceBlockForWorldGen''' and pass in an IBlockAccessor. There are many implementations of '''IBlockAccessor''' and we will cover that in a little more detail later. For now we are using this one. The second argument just calculates the world coordinates for 2 blocks in front of the player.<br />
<br />
Now if you run the mod from Visual Studio by pressing "Start" at the top you should be able to execute the '''/treasure''' command in the game. Once you do that you will have a fancy new chest appear in front of you with no items. Well I guess it's time for us to add some items.<br />
<br />
<br />
== Adding items to our chest ==<br />
We want to add some items to the chest since after all it is a "treasure" chest. For now we are going to add various ingots to the chest. However there are lots of items in Vintagestory and I encourage you to play with this and feel free to add other items. We also want to add items at random. Not only the type of items should be random but also the ingots we add should be random. There are all kinds of ways to do this but lets write a data structure that represents a grab bag full of items and lets pull items out of that bag and place them in the chest like Santa Claus! We will create a ShuffleBag class so in Visual Studio right click on your project and go to Add->Class. Call it ShuffleBag.cs and press Add. Here's the code to place in the ShuffleBag class.<br />
<syntaxhighlight lang="c#"><br />
using System;<br />
using System.Collections.Generic;<br />
<br />
namespace Vintagestory.Mods.TreasureChest<br />
{<br />
/// <summary><br />
/// Data structure for picking random items<br />
/// </summary><br />
public class ShuffleBag<T><br />
{<br />
private Random random = new Random();<br />
private List<T> data;<br />
<br />
private T currentItem;<br />
private int currentPosition = -1;<br />
<br />
private int Capacity { get { return data.Capacity; } }<br />
public int Size { get { return data.Count; } }<br />
<br />
public ShuffleBag(int initCapacity)<br />
{<br />
this.data = new List<T>(initCapacity);<br />
this.random = new Random();<br />
}<br />
<br />
public ShuffleBag(int initCapacity, Random random)<br />
{<br />
this.random = random;<br />
this.data = new List<T>(initCapacity);<br />
}<br />
<br />
/// <summary><br />
/// Adds the specified number of the given item to the bag<br />
/// </summary><br />
public void Add(T item, int amount)<br />
{<br />
for (int i = 0; i < amount; i++)<br />
data.Add(item);<br />
<br />
currentPosition = Size - 1;<br />
}<br />
<br />
/// <summary><br />
/// Returns the next random item from the bag<br />
/// </summary><br />
public T Next()<br />
{<br />
if (currentPosition < 1)<br />
{<br />
currentPosition = Size - 1;<br />
currentItem = data[0];<br />
<br />
return currentItem;<br />
}<br />
<br />
var pos = random.Next(currentPosition);<br />
<br />
currentItem = data[pos];<br />
data[pos] = data[currentPosition];<br />
data[currentPosition] = currentItem;<br />
currentPosition--;<br />
<br />
return currentItem;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
This is all basic C# stuff but the idea is that we are going to call Add on our ShuffleBag several times to load it up, then we are going to call Next to pull items out of it. This will let us kind of control the probability or rarity of items placed in chests. Items that are more rare will have fewer items in the bag.<br />
<br />
Lets add a couple of class variables to control the minimum and maximum number of items that will go in our chest.<br />
<syntaxhighlight lang="c#"><br />
private const int MIN_ITEMS = 3;<br />
private const int MAX_ITEMS = 10;<br />
</syntaxhighlight><br />
Since we will want to create a new ShuffleBag with each chest we place lets go ahead and create a MakeShuffleBag method.<br />
<syntaxhighlight lang="c#"><br />
private ShuffleBag<string> MakeShuffleBag()<br />
{<br />
ShuffleBag<string> shuffleBag = new ShuffleBag<string>(100, api.World.Rand);<br />
shuffleBag.Add("ingot-iron", 10);<br />
shuffleBag.Add("ingot-bismuth", 5);<br />
shuffleBag.Add("ingot-silver", 5);<br />
shuffleBag.Add("ingot-zinc", 5);<br />
shuffleBag.Add("ingot-titanium", 5);<br />
shuffleBag.Add("ingot-platinum", 5);<br />
shuffleBag.Add("ingot-chromium", 5);<br />
shuffleBag.Add("ingot-tin", 5);<br />
shuffleBag.Add("ingot-lead", 5);<br />
shuffleBag.Add("ingot-gold", 5);<br />
return shuffleBag;<br />
}<br />
</syntaxhighlight><br />
This loads up our ShuffleBag with various ingots. The only more common item is iron. Feel free to change the item counts as you see fit. One thing to note here is the API does give us an instance of Random that we can use so we pass it in to our ShuffleBag.<br />
<br />
We are almost ready to place these items in the chest but we need to create an ItemStack for each slot we will be taking up in the chest. The chest is an instance of IBlockEntityContainer which has an Inventory property. An Inventory is made up of several IItemSlot instances. We need a utility method to create a list of ItemStacks to place in those slots.<br />
<syntaxhighlight lang="c#"><br />
private IEnumerable<ItemStack> MakeItemStacks()<br />
{<br />
ShuffleBag<string> shuffleBag = MakeShuffleBag();<br />
Dictionary<string, ItemStack> itemStacks = new Dictionary<string, ItemStack>();<br />
int grabCount = api.World.Rand.Next(MIN_ITEMS, MAX_ITEMS);<br />
for (int i = 0; i < grabCount; i++)<br />
{<br />
string nextItem = shuffleBag.Next();<br />
Item item = api.World.GetItem(nextItem);<br />
if (itemStacks.ContainsKey(nextItem))<br />
{<br />
itemStacks[nextItem].StackSize++;<br />
}<br />
else<br />
{<br />
itemStacks.Add(nextItem, new ItemStack(item));<br />
}<br />
}<br />
return itemStacks.Values;<br />
}<br />
</syntaxhighlight><br />
Here we make our ShuffleBag by calling MakeShuffleBag. We calculate a grabCount which is random number between MIN_ITEMS and MAX_ITEMS that controls the number of times Santa is going to reach into his bag. We don't want to create an ItemStack for each item because we may get 3 iron ingots for example. We don't want 3 slots with one iron ingot, we want one slot with 3 iron ingots. So we create a Dictionary and add items of the same type to the same ItemStack. This method returns an IEnumerable that we can loop over so we need to add a method that can loop over a list of ItemStacks and add them to our chest.<br />
<syntaxhighlight lang="c#"><br />
private void AddItemStacks(IBlockEntityContainer chest, IEnumerable<ItemStack> itemStacks)<br />
{<br />
int slotNumber = 0;<br />
foreach (ItemStack itemStack in itemStacks)<br />
{<br />
slotNumber = Math.Min(slotNumber, chest.Inventory.QuantitySlots - 1);<br />
IItemSlot slot = chest.Inventory.GetSlot(slotNumber);<br />
slot.Itemstack = itemStack;<br />
slotNumber++;<br />
}<br />
}<br />
</syntaxhighlight><br />
This method does just that. It advances the IItemSlot number each time, ensuring not to place more ItemStacks than there are IItemSlots, and sets the IItemSlot.ItemStack value to the current ItemStack in the loop. We are almost there! We have all the pieces. Now we just need to get a reference to our chest that we have already placed and pass it to this method along with the ItemStacks.<br />
<br />
Lets go back to our PlaceTreasureChest method and replace the last line with the following code snippet.<br />
<syntaxhighlight lang="c#"><br />
BlockPos pos = player.Entity.Pos.HorizontalAheadCopy(2).AsBlockPos;<br />
chest.TryPlaceBlockForWorldGen(api.World.BlockAccessor, pos, BlockFacing.UP);<br />
IBlockEntityContainer chestEntity = (IBlockEntityContainer)api.World.BlockAccessor.GetBlockEntity(pos);<br />
AddItemStacks(chestEntity, MakeItemStacks());<br />
</syntaxhighlight><br />
The first line is just capturing the BlockPos position object so that we can use it in two places. The next is the same as before, just placing the chest in the world. Next we go back to the IBlockAccessor to get the block entity at that position. It's important to call GetBlockEntity here because a chest is an Entity. An Entity is something that has extra behavior attached to it as opposed to a normal block. This method returns an IBlockEntity which is a generic interface for all block entities. However we specifically need a block entity that has an Inventory. Since we know the block entity we just placed is a chest then it's safe to to cast the returned IBlockEntity to an IBlockEntityContainer which is a specialized version of IBlockEntity that provides access to an Inventory. Now that we have that we pass it along to our AddItemStacks method we created earlier and additionally pass in the list of ItemStacks that are created by our MakeItemStacks method that we also created earlier. Now if you run the code again and type /treasure you should have random items in there! Try it several times and you will see them change.<br />
<br />
That's really cool and all but not real fun for a game play experience. We want the player to find these chests and encourage them to explore the world! So lets plug in to world gen next!<br />
<br />
== Hooking in to the world gen API ==<br />
The IServerEventAPI has a method called ChunkColumnGeneration that allows you to pass a delegate just like we did for our /treasure command. However, the method signature for this is different.<br />
TODO:<br />
<br />
<br />
== Finding where to place the chest ==<br />
TODO<br />
<br />
<br />
== Excercises ==<br />
A few things could be done to improve this code and it's left as an exercise for the reader. Doing this will help you get familiar with the API without overwhelming you.<br />
<ul><br />
<li>Make chests a more rare item to find.</li><br />
<li>Currently the code will place chests over water or air. Change TryGetChestLocation to only place chests over solid blocks.</li><br />
<li>Chests should have more interesting items. Modify the code to put some more useful things in there. Maybe tools or weapons that can't be crafted.</li><br />
<li>A harder exercise might be to only place chests in caves.</li><br />
</ul><br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Adding_Block_Behavior&diff=4856Modding:Adding Block Behavior2019-05-21T08:54:49Z<p>CreativeMD: </p>
<hr />
<div><languages /><br />
<translate><br />
__FORCETOC__<br />
<br />
== Introduction ==<br />
Block Behaviors are useful when you want different blocks to act in the same way, as you can attach one or more block behaviors to an arbitrary number of blocks.<br />
You may want to have a look at the existing [[Block Json Properties#p_behaviors|block behaviors]] before implementing your own.<br />
<br />
In this tutorial we'll create a new Behavior that we can attach to blocks to make them movable by right clicking them.<br />
<br />
== Setting up ==<br />
<br />
A [[Setting up your Development Environment|development workspace]] is required. Additionally you will need the assets (blocktype, texture and lang file). You can either create your one owns or use those pre-made ones: [https://wiki.vintagestory.at/images/2/2f/Moving_-_No_CS_File.zip Moving - No CS File.zip]<br />
<br />
== Creating the behavior ==<br />
<br />
So first of all we need to create the behavior itself, which is a class extending BlockBehavior<br />
<syntaxhighlight lang="csharp"><br />
class Moving : BlockBehavior<br />
{<br />
public Moving(Block block) : base(block)<br />
{<br />
<br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
This class provides several methods we can override. When you use Visual Studio you can find a full list of a methods by hovering with the mouse of "BlockBehavior" and pressing "F12".<br />
<br />
----<br />
<br />
The method <code>bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)</code> looks to be ideal for our purpose.<br />
<br />
What should it do?<br />
<br />
# Calculate the new position of the block depending on the face the player is looking at<br />
# Check if the block can be placed at this position<br />
# Remove the original block<br />
# Place the new block using the previously calculated position<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)<br />
{<br />
// Find the target position<br />
BlockPos pos = blockSel.Position.AddCopy(blockSel.Face.GetOpposite());<br />
<br />
// Can we place the block there?<br />
if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))<br />
{<br />
// Remove the block at the current position and place it at the target position<br />
world.BlockAccessor.SetBlock(0, blockSel.Position);<br />
world.BlockAccessor.SetBlock(block.BlockId, pos);<br />
}<br />
<br />
// Notify the game engine other block behaviors that we handled the players interaction with the block.<br />
// If we would not set the handling field the player would still be able to place blocks if he has them in hands.<br />
handling = EnumHandling.PreventDefault;<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Register ==<br />
<br />
In order the register the BlockBehavior we need to create a mod class, override <code>Start(ICoreAPI)</code> and register it with the given name:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class MovingBlocks : ModSystem<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockBehaviorClass("Moving", typeof(Moving));<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people.<br />
* for VS 1.9: [https://wiki.vintagestory.at/images/2/2a/Moving_v1.0.0.zip Moving_v1.0.0.zip]<br />
* for VS 1.6: [https://wiki.vintagestory.at/images/c/cb/Moving.zip Moving.zip]<br />
<br />
== Testing ==<br />
<br />
<youtube>8eVG0uQF2xs</youtube><br />
<br />
= Advanced Behavior =<br />
<br />
Our behavior is still rather simple, but there are a lot more possibilities. A behavior can have special properties, which can be defined by the blocktype itself.<br />
<br />
== Example ==<br />
<br />
The behavior liquid supports some special properties as shown in this example of the water blocktype:<br />
<br />
<syntaxhighlight lang="json"><br />
behaviors: [<br />
{<br />
name: "FiniteSpreadingLiquid", <br />
properties:<br />
{<br />
spreadDelay: 150, <br />
liquidCollisionSound: "hotmetal", <br />
sourceReplacementCode: "obsidian", <br />
flowingReplacementCode: "basalt"<br />
}<br />
}<br />
],<br />
</syntaxhighlight><br />
<br />
== Parsing properties ==<br />
<br />
In order to take care of special properties there is a method called <code>Initialize(JsonObject)</code>. Each blocktype creates a new instance of the behavior, so the method can be used to parse the properties.<br />
<br />
So what kind of properties could we add?<br />
* push distance<br />
* pull block if player is sneaking<br />
<br />
First of all, we need to override the method in our block behavior class ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void Initialize(JsonObject properties)<br />
{<br />
base.Initialize(properties);<br />
}<br />
</syntaxhighlight><br />
<br />
Additionally we need to add two fields, one for the distance and another one if the player should pull the block while sneaking ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public int distance = 1;<br />
public bool pull = false;<br />
</syntaxhighlight><br />
<br />
Now we can parse the two properties like so:<br />
<br />
<syntaxhighlight lang="c#"><br />
distance = properties["distance"].AsInt(1);<br />
pull = properties["pull"].AsBool(false);<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
The next thing we need to change is the interact method itself, so that it takes care of the distance and the pull properties ...<br />
<syntaxhighlight lang="c#"><br />
public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)<br />
{<br />
BlockPos pos = blockSel.Position.AddCopy(pull && byPlayer.WorldData.EntityControls.Sneak ? blockSel.Face : blockSel.Face.GetOpposite(), distance);<br />
if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))<br />
{<br />
world.BlockAccessor.SetBlock(0, blockSel.Position);<br />
world.BlockAccessor.SetBlock(block.BlockId, pos);<br />
}<br />
handling = EnumHandling.PreventDefault;<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Adding another block ==<br />
<br />
Let's create another block using this behavior, but this time we will configure some additional properties ...<br />
<br />
<syntaxhighlight lang="json"><br />
behaviors: [<br />
{<br />
name: "Moving",<br />
properties: {<br />
"distance": 2,<br />
"pull": true<br />
}<br />
}<br />
], <br />
</syntaxhighlight><br />
<br />
The block will be pushed two blocks instead of one and the player can pull it by sneaking while right clicking.<br />
<br />
* for VS 1.9: [https://wiki.vintagestory.at/images/7/7b/Advancedmoving_v1.0.0.zip AdvancedMoving_v1.0.0.zip]<br />
* for VS 1.6: [https://wiki.vintagestory.at/images/7/72/AdvancedMoving.zip AdvancedMoving.zip]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}<br />
<br />
<br />
</translate></div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Block_Entity&diff=4855Modding:Block Entity2019-05-21T08:54:41Z<p>CreativeMD: </p>
<hr />
<div>__FORCETOC__<br />
<br />
== Introduction ==<br />
<br />
A block entity is a construct that you can tack onto an existing block to give it additional functionality. Whenever a block should do something on a regular interval or store extra information, such as the contents of a chest block, you need a block entity. It's highly recommend to have read the tutorial about [[Basic Modding|Basic Blocks]] and [[Advanced Blocks|Block Class]] in order to understand this tutorial properly.<br />
<br />
== The Texture Flipper ==<br />
<br />
Let's create a block which switches its texture every 3 seconds. It should have two variants <code>"on"</code> and <code>"off"</code>. Additionally we need to define the blockentity class like so:<br />
<syntaxhighlight lang="json"><br />
entityClass: "tickingcounter",<br />
</syntaxhighlight><br />
<br />
You can download the assets [https://wiki.vintagestory.at/images/d/d4/Ticking_-_No_CS_File.zip here] and place it in your mods directory.<br />
<br />
== The BlockEntity ==<br />
<br />
Now we need to register our blockentity class and therefore we need to create a new *.cs file in our project. Let's name it <code>Ticking.cs</code>.<br />
<br />
First of all you need to create the blockentity class itself. Therefore you need to extend <code>BlockEntity</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TickingBlockEntity : BlockEntity<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
This class needs to have a timer, once the timer reaches 3 seconds it should replace the current block with the different state.<br />
<br />
In order to create a timer we need to register a tick listener. Therefore we need to override <code>Initialize(ICoreAPI)</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void Initialize(ICoreAPI api)<br />
{<br />
base.Initialize(api);<br />
}<br />
</syntaxhighlight><br />
<br />
add a counter (which should increase per tick) ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public int timer;<br />
</syntaxhighlight><br />
<br />
... and the actual ticking method ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public void onTick(float par)<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
To register the ticking method we can use <code>RegisterGameTickListener</code> in <code>Inizialize</code><br />
<br />
<syntaxhighlight lang="c#"><br />
public override void Initialize(ICoreAPI api)<br />
{<br />
base.Initialize(api);<br />
RegisterGameTickListener(onTick, 20);<br />
}<br />
</syntaxhighlight><br />
<br />
The timer itself should increase per tick. It ticks 20 times per seconds, meaning 3 seconds have passed after the timer has reached 60. So if it's greater than 60 it should replace the block:<br />
<br />
<syntaxhighlight lang="c#"><br />
public void onTick(float par)<br />
{<br />
timer++;<br />
if(timer > 60)<br />
{<br />
Block block = api.World.BlockAccessor.GetBlock(pos);<br />
if (block.Code.Path.EndsWith("-on"))<br />
block = api.World.GetBlock(block.CodeWithParts("off"));<br />
else<br />
block = api.World.GetBlock(block.CodeWithParts("on"));<br />
api.World.BlockAccessor.SetBlock(block.BlockId, pos);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
Furthermore we need to save the current time:<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void ToTreeAttributes(ITreeAttribute tree)<br />
{<br />
base.ToTreeAttributes(tree);<br />
tree.SetInt("timer", timer);<br />
}<br />
<br />
public override void FromTreeAtributes(ITreeAttribute tree)<br />
{<br />
base.FromTreeAtributes(tree);<br />
timer = tree.GetInt("timer");<br />
}<br />
</syntaxhighlight><br />
<br />
== Registering the Block Entity ==<br />
<br />
Registering the blockentity class is rather simple (rather similar to registering a block class). You need a mod class and override <code>Start(ICoreAPI)</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class Ticking : ModSystem<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockEntityClass("tickingcounter", typeof(TickingBlockEntity));<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing ==<br />
<br />
Now everything is ready to run the first test:<br />
<br />
<youtube>QQUibC4H9TI</youtube><br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people. It will work in the same way as ordinary mods, you can install it by copying it into the mods folder.<br />
<br />
* for VS 1.9: [https://wiki.vintagestory.at/images/8/80/Ticking_v1.0.0.zip Ticking_v1.0.0.zip]<br />
* for VS 1.6: [https://wiki.vintagestory.at/images/6/65/Ticking.zip Ticking.zip]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Adding_Block_Behavior&diff=4854Modding:Adding Block Behavior2019-05-21T08:54:14Z<p>CreativeMD: /* Adding another block */</p>
<hr />
<div><languages /><br />
<translate><br />
__FORCETOC__<br />
<br />
== Introduction ==<br />
Block Behaviors are useful when you want different blocks to act in the same way, as you can attach one or more block behaviors to an arbitrary number of blocks.<br />
You may want to have a look at the existing [[Block Json Properties#p_behaviors|block behaviors]] before implementing your own.<br />
<br />
In this tutorial we'll create a new Behavior that we can attach to blocks to make them movable by right clicking them.<br />
<br />
== Setting up ==<br />
<br />
A [[Setting up your Development Environment|development workspace]] is required. Additionally you will need the assets (blocktype, texture and lang file). You can either create your one owns or use those pre-made ones: [https://wiki.vintagestory.at/images/2/2f/Moving_-_No_CS_File.zip Moving - No CS File.zip]<br />
<br />
== Creating the behavior ==<br />
<br />
So first of all we need to create the behavior itself, which is a class extending BlockBehavior<br />
<syntaxhighlight lang="csharp"><br />
class Moving : BlockBehavior<br />
{<br />
public Moving(Block block) : base(block)<br />
{<br />
<br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
This class provides several methods we can override. When you use Visual Studio you can find a full list of a methods by hovering with the mouse of "BlockBehavior" and pressing "F12".<br />
<br />
----<br />
<br />
The method <code>bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)</code> looks to be ideal for our purpose.<br />
<br />
What should it do?<br />
<br />
# Calculate the new position of the block depending on the face the player is looking at<br />
# Check if the block can be placed at this position<br />
# Remove the original block<br />
# Place the new block using the previously calculated position<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)<br />
{<br />
// Find the target position<br />
BlockPos pos = blockSel.Position.AddCopy(blockSel.Face.GetOpposite());<br />
<br />
// Can we place the block there?<br />
if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))<br />
{<br />
// Remove the block at the current position and place it at the target position<br />
world.BlockAccessor.SetBlock(0, blockSel.Position);<br />
world.BlockAccessor.SetBlock(block.BlockId, pos);<br />
}<br />
<br />
// Notify the game engine other block behaviors that we handled the players interaction with the block.<br />
// If we would not set the handling field the player would still be able to place blocks if he has them in hands.<br />
handling = EnumHandling.PreventDefault;<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Register ==<br />
<br />
In order the register the BlockBehavior we need to create a mod class, override <code>Start(ICoreAPI)</code> and register it with the given name:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class MovingBlocks : ModBase<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockBehaviorClass("Moving", typeof(Moving));<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people.<br />
* for VS 1.9: [https://wiki.vintagestory.at/images/2/2a/Moving_v1.0.0.zip Moving_v1.0.0.zip]<br />
* for VS 1.6: [https://wiki.vintagestory.at/images/c/cb/Moving.zip Moving.zip]<br />
<br />
== Testing ==<br />
<br />
<youtube>8eVG0uQF2xs</youtube><br />
<br />
= Advanced Behavior =<br />
<br />
Our behavior is still rather simple, but there are a lot more possibilities. A behavior can have special properties, which can be defined by the blocktype itself.<br />
<br />
== Example ==<br />
<br />
The behavior liquid supports some special properties as shown in this example of the water blocktype:<br />
<br />
<syntaxhighlight lang="json"><br />
behaviors: [<br />
{<br />
name: "FiniteSpreadingLiquid", <br />
properties:<br />
{<br />
spreadDelay: 150, <br />
liquidCollisionSound: "hotmetal", <br />
sourceReplacementCode: "obsidian", <br />
flowingReplacementCode: "basalt"<br />
}<br />
}<br />
],<br />
</syntaxhighlight><br />
<br />
== Parsing properties ==<br />
<br />
In order to take care of special properties there is a method called <code>Initialize(JsonObject)</code>. Each blocktype creates a new instance of the behavior, so the method can be used to parse the properties.<br />
<br />
So what kind of properties could we add?<br />
* push distance<br />
* pull block if player is sneaking<br />
<br />
First of all, we need to override the method in our block behavior class ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void Initialize(JsonObject properties)<br />
{<br />
base.Initialize(properties);<br />
}<br />
</syntaxhighlight><br />
<br />
Additionally we need to add two fields, one for the distance and another one if the player should pull the block while sneaking ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public int distance = 1;<br />
public bool pull = false;<br />
</syntaxhighlight><br />
<br />
Now we can parse the two properties like so:<br />
<br />
<syntaxhighlight lang="c#"><br />
distance = properties["distance"].AsInt(1);<br />
pull = properties["pull"].AsBool(false);<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
The next thing we need to change is the interact method itself, so that it takes care of the distance and the pull properties ...<br />
<syntaxhighlight lang="c#"><br />
public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)<br />
{<br />
BlockPos pos = blockSel.Position.AddCopy(pull && byPlayer.WorldData.EntityControls.Sneak ? blockSel.Face : blockSel.Face.GetOpposite(), distance);<br />
if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))<br />
{<br />
world.BlockAccessor.SetBlock(0, blockSel.Position);<br />
world.BlockAccessor.SetBlock(block.BlockId, pos);<br />
}<br />
handling = EnumHandling.PreventDefault;<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Adding another block ==<br />
<br />
Let's create another block using this behavior, but this time we will configure some additional properties ...<br />
<br />
<syntaxhighlight lang="json"><br />
behaviors: [<br />
{<br />
name: "Moving",<br />
properties: {<br />
"distance": 2,<br />
"pull": true<br />
}<br />
}<br />
], <br />
</syntaxhighlight><br />
<br />
The block will be pushed two blocks instead of one and the player can pull it by sneaking while right clicking.<br />
<br />
* for VS 1.9: [https://wiki.vintagestory.at/images/7/7b/Advancedmoving_v1.0.0.zip AdvancedMoving_v1.0.0.zip]<br />
* for VS 1.6: [https://wiki.vintagestory.at/images/7/72/AdvancedMoving.zip AdvancedMoving.zip]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}<br />
<br />
<br />
</translate></div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Adding_Block_Behavior&diff=4853Modding:Adding Block Behavior2019-05-21T08:53:33Z<p>CreativeMD: /* Distribution */</p>
<hr />
<div><languages /><br />
<translate><br />
__FORCETOC__<br />
<br />
== Introduction ==<br />
Block Behaviors are useful when you want different blocks to act in the same way, as you can attach one or more block behaviors to an arbitrary number of blocks.<br />
You may want to have a look at the existing [[Block Json Properties#p_behaviors|block behaviors]] before implementing your own.<br />
<br />
In this tutorial we'll create a new Behavior that we can attach to blocks to make them movable by right clicking them.<br />
<br />
== Setting up ==<br />
<br />
A [[Setting up your Development Environment|development workspace]] is required. Additionally you will need the assets (blocktype, texture and lang file). You can either create your one owns or use those pre-made ones: [https://wiki.vintagestory.at/images/2/2f/Moving_-_No_CS_File.zip Moving - No CS File.zip]<br />
<br />
== Creating the behavior ==<br />
<br />
So first of all we need to create the behavior itself, which is a class extending BlockBehavior<br />
<syntaxhighlight lang="csharp"><br />
class Moving : BlockBehavior<br />
{<br />
public Moving(Block block) : base(block)<br />
{<br />
<br />
} <br />
}<br />
</syntaxhighlight><br />
<br />
This class provides several methods we can override. When you use Visual Studio you can find a full list of a methods by hovering with the mouse of "BlockBehavior" and pressing "F12".<br />
<br />
----<br />
<br />
The method <code>bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)</code> looks to be ideal for our purpose.<br />
<br />
What should it do?<br />
<br />
# Calculate the new position of the block depending on the face the player is looking at<br />
# Check if the block can be placed at this position<br />
# Remove the original block<br />
# Place the new block using the previously calculated position<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)<br />
{<br />
// Find the target position<br />
BlockPos pos = blockSel.Position.AddCopy(blockSel.Face.GetOpposite());<br />
<br />
// Can we place the block there?<br />
if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))<br />
{<br />
// Remove the block at the current position and place it at the target position<br />
world.BlockAccessor.SetBlock(0, blockSel.Position);<br />
world.BlockAccessor.SetBlock(block.BlockId, pos);<br />
}<br />
<br />
// Notify the game engine other block behaviors that we handled the players interaction with the block.<br />
// If we would not set the handling field the player would still be able to place blocks if he has them in hands.<br />
handling = EnumHandling.PreventDefault;<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Register ==<br />
<br />
In order the register the BlockBehavior we need to create a mod class, override <code>Start(ICoreAPI)</code> and register it with the given name:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class MovingBlocks : ModBase<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockBehaviorClass("Moving", typeof(Moving));<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people.<br />
* for VS 1.9: [https://wiki.vintagestory.at/images/2/2a/Moving_v1.0.0.zip Moving_v1.0.0.zip]<br />
* for VS 1.6: [https://wiki.vintagestory.at/images/c/cb/Moving.zip Moving.zip]<br />
<br />
== Testing ==<br />
<br />
<youtube>8eVG0uQF2xs</youtube><br />
<br />
= Advanced Behavior =<br />
<br />
Our behavior is still rather simple, but there are a lot more possibilities. A behavior can have special properties, which can be defined by the blocktype itself.<br />
<br />
== Example ==<br />
<br />
The behavior liquid supports some special properties as shown in this example of the water blocktype:<br />
<br />
<syntaxhighlight lang="json"><br />
behaviors: [<br />
{<br />
name: "FiniteSpreadingLiquid", <br />
properties:<br />
{<br />
spreadDelay: 150, <br />
liquidCollisionSound: "hotmetal", <br />
sourceReplacementCode: "obsidian", <br />
flowingReplacementCode: "basalt"<br />
}<br />
}<br />
],<br />
</syntaxhighlight><br />
<br />
== Parsing properties ==<br />
<br />
In order to take care of special properties there is a method called <code>Initialize(JsonObject)</code>. Each blocktype creates a new instance of the behavior, so the method can be used to parse the properties.<br />
<br />
So what kind of properties could we add?<br />
* push distance<br />
* pull block if player is sneaking<br />
<br />
First of all, we need to override the method in our block behavior class ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void Initialize(JsonObject properties)<br />
{<br />
base.Initialize(properties);<br />
}<br />
</syntaxhighlight><br />
<br />
Additionally we need to add two fields, one for the distance and another one if the player should pull the block while sneaking ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public int distance = 1;<br />
public bool pull = false;<br />
</syntaxhighlight><br />
<br />
Now we can parse the two properties like so:<br />
<br />
<syntaxhighlight lang="c#"><br />
distance = properties["distance"].AsInt(1);<br />
pull = properties["pull"].AsBool(false);<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
The next thing we need to change is the interact method itself, so that it takes care of the distance and the pull properties ...<br />
<syntaxhighlight lang="c#"><br />
public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)<br />
{<br />
BlockPos pos = blockSel.Position.AddCopy(pull && byPlayer.WorldData.EntityControls.Sneak ? blockSel.Face : blockSel.Face.GetOpposite(), distance);<br />
if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))<br />
{<br />
world.BlockAccessor.SetBlock(0, blockSel.Position);<br />
world.BlockAccessor.SetBlock(block.BlockId, pos);<br />
}<br />
handling = EnumHandling.PreventDefault;<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Adding another block ==<br />
<br />
Let's create another block using this behavior, but this time we will configure some additional properties ...<br />
<br />
<syntaxhighlight lang="json"><br />
behaviors: [<br />
{<br />
name: "Moving",<br />
properties: {<br />
"distance": 2,<br />
"pull": true<br />
}<br />
}<br />
], <br />
</syntaxhighlight><br />
<br />
The block will be pushed two blocks instead of one and the player can pull it by sneaking while right clicking.<br />
<br />
You can download the complete mod [https://wiki.vintagestory.at/images/7/72/AdvancedMoving.zip here].<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}<br />
<br />
<br />
</translate></div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Advancedmoving_v1.0.0.zip&diff=4852File:Advancedmoving v1.0.0.zip2019-05-21T08:52:54Z<p>CreativeMD: Category:Tutorial Files</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Moving_v1.0.0.zip&diff=4851File:Moving v1.0.0.zip2019-05-21T08:52:47Z<p>CreativeMD: Category:Tutorial Files</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Block_Entity&diff=4850Modding:Block Entity2019-05-21T08:51:41Z<p>CreativeMD: /* Distribution */</p>
<hr />
<div>__FORCETOC__<br />
<br />
== Introduction ==<br />
<br />
A block entity is a construct that you can tack onto an existing block to give it additional functionality. Whenever a block should do something on a regular interval or store extra information, such as the contents of a chest block, you need a block entity. It's highly recommend to have read the tutorial about [[Basic Modding|Basic Blocks]] and [[Advanced Blocks|Block Class]] in order to understand this tutorial properly.<br />
<br />
== The Texture Flipper ==<br />
<br />
Let's create a block which switches its texture every 3 seconds. It should have two variants <code>"on"</code> and <code>"off"</code>. Additionally we need to define the blockentity class like so:<br />
<syntaxhighlight lang="json"><br />
entityClass: "tickingcounter",<br />
</syntaxhighlight><br />
<br />
You can download the assets [https://wiki.vintagestory.at/images/d/d4/Ticking_-_No_CS_File.zip here] and place it in your mods directory.<br />
<br />
== The BlockEntity ==<br />
<br />
Now we need to register our blockentity class and therefore we need to create a new *.cs file in our project. Let's name it <code>Ticking.cs</code>.<br />
<br />
First of all you need to create the blockentity class itself. Therefore you need to extend <code>BlockEntity</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TickingBlockEntity : BlockEntity<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
This class needs to have a timer, once the timer reaches 3 seconds it should replace the current block with the different state.<br />
<br />
In order to create a timer we need to register a tick listener. Therefore we need to override <code>Initialize(ICoreAPI)</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void Initialize(ICoreAPI api)<br />
{<br />
base.Initialize(api);<br />
}<br />
</syntaxhighlight><br />
<br />
add a counter (which should increase per tick) ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public int timer;<br />
</syntaxhighlight><br />
<br />
... and the actual ticking method ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public void onTick(float par)<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
To register the ticking method we can use <code>RegisterGameTickListener</code> in <code>Inizialize</code><br />
<br />
<syntaxhighlight lang="c#"><br />
public override void Initialize(ICoreAPI api)<br />
{<br />
base.Initialize(api);<br />
RegisterGameTickListener(onTick, 20);<br />
}<br />
</syntaxhighlight><br />
<br />
The timer itself should increase per tick. It ticks 20 times per seconds, meaning 3 seconds have passed after the timer has reached 60. So if it's greater than 60 it should replace the block:<br />
<br />
<syntaxhighlight lang="c#"><br />
public void onTick(float par)<br />
{<br />
timer++;<br />
if(timer > 60)<br />
{<br />
Block block = api.World.BlockAccessor.GetBlock(pos);<br />
if (block.Code.Path.EndsWith("-on"))<br />
block = api.World.GetBlock(block.CodeWithParts("off"));<br />
else<br />
block = api.World.GetBlock(block.CodeWithParts("on"));<br />
api.World.BlockAccessor.SetBlock(block.BlockId, pos);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
Furthermore we need to save the current time:<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void ToTreeAttributes(ITreeAttribute tree)<br />
{<br />
base.ToTreeAttributes(tree);<br />
tree.SetInt("timer", timer);<br />
}<br />
<br />
public override void FromTreeAtributes(ITreeAttribute tree)<br />
{<br />
base.FromTreeAtributes(tree);<br />
timer = tree.GetInt("timer");<br />
}<br />
</syntaxhighlight><br />
<br />
== Registering the Block Entity ==<br />
<br />
Registering the blockentity class is rather simple (rather similar to registering a block class). You need a mod class and override <code>Start(ICoreAPI)</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class Ticking : ModBase<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockEntityClass("tickingcounter", typeof(TickingBlockEntity));<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing ==<br />
<br />
Now everything is ready to run the first test:<br />
<br />
<youtube>QQUibC4H9TI</youtube><br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people. It will work in the same way as ordinary mods, you can install it by copying it into the mods folder.<br />
<br />
* for VS 1.9: [https://wiki.vintagestory.at/images/8/80/Ticking_v1.0.0.zip Ticking_v1.0.0.zip]<br />
* for VS 1.6: [https://wiki.vintagestory.at/images/6/65/Ticking.zip Ticking.zip]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Ticking_v1.0.0.zip&diff=4849File:Ticking v1.0.0.zip2019-05-21T08:50:49Z<p>CreativeMD: Category:Tutorial Files</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Block_and_Item_Interactions&diff=4848Modding:Block and Item Interactions2019-05-21T08:49:42Z<p>CreativeMD: </p>
<hr />
<div>This tutorial should introduce you into the basics of custom interactions. We will create a magic wand which should spawn particles when holding right click.<br />
<br />
== Preparations ==<br />
<br />
I highly recommend to read about [[Advanced Items|The Item Class]] first. Additionally you can download the assets [https://wiki.vintagestory.at/images/4/4d/MagicWand_-_No_CS_File.zip here].<br />
<br />
All of this should be familiar to you, creating and registering the item class ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public class Magic : ModSystem<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("ItemMagicWand", typeof(ItemMagicWand));<br />
}<br />
<br />
}<br />
<br />
public class ItemMagicWand : Item<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
== Adding particles ==<br />
<br />
Now we need to implement the interact function. First of all we need to specify that the player can "use" this tool, therefore we need to set handling to <code>handled</code> ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void OnHeldInteractStart(ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handling)<br />
{<br />
handling = EnumHandHandling.Handled;<br />
}<br />
</syntaxhighlight><br />
<br />
The method <code>OnHeldInteractStep</code> allows us to spawn particles per tick while the player is using the item, but it would be better to implement an animation first. Particles should spawn after the animation is done ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)<br />
{<br />
if (byEntity.World is IClientWorldAccessor)<br />
{<br />
ModelTransform tf = new ModelTransform();<br />
tf.EnsureDefaultValues();<br />
<br />
tf.Origin.Set(0, -1, 0);<br />
tf.Rotation.Z = Math.Min(30, secondsUsed * 40);<br />
byEntity.Controls.UsingHeldItemTransformAfter = tf;<br />
}<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
Holding rightclick ...<br />
<br />
[[File:Magic Stick Interact.gif|300px]]<br />
<br />
So let's start to mess around with particles, therefore we need a static particle type ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public static SimpleParticleProperties particles = new SimpleParticleProperties(<br />
1, 1,<br />
ColorUtil.ColorFromArgb(50, 220, 220, 220),<br />
new Vec3d(),<br />
new Vec3d(),<br />
new Vec3f(-0.25f, 0.1f, -0.25f),<br />
new Vec3f(0.25f, 0.1f, 0.25f),<br />
1.5f,<br />
-0.075f,<br />
0.25f,<br />
0.25f,<br />
EnumParticleModel.Quad<br />
);<br />
</syntaxhighlight><br />
<br />
Particles should spawn once the animation is completed. This will be the case after <code>0.6</code> seconds ...<br />
<br />
<syntaxhighlight lang="c#"><br />
if (secondsUsed > 0.6)<br />
{<br />
//Spawn particles<br />
}<br />
</syntaxhighlight><br />
<br />
I suggest to read the tutorial about [[Simple Particles]] first. This code will spawn particles in front of the player with a randomized color and a sinus evolving size ...<br />
<br />
<syntaxhighlight lang="c#"><br />
Vec3d pos =<br />
byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight(), 0)<br />
.Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)<br />
;<br />
<br />
Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();<br />
particles.minVelocity = speedVec;<br />
Random rand = new Random();<br />
particles.color = ColorUtil.ToRGBABytes(ColorUtil.ColorFromArgb(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255)));<br />
particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);<br />
particles.addPos.Set(0.1, 0.1, 0.1);<br />
particles.minSize = 0.1F;<br />
particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);<br />
byEntity.World.SpawnParticles(particles);<br />
</syntaxhighlight><br />
<br />
If we put everything together the <code>OnHeldInteractStep</code> method will look like this ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)<br />
{<br />
if (byEntity.World is IClientWorldAccessor)<br />
{<br />
ModelTransform tf = new ModelTransform();<br />
tf.EnsureDefaultValues();<br />
<br />
tf.Origin.Set(0, -1, 0);<br />
tf.Rotation.Z = Math.Min(30, secondsUsed * 40);<br />
byEntity.Controls.UsingHeldItemTransformAfter = tf;<br />
<br />
if (secondsUsed > 0.6)<br />
{<br />
Vec3d pos =<br />
byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight, 0)<br />
.Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)<br />
;<br />
<br />
Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();<br />
particles.minVelocity = speedVec;<br />
Random rand = new Random();<br />
particles.color = ColorUtil.ToRgba(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255));<br />
particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);<br />
particles.addPos.Set(0.1, 0.1, 0.1);<br />
particles.minSize = 0.1F;<br />
particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);<br />
byEntity.World.SpawnParticles(particles);<br />
}<br />
}<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing ==<br />
<br />
Now we can run our first test, doesn't it look beautiful?<br />
<br />
<youtube>bTPXL97Gfns</youtube><br />
<br />
== Download ==<br />
<br />
Feel free to try it out yourself:<br />
<br />
Here is my version: <br />
* for VS v1.9: [https://wiki.vintagestory.at/images/7/72/Magicwand_vs1.9_v1.0.0.zip Magicwand_vs1.9_v1.0.0.zip]<br />
* for VS v1.8: [https://wiki.vintagestory.at/images/3/38/MagicWand.zip MagicWand.zip]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Advanced_Items&diff=4847Modding:Advanced Items2019-05-21T08:49:19Z<p>CreativeMD: </p>
<hr />
<div>__FORCETOC__<br />
<br />
It's highly recommended to read [[Basic Item]] first. Additionally this tutorial requires a development environment. If you don't have one already you should read the tutorial [[Setting up your Development Environment]].<br />
<br />
= Tunnel pickaxe =<br />
<br />
Let's create an item, which allows you to dig a 3x3 tunnel by mining just one block.<br />
<br />
== Item Assets ==<br />
<br />
First of all we need to create a new item, including a texture and a lang file. Those assets are pretty straight forward and you can download them [https://wiki.vintagestory.at/images/c/cd/Tunnler_-_No_CS_File.zip here]. Just place the file in your mods folder and you are ready to start programming.<br />
<br />
There is only one new property in your json item file called <code>class</code>:<br />
<syntaxhighlight lang="json"><br />
class: "tunnler",<br />
</syntaxhighlight><br />
<br />
We will create this class, to give the item the desired functionality, so if you pick a different name make sure it matches the one below.<br />
<br />
== The Item Class ==<br />
<br />
If you have read the [[Advanced Blocks]] Tutorial already, this should be fimilar to you.<br />
<br />
In order to register your item class, we need to create a mod, which is basically a class exendting ModSystem:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerMod : ModSystem<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
By overriding the <code>Start(ICoreAPI)</code> method, we can register our class. Remember if you have picked a different class name you have to use that one instead.<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerMod : ModSystem<br />
{<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("tunnler", typeof(TunnlerItem));<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
This should be marked as a syntax error because there is no <code>TunnlerItem</code> class yet.<br />
<br />
=== The Item Class ===<br />
<br />
Let's create our item class itself which of course has to extend <code>Item</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerItem : Item<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
This should solve all syntax errors.<br />
<br />
'''So what should our tool do?''' Once the player mines a block with this tool every block around it should be mined as well. This is rather easy to implement by overriding the method <code>void OnBlockBroken(IWorldAccessor world, IEntity byEntity, IItemSlot itemslot, BlockSelection blockSel)</code>.<br />
<br />
We need to take care of the facing (which side the player is focusing) and if the player is in creative or survival mode (whether items should be dropped or not). Before we are going to override OnBlockBroken we should create a method which destroys all blocks between two block positions (min & max). It should also only drop items if the player is in survival mode:<br />
<br />
<syntaxhighlight lang="c#"><br />
public void destroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player)<br />
{<br />
BlockPos tempPos = new BlockPos();<br />
for (int x = min.X; x <= max.X; x++)<br />
{<br />
for (int y = min.Y; y <= max.Y; y++)<br />
{<br />
for (int z = min.Z; z <= max.Z; z++)<br />
{<br />
tempPos.Set(x, y, z);<br />
if (player.WorldData.CurrentGameMode == EnumGameMode.Creative)<br />
world.BlockAccessor.SetBlock(0, tempPos);<br />
else<br />
world.BlockAccessor.BreakBlock(tempPos, player);<br />
}<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
Now we can implement <code>OnBlockBroken</code> rather easily, by taken care of every possible axis the player could face:<br />
<syntaxhighlight lang="c#"><br />
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel)<br />
{<br />
if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel))<br />
{<br />
if (byEntity is EntityPlayer)<br />
{<br />
IPlayer player = world.PlayerByUid((byEntity as EntityPlayer).PlayerUID);<br />
switch (blockSel.Face.Axis)<br />
{<br />
case EnumAxis.X:<br />
destroyBlocks(world, blockSel.Position.AddCopy(0, -1, -1), blockSel.Position.AddCopy(0, 1, 1), player);<br />
break;<br />
case EnumAxis.Y:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, 0, -1), blockSel.Position.AddCopy(1, 0, 1), player);<br />
break;<br />
case EnumAxis.Z:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, -1, 0), blockSel.Position.AddCopy(1, 1, 0), player);<br />
break;<br />
}<br />
}<br />
return true;<br />
}<br />
return false; <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
----<br />
<br />
If you have done everything right, your file should look similar to this:<br />
<syntaxhighlight lang="c#"><br />
using Vintagestory.API.Common;<br />
using Vintagestory.API.Common.Entities;<br />
using Vintagestory.API.MathTools;<br />
<br />
namespace ExampleMods<br />
{<br />
public class TunnlerMod : ModSystem<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("tunnler", typeof(TunnlerItem));<br />
}<br />
<br />
}<br />
<br />
public class TunnlerItem : Item<br />
{<br />
<br />
public void destroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player)<br />
{<br />
BlockPos tempPos = new BlockPos();<br />
for (int x = min.X; x <= max.X; x++)<br />
{<br />
for (int y = min.Y; y <= max.Y; y++)<br />
{<br />
for (int z = min.Z; z <= max.Z; z++)<br />
{<br />
tempPos.Set(x, y, z);<br />
if (player.WorldData.CurrentGameMode == EnumGameMode.Creative)<br />
world.BlockAccessor.SetBlock(0, tempPos);<br />
else<br />
world.BlockAccessor.BreakBlock(tempPos, player);<br />
}<br />
}<br />
}<br />
}<br />
<br />
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel)<br />
{<br />
if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel))<br />
{<br />
if (byEntity is EntityPlayer)<br />
{<br />
IPlayer player = world.PlayerByUid((byEntity as EntityPlayer).PlayerUID);<br />
switch (blockSel.Face.Axis)<br />
{<br />
case EnumAxis.X:<br />
destroyBlocks(world, blockSel.Position.AddCopy(0, -1, -1), blockSel.Position.AddCopy(0, 1, 1), player);<br />
break;<br />
case EnumAxis.Y:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, 0, -1), blockSel.Position.AddCopy(1, 0, 1), player);<br />
break;<br />
case EnumAxis.Z:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, -1, 0), blockSel.Position.AddCopy(1, 1, 0), player);<br />
break;<br />
}<br />
}<br />
return true;<br />
}<br />
return false; <br />
}<br />
<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
You can also download the file directly: [https://wiki.vintagestory.at/images/a/ad/Tunnler.cs Tunnler.cs].<br />
<br />
== Testing ==<br />
<br />
This is how it looks ingame:<br />
<br />
<youtube>2MRzYKguVFY</youtube><br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people. It will work in the same way as ordinary mods, you can install it by copying it into the <code>mods</code> folder.<br />
<br />
Here is my version: <br />
* for VS v1.9: [https://wiki.vintagestory.at/images/7/7b/Tunnler_vs1.9_v1.0.0.zip Tunnler_vs1.9_v1.0.0.zip]<br />
* for VS v1.8: [https://wiki.vintagestory.at/images/6/66/Tunnler.zip Tunnler.zip]<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4718Modding:Setting up your Development Environment2019-05-13T09:51:28Z<p>CreativeMD: /* Get the Modtemplate */</p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.5.3/VSModTemplate-v1.5.3.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (Compiled Zip) =<br />
<br />
Both dll and zip mods have their advantages and disadvantages, so why not combine them together? This project setup is very similar to zip. Instead of adding the source code to the zip file, it uses the compiled dll. This allows you to have all the dll benefits while still having the zip mod asset structure.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid> compiled</code>''<br />
<br />
Adds a compiled zip mod template to your workspace. The difference is that it uses a compiled dll instead of the actual source code. All other commands are equal to the zip ones.<br />
<br />
== Set Mod ==<br />
<br />
''Syntax: <code>set <modid> <source|compiled></code>''<br />
<br />
Sets the given zip mod either to source or compiled. This can be useful if you want to change the type of your mod later on.<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4614Modding:Setting up your Development Environment2019-05-09T15:48:08Z<p>CreativeMD: /* Get the Modtemplate */</p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.5.2/VSModTemplate-v1.5.2.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (Compiled Zip) =<br />
<br />
Both dll and zip mods have their advantages and disadvantages, so why not combine them together? This project setup is very similar to zip. Instead of adding the source code to the zip file, it uses the compiled dll. This allows you to have all the dll benefits while still having the zip mod asset structure.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid> compiled</code>''<br />
<br />
Adds a compiled zip mod template to your workspace. The difference is that it uses a compiled dll instead of the actual source code. All other commands are equal to the zip ones.<br />
<br />
== Set Mod ==<br />
<br />
''Syntax: <code>set <modid> <source|compiled></code>''<br />
<br />
Sets the given zip mod either to source or compiled. This can be useful if you want to change the type of your mod later on.<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4575Modding:Setting up your Development Environment2019-05-07T10:45:30Z<p>CreativeMD: /* Project Setup (ZIP - DLL) */</p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.5.1/VSModTemplate-v1.5.1.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (Compiled Zip) =<br />
<br />
Both dll and zip mods have their advantages and disadvantages, so why not combine them together? This project setup is very similar to zip. Instead of adding the source code to the zip file, it uses the compiled dll. This allows you to have all the dll benefits while still having the zip mod asset structure.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid> compiled</code>''<br />
<br />
Adds a compiled zip mod template to your workspace. The difference is that it uses a compiled dll instead of the actual source code. All other commands are equal to the zip ones.<br />
<br />
== Set Mod ==<br />
<br />
''Syntax: <code>set <modid> <source|compiled></code>''<br />
<br />
Sets the given zip mod either to source or compiled. This can be useful if you want to change the type of your mod later on.<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4574Modding:Setting up your Development Environment2019-05-07T10:41:26Z<p>CreativeMD: /* Get the Modtemplate */</p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.5.1/VSModTemplate-v1.5.1.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (ZIP - DLL) =<br />
<br />
Both dll and zip mods have their advantages and disadvantages, so why not combine them together? This project setup is equal to zip, but you can pack your zip in a different way. Instead of adding the source code to the zip file, it uses the compiled dll. This allows you to have all the dll benefits while still having the zip mod asset structure.<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack-dll <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>_dll.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:MagicWand_-_No_CS_File.zip&diff=4487File:MagicWand - No CS File.zip2019-05-02T08:43:03Z<p>CreativeMD: CreativeMD uploaded a new version of File:MagicWand - No CS File.zip</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Advanced_Items&diff=4486Modding:Advanced Items2019-05-02T08:42:05Z<p>CreativeMD: /* Distribution */</p>
<hr />
<div>__FORCETOC__<br />
<br />
It's highly recommended to read [[Basic Item]] first. Additionally this tutorial requires a development environment. If you don't have one already you should read the tutorial [[Setting up your Development Environment]].<br />
<br />
= Tunnel pickaxe =<br />
<br />
Let's create an item, which allows you to dig a 3x3 tunnel by mining just one block.<br />
<br />
== Item Assets ==<br />
<br />
First of all we need to create a new item, including a texture and a lang file. Those assets are pretty straight forward and you can download them [https://wiki.vintagestory.at/images/c/cd/Tunnler_-_No_CS_File.zip here]. Just place the file in your mods folder and you are ready to start programming.<br />
<br />
There is only one new property in your json item file called <code>class</code>:<br />
<syntaxhighlight lang="json"><br />
class: "tunnler",<br />
</syntaxhighlight><br />
<br />
We will create this class, to give the item the desired functionality, so if you pick a different name make sure it matches the one below.<br />
<br />
== The Item Class ==<br />
<br />
If you have read the [[Advanced Blocks]] Tutorial already, this should be fimilar to you.<br />
<br />
In order to register your item class, we need to create a mod, which is basically a class exendting ModBase:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerMod : ModBase<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
By overriding the <code>Start(ICoreAPI)</code> method, we can register our class. Remember if you have picked a different class name you have to use that one instead.<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerMod : ModBase<br />
{<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("tunnler", typeof(TunnlerItem));<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
This should be marked as a syntax error because there is no <code>TunnlerItem</code> class yet.<br />
<br />
=== The Item Class ===<br />
<br />
Let's create our item class itself which of course has to extend <code>Item</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerItem : Item<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
This should solve all syntax errors.<br />
<br />
'''So what should our tool do?''' Once the player mines a block with this tool every block around it should be mined as well. This is rather easy to implement by overriding the method <code>void OnBlockBroken(IWorldAccessor world, IEntity byEntity, IItemSlot itemslot, BlockSelection blockSel)</code>.<br />
<br />
We need to take care of the facing (which side the player is focusing) and if the player is in creative or survival mode (whether items should be dropped or not). Before we are going to override OnBlockBroken we should create a method which destroys all blocks between two block positions (min & max). It should also only drop items if the player is in survival mode:<br />
<br />
<syntaxhighlight lang="c#"><br />
public void destroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player)<br />
{<br />
BlockPos tempPos = new BlockPos();<br />
for (int x = min.X; x <= max.X; x++)<br />
{<br />
for (int y = min.Y; y <= max.Y; y++)<br />
{<br />
for (int z = min.Z; z <= max.Z; z++)<br />
{<br />
tempPos.Set(x, y, z);<br />
if (player.WorldData.CurrentGameMode == EnumGameMode.Creative)<br />
world.BlockAccessor.SetBlock(0, tempPos);<br />
else<br />
world.BlockAccessor.BreakBlock(tempPos, player);<br />
}<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
Now we can implement <code>OnBlockBroken</code> rather easily, by taken care of every possible axis the player could face:<br />
<syntaxhighlight lang="c#"><br />
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel)<br />
{<br />
if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel))<br />
{<br />
if (byEntity is EntityPlayer)<br />
{<br />
IPlayer player = world.PlayerByUid((byEntity as EntityPlayer).PlayerUID);<br />
switch (blockSel.Face.Axis)<br />
{<br />
case EnumAxis.X:<br />
destroyBlocks(world, blockSel.Position.AddCopy(0, -1, -1), blockSel.Position.AddCopy(0, 1, 1), player);<br />
break;<br />
case EnumAxis.Y:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, 0, -1), blockSel.Position.AddCopy(1, 0, 1), player);<br />
break;<br />
case EnumAxis.Z:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, -1, 0), blockSel.Position.AddCopy(1, 1, 0), player);<br />
break;<br />
}<br />
}<br />
return true;<br />
}<br />
return false; <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
----<br />
<br />
If you have done everything right, your file should look similar to this:<br />
<syntaxhighlight lang="c#"><br />
using Vintagestory.API.Common;<br />
using Vintagestory.API.Common.Entities;<br />
using Vintagestory.API.MathTools;<br />
<br />
namespace ExampleMods<br />
{<br />
public class TunnlerMod : ModBase<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("tunnler", typeof(TunnlerItem));<br />
}<br />
<br />
}<br />
<br />
public class TunnlerItem : Item<br />
{<br />
<br />
public void destroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player)<br />
{<br />
BlockPos tempPos = new BlockPos();<br />
for (int x = min.X; x <= max.X; x++)<br />
{<br />
for (int y = min.Y; y <= max.Y; y++)<br />
{<br />
for (int z = min.Z; z <= max.Z; z++)<br />
{<br />
tempPos.Set(x, y, z);<br />
if (player.WorldData.CurrentGameMode == EnumGameMode.Creative)<br />
world.BlockAccessor.SetBlock(0, tempPos);<br />
else<br />
world.BlockAccessor.BreakBlock(tempPos, player);<br />
}<br />
}<br />
}<br />
}<br />
<br />
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel)<br />
{<br />
if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel))<br />
{<br />
if (byEntity is EntityPlayer)<br />
{<br />
IPlayer player = world.PlayerByUid((byEntity as EntityPlayer).PlayerUID);<br />
switch (blockSel.Face.Axis)<br />
{<br />
case EnumAxis.X:<br />
destroyBlocks(world, blockSel.Position.AddCopy(0, -1, -1), blockSel.Position.AddCopy(0, 1, 1), player);<br />
break;<br />
case EnumAxis.Y:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, 0, -1), blockSel.Position.AddCopy(1, 0, 1), player);<br />
break;<br />
case EnumAxis.Z:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, -1, 0), blockSel.Position.AddCopy(1, 1, 0), player);<br />
break;<br />
}<br />
}<br />
return true;<br />
}<br />
return false; <br />
}<br />
<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
You can also download the file directly: [https://wiki.vintagestory.at/images/a/ad/Tunnler.cs Tunnler.cs].<br />
<br />
== Testing ==<br />
<br />
This is how it looks ingame:<br />
<br />
<youtube>2MRzYKguVFY</youtube><br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people. It will work in the same way as ordinary mods, you can install it by copying it into the <code>mods</code> folder.<br />
<br />
Here is my version: <br />
* for VS v1.9: [https://wiki.vintagestory.at/images/7/7b/Tunnler_vs1.9_v1.0.0.zip Tunnler_vs1.9_v1.0.0.zip]<br />
* for VS v1.8: [https://wiki.vintagestory.at/images/6/66/Tunnler.zip Tunnler.zip]<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Block_and_Item_Interactions&diff=4485Modding:Block and Item Interactions2019-05-02T08:41:48Z<p>CreativeMD: /* Download */</p>
<hr />
<div>This tutorial should introduce you into the basics of custom interactions. We will create a magic wand which should spawn particles when holding right click.<br />
<br />
== Preparations ==<br />
<br />
I highly recommend to read about [[Advanced Items|The Item Class]] first. Additionally you can download the assets [https://wiki.vintagestory.at/images/4/4d/MagicWand_-_No_CS_File.zip here].<br />
<br />
All of this should be familiar to you, creating and registering the item class ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public class Magic : ModBase<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("ItemMagicWand", typeof(ItemMagicWand));<br />
}<br />
<br />
}<br />
<br />
public class ItemMagicWand : Item<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
== Adding particles ==<br />
<br />
Now we need to implement the interact function. First of all we need to specify that the player can "use" this tool, therefore we need to set handling to <code>handled</code> ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void OnHeldInteractStart(ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handling)<br />
{<br />
handling = EnumHandHandling.Handled;<br />
}<br />
</syntaxhighlight><br />
<br />
The method <code>OnHeldInteractStep</code> allows us to spawn particles per tick while the player is using the item, but it would be better to implement an animation first. Particles should spawn after the animation is done ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)<br />
{<br />
if (byEntity.World is IClientWorldAccessor)<br />
{<br />
ModelTransform tf = new ModelTransform();<br />
tf.EnsureDefaultValues();<br />
<br />
tf.Origin.Set(0, -1, 0);<br />
tf.Rotation.Z = Math.Min(30, secondsUsed * 40);<br />
byEntity.Controls.UsingHeldItemTransformAfter = tf;<br />
}<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
Holding rightclick ...<br />
<br />
[[File:Magic Stick Interact.gif|300px]]<br />
<br />
So let's start to mess around with particles, therefore we need a static particle type ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public static SimpleParticleProperties particles = new SimpleParticleProperties(<br />
1, 1,<br />
ColorUtil.ColorFromArgb(50, 220, 220, 220),<br />
new Vec3d(),<br />
new Vec3d(),<br />
new Vec3f(-0.25f, 0.1f, -0.25f),<br />
new Vec3f(0.25f, 0.1f, 0.25f),<br />
1.5f,<br />
-0.075f,<br />
0.25f,<br />
0.25f,<br />
EnumParticleModel.Quad<br />
);<br />
</syntaxhighlight><br />
<br />
Particles should spawn once the animation is completed. This will be the case after <code>0.6</code> seconds ...<br />
<br />
<syntaxhighlight lang="c#"><br />
if (secondsUsed > 0.6)<br />
{<br />
//Spawn particles<br />
}<br />
</syntaxhighlight><br />
<br />
I suggest to read the tutorial about [[Simple Particles]] first. This code will spawn particles in front of the player with a randomized color and a sinus evolving size ...<br />
<br />
<syntaxhighlight lang="c#"><br />
Vec3d pos =<br />
byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight(), 0)<br />
.Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)<br />
;<br />
<br />
Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();<br />
particles.minVelocity = speedVec;<br />
Random rand = new Random();<br />
particles.color = ColorUtil.ToRGBABytes(ColorUtil.ColorFromArgb(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255)));<br />
particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);<br />
particles.addPos.Set(0.1, 0.1, 0.1);<br />
particles.minSize = 0.1F;<br />
particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);<br />
byEntity.World.SpawnParticles(particles);<br />
</syntaxhighlight><br />
<br />
If we put everything together the <code>OnHeldInteractStep</code> method will look like this ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)<br />
{<br />
if (byEntity.World is IClientWorldAccessor)<br />
{<br />
ModelTransform tf = new ModelTransform();<br />
tf.EnsureDefaultValues();<br />
<br />
tf.Origin.Set(0, -1, 0);<br />
tf.Rotation.Z = Math.Min(30, secondsUsed * 40);<br />
byEntity.Controls.UsingHeldItemTransformAfter = tf;<br />
<br />
if (secondsUsed > 0.6)<br />
{<br />
Vec3d pos =<br />
byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight, 0)<br />
.Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)<br />
;<br />
<br />
Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();<br />
particles.minVelocity = speedVec;<br />
Random rand = new Random();<br />
particles.color = ColorUtil.ToRgba(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255));<br />
particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);<br />
particles.addPos.Set(0.1, 0.1, 0.1);<br />
particles.minSize = 0.1F;<br />
particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);<br />
byEntity.World.SpawnParticles(particles);<br />
}<br />
}<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing ==<br />
<br />
Now we can run our first test, doesn't it look beautiful?<br />
<br />
<youtube>bTPXL97Gfns</youtube><br />
<br />
== Download ==<br />
<br />
Feel free to try it out yourself:<br />
<br />
Here is my version: <br />
* for VS v1.9: [https://wiki.vintagestory.at/images/7/72/Magicwand_vs1.9_v1.0.0.zip Magicwand_vs1.9_v1.0.0.zip]<br />
* for VS v1.8: [https://wiki.vintagestory.at/images/3/38/MagicWand.zip MagicWand.zip]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Magicwand_vs1.9_v1.0.0.zip&diff=4484File:Magicwand vs1.9 v1.0.0.zip2019-05-02T08:41:05Z<p>CreativeMD: Category:Tutorial Files</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Block_and_Item_Interactions&diff=4483Modding:Block and Item Interactions2019-05-02T08:40:06Z<p>CreativeMD: /* Adding particles */</p>
<hr />
<div>This tutorial should introduce you into the basics of custom interactions. We will create a magic wand which should spawn particles when holding right click.<br />
<br />
== Preparations ==<br />
<br />
I highly recommend to read about [[Advanced Items|The Item Class]] first. Additionally you can download the assets [https://wiki.vintagestory.at/images/4/4d/MagicWand_-_No_CS_File.zip here].<br />
<br />
All of this should be familiar to you, creating and registering the item class ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public class Magic : ModBase<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("ItemMagicWand", typeof(ItemMagicWand));<br />
}<br />
<br />
}<br />
<br />
public class ItemMagicWand : Item<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
== Adding particles ==<br />
<br />
Now we need to implement the interact function. First of all we need to specify that the player can "use" this tool, therefore we need to set handling to <code>handled</code> ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override void OnHeldInteractStart(ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel, bool firstEvent, ref EnumHandHandling handling)<br />
{<br />
handling = EnumHandHandling.Handled;<br />
}<br />
</syntaxhighlight><br />
<br />
The method <code>OnHeldInteractStep</code> allows us to spawn particles per tick while the player is using the item, but it would be better to implement an animation first. Particles should spawn after the animation is done ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)<br />
{<br />
if (byEntity.World is IClientWorldAccessor)<br />
{<br />
ModelTransform tf = new ModelTransform();<br />
tf.EnsureDefaultValues();<br />
<br />
tf.Origin.Set(0, -1, 0);<br />
tf.Rotation.Z = Math.Min(30, secondsUsed * 40);<br />
byEntity.Controls.UsingHeldItemTransformAfter = tf;<br />
}<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
Holding rightclick ...<br />
<br />
[[File:Magic Stick Interact.gif|300px]]<br />
<br />
So let's start to mess around with particles, therefore we need a static particle type ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public static SimpleParticleProperties particles = new SimpleParticleProperties(<br />
1, 1,<br />
ColorUtil.ColorFromArgb(50, 220, 220, 220),<br />
new Vec3d(),<br />
new Vec3d(),<br />
new Vec3f(-0.25f, 0.1f, -0.25f),<br />
new Vec3f(0.25f, 0.1f, 0.25f),<br />
1.5f,<br />
-0.075f,<br />
0.25f,<br />
0.25f,<br />
EnumParticleModel.Quad<br />
);<br />
</syntaxhighlight><br />
<br />
Particles should spawn once the animation is completed. This will be the case after <code>0.6</code> seconds ...<br />
<br />
<syntaxhighlight lang="c#"><br />
if (secondsUsed > 0.6)<br />
{<br />
//Spawn particles<br />
}<br />
</syntaxhighlight><br />
<br />
I suggest to read the tutorial about [[Simple Particles]] first. This code will spawn particles in front of the player with a randomized color and a sinus evolving size ...<br />
<br />
<syntaxhighlight lang="c#"><br />
Vec3d pos =<br />
byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight(), 0)<br />
.Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)<br />
;<br />
<br />
Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();<br />
particles.minVelocity = speedVec;<br />
Random rand = new Random();<br />
particles.color = ColorUtil.ToRGBABytes(ColorUtil.ColorFromArgb(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255)));<br />
particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);<br />
particles.addPos.Set(0.1, 0.1, 0.1);<br />
particles.minSize = 0.1F;<br />
particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);<br />
byEntity.World.SpawnParticles(particles);<br />
</syntaxhighlight><br />
<br />
If we put everything together the <code>OnHeldInteractStep</code> method will look like this ...<br />
<br />
<syntaxhighlight lang="c#"><br />
public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)<br />
{<br />
if (byEntity.World is IClientWorldAccessor)<br />
{<br />
ModelTransform tf = new ModelTransform();<br />
tf.EnsureDefaultValues();<br />
<br />
tf.Origin.Set(0, -1, 0);<br />
tf.Rotation.Z = Math.Min(30, secondsUsed * 40);<br />
byEntity.Controls.UsingHeldItemTransformAfter = tf;<br />
<br />
if (secondsUsed > 0.6)<br />
{<br />
Vec3d pos =<br />
byEntity.Pos.XYZ.Add(0, byEntity.EyeHeight, 0)<br />
.Ahead(1f, byEntity.Pos.Pitch, byEntity.Pos.Yaw)<br />
;<br />
<br />
Vec3f speedVec = new Vec3d(0, 0, 0).Ahead(5, byEntity.Pos.Pitch, byEntity.Pos.Yaw).ToVec3f();<br />
particles.minVelocity = speedVec;<br />
Random rand = new Random();<br />
particles.color = ColorUtil.ToRgba(255, rand.Next(0, 255), rand.Next(0, 255), rand.Next(0, 255));<br />
particles.minPos = pos.AddCopy(-0.05, -0.05, -0.05);<br />
particles.addPos.Set(0.1, 0.1, 0.1);<br />
particles.minSize = 0.1F;<br />
particles.SizeEvolve = EvolvingNatFloat.create(EnumTransformFunction.SINUS, 10);<br />
byEntity.World.SpawnParticles(particles);<br />
}<br />
}<br />
return true;<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing ==<br />
<br />
Now we can run our first test, doesn't it look beautiful?<br />
<br />
<youtube>bTPXL97Gfns</youtube><br />
<br />
== Download ==<br />
<br />
Feel free to try it out yourself:<br />
<br />
[https://wiki.vintagestory.at/images/3/38/MagicWand.zip MagicWand.zip]<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Advanced_Blocks&diff=4482Modding:Advanced Blocks2019-05-02T08:37:18Z<p>CreativeMD: /* Distribution */</p>
<hr />
<div>__FORCETOC__<br />
<br />
It's highly recommended to read [[Basic Block]] first. Additionally this tutorial requires a development environment. If you don't have one already you should read the tutorial [[Setting up your Development Environment]].<br />
<br />
= Trampoline =<br />
<br />
In this tutorial will we create something more advanced. A block with functionality ... a trampoline!<br />
<br />
== Block Assets ==<br />
<br />
The first thing we are going to need are the assets of the block. Those are pretty straight forward. <br />
<br />
The only new property is the <code>class</code>:<br />
<syntaxhighlight lang="json"><br />
class: "trampoline",<br />
</syntaxhighlight><br />
<br />
We will create this class, to give the block the desired functionality, so make sure if you pick a different name it matches the one below.<br />
You can download the assets of the mod [https://wiki.vintagestory.at/images/b/b9/Trampoline_-_No_CS_FILE.zip here].<br />
All you need to do is to place this zip file in your <code>assets</code> directory in your development project.<br />
<br />
== The Block Class ==<br />
<br />
Now we need to register our class and therefore we need to create a new <code>*.cs</code> file in our project. I'm gonna name it <code>Trampoline.cs</code>.<br />
<br />
=== The Mod System ===<br />
<br />
In order to create a mod your class needs to extend <code>ModSystem</code>. This will allow use to register all kinds of stuff, but for now we will stick to our block class example.<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TrampolineMod : ModSystem<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
Now you need to override the <code>Start(ICoreAPI)</code> method and register the class. If you have picked a different class name you have to use that one instead of trampoline.<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TrampolineMod : ModSystem<br />
{<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockClass("trampoline", typeof(TrampolineBlock));<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
This should be marked as a syntax error because there is no <code>TrampolineBlock</code> class yet.<br />
<br />
=== The Block Class ===<br />
<br />
Let's create our block class itself which of course has to extend <code>Block</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TrampolineBlock : Block<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
This should solve all syntax errors.<br />
<br />
So how do we implement a bouncy block? It's pretty helpful to take a look at the [https://apidocs.vintagestory.at/api/Vintagestory.API.Common.Block.html api documentation] to find a proper way to implement it.<br />
<br />
The method <code>void onEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, bool isImpact)</code> seems to be a good way to implement a bouncy functionality.<br />
<br />
'''When should an entity bounce?'''<br />
# The entity should bounce in the moment it lands on top of the block and not if it is standing on it already. Therefore <code>isImpact</code> has to be <code>true</code><br />
# If the entity is colliding vertically. The sides of the block shouldn't push an entity away. So the <code>axis</code> of the <code>facing</code> has to be <code>Y</code>.<br />
<br />
'''How can we make the entity bounce?'''<br />
In order to make an entity bounce, we need to change its direction. Therefore we can simply revert its motion. The faster the entity will be when during the collision the further it will be pushed away. But simply reverting the motion wouldn't be ideal. The entity would never lose its motion and bounce endless. So let's go for something smaller and make the entity lose 20% of its motion each bounce:<br />
<syntaxhighlight lang="c#"><br />
entity.Pos.Motion.Y *= -0.8;<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TrampolineBlock : Block<br />
{<br />
public override void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact)<br />
{<br />
if (isImpact && facing.Axis == EnumAxis.Y)<br />
{<br />
world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);<br />
entity.Pos.Motion.Y *= -0.8;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
Although this code works already, some sound effects would be rather nice. We can implement it by adding a sound link field to our block, which can use to play the <code>game:tick</code> sound.<br />
<br />
<syntaxhighlight lang="c#"><br />
public AssetLocation tickSound = new AssetLocation("game", "tick");<br />
</syntaxhighlight><br />
<br />
This <code>tickSound</code> will played every time an entity bounces:<br />
<br />
<syntaxhighlight lang="c#"><br />
world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
If you have done everything right, your file should look similar to this:<br />
<syntaxhighlight lang="c#"><br />
using Vintagestory.API.Common;<br />
using Vintagestory.API.Common.Entities;<br />
using Vintagestory.API.MathTools;<br />
<br />
namespace VSExampleMods<br />
{<br />
public class TrampolineMod : ModSystem<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockClass("trampoline", typeof(TrampolineBlock));<br />
}<br />
}<br />
<br />
public class TrampolineBlock : Block<br />
{<br />
public AssetLocation tickSound = new AssetLocation("game", "tick");<br />
<br />
public override void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact)<br />
{<br />
if (isImpact && facing.Axis == EnumAxis.Y)<br />
{<br />
world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);<br />
entity.Pos.Motion.Y *= -0.8;<br />
}<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
Of course you can download the file directly [https://wiki.vintagestory.at/images/8/8a/Trampoline.cs Trampoline.cs].<br />
<br />
== Testing ==<br />
<br />
Finally we can run our first test. Looks pretty good, right?<br />
<br />
<youtube>Kg8J_rNOweU</youtube><br />
<br />
'''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.<br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people. It will work in the same way as ordinary mods, you can install it by copying it into the <code>mods</code> folder.<br />
<br />
Here is my version: <br />
* for VS v1.9: [https://wiki.vintagestory.at/images/2/24/Trampoline_vs1.9_v1.0.0.zip Trampoline_vs1.9_v1.0.0.zip]<br />
* for VS v1.5: [https://wiki.vintagestory.at/images/c/ce/Trampoline.zip Trampoline.zip]<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Trampoline_vs1.9_v1.0.0.zip&diff=4481File:Trampoline vs1.9 v1.0.0.zip2019-05-02T08:36:44Z<p>CreativeMD: Category:Tutorial Files</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Trampoline.cs&diff=4480File:Trampoline.cs2019-05-02T08:36:12Z<p>CreativeMD: CreativeMD uploaded a new version of File:Trampoline.cs</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Advanced_Blocks&diff=4479Modding:Advanced Blocks2019-05-02T08:35:29Z<p>CreativeMD: /* The Block Class */</p>
<hr />
<div>__FORCETOC__<br />
<br />
It's highly recommended to read [[Basic Block]] first. Additionally this tutorial requires a development environment. If you don't have one already you should read the tutorial [[Setting up your Development Environment]].<br />
<br />
= Trampoline =<br />
<br />
In this tutorial will we create something more advanced. A block with functionality ... a trampoline!<br />
<br />
== Block Assets ==<br />
<br />
The first thing we are going to need are the assets of the block. Those are pretty straight forward. <br />
<br />
The only new property is the <code>class</code>:<br />
<syntaxhighlight lang="json"><br />
class: "trampoline",<br />
</syntaxhighlight><br />
<br />
We will create this class, to give the block the desired functionality, so make sure if you pick a different name it matches the one below.<br />
You can download the assets of the mod [https://wiki.vintagestory.at/images/b/b9/Trampoline_-_No_CS_FILE.zip here].<br />
All you need to do is to place this zip file in your <code>assets</code> directory in your development project.<br />
<br />
== The Block Class ==<br />
<br />
Now we need to register our class and therefore we need to create a new <code>*.cs</code> file in our project. I'm gonna name it <code>Trampoline.cs</code>.<br />
<br />
=== The Mod System ===<br />
<br />
In order to create a mod your class needs to extend <code>ModSystem</code>. This will allow use to register all kinds of stuff, but for now we will stick to our block class example.<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TrampolineMod : ModSystem<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
Now you need to override the <code>Start(ICoreAPI)</code> method and register the class. If you have picked a different class name you have to use that one instead of trampoline.<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TrampolineMod : ModSystem<br />
{<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockClass("trampoline", typeof(TrampolineBlock));<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
This should be marked as a syntax error because there is no <code>TrampolineBlock</code> class yet.<br />
<br />
=== The Block Class ===<br />
<br />
Let's create our block class itself which of course has to extend <code>Block</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TrampolineBlock : Block<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
This should solve all syntax errors.<br />
<br />
So how do we implement a bouncy block? It's pretty helpful to take a look at the [https://apidocs.vintagestory.at/api/Vintagestory.API.Common.Block.html api documentation] to find a proper way to implement it.<br />
<br />
The method <code>void onEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, bool isImpact)</code> seems to be a good way to implement a bouncy functionality.<br />
<br />
'''When should an entity bounce?'''<br />
# The entity should bounce in the moment it lands on top of the block and not if it is standing on it already. Therefore <code>isImpact</code> has to be <code>true</code><br />
# If the entity is colliding vertically. The sides of the block shouldn't push an entity away. So the <code>axis</code> of the <code>facing</code> has to be <code>Y</code>.<br />
<br />
'''How can we make the entity bounce?'''<br />
In order to make an entity bounce, we need to change its direction. Therefore we can simply revert its motion. The faster the entity will be when during the collision the further it will be pushed away. But simply reverting the motion wouldn't be ideal. The entity would never lose its motion and bounce endless. So let's go for something smaller and make the entity lose 20% of its motion each bounce:<br />
<syntaxhighlight lang="c#"><br />
entity.Pos.Motion.Y *= -0.8;<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TrampolineBlock : Block<br />
{<br />
public override void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact)<br />
{<br />
if (isImpact && facing.Axis == EnumAxis.Y)<br />
{<br />
world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);<br />
entity.Pos.Motion.Y *= -0.8;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
Although this code works already, some sound effects would be rather nice. We can implement it by adding a sound link field to our block, which can use to play the <code>game:tick</code> sound.<br />
<br />
<syntaxhighlight lang="c#"><br />
public AssetLocation tickSound = new AssetLocation("game", "tick");<br />
</syntaxhighlight><br />
<br />
This <code>tickSound</code> will played every time an entity bounces:<br />
<br />
<syntaxhighlight lang="c#"><br />
world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);<br />
</syntaxhighlight><br />
<br />
----<br />
<br />
If you have done everything right, your file should look similar to this:<br />
<syntaxhighlight lang="c#"><br />
using Vintagestory.API.Common;<br />
using Vintagestory.API.Common.Entities;<br />
using Vintagestory.API.MathTools;<br />
<br />
namespace VSExampleMods<br />
{<br />
public class TrampolineMod : ModSystem<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterBlockClass("trampoline", typeof(TrampolineBlock));<br />
}<br />
}<br />
<br />
public class TrampolineBlock : Block<br />
{<br />
public AssetLocation tickSound = new AssetLocation("game", "tick");<br />
<br />
public override void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact)<br />
{<br />
if (isImpact && facing.Axis == EnumAxis.Y)<br />
{<br />
world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);<br />
entity.Pos.Motion.Y *= -0.8;<br />
}<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
Of course you can download the file directly [https://wiki.vintagestory.at/images/8/8a/Trampoline.cs Trampoline.cs].<br />
<br />
== Testing ==<br />
<br />
Finally we can run our first test. Looks pretty good, right?<br />
<br />
<youtube>Kg8J_rNOweU</youtube><br />
<br />
'''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.<br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people. It will work in the same way as ordinary mods, you can install it by copying it into the <code>mods</code> folder.<br />
<br />
Here is my version: <br />
* for VS v1.9: [https://wiki.vintagestory.at/images/b/b8/Trampoline_vs1.9-1.0.0.zip Trampoline_vs1.9-1.0.0.zip]<br />
* for VS v1.5: [https://wiki.vintagestory.at/images/c/ce/Trampoline.zip Trampoline.zip]<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Tunnler_vs1.9_v1.0.0.zip&diff=4478File:Tunnler vs1.9 v1.0.0.zip2019-05-02T08:33:53Z<p>CreativeMD: Category:Tutorial Files</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Tunnler.cs&diff=4476File:Tunnler.cs2019-05-02T08:28:40Z<p>CreativeMD: CreativeMD uploaded a new version of File:Tunnler.cs</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Advanced_Items&diff=4475Modding:Advanced Items2019-05-02T08:27:25Z<p>CreativeMD: /* The Item Class */</p>
<hr />
<div>__FORCETOC__<br />
<br />
It's highly recommended to read [[Basic Item]] first. Additionally this tutorial requires a development environment. If you don't have one already you should read the tutorial [[Setting up your Development Environment]].<br />
<br />
= Tunnel pickaxe =<br />
<br />
Let's create an item, which allows you to dig a 3x3 tunnel by mining just one block.<br />
<br />
== Item Assets ==<br />
<br />
First of all we need to create a new item, including a texture and a lang file. Those assets are pretty straight forward and you can download them [https://wiki.vintagestory.at/images/c/cd/Tunnler_-_No_CS_File.zip here]. Just place the file in your mods folder and you are ready to start programming.<br />
<br />
There is only one new property in your json item file called <code>class</code>:<br />
<syntaxhighlight lang="json"><br />
class: "tunnler",<br />
</syntaxhighlight><br />
<br />
We will create this class, to give the item the desired functionality, so if you pick a different name make sure it matches the one below.<br />
<br />
== The Item Class ==<br />
<br />
If you have read the [[Advanced Blocks]] Tutorial already, this should be fimilar to you.<br />
<br />
In order to register your item class, we need to create a mod, which is basically a class exendting ModBase:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerMod : ModBase<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
By overriding the <code>Start(ICoreAPI)</code> method, we can register our class. Remember if you have picked a different class name you have to use that one instead.<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerMod : ModBase<br />
{<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("tunnler", typeof(TunnlerItem));<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
This should be marked as a syntax error because there is no <code>TunnlerItem</code> class yet.<br />
<br />
=== The Item Class ===<br />
<br />
Let's create our item class itself which of course has to extend <code>Item</code>:<br />
<br />
<syntaxhighlight lang="c#"><br />
public class TunnlerItem : Item<br />
{<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
This should solve all syntax errors.<br />
<br />
'''So what should our tool do?''' Once the player mines a block with this tool every block around it should be mined as well. This is rather easy to implement by overriding the method <code>void OnBlockBroken(IWorldAccessor world, IEntity byEntity, IItemSlot itemslot, BlockSelection blockSel)</code>.<br />
<br />
We need to take care of the facing (which side the player is focusing) and if the player is in creative or survival mode (whether items should be dropped or not). Before we are going to override OnBlockBroken we should create a method which destroys all blocks between two block positions (min & max). It should also only drop items if the player is in survival mode:<br />
<br />
<syntaxhighlight lang="c#"><br />
public void destroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player)<br />
{<br />
BlockPos tempPos = new BlockPos();<br />
for (int x = min.X; x <= max.X; x++)<br />
{<br />
for (int y = min.Y; y <= max.Y; y++)<br />
{<br />
for (int z = min.Z; z <= max.Z; z++)<br />
{<br />
tempPos.Set(x, y, z);<br />
if (player.WorldData.CurrentGameMode == EnumGameMode.Creative)<br />
world.BlockAccessor.SetBlock(0, tempPos);<br />
else<br />
world.BlockAccessor.BreakBlock(tempPos, player);<br />
}<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
Now we can implement <code>OnBlockBroken</code> rather easily, by taken care of every possible axis the player could face:<br />
<syntaxhighlight lang="c#"><br />
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel)<br />
{<br />
if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel))<br />
{<br />
if (byEntity is EntityPlayer)<br />
{<br />
IPlayer player = world.PlayerByUid((byEntity as EntityPlayer).PlayerUID);<br />
switch (blockSel.Face.Axis)<br />
{<br />
case EnumAxis.X:<br />
destroyBlocks(world, blockSel.Position.AddCopy(0, -1, -1), blockSel.Position.AddCopy(0, 1, 1), player);<br />
break;<br />
case EnumAxis.Y:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, 0, -1), blockSel.Position.AddCopy(1, 0, 1), player);<br />
break;<br />
case EnumAxis.Z:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, -1, 0), blockSel.Position.AddCopy(1, 1, 0), player);<br />
break;<br />
}<br />
}<br />
return true;<br />
}<br />
return false; <br />
}<br />
</syntaxhighlight><br />
<br />
<br />
----<br />
<br />
If you have done everything right, your file should look similar to this:<br />
<syntaxhighlight lang="c#"><br />
using Vintagestory.API.Common;<br />
using Vintagestory.API.Common.Entities;<br />
using Vintagestory.API.MathTools;<br />
<br />
namespace ExampleMods<br />
{<br />
public class TunnlerMod : ModBase<br />
{<br />
<br />
public override void Start(ICoreAPI api)<br />
{<br />
base.Start(api);<br />
api.RegisterItemClass("tunnler", typeof(TunnlerItem));<br />
}<br />
<br />
}<br />
<br />
public class TunnlerItem : Item<br />
{<br />
<br />
public void destroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player)<br />
{<br />
BlockPos tempPos = new BlockPos();<br />
for (int x = min.X; x <= max.X; x++)<br />
{<br />
for (int y = min.Y; y <= max.Y; y++)<br />
{<br />
for (int z = min.Z; z <= max.Z; z++)<br />
{<br />
tempPos.Set(x, y, z);<br />
if (player.WorldData.CurrentGameMode == EnumGameMode.Creative)<br />
world.BlockAccessor.SetBlock(0, tempPos);<br />
else<br />
world.BlockAccessor.BreakBlock(tempPos, player);<br />
}<br />
}<br />
}<br />
}<br />
<br />
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel)<br />
{<br />
if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel))<br />
{<br />
if (byEntity is EntityPlayer)<br />
{<br />
IPlayer player = world.PlayerByUid((byEntity as EntityPlayer).PlayerUID);<br />
switch (blockSel.Face.Axis)<br />
{<br />
case EnumAxis.X:<br />
destroyBlocks(world, blockSel.Position.AddCopy(0, -1, -1), blockSel.Position.AddCopy(0, 1, 1), player);<br />
break;<br />
case EnumAxis.Y:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, 0, -1), blockSel.Position.AddCopy(1, 0, 1), player);<br />
break;<br />
case EnumAxis.Z:<br />
destroyBlocks(world, blockSel.Position.AddCopy(-1, -1, 0), blockSel.Position.AddCopy(1, 1, 0), player);<br />
break;<br />
}<br />
}<br />
return true;<br />
}<br />
return false; <br />
}<br />
<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
You can also download the file directly: [https://wiki.vintagestory.at/images/a/ad/Tunnler.cs Tunnler.cs].<br />
<br />
== Testing ==<br />
<br />
This is how it looks ingame:<br />
<br />
<youtube>2MRzYKguVFY</youtube><br />
<br />
== Distribution ==<br />
<br />
In order to finish everything, open the modtools and type in <code>pack <your mod id></code>. Now you can take the zip file and share it with other people. It will work in the same way as ordinary mods, you can install it by copying it into the <code>mods</code> folder.<br />
<br />
Here is the complete example mod: [https://wiki.vintagestory.at/images/6/66/Tunnler.zip Tunnler.zip]<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4474Modding:Setting up your Development Environment2019-04-29T08:54:22Z<p>CreativeMD: /* Pack */</p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.5.0/VSModTemplate-v1.5.0.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (ZIP - DLL) =<br />
<br />
Both dll and zip mods have their advantages and disadvantages, so why not combine them together? This project setup is equal to zip, but you can pack your zip in a different way. Instead of adding the source code to the zip file, it uses the compiled dll. This allows you to have all the dll benefits while still having the zip mod asset structure.<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack-dll <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>_dll.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4473Modding:Setting up your Development Environment2019-04-29T08:54:08Z<p>CreativeMD: /* Project Setup (ZIP - DLL) */</p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.5.0/VSModTemplate-v1.5.0.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (ZIP - DLL) =<br />
<br />
Both dll and zip mods have their advantages and disadvantages, so why not combine them together? This project setup is equal to zip, but you can pack your zip in a different way. Instead of adding the source code to the zip file, it uses the compiled dll. This allows you to have all the dll benefits while still having the zip mod asset structure.<br />
<br />
== Pack ==<br />
''Syntax: <code>packd-dll <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>_dll.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4472Modding:Setting up your Development Environment2019-04-29T08:49:48Z<p>CreativeMD: </p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.5.0/VSModTemplate-v1.5.0.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (ZIP - DLL) =<br />
<br />
Coming soon ...<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Setting_up_your_Development_Environment&diff=4471Modding:Setting up your Development Environment2019-04-26T10:01:31Z<p>CreativeMD: </p>
<hr />
<div><br />
== Software ==<br />
<br />
When you are ready to begin coding mods for Vintage Story, you probably would want to set up a development environment that simplifies the process of coding and testing your creations. There are several applications that aid you in the development of mods. Here are some suggestions:<br />
<br />
* [https://www.visualstudio.com/de/vs/community/ Visual Studio Community] is a free and very powerful development environment and covered in below guide. This is also the tool the Vintage Story Team uses to build the game. It also has a [https://www.visualstudio.com/vs/mac/ MacOS Version].<br />
<br />
* [https://code.visualstudio.com/ Visual Studio Code] is very a lightweight version of Visual Studio. Our precious community member [https://twitter.com/koppeh?lang=en copygirl] is using this tool and also [https://github.com/copygirl/howto-example-mod wrote a set up guide on github]<br />
<br />
* [https://www.monodevelop.com/ MonoDevelop] is another IDE that is more lightweight than Visual Studio Community.<br />
<br />
* [https://notepad-plus-plus.org/ Notepad++] your very basic text editing tool with some extra features. You can code mods in any text editor, really. It does however lack instant context sensitive feedback while programming, which is very helpful. If you choose this way, you can use the game itself to trial and error mods by reloading them while the game is running.<br />
<br />
== Install Development Tool ==<br />
<br />
VintageStory is developed in C#. Choose one of the above IDEs or other alternatives. We suggest '''Visual Studio Community''' on Windows and on Linux you may want to use '''MonoDevelop''' or '''Visual Studio Code'''.<br />
<br />
=== Installation Guide on Linux (MonoDevelop) ===<br />
<br />
'''1. Install FlatPak'''<br />
<br />
It is required to install MonoDevelop so if you already have FlatPak then you can skip this step. FlatPak have their own guides of how to install it for many distributions [http://flatpak.org/getting.html here].<br />
<br />
'''2. Install MonoDevelop'''<br />
<br />
Simply open up a terminal and run the following command:<br />
<code>flatpak install --user --from https://download.mono-project.com/repo/monodevelop.flatpakref</code><br />
<br><br />
This might take a few minutes depending on your internet connection. (The latest version at the time of writing was around 275MB.)<br />
To open up MonoDevelop enter <code>flatpak run com.xamarin.MonoDevelop</code> in the terminal.<br />
<br />
== Get the Modtemplate ==<br />
<br />
To get started download the VSModTemplate solution ([https://github.com/anegostudios/vsmodtemplate/releases/download/1.4.1/VSModTemplate-v1.4.1.zip here]). Now you simply need to extract the zip archive to your desired place:<br />
<br />
[[File:VSMods9.png]]<br />
<br />
Navigate to <code>VSMods</code> and double click <code>VSMods.sln</code> (only works if VisualStudio is installed). Alternatively you can also start VisualStudio hit <code>Open Project/ Solution</code>, navigate to the extracted folder and select <code>VSMods.sln</code>.<br />
<br />
But before you can start to work, you have to set up the ModTools first.<br />
<br />
== Run ModTools ==<br />
<br />
The ModTools allow you to do various tasks rather easily by typing in a command. Each platform requires a different way to start it.<br />
Please note, the mod tools have only been tested with Visual Studio and MonoDevelop, but they are not required to mod the game, it merely simplifies some of the tasks.<br />
<br />
=== Windows ===<br />
<br />
Double-click <code>vsmodtools.exe</code>.<br />
<br />
=== Linux ===<br />
<br />
Open a terminal and navigate to this folder and enter <code>mono vsmodtools.exe</code>.<br />
<br />
=== Mac OS ===<br />
<br />
Double-click <code>modtools.command</code>.<br />
<br />
[[File:ModTools.png]]<br />
<br />
== Setup ==<br />
<br />
''Syntax: <code>setup [optional path]</code>''<br />
<br />
Before doing anything else you have to setup your workspace. Just type in <code>setup</code> and it will automatically try to locate your VintageStory installation directory. If it cannot find it, you will be asked to type in the full path. Once you have entered your path, it will update your project files so you can start to work with it. Now open the project again and run your first test by hitting <code>start</code> [[File:VSMods10.png]]. If everything has been done correctly VintageStory should start.<br />
<br />
= Project Setup (ZIP) =<br />
<br />
The source mod system lets you build zip mods that can ship source code besides their assets. The source code is compiled during run-time by the modloader engine. This has the great advantage of being open and easy to modify on the run but also comes with 2 major disadvantages. Up until game version 1.7.x you only have a hardcoded list of library references available to you (System.dll, System.Core.dll, System.Drawing.dll, System.Xml.dll, System.Net.Http.dll, VintagestoryAPI.dll, VSCreativeMod.dll, VSSurvivalMod.dll, VSEssentials.dll, Newtonsoft.Json.dll, protobuf-net.dll, Tavis.JsonPatch.dll, cairo-sharp.dll), any other reference will not get loaded and thus your mod would fail to compile. The second major disadvantage, affecting all game versions, is that the inbuilt source code compiler can only compile code only up until C# 6.0, so newer language features are not supported. If either of these disadvantages are a showstopper to you, we advise you to build a compiled mod.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add <modid></code>''<br />
<br />
Adds a new mod project to your workspace, also generates an <code>assets</code>, a <code>src</code> folder and a <code>modinfo.json</code> file. The mod will be added to your visual studio solution and will be loaded by VintageStory. Make sure to fill in all additional information in <code>modinfo.json</code>.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Pack Mod ==<br />
''Syntax: <code>pack <modid></code>''<br />
<br />
Creates a mod zip file and places it in <code>/releases/<modid>/<modid>_v<modversion>.zip</code>. This file is ready for use and can be shared with other people.<br />
<br />
''Syntax: <code>pack-all</code>''<br />
<br />
Packs all mods in your workspace at once.<br />
<br />
= Project Setup (ZIP - DLL) =<br />
<br />
Coming soon ...<br />
<br />
= Project Setup (DLL) =<br />
<br />
Dll mods are way more powerful than source mods, but they have two major downsides. Firstly, they are not able to carry assets which will be loaded by the game, secondly because they are so powerful they can be dangerous. Besides that dll mods can (unlike the others) have cross mod references, provide APIs and use C# 7. We recommend this type of mod for more experienced mod developers.<br />
<br />
== Add Mod ==<br />
<br />
''Syntax: <code>add-dll <modid></code>''<br />
<br />
Adds a new mod project to your workspace. A generated <code>AssemblyInfo.cs</code> file will be in your properties folder, it contains the mod information (name, author, version, description etc.) so make sure to change them before you spread the mod to other people. The mod will be added to your visual studio solution and will be loaded by VintageStory.<br />
<br />
== Delete Mod ==<br />
<br />
''Syntax: <code>delete <modid></code>''<br />
<br />
Before executing, make sure your project is closed, otherwise you might run into some difficulties. Running this command will delete the given mod completely (irreversible).<br />
<br />
== Release Mod ==<br />
<br />
Once you launch VintageStory in your workspace, the dll mod will be compiled. You can find it in your <code>mods</code> folder, with the give name: <code><modid>.dll</code>. If you want to upload this mod or share it with your friends this is the file you need to use.</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Basic_Entity&diff=4462Modding:Basic Entity2019-04-15T12:06:28Z<p>CreativeMD: /* Testing/ Distribution */</p>
<hr />
<div>__FORCETOC__<br />
<br />
We highly recommend to read the tutorial [[Getting Started with Advanced Modding#Domains|Getting Started]] first. This tutorial will cover the basics of adding an entity to the game using JSON files. There is a full list of all properties which can be defined inside the json file [[Entity Json Properties|here]].<br />
<br />
= Little Figure =<br />
<br />
The idea is create a little passive figure, made out of wood. The modid of our mod will be <code>figure</code>.<br />
<br />
== EntityType ==<br />
<br />
=== Common ===<br />
<br />
So first of all we have to create the entity type file <code>assets/figure/entities/land/littlefigure.json</code>. Now we go through all the properties:<br />
<br />
<code>code</code>: The unique identifier for your entity. A prefix of your mod id will be added automatically. Our case its <code>figure:littlefigure</code>.<br />
<br />
<code>class</code>: The class of the entity, it can be used to program special features for it. We don't need it at the moment, so we set it to <code>EntityAgent</code>.<br />
<br />
<code>hitboxSize</code>: The size of the hitbox.<br />
<br />
<syntaxhighlight lang="c#"><br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>deadHitboxSize</code>: The size of the hitbox when the entity has died.<br />
<syntaxhighlight lang="c#"><br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>eyeHeight</code>: The height of the eyes, which is <code>0.4</code> for the little figure.<br />
<br />
<code>drops</code>: A list of items to be dropped (can also include chances). We leave it empty for now: <code>[]</code>.<br />
<br />
<code>sounds</code>: Set the sounds for the entity<br />
<syntaxhighlight lang="c#"><br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
</syntaxhighlight><br />
<br />
=== Client ===<br />
<br />
The client type has different properties for client and server. This will cover the client side (rendering, shape, texture)<br />
<br />
(please note that // comments are actually not a valid json syntax, so if you want to use this json code in your projects, you'd have to remove these first)<br />
<br />
<syntaxhighlight lang="c#"><br />
"client": {<br />
"renderer": "Shape", // How the entity will be rendered, "Shape" is the right one in almost all cases.<br />
"shape": { "base": "entity/land/littlefigure" }, // a path to our shape<br />
"texture": { "base": "game:block/wood/planks/birch1" }, // the figure should have the texture of birch wood. Therefore the prefix "game" is needed<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physics to the entity<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" } // Smooths out movement of entity<br />
],<br />
"animations": [ // Animations which have to be implemented by the shape as well<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Server ===<br />
<br />
The server side handles the "brain" of the entity.<br />
<br />
<syntaxhighlight lang="c#"><br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physic interaction<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health", // Adds a health bar to the entity<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay", // Makes the dead entity stay for one hour<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn", // Makes the entity despawn if there is no player within 48 blocks<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates", // Adds different emotion states<br />
"states": [<br />
{<br />
"code": "fleeondamage", // After the entity is hit it will try to flee for 10 seconds<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai", // Handles what the entity does, a task will be processed one at a time<br />
"aitasks": [<br />
{<br />
"code": "idle", // the figure will stand still and think<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander", // The entity will walk around<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround", // The entity will look around<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Result ===<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "littlefigure",<br />
"class": "EntityAgent",<br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"eyeHeight": 0.4,<br />
"drops": [],<br />
"client": {<br />
"renderer": "Shape",<br />
"shape": { "base": "entity/land/littlefigure" },<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" }<br />
],<br />
"animations": [<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health",<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay",<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn",<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates",<br />
"states": [<br />
{<br />
"code": "fleeondamage",<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai",<br />
"aitasks": [<br />
{<br />
"code": "idle",<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander",<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround",<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
"sounds": {<br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Shape ==<br />
<br />
If you want to know how to create the shape for the entity I suggest you checkout [[VS Model Creator]].<br />
<br />
== Item ==<br />
<br />
In order to spawn the entity we can create an item to do so:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "creature",<br />
"class": "ItemCreature",<br />
"maxstacksize": 64,<br />
"variantgroups": [<br />
{<br />
"code": "type",<br />
"states": [ "figure:littlefigure" ]<br />
}<br />
],<br />
"shape": {<br />
"base": "figure:entity/land/littlefigure"<br />
},<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"creativeinventory": {<br />
"general": [ "*" ],<br />
"items": [ "*" ],<br />
"creatures": [ "*" ]<br />
},<br />
"materialDensity": 600,<br />
"guiTransform": {<br />
"rotation": {<br />
"x": 0,<br />
"y": -90,<br />
"z": -180<br />
},<br />
"origin": {<br />
"x": 0.5,<br />
"y": 0.15,<br />
"z": 0.5<br />
},<br />
"scale": 6<br />
},<br />
"fpHandTransform": {<br />
"rotation": {<br />
"x": 0,<br />
"y": -90,<br />
"z": 0<br />
},<br />
"origin": {<br />
"x": 0.5,<br />
"y": 0.15,<br />
"z": 0.5<br />
},<br />
"scale": 6<br />
},<br />
"groundTransform": {<br />
"translation": {<br />
"x": 0,<br />
"y": 0.15,<br />
"z": 0<br />
},<br />
"rotation": {<br />
"x": 0,<br />
"y": -90,<br />
"z": 0<br />
},<br />
"origin": {<br />
"x": 0.5,<br />
"y": 0.15,<br />
"z": 0.5<br />
},<br />
"scale": 6<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing/ Distribution ==<br />
<br />
<youtube>Ci9CB0fnK7U</youtube><br />
<br />
Download [https://wiki.vintagestory.at/images/d/d8/Figure_v1.0.0.zip Figure v1.0.0] for VintageStory 1.8<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Basic_Entity&diff=4459Modding:Basic Entity2019-04-15T11:10:10Z<p>CreativeMD: </p>
<hr />
<div>__FORCETOC__<br />
<br />
We highly recommend to read the tutorial [[Getting Started with Advanced Modding#Domains|Getting Started]] first. This tutorial will cover the basics of adding an entity to the game using JSON files. There is a full list of all properties which can be defined inside the json file [[Entity Json Properties|here]].<br />
<br />
= Little Figure =<br />
<br />
The idea is create a little passive figure, made out of wood. The modid of our mod will be <code>figure</code>.<br />
<br />
== EntityType ==<br />
<br />
=== Common ===<br />
<br />
So first of all we have to create the entity type file <code>assets/figure/entities/land/littlefigure.json</code>. Now we go through all the properties:<br />
<br />
<code>code</code>: The unique identifier for your entity. A prefix of your mod id will be added automatically. Our case its <code>figure:littlefigure</code>.<br />
<br />
<code>class</code>: The class of the entity, it can be used to program special features for it. We don't need it at the moment, so we set it to <code>EntityAgent</code>.<br />
<br />
<code>hitboxSize</code>: The size of the hitbox.<br />
<br />
<syntaxhighlight lang="c#"><br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>deadHitboxSize</code>: The size of the hitbox when the entity has died.<br />
<syntaxhighlight lang="c#"><br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>eyeHeight</code>: The height of the eyes, which is <code>0.4</code> for the little figure.<br />
<br />
<code>drops</code>: A list of items to be dropped (can also include chances). We leave it empty for now: <code>[]</code>.<br />
<br />
<code>sounds</code>: Set the sounds for the entity<br />
<syntaxhighlight lang="c#"><br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
</syntaxhighlight><br />
<br />
=== Client ===<br />
<br />
The client type has different properties for client and server. This will cover the client side (rendering, shape, texture):<br />
<br />
<syntaxhighlight lang="c#"><br />
"client": {<br />
"renderer": "Shape", // How the entity will be rendered, "Shape" is the right one in almost all cases.<br />
"shape": { "base": "entity/land/littlefigure" }, // a path to our shape<br />
"texture": { "base": "game:block/wood/planks/birch1" }, // the figure should have the texture of birch wood. Therefore the prefix "game" is needed<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physics to the entity<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" } // Smooths out movement of entity<br />
],<br />
"animations": [ // Animations which have to be implemented by the shape as well<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Server ===<br />
<br />
The server side handles the "brain" of the entity.<br />
<br />
<syntaxhighlight lang="c#"><br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physic interaction<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health", // Adds a health bar to the entity<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay", // Makes the dead entity stay for one hour<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn", // Makes the entity despawn if there is no player within 48 blocks<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates", // Adds different emotion states<br />
"states": [<br />
{<br />
"code": "fleeondamage", // After the entity is hit it will try to flee for 10 seconds<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai", // Handles what the entity does, a task will be processed one at a time<br />
"aitasks": [<br />
{<br />
"code": "idle", // the figure will stand still and think<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander", // The entity will walk around<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround", // The entity will look around<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Result ===<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "littlefigure",<br />
"class": "EntityAgent",<br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"eyeHeight": 0.4,<br />
"drops": [],<br />
"client": {<br />
"renderer": "Shape",<br />
"shape": { "base": "entity/land/littlefigure" },<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" }<br />
],<br />
"animations": [<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health",<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay",<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn",<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates",<br />
"states": [<br />
{<br />
"code": "fleeondamage",<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai",<br />
"aitasks": [<br />
{<br />
"code": "idle",<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander",<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround",<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
"sounds": {<br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Shape ==<br />
<br />
If you want to know how to create the shape for the entity I suggest you checkout [[VS Model Creator]].<br />
<br />
== Item ==<br />
<br />
In order to spawn the entity we can create an item to do so:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "creature",<br />
"class": "ItemCreature",<br />
"maxstacksize": 64,<br />
"variantgroups": [<br />
{<br />
"code": "type",<br />
"states": [ "figure:littlefigure" ]<br />
}<br />
],<br />
"shape": {<br />
"base": "figure:entity/land/littlefigure"<br />
},<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"creativeinventory": {<br />
"general": [ "*" ],<br />
"items": [ "*" ],<br />
"creatures": [ "*" ]<br />
},<br />
"materialDensity": 600,<br />
"guiTransform": {<br />
"rotation": {<br />
"x": 0,<br />
"y": -90,<br />
"z": -180<br />
},<br />
"origin": {<br />
"x": 0.5,<br />
"y": 0.15,<br />
"z": 0.5<br />
},<br />
"scale": 6<br />
},<br />
"fpHandTransform": {<br />
"rotation": {<br />
"x": 0,<br />
"y": -90,<br />
"z": 0<br />
},<br />
"origin": {<br />
"x": 0.5,<br />
"y": 0.15,<br />
"z": 0.5<br />
},<br />
"scale": 6<br />
},<br />
"groundTransform": {<br />
"translation": {<br />
"x": 0,<br />
"y": 0.15,<br />
"z": 0<br />
},<br />
"rotation": {<br />
"x": 0,<br />
"y": -90,<br />
"z": 0<br />
},<br />
"origin": {<br />
"x": 0.5,<br />
"y": 0.15,<br />
"z": 0.5<br />
},<br />
"scale": 6<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Testing/ Distribution ==<br />
<br />
<youtube>Ci9CB0fnK7U</youtube><br />
<br />
Download [https://wiki.vintagestory.at/images/d/d8/Figure_v1.0.0.zip Figure v1.0.0]<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Figure_v1.0.0.zip&diff=4458File:Figure v1.0.0.zip2019-04-15T11:01:05Z<p>CreativeMD: CreativeMD uploaded a new version of File:Figure v1.0.0.zip</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Basic_Entity&diff=4457Modding:Basic Entity2019-04-15T10:49:23Z<p>CreativeMD: /* Shape */</p>
<hr />
<div>__FORCETOC__<br />
<br />
We highly recommend to read the tutorial [[Getting Started with Advanced Modding#Domains|Getting Started]] first. This tutorial will cover the basics of adding an entity to the game using JSON files. There is a full list of all properties which can be defined inside the json file [[Entity Json Properties|here]].<br />
<br />
= Little Figure =<br />
<br />
The idea is create a little passive figure, made out of wood. The modid of our mod will be <code>figure</code>.<br />
<br />
== EntityType ==<br />
<br />
=== Common ===<br />
<br />
So first of all we have to create the entity type file <code>assets/figure/entities/land/littlefigure.json</code>. Now we go through all the properties:<br />
<br />
<code>code</code>: The unique identifier for your entity. A prefix of your mod id will be added automatically. Our case its <code>figure:littlefigure</code>.<br />
<br />
<code>class</code>: The class of the entity, it can be used to program special features for it. We don't need it at the moment, so we set it to <code>EntityAgent</code>.<br />
<br />
<code>hitboxSize</code>: The size of the hitbox.<br />
<br />
<syntaxhighlight lang="c#"><br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>deadHitboxSize</code>: The size of the hitbox when the entity has died.<br />
<syntaxhighlight lang="c#"><br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>eyeHeight</code>: The height of the eyes, which is <code>0.4</code> for the little figure.<br />
<br />
<code>drops</code>: A list of items to be dropped (can also include chances). We leave it empty for now: <code>[]</code>.<br />
<br />
<code>sounds</code>: Set the sounds for the entity<br />
<syntaxhighlight lang="c#"><br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
</syntaxhighlight><br />
<br />
=== Client ===<br />
<br />
The client type has different properties for client and server. This will cover the client side (rendering, shape, texture):<br />
<br />
<syntaxhighlight lang="c#"><br />
"client": {<br />
"renderer": "Shape", // How the entity will be rendered, "Shape" is the right one in almost all cases.<br />
"shape": { "base": "entity/land/littlefigure" }, // a path to our shape<br />
"texture": { "base": "game:block/wood/planks/birch1" }, // the figure should have the texture of birch wood. Therefore the prefix "game" is needed<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physics to the entity<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" } // Smooths out movement of entity<br />
],<br />
"animations": [ // Animations which have to be implemented by the shape as well<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Server ===<br />
<br />
The server side handles the "brain" of the entity.<br />
<br />
<syntaxhighlight lang="c#"><br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physic interaction<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health", // Adds a health bar to the entity<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay", // Makes the dead entity stay for one hour<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn", // Makes the entity despawn if there is no player within 48 blocks<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates", // Adds different emotion states<br />
"states": [<br />
{<br />
"code": "fleeondamage", // After the entity is hit it will try to flee for 10 seconds<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai", // Handles what the entity does, a task will be processed one at a time<br />
"aitasks": [<br />
{<br />
"code": "idle", // the figure will stand still and think<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander", // The entity will walk around<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround", // The entity will look around<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Result ===<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "littlefigure",<br />
"class": "EntityAgent",<br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"eyeHeight": 0.4,<br />
"drops": [],<br />
"client": {<br />
"renderer": "Shape",<br />
"shape": { "base": "entity/land/littlefigure" },<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" }<br />
],<br />
"animations": [<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health",<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay",<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn",<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates",<br />
"states": [<br />
{<br />
"code": "fleeondamage",<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai",<br />
"aitasks": [<br />
{<br />
"code": "idle",<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander",<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround",<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
"sounds": {<br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Shape ==<br />
<br />
If you want to know how to create the shape for the entity I suggest you checkout [[VS Model Creator]].<br />
<br />
== Testing/ Distribution ==<br />
<br />
[https://wiki.vintagestory.at/images/d/d8/Figure_v1.0.0.zip Figure v1.0.0]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Basic_Entity&diff=4456Modding:Basic Entity2019-04-15T10:31:38Z<p>CreativeMD: /* Shape */</p>
<hr />
<div>__FORCETOC__<br />
<br />
We highly recommend to read the tutorial [[Getting Started with Advanced Modding#Domains|Getting Started]] first. This tutorial will cover the basics of adding an entity to the game using JSON files. There is a full list of all properties which can be defined inside the json file [[Entity Json Properties|here]].<br />
<br />
= Little Figure =<br />
<br />
The idea is create a little passive figure, made out of wood. The modid of our mod will be <code>figure</code>.<br />
<br />
== EntityType ==<br />
<br />
=== Common ===<br />
<br />
So first of all we have to create the entity type file <code>assets/figure/entities/land/littlefigure.json</code>. Now we go through all the properties:<br />
<br />
<code>code</code>: The unique identifier for your entity. A prefix of your mod id will be added automatically. Our case its <code>figure:littlefigure</code>.<br />
<br />
<code>class</code>: The class of the entity, it can be used to program special features for it. We don't need it at the moment, so we set it to <code>EntityAgent</code>.<br />
<br />
<code>hitboxSize</code>: The size of the hitbox.<br />
<br />
<syntaxhighlight lang="c#"><br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>deadHitboxSize</code>: The size of the hitbox when the entity has died.<br />
<syntaxhighlight lang="c#"><br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>eyeHeight</code>: The height of the eyes, which is <code>0.4</code> for the little figure.<br />
<br />
<code>drops</code>: A list of items to be dropped (can also include chances). We leave it empty for now: <code>[]</code>.<br />
<br />
<code>sounds</code>: Set the sounds for the entity<br />
<syntaxhighlight lang="c#"><br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
</syntaxhighlight><br />
<br />
=== Client ===<br />
<br />
The client type has different properties for client and server. This will cover the client side (rendering, shape, texture):<br />
<br />
<syntaxhighlight lang="c#"><br />
"client": {<br />
"renderer": "Shape", // How the entity will be rendered, "Shape" is the right one in almost all cases.<br />
"shape": { "base": "entity/land/littlefigure" }, // a path to our shape<br />
"texture": { "base": "game:block/wood/planks/birch1" }, // the figure should have the texture of birch wood. Therefore the prefix "game" is needed<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physics to the entity<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" } // Smooths out movement of entity<br />
],<br />
"animations": [ // Animations which have to be implemented by the shape as well<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Server ===<br />
<br />
The server side handles the "brain" of the entity.<br />
<br />
<syntaxhighlight lang="c#"><br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physic interaction<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health", // Adds a health bar to the entity<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay", // Makes the dead entity stay for one hour<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn", // Makes the entity despawn if there is no player within 48 blocks<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates", // Adds different emotion states<br />
"states": [<br />
{<br />
"code": "fleeondamage", // After the entity is hit it will try to flee for 10 seconds<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai", // Handles what the entity does, a task will be processed one at a time<br />
"aitasks": [<br />
{<br />
"code": "idle", // the figure will stand still and think<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander", // The entity will walk around<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround", // The entity will look around<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Result ===<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "littlefigure",<br />
"class": "EntityAgent",<br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"eyeHeight": 0.4,<br />
"drops": [],<br />
"client": {<br />
"renderer": "Shape",<br />
"shape": { "base": "entity/land/littlefigure" },<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" }<br />
],<br />
"animations": [<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health",<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay",<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn",<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates",<br />
"states": [<br />
{<br />
"code": "fleeondamage",<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai",<br />
"aitasks": [<br />
{<br />
"code": "idle",<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander",<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround",<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
"sounds": {<br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Shape ==<br />
<br />
Soon (tm) ...<br />
<br />
== Testing/ Distribution ==<br />
<br />
[https://wiki.vintagestory.at/images/d/d8/Figure_v1.0.0.zip Figure v1.0.0]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Basic_Entity&diff=4455Modding:Basic Entity2019-04-15T10:18:59Z<p>CreativeMD: </p>
<hr />
<div>__FORCETOC__<br />
<br />
We highly recommend to read the tutorial [[Getting Started with Advanced Modding#Domains|Getting Started]] first. This tutorial will cover the basics of adding an entity to the game using JSON files. There is a full list of all properties which can be defined inside the json file [[Entity Json Properties|here]].<br />
<br />
= Little Figure =<br />
<br />
The idea is create a little passive figure, made out of wood. The modid of our mod will be <code>figure</code>.<br />
<br />
== EntityType ==<br />
<br />
=== Common ===<br />
<br />
So first of all we have to create the entity type file <code>assets/figure/entities/land/littlefigure.json</code>. Now we go through all the properties:<br />
<br />
<code>code</code>: The unique identifier for your entity. A prefix of your mod id will be added automatically. Our case its <code>figure:littlefigure</code>.<br />
<br />
<code>class</code>: The class of the entity, it can be used to program special features for it. We don't need it at the moment, so we set it to <code>EntityAgent</code>.<br />
<br />
<code>hitboxSize</code>: The size of the hitbox.<br />
<br />
<syntaxhighlight lang="c#"><br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>deadHitboxSize</code>: The size of the hitbox when the entity has died.<br />
<syntaxhighlight lang="c#"><br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>eyeHeight</code>: The height of the eyes, which is <code>0.4</code> for the little figure.<br />
<br />
<code>drops</code>: A list of items to be dropped (can also include chances). We leave it empty for now: <code>[]</code>.<br />
<br />
<code>sounds</code>: Set the sounds for the entity<br />
<syntaxhighlight lang="c#"><br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
</syntaxhighlight><br />
<br />
=== Client ===<br />
<br />
The client type has different properties for client and server. This will cover the client side (rendering, shape, texture):<br />
<br />
<syntaxhighlight lang="c#"><br />
"client": {<br />
"renderer": "Shape", // How the entity will be rendered, "Shape" is the right one in almost all cases.<br />
"shape": { "base": "entity/land/littlefigure" }, // a path to our shape<br />
"texture": { "base": "game:block/wood/planks/birch1" }, // the figure should have the texture of birch wood. Therefore the prefix "game" is needed<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physics to the entity<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" } // Smooths out movement of entity<br />
],<br />
"animations": [ // Animations which have to be implemented by the shape as well<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Server ===<br />
<br />
The server side handles the "brain" of the entity.<br />
<br />
<syntaxhighlight lang="c#"><br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physic interaction<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health", // Adds a health bar to the entity<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay", // Makes the dead entity stay for one hour<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn", // Makes the entity despawn if there is no player within 48 blocks<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates", // Adds different emotion states<br />
"states": [<br />
{<br />
"code": "fleeondamage", // After the entity is hit it will try to flee for 10 seconds<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai", // Handles what the entity does, a task will be processed one at a time<br />
"aitasks": [<br />
{<br />
"code": "idle", // the figure will stand still and think<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander", // The entity will walk around<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround", // The entity will look around<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Result ===<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "littlefigure",<br />
"class": "EntityAgent",<br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"eyeHeight": 0.4,<br />
"drops": [],<br />
"client": {<br />
"renderer": "Shape",<br />
"shape": { "base": "entity/land/littlefigure" },<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" }<br />
],<br />
"animations": [<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health",<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay",<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn",<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates",<br />
"states": [<br />
{<br />
"code": "fleeondamage",<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai",<br />
"aitasks": [<br />
{<br />
"code": "idle",<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander",<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround",<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
"sounds": {<br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Shape ==<br />
<br />
== Testing/ Distribution ==<br />
<br />
[https://wiki.vintagestory.at/images/d/d8/Figure_v1.0.0.zip Figure v1.0.0]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Basic_Entity&diff=4454Modding:Basic Entity2019-04-15T10:17:48Z<p>CreativeMD: /* Testing/ Distribution */</p>
<hr />
<div>__FORCETOC__<br />
<br />
We highly recommend to read the tutorial [[Getting Started with Advanced Modding#Domains|Getting Started]] first. This tutorial will cover the basics of adding an entity to the game using JSON files. There is a full list of all properties which can be defined inside the json file [[Entity Json Properties|here]].<br />
<br />
= Little Figure =<br />
<br />
The idea is create a little passive figure, made out of wood. The modid of our mod will be <code>figure</code>.<br />
<br />
== EntityType ==<br />
<br />
=== Common ===<br />
<br />
So first of all we have to create the entity type file <code>assets/figure/entities/land/littlefigure.json</code>. Now we go through all the properties:<br />
<br />
<code>code</code>: The unique identifier for your entity. A prefix of your mod id will be added automatically. Our case its <code>figure:littlefigure</code>.<br />
<br />
<code>class</code>: The class of the entity, it can be used to program special features for it. We don't need it at the moment, so we set it to <code>EntityAgent</code>.<br />
<br />
<code>hitboxSize</code>: The size of the hitbox.<br />
<br />
<syntaxhighlight lang="c#"><br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>deadHitboxSize</code>: The size of the hitbox when the entity has died.<br />
<syntaxhighlight lang="c#"><br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>eyeHeight</code>: The height of the eyes, which is <code>0.4</code> for the little figure.<br />
<br />
<code>drops</code>: A list of items to be dropped (can also include chances). We leave it empty for now: <code>[]</code>.<br />
<br />
<code>sounds</code>: Set the sounds for the entity<br />
<syntaxhighlight lang="c#"><br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
</syntaxhighlight><br />
<br />
=== Client ===<br />
<br />
The client type has different properties for client and server. This will cover the client side (rendering, shape, texture):<br />
<br />
<syntaxhighlight lang="c#"><br />
"client": {<br />
"renderer": "Shape", // How the entity will be rendered, "Shape" is the right one in almost all cases.<br />
"shape": { "base": "entity/land/littlefigure" }, // a path to our shape<br />
"texture": { "base": "game:block/wood/planks/birch1" }, // the figure should have the texture of birch wood. Therefore the prefix "game" is needed<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physics to the entity<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" } // Smooths out movement of entity<br />
],<br />
"animations": [ // Animations which have to be implemented by the shape as well<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Server ===<br />
<br />
The server side handles the "brain" of the entity.<br />
<br />
<syntaxhighlight lang="c#"><br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physic interaction<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health", // Adds a health bar to the entity<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay", // Makes the dead entity stay for one hour<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn", // Makes the entity despawn if there is no player within 48 blocks<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates", // Adds different emotion states<br />
"states": [<br />
{<br />
"code": "fleeondamage", // After the entity is hit it will try to flee for 10 seconds<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai", // Handles what the entity does, a task will be processed one at a time<br />
"aitasks": [<br />
{<br />
"code": "idle", // the figure will stand still and think<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander", // The entity will walk around<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround", // The entity will look around<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Result ===<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "littlefigure",<br />
"class": "EntityAgent",<br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"eyeHeight": 0.4,<br />
"drops": [],<br />
"client": {<br />
"renderer": "Shape",<br />
"shape": { "base": "entity/land/littlefigure" },<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" }<br />
],<br />
"animations": [<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health",<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay",<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn",<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates",<br />
"states": [<br />
{<br />
"code": "fleeondamage",<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai",<br />
"aitasks": [<br />
{<br />
"code": "idle",<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander",<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround",<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
"sounds": {<br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Shape ==<br />
<br />
== Behaviors ==<br />
<br />
== Testing/ Distribution ==<br />
<br />
[https://wiki.vintagestory.at/images/d/d8/Figure_v1.0.0.zip Figure v1.0.0]<br />
<br />
<br />
<br />
{{Navbox/modding|Vintage Story}}</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=File:Figure_v1.0.0.zip&diff=4453File:Figure v1.0.0.zip2019-04-15T10:17:14Z<p>CreativeMD: Category:Tutorial Files</p>
<hr />
<div>[[Category:Tutorial Files]]</div>CreativeMDhttps://wiki.vintagestory.at/index.php?title=Modding:Basic_Entity&diff=4452Modding:Basic Entity2019-04-15T10:00:29Z<p>CreativeMD: </p>
<hr />
<div>__FORCETOC__<br />
<br />
We highly recommend to read the tutorial [[Getting Started with Advanced Modding#Domains|Getting Started]] first. This tutorial will cover the basics of adding an entity to the game using JSON files. There is a full list of all properties which can be defined inside the json file [[Entity Json Properties|here]].<br />
<br />
= Little Figure =<br />
<br />
The idea is create a little passive figure, made out of wood. The modid of our mod will be <code>figure</code>.<br />
<br />
== EntityType ==<br />
<br />
=== Common ===<br />
<br />
So first of all we have to create the entity type file <code>assets/figure/entities/land/littlefigure.json</code>. Now we go through all the properties:<br />
<br />
<code>code</code>: The unique identifier for your entity. A prefix of your mod id will be added automatically. Our case its <code>figure:littlefigure</code>.<br />
<br />
<code>class</code>: The class of the entity, it can be used to program special features for it. We don't need it at the moment, so we set it to <code>EntityAgent</code>.<br />
<br />
<code>hitboxSize</code>: The size of the hitbox.<br />
<br />
<syntaxhighlight lang="c#"><br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>deadHitboxSize</code>: The size of the hitbox when the entity has died.<br />
<syntaxhighlight lang="c#"><br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
</syntaxhighlight><br />
<br />
<code>eyeHeight</code>: The height of the eyes, which is <code>0.4</code> for the little figure.<br />
<br />
<code>drops</code>: A list of items to be dropped (can also include chances). We leave it empty for now: <code>[]</code>.<br />
<br />
<code>sounds</code>: Set the sounds for the entity<br />
<syntaxhighlight lang="c#"><br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
</syntaxhighlight><br />
<br />
=== Client ===<br />
<br />
The client type has different properties for client and server. This will cover the client side (rendering, shape, texture):<br />
<br />
<syntaxhighlight lang="c#"><br />
"client": {<br />
"renderer": "Shape", // How the entity will be rendered, "Shape" is the right one in almost all cases.<br />
"shape": { "base": "entity/land/littlefigure" }, // a path to our shape<br />
"texture": { "base": "game:block/wood/planks/birch1" }, // the figure should have the texture of birch wood. Therefore the prefix "game" is needed<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physics to the entity<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" } // Smooths out movement of entity<br />
],<br />
"animations": [ // Animations which have to be implemented by the shape as well<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Server ===<br />
<br />
The server side handles the "brain" of the entity.<br />
<br />
<syntaxhighlight lang="c#"><br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics", // Adds physic interaction<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health", // Adds a health bar to the entity<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay", // Makes the dead entity stay for one hour<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck", // Fixes corpse get stuck in ground<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn", // Makes the entity despawn if there is no player within 48 blocks<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates", // Adds different emotion states<br />
"states": [<br />
{<br />
"code": "fleeondamage", // After the entity is hit it will try to flee for 10 seconds<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai", // Handles what the entity does, a task will be processed one at a time<br />
"aitasks": [<br />
{<br />
"code": "idle", // the figure will stand still and think<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander", // The entity will walk around<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround", // The entity will look around<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
</syntaxhighlight><br />
<br />
=== Result ===<br />
<br />
If we put everything together it should look like this:<br />
<br />
<syntaxhighlight lang="c#"><br />
{<br />
"code": "littlefigure",<br />
"class": "EntityAgent",<br />
"hitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"deadHitboxSize": {<br />
"x": 0.4,<br />
"y": 0.5<br />
},<br />
"eyeHeight": 0.4,<br />
"drops": [],<br />
"client": {<br />
"renderer": "Shape",<br />
"shape": { "base": "entity/land/littlefigure" },<br />
"texture": { "base": "game:block/wood/planks/birch1" },<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{ "code": "interpolateposition" }<br />
],<br />
"animations": [<br />
{<br />
"code": "hurt",<br />
"animation": "hurt",<br />
"animationSpeed": 2.2,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
},<br />
{<br />
"code": "die",<br />
"animation": "die",<br />
"animationSpeed": 1.25,<br />
"weight": 10,<br />
"blendMode": "AddAverage"<br />
}<br />
]<br />
},<br />
"server": {<br />
"behaviors": [<br />
{ "code": "repulseagents" },<br />
{<br />
"code": "controlledphysics",<br />
"stepHeight": 0.2<br />
},<br />
{<br />
"code": "health",<br />
"currenthealth": 4,<br />
"maxhealth": 4<br />
},<br />
{<br />
"code": "deaddecay",<br />
"hoursToDecay": 1<br />
},<br />
{<br />
"code": "floatupwhenstuck",<br />
"onlyWhenDead": true<br />
},<br />
{<br />
"code": "despawn",<br />
"minPlayerDistance": 48,<br />
"minSeconds": 5<br />
},<br />
{<br />
"code": "emotionstates",<br />
"states": [<br />
{<br />
"code": "fleeondamage",<br />
"duration": 10,<br />
"chance": 0.2,<br />
"slot": 0,<br />
"prority": 1,<br />
"accumType": "max"<br />
}<br />
]<br />
},<br />
{<br />
"code": "taskai",<br />
"aitasks": [<br />
{<br />
"code": "idle",<br />
"priority": 1.2,<br />
"priorityForCancel": 1.35,<br />
"minduration": 4000,<br />
"maxduration": 6000,<br />
"chance": 0.001,<br />
"initialMinCoolDown": 2000,<br />
"initialMaxCoolDown": 150000,<br />
"mincooldown": 300000,<br />
"maxcooldown": 10000000,<br />
"animation": "think",<br />
"animationSpeed": 1.25<br />
},<br />
{<br />
"code": "wander",<br />
"priority": 1.0,<br />
"movespeed": 0.008,<br />
"animationSpeed": 1.6,<br />
"animation": "run",<br />
"preferredLightLevel": 15<br />
},<br />
{<br />
"code": "lookaround",<br />
"priority": 0.5<br />
}<br />
]<br />
}<br />
]<br />
},<br />
"sounds": {<br />
"hurt": "creature/figure-hurt",<br />
"death": "creature/figure-death",<br />
"idle": "creature/figure-idle"<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Shape ==<br />
<br />
== Behaviors ==<br />
<br />
== Testing/ Distribution ==</div>CreativeMD