Modding:Advanced Blocks/ru: Difference between revisions

From Vintage Story Wiki
(Created page with "{{GameVersion|1.15}}")
 
No edit summary
 
(78 intermediate revisions by 4 users not shown)
Line 1: Line 1:
<languages />
<languages />
__FORCETOC__
__FORCETOC__
{{GameVersion|1.15}}
{{GameVersion|1.19.3}}
<div lang="en" dir="ltr" class="mw-content-ltr">
Этот руководство по '''code mod''' требует наличия среды разработки. Если у вас её еще нет, прочтите руководство по {{ll|Modding:Setting up your Development Environment|настройке среды для разработки}}. Также рекомендуется сначала прочитать про {{ll|Modding:Basic Block|Простые Блоки}} и изучить их устройство если вы не сделали этого ранее.
It's highly recommended to read [[Basic Block]] first. Additionally this tutorial requires a development environment. If you don't have one already you should read the tutorial [[Setting up your Development Environment]].
= Создание Батута =
</div>
= <span lang="en" dir="ltr" class="mw-content-ltr">Trampoline</span> =


<div lang="en" dir="ltr" class="mw-content-ltr">
В этом уроке мы создадим блок с более продвинутой функциональностью: Батут.
In this tutorial will we create something more advanced. A block with functionality ... a trampoline!
</div>


== <span lang="en" dir="ltr" class="mw-content-ltr">Block Assets</span> ==
== Ассеты Блока ==


<div lang="en" dir="ltr" class="mw-content-ltr">
Как и в случае с нашим {{ll|Modding:Basic Block|Простым Блоком}}, первое, что нам нужно - это assets блока. Создайте тип блока <code>trampoline.json</code> на основе нашего блока, созданного в предыдущем руководстве. 
The first thing we are going to need are the assets of the block. Those are pretty straight forward.
</div>  


<div lang="en" dir="ltr" class="mw-content-ltr">
В нашем файле blocktype нам нужно добавить свойство <code>class</code>. Это свойство, по сути, указывает нашему новому блоку, что он будет управляться определенным классом C#.
The only new property is the <code>class</code>:
</div>
<syntaxhighlight lang="json">
<syntaxhighlight lang="json">
class: "trampoline",
class: "trampoline",
</syntaxhighlight>
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
Мы создадим этот класс в нашей среде разработки, чтобы придать блоку желаемую функциональность. Вы можете скачать ассеты мода [https://wiki.vintagestory.at/images/b/b9/Trampoline_-_No_CS_FILE.zip здесь].
We will create this class, to give the block the desired functionality, so make sure if you pick a different name it matches the one below.
Все, что вам нужно сделать, это поместить содержимое этого zip-файла в директорию <code>assets</code> в вашем проекте разработки.
You can download the assets of the mod [https://wiki.vintagestory.at/images/b/b9/Trampoline_-_No_CS_FILE.zip here].
All you need to do is to place this zip file in your <code>assets</code> directory in your development project.
</div>


== <span lang="en" dir="ltr" class="mw-content-ltr">The Block Class</span> ==
== Класс Блока ==


<div lang="en" dir="ltr" class="mw-content-ltr">
Чтобы создать наш мод, нам понадобится несколько новых файлов <code>*.cs</code> в нашем проекте.  
Now we need to register our class and therefore we need to create a new <code>*.cs</code> file in our project. I'm gonna name it <code>Trampoline.cs</code>.
</div>


=== <span lang="en" dir="ltr" class="mw-content-ltr">The Mod System</span> ===
=== Система Мода ===


<div lang="en" dir="ltr" class="mw-content-ltr">
Для того чтобы создать мод, нам нужно создать класс, который будет наследоваться от <code>ModSystem</code>. Это позволит регистрировать всевозможные вещи, но пока мы ограничимся регистрацией только нашего класса блока.
In order to create a mod your class needs to extend <code>ModSystem</code>. This will allow use to register all kinds of stuff, but for now we will stick to our block class example.
</div>


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 49: Line 34:
</syntaxhighlight>
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
Теперь вам нужно переопределить метод <code>Start(ICoreAPI)</code> и зарегистрировать класс.
Now you need to override the <code>Start(ICoreAPI)</code> method and register the class. If you have picked a different class name you have to use that one instead of trampoline.
 
</div>
Функция <code>RegisterBlockClass</code> имеет два параметра: первый - идентификатор класса блока, который мы используем в json-файлах blocktype. Убедитесь, что он идентичен классу, который мы указали в нашем предыдущем файле активов. Второй параметр - это тип нашего класса блока.


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 64: Line 49:
</syntaxhighlight>
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
Так как класса <code>TrampolineBlock</code> ещё не существует, это место будет отображаться как синтаксическая ошибка.
This should be marked as a syntax error because there is no <code>TrampolineBlock</code> class yet.
 
</div>
=== Класс Блока ===


=== <span lang="en" dir="ltr" class="mw-content-ltr">The Block Class</span> ===
Давайте создадим наш класс блока, который, конечно, должен унаследовать класс <code>Block</code>:


<div lang="en" dir="ltr" class="mw-content-ltr">
Давайте создадим наш класс блока. При именовании скриптов блоков рекомендуется называть их в формате "{Name}Block". В случае с батутом мы назовем наш скрипт <code>TrampolineBlock.cs</code>. Любой класс блока должен наследоваться от <code>Block</code>, предоставляющий ему необходимую нам функциональность:
Let's create our block class itself which of course has to extend <code>Block</code>:
</div>
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
public class TrampolineBlock : Block
public class TrampolineBlock : Block
Line 80: Line 63:
</syntaxhighlight>
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
Это должно решить все синтаксические ошибки.
This should solve all syntax errors.
 
</div>
Итак, как же нам реализовать прыгучий блок? Будет не лишним взглянуть на [https://apidocs.vintagestory.at/api/Vintagestory.API.Common.Block.html документацию API], чтобы найти правильный способ.


<div lang="en" dir="ltr" class="mw-content-ltr">
Метод <code>void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact)</code> выглядит как неплохой вариант для реализации прыгучего функционала. Заметьте, что каждый блок батута размещенный в игре будет {{ll|Modding:Block_Cardinality|совместно использовать}} один и тот же экземпляр <code>TrampolineBlock</code>. Поскольку этот объект используется несколькими блоками, он не имеет поля для позиции блока. Поэтому в обработчике события присутствует параметр <code>pos</code>.
So how do we implement a bouncy block? It's pretty helpful to take a look at the [https://apidocs.vintagestory.at/api/Vintagestory.API.Common.Block.html api documentation] to find a proper way to implement it.
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
'''Когда объект должен отскочить?'''
The method <code>void onEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, bool isImpact)</code> seems to be a good way to implement a bouncy functionality. Note that every trampoline block placed in the game will [[Modding:Block_Cardinality|share]] the same instance of <code>TrampolineBlock</code>. Because that object is shared by multiple blocks, it does not have a field for the block position. That's why the event handler includes the <code>pos</code> parameter.
# Сущность должна отскочить в тот момент, когда она приземляется на вершину блока, а не, когда она уже стоит на нем. Поэтому <code>isImpact</code> должно быть <code>true</code>.
</div>
# Сущность должна сталкиваться вертикально. Стороны блока не должны отталкивать сущность. Таким образом, осью стороны <code>axis</code> <code>facing</code> должна быть <code>Y</code>.


<div lang="en" dir="ltr" class="mw-content-ltr">
'''Как мы можем заставить объект подпрыгивать?'''
'''When should an entity bounce?'''
# The entity should bounce in the moment it lands on top of the block and not if it is standing on it already. Therefore <code>isImpact</code> has to be <code>true</code>
# If the entity is colliding vertically. The sides of the block shouldn't push an entity away. So the <code>axis</code> of the <code>facing</code> has to be <code>Y</code>.
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
Чтобы заставить объект подпрыгнуть, нам нужно изменить его направление. Поэтому мы можем просто изменить направление его движения. Чем быстрее сущность будет двигаться во время столкновения, тем дальше она будет отброшена. Но простое изменение направления движения не будет идеальным. Сущность никогда не потеряет своего движения и будет бесконечно отскакивать. Поэтому давайте сделаем что-нибудь, что заставит сущность терять 20% своего движения при каждом отскоке:
'''How can we make the entity bounce?'''
In order to make an entity bounce, we need to change its direction. Therefore we can simply revert its motion. The faster the entity will be when during the collision the further it will be pushed away. But simply reverting the motion wouldn't be ideal. The entity would never lose its motion and bounce endless. So let's go for something smaller and make the entity lose 20% of its motion each bounce:
</div>
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
entity.Pos.Motion.Y *= -0.8;
entity.Pos.Motion.Y *= -0.8;
</syntaxhighlight>The <code>*=</code> is a shorthand way of writing:<syntaxhighlight lang="c#">
entity.Pos.Motion.Y = entity.Pos.Motion.Y * -0.8;
</syntaxhighlight>
</syntaxhighlight>


----
----


<div lang="en" dir="ltr" class="mw-content-ltr">
Если собрать всё воедино, это должно выглядеть так:
If we put everything together it should look like this:
</div>


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 119: Line 93:
         if (isImpact && facing.Axis == EnumAxis.Y)
         if (isImpact && facing.Axis == EnumAxis.Y)
         {
         {
            world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);
             entity.Pos.Motion.Y *= -0.8;
             entity.Pos.Motion.Y *= -0.8;
         }
         }
Line 126: Line 99:
</syntaxhighlight>
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
Хотя этот код уже работает, некоторые звуковые эффекты были бы весьма кстати. Мы можем реализовать это, добавив в наш блок поле звуковой ссылки, которое можно использовать для воспроизведения звука <code>game:tick</code>.
Although this code works already, some sound effects would be rather nice. We can implement it by adding a sound link field to our block, which can use to play the <code>game:tick</code> sound.
</div>


<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
Line 134: Line 105:
</syntaxhighlight>
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
Этот <code>tickSound</code> будет воспроизводиться каждый раз, когда объект отскакивает:
This <code>tickSound</code> will played every time an entity bounces:
</div>


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


<div lang="en" dir="ltr" class="mw-content-ltr">
Если вы всё сделали правильно, то ваш файл должен быть похож на:
If you have done everything right, your file should look similar to this:
</div>
<syntaxhighlight lang="c#">
<syntaxhighlight lang="c#">
using Vintagestory.API.Common;
using Vintagestory.API.Common;
Line 180: Line 147:
</syntaxhighlight>
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
Конечно, вы можете скачать файл напрямую [https://wiki.vintagestory.at/images/8/8a/Trampoline.cs Trampoline.cs].
Of course you can download the file directly [https://wiki.vintagestory.at/images/8/8a/Trampoline.cs Trampoline.cs].
</div>


== <span lang="en" dir="ltr" class="mw-content-ltr">Testing</span> ==
== Тестирование ==


<div lang="en" dir="ltr" class="mw-content-ltr">
Наконец мы можем запустить наш первый тест. Выглядит неплохо, так ведь?
Finally we can run our first test. Looks pretty good, right?
</div>


<youtube>Kg8J_rNOweU</youtube>
<youtube>Kg8J_rNOweU</youtube>


<div lang="en" dir="ltr" class="mw-content-ltr">
'''Подсказка''': используйте клиентскую команду {{ll|List_of_client_commands#.tfedit|<code>.tfedit</code>}}, если вы хотите отрегулировать положение, вращение и масштаб блока в руках, в графическом интерфейсе, при падении на землю или в режиме от третьего лица.
'''Hint''': Use the client command <code>.tfedit</code> if you want to adjust the block position, rotation and scale in Hands, in GUI, when dropped on the ground or in third person mode.
 
</div>
== Распространение ==


== <span lang="en" dir="ltr" class="mw-content-ltr">Distribution</span> ==
=== Использование нового шаблона мода ===
Если вы используете шаблон мода, следуйте инструкциям [[Modding:Setting up your Development Environment#Packaging the Mod|Настройка среды разработки]], чтобы упаковать ваш мод для дальнейшего распространения.


<div lang="en" dir="ltr" class="mw-content-ltr">
=== Использование Modtools (старый способ) ===
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. It will work in the same way as ordinary mods, you can install it by copying it into the <code>mods</code> folder.
Если вы используете программу modtools, откройте её и введите <code>pack <your mod id></code>. Теперь вы можете взять zip-файл и поделиться им с другими людьми. Он будет работать так же, как и обычные моды, вы можете установить его, скопировав в папку <code>mods</code>.
</div>


= <span lang="en" dir="ltr" class="mw-content-ltr">Mod Download</span> =
= Скачать Мод =


<div lang="en" dir="ltr" class="mw-content-ltr">
Варианты мода из этого руководства:  
Here is my version:  
* для версии 1.9: [https://wiki.vintagestory.at/images/2/24/Trampoline_vs1.9_v1.0.0.zip Trampoline_vs1.9_v1.0.0.zip]
* for VS v1.9: [https://wiki.vintagestory.at/images/2/24/Trampoline_vs1.9_v1.0.0.zip Trampoline_vs1.9_v1.0.0.zip]
* для версии 1.5: [https://wiki.vintagestory.at/images/c/ce/Trampoline.zip Trampoline.zip]
* for VS v1.5: [https://wiki.vintagestory.at/images/c/ce/Trampoline.zip Trampoline.zip]
</div>


= <span lang="en" dir="ltr" class="mw-content-ltr">Moving Forward</span> =
= Дальнейшие Шаги =


<div lang="en" dir="ltr" class="mw-content-ltr">
Теперь, когда вы успешно создали функциональный блок, вы можете пойти еще дальше, научившись использовать '''[[Modding:Block Entity| Сущность Блоков]]''' и создавать собственные '''[[Modding:Adding Block Behavior | Поведения Блоков]]'''. Оба эти руководства научат вас добавлять еще больше механики в ваши пользовательские блоки.
Now that you've successfully made an advanced block you can go even further by learning how to utilize '''[[Modding:Block Entity| Block Entities]]''' and how to create your own '''[[Modding:Adding Block Behavior | Block Behaviors]]'''. Both of these tutorials will teach you how to add even more mechanics to your custom blocks.
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
Или вы можете попробовать создать '''[[Modding:Advanced Items | Функциональный Предмет]]''', если вы еще этого не сделали.  
Or, you can try out making an '''[[Modding:Advanced Items | Advanced Item]]''' if you haven't already.
</div>


{{Navbox/modding|Vintage Story}}
{{Navbox/modding|Vintage Story}}

Latest revision as of 15:19, 25 March 2024

Other languages:

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

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

Создание Батута

В этом уроке мы создадим блок с более продвинутой функциональностью: Батут.

Ассеты Блока

Как и в случае с нашим Простым Блоком , первое, что нам нужно - это assets блока. Создайте тип блока trampoline.json на основе нашего блока, созданного в предыдущем руководстве.

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

	class: "trampoline",

Мы создадим этот класс в нашей среде разработки, чтобы придать блоку желаемую функциональность. Вы можете скачать ассеты мода здесь. Все, что вам нужно сделать, это поместить содержимое этого zip-файла в директорию assets в вашем проекте разработки.

Класс Блока

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

Система Мода

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

public class TrampolineMod : ModSystem
{
    
}

Теперь вам нужно переопределить метод Start(ICoreAPI) и зарегистрировать класс.

Функция RegisterBlockClass имеет два параметра: первый - идентификатор класса блока, который мы используем в json-файлах blocktype. Убедитесь, что он идентичен классу, который мы указали в нашем предыдущем файле активов. Второй параметр - это тип нашего класса блока.

public class TrampolineMod : ModSystem
{
    public override void Start(ICoreAPI api)
    {
        base.Start(api);
        api.RegisterBlockClass("trampoline", typeof(TrampolineBlock));
    }
}

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

Класс Блока

Давайте создадим наш класс блока, который, конечно, должен унаследовать класс Block:

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

public class TrampolineBlock : Block
{

}

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

Итак, как же нам реализовать прыгучий блок? Будет не лишним взглянуть на документацию API, чтобы найти правильный способ.

Метод void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact) выглядит как неплохой вариант для реализации прыгучего функционала. Заметьте, что каждый блок батута размещенный в игре будет совместно использовать один и тот же экземпляр TrampolineBlock. Поскольку этот объект используется несколькими блоками, он не имеет поля для позиции блока. Поэтому в обработчике события присутствует параметр pos.

Когда объект должен отскочить?

  1. Сущность должна отскочить в тот момент, когда она приземляется на вершину блока, а не, когда она уже стоит на нем. Поэтому isImpact должно быть true.
  2. Сущность должна сталкиваться вертикально. Стороны блока не должны отталкивать сущность. Таким образом, осью стороны axis facing должна быть Y.

Как мы можем заставить объект подпрыгивать?

Чтобы заставить объект подпрыгнуть, нам нужно изменить его направление. Поэтому мы можем просто изменить направление его движения. Чем быстрее сущность будет двигаться во время столкновения, тем дальше она будет отброшена. Но простое изменение направления движения не будет идеальным. Сущность никогда не потеряет своего движения и будет бесконечно отскакивать. Поэтому давайте сделаем что-нибудь, что заставит сущность терять 20% своего движения при каждом отскоке:

entity.Pos.Motion.Y *= -0.8;

The *= is a shorthand way of writing:

entity.Pos.Motion.Y = entity.Pos.Motion.Y * -0.8;

Если собрать всё воедино, это должно выглядеть так:

public class TrampolineBlock : Block
{
    public override void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact)
    {
        if (isImpact && facing.Axis == EnumAxis.Y)
        {
            entity.Pos.Motion.Y *= -0.8;
        }
    }
}

Хотя этот код уже работает, некоторые звуковые эффекты были бы весьма кстати. Мы можем реализовать это, добавив в наш блок поле звуковой ссылки, которое можно использовать для воспроизведения звука game:tick.

public AssetLocation tickSound = new AssetLocation("game", "tick");

Этот tickSound будет воспроизводиться каждый раз, когда объект отскакивает:

world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);

Если вы всё сделали правильно, то ваш файл должен быть похож на:

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

namespace VSExampleMods
{
    public class TrampolineMod : ModSystem
    {

        public override void Start(ICoreAPI api)
        {
            base.Start(api);
            api.RegisterBlockClass("trampoline", typeof(TrampolineBlock));
        }
    }

    public class TrampolineBlock : Block
    {
        public AssetLocation tickSound = new AssetLocation("game", "tick");

        public override void OnEntityCollide(IWorldAccessor world, Entity entity, BlockPos pos, BlockFacing facing, Vec3d collideSpeed, bool isImpact)
        {
            if (isImpact && facing.Axis == EnumAxis.Y)
            {
                world.PlaySoundAt(tickSound, entity.Pos.X, entity.Pos.Y, entity.Pos.Z);
                entity.Pos.Motion.Y *= -0.8;
            }
        }
    }
}

Конечно, вы можете скачать файл напрямую Trampoline.cs.

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

Наконец мы можем запустить наш первый тест. Выглядит неплохо, так ведь?

Подсказка: используйте клиентскую команду .tfedit , если вы хотите отрегулировать положение, вращение и масштаб блока в руках, в графическом интерфейсе, при падении на землю или в режиме от третьего лица.

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

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

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

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

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

Скачать Мод

Варианты мода из этого руководства:

Дальнейшие Шаги

Теперь, когда вы успешно создали функциональный блок, вы можете пойти еще дальше, научившись использовать Сущность Блоков и создавать собственные Поведения Блоков. Оба эти руководства научат вас добавлять еще больше механики в ваши пользовательские блоки.

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

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