Modding:Block Entity: Difference between revisions

From Vintage Story Wiki
No edit summary
Line 3: Line 3:
== Introduction ==
== Introduction ==


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.
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.


== The Texture Flipper ==
== The Texture Flipper ==


Let's take our [[Basic Modding|Basic block]] that we already created and make it flip between a gold and silver texture every 3 seconds. We'll use "Textureflipper" as our unique identifier for this new block entity.
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:
<syntaxhighlight lang="json">
entityClass: "tickingcounter",
</syntaxhighlight>
 
You can download the assets [http://wiki.vintagestory.at/images/d/d4/Ticking_-_No_CS_File.zip here] and place it in your mods directory.


== The BlockEntity ==
== The BlockEntity ==


TBD
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>.
 
First of all you need to create the blockentity class itself. Therefore you need to extend <code>BlockEntity</code>:
 
<syntaxhighlight lang="c#">
    public class TickingBlockEntity : BlockEntity
    {
   
    }
</syntaxhighlight>
 
----


== Attaching the Block Entity ==
This class needs to have a timer, once the timer reaches 3 seconds it should replace the current block with the different state.


Open the blocktype json file and add the following line. This will attach the block entity-to-be to our block.
In order to create a timer we need to register a tick listener. Therefore we need to override <code>Initialize(ICoreAPI)</code>:


The only new property is the <code>class</code>:
<syntaxhighlight lang="c#">
<syntaxhighlight lang="json">
        public override void Initialize(ICoreAPI api)
entityClass: "Textureflipper",
        {
            base.Initialize(api);
        }
</syntaxhighlight>
 
add a counter (which should increase per tick) ...
 
<syntaxhighlight lang="c#">
        public int timer;
</syntaxhighlight>
 
... and the actual ticking method ...
 
<syntaxhighlight lang="c#">
        public void onTick(float par)
        {
       
        }
</syntaxhighlight>
 
To register the ticking method we can use <code>RegisterGameTickListener</code> in <code>Inizialize</code>
 
<syntaxhighlight lang="c#">
        public override void Initialize(ICoreAPI api)
        {
            base.Initialize(api);
            RegisterGameTickListener(onTick, 20);
        }
</syntaxhighlight>
 
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:
 
<syntaxhighlight lang="c#">
        public void onTick(float par)
        {
            timer++;
            if(timer > 60)
            {
                Block block = api.World.BlockAccessor.GetBlock(pos);
                if (block.Code.Path.EndsWith("-on"))
                    block = api.World.GetBlock(block.CodeWithParts("off"));
                else
                    block = api.World.GetBlock(block.CodeWithParts("on"));
                api.World.BlockAccessor.SetBlock(block.BlockId, pos);
            }
        }
</syntaxhighlight>
 
----
 
Furthermore we need to save the current time:
 
<syntaxhighlight lang="c#">
        public override void ToTreeAttributes(ITreeAttribute tree)
        {
            base.ToTreeAttributes(tree);
            tree.SetInt("timer", timer);
        }
 
        public override void FromTreeAtributes(ITreeAttribute tree)
        {
            base.FromTreeAtributes(tree);
            timer = tree.GetInt("timer");
        }
</syntaxhighlight>
</syntaxhighlight>


== Registering the Block Entity ==
== Registering the Block Entity ==


TBD
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>:


== The Mod Class ==
<syntaxhighlight lang="c#">
    public class Ticking : ModBase
    {


TBD
        public override void Start(ICoreAPI api)
        {
            base.Start(api);
            api.RegisterBlockEntity("tickingcounter", typeof(TickingBlockEntity));
        }
 
    }
</syntaxhighlight>


== Testing ==
== Testing ==


TBD
Now everything is ready to run the first test:
 
https://youtu.be/QQUibC4H9TI


== Distribution ==
== Distribution ==


TBD
There is only one thing left to do and that is to place your *.cs file in the zip archive. Once that is done you can 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.
 
Here is my version: [http://wiki.vintagestory.at/images/6/65/Ticking.zip Ticking.zip]

Revision as of 11:16, 26 October 2017


Introduction

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 Blocks and Block Class in order to understand this tutorial properly.

The Texture Flipper

Let's create a block which switches its texture every 3 seconds. It should have two variants "on" and "off". Additionally we need to define the blockentity class like so:

	entityClass: "tickingcounter",

You can download the assets here and place it in your mods directory.

The BlockEntity

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 Ticking.cs.

First of all you need to create the blockentity class itself. Therefore you need to extend BlockEntity:

    public class TickingBlockEntity : BlockEntity
    {
    
    }

This class needs to have a timer, once the timer reaches 3 seconds it should replace the current block with the different state.

In order to create a timer we need to register a tick listener. Therefore we need to override Initialize(ICoreAPI):

        public override void Initialize(ICoreAPI api)
        {
            base.Initialize(api);
        }

add a counter (which should increase per tick) ...

        public int timer;

... and the actual ticking method ...

        public void onTick(float par)
        {
        
        }

To register the ticking method we can use RegisterGameTickListener in Inizialize

        public override void Initialize(ICoreAPI api)
        {
            base.Initialize(api);
            RegisterGameTickListener(onTick, 20);
        }

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:

        public void onTick(float par)
        {
            timer++;
            if(timer > 60)
            {
                Block block = api.World.BlockAccessor.GetBlock(pos);
                if (block.Code.Path.EndsWith("-on"))
                    block = api.World.GetBlock(block.CodeWithParts("off"));
                else
                    block = api.World.GetBlock(block.CodeWithParts("on"));
                api.World.BlockAccessor.SetBlock(block.BlockId, pos);
            }
        }

Furthermore we need to save the current time:

        public override void ToTreeAttributes(ITreeAttribute tree)
        {
            base.ToTreeAttributes(tree);
            tree.SetInt("timer", timer);
        }

        public override void FromTreeAtributes(ITreeAttribute tree)
        {
            base.FromTreeAtributes(tree);
            timer = tree.GetInt("timer");
        }

Registering the Block Entity

Registering the blockentity class is rather simple (rather similar to registering a block class). You need a mod class and override Start(ICoreAPI):

    public class Ticking : ModBase
    {

        public override void Start(ICoreAPI api)
        {
            base.Start(api);
            api.RegisterBlockEntity("tickingcounter", typeof(TickingBlockEntity));
        }

    }

Testing

Now everything is ready to run the first test:

https://youtu.be/QQUibC4H9TI

Distribution

There is only one thing left to do and that is to place your *.cs file in the zip archive. Once that is done you can 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.

Here is my version: Ticking.zip