"Тестирование скриптов без обрушения и перезапуска игры"
Тестирование скриптов без обрушения и перезапуска игры
Ключевыми элементами являются две функции из стандартной библиотеки Lua:
dofile - позволяет загрузить и выполнить как chunk внешний файл.
pcall - позволяет выполнить произвольную функцию в т.н. защищённом режиме. Это значит, что любая ошибка интерпретатора Lua не выйдет за пределы функции, вызванной таким образом. Напомню, что обычно любая ошибка времени выполнения Lua передаётся хост-программе, т.е. игре, и вызывает её вылет. Ну и собственно рецепт пилюли
следующий фрагмент может, скажем, выполняться по горячей клавише из главного меню.
Код
local res, err = pcall(my_proxy.start_chunk_from_file)
get_console():execute(res and "Succesfull!" or string.gsub(err, " ", "_")) --имитация тернарного оператора
pcall возвращает два значения. Первое - результат запуска. Если все прошло пучком, то true. Второе - добавочное значение с сообщением об ошибке, если ошибка была. Иначе nil.
файл my_proxy.script содержит всего одну функцию
Код
function start_chunk_from_file()
local chunk, err = dofile("..\\gamedata\\scripts\\test.lua")
if err then
get_console():execute("err="..tostring(string.gsub(err, " ", "_")))
end
end
dofile принимает имя файла со скриптом, загружает его и выполняет как функцию. Путём экспериментов я выяснил, что текущим каталогом Lua считает папку bin. Так что если хотим держать скрипт там, где и все остальные, то пишем путь относительно этой папки "..\\gamedata\\scripts\\test.lua".
test.lua - это отлаживаемый скрипт.
Обработка ошибок осуществляется аналогично pcall.
Так можно не выходя из игры и даже не перегружая уровень копаться в скрипте test.lua и запускать его по много раз, существенно менее рискуя обрушить игру. Особенно удобно, если есть два компа и сетка. В этом случае даже Alt-Tab не нужен. Редактируешь файл по сети на одном компе, а запускаешь в загруженной игре на другом.
Само-собой, если сделаем что-то, что фатально затронет игровую логику или что-то из ошибок категории 3, то обрушение может всё равно случиться. Сразу или в другом месте. В основном, в таких случаях уже ничего не поделаешь. Однако, довольно часто можно свести потенциальную ошибку времени выполнения движка к ошибке Lua. Например, если вызвать функцию get_console():execute(<аргумент>) с нулевым аргументом, то получим вылет без лога. Однако ничто не мешает сделать так:
get_console():execute("value="..obj)
В этом случае сначала будет выполняться конкатенация двух строк. Если obj будет равно nil, то получим ошибку Lua, а её тестовый полигон не пропустит, и обрушения игры не будет.
И ещё. Это всё работает для ТЧ. Для ЧН мне наладить такой же полигон не удалось. Что-то там изменено в движке, что вызывает у него аллергию на функцию pcall.