Cleanup, Refactoring and Fixes

- Remove unused util functions
- Put util stuff into its own namespace
- Move all initialization stuff into root init.lua
- Move progressBarString function into ui.lua
- Fix ffi.load error message
- Fix DebugAPI.BiomeMapGetFilename
- Move JSON lib into Noita API wrapper
- Move Vec2 lib into Noita API wrapper
- Move compatibility stuff into Noita API wrapper
- Emulate package tables if in restricted API mode
- Emulate require if in restricted API mode
- Use require instead of dofile_once everywhere
- Fix WrapID method to accept nil
- Add EmmyLua annotations for the default Noita API
- Add README.md to Noita API wrapper
This commit is contained in:
David Vogel 2022-07-23 17:36:21 +02:00
parent 994c44f1ba
commit 98dfb5fbb0
20 changed files with 1751 additions and 238 deletions

View File

@ -3,6 +3,7 @@
"backbuffer",
"basicfont",
"cheggaaa",
"dofile",
"Downscales",
"downscaling",
"executables",
@ -11,6 +12,7 @@
"gridify",
"hacky",
"hilbertify",
"ipairs",
"kbinani",
"Lanczos",
"ldflags",

View File

@ -3,14 +3,23 @@
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
---@type NoitaEntityAPI
local EntityAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api/entity.lua")
--------------------
-- Load libraries --
--------------------
---@type HilbertLib
local Hilbert = dofile_once("mods/noita-mapcap/files/libraries/hilbert-curve.lua")
local JSON = require("libraries.noita-api.json")
local EntityAPI = require("libraries.noita-api.entity")
local Hilbert = require("libraries.hilbert-curve")
---@type JSONLib
local JSON = dofile_once("mods/noita-mapcap/files/libraries/json.lua")
------------------
-- Load modules --
------------------
local Utils = require("utils")
----------
-- Code --
----------
CAPTURE_PIXEL_SIZE = 1 -- Screen to virtual pixel ratio.
CAPTURE_GRID_SIZE = 512 -- in virtual (world) pixels. There will always be exactly 4 images overlapping if the virtual resolution is 1024x1024.
@ -267,7 +276,7 @@ function startCapturingSpiral()
-- +x
for i = 1, i, 1 do
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
captureScreenshot(x, y, rx, ry, entityFile)
end
x, y = x + CAPTURE_GRID_SIZE, y
@ -275,7 +284,7 @@ function startCapturingSpiral()
-- +y
for i = 1, i, 1 do
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
captureScreenshot(x, y, rx, ry, entityFile)
end
x, y = x, y + CAPTURE_GRID_SIZE
@ -284,7 +293,7 @@ function startCapturingSpiral()
-- -x
for i = 1, i, 1 do
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
captureScreenshot(x, y, rx, ry, entityFile)
end
x, y = x - CAPTURE_GRID_SIZE, y
@ -292,7 +301,7 @@ function startCapturingSpiral()
-- -y
for i = 1, i, 1 do
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
captureScreenshot(x, y, rx, ry, entityFile)
end
x, y = x, y - CAPTURE_GRID_SIZE
@ -362,7 +371,7 @@ function startCapturingHilbert(area)
local x, y = (hx + gridLeft) * CAPTURE_GRID_SIZE, (hy + gridTop) * CAPTURE_GRID_SIZE
x, y = x + 256, y + 256 -- Align screen with ingame chunk grid that is 512x512.
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
if not fileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
captureScreenshot(x, y, rx, ry, entityFile)
end
UiProgress.Progress = UiProgress.Progress + 1

View File

@ -1,37 +0,0 @@
-- Copyright (c) 2019-2022 David Vogel
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
-- Some code to make noita's lua more conform to standard lua
-- Globally overwrite print function to behave more like expected
local oldPrint = print
function print(...)
local arg = {...}
local stringArgs = {}
for i, v in ipairs(arg) do
table.insert(stringArgs, tostring(v))
end
oldPrint(unpack(stringArgs))
end
-- Overwrite print to copy its output into a file
--[[local logFile = io.open("lualog.txt", "w")
function print(...)
local arg = {...}
local stringArgs = {}
local result = ""
for i, v in ipairs(arg) do
table.insert(stringArgs, tostring(v))
result = result .. tostring(v) .. "\t"
end
result = result .. "\n"
logFile:write(result)
logFile:flush()
oldPrint(unpack(stringArgs))
end]]

View File

@ -1,4 +1,4 @@
-- Copyright (c) 2019-2020 David Vogel
-- Copyright (c) 2019-2022 David Vogel
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
@ -7,7 +7,7 @@ local ffi = ffi or _G.ffi or require("ffi")
local status, caplib = pcall(ffi.load, "mods/noita-mapcap/bin/capture-b/capture")
if not status then
print("Error loading capture lib: " .. cap)
print("Error loading capture lib: " .. caplib)
end
ffi.cdef [[
typedef long LONG;

View File

@ -1,15 +0,0 @@
-- Copyright (c) 2019-2022 David Vogel
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
if not async then
dofile("data/scripts/lib/coroutines.lua")
end
dofile("data/scripts/perks/perk_list.lua")
dofile("mods/noita-mapcap/files/compatibility.lua")
dofile("mods/noita-mapcap/files/util.lua")
dofile("mods/noita-mapcap/files/external.lua")
dofile("mods/noita-mapcap/files/capture.lua")
dofile("mods/noita-mapcap/files/ui.lua")

View File

@ -5,11 +5,8 @@
-- Viewport coordinates transformation (world <-> window) for Noita.
---@type Vec2
local Vec2 = dofile_once("mods/noita-mapcap/files/libraries/vec2.lua")
---@type NoitaCameraAPI
local CameraAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api/camera.lua")
local Vec2 = require("libraries.noita-api.vec2")
local CameraAPI = require("libraries.noita-api.camera")
---@class Coords
---@field InternalResolution Vec2

View File

@ -0,0 +1,47 @@
# Noita API wrapper
This wraps the Noita API and exposes it in a more dev friendly way.
Entities and components are returned as objects. All entity and component related functions are now methods of the respective objects.
The library also comes with EmmyLua annotations, so code completion, type information and other hints will work in any IDE or editor that supports this.
(Only tested with VSCode for now)
## State
Working but incomplete.
If something is missing, you need to add it!
It would be nice to have code generation to generate this library from the official files, but meh.
But this would be too complex, as there are a lot of edge cases and stuff that has to be handled in a specific way.
## Usage
1. Copy this into your mod so you get the following file path: `mods/your-mod/files/libraries/noita-api/README.md`.
2. Add the following at the beginning of your mod's `init.lua`:
```lua
-- Emulate and override some functions and tables to make everything conform more to standard lua.
-- This will make `require` work, even in sandboxes with restricted Noita API.
local modFolder = "noita-mapcap"
dofile("mods/" .. modFolder .. "/files/libraries/noita-api/compatibility.lua")(modFolder)
```
You need to set `modFolder` to your mod's directory name.
After that you can import and use the library like this:
```lua
local EntityAPI = require("libraries.noita-api.entity")
local x, y, radius = 10, 10, 100
local entities = EntityAPI.GetInRadius(x, y, radius)
for _, entity in ipairs(entities) do
print(entity:GetName())
local components = entity:GetComponents("VelocityComponent")
for _, component in ipairs(components) do
entity:SetComponentsEnabled(component, false)
end
end
```

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,7 @@
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
-- Noita modding API, but a bit more beautiful.
-- Current modding API version: 7
-- State: Working but incomplete. If something is missing, add it by hand!
-- It would be optimal to generate this API wrapper automatically...
---@type Vec2
local Vec2 = dofile_once("mods/noita-mapcap/files/libraries/vec2.lua")
local Vec2 = require("libraries.noita-api.vec2")
-------------
-- Classes --

View File

@ -0,0 +1,104 @@
-- Copyright (c) 2019-2022 David Vogel
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
-- Some code to make Noita's lua conform more to standard lua.
-- Stupid way to prevent this code from being called more than once per sandbox.
-- Calling this lua file with dofile_once would still cause the setup function to be called multiple times.
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))
end
oldPrint(unpack(stringArgs))
end
-- Package doesn't exist when the Lua API is restricted.
-- Therefore we create it here and apply some default values.
package = package or {}
package.path = package.path or "./?.lua;"
package.preload = package.preload or {}
package.loaded = package.loaded or {
_G = _G,
bit = bit,
coroutine = coroutine,
debug = debug,
math = math,
package = package,
string = string,
table = table,
--io = io,
--jit = jit,
--os = os,
}
for k, v in pairs(package.loaded) do
print(k, v)
end
---Emulated require function in case the Lua API is restricted.
---It's probably good enough for most usecases.
---@param modName string
---@return any
local function customRequire(modName)
-- Check if package was already loaded, return previous result.
if package.loaded[modName] then return package.loaded[modName] end
local notFoundStr = ""
-- Check if there is an entry in the preload table.
local preloadFunc = package.preload[modName]
if preloadFunc then
local res = preloadFunc(modName)
if res == nil then res = true end
package.loaded[modName] = res
return res
else
notFoundStr = notFoundStr .. string.format("\tno field package.preload[%q]\n", modName)
end
-- Load and execute scripts.
-- Iterate over all package.path entries.
for pathEntry in string.gmatch(package.path, "[^;]+") do
local modPath = string.gsub(modName, "%.", "/") -- Replace "." with file path delimiter.
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 res == nil then
notFoundStr = notFoundStr .. string.format("\tno file %q\n", filePath)
else
if res == nil then res = true end
package.loaded[modName] = res
return res
end
else
notFoundStr = notFoundStr .. string.format("\tnot allowed %q\n", filePath)
end
end
error(string.format("module %q not found:\n%s", modName, notFoundStr))
end
require = require or customRequire
---Set up some stuff so `require` works as expected.
---@param modName any
local function setup(modName)
-- Add the files folder of the given mod as base for any `require` lookups.
package.path = package.path .. "./mods/" .. modName .. "/files/?.lua;"
--package.path = package.path .. "./mods/" .. modName .. "/files/?/init.lua;"
end
return setup

View File

@ -3,14 +3,7 @@
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
-- Noita modding API, but a bit more beautiful.
-- Current modding API version: 7
-- State: Working but incomplete. If something is missing, add it by hand!
-- It would be optimal to generate this API wrapper automatically...
---@type JSONLib
local JSON = dofile_once("mods/noita-mapcap/files/libraries/json.lua")
local JSON = require("libraries.noita-api.json")
-------------
-- Classes --
@ -26,7 +19,7 @@ NoitaComponent.__index = NoitaComponent
ComponentAPI.MetaTable = NoitaComponent
---WrapID wraps the given component ID and returns a Noita component object.
---@param id number
---@param id number|nil
---@return NoitaComponent|nil
function ComponentAPI.WrapID(id)
if id == nil or type(id) ~= "number" then return nil end

View File

@ -3,14 +3,7 @@
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
-- Noita modding API, but a bit more beautiful.
-- Current modding API version: 7
-- State: Working but incomplete. If something is missing, add it by hand!
-- It would be optimal to generate this API wrapper automatically...
---@type Vec2
local Vec2 = dofile_once("mods/noita-mapcap/files/libraries/vec2.lua")
local Vec2 = require("libraries.noita-api.vec2")
-------------
-- Classes --
@ -72,7 +65,7 @@ end
---@param pos Vec2 -- In world coordinates.
---@return string
function DebugAPI.BiomeMapGetFilename(pos)
return DebugBiomeMapGetFilename(pos)
return DebugBiomeMapGetFilename(pos.x, pos.y)
end
return DebugAPI

View File

@ -3,20 +3,9 @@
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
-- Noita modding API, but a bit more beautiful.
-- Current modding API version: 7
-- State: Working but incomplete. If something is missing, add it by hand!
-- It would be optimal to generate this API wrapper automatically...
---@type NoitaComponentAPI
local ComponentAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api/component.lua")
---@type Vec2
local Vec2 = dofile_once("mods/noita-mapcap/files/libraries/vec2.lua")
---@type JSONLib
local JSON = dofile_once("mods/noita-mapcap/files/libraries/json.lua")
local Vec2 = require("libraries.noita-api.vec2")
local JSON = require("libraries.noita-api.json")
local ComponentAPI = require("libraries.noita-api.component")
-------------
-- Classes --
@ -32,7 +21,7 @@ NoitaEntity.__index = NoitaEntity
EntityAPI.MetaTable = NoitaEntity
---WrapID wraps the given entity ID and returns a Noita entity object.
---@param id number
---@param id number|nil
---@return NoitaEntity|nil
function EntityAPI.WrapID(id)
if id == nil or type(id) ~= "number" then return nil end

View File

@ -3,7 +3,7 @@
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
-- Simple library to marshal JSON values.
-- Simple library to marshal JSON values. Mainly for Noita.
---@class JSONLib
local lib = {}

View File

@ -3,7 +3,7 @@
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
-- Just 2D vector stuff.
-- Just 2D vector stuff. Mainly for Noita.
-- State: Some stuff is untested.

View File

@ -3,8 +3,12 @@
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
---@type NoitaEntityAPI
local EntityAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api/entity.lua")
-- Emulate and override some functions and tables to make everything conform more to standard lua.
-- This will make `require` work, even in sandboxes with restricted Noita API.
local modFolder = "noita-mapcap"
dofile("mods/" .. modFolder .. "/files/libraries/noita-api/compatibility.lua")(modFolder)
local EntityAPI = require("libraries.noita-api.entity")
local oldPerkSpawn = perk_spawn

View File

@ -1,12 +1,34 @@
-- Copyright (c) 2019-2020 David Vogel
-- Copyright (c) 2019-2022 David Vogel
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
--------------------
-- Load libraries --
--------------------
------------------
-- Load modules --
------------------
local Utils = require("utils")
----------
-- Code --
----------
UiCaptureDelay = 0 -- Waiting time in frames
UiProgress = nil
UiCaptureProblem = nil
local function progressBarString(progress, look)
local factor = progress.Progress / progress.Max
local count = math.ceil(look.BarLength * factor)
local barString = string.rep(look.CharFull, count) .. string.rep(look.CharEmpty, look.BarLength - count)
return string.format(look.Format, barString, progress.Progress, progress.Max, factor * 100)
end
function DrawUI()
if modGUI ~= nil then
GuiStartFrame(modGUI)
@ -65,7 +87,7 @@ function DrawUI()
end
end
if not fileExists("mods/noita-mapcap/bin/capture-b/capture.dll") then
if not Utils.FileExists("mods/noita-mapcap/bin/capture-b/capture.dll") then
GuiTextCentered(modGUI, 0, 0, "!!! WARNING !!! Can't find library for screenshots.")
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
GuiTextCentered(modGUI, 0, 0, "- Redownload a release of this mod from GitHub, don't download the sourcecode")
@ -73,7 +95,7 @@ function DrawUI()
problem = true
end
if not fileExists("mods/noita-mapcap/bin/stitch/stitch.exe") then
if not Utils.FileExists("mods/noita-mapcap/bin/stitch/stitch.exe") then
GuiTextCentered(modGUI, 0, 0, "!!! WARNING !!! Can't find software for stitching.")
GuiTextCentered(modGUI, 0, 0, "You can still take screenshots, but you won't be able to stitch those screenshots.")
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")

View File

@ -1,107 +0,0 @@
-- Copyright (c) 2019-2022 David Vogel
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
function SplitStringByLength(string, length)
local chunks = {}
for i = 1, #string, length do
table.insert(chunks, string:sub(i, i + length - 1))
end
return chunks
end
-- Improved version of GamePrint, that behaves more like print.
local oldGamePrint = GamePrint
function GamePrint(...)
local arg = {...}
local result = ""
for i, v in ipairs(arg) do
result = result .. tostring(v) .. " "
end
for line in result:gmatch("[^\r\n]+") do
for i, v in ipairs(SplitStringByLength(line, 100)) do
oldGamePrint(v)
end
end
end
function getPlayer()
local players = EntityGetWithTag("player_unit")
if players == nil or #players < 1 then
return nil
end
return players[1]
end
function getPlayerPos()
return EntityGetTransform(getPlayer())
end
function teleportPlayer(x, y)
EntitySetTransform(getPlayer(), x, y)
end
function setPlayerHP(hp)
local damagemodels = EntityGetComponent(getPlayer(), "DamageModelComponent")
if damagemodels ~= nil then
for i, damagemodel in ipairs(damagemodels) do
ComponentSetValue(damagemodel, "max_hp", hp)
ComponentSetValue(damagemodel, "hp", hp)
end
end
end
function addEffectToEntity(entity, gameEffect)
local gameEffectComp = GetGameEffectLoadTo(entity, gameEffect, true)
if gameEffectComp ~= nil then
ComponentSetValue(gameEffectComp, "frames", "-1")
end
end
function addPerkToPlayer(perkID)
local playerEntity = getPlayer()
local x, y = getPlayerPos()
local perkData = get_perk_with_id(perk_list, perkID)
-- Add effect
addEffectToEntity(playerEntity, perkData.game_effect)
-- Add ui icon etc
--[[local perkIcon = EntityCreateNew("")
EntityAddComponent(
perkIcon,
"UIIconComponent",
{
name = perkData.ui_name,
description = perkData.ui_description,
icon_sprite_file = perkData.ui_icon
}
)
EntityAddChild(playerEntity, perkIcon)]]
--local effect = EntityLoad("data/entities/misc/effect_protection_all.xml", x, y)
--EntityAddChild(playerEntity, effect)
end
function fileExists(fileName)
local f = io.open(fileName, "r")
if f ~= nil then
io.close(f)
return true
else
return false
end
end
function progressBarString(progress, look)
local factor = progress.Progress / progress.Max
local count = math.ceil(look.BarLength * factor)
local barString = string.rep(look.CharFull, count) .. string.rep(look.CharEmpty, look.BarLength - count)
return string.format(look.Format, barString, progress.Progress, progress.Max, factor * 100)
end

22
files/utils.lua Normal file
View File

@ -0,0 +1,22 @@
-- Copyright (c) 2019-2022 David Vogel
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
---@class Utils
local Utils = {}
---Returns if the file at filePath exists.
---@param filePath string
---@return boolean
function Utils.FileExists(filePath)
local f = io.open(filePath, "r")
if f ~= nil then
io.close(f)
return true
else
return false
end
end
return Utils

View File

@ -1,15 +1,45 @@
-- Copyright (c) 2022 David Vogel
--
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT
dofile("mods/noita-mapcap/files/init.lua")
-----------------------
-- Load global stuff --
-----------------------
---Called in order upon loading game.
function OnModInit() end
-- Emulate and override some functions and tables to make everything conform more to standard lua.
-- This will make `require` work, even in sandboxes with restricted Noita API.
local modFolder = "noita-mapcap"
dofile("mods/" .. modFolder .. "/files/libraries/noita-api/compatibility.lua")(modFolder)
function OnPlayerSpawned(player_entity)
--EntityLoad("mods/noita-mapcap/files/luacomponent.xml") -- ffi isn't accessible from inside lua components, scrap that idea
if not async then
dofile_once("data/scripts/lib/coroutines.lua")
end
dofile("mods/noita-mapcap/files/external.lua")
dofile("mods/noita-mapcap/files/capture.lua")
dofile("mods/noita-mapcap/files/ui.lua")
--------------------
-- Hook callbacks --
--------------------
---Called in order upon loading a new(?) game.
function OnModPreInit()
end
---Called in order upon loading a new(?) game.
function OnModInit()
end
---Called in order upon loading a new(?) game.
function OnModPostInit()
end
---Called when player entity has been created.
---Ensures chunks around the player have been loaded & created.
---@param playerEntityID integer
function OnPlayerSpawned(playerEntityID)
modGUI = GuiCreate()
GameSetCameraFree(true)
@ -17,15 +47,56 @@ function OnPlayerSpawned(player_entity)
--DebugEntityCapture()
end
-- Called *every* time the game is about to start updating the world
function OnWorldPreUpdate()
wake_up_waiting_threads(1) -- Coroutines aren't run every frame in this sandbox, do it manually here.
---Called when the player dies.
---@param playerEntityID integer
function OnPlayerDied(playerEntityID)
end
-- Called *every* time the game has finished updating the world
function OnWorldPostUpdate() end
---Called once the game world is initialized.
---Doesn't ensure any chunks around the player.
function OnWorldInitialized()
end
ModMagicNumbersFileAdd("mods/noita-mapcap/files/magic_numbers.xml") -- override some game constants
---Called *every* time the game is about to start updating the world.
function OnWorldPreUpdate()
-- Coroutines aren't run every frame in this lua sandbox, do it manually here.
wake_up_waiting_threads(1)
end
-- Apply overrides.
---Called *every* time the game has finished updating the world.
function OnWorldPostUpdate()
end
---Called when the biome config is loaded.
function OnBiomeConfigLoaded()
end
---The last point where the Mod API is available.
---After this materials.xml will be loaded.
function OnMagicNumbersAndWorldSeedInitialized()
end
---Called when the game is paused or unpaused.
---@param isPaused boolean
---@param isInventoryPause boolean
function OnPausedChanged(isPaused, isInventoryPause)
end
---Will be called when the game is unpaused, if player changed any mod settings while the game was paused.
function OnModSettingsChanged()
end
---Will be called when the game is paused, either by the pause menu or some inventory menus.
---Please be careful with this, as not everything will behave well when called while the game is paused.
function OnPausePreUpdate()
end
---------------
-- Overrides --
---------------
-- Override virtual resolution and some other stuff.
ModMagicNumbersFileAdd("mods/noita-mapcap/files/magic_numbers.xml")
-- Remove hover animation of newly created perks.
ModLuaFileAppend("data/scripts/perks/perk.lua", "mods/noita-mapcap/files/overrides/perks/perk.lua")