Modding:Добавление поведения Блока

From Vintage Story Wiki
Revision as of 19:55, 25 March 2024 by Lett0 (talk | contribs) (Created page with "Для того чтобы разобраться со специальными свойствами, существует метод <code>Initialize(JsonObject)</code>. Каждый blocktype создает новый экземпляр поведения, поэтому этот метод можно использовать для разбора свойств.")
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))
        {
            // 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);
        }
        // Сообщите игровому движку и другим моделям поведения блоков, что мы обработали взаимодействие игрока с блоком.
        // Если бы мы не задали поле обработки, игрок все равно смог бы ставить блоки, если бы они были у него в руках.
        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 создает новый экземпляр поведения, поэтому этот метод можно использовать для разбора свойств.

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