Skip to content

Helpers

Les helpers sont un ensemble de fonctions auxiliaires Lua pour un travail confortable dans le projet.

Ces fonctions helper étendent considérablement les capacités standard de Lua et simplifient le développement.


String

Méthodes fournies par Luanti :

string:lower()

Convertit la chaîne en minuscules avec support pour le cyrillique.

lua
print(('ПРИВЕТ МИР'):lower())  -- 'привет мир'

string:upper()

Convertit la chaîne en majuscules avec support pour le cyrillique.

lua
print(string.upper('привет мир'))  -- 'ПРИВЕТ МИР'

string:is_one_of(table)

Vérifie si la chaîne est l'une des valeurs dans le tableau passé.
(Analogue sémantique de table.contains, qui vérifie si la chaîne est contenue dans le tableau passé.)

lua
local text = 'hello'
local options = { 'hello', 'world', 'lua' }
print(text:is_one_of(options))  -- true

string:first_to_upper()

Convertit la première lettre en majuscule.

lua
local text = 'hello world'
print(text:first_to_upper())  -- 'Hello world'

string :title()/:to_headline()

Convertit la première lettre de chaque mot en title case.
Nom alternatif : string:to_headline()

lua
local text = 'hello world from lua'
print(text:title())           -- 'Hello World From Lua'
print(text:to_headline())     -- 'Hello World From Lua'

string:starts_with(prefix)

Vérifie si la chaîne commence avec le préfixe spécifié.

lua
local filename = 'config.json'
print(filename:starts_with('config'))    -- true
print(filename:starts_with('settings'))  -- false

string:ends_with(suffix)

Vérifie si la chaîne se termine avec le suffixe spécifié.

lua
local filename = 'config.json'
print(filename:ends_with('.json'))    -- true
print(filename:ends_with('.conf'))    -- false

string:contains(sub_string)

Vérifie la présence d'une sous-chaîne.

lua
local text = 'Hello, World !!!'
print(text:contains('World'))   -- true
print(text:contains('world'))   -- false (sensible à la casse)

string:replace(pattern, replacement, n?)

Remplace la sous-chaîne (analogue de gsub, mais retourne seulement la chaîne sans le nombre de remplacements).
Voir la documentation pour string.gsub et Patterns

lua
local text = 'Hello, World, World!'
local result = text:replace('World', 'Lua')
print(result)  -- 'Hello, Lua, Lua!'

-- Remplacer seulement la première occurrence
local result2 = text:replace('World', 'Lua', 1)
print(result2)  -- 'Hello, Lua, World!'

string:remove(pattern, n?)

Supprime la sous-chaîne.
Voir la documentation pour string.gsub et Patterns

lua
local text = 'Hello, World!'
print(text:remove(', '))        -- 'HelloWorld!'
print(text:remove('o', 1))      -- 'Hell, Wrld!' (supprimer seulement le premier 'o')

string:reg_escape()

Échappe les caractères spéciaux pour les expressions régulières.
Voir Patterns

lua
local pattern = 'file.txt'
print(pattern:reg_escape())      -- 'file%.txt'

local pattern2 = '^$()%.[]*+-?)'
print(pattern2:reg_escape())     -- '%^%$()%.%[%]%*%+\-%?)'

string:vxr_split(delimiter?, processor?)

Divise la chaîne par le delimiter spécifié avec la capacité de traiter les parties.

Luanti a sa propre méthode string.split, mais elle ne supporte pas le traitement des parties.
Cette méthode ajoute la capacité de traiter les parties de la chaîne.

lua
-- Sans traitement
('hello world'):vxr_split()             -- { 'hello', 'world' }
('apple,banana,cherry'):vxr_split(',')  -- { 'apple', 'banana', 'cherry' }

-- Avec traitement
local numbers = '1,2,3,4,5'
local squared = numbers:vxr_split(',', function(x)
    return tonumber(x)^2 
end)
print(squared[1], squared[2], squared[3], squared[4], squared[5])
-- 1 4 9 16 25

string.or_nil(value)

Convertit en chaîne ou retourne nil.

lua
print(string.or_nil('hello'))     -- 'hello'
print(string.or_nil(42))          -- '42'
print(string.or_nil(nil))         -- nil
print(tostring(nil))              -- 'nil' (comparaison)

Méthodes fournies par Luanti :

Luanti string.split()

Voir aussi : string.vxr_split(delimiter?, processor?)

Divise la chaîne en parties par le séparateur spécifié. Retourne un tableau de chaînes. Arguments :

  • separator? séparateur, par défaut : ","
  • include_empty? par défaut : false
  • max_splits? si négatif, divisions illimitées, par défaut : -1
  • sep_is_pattern? si le séparateur est une chaîne normale ou un pattern (regex), par défaut : false
lua
local text = 'apple,banana,cherry'
local parts = text.split(',')
print(parts[1], parts[2], parts[3])  -- 'apple', 'banana', 'cherry'

-- Diviser par espaces
local words = 'hello world lua'.split(' ')
print(words[1], words[2], words[3])  -- 'hello', 'world', 'lua'

Luanti string.trim()

Supprime les caractères d'espace au début et à la fin de la chaîne.

lua
print(("\n \t\tfoo bar\t "):trim())  -- 'foo bar'

Luanti string.pack()

Empaquette les valeurs dans une chaîne binaire selon le format.
Backport de Lua 5.4.

lua
-- Empaqueter des entiers
local packed = string.pack('i4', 42)
print(#packed)  -- 4 (taille en octets)

-- Empaqueter plusieurs valeurs
local data = string.pack('i4f8', 100, 3.14)
print(#data)  -- 12 (4 + 8 octets)

Luanti string.unpack()

Dépaquête la chaîne binaire en valeurs selon le format.
Backport de Lua 5.4.

lua
local packed = string.pack('i4f8', 100, 3.14)
local num, float, next_pos = string.unpack('i4f8', packed)
print(num, float)      -- 100, 3.14
print(next_pos)        -- 13 (position après dépaquetage)

-- Dépaqueter depuis la position spécifiée
local value = string.unpack('i4', packed, 5)
print(value)            -- 3.14 (comme float)

Luanti string.packsize()

Retourne la taille de la chaîne qui sera créée par string.pack.
Backport de Lua 5.4.

lua
local size = string.packsize('i4f8')
print(size)  -- 12 (4 + 8 octets)

-- Pour les formats complexes
local complex_size = string.packsize('i4c10f8')
print(complex_size)  -- 22 (4 + 10 + 8 octets)

Table

Méthodes, fournies par Luanti :

  • table.copy()
  • table.copy_with_metatables()
  • table.insert_all()
  • table.indexof()
  • table.keyof()
  • table.key_value_swap()
  • table.shuffle()

table.keys(table)

Retourne un tableau de clés de la table.

lua
local data = { name = 'Alek', age = 25, city = 'Vladivostok' }

local keys = table.keys(data)
-- `keys` contient `{ 'name', 'age', 'city' }` (l'ordre peut varier)

table.values(table)

Retourne un tableau de valeurs de la table.

lua
local data = { name = 'Alek', age = 25, city = 'Vladivostok' }

local values = table.values(data)
-- `values` contient { 'Alek', 25, 'Vladivostok' }

table.has_key(table, key)

Vérifie si une clé existe dans la table.

lua
local data = { name = 'Alek', age = 25 }
print(table.has_key(data, 'name'))   -- true
print(table.has_key(data, 'city'))   -- false

table .contains/has_value(table, value)

Vérifie si une valeur existe dans la table.

lua
local fruits = { 'apple', 'banana', 'cherry' }
print(table.contains(fruits, 'banana'))  -- true
print(table.contains(fruits, 'orange'))  -- false

Vous pouvez aussi utiliser string:is_one_of() :

lua
print('banana':is_one_of(fruits))  -- true
print('orange':is_one_of(fruits))  -- false

Nom alternatif : table.has_value

lua
local data = { x = 10, y = 20 }
print(table.has_value(data, 10))     -- true
print(table.has_value(data, 30))     -- false

table.keys_of(table, value)

Retourne une table avec les clés de la table spécifiée qui ont la valeur spécifiée.

lua
local data = { a = 10, b = 20, c = 10, d = 30 }
local keys = table.keys_of(data, 10)
print(dump(keys))  -- { 'a', 'c' }

local keys2 = table.keys_of(data, 99)
print(keys2)  -- nil (aucune clé ainsi)

table.has_any_key(table, find_keys)

Vérifie si les clés de la table contiennent au moins une valeur du tableau spécifié.

lua
local data = { name = 'test', age = 25, active = true }
local find_keys = { 'name', 'email', 'phone' }

print(table.has_any_key(data, find_keys))   -- true (clé 'name' est dans find_keys)

local find_keys2 = { 'email', 'phone', 'address' }
print(table.has_any_key(data, find_keys2))  -- false

table.equals(table1, table2)

Compare récursivement deux tables pour égalité complète.

lua
local table1 = { a = 1, b = { c = 2, d = 3 } }
local table2 = { a = 1, b = { c = 2, d = 3 } }
local table3 = { a = 1, b = { c = 2, d = 4 } }

print(table.equals(table1, table2))  -- true
print(table.equals(table1, table3))  -- false

table.is_empty(table)

Vérifie si la table est vide.

lua
print(table.is_empty({}))           -- true
print(table.is_empty({ a = 1 }))    -- false

table.is_position(table)

Vérifie si la table représente des coordonnées.

lua
print(table.is_position({ x = 10, y = 20, z = 30 }))  -- true
print(table.is_position({ x = 10, y = 20 }))          -- false
print(table.is_position({ a = 1, b = 2, c = 3 }))     -- false

table.each_value_is(table, value)

Vérifie que tous les éléments de la table sont égaux à la valeur spécifiée. Par défaut vérifie pour true.

lua
local data1 = { true, true, true }
print(table.each_value_is(data1))  -- true

local data2 = { 5, 5, 5, 5 }
print(table.each_value_is(data2, 5))  -- true

local data3 = { 1, 2, 3 }
print(table.each_value_is(data3, 1))  -- false

table.count(table)

Compte le nombre d'éléments dans la table.

NOTE

Pour les tables avec des clés entières, utilisez #table.
Comme l'opérateur # ne fonctionne pas sur les tables avec des clés non-entières, utilisez table.count pour elles.

lua
local data = { a = 1, b = 2, c = 3 }
print(table.count(data))  -- 3
print(#data)              -- 0, parce que l'opérateur `#` ne fonctionne pas avec des clés non-entières.

local array = { 1, 2, 3, 4, 5 }
print(#array) -- 5

table.generate_sequence(max, start_from?, step?)

Génère une séquence de nombres.

lua
local seq1 = table.generate_sequence(5)
print(dump(seq1))  -- { 1, 2, 3, 4, 5 }

local seq2 = table.generate_sequence(10, 2, 2)
print(dump(seq2))  -- { 2, 4, 6, 8, 10 }

local seq3 = table.generate_sequence(1, 5, -1)
print(dump(seq3))  -- { 5, 4, 3, 2, 1 }

table.only(table, only)

Retourne une nouvelle table contenant des données seulement avec les clés spécifiées.

lua
local data = { name = 'Alek', age = 25, city = 'Vladivostok', country = 'Russia' }
local filtered = table.only(data, { 'name', 'age' })
-- `filtered` contient `{ name = 'Alek', age = 25 }`
print(filtered.name, filtered.age)    -- 'Alek', 25
print(filtered.city)                  -- nil

table.except(table, keys)

Retourne une nouvelle table contenant des données sans les clés spécifiées.
(copie la table, excluant les clés spécifiées)

lua
local data = { name = 'Alek', age = 25, city = 'Vladivostok', country = 'Russia' }
local filtered = table.except(data, { 'age', 'country' })
-- `filtered` contient `{ name = 'Alek', city = 'Vladivostok' }`
print(filtered.name, filtered.city)      -- 'Alek', 'Vladivostok'
print(filtered.age,  filtered.country)   -- nil, nil

table.merge(table1, table2, overwrite?)

Fusionne les tables récursivement.

Par défaut, la première table n'est pas écrasée, une nouvelle est créée.

lua
local defaults = { theme = 'dark', font = { size = 12, family = 'Arial' } }
local user_config = { font = { size = 16 }, language = 'en' }

local merged = table.merge(defaults, user_config)
print(dump(merged))
-- {
--     theme = "dark",
--     font = {
--         size = 16,
--         family = "Arial",
--     },
--     language = "en",
-- }

Écraser la première table :

lua
table.merge(defaults, user_config, true)

TIP

Il est préférable d'utiliser table.overwrite() pour une meilleure lisibilité.

table.join(table1, table2, recursively?)

Ajoute les clés manquantes de table2 à table1.
Les valeurs qui sont des tables sont copiées en utilisant table.copy().

lua
local base     = { a = 1, b =  2        }
local addition = {        b = 10, c = 3 }

table.join(base, addition)
print(dump(base))  -- { a = 1, b = 2, c = 3 }

Si recursively est true, la fonction sera appliquée récursivement seulement pour les valeurs qui sont des tables dans les deux table1 et table2.

lua
local base     = { a = 1, b = { c = 2          } }
local addition = {        b = { c = 10, d = 20 } }

table.join(base, addition, true)
print(dump(base))
-- {
--     a = 1,
--     b = {
--         c = 2,
--         d = 20,
--     },
-- }

table.overwrite(table1, table2)

Écrase complètement table1 avec les valeurs de table2.

Variante sémantique pour table.merge(table1, table2, true).

table.merge_values(table1, table2)

Fusionne les valeurs de deux tables en une, supprimant les doublons.
L'ordre est préservé - d'abord les valeurs de table1, puis de table2 qui n'étaient pas dans table1.

lua
local table1 = { 'apple', 'banana', 'cherry' }
local table2 = { 'banana', 'date', 'apple', 'elderberry' }

local merged = table.merge_values(table1, table2)
print(dump(merged))  -- { 'apple', 'banana', 'cherry', 'date', 'elderberry' }

table.map(table, callback, overwrite?)

Applique la fonction à chaque élément de la table.
callback: fun(value: any, key: any): any - accepte la valeur et la clé, retourne une nouvelle valeur.

Par défaut retourne une nouvelle table.

lua
local numbers = { 1, 2, 3, 4, 5 }
local squared = table.map(numbers, function(x) return x * x end)
print(dump(squared))
-- { 1, 4, 9, 16, 25 }

local data = { a = 10, b = 20 }
local doubled = table.map(data, function(value, key)
	print(key, value)
	return value * 2
end)
-- a       10
-- b       20
print(dump(doubled))
-- { a = 20, b = 40 }

Si overwrite est true, alors la fonction modifie la table originale.

lua
local data = { a = 10, b = 20 }
table.map(data, function(value, key) return value * 2 end, true)
print(dump(data))  -- { a = 20, b = 40 }

table .walk/.each(table, callback)

Itère sur la table en appliquant la fonction (ne modifie pas la table).
callback: fun(value: any, key: any): void - accepte la valeur et la clé ; ne retourne rien.

lua
local data = { a = 10, b = 20, c = 30 }
table.walk(data, function(value, key)
    print(key, value)
end)
-- a       10
-- c       30
-- b       20

Nom alternatif : table.each()

lua
local data = { a = 10, b = 20, c = 30 }
table.each(data, function(value, key)
    data[key] = value * 2
    -- Rien n'empêche l'accès à l'upvalue `data`. Maintenant `data` a été écrasé.
end)
print(dump(data))  -- { a = 20, b = 40, c = 60 }

table.multiply_each_value(table, multiplier_table)

Multiplie chaque valeur de la table par la valeur correspondante de multiplier_table par clé.

lua
local data = { a = 10, b = 20, c = 30 }
local multipliers = { a = 2, b = 0.5, c = 3 }

local result = table.multiply_each_value(data, multipliers)
print(dump(result))  -- { a = 20, b = 10, c = 90 }
-- Les clés sans multiplicateur restent inchangées

table.add_values(table1, table2, empty_value?, overwrite?)

Ajoute les valeurs avec les mêmes clés de deux tables.

lua
local table1 = { a = 10, b = 20 }
local table2 = { b = 5, c = 15 }

local result = table.add_values(table1, table2)
print(dump(result))  -- { a = 10, b = 25, c = 15 }

-- Avec valeur vide pour les clés manquantes
local result2 = table.add_values(table1, table2, 0)
print(dump(result2))  -- { a = 10, b = 25, c = 15 }

table.sub_values(table1, table2, empty_value?, overwrite?)

Soustrait les valeurs table2 de table1 pour les clés égales.

lua
local table1 = { a = 10, b = 20, c = 30 }
local table2 = { b = 5, c = 10, d = 5 }

local result = table.sub_values(table1, table2)
print(dump(result))  -- { a = 10, b = 15, c = 20, d = -5 }

table.mul_values(table1, table2, empty_value?, overwrite?)

Multiplie les valeurs avec les mêmes clés de deux tables.

lua
local table1 = { a = 2, b = 3 }
local table2 = { b = 4, c = 5 }

local result = table.mul_values(table1, table2)
print(dump(result))  -- { a = 2, b = 12, c = 5 }

table.div_values(table1, table2, empty_value?, overwrite?)

Divise les valeurs table1 par les valeurs table2 pour les clés égales.

lua
local table1 = { a = 10, b = 20, c = 30 }
local table2 = { b = 5, c = 10, d = 2 }

local result = table.div_values(table1, table2)
print(dump(result))  -- { a = 10, b = 4, c = 3, d = 0.5 }

Math

math .limit/.clamp(value, min, max)

Limite la valeur à l'intervalle spécifié.
Nom alternatif : math.clamp().

lua
local health = 150
local max_health = 100
local clamped_health = math.limit(health, 0, max_health)
print(clamped_health)  -- 100

math.is_within(value, min, max)

Vérifie que la valeur est strictement dans l'intervalle (min < value < max).

lua
print(math.is_within(5, 1, 10))   -- true
print(math.is_within(1, 1, 10))   -- false (limites non inclus)
print(math.is_within(10, 1, 10))  -- false

math.is_among(value, min, max)

Vérifie que la valeur est dans l'intervalle, incluant les limites (min <= value <= max).

lua
print(math.is_among(5, 1, 10))   -- true
print(math.is_among(1, 1, 10))   -- true
print(math.is_among(10, 1, 10))  -- true

math.is_in_range(value, min, max)

Vérifie que la valeur est dans l'intervalle semi-ouvert (min, max] (min < value <= max).

lua
print(math.is_in_range(5, 1, 10))   -- true
print(math.is_in_range(1, 1, 10))   -- false (égal au minimum)
print(math.is_in_range(10, 1, 10))  -- true (égal au maximum)

math.is_near(value, near, gap?)

Vérifie que la valeur est proche de celle spécifiée (|value - near| <= gap).

lua
print(math.is_near(10, 12))        -- false (gap = 1 par défaut)
print(math.is_near(11, 12))        -- true
print(math.is_near(10, 12, 3))     -- true (gap = 3)

math.quadratic_equation_roots(a, b, c)

Résout l'équation quadratique de la forme y = a*x^2 + b*x + c.

lua
local root1, root2 = math.quadratic_equation_roots(1, -5, 6)
print(root1, root2)  -- 3, 2

-- Pas de racines réelles
local r1, r2 = math.quadratic_equation_roots(1, 0, 1)
print(r1, r2)  -- nil, nil

math.point_on_circle(radius, angle)

Calcule un point sur un cercle.

lua
local x, z = math.point_on_circle(5, math.pi/4)
print(x, z)  -- coordonnées d'un point sur un cercle de rayon 5 à l'angle 45°

Debug

__FILE__(depth?, full?)

Retourne le nom du fichier actuel ou du fichier de la fonction appelante selon la profondeur de la pile.

  • depth? - profondeur de la pile d'appels (par défaut 0)
  • full? - afficher le chemin complet (par défaut false)
lua
-- Obtenir le chemin relatif du fichier
print(__FILE__())  -- 'mods/Voxrame/helpers/src/lua_ext/debug.lua'

-- Obtenir le chemin complet du fichier
print(__FILE__(0, true))  -- '/home/alek13/projects/my-game/mods/Voxrame/helpers/src/lua_ext/debug.lua'

-- Obtenir le fichier 2 niveaux au-dessus dans la pile d'appels
print(__FILE__(2))  -- fichier de la fonction qui a appelé la fonction appelante

__LINE__(depth?)

Retourne le numéro de ligne actuel ou de la ligne de la fonction appelante selon la profondeur de la pile.

lua
print(__LINE__())  -- 57

-- Obtenir le numéro de ligne de la fonction appelante
print(__LINE__(1))  -- numéro de ligne dans le fichier d'appel

__FILE_LINE__(depth?, full?)

Retourne fichier et ligne au format "chemin/relatif/vers/fichier:ligne".

lua
print(__FILE_LINE__())  -- 'mods/Voxrame/helpers/src/lua_ext/debug.lua:65'

-- Avec chemin complet
print(__FILE_LINE__(0, true))  -- '/home/alek13/projects/my-game/mods/Voxrame/helpers/src/lua_ext/debug.lua:65'

__DIR__(depth?)

Retourne le répertoire du fichier actuel ou du fichier de la fonction appelante selon la profondeur de la pile.

lua
print(__DIR__())  -- 'mods/Voxrame/helpers/src/lua_ext/'

__FUNC__(depth?)

Retourne le nom de la fonction actuelle.

lua
function my_function()
    print(__FUNC__())  -- 'my_function'
end

Affiche le contenu de tous les paramètres passés ....
Avant l'affichage, ajoute le nom du fichier et la ligne @ <file>:<line>.

Si with_trace est true, affiche également la pile d'appels.

NOTE

Si votre terminal supporte les liens, chaque @ <file>:<line> sera lié à l'ouverture de l'IDE, voir readme.md pour la configuration.

TIP

Utilisez pd() et pdt() pour une syntaxe plus concise. Voir les exemples ci-dessous.

pd(...)

Abréviation pour print_dump. Appelle print_dump avec with_trace == false.

lua
local player_name = 'test_player'
local position = { x = 10, y = 20, z = 30 }

pd(player_name, position)

output:

[93m@ [0m[33mmods/lord/Core/map/src/map/Corridor.lua[0m[97m:[0m[32m14[0m
[36mplayer_name:[0m "test_player"
[36m   position:[0m {
    x = 10,
    y = 20,
    z = 30,
}

pdt(...)

Abréviation pour print_dump traced. Appelle print_dump avec with_trace == true.

lua
local player_name = 'test_player'
local position = { x = 10, y = 20, z = 30 }

pdt(player_name, position)

output:

[93m@ [0m[33mmods/lord/Core/map/src/map/Corridor.lua[0m[97m:[0m[32m14[0m
[3m[2m   1   [0m[93m@[0m [C][36m: in dofile[0m
[3m[2m   2   [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod/require.lua[0m[97m:[0m[32m29[0m[36m: in require[0m
[3m[2m   3   [0m[93m@ [0m[33mmods/lord/Core/map/src/map.lua[0m[97m:[0m[32m9[0m[36m: in main[0m
[3m[2m   4   [0m[93m@ [0m [C][36m: in dofile[0m
[3m[2m   5   [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod/require.lua[0m[97m:[0m[32m29[0m[36m: in require[0m
[3m[2m   6   [0m[93m@ [0m[33mmods/lord/Core/map/init.lua[0m[97m:[0m[32m4[0m[36m: in mod_init_function[0m
[3m[2m   7   [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod.lua[0m[97m:[0m[32m80[0m[36m: in mod[0m
[3m[2m   8   [0m[93m@ [0m[33mmods/lord/Core/map/init.lua[0m[97m:[0m[32m3[0m[36m: in main[0m
[36mplayer_name:[0m "test_player"
[36m   position:[0m {
    x = 10,
    y = 20,
    z = 30,
}

debug.measure(name, callback, print_result?)

Mesure le temps d'exécution de la fonction.

lua
local function heavy_calculation()
    local sum = 0
    for i = 1, 2000000 do
        sum = sum + math.random(1, 100) + math.sin(i)
    end
end

-- Mesurer avec sortie de résultat
debug.measure('calculation', heavy_calculation, true)
debug.measure('calculation', heavy_calculation, true)
debug.measure('calculation', heavy_calculation, true)
debug.measure('calculation', heavy_calculation, true)
debug.measure('calculation', heavy_calculation, true)
-- output:
-- Measure of [calculation]:  Time:    42 ms ;  Average:    42 ms
-- Measure of [calculation]:  Time:    58 ms ;  Average:    50 ms
-- Measure of [calculation]:  Time:    58 ms ;  Average:    53 ms
-- Measure of [calculation]:  Time:    35 ms ;  Average:    48 ms
-- Measure of [calculation]:  Time:    33 ms ;  Average:    45 ms


-- Mesurer sans sortie
local time, avg, count = debug.measure('calculation', heavy_calculation)
print(time, avg, count)
local time, avg, count = debug.measure('calculation', heavy_calculation)
print(time, avg, count)
-- output:
-- 33.075  43.170833333333 6
-- 33.135  41.737142857143 7

debug.mesure_print(name)

Affiche les statistiques des mesures précédentes name obtenues par les appels à debug.measure(name, ....).

lua
debug.mesure_print('calculation')
-- output:
-- Measure of [calculation]: Average time:    42 ms ; Last time:    33 ms ; Count of mesures:     7

Global

errorf(message, ...)

Similaire à error() dans Lua, mais message peut être un string template avec des paramètres spécifiés, similaire à string.format().

lua
local player_name = nil
errorf('Joueur '%s' non trouvé', player_name)
-- Erreur: Joueur 'nil' non trouvé

output (quand debug est activé) :

[93m@ [0m[33mmods/lord/Core/map/src/map/Corridor.lua[0m[97m:[0m[32m9[0m
[32m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[0m
[1m[91mERROR:[0m
[91m  Joueur `nil` non trouvé[0m

[1m[91mStack trace:[0m
[3m[2m   1   [0m[93m@[0m [C][36m: in error[0m
[3m[2m   2   [0m[93m@ [0m[33mmods/lord/Core/helpers/src/lua_ext/global.lua[0m[97m:[0m[32m9[0m[36m: in errorf[0m
[3m[2m   3   [0m[93m@ [0m[33mmods/lord/Core/map/src/map/Corridor.lua[0m[97m:[0m[32m12[0m[36m: in main[0m
[3m[2m   4   [0m[93m@ [0m [C][36m: in dofile[0m
[3m[2m   5   [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod/require.lua[0m[97m:[0m[32m29[0m[36m: in require[0m
[3m[2m   6   [0m[93m@ [0m[33mmods/lord/Core/map/src/map.lua[0m[97m:[0m[32m9[0m[36m: in main[0m
[3m[2m   7   [0m[93m@ [0m [C][36m: in dofile[0m
[3m[2m   8   [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod/require.lua[0m[97m:[0m[32m29[0m[36m: in require[0m
[3m[2m   9   [0m[93m@ [0m[33mmods/lord/Core/map/init.lua[0m[97m:[0m[32m4[0m[36m: in mod_init_function[0m
[3m[2m  10   [0m[93m@ [0m[33mmods/lord/Core/builtin_ext/src/mod.lua[0m[97m:[0m[32m80[0m[36m: in mod[0m
[3m[2m  11   [0m[93m@ [0m[33mmods/lord/Core/map/init.lua[0m[97m:[0m[32m3[0m[36m: in main[0m

[32m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[0m
Gestion des erreurs dans Luanti

WARNING

La pile d'appels contiendra des lignes supplémentaires, car Luanti ne passe pas le level spécifié à core.error_handler().

errorlf(message, level, ...)

Comme dans errorf() vous pouvez passer un string de format et des paramètres, et aussi spécifier le niveau de trace.

lua
errorlf('Erreur dans les données', 3, 'valeur: %d', 42)
-- Erreur avec trace 3 niveaux au-dessus

voir gestion des erreurs dans Luanti

assertf(condition, message, ...)

Similaire à assert() dans Lua, mais comme message vous pouvez spécifier un string de format avec des paramètres, similaire à string.format().

Appelle errorf() si la condition condition n'est pas remplie.

lua
-- Continue l'exécution si player existe, sinon erreur
local player = nil
assertf(player, 'Joueur `%s` non trouvé', player)

IO

io.file_exists(name)

Vérifie si un fichier existe.

lua
if io.file_exists('config.txt') then
    print('Fichier de configuration trouvé')
else
    print('Fichier de configuration manquant')
end

io.dirname(path)

Retourne le répertoire du chemin.

lua
print(io.dirname('/home/user/project/file.txt'))  -- '/home/user/project'
print(io.dirname('relative/path/file.txt'))       -- 'relative/path'
print(io.dirname('file.txt'))                     -- '.'

io.write_to_file(filepath, content, mode?)

Écrit le contenu dans un fichier.

lua
local success, error_code, error_message = io.write_to_file('data.txt', 'Hello, World!')

if success then
    print('Données écrites avec succès')
else
    print('Erreur d'écriture:', error_code, error_message)
end

-- Ajouter à la fin du fichier
io.write_to_file('log.txt', 'Nouvelle entrée\n', 'a')

io.read_from_file(filepath, mode?)

Lit tout le contenu d'un fichier.
Retourne un string avec le contenu du fichier en cas de succès ou false, error_code, error_message en cas d'erreur.

lua
local content = io.read_from_file('config.json')
if content then
    print('Contenu du fichier:', content)
else
    print('Erreur de lecture du fichier')
end

Gestion des erreurs

lua
local success, error_code, error_message = io.read_from_file('nonexistent.txt')
if not success then
    print('Erreur:', error_code, error_message)
end
-- Erreur: 2       nonexistent.txt: No such file or directory

ou:

lua
local success = io.read_from_file('nonexistent.txt')
if not success then
    local error_code, error_message = io.get_file_error()
    print('Erreur:', error_code, error_message)
end
-- Erreur: 2       nonexistent.txt: No such file or directory

Lecture en mode binaire

lua
local binary_content = io.read_from_file('image.png', 'rb')
if binary_content then
    print('Taille du fichier:', #binary_content, 'octets')
end

io.get_file_error()

Retourne le code et le message de la dernière erreur des fonctions io.read_from_file() ou io.write_to_file().

lua
local success = io.read_from_file('nonexistent.txt')
if not success then
    local error_code, error_message = io.get_file_error()
    print('Erreur:', error_code, error_message)
end
-- Output: Erreur: 2       nonexistent.txt: No such file or directory
lua
local success = io.write_to_file('/readonly/file.txt', 'data')
if not success then
    local error_code, error_message = io.get_file_error()
    print('Erreur d'écriture:', error_code, error_message)
end
-- Output: Erreur d'écriture: 13       /readonly/file.txt: Permission denied

OS

os.DIRECTORY_SEPARATOR

Séparateur de répertoire pour le système d'exploitation actuel.

lua
local DS = os.DIRECTORY_SEPARATOR

print(DS)  -- '/' sur Linux/Mac, '\' sur Windows
print('folder' .. DS .. 'file.txt')
-- sur Linux/Mac: 'folder/file.txt'
-- sur Windows:   'folder\file.txt'