Modding:Advanced Items/ru: Difference between revisions

From Vintage Story Wiki
(Created page with "В нашем конкретном случае мы можем переопределить метод <code>bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1)</code>.")
(Created page with "Нам нужно знать, с какой стороны стоит игрок (на какую сторону он ориентируется) и находится ли он в творческом режиме или режиме выживания (нужно ли сбрасывать добытые предметы или нет). Прежде чем переопределять <code>OnBlockBrokenWith</code>, мы должны создать метод, кото...")
Line 93: Line 93:


<!--T:25-->
<!--T:25-->
<div lang="en" dir="ltr" class="mw-content-ltr">
Нам нужно знать, с какой стороны стоит игрок (на какую сторону он ориентируется) и находится ли он в творческом режиме или режиме выживания (нужно ли сбрасывать добытые предметы или нет). Прежде чем переопределять <code>OnBlockBrokenWith</code>, мы должны создать метод, который уничтожает все блоки между двумя позициями блока (min и max). Он также должен сбрасывать предметы, только если игрок находится в режиме выживания:
We need to be aware of the facing (which side the player is focusing) and if the player is in creative or survival mode (whether items should be dropped or not). Before we are going to override <code>OnBlockBrokenWith</code> we should create a method which destroys all blocks between two block positions (min & max). It should also only drop items if the player is in survival mode:
</div>


<!--T:26-->
<!--T:26-->

Revision as of 14:52, 25 March 2024

Other languages:

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


Этот руководство по code mod требует наличия среды разработки. Если у вас её еще нет, прочтите руководство по настройке среды для разработки . Также рекомендуется сначала прочитать про Простые Предметы и изучить их устройство если вы не сделали этого ранее.

Создание Туннельной Кирки

В этом уроке мы создадим предмет с более продвинутой функциональностью: Кирка, которая позволяет вырыть туннель 3x3, добыв всего один блок.

Ассеты Предмета

Как и в случае с Простым Предметом , нам нужно создать ассеты для нашего предмета, включая тип предмета, текстуру и lang-файл. Эти ассеты довольно простые, и вы можете скачать их здесь. Распакуйте файл в папку mods, и что бы приступить к программированию.

В json вашего itemtype есть только одно новое свойство, class. Это свойство указывает нашему новому предмету, что он будет управляться определенным классом C#.

	class: "tunnler",

Мы создадим этот класс, чтобы придать предмету желаемую функциональность.

Класс Предмета

Создание нашего предмета требует создания пары новых файлов *.cs в нашем проекте.

Если вы уже читали руководство - Функциональные Блоки , это должно быть вам знакомо.

Система Мода

Для того чтобы зарегистрировать ваш класс предмета, нам нужно создать мод, который представляет собой класс, наследующийся от ModSystem:

public class TunnlerMod : ModSystem
{
    
}

Переопределив метод Start(ICoreAPI), мы можем зарегистрировать наш класс. Функция RegisterItemClass имеет два параметра: Первый - идентификатор класса предмета, поскольку именно так мы будем ссылаться на этот класс в наших json-файлах itemtype. Убедитесь, что он идентичен классу, который мы указали в нашем предыдущем файле ассетов. Второй параметр - тип нашего класса предмета.

public class TunnlerMod : ModSystem
{
    public override void Start(ICoreAPI api)
    {
        base.Start(api);
        api.RegisterItemClass("tunnler", typeof(TunnlerItem));
    }
}

Так как класса TunnlerItem ещё не существует, это место будет отображаться как синтаксическая ошибка.

Класс Предмета

При наименовании скриптов предметов рекомендуется называть их в формате "{Name}Item". В случае с туннельной киркой мы назовем наш скрипт TunnlerItem.cs. Любой itemclass должен наследоваться от Item, предоставляющий ему необходимую нам функциональность:

public class TunnlerItem : Item
{

<!--T:20-->
}

Это должно решить все синтаксические ошибки.


Так что же должен делать наш инструмент? Когда игрок добывает блок с помощью этого инструмента, все блоки вокруг него также должны быть добыты.

Как обычно, мы можем обратиться к item api docs, чтобы найти функцию, которую мы можем использовать. Хотя сам класс item не содержит соответствующей функции, мы также можем обратиться к CollectibleObject api docs, от которого класс item наследуется.

В нашем конкретном случае мы можем переопределить метод bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1).

Нам нужно знать, с какой стороны стоит игрок (на какую сторону он ориентируется) и находится ли он в творческом режиме или режиме выживания (нужно ли сбрасывать добытые предметы или нет). Прежде чем переопределять OnBlockBrokenWith, мы должны создать метод, который уничтожает все блоки между двумя позициями блока (min и max). Он также должен сбрасывать предметы, только если игрок находится в режиме выживания:

public void DestroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player)
{
    BlockPos tempPos = new BlockPos();
    for (int x = min.X; x <= max.X; x++)
    {
        for (int y = min.Y; y <= max.Y; y++)
        {
            for (int z = min.Z; z <= max.Z; z++)
            {
                tempPos.Set(x, y, z);
                if (player.WorldData.CurrentGameMode == EnumGameMode.Creative)
                    world.BlockAccessor.SetBlock(0, tempPos);
                else
                    world.BlockAccessor.BreakBlock(tempPos, player);
            }
        }
    }
}

Now we can implement OnBlockBroken rather easily, by taken care of every possible axis the player could face:

public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1)
{
    if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel))
    {
        if (byEntity is EntityPlayer)
        {
            IPlayer player = world.PlayerByUid((byEntity as EntityPlayer).PlayerUID);
            switch (blockSel.Face.Axis)
            {
                case EnumAxis.X:
                    destroyBlocks(world, blockSel.Position.AddCopy(0, -1, -1), blockSel.Position.AddCopy(0, 1, 1), player);
                    break;
                case EnumAxis.Y:
                    destroyBlocks(world, blockSel.Position.AddCopy(-1, 0, -1), blockSel.Position.AddCopy(1, 0, 1), player);
                    break;
                case EnumAxis.Z:
                    destroyBlocks(world, blockSel.Position.AddCopy(-1, -1, 0), blockSel.Position.AddCopy(1, 1, 0), player);
                    break;
            }
        }
        return true;
    }
    return false; 
}

If you have done everything right, your file should look similar to this:

using Vintagestory.API.Common;
using Vintagestory.API.Common.Entities;
using Vintagestory.API.MathTools;

<!--T:30-->
namespace ExampleMods
{
    public class TunnlerMod : ModSystem
    {

        <!--T:31-->
public override void Start(ICoreAPI api)
        {
            base.Start(api);
            api.RegisterItemClass("tunnler", typeof(TunnlerItem));
        }

    <!--T:32-->
}

    <!--T:33-->
public class TunnlerItem : Item
    {

        <!--T:34-->
public void DestroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player)
        {
            BlockPos tempPos = new BlockPos();
            for (int x = min.X; x <= max.X; x++)
            {
                for (int y = min.Y; y <= max.Y; y++)
                {
                    for (int z = min.Z; z <= max.Z; z++)
                    {
                        tempPos.Set(x, y, z);
                        if (player.WorldData.CurrentGameMode == EnumGameMode.Creative)
                            world.BlockAccessor.SetBlock(0, tempPos);
                        else
                            world.BlockAccessor.BreakBlock(tempPos, player);
                    }
                }
            }
        }

        <!--T:35-->
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1)
        {
            if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel))
            {
                if (byEntity is EntityPlayer)
                {
                    IPlayer player = world.PlayerByUid((byEntity as EntityPlayer).PlayerUID);
                    switch (blockSel.Face.Axis)
                    {
                        case EnumAxis.X:
                            destroyBlocks(world, blockSel.Position.AddCopy(0, -1, -1), blockSel.Position.AddCopy(0, 1, 1), player);
                            break;
                        case EnumAxis.Y:
                            destroyBlocks(world, blockSel.Position.AddCopy(-1, 0, -1), blockSel.Position.AddCopy(1, 0, 1), player);
                            break;
                        case EnumAxis.Z:
                            destroyBlocks(world, blockSel.Position.AddCopy(-1, -1, 0), blockSel.Position.AddCopy(1, 1, 0), player);
                            break;
                    }
                }
                return true;
            }
            return false; 
        }

    <!--T:36-->
}
}

<!--T:37-->

You can also download the file directly: Tunnler.cs.

Testing

This is how it looks ingame:

Distribution

Using the new Mod Template

If using the mod template setup, follow the instructions on Setting up your Development Environment to pack and distribute your mod.

Using the (old) Modtools

If using the modtools program, open the modtools and type in pack <your mod id>. Now you can take the zip file and share it with other people. It will work in the same way as ordinary mods, you can install it by copying it into the mods folder.

Mod Download

Here is my version:

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