Modding:Advanced Items/ru: Difference between revisions
(Created page with "== Класс Предмета ==") |
(Created page with "{{Navbox/modding|Vintage Story}}") |
||
(38 intermediate revisions by the same user not shown) | |||
Line 4: | Line 4: | ||
{{GameVersion|1.19.3}} | {{GameVersion|1.19.3}} | ||
Это руководство по ''код моду'' требует наличия среды разработки. Если у вас её нет, перейдите на страницу | Это руководство по ''код моду'' требует наличия среды разработки. Если у вас её нет, перейдите на страницу {{ll|Modding:Setting up your Development Environment|Настройка среды для разработки}} и следуйте инструкции. Также настоятельно рекомендуется прочитать руководство и закончить создание {{ll|Modding:Basic Item|Простого предмета}}. | ||
= Создание Тоннельной Кирки = | = Создание Тоннельной Кирки = | ||
Line 12: | Line 12: | ||
== Активы Предмета == | == Активы Предмета == | ||
Как и в случае с | Как и в случае с {{ll|Modding:Basic Item|Простым предметом}}, нам нужно создать активы (ассеты) для нашего предмета, включая тип предмета, текстуру и lang-файл. Эти активы довольно просты, и вы можете скачать их [https://wiki.vintagestory.at/images/c/cd/Tunnler_-_No_CS_File.zip здесь]. Распакуйте файл в папку mods, и вы готовы приступить к программированию. | ||
В json вашего itemtype есть только одно новое свойство, <code>class</code>. Это свойство указывает нашему новому элементу, что он будет управляться определенным классом C#. | В json вашего itemtype есть только одно новое свойство, <code>class</code>. Это свойство указывает нашему новому элементу, что он будет управляться определенным классом C#. | ||
Line 23: | Line 23: | ||
== Класс Предмета == | == Класс Предмета == | ||
Создание нашего элемента требует создания пары новых файлов <code>*.cs</code> в нашем проекте. | |||
Если вы уже читали руководство - {{ll|Modding:Advanced Blocks|Продвинутые блоки}}, это должно быть вам знакомо. | |||
=== Система Модов === | |||
Для того чтобы зарегистрировать класс предмета, нам нужно создать мод, который представляет собой класс, расширяющий ModSystem: | |||
<syntaxhighlight lang="c#"> | <syntaxhighlight lang="c#"> | ||
public class TunnlerMod : ModSystem | public class TunnlerMod : ModSystem | ||
Line 43: | Line 36: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Переопределив метод <code>Start(ICoreAPI)</code>, мы можем зарегистрировать наш класс. Функция <code>RegisterItemClass</code> имеет два параметра: | |||
Первый - идентификатор элемента класса, поскольку именно так мы будем ссылаться на этот класс в наших json-файлах itemtype. Убедитесь, что он идентичен классу, который мы указали в нашем предыдущем файле активов. | |||
Второй параметр - тип нашего элемента класса. | |||
<syntaxhighlight lang="c#"> | <syntaxhighlight lang="c#"> | ||
public class TunnlerMod : ModSystem | public class TunnlerMod : ModSystem | ||
Line 60: | Line 51: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Это должно быть отмечено как синтаксическая ошибка, потому что класса <code>TunnlerItem</code> пока не существует. | |||
=== Класс Предмета === | |||
=== | |||
При наименовании скриптов предметов рекомендуется называть их в формате "{Name}Item". В случае с тоннельной киркой мы назовем наш скрипт <code>TunnlerItem.cs</code>. Любой itemclass должен расширять Item, предоставляя ему необходимую нам функциональность: | |||
<syntaxhighlight lang="c#"> | <syntaxhighlight lang="c#"> | ||
public class TunnlerItem : Item | public class TunnlerItem : Item | ||
{ | { | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Это должно решить все синтаксические ошибки. | |||
'''Так что же должен делать наш инструмент?''' Когда игрок добывает блок с помощью этого инструмента, все блоки вокруг него также должны быть добыты. | |||
''' | |||
Как обычно, мы можем обратиться к [https://apidocs.vintagestory.at/api/Vintagestory.API.Common.Item.html#methods item api docs], чтобы найти функцию, которую мы можем использовать. Хотя сам класс item не содержит соответствующей функции, мы также можем обратиться к [https://apidocs.vintagestory.at/api/Vintagestory.API.Common.CollectibleObject.html CollectibleObject api docs], от которого класс item расширяется. | |||
В нашем конкретном случае мы можем переопределить метод <code>bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1)</code>. | |||
Нам нужно знать, с какой стороны стоит игрок (на какую сторону он ориентируется) и находится ли он в творческом режиме или режиме выживания (нужно ли бросать предметы или нет). Прежде чем переопределять <code>OnBlockBrokenWith</code>, мы должны создать метод, который уничтожает все блоки между двумя позициями блока (min и max). Он также должен сбрасывать предметы, только если игрок находится в режиме выживания: | |||
<syntaxhighlight lang="c#"> | <syntaxhighlight lang="c#"> | ||
public void DestroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player) | public void DestroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player) | ||
Line 127: | Line 96: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Теперь мы можем реализовать <code>OnBlockBroken</code> довольно легко, позаботившись обо всех возможных осях, с которыми может столкнуться игрок: | |||
<syntaxhighlight lang="c#"> | <syntaxhighlight lang="c#"> | ||
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1) | public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1) | ||
Line 157: | Line 124: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
---- | ---- | ||
Если вы все сделали правильно, ваш файл должен выглядеть примерно так: | |||
<syntaxhighlight lang="c#"> | <syntaxhighlight lang="c#"> | ||
using Vintagestory.API.Common; | using Vintagestory.API.Common; | ||
using Vintagestory.API.Common.Entities; | using Vintagestory.API.Common.Entities; | ||
using Vintagestory.API.MathTools; | using Vintagestory.API.MathTools; | ||
namespace ExampleMods | namespace ExampleMods | ||
{ | { | ||
public class TunnlerMod : ModSystem | public class TunnlerMod : ModSystem | ||
{ | { | ||
public override void Start(ICoreAPI api) | |||
public override void Start(ICoreAPI api) | |||
{ | { | ||
base.Start(api); | base.Start(api); | ||
api.RegisterItemClass("tunnler", typeof(TunnlerItem)); | api.RegisterItemClass("tunnler", typeof(TunnlerItem)); | ||
} | } | ||
} | |||
} | |||
public class TunnlerItem : Item | |||
public class TunnlerItem : Item | |||
{ | { | ||
public void DestroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player) | |||
public void DestroyBlocks(IWorldAccessor world, BlockPos min, BlockPos max, IPlayer player) | |||
{ | { | ||
BlockPos tempPos = new BlockPos(); | BlockPos tempPos = new BlockPos(); | ||
Line 214: | Line 167: | ||
} | } | ||
} | } | ||
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1) | |||
public override bool OnBlockBrokenWith(IWorldAccessor world, Entity byEntity, ItemSlot itemslot, BlockSelection blockSel, float dropQuantityMultiplier = 1) | |||
{ | { | ||
if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel)) | if (base.OnBlockBrokenWith(world, byEntity, itemslot, blockSel)) | ||
Line 241: | Line 192: | ||
return false; | return false; | ||
} | } | ||
} | |||
} | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Вы также можете скачать файл напрямую: [https://wiki.vintagestory.at/images/a/ad/Tunnler.cs Tunnler.cs]. | |||
== Тестирование == | |||
= | |||
Вот как это выглядит в игре: | |||
<youtube>2MRzYKguVFY</youtube> | <youtube>2MRzYKguVFY</youtube> | ||
== Распределение == | |||
= | |||
=== Использование нового шаблона мода === | |||
При использовании шаблона мода следуйте инструкциям [[Modding:Setting up your Development Environment#Packaging%20the%20Mod|Setting up your Development Environment]], чтобы упаковать и распространить свой мод. | |||
=== Использование (старого) Modtools === | |||
Если вы используете программу modtools, откройте ее и введите <code>pack <your mod id></code>. Теперь вы можете взять zip-файл и поделиться им с другими людьми. Он будет работать так же, как и обычные моды, вы можете установить его, скопировав в папку <code>mods</code>. | |||
= Скачать Мод = | |||
= | |||
Вот моя версия: | |||
* 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] | ||
{{Navbox/modding|Vintage Story}} | {{Navbox/modding|Vintage Story}} | ||
Revision as of 16:46, 24 March 2024
Эта страница проверялась в последний раз для версии 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
.
Скачать Мод
Вот моя версия:
- for VS v1.9: Tunnler_vs1.9_v1.0.0.zip
- for VS v1.8: Tunnler.zip
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 | Item • Entity • Block • Block Behaviors • Block Classes • Block Entities • Block Entity Behaviors • World properties |
Workflows & Infrastructure | Modding Efficiency Tips • Mod-engine compatibility • Mod Extensibility • VS Engine |
Additional Resources | Community Resources • Modding API Updates • Programming Languages • List of server commands • List of client commands • Client startup parameters • Server startup parameters Example Mods • API Docs • GitHub Repository |