Modding:Adding Block Behavior/ru: Difference between revisions

From Vintage Story Wiki
No edit summary
(Updating to match new version of source page)
Line 1: Line 1:
<languages />
<languages/>
__FORCETOC__
__FORCETOC__
{{GameVersion|1.15}}
{{GameVersion|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.
Возможно, вы захотите взглянуть на существующие [[Block Json Properties # p_behaviors | block behaviors]] перед реализацией своего собственного.
You may want to have a look at the existing [[Block Json Properties#p_behaviors|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.


Требуется ознакомится со статьёй - {{ll|Modding:Setting_up_your_Development_Environment}}. Кроме того, вам понадобятся ресурсы (тип блока, текстура и файл lang). Вы можете создать свои собственные или использовать готовые: [https://wiki.vintagestory.at/images/2/2f/Moving_-_No_CS_File.zip Moving - No CS File.zip]
== Setting up ==


== Создание поведения ==
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]


Итак, прежде всего нам нужно создать само поведение, которое является классом, расширяющим 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 26: Line 27:
</syntaxhighlight>
</syntaxhighlight>


Этот класс предоставляет несколько методов, которые мы можем переопределить. Когда вы используете Visual Studio, вы можете найти полный список методов, наведя курсор мыши на «BlockBehavior» и нажав «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".


----
----


Метод <code> bool OnPlayerInteract (IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling) </code> выглядит идеально подходящим для наших целей.
The method <code>bool OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)</code> looks to be ideal for our purpose.


Что это должно сделать?
What should it do?


# Рассчитайте новую позицию для перемещения блока на основе грани блока, на которую смотрит игрок.
# Calculate the new position to move the block to, based on the block face the player is looking at.
# Проверить, можно ли разместить блок в новой позиции.
# Check if the block can be placed at this new position.
# Удалить блок на старой позиции.
# Remove the block at the old position.
# [[Modding:Behavior_Traversal/ru|Пропустить]] логику по умолчанию, которая поместила бы любой элемент в старую позицию.
# Place the same type of block at the new position.
# [[Modding:Behavior_Traversal|Skip]] the default logic that would otherwise place whatever item is held at the old position.


<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)
     {
     {
         // Находим целевую позицию
         // 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?
         // Можем ли мы разместить блок там?
        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
             // Remove the block at the current position and place it at the target position
Line 52: Line 53:
             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;
}
    }
</syntaxhighlight>
</syntaxhighlight>


== Регистрация ==
== Register ==  


Чтобы зарегистрировать BlockBehavior, нам нужно создать класс мода, переопределить <code> Start (ICoreAPI) </code> и зарегистрировать его с заданным именем:
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 68: Line 68:
     {
     {


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


    }
}
</syntaxhighlight>
</syntaxhighlight>


== Распределение ==
== Distribution ==  


Чтобы закончить все, откройте modtools и введите <code> pack <ваш mod id> </ code>. Теперь вы можете взять zip-файл и поделиться им с другими людьми.
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.
* Для 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]
* Для 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]


== Тестирование ==
== Testing ==  


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


= Расширенное поведение =
= 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:


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


== Разбор свойств ==
== Parsing properties ==  


Чтобы позаботиться о специальных свойствах, существует метод <code> Initialize (JsonObject) </code>. Каждый тип блока создает новый экземпляр поведения, поэтому метод может использоваться для анализа свойств.
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.


Итак, какие свойства мы можем добавить?
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 ...


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


Кроме того, нам нужно добавить два поля, одно для расстояния и другое, если игрок должен вытащить блок когда крадется ...
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 134: Line 134:
</syntaxhighlight>
</syntaxhighlight>


Теперь мы можем проанализировать два свойства следующим образом:
Now we can parse the two properties like so:


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


Следующее, что нам нужно изменить, - это сам метод взаимодействия, чтобы он позаботился о расстоянии и свойствах вытягивания ...
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 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;
        }
</syntaxhighlight>


== Добавление другого блока ==
== Adding another block ==  


Давайте создадим еще один блок, используя это поведение, но на этот раз мы настроим некоторые дополнительные свойства ...
Let's create another block using this behavior, but this time we will configure some additional properties ...


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


Блок будет толкать два блока вместо одного, и игрок может тянуть его, крадясь, щелкая правой кнопкой мыши.
The block will be pushed two blocks instead of one and the player can pull it by sneaking while right clicking.


= Загрузка мода =
= Mod Download =  


* Для 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]
* Для 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}}

Revision as of 19:02, 25 March 2024

Other languages:

Эта страница проверялась в последний раз для версии Vintage Story 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 Пакет тем
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