Modding:Advanced Items/ru: Difference between revisions

From Vintage Story Wiki
(Created page with "=== Использование (старого) Modtools === Если вы используете программу modtools, откройте ее и введите <code>pack <your mod id></code>. Теперь вы можете взять zip-файл и поделиться им с другими людьми. Он будет работать так же, как и обычные моды, вы можете установить его, скопировав в пап...")
Tags: Mobile edit Mobile web edit
(Created page with "Вот моя версия: * for VS v1.9: [https://wiki.vintagestory.at/images/7/7b/Tunnler_vs1.9_v1.0.0.zip Tunnler_vs1.9_v1.0.0.zip] * for VS v1.8: [https://wiki.vintagestory.at/images/6/66/Tunnler.zip Tunnler.zip]")
Tags: Mobile edit Mobile web edit
Line 215: Line 215:
= Скачать Мод =
= Скачать Мод =


<div lang="en" dir="ltr" class="mw-content-ltr">
Вот моя версия:  
Here is my version:  
* for VS v1.9: [https://wiki.vintagestory.at/images/7/7b/Tunnler_vs1.9_v1.0.0.zip Tunnler_vs1.9_v1.0.0.zip]
* for VS v1.9: [https://wiki.vintagestory.at/images/7/7b/Tunnler_vs1.9_v1.0.0.zip Tunnler_vs1.9_v1.0.0.zip]
* for VS v1.8: [https://wiki.vintagestory.at/images/6/66/Tunnler.zip Tunnler.zip]
* for VS v1.8: [https://wiki.vintagestory.at/images/6/66/Tunnler.zip Tunnler.zip]
</div>





Revision as of 16:46, 24 March 2024

Other languages:


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


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

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

В этом уроке мы создадим предмет с более продвинутой функциональностью: Кирка, которая позволяет вырыть туннель 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
{

}

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


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

Как обычно, мы можем обратиться к 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);
            }
        }
    }
}

Теперь мы можем реализовать OnBlockBroken довольно легко, позаботившись обо всех возможных осях, с которыми может столкнуться игрок:

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

Если вы все сделали правильно, ваш файл должен выглядеть примерно так:

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

namespace ExampleMods
{
    public class TunnlerMod : ModSystem
    {

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

    }

    public class TunnlerItem : Item
    {

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

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

    }
}

Вы также можете скачать файл напрямую: Tunnler.cs.

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

Вот как это выглядит в игре:

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

Использование нового шаблона мода

При использовании шаблона мода следуйте инструкциям Setting up your Development Environment, чтобы упаковать и распространить свой мод.

Использование (старого) Modtools

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

Скачать Мод

Вот моя версия: