Modding:Adding Block Behavior/ru: Difference between revisions

From Vintage Story Wiki
(Created page with " == Настройка ==")
No edit summary
 
(32 intermediate revisions by the same user not shown)
Line 11: Line 11:
В этом уроке мы создадим новое поведение(Behavior), которое можно будет прикреплять к блокам, чтобы сделать их подвижными, нажав правую кнопку мыши.
В этом уроке мы создадим новое поведение(Behavior), которое можно будет прикреплять к блокам, чтобы сделать их подвижными, нажав правую кнопку мыши.


== Настройка ==  
== Подготовка ==  


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]
Этот руководство по '''code mod''' требует наличия среды разработки. Если у вас её еще нет, прочтите руководство по {{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]


== Creating the behavior ==  
== Создание поведения ==  


So first of all we need to create the behavior itself, which is a class extending BlockBehavior
Итак, прежде всего нам нужно создать само поведение, которое представляет собой класс, наследующийся от BlockBehavior
<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">
class Moving : BlockBehavior
class Moving : BlockBehavior
Line 28: Line 28:
</syntaxhighlight>
</syntaxhighlight>


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


----
----


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


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.
# Удалить блок в старой позиции.
# 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.
# [[Modding:Behavior_Traversal|Skip]] логика по умолчанию, которая в противном случае поместит любой удерживаемый предмет на старую позицию.


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
     public override bool OnBlockInteractStart(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.Opposite);
         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
             // Удалите блок в текущей позиции и поместите его в выбранную позицию
             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 61: Line 61:
</syntaxhighlight>
</syntaxhighlight>


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


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


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


== Distribution ==  
== Распространение ==  


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.
Чтобы закончить все, откройте modtools и введите <code>pack <your mod id></code>. Теперь вы можете взять zip-файл и поделиться им с другими людьми.
* for VS 1.9: [https://wiki.vintagestory.at/images/2/2a/Moving_v1.0.0.zip Moving_v1.0.0.zip]
* Для 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]
* Для 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 111: Line 111:
</syntaxhighlight>
</syntaxhighlight>


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


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


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 128: Line 128:
</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 135: Line 135:
</syntaxhighlight>
</syntaxhighlight>


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


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


The next thing we need to change is the interact method itself, so that it takes care of the distance and the pull properties ...
Следующее, что нам нужно изменить, - это сам метод interact, чтобы он позаботился о свойствах расстояния и притяжения...
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
         public override bool OnBlockInteractStart(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(pull && byPlayer.WorldData.EntityControls.Sneak ? blockSel.Face : blockSel.Face.Opposite, distance);
             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 166: Line 166:
</syntaxhighlight>
</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 182: Line 182:
</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 =  
= Скачать Мод =  


* for VS 1.9: [https://wiki.vintagestory.at/images/7/7b/Advancedmoving_v1.0.0.zip AdvancedMoving_v1.0.0.zip]
* Для 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]
* Для 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 20:24, 25 March 2024

Other languages:

Эта страница проверялась в последний раз для версии Vintage Story 1.19.3.


Введение

Некоторые блоки в игре имеют особое поведение, например песок, гравий могут осыпаться, это и называется поведением блока. Поведения блоков полезны, когда вы хотите, чтобы разные блоки действовали одинаково, поскольку вы можете прикрепить одно или несколько поведений к произвольному количеству блоков. Возможно, вам захочется взглянуть на существующие Поведения Блоков, прежде чем реализовывать свои собственные.


В этом уроке мы создадим новое поведение(Behavior), которое можно будет прикреплять к блокам, чтобы сделать их подвижными, нажав правую кнопку мыши.

Подготовка

Этот руководство по code mod требует наличия среды разработки. Если у вас её еще нет, прочтите руководство по настройке среды для разработки . Кроме того, вам понадобятся активы (тип блока, текстура и lang-файл). Вы можете либо создать свой собственный, либо воспользоваться готовыми: Moving - No CS File.zip

Создание поведения

Итак, прежде всего нам нужно создать само поведение, которое представляет собой класс, наследующийся от BlockBehavior

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

Этот класс предоставляет несколько методов, которые мы можем переопределить. При использовании Visual Studio вы можете найти полный список методов, наведя курсор мыши на "BlockBehavior" и нажав "F12".


Метод bool OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling) выглядит идеально подходящим для нашей цели.

Что метод должен делать?

  1. Рассчитать новую позицию для перемещения блока, основываясь на лицевой стороне блока, на которую смотрит игрок.
  2. Проверить, можно ли поместить блок в эту новую позицию.
  3. Удалить блок в старой позиции.
  4. Поместить блок того же типа на новую позицию.
  5. Skip логика по умолчанию, которая в противном случае поместит любой удерживаемый предмет на старую позицию.
    public override bool OnBlockInteractStart(IWorldAccessor world, IPlayer byPlayer, BlockSelection blockSel, ref EnumHandling handling)
    {
        // Найдите выбранную позицию
        BlockPos pos = blockSel.Position.AddCopy(blockSel.Face.Opposite);
        // Можем ли мы разместить здесь блок?
        if (world.BlockAccessor.GetBlock(pos).IsReplacableBy(block))
        {
            // Удалите блок в текущей позиции и поместите его в выбранную позицию
            world.BlockAccessor.SetBlock(0, blockSel.Position);
            world.BlockAccessor.SetBlock(block.BlockId, pos);
        }
        // Сообщите игровому движку и другим моделям поведения блоков, что мы обработали взаимодействие игрока с блоком.
        // Если бы мы не задали поле обработки, игрок все равно смог бы ставить блоки, если бы они были у него в руках.
        handling = EnumHandling.PreventDefault;
        return true;
    }

Регистрация

Чтобы зарегистрировать BlockBehavior, нам нужно создать класс мода, переопределив от Start(ICoreAPI) и зарегистрировать его с указанным именем:

    public class MovingBlocks : ModSystem
    {

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

}

Распространение

Чтобы закончить все, откройте modtools и введите pack <your mod id>. Теперь вы можете взять zip-файл и поделиться им с другими людьми.

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

Расширенное Поведение

Наше созданное поведение все еще довольно простое, но возможностей гораздо больше. Поведение может иметь особые свойства, которые могут быть определены самим типом блока.

Пример

Поведение жидкости поддерживает некоторые особые свойства, как показано в этом примере с типом блока "Вода":

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

Разбор свойств

Для того чтобы разобраться со специальными свойствами, существует метод Initialize(JsonObject). Каждый blocktype создает новый экземпляр поведения, поэтому этот метод можно использовать для разбора свойств.

Итак, какие свойства мы можем добавить?

  • Толчок блока на расстояние
  • Тянуть блок, если игрок крадется

Прежде всего, нам нужно переопределить метод в нашем классе поведения блока ...

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

Дополнительно нам нужно добавить два поля, одно для расстояния, а другое - если игрок должен потянуть за блок, когда крадется...

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

Теперь мы можем разобрать эти два свойства следующим образом:

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

Следующее, что нам нужно изменить, - это сам метод interact, чтобы он позаботился о свойствах расстояния и притяжения...

        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.Opposite, 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;
        }

Добавление другого блока

Давайте создадим еще один блок, используя это поведение, но на этот раз мы настроим некоторые дополнительные свойства ...

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

Блок будет толкать два блока вместо одного, и игрок может тянуть его, крадясь, нажимая правую кнопку мыши.

Скачать Мод


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 ItemEntityEntity BehaviorsBlockBlock BehaviorsBlock ClassesBlock EntitiesBlock Entity BehaviorsCollectible 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