Modding:Adding Block Behavior: Difference between revisions

From Vintage Story Wiki
Marked this version for translation
No edit summary
(Marked this version for translation)
(36 intermediate revisions by 6 users not shown)
Line 1: Line 1:
<languages />
<translate>
<!--T:1-->
__FORCETOC__
__FORCETOC__
{{GameVersion|1.9}}


= Unbreakable =
= Introduction = <!--T:2-->
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.
You may want to have a look at the existing [[Block Json Properties#p_behaviors|block behaviors]] before implementing your own.


Let's create a behavior which makes a block unbreakable even in creative mode.
<!--T:3-->
In this tutorial we'll create a new Behavior that we can attach to blocks to make them movable by right clicking them.


== Creating ==
== Setting up == <!--T:4-->


== Register ==
<!--T:5-->
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]


== Testing ==
== Creating the behavior == <!--T:6-->


= Second Behavior (using custom properties) =
<!--T:7-->
So first of all we need to create the behavior itself, which is a class extending BlockBehavior
<syntaxhighlight lang="csharp">
class Moving : BlockBehavior
{
    public Moving(Block block) : base(block)
    {
       
    }
}
</syntaxhighlight>


Still trying to find an idea.
<!--T:8-->
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".
 
<!--T:9-->
----
 
<!--T:10-->
The method <code>bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)</code> looks to be ideal for our purpose.
 
<!--T:11-->
What should it do?
 
<!--T:12-->
# Calculate the new position of the block depending on the face the player is looking at
# Check if the block can be placed at this position
# Remove the original block
# Place the new block using the previously calculated position
 
<!--T:13-->
<syntaxhighlight lang="c#">
    public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)
    {
        // Find the target position
        BlockPos pos = blockSel.Position.AddCopy(blockSel.Face.GetOpposite());
 
        <!--T:14-->
// Can we place the block there?
        if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))
        {
            // Remove the block at the current position and place it at the target position
            world.BlockAccessor.SetBlock(0, blockSel.Position);
            world.BlockAccessor.SetBlock(block.BlockId, pos);
        }
 
        <!--T:15-->
// Notify the game engine other block behaviors that we handled the players interaction with the block.
        // If we would not set the handling field the player would still be able to place blocks if he has them in hands.
        handling = EnumHandling.PreventDefault;
        return true;
    }
</syntaxhighlight>
 
== Register == <!--T:16-->
 
<!--T:17-->
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:
 
<!--T:18-->
<syntaxhighlight lang="c#">
    public class MovingBlocks : ModSystem
    {
 
        <!--T:19-->
public override void Start(ICoreAPI api)
        {
            base.Start(api);
            api.RegisterBlockBehaviorClass("Moving", typeof(Moving));
        }
 
    <!--T:20-->
}
</syntaxhighlight>
 
== Distribution == <!--T:21-->
 
<!--T:22-->
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.
* for VS 1.9: [https://wiki.vintagestory.at/images/2/2a/Moving_v1.0.0.zip Moving_v1.0.0.zip]
* for VS 1.6: [https://wiki.vintagestory.at/images/c/cb/Moving.zip Moving.zip]
 
== Testing == <!--T:23-->
 
<!--T:24-->
<youtube>8eVG0uQF2xs</youtube>
 
= Advanced Behavior = <!--T:25-->
 
<!--T:26-->
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.
 
== Example == <!--T:27-->
 
<!--T:28-->
The behavior liquid supports some special properties as shown in this example of the water blocktype:
 
<!--T:29-->
<syntaxhighlight lang="json">
behaviors: [
{
name: "FiniteSpreadingLiquid",
properties:
{
spreadDelay: 150,
liquidCollisionSound: "hotmetal",
sourceReplacementCode: "obsidian",
flowingReplacementCode: "basalt"
}
}
],
</syntaxhighlight>
 
== Parsing properties == <!--T:30-->
 
<!--T:31-->
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.
 
<!--T:32-->
So what kind of properties could we add?
* push distance
* pull block if player is sneaking
 
<!--T:33-->
First of all, we need to override the method in our block behavior class ...
 
<!--T:34-->
<syntaxhighlight lang="c#">
        public override void Initialize(JsonObject properties)
        {
            base.Initialize(properties);
        }
</syntaxhighlight>
 
<!--T:35-->
Additionally we need to add two fields, one for the distance and another one if the player should pull the block while sneaking ...
 
<!--T:36-->
<syntaxhighlight lang="c#">
        public int distance = 1;
        public bool pull = false;
</syntaxhighlight>
 
<!--T:37-->
Now we can parse the two properties like so:
 
<!--T:38-->
<syntaxhighlight lang="c#">
        distance = properties["distance"].AsInt(1);
        pull = properties["pull"].AsBool(false);
</syntaxhighlight>
 
<!--T:39-->
----
 
<!--T:40-->
The next thing we need to change is the interact method itself, so that it takes care of the distance and the pull properties ...
<syntaxhighlight lang="c#">
        public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)
        {
            BlockPos pos = blockSel.Position.AddCopy(pull && byPlayer.WorldData.EntityControls.Sneak ? blockSel.Face : blockSel.Face.GetOpposite(), distance);
            if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))
            {
                world.BlockAccessor.SetBlock(0, blockSel.Position);
                world.BlockAccessor.SetBlock(block.BlockId, pos);
            }
            handling = EnumHandling.PreventDefault;
            return true;
        }
</syntaxhighlight>
 
== Adding another block == <!--T:41-->
 
<!--T:42-->
Let's create another block using this behavior, but this time we will configure some additional properties ...
 
<!--T:43-->
<syntaxhighlight lang="json">
behaviors: [
{
name: "Moving",
properties: {
"distance": 2,
"pull": true
}
}
],
</syntaxhighlight>
 
<!--T:44-->
The block will be pushed two blocks instead of one and the player can pull it by sneaking while right clicking.
 
= Mod Download = <!--T:45-->
 
<!--T:46-->
* for VS 1.9: [https://wiki.vintagestory.at/images/7/7b/Advancedmoving_v1.0.0.zip AdvancedMoving_v1.0.0.zip]
* for VS 1.6: [https://wiki.vintagestory.at/images/7/72/AdvancedMoving.zip AdvancedMoving.zip]
 
 
 
<!--T:47-->
{{Navbox/modding|Vintage Story}}
 
 
</translate>
681

edits