Skip to content

JavaScript API en

And42 edited this page Dec 19, 2024 · 2 revisions

JavaScript API

Mods are written in JavaScript. By default, JavaScript does not provide any methods for working with Terraria or mods. However, these methods are necessary, otherwise JavaScript would be useless. Therefore, TL provides an API (a set of functions) that allows you to work with the game and mods.

The set of available functions depends on the pack structure version (which can be viewed and modified in TL Packer or manually in the packStructureVersion field in the pack's Settings.json). We strive to ensure that new TL versions support working with all structure versions so that mods don't need to be rewritten after we change some functions. Ideally, mods should be created using the latest pack structure version available at the time of mod creation to access the maximum number of functions.

Type Conversions:

In C#, there are concepts of boxing and unboxing. Boxing occurs when an instance of a structure (or primitive) is converted to an object type. Example: object number = 3 - the primitive 3 is boxed into an object. In C#, boxing is done automatically, but for unboxing you need to specify the concrete type in parentheses (Example: object boxedNumber = 3; int unboxedNumber = (int) boxedNumber).

The TL Mod API automatically converts primitive types to their JavaScript equivalents when working with C# objects for convenience. For example, the field Terraria.ID.ItemID.SummonerEmblem has a type of short, so the code new NativeClass('Terraria.ID', 'ItemID').SummonerEmblem automatically converts the returned value to the Number type in JavaScript.

These type conversions usually don't cause problems, but sometimes they do.

For example, you might need to pass an object as an argument to a function when creating and filling an int array:

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) // Will throw an error due to type mismatch - an object is needed, but a primitive is passed
SetValue(newArray, NativeObject.wrap(20, 'int'), 0n); // All good
const arrayBoxedValue = GetValue(newArray, 0n); // The type of `arrayBoxedValue` is NativeObject, in other words, a boxed primitive value
const arrayUnboxedValue = NativeObject.unwrap(arrayBoxedValue); // The type of `arrayUnboxedValue` is `Number`

In the example above, the Array.SetValue method, according to its signature, takes a value of type object as the first argument. If you pass a JavaScript Number (20) instead of a NativeObject, the Mod API will not be able to determine which primitive type this number should be converted to (whether it should be passed as int, short, byte, etc.). Therefore, before passing the value, it needs to be wrapped using NativeObject.wrap.

The Array.GetValue method, according to its signature, returns an object, so arrayBoxedValue will not be automatically converted to a JavaScript Number. To convert it and perform calculations using standard JavaScript operations, you need to use the NativeObject.unwrap function.

NativeObject.wrap/unwrap is also used to convert other C# objects to their JavaScript equivalents. For example, calling NativeObject.wrap('hello', 'string') will return a wrapped instance of type string, and NativeObject.unwrap(<some string object>) will return a JavaScript string.

For information on the NativeObject.wrap/unwrap methods, see below.

Table of contents

  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

Description: returns the path to the folder of the current script.

Version: 22 and above

Example:

main.js

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

callScript();

inner/script.js

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

Log content: "inner"

⬆ Table of Contents


new NativeClass(String namespace, String name)

Description: creates a new instance of the NativeClass. This class allows you to work with methods from C#

Version: 22 and above

Example:

main.js

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

Log content: 2998

⬆ Table of Contents


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

Description: allows working with generic C# classes

Version: 22 and above

Example:

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

Log content: 15

⬆ Table of Contents


NativeClass.new() -> NativeObject

Description: allows creating instances of objects

Important: after creating an object, you must call one of the class constructors on the created instance. If this is not done, the object's fields will be uninitialized, which can lead to unexpected problems when working with the object

Version: 22 and above

Example:

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

Log content: 2

⬆ Table of Contents


NativeClass.property or NativeClass["property"]

Description: allows working with methods/properties/fields of a C# class

Version: 22 and above

Example 1 - static field:

main.js

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

Log content:

2998
2998

Example 2 - static method:

main.js

const Path = new NativeClass('System.IO', 'Path');
const method1 = Path.GetExtension; // Works because Path has only one method named GetExtension
const method2 = Path['string GetExtension(string path)'];
tl.log(method1('file.txt'));
tl.log(method2('file.txt'));

Log content:

.txt
.txt

⬆ Table of Contents


static NativeClass.unwrap(NativeObject wrappedValue) -> Any

Description: сonverts C# objects to JavaScript objects

Version: 27 and above

Example:

main.js

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

const someArray = ... // `someArray` is a NativeObject with an array of `int` inside

const arrayBoxedValue = GetValue(newArray, 0n); // Type of `arrayBoxedValue` is NativeObject
const arrayUnboxedValue = NativeObject.unwrap(arrayBoxedValue); // Type of `arrayUnboxedValue` is `Number`

⬆ Table of Contents


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

Description: converts JavaScript objects to C# objects

Version: 27 and above

Example:

main.js

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

const someArray = ... // someArray is a NativeObject with an array of int inside

const valueToSetUnboxed = 20; // Type of valueToSetUnboxed is Number
const valueToSetBoxed = NativeObject.wrap(valueToSetUnboxed, 'int'); // Type of valueToSetBoxed is NativeObject
SetValue(someArray, valueToSetBoxed, 0n);

⬆ Table of Contents


tl.info.terrariaVersionName String

Description: returns the string version of Terraria

Version: 22 and above

Example:

main.js:

tl.log(tl.info.terrariaVersionName)

Log content: "1.4.0.5.2.1"

⬆ Table of Contents


tl.info.terrariaVersionCode Integer

Description: returns the integer version of Terraria

Version: 22 and above

Example:

main.js:

tl.log(tl.info.terrariaVersionCode)

Log content: 300543

⬆ Table of Contents


tl.mod.name String

Description: returns the pack name taken from the title field of the Settings.json file

Version: 22 and above

Example: Settings.json:

{
    "title": "Interesting pack"
}
tl.log(tl.mod.name);

Log content: "Interesting pack"

⬆ Table of Contents


tl.mod.path String

Description: returns the path to the mod directory on the user's device. TL functions that work with files consider this path as the root directory where the required file path is searched. For example, tl.file.read("some_file.txt") will read the file from the folder tl.mod.path + '/some_file.txt', this happens implicitly

Version: 22 and above

Example: main.js

tl.log(tl.mod.path);

Log content: "/storage/emulated/0/Android/data/com.pixelcurves.terlauncher/tl_files/packs/7634960c-2c5a-4509-b586-c26a35fa5546/Modified/1.mod"

⬆ Table of Contents


tl.mod.uuid String

Description: returns the id of the mod - the id field inside the <mod_dir>.json file

Version: 22 and above

Example: <mod_dir>.json:

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

Log content: ae7d54e7-c8db-4d66-bb50-713c76b76d59

⬆ Table of Contents


tl.mod.packUuid String

Description: returns the id of the mod's pack - the guid field inside the Settings.json file

Version: 22 and above

Example:

Settings.json:

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

Log content: 7634960c-2c5a-4509-b586-c26a35fa5546

⬆ Table of Contents


tl.mod.packStructureVersion Integer

Description: returns the pack structure version of the mod - the packStructureVersion field inside the Settings.json file

Version: 22 and above

Example:

Settings.json:

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

Log content: "17"

⬆ Table of Contents


tl.mod.dataDirectory String

Description: returns the directory where files are saved when the pack is updated. Use this folder to store mod data

Version: 27 and above

Example 1 (output path):

main.js

tl.log(tl.mod.dataDirectory)

Log content: "data"

Example 2 (saving and restoring data):

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

Log content: "Hello everyone"

⬆ Table of Contents


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

Description: adds a translation for the specified language

Version: 22 and above

Example: TBD

⬆ Table of Contents


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

Description: deletes the file at the specified path and returns true if the deletion is successful

Version: 27 and above

Example:

main.js:

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

Log content: "true"

⬆ Table of Contents


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

Description: checks for the existence of a file at the specified path

Version: 22 and above

Example:

main.js:

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

Log content: "true"

⬆ Table of Contents


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

Description: reads text from a file in UTF-8 encoding and returns it as a string

Version: 27 and above

Example:

main.js:

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

Log content: "Hello"

⬆ Table of Contents


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

Description: writes text to a file in UTF-8 encoding

Version: 27 and above

Example:

main.js:

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

Log content: "Hello"

⬆ Table of Contents


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

Description: adds a new item with the name itemName to the game and returns its ID

Version: 22 and above

Example:

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

Log content: "6000"

⬆ Table of Contents


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

Description: loads an image in .png format from a file, converts it to Xna Texture2D, and returns it

Version: 22 and above

Example:

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

⬆ Table of Contents


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

Description: TBD

Version: 22 and above

Example: TBD

⬆ Table of Contents


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

Description: returns the current list of item categories in the cheat menu

Version: 22 and above

Example:

main.js:

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

Log content: "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"

⬆ Table of Contents


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

Description: adds a new category to the list of item categories in the cheat menu and returns its name (": ") in the category list

Version: 22 and above

Example:

main.js:

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

Log content:

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

⬆ Table of Contents


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

Description: adds an item to the specified item category in the cheat menu and returns whether the addition was successful (unsuccessful if the category with the specified name is not found)

Version: 22 and above

Example:

main.js:

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

⬆ Table of Contents


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

Description: creates a directory with subdirectories at the specified path and returns true if the creation is successful

Version: 27 and above

Example:

main.js:

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

Log content: "true"

⬆ Table of Contents


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

Description: deletes the directory at the specified path and returns true if the deletion is successful

Version: 27 and above

Example:

main.js:

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

Log content: "true"

⬆ Table of Contents


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

Description: checks for the existence of a directory at the specified path

Version: 27 and above

Example:

main.js:

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

Log content: "true"

⬆ Table of Contents


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

Description: returns a list of directories at the specified path

Version: 27 and above

Example:

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

Log content: "files/textures","files/sounds"

⬆ Table of Contents


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

Description: returns a list of files at the specified path

Version: 27 and above

Example:

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

Log content: "files/file.txt"

⬆ Table of Contents


tl.log(Object data)

Description: logs the passed object

Version: 22 and above

Example:

main.js:

tl.log("Hello world!")

Log content: "Hello world!"

⬆ Table of Contents