mirror of
https://github.com/Dadido3/noita-mapcap.git
synced 2024-12-22 02:17:33 +00:00
Fix compatibility stuff
- Make dofile more conform to standard lua - Move dofile from live-reload.lua to compatibility.lua - Let dofile and require throw errors on script errors - Fix bug in recursion detection - Remove Noita's dofile annotation - Fix some EmmyLua annotations - Improve print replacement
This commit is contained in:
parent
e863ba459b
commit
403167b366
@ -1416,10 +1416,6 @@ function SetValueBool(key, value) end
|
||||
---@param default_value number
|
||||
---@return boolean
|
||||
function GetValueBool(key, default_value) end
|
||||
---Returns the script's return value, if any. Returns nil,error_string if the script had errors.
|
||||
---@param filename string
|
||||
---@return any script_return_type, string|nil error_string
|
||||
function dofile(filename) end
|
||||
---Runs the script only once per lua context, returns the script's return value, if any. Returns nil,error_string if the script had errors. For performance reasons it is recommended scripts use dofile_once(), unless the standard dofile behaviour is required.
|
||||
---@param filename string
|
||||
---@return any script_return_type, string|nil error_string
|
||||
|
@ -10,14 +10,16 @@
|
||||
if _NoitaAPICompatibilityWrapperGuard_ then return function(dummy) end end
|
||||
_NoitaAPICompatibilityWrapperGuard_ = true
|
||||
|
||||
-- Override print function to behave more like the standard lua one.
|
||||
local oldPrint = print
|
||||
function print(...)
|
||||
local arg = { ... }
|
||||
local stringArgs = {}
|
||||
|
||||
for i, v in ipairs(arg) do
|
||||
table.insert(stringArgs, tostring(v))
|
||||
-- Emulated print function that behaves more like the standard lua one.
|
||||
function print(...)
|
||||
local n = select("#", ...)
|
||||
|
||||
--for i, v in ipairs(arg) do
|
||||
local stringArgs = {}
|
||||
for i = 1, n do
|
||||
table.insert(stringArgs, tostring(select(i, ...)))
|
||||
end
|
||||
|
||||
oldPrint(unpack(stringArgs))
|
||||
@ -42,25 +44,40 @@ package.loaded = package.loaded or {
|
||||
--os = os,
|
||||
}
|
||||
|
||||
local oldDofile = dofile
|
||||
|
||||
---Emulated dofile to execute a lua script from disk and circumvent any caching.
|
||||
---Noita for some reason caches script files (Or loads them into its virtual filesystem)(Or caches compiled bytecode), so reloading script files from disk does not work without this.
|
||||
---
|
||||
---This conforms more with standard lua.
|
||||
---@param path string
|
||||
---@return any ...
|
||||
function dofile(path)
|
||||
local func, err = loadfile(path)
|
||||
if not func then error(err) end
|
||||
|
||||
return func()
|
||||
end
|
||||
|
||||
local oldRequire = require
|
||||
|
||||
local recursionSet = {}
|
||||
local recursionLast
|
||||
|
||||
---Emulated require function in case the Lua API is restricted.
|
||||
---It's probably good enough for most usecases.
|
||||
---
|
||||
---We need to override the default require in any case, as only dofile can access stuff in the virtual filesystem.
|
||||
---We need to override the default require in any case, as only dofile and loadfile can access stuff in the virtual filesystem.
|
||||
---@param modName string
|
||||
---@return any
|
||||
---@return any ...
|
||||
function require(modName)
|
||||
-- Check if package was already loaded, return previous result.
|
||||
if package.loaded[modName] ~= nil then return package.loaded[modName] end
|
||||
|
||||
if recursionSet[modName] then
|
||||
error(string.format("Cyclic dependency with module %q called by %q", modName, recursionLast))
|
||||
recursionSet = {}
|
||||
error(string.format("Cyclic dependency with module %q", modName))
|
||||
end
|
||||
recursionSet[modName], recursionLast = true, modName
|
||||
recursionSet[modName] = true
|
||||
|
||||
local notFoundStr = ""
|
||||
|
||||
@ -71,7 +88,7 @@ function require(modName)
|
||||
|
||||
if res == nil then res = true end
|
||||
package.loaded[modName] = res
|
||||
recursionSet[modName], recursionLast = nil, nil
|
||||
recursionSet[modName] = nil
|
||||
return res
|
||||
else
|
||||
notFoundStr = notFoundStr .. string.format("\tno field package.preload['%s']\n", modName)
|
||||
@ -84,14 +101,22 @@ function require(modName)
|
||||
local filePath = string.gsub(pathEntry, "?", modPath, 1) -- Insert modPath into "?" placeholder.
|
||||
local fixedPath = string.gsub(filePath, "^%.[\\/]", "") -- Need to remove "./" or ".\" at the beginning, as Noita allows only "data" and "mods".
|
||||
if fixedPath:sub(1, 4) == "data" or fixedPath:sub(1, 4) == "mods" then -- Ignore everything other than data and mod root path elements. It's not perfect, but this is just there to prevent console spam.
|
||||
local res, err = dofile(fixedPath)
|
||||
if err then
|
||||
notFoundStr = notFoundStr .. string.format("\tno file '%s'\n", filePath)
|
||||
else
|
||||
local func, err = loadfile(fixedPath)
|
||||
if func then
|
||||
local state, res = pcall(func)
|
||||
if not state then
|
||||
recursionSet = {}
|
||||
error(res)
|
||||
end
|
||||
if res == nil then res = true end
|
||||
package.loaded[modName] = res
|
||||
recursionSet[modName], recursionLast = nil, nil
|
||||
recursionSet[modName] = nil
|
||||
return res
|
||||
elseif err and err:sub(1, 45) == "Error loading lua script - file doesn't exist" then -- I hate to do that.
|
||||
notFoundStr = notFoundStr .. string.format("\tno file '%s'\n", filePath)
|
||||
else
|
||||
recursionSet = {}
|
||||
error(err)
|
||||
end
|
||||
else
|
||||
notFoundStr = notFoundStr .. string.format("\tnot allowed '%s'\n", filePath)
|
||||
@ -102,14 +127,14 @@ function require(modName)
|
||||
if oldRequire then
|
||||
local ok, res = pcall(oldRequire, modName)
|
||||
if ok then
|
||||
recursionSet[modName], recursionLast = nil, nil
|
||||
recursionSet[modName] = nil
|
||||
return res
|
||||
else
|
||||
notFoundStr = notFoundStr .. string.format("\toriginal require:%s", res)
|
||||
end
|
||||
end
|
||||
|
||||
recursionSet[modName], recursionLast = nil, nil
|
||||
recursionSet = {}
|
||||
error(string.format("module %q not found:\n%s", modName, notFoundStr))
|
||||
end
|
||||
|
||||
|
@ -5,31 +5,12 @@
|
||||
|
||||
-- Allows Noita mods to reload themselves every now and then.
|
||||
-- This helps dramatically with development, as we don't have to restart Noita for every change.
|
||||
-- To accomplish this, we need to override the default behavior of dofile and some other things.
|
||||
|
||||
local LiveReload = {}
|
||||
|
||||
local oldDofile = dofile
|
||||
---Overwritten dofile to execute a lua script from disk and cirumvent any caching.
|
||||
---Noita for some reason caches script files (Or loads them into its virtual filesystem)(Or caches compiled bytecode), so reloading script files from disk does not work without this.
|
||||
---
|
||||
---This is not fully conform the the standard lua implementation, but so isn't Noita's implementation.
|
||||
---@param path string
|
||||
---@return any result
|
||||
---@return string|nil err
|
||||
function dofile(path) ---TODO: Consider moving dofile into compatibility.lua
|
||||
local func, err = loadfile(path)
|
||||
if not func then return nil, err end
|
||||
|
||||
local status, res = pcall(func)
|
||||
if not status then return nil, res end
|
||||
|
||||
return res, nil
|
||||
end
|
||||
|
||||
---Reloads the mod's init file in the given interval in frames.
|
||||
---For reloading to work correctly, the mod has to be structured in a special way.
|
||||
---Like the usage of require and namespaces.
|
||||
---Like the usage of require, namespaces, correct error handling, ...
|
||||
---
|
||||
---Just put this into your `OnWorldPreUpdate` or `OnWorldPostUpdate` callback:
|
||||
---
|
||||
@ -42,11 +23,7 @@ function LiveReload:Reload(modPath, interval)
|
||||
if self.Counter < interval then return end
|
||||
self.Counter = nil
|
||||
|
||||
local res, err = dofile(modPath .. "init.lua")
|
||||
if err then
|
||||
print(string.format("Error reloading mod: %s", err))
|
||||
error(string.format("Error reloading mod: %s", err))
|
||||
end
|
||||
dofile(modPath .. "init.lua")
|
||||
end
|
||||
|
||||
return LiveReload
|
||||
|
4
init.lua
4
init.lua
@ -24,7 +24,7 @@ end
|
||||
local CameraAPI = require("noita-api.camera")
|
||||
local Coords = require("coordinates")
|
||||
local DebugAPI = require("noita-api.debug")
|
||||
--local LiveReload = require("noita-api.live-reload")
|
||||
local LiveReload = require("noita-api.live-reload")
|
||||
local Vec2 = require("noita-api.vec2")
|
||||
|
||||
-----------------------
|
||||
@ -120,7 +120,7 @@ function OnWorldPostUpdate()
|
||||
Message:CatchException("OnWorldPostUpdate", function()
|
||||
-- Reload mod every 60 frames.
|
||||
-- This allows live updates to the mod while Noita is running.
|
||||
-- !!! DISABLE THIS LINE AND THE CORRESPONDING REQUIRE BEFORE COMMITTING !!!
|
||||
-- !!! DISABLE THE FOLLOWING LINE BEFORE COMMITTING !!!
|
||||
--LiveReload:Reload("mods/noita-mapcap/", 60)
|
||||
|
||||
-- Run checks every 60 frames.
|
||||
|
Loading…
Reference in New Issue
Block a user