Skip to content

JavaScript API

And42 edited this page Dec 19, 2024 · 4 revisions

JavaScript API

Моды пишутся на JavaScript. По умолчанию JavaScript не предоставляет ни методов для работы с Terraria, ни методов для работы с модами. Но все эти методы нужны, иначе толку от JavaScript никакого. В связи с этим TL предоставляет API (набор функций), который позволяет работать с игрой и модами.

Набор доступных функций зависит от версии структуры пака (её можно увидеть и изменить в TL Packer или вручную в поле packStructureVersion в Settings.json пака). Мы стараемся делать так, чтобы новые версии TL поддерживали работу со всеми версиями структур, чтобы не нужно было переписывать моды после того, как мы изменили часть функций. В идеале, стоит создавать моды под последнюю версию структуры пака на момент создания мода, чтобы получить доступ к наибольшему количеству функций.

Преобразования типов:

В C# есть понятия упаковки и распаковки (boxing и unboxing соответственно). Упаковка происходит, когда экземпляр структуры (или примитива) приводится к типу объекта. Пример: object number = 3 - примитив 3 упаковывается в объект. В C# упаковка производится автоматически, а для распаковки нужно указать конкретный тип в скобках (Пример: object boxedNumber = 3; int unboxedNumber = (int) boxedNumber).

TL Mod API при работе с объектами C# автоматически выполняет приведение примитивных типов к аналогам в JavaScript для удобства работы с ними. К примеру поле Terraria.ID.ItemID.SummonerEmblem имеет тип short, поэтому код new NativeClass('Terraria.ID', 'ItemID').SummonerEmblem автоматически преобразует возвращённое значение к типу Number в JavaScript.

Данные приведения в большинстве случаев не вызывают проблем, но иногда всё же вызывают.

К примеру, может потребоваться передать объект в качестве аргумента в функцию при создании и заполнении массива int:

const Array = new NativeClass('System', 'Array');
const CreateInstance = Array['Array CreateInstance(Type elementType, int length)'];
const GetValue = Array['object GetValue(long index)'];
const SetValue = Array['void SetValue(object value, long index)'];

const Type = new NativeClass('System', 'Type');
const GetType = Type['Type GetType(string typeName)'];

const Int32Type = GetType('System.Int32');

const newArray = CreateInstance(Int32Type, 1);
SetValue(newArray, 20, 0n) // Выбросит ошибку из-за несоотвествия типов - нужен объект, а передаётся примитив
SetValue(newArray, NativeObject.wrap(20, 'int'), 0n); // Всё хорошо
const arrayBoxedValue = GetValue(newArray, 0n); // Тип `arrayBoxedValue` - NativeObject, другими словами, упакованное примитивное значение
const arrayUnboxedValue = NativeObject.unwrap(arrayBoxedValue); // Тип `arrayUnboxedValue` - `Number`

В примере выше метод Array.SetValue согласно сигнатуре принимает первым аргументом значение типа object. Если вместо NativeObject передать JavaScript Number (20), то Mod API не сможет понять, к какому типу примитива это число нужно преобразовать (нужно ли передать int, или short, или byte и т.п.). Поэтому перед передачей значения его нужно упаковать с помощью NativeObject.wrap.

Метод же Array.GetValue согласно сигнатуре возвращает объект, поэтому arrayBoxedValue не будет автоматически преобразован в JavaScript Number. Для его преобразования и вычислений с помощью стандартных JavaScript операций нужно использовать функцию NativeObject.unwrap.

NativeObject.wrap/unwrap также используется для преобразования других C# объектов в их аналоги в JavaScript. К примеру, вызов NativeObject.wrap('hello', 'string') вернёт упакованный экземпляр типа string, а NativeObject.unwrap(<some string object>) вернёт JavaScript строку.

Информацию по методам NativeObject.wrap/unwrap смотри ниже.

Оглавление

  1. import.meta.currentDirectory (v22+)
  2. NativeClass.constructor (v22+)
  3. NativeClass.makeGeneric (v22+)
  4. NativeClass.new (v22+)
  5. NativeObject.unwrap (v27+)
  6. NativeObject.wrap (v27+)
  7. tl.info.terrariaVersionName (v22+)
  8. tl.info.terrariaVersionCode (v22+)
  9. tl.mod.dataDirectory (v27+)
  10. tl.mod.name (v22+)
  11. tl.mod.path (v22+)
  12. tl.mod.uuid (v22+)
  13. tl.mod.packUuid (v22+)
  14. tl.mod.packStructureVersion (v22+)
  15. tl.translation.add (v22+)
  16. tl.file.delete (v27+)
  17. tl.file.exists (v22+)
  18. tl.file.read (v22+)
  19. tl.file.write (v27+)
  20. tl.item.registerNew (v22+)
  21. tl.texture.load (v22+)
  22. tl.texture.loadAnimation (v22+)
  23. tl.cheatMenu.getItemCategories (v22+)
  24. tl.cheatMenu.addItemCategory (v22+)
  25. tl.cheatMenu.addItemToCategory (v22+)
  26. tl.directory.create (v27+)
  27. tl.directory.delete (v27+)
  28. tl.directory.exists (v27+)
  29. tl.directory.listDirectories (v27+)
  30. tl.directory.listFiles (v27+)
  31. tl.log (v22+)

import.meta.currentDirectory String

Описание: возвращает путь к папке текущего скрипта.

Версия: 22 и выше

Пример:

main.js:

import { callScript } from 'inner/script.js'

callScript();

inner/script.js:

export function callScript() {
    tl.log(import.meta.currentDirectory)
}

Содержимое лога: "inner"

⬆ Оглавление


new NativeClass(String namespace, String name)

Описание: создаёт новый экземпляр класса NativeClass. Этот класс позволяет работать с методами из C#

Версия: 22 и выше

Пример:

main.js

const ItemID = new NativeClass('Terraria.ID', 'ItemID');
tl.log(ItemID.SummonerEmblem);

Содержимое лога: 2998

⬆ Оглавление


NativeClass.makeGeneric(NativeClass[] types) -> NativeClass

Описание: позволяет работать с generic C# классами

Версия: 22 и выше

Пример:

main.js

const List = new NativeClass('System.Collections.Generic', 'List`1');
const Int32Type = new NativeClass('System', 'Int32');

const IntList = List.makeGeneric(Int32Type);

const list = IntList.new();
list['void .ctor()']();

list.Add(5);
list.Add(10);
list.Add(15);

const lastItem = list['int get_Item(int index)'](2);

tl.log(lastItem);

Содержимое лога: 15

⬆ Оглавление


NativeClass.new() -> NativeObject

Описание: позволяет создавать экземпляры объектов

Важно: после создания объекта необходимо вызвать один из конструкторов класса на созданном экземпляре. Если этого не сделать, то поля объекта будут неинициализированы, что может привести к неожиданным проблемам при работе с объектом

Версия: 22 и выше

Пример:

main.js

const Viewport = new NativeClass('Microsoft.Xna.Framework.Graphics', 'Viewport');

const instance = Viewport.new();
instance['void .ctor(int x, int y, int width, int height)'](1, 2, 3, 4);

tl.log(instance.Y);

Содержимое лога: 2

⬆ Оглавление


NativeClass.property или NativeClass["property"]

Описание: позволяет работать с методами/свойствами/полями C# класса

Версия: 22 и выше

Пример 1 - статическое поле:

main.js

const ItemID = new NativeClass('Terraria.ID', 'ItemID');
tl.log(ItemID.SummonerEmblem);
tl.log(ItemID["SummonerEmblem"]);

Содержимое лога:

2998
2998

Пример 2 - статический метод:

main.js

const Path = new NativeClass('System.IO', 'Path');
const method1 = Path.GetExtension; // работает, т.к. у Path есть только один метод с именем GetExtension
const method2 = Path['string GetExtension(string path)'];
tl.log(method1('file.txt'));
tl.log(method2('file.txt'));

Содержимое лога:

.txt
.txt

⬆ Оглавление


static NativeClass.unwrap(NativeObject wrappedValue) -> Any

Описание: преобразовывает объекты C# в JavaScript объекты

Версия: 27 и выше

Пример:

main.js

const Array = new NativeClass('System', 'Array');
const GetValue = Array['object GetValue(long index)'];

const someArray = ... // Тип `someArray` - NativeObject c массивом `int` внутри 

const arrayBoxedValue = GetValue(newArray, 0n); // Тип `arrayBoxedValue` - NativeObject
const arrayUnboxedValue = NativeObject.unwrap(arrayBoxedValue); // Тип `arrayUnboxedValue` - `Number`

⬆ Оглавление


static NativeClass.wrap(Any value, String type) -> NativeObject
type - byte | sbyte | short | ushort | int | uint | long | ulong | float | double | bool | char | string

Описание: преобразовывает JavaScript объекты в C# объекты

Версия: 27 и выше

Пример:

main.js

const Array = new NativeClass('System', 'Array');
const SetValue = Array['void SetValue(object value, long index)'];

const someArray = ... // Тип someArray - NativeObject c массивом int внутри 

const valueToSetUnboxed = 20; // Тип valueToSetUnboxed - Number
const valueToSetBoxed = NativeObject.wrap(valueToSetUnboxed, 'int'); // Тип valueToSetBoxed - NativeObject
SetValue(someArray, valueToSetBoxed, 0n);

⬆ Оглавление


tl.info.terrariaVersionName String

Описание: возвращает строковую версию террарии

Версия: 22 и выше

Пример:

main.js:

tl.log(tl.info.terrariaVersionName)

Содержимое лога: "1.4.0.5.2.1"

⬆ Оглавление


tl.info.terrariaVersionCode Integer

Описание: возвращает целочисленную версию террарии

Версия: 22 и выше

Пример:

main.js:

tl.log(tl.info.terrariaVersionCode)

Содержимое лога: 300543

⬆ Оглавление


tl.mod.name String

Описание: возвращает название пака, взятое из поля title файла Settings.json

Версия: 22 и выше

Пример: Settings.json:

{
    "title": "Интересный пак"
}
tl.log(tl.mod.name);

Содержимое лога: "Интересный пак"

⬆ Оглавление


tl.mod.path String

Описание: возвращает путь к директории мода на устройстве пользователя. Функции TL, работающие с файлами, считают этот путь корневой директорией, в которой ищется необходимый путь к файлу. К примеру, tl.file.read("some_file.txt") прочитает файл из папки tl.mod.path + '/some_file.txt', это происходит неявно

Версия: 22 и выше

Пример: main.js

tl.log(tl.mod.path);

Содержимое лога: "/storage/emulated/0/Android/data/com.pixelcurves.terlauncher/tl_files/packs/7634960c-2c5a-4509-b586-c26a35fa5546/Modified/1.mod"

⬆ Оглавление


tl.mod.uuid String

Описание: возвращает id мода - поле id внутри файла <mod_dir>.json

Версия: 22 и выше

Пример: <mod_dir>.json:

{
    "id": "ae7d54e7-c8db-4d66-bb50-713c76b76d59"
}
tl.log(tl.mod.uuid)

Содержимое лога: ae7d54e7-c8db-4d66-bb50-713c76b76d59

⬆ Оглавление


tl.mod.packUuid String

Описание: возвращает id пака с модом - поле guid внутри файла Settings.json

Версия: 22 и выше

Пример:

Settings.json:

{
    "packStructureVersion": 17,
    "title": "Bosses stop spawn mobs",
    "guid": "7634960c-2c5a-4509-b586-c26a35fa5546"
}
tl.log(tl.mod.packUuid)

Содержимое лога: 7634960c-2c5a-4509-b586-c26a35fa5546

⬆ Оглавление


tl.mod.packStructureVersion Integer

Описание: возвращает версию структуры пака с модом - поле packStructureVersion внутри файла Settings.json

Версия: 22 и выше

Пример:

Settings.json:

{
    "packStructureVersion": 17,
    "title": "Bosses stop spawn mobs",
    "guid": "7634960c-2c5a-4509-b586-c26a35fa5546"
}
tl.log(tl.mod.packStructureVersion)

Содержимое лога: "17"

⬆ Оглавление


tl.mod.dataDirectory String

Описание: возвращает директорию, файлы в которой сохраняются при обновлении пака. Используйте данную папку для хранения данных мода

Версия: 27 и выше

Пример 1 (вывод пути):

main.js

tl.log(tl.mod.dataDirectory)

Содержимое лога: "data"

Пример 2 (сохранение и чтение данных):

main.js

function saveData(dataString) {
    tl.directory.create(tl.mod.dataDirectory);
    tl.file.write(tl.mod.dataDirectory + "/some_data.json", dataString);
}

function restoreData() {
    tl.directory.create(tl.mod.dataDirectory);
    return tl.file.read(tl.mod.dataDirectory + "/some_data.json");
}

saveData("Hello everyone");
tl.log(restoreData());

Содержимое лога: "data"

⬆ Оглавление


tl.translation.add(String languageCode, String jsonContents)

Описание: добавляет перевод для указанного языка

Версия: 22 и выше

Пример: TBD

⬆ Оглавление


tl.file.delete(String filePath) -> Boolean

Описание: удаляет файл по указанному пути и возвращает true, если удаление успешно

Версия: 27 и выше

Пример:

main.js:

tl.file.write("test.txt", "Hello");
tl.log(tl.file.delete("test.txt"));

Содержимое лога: "true"

⬆ Оглавление


tl.file.exists(String filePath) -> Boolean

Описание: проверяет наличие файла по указанному пути

Версия: 22 и выше

Пример:

main.js:

tl.file.write("test.txt", "Hello");
tl.log(tl.file.exists("test.txt"));

Содержимое лога: "true"

⬆ Оглавление


tl.file.read(String filePath) -> String

Описание: читает текст из файла в кодировке utf-8 и возвращает в виде строки

Версия: 27 и выше

Пример:

main.js:

tl.file.write("test.txt", "Привет");
tl.log(tl.file.read("test.txt"));

Содержимое лога: "Привет"

⬆ Оглавление


tl.file.write(String filePath, String data)

Описание: записывает текст в файл в кодировке utf-8

Версия: 27 и выше

Пример:

main.js:

tl.file.write("test.txt", "Привет");
tl.log(tl.file.read("test.txt"));

Содержимое лога: "Привет"

⬆ Оглавление


tl.item.registerNew(String itemName) -> Integer

Описание: добавляет новый предмет с именем itemName в игру и возвращает его ID

Версия: 22 и выше

Пример:

let itemId = tl.item.registerNew("Some cool item");
tl.log(itemId);

Содержимое лога: "6000"

⬆ Оглавление


tl.texture.load(String filePath) -> NativeObject (Xna Texture2D)

Описание: загружает из файла картинку формата .png, преобразует её в Xna Texture2D и возвращает её

Версия: 22 и выше

Пример:

let myTexture = tl.texture.load("textures/myLovelyTexture.png");

⬆ Оглавление


tl.texture.loadAnimation(String filePath, Integer horizontalFramesCount, Integer millisPerFrame) -> NativeObject (Xna Texture2D)

Описание: TBD

Версия: 22 и выше

Пример: TBD

⬆ Оглавление


tl.cheatMenu.getItemCategories() -> String[]

Описание: возвращает текущий список категорий предметов в чит меню

Версия: 22 и выше

Пример:

main.js:

tl.log(tl.cheatMenu.getItemCategories())

Содержимое лога: "all,tile,wall,pick,axe,hammer,armor,melee,summon,magic,ranged,thrown,accessory,wings,shield,mount,expert,potion,fishingPole,questItem,helmet,breastplate,boots,painting,mod,redirected,redirectedAnimated"

⬆ Оглавление


tl.cheatMenu.addItemCategory(String categoryName, String iconPath) -> String

Описание: добавляет в список категорий предметов в чит меню новую категорию и возвращает её имя ("<mod id>: <category name>") в списке категорий

Версия: 22 и выше

Пример:

main.js:

tl.log(tl.cheatMenu.addItemCategory("animated category", "textures/animated.gif"));
tl.log(tl.cheatMenu.addItemCategory("static category", "textures/static.webp"));

Содержимое лога:

00000000-0000-0001-0000-000000000001: animated category
00000000-0000-0001-0000-000000000001: static category

⬆ Оглавление


tl.cheatMenu.addItemToCategory(String categoryName, int id) -> Boolean

Описание: добавляет предмет в заданную категорию предметов в чит меню и возвращает, успешно ли добавление (неуспешно, если категория с заданным именем не найдена)

Версия: 22 и выше

Пример:

main.js:

let categoryName = tl.cheatMenu.addItemCategory("static category", "textures/static.webp");
tl.cheatMenu.addItemToCategory(categoryName, 10);
tl.cheatMenu.addItemToCategory(categoryName, 201);

⬆ Оглавление


tl.directory.create(String directoryPath) -> Boolean

Описание: создаёт директорию с поддиректориями по указанному пути и возвращает true, если создание успешно

Версия: 27 и выше

Пример:

main.js:

tl.directory.create("files/textures");
tl.log(tl.directory.exists("files/textures"));

Содержимое лога: "true"

⬆ Оглавление


tl.directory.delete(String directoryPath) -> Boolean

Описание: удаляет директорию по указанному пути и возвращает true, если удаление успешно

Версия: 27 и выше

Пример:

main.js:

tl.directory.create("files/textures");
tl.log(tl.directory.delete("files/textures"));

Содержимое лога: "true"

⬆ Оглавление


tl.directory.exists(String directoryPath) -> Boolean

Описание: проверяет наличие директории по указанному пути

Версия: 27 и выше

Пример:

main.js:

tl.directory.create("files/textures");
tl.log(tl.directory.exists("files/textures"));

Содержимое лога: "true"

⬆ Оглавление


tl.directory.listDirectories(String directoryPath) -> String[]

Описание: возвращает список директорий по указанному пути

Версия: 27 и выше

Пример:

main.js:

tl.directory.create("files/textures/custom");
tl.directory.create("files/sounds");
tl.file.write("files/file.txt", "Hello");
tl.log(tl.directory.listDirectories("files"));

Содержимое лога: "files/textures","files/sounds"

⬆ Оглавление


tl.directory.listFiles(String directoryPath) -> String[]

Описание: возвращает список файлов по указанному пути

Версия: 27 и выше

Пример:

main.js:

tl.directory.create("files/textures/custom");
tl.directory.create("files/sounds");
tl.file.write("files/file.txt", "Hello");
tl.log(tl.directory.listFiles("files"));

Содержимое лога: "files/file.txt"

⬆ Оглавление


tl.log(Object data)

Описание: выводит переданный объект в лог

Версия: 22 и выше

Пример:

main.js:

tl.log("Привет мир!")

Содержимое лога: "Привет мир!"

⬆ Оглавление