Modding:Adding Block Behavior/es: Difference between revisions

From Vintage Story Wiki
(Updating to match new version of source page)
(Updating to match new version of source page)
 
Line 1: Line 1:
<languages />
<languages/>
<div class="mw-translate-fuzzy">
__FORCETOC__
__FORCETOC__
{{GameVersion|1.9}}
{{GameVersion|1.19.3}}
</div>


= Introducción =
= Introduction =
Los comportamientos de bloque son útiles cuando se desea que diferentes bloques actúen de la misma manera, ya que se pueden adjuntar uno o más comportamientos de bloque a un número arbitrario de bloques.
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.
Puede que le interese echar un vistazo a las [[Block Json Properties/es#p_behaviors|comportamientos de bloque]] existentes antes de implementar las suyas propias.
You may want to have a look at the existing [[Block Json Properties#p_behaviors|block behaviors]] before implementing your own.


En este tutorial crearemos un nuevo comportamiento que podremos adjuntar a los bloques para hacerlos móviles haciendo clic con el botón derecho del ratón.


== Configuración ==
In this tutorial we'll create a new Behavior that we can attach to blocks to make them movable by right clicking them.


Se requiere un [[Setting up your Development Environment/es|espacio de trabajo de desarrollo]]. Además, necesitarás los recursos (tipo de bloque, textura y archivo lang). Se puede crear una propia o utilizar los que ya están hechos: [https://wiki.vintagestory.at/images/2/2f/Moving_-_No_CS_File.zip Moving - No CS File.zip]
== Setting up ==


== Creación del comportamiento ==
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]


Así que en primer lugar tenemos que crear el comportamiento en sí, que es una clase que extiende BlockBehavior
== Creating the behavior ==
 
So first of all we need to create the behavior itself, which is a class extending BlockBehavior
<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">
class Moving : BlockBehavior
class Moving : BlockBehavior
Line 28: Line 27:
</syntaxhighlight>
</syntaxhighlight>


Esta clase proporciona varios métodos que podemos anular. Si utilizas Visual Studio puedes encontrar una lista completa de métodos pasando el ratón por encima de "BlockBehavior" y pulsando "F12".
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".


----
----


El método <code>bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)</code> parece ideal para nuestro propósito.
The method <code>bool OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)</code> looks to be ideal for our purpose.


¿Qué debe hacer?
What should it do?


<div class="mw-translate-fuzzy">
# Calculate the new position to move the block to, based on the block face the player is looking at.
# Calcula la nueva posición del bloque en función de la cara que mire el jugador
# Check if the block can be placed at this new position.
# Comprueba si el bloque se puede colocar en esta posición
# Remove the block at the old position.
# Retira el bloque original
# Place the same type of block at the new position.
# Coloca el nuevo bloque utilizando la posición calculada anteriormente
# [[Modding:Behavior_Traversal|Skip]] the default logic that would otherwise place whatever item is held at the old position.
</div>


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
     public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)
     public override bool OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)
     {
     {
         // Encontrar la posición objetivo
         // Find the target position
         BlockPos pos = blockSel.Position.AddCopy(blockSel.Face.GetOpposite());
         BlockPos pos = blockSel.Position.AddCopy(blockSel.Face.Opposite);
 
         // Can we place the block there?
         // ¿Podemos colocar el bloque ahí?
         if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))
         if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))
         {
         {
             // Elimina el bloque de la posición actual y lo coloca en la posición de destino
             // Remove the block at the current position and place it at the target position
             world.BlockAccessor.SetBlock(0, blockSel.Position);
             world.BlockAccessor.SetBlock(0, blockSel.Position);
             world.BlockAccessor.SetBlock(block.BlockId, pos);
             world.BlockAccessor.SetBlock(block.BlockId, pos);
         }
         }
 
         // Notify the game engine other block behaviors that we handled the players interaction with the block.
         // Notificar al motor del juego otros comportamientos de bloque que manejamos la interacción de los jugadores con el bloque.
         // If we would not set the handling field the player would still be able to place blocks if he has them in hands.
         // Si no fijáramos el campo de manipulación, el jugador seguiría pudiendo colocar bloques si los tiene en las manos.
         handling = EnumHandling.PreventDefault;
         handling = EnumHandling.PreventDefault;
         return true;
         return true;
Line 64: Line 60:
</syntaxhighlight>
</syntaxhighlight>


== Registro ==
== Register ==  


Para registrar el BlockBehavior tenemos que crear una clase mod, anular <code>Start(ICoreAPI)</code> y registrarlo con el nombre dado:
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:


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 72: Line 68:
     {
     {


        public override void Start(ICoreAPI api)
public override void Start(ICoreAPI api)
         {
         {
             base.Start(api);
             base.Start(api);
Line 78: Line 74:
         }
         }


    }
}
</syntaxhighlight>
</syntaxhighlight>


== Distribución ==
== Distribution ==  


Para terminar todo, abre el modtools y teclea <code>pack <mod id></code>. Ahora puedes coger el archivo zip y compartirlo con otras personas.
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.
* para VS 1.9: [https://wiki.vintagestory.at/images/2/2a/Moving_v1.0.0.zip Moving_v1.0.0.zip]
* for VS 1.9: [https://wiki.vintagestory.at/images/2/2a/Moving_v1.0.0.zip Moving_v1.0.0.zip]
* para VS 1.6: [https://wiki.vintagestory.at/images/c/cb/Moving.zip Moving.zip]
* for VS 1.6: [https://wiki.vintagestory.at/images/c/cb/Moving.zip Moving.zip]


== Testeo ==
== Testing ==  


<youtube>8eVG0uQF2xs</youtube>
<youtube>8eVG0uQF2xs</youtube>


= Comportamiento avanzado =
= Advanced Behavior =  


Nuestro comportamiento sigue siendo bastante simple, pero hay muchas más posibilidades. Un comportamiento puede tener propiedades especiales, que pueden ser definidas por el propio tipo de bloque.
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.


=== Ejemplo ===
== Example ==  


El comportamiento líquido admite algunas propiedades especiales, como se muestra en este ejemplo del tipo de bloque agua:
The behavior liquid supports some special properties as shown in this example of the water blocktype:


<syntaxhighlight lang="json">
<syntaxhighlight lang="json">
Line 114: Line 110:
</syntaxhighlight>
</syntaxhighlight>


== Propiedades de análisis ==
== Parsing properties ==  


Para ocuparse de las propiedades especiales existe un método llamado <code>Initialize(JsonObject)</code>. Cada tipo de bloque crea una nueva instancia del comportamiento, por lo que el método se puede utilizar para analizar las propiedades.
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.


¿Qué tipo de propiedades podríamos añadir?
So what kind of properties could we add?
* distancia de empuje
* push distance
* Bloqueo si el jugador se agacha
* pull block if player is sneaking


En primer lugar, tenemos que anular el método en nuestra clase de comportamiento de bloque ...
First of all, we need to override the method in our block behavior class ...


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 131: Line 127:
</syntaxhighlight>
</syntaxhighlight>


Además necesitamos añadir dos campos, uno para la distancia y otro si el jugador acciona el bloqueo mientras se escabulle
Additionally we need to add two fields, one for the distance and another one if the player should pull the block while sneaking ...


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 138: Line 134:
</syntaxhighlight>
</syntaxhighlight>


Ahora podemos analizar las dos propiedades de la siguiente manera:
Now we can parse the two properties like so:


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 147: Line 143:
----
----


Lo siguiente que tenemos que cambiar es el propio método interact, para que se encargue de las propiedades de distancia y accionar...
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#">
<syntaxhighlight lang="c#">
         public override bool OnPlayerInteract(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)
         public override bool OnBlockInteractStart(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);
            // Find the target position
             BlockPos pos = blockSel.Position.AddCopy(pull && byPlayer.WorldData.EntityControls.Sneak ? blockSel.Face : blockSel.Face.Opposite, distance);
 
            // Can we place the block there?
             if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))
             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(0, blockSel.Position);
                 world.BlockAccessor.SetBlock(block.BlockId, pos);
                 world.BlockAccessor.SetBlock(block.BlockId, pos);
             }
             }
            // 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;
             handling = EnumHandling.PreventDefault;
             return true;
             return true;
Line 162: Line 165:
</syntaxhighlight>
</syntaxhighlight>


== Añadir otro bloque ==
== Adding another block ==  


Vamos a crear otro bloque utilizando este comportamiento, pero esta vez vamos a configurar algunas propiedades adicionales ...
Let's create another block using this behavior, but this time we will configure some additional properties ...


<syntaxhighlight lang="json">
<syntaxhighlight lang="json">
Line 178: Line 181:
</syntaxhighlight>
</syntaxhighlight>


El bloque será empujado dos bloques en lugar de uno y el jugador podrá accionarlo sigilosamente mientras hace clic con el botón derecho.
The block will be pushed two blocks instead of one and the player can pull it by sneaking while right clicking.


= Descarga de Mod =
= Mod Download =  


* para VS 1.9: [https://wiki.vintagestory.at/images/7/7b/Advancedmoving_v1.0.0.zip AdvancedMoving_v1.0.0.zip]
* for VS 1.9: [https://wiki.vintagestory.at/images/7/7b/Advancedmoving_v1.0.0.zip AdvancedMoving_v1.0.0.zip]
* para VS 1.6: [https://wiki.vintagestory.at/images/7/72/AdvancedMoving.zip AdvancedMoving.zip]
* for VS 1.6: [https://wiki.vintagestory.at/images/7/72/AdvancedMoving.zip AdvancedMoving.zip]






{{Navbox/modding|Vintage Story}}
{{Navbox/modding|Vintage Story}}

Latest revision as of 19:02, 25 March 2024

Other languages:

This page was last verified for Vintage Story version 1.19.3.


Introduction

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 behaviors before implementing your own.


In this tutorial we'll create a new Behavior that we can attach to blocks to make them movable by right clicking them.

Setting up

A 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: Moving - No CS File.zip

Creating the behavior

So first of all we need to create the behavior itself, which is a class extending BlockBehavior

class Moving : BlockBehavior
{
    public Moving(Block block) : base(block)
    {
        
    } 
}

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


The method bool OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling) looks to be ideal for our purpose.

What should it do?

  1. Calculate the new position to move the block to, based on the block face the player is looking at.
  2. Check if the block can be placed at this new position.
  3. Remove the block at the old position.
  4. Place the same type of block at the new position.
  5. Skip the default logic that would otherwise place whatever item is held at the old position.
    public override bool OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)
    {
        // Find the target position
        BlockPos pos = blockSel.Position.AddCopy(blockSel.Face.Opposite);
        // 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);
        }
        // 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;
    }

Register

In order the register the BlockBehavior we need to create a mod class, override Start(ICoreAPI) and register it with the given name:

    public class MovingBlocks : ModSystem
    {

public override void Start(ICoreAPI api)
        {
            base.Start(api);
            api.RegisterBlockBehaviorClass("Moving", typeof(Moving));
        }

}

Distribution

In order to finish everything, open the modtools and type in pack <your mod id>. Now you can take the zip file and share it with other people.

Testing

Advanced Behavior

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

The behavior liquid supports some special properties as shown in this example of the water blocktype:

	behaviors: [
		{
			name: "FiniteSpreadingLiquid", 
			properties:
			{
				spreadDelay: 150, 
				liquidCollisionSound: "hotmetal", 
				sourceReplacementCode: "obsidian", 
				flowingReplacementCode: "basalt"
			}
		}
	],

Parsing properties

In order to take care of special properties there is a method called Initialize(JsonObject). Each blocktype creates a new instance of the behavior, so the method can be used to parse the properties.

So what kind of properties could we add?

  • push distance
  • pull block if player is sneaking

First of all, we need to override the method in our block behavior class ...

        public override void Initialize(JsonObject properties)
        {
            base.Initialize(properties);
        }

Additionally we need to add two fields, one for the distance and another one if the player should pull the block while sneaking ...

        public int distance = 1;
        public bool pull = false;

Now we can parse the two properties like so:

        distance = properties["distance"].AsInt(1);
        pull = properties["pull"].AsBool(false);

The next thing we need to change is the interact method itself, so that it takes care of the distance and the pull properties ...

        public override bool OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)
        {
            // Find the target position
            BlockPos pos = blockSel.Position.AddCopy(pull && byPlayer.WorldData.EntityControls.Sneak ? blockSel.Face : blockSel.Face.Opposite, distance);

            // 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);
            }

            // 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;
        }

Adding another block

Let's create another block using this behavior, but this time we will configure some additional properties ...

	behaviors: [
		{
			name: "Moving",
			properties: {
				"distance": 2,
				"pull": true
			}
		}
	],

The block will be pushed two blocks instead of one and the player can pull it by sneaking while right clicking.

Mod Download


Icon Sign.png

Wondering where some links have gone?
The modding navbox is going through some changes! Check out Navigation Box Updates for more info and help finding specific pages.

Modding
Modding Introduction Getting Started Pack Temático
Content Modding Content Mods Developing a Content Mod Basic Tutorials Intermediate Tutorials Advanced Tutorials Content Mod Concepts
Code Modding Code Mods Setting up your Development Environment
Property Overview ItemEntityBlockBlock BehaviorsBlock ClassesBlock EntitiesBlock Entity BehaviorsWorld properties
Workflows & Infrastructure Modding Efficiency TipsMod-engine compatibilityMod ExtensibilityVS Engine
Additional Resources Community Resources Modding API Updates Programming Languages List of server commandsList of client commandsClient startup parametersServer startup parameters
Example ModsAPI DocsGitHub Repository