mirror of
https://github.com/Dadido3/noita-mapcap.git
synced 2024-11-22 21:17:33 +00:00
Split Noita API wrapper into several files
This commit is contained in:
parent
a30c3b0cbe
commit
aa99e101b4
@ -3,8 +3,8 @@
|
|||||||
-- This software is released under the MIT License.
|
-- This software is released under the MIT License.
|
||||||
-- https://opensource.org/licenses/MIT
|
-- https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
---@type NoitaAPI
|
---@type NoitaEntityAPI
|
||||||
local noitaAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api.lua")
|
local EntityAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api/entity.lua")
|
||||||
|
|
||||||
---@type JSONLib
|
---@type JSONLib
|
||||||
local json = dofile_once("mods/noita-mapcap/files/libraries/json.lua")
|
local json = dofile_once("mods/noita-mapcap/files/libraries/json.lua")
|
||||||
@ -78,7 +78,7 @@ end
|
|||||||
local function captureEntities(entityFile, x, y, radius)
|
local function captureEntities(entityFile, x, y, radius)
|
||||||
if not entityFile then return end
|
if not entityFile then return end
|
||||||
|
|
||||||
local entities = noitaAPI.Entity.GetInRadius(x, y, radius)
|
local entities = EntityAPI.GetInRadius(x, y, radius)
|
||||||
for _, entity in ipairs(entities) do
|
for _, entity in ipairs(entities) do
|
||||||
-- Get to the root entity, as we are exporting entire entity trees.
|
-- Get to the root entity, as we are exporting entire entity trees.
|
||||||
local rootEntity = entity:GetRootEntity()
|
local rootEntity = entity:GetRootEntity()
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
---@type Vec2
|
---@type Vec2
|
||||||
local Vec2 = dofile_once("mods/noita-mapcap/files/libraries/vec2.lua")
|
local Vec2 = dofile_once("mods/noita-mapcap/files/libraries/vec2.lua")
|
||||||
|
|
||||||
---@type NoitaAPI
|
---@type NoitaCameraAPI
|
||||||
local NoitaAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api.lua")
|
local CameraAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api/camera.lua")
|
||||||
|
|
||||||
---@class Coords
|
---@class Coords
|
||||||
---@field InternalResolution Vec2
|
---@field InternalResolution Vec2
|
||||||
@ -79,7 +79,7 @@ end
|
|||||||
---@param viewportCenter Vec2|nil -- Result of `GameGetCameraPos()`. Will be queried automatically if set to nil.
|
---@param viewportCenter Vec2|nil -- Result of `GameGetCameraPos()`. Will be queried automatically if set to nil.
|
||||||
---@return Vec2 window
|
---@return Vec2 window
|
||||||
function Coords:ToWindow(world, viewportCenter)
|
function Coords:ToWindow(world, viewportCenter)
|
||||||
viewportCenter = viewportCenter or NoitaAPI.Camera.Pos()
|
viewportCenter = viewportCenter or CameraAPI.Pos()
|
||||||
|
|
||||||
local internalTopLeft, internalBottomRight = self:InternalRect()
|
local internalTopLeft, internalBottomRight = self:InternalRect()
|
||||||
local pixelScale = self:PixelScale()
|
local pixelScale = self:PixelScale()
|
||||||
@ -92,7 +92,7 @@ end
|
|||||||
---@param viewportCenter Vec2|nil -- Result of `GameGetCameraPos()`. Will be queried automatically if set to nil.
|
---@param viewportCenter Vec2|nil -- Result of `GameGetCameraPos()`. Will be queried automatically if set to nil.
|
||||||
---@return Vec2 world
|
---@return Vec2 world
|
||||||
function Coords:ToWorld(window, viewportCenter)
|
function Coords:ToWorld(window, viewportCenter)
|
||||||
viewportCenter = viewportCenter or NoitaAPI.Camera.Pos()
|
viewportCenter = viewportCenter or CameraAPI.Pos()
|
||||||
|
|
||||||
local internalTopLeft, internalBottomRight = self:InternalRect()
|
local internalTopLeft, internalBottomRight = self:InternalRect()
|
||||||
local pixelScale = self:PixelScale()
|
local pixelScale = self:PixelScale()
|
||||||
|
63
files/libraries/noita-api/camera.lua
Normal file
63
files/libraries/noita-api/camera.lua
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
-- Copyright (c) 2022 David Vogel
|
||||||
|
--
|
||||||
|
-- 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")
|
||||||
|
|
||||||
|
-------------
|
||||||
|
-- Classes --
|
||||||
|
-------------
|
||||||
|
|
||||||
|
---@class NoitaCameraAPI
|
||||||
|
local CameraAPI = {}
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Noita API wrappers --
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
---
|
||||||
|
---@param strength number
|
||||||
|
---@param position Vec2|nil -- Defaults to camera position if not set.
|
||||||
|
function CameraAPI.Screenshake(strength, position)
|
||||||
|
if position == nil then
|
||||||
|
return GameScreenshake(strength)
|
||||||
|
end
|
||||||
|
return GameScreenshake(strength, position.x, position.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns the center position of the viewport in world/virtual coordinates.
|
||||||
|
---@return Vec2
|
||||||
|
function CameraAPI.Pos()
|
||||||
|
return Vec2(GameGetCameraPos())
|
||||||
|
end
|
||||||
|
|
||||||
|
---Sets the center position of the viewport in world/virtual coordinates.
|
||||||
|
---@param position Vec2
|
||||||
|
function CameraAPI.SetPos(position)
|
||||||
|
return GameSetCameraPos(position.x, position.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---@param isFree boolean
|
||||||
|
function CameraAPI.SetCameraFree(isFree)
|
||||||
|
return GameSetCameraFree(isFree)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns the camera boundary rectangle in world/virtual coordinates.
|
||||||
|
---This may not be 100% pixel perfect with regards to what you see on the screen.
|
||||||
|
---@return Vec2 topLeft
|
||||||
|
---@return Vec2 bottomRight
|
||||||
|
function CameraAPI.Bounds()
|
||||||
|
local x, y, w, h = GameGetCameraBounds()
|
||||||
|
return Vec2(x, y), Vec2(x + w, y + h)
|
||||||
|
end
|
||||||
|
|
||||||
|
return CameraAPI
|
189
files/libraries/noita-api/component.lua
Normal file
189
files/libraries/noita-api/component.lua
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
-- Copyright (c) 2022 David Vogel
|
||||||
|
--
|
||||||
|
-- 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")
|
||||||
|
|
||||||
|
-------------
|
||||||
|
-- Classes --
|
||||||
|
-------------
|
||||||
|
|
||||||
|
---@class NoitaComponentAPI
|
||||||
|
local ComponentAPI = {}
|
||||||
|
|
||||||
|
---@class NoitaComponent
|
||||||
|
---@field ID integer -- Noita component ID.
|
||||||
|
local NoitaComponent = {}
|
||||||
|
NoitaComponent.__index = NoitaComponent
|
||||||
|
ComponentAPI.MetaTable = NoitaComponent
|
||||||
|
|
||||||
|
---WrapID wraps the given component ID and returns a Noita component object.
|
||||||
|
---@param id number
|
||||||
|
---@return NoitaComponent|nil
|
||||||
|
function ComponentAPI.WrapID(id)
|
||||||
|
if id == nil or type(id) ~= "number" then return nil end
|
||||||
|
return setmetatable({ ID = id }, NoitaComponent)
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Noita API wrappers --
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
---
|
||||||
|
---@param tag string
|
||||||
|
function NoitaComponent:AddTag(tag)
|
||||||
|
return ComponentAddTag(self.ID, tag)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---@param tag string
|
||||||
|
function NoitaComponent:RemoveTag(tag)
|
||||||
|
return ComponentRemoveTag(self.ID, tag)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---@param tag string
|
||||||
|
---@return boolean
|
||||||
|
function NoitaComponent:HasTag(tag)
|
||||||
|
return ComponentHasTag(self.ID, tag)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns one or many values matching the type or subtypes of the requested field.
|
||||||
|
---Reports error and returns nil if the field type is not supported or field was not found.
|
||||||
|
---@param fieldName string
|
||||||
|
---@return any|nil
|
||||||
|
function NoitaComponent:GetValue(fieldName)
|
||||||
|
return ComponentGetValue2(self.ID, fieldName) -- TODO: Rework Noita API to handle vectors, and return a vector instead of some shitty multi value result
|
||||||
|
end
|
||||||
|
|
||||||
|
---Sets the value of a field. Value(s) should have a type matching the field type.
|
||||||
|
---Reports error if the values weren't given in correct type, the field type is not supported, or the component does not exist.
|
||||||
|
---@param fieldName string
|
||||||
|
---@param ... any|nil -- Vectors use one argument per dimension.
|
||||||
|
function NoitaComponent:SetValue(fieldName, ...)
|
||||||
|
return ComponentSetValue2(self.ID, fieldName, ...) -- TODO: Rework Noita API to handle vectors, and use a vector instead of shitty multi value arguments
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns one or many values matching the type or subtypes of the requested field in a component subobject.
|
||||||
|
---Reports error and returns nil if the field type is not supported or 'object_name' is not a metaobject.
|
||||||
|
---
|
||||||
|
---Reporting errors means that it spams the stdout with messages, instead of using the lua error handling. Thanks Nolla.
|
||||||
|
---@param objectName string
|
||||||
|
---@param fieldName string
|
||||||
|
---@return any|nil
|
||||||
|
function NoitaComponent:ObjectGetValue(objectName, fieldName)
|
||||||
|
return ComponentObjectGetValue2(self.ID, objectName, fieldName) -- TODO: Rework Noita API to handle vectors, and return a vector instead of some shitty multi value result
|
||||||
|
end
|
||||||
|
|
||||||
|
---Sets the value of a field in a component subobject. Value(s) should have a type matching the field type.
|
||||||
|
---Reports error if the values weren't given in correct type, the field type is not supported or 'object_name' is not a metaobject.
|
||||||
|
---@param objectName string
|
||||||
|
---@param fieldName string
|
||||||
|
---@param ... any|nil -- Vectors use one argument per dimension.
|
||||||
|
function NoitaComponent:ObjectSetValue(objectName, fieldName, ...)
|
||||||
|
return ComponentObjectSetValue2(self.ID, objectName, fieldName, ...) -- TODO: Rework Noita API to handle vectors, and use a vector instead of shitty multi value arguments
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---@param arrayMemberName string
|
||||||
|
---@param typeStoredInVector "int"|"float"|"string"
|
||||||
|
---@return number
|
||||||
|
function NoitaComponent:GetVectorSize(arrayMemberName, typeStoredInVector)
|
||||||
|
return ComponentGetVectorSize(self.ID, arrayMemberName, typeStoredInVector)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---@param arrayName string
|
||||||
|
---@param typeStoredInVector "int"|"float"|"string"
|
||||||
|
---@param index number
|
||||||
|
---@return number|number|string|nil
|
||||||
|
function NoitaComponent:GetVectorValue(arrayName, typeStoredInVector, index)
|
||||||
|
return ComponentGetVectorValue(self.ID, arrayName, typeStoredInVector, index)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---@param arrayName string
|
||||||
|
---@param typeStoredInVector "int"|"float"|"string"
|
||||||
|
---@return number[]|number|string|nil
|
||||||
|
function NoitaComponent:GetVector(arrayName, typeStoredInVector)
|
||||||
|
return ComponentGetVector(self.ID, arrayName, typeStoredInVector)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns true if the given component exists and is enabled, else false.
|
||||||
|
---@return boolean
|
||||||
|
function NoitaComponent:GetIsEnabled()
|
||||||
|
return ComponentGetIsEnabled(self.ID)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns a string-indexed table of string.
|
||||||
|
---@return table<string, string>|nil
|
||||||
|
function NoitaComponent:GetMembers()
|
||||||
|
return ComponentGetMembers(self.ID)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns a string-indexed table of string or nil.
|
||||||
|
---@param objectName string
|
||||||
|
---@return table<string, string>|nil
|
||||||
|
function NoitaComponent:ObjectGetMembers(objectName)
|
||||||
|
return ComponentObjectGetMembers(self.ID, objectName)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
---@return string string
|
||||||
|
function NoitaComponent:GetTypeName()
|
||||||
|
return ComponentGetTypeName(self.ID)
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
-- JSON Implementation --
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
-- Set of component keys that would return an "invalid type" error when called with ComponentGetValue2().
|
||||||
|
-- This is more or less to get around console error spam that otherwise can't be prevented when iterating over component members.
|
||||||
|
-- Only used inside the JSON marshaler, until there is a better solution.
|
||||||
|
local componentValueKeysWithInvalidType = {}
|
||||||
|
|
||||||
|
---MarshalJSON implements the JSON marshaler interface.
|
||||||
|
---@return string
|
||||||
|
function NoitaComponent:MarshalJSON()
|
||||||
|
-- Get list of members, but with correct type (instead of string values).
|
||||||
|
local membersTable = self:GetMembers()
|
||||||
|
local members = {}
|
||||||
|
if membersTable then
|
||||||
|
for k, v in pairs(membersTable) do
|
||||||
|
if not componentValueKeysWithInvalidType[k] then
|
||||||
|
local packedResult = table.pack(self:GetValue(k)) -- Try to get value with correct type. Assuming nil is an error, but this is not always the case... meh.
|
||||||
|
if packedResult.n == 0 then
|
||||||
|
members[k] = nil -- Write no result as nil. Basically do nothing.
|
||||||
|
elseif packedResult.n == 1 then
|
||||||
|
members[k] = packedResult[1] -- Write single value result as single value.
|
||||||
|
else
|
||||||
|
packedResult.n = nil -- Discard n field, otherwise this is not a pure array.
|
||||||
|
members[k] = packedResult -- Write multi value result as array.
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if members[k] == nil then
|
||||||
|
componentValueKeysWithInvalidType[k] = true
|
||||||
|
--members[k] = v -- Fall back to string value of self:GetMembers().
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local resultObject = {
|
||||||
|
typeName = self:GetTypeName(),
|
||||||
|
members = members,
|
||||||
|
--objectMembers = component:ObjectGetMembers
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(resultObject)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ComponentAPI
|
@ -9,6 +9,9 @@
|
|||||||
-- State: Working but incomplete. If something is missing, add it by hand!
|
-- State: Working but incomplete. If something is missing, add it by hand!
|
||||||
-- It would be optimal to generate this API wrapper automatically...
|
-- 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
|
---@type Vec2
|
||||||
local Vec2 = dofile_once("mods/noita-mapcap/files/libraries/vec2.lua")
|
local Vec2 = dofile_once("mods/noita-mapcap/files/libraries/vec2.lua")
|
||||||
|
|
||||||
@ -19,12 +22,14 @@ local json = dofile_once("mods/noita-mapcap/files/libraries/json.lua")
|
|||||||
-- Classes --
|
-- Classes --
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
---@class NoitaEntityAPI
|
||||||
local EntityAPI = {}
|
local EntityAPI = {}
|
||||||
|
|
||||||
---@class NoitaEntity
|
---@class NoitaEntity
|
||||||
---@field ID integer -- Noita entity ID.
|
---@field ID integer -- Noita entity ID.
|
||||||
local NoitaEntity = {}
|
local NoitaEntity = {}
|
||||||
NoitaEntity.__index = NoitaEntity
|
NoitaEntity.__index = NoitaEntity
|
||||||
|
EntityAPI.MetaTable = NoitaEntity
|
||||||
|
|
||||||
---WrapID wraps the given entity ID and returns a Noita entity object.
|
---WrapID wraps the given entity ID and returns a Noita entity object.
|
||||||
---@param id number
|
---@param id number
|
||||||
@ -34,84 +39,6 @@ function EntityAPI.WrapID(id)
|
|||||||
return setmetatable({ ID = id }, NoitaEntity)
|
return setmetatable({ ID = id }, NoitaEntity)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ComponentAPI = {}
|
|
||||||
|
|
||||||
---@class NoitaComponent
|
|
||||||
---@field ID integer -- Noita component ID.
|
|
||||||
local NoitaComponent = {}
|
|
||||||
NoitaComponent.__index = NoitaComponent
|
|
||||||
|
|
||||||
---WrapID wraps the given component ID and returns a Noita component object.
|
|
||||||
---@param id number
|
|
||||||
---@return NoitaComponent|nil
|
|
||||||
function ComponentAPI.WrapID(id)
|
|
||||||
if id == nil or type(id) ~= "number" then return nil end
|
|
||||||
return setmetatable({ ID = id }, NoitaComponent)
|
|
||||||
end
|
|
||||||
|
|
||||||
local CameraAPI = {}
|
|
||||||
|
|
||||||
-------------------------
|
|
||||||
-- JSON Implementation --
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
-- Set of component keys that would return an "invalid type" error when called with ComponentGetValue2().
|
|
||||||
-- This is more or less to get around console error spam that otherwise can't be prevented when iterating over component members.
|
|
||||||
-- Only used inside the JSON marshaler, until there is a better solution.
|
|
||||||
local componentValueKeysWithInvalidType = {}
|
|
||||||
|
|
||||||
---MarshalJSON implements the JSON marshaler interface.
|
|
||||||
---@return string
|
|
||||||
function NoitaComponent:MarshalJSON()
|
|
||||||
-- Get list of members, but with correct type (instead of string values).
|
|
||||||
local membersTable = self:GetMembers()
|
|
||||||
local members = {}
|
|
||||||
if membersTable then
|
|
||||||
for k, v in pairs(membersTable) do
|
|
||||||
if not componentValueKeysWithInvalidType[k] then
|
|
||||||
local packedResult = table.pack(self:GetValue(k)) -- Try to get value with correct type. Assuming nil is an error, but this is not always the case... meh.
|
|
||||||
if packedResult.n == 0 then
|
|
||||||
members[k] = nil -- Write no result as nil. Basically do nothing.
|
|
||||||
elseif packedResult.n == 1 then
|
|
||||||
members[k] = packedResult[1] -- Write single value result as single value.
|
|
||||||
else
|
|
||||||
packedResult.n = nil -- Discard n field, otherwise this is not a pure array.
|
|
||||||
members[k] = packedResult -- Write multi value result as array.
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if members[k] == nil then
|
|
||||||
componentValueKeysWithInvalidType[k] = true
|
|
||||||
--members[k] = v -- Fall back to string value of self:GetMembers().
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local resultObject = {
|
|
||||||
typeName = self:GetTypeName(),
|
|
||||||
members = members,
|
|
||||||
--objectMembers = component:ObjectGetMembers
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.Marshal(resultObject)
|
|
||||||
end
|
|
||||||
|
|
||||||
---MarshalJSON implements the JSON marshaler interface.
|
|
||||||
---@return string
|
|
||||||
function NoitaEntity:MarshalJSON()
|
|
||||||
local result = {
|
|
||||||
name = self:GetName(),
|
|
||||||
filename = self:GetFilename(),
|
|
||||||
tags = self:GetTags(),
|
|
||||||
children = self:GetAllChildren(),
|
|
||||||
components = self:GetAllComponents(),
|
|
||||||
transform = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
result.transform.x, result.transform.y, result.transform.rotation, result.transform.scaleX, result.transform.scaleY = self:GetTransform()
|
|
||||||
|
|
||||||
return json.Marshal(result)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
-- Noita API wrappers --
|
-- Noita API wrappers --
|
||||||
------------------------
|
------------------------
|
||||||
@ -122,11 +49,7 @@ end
|
|||||||
---@param posY number -- Y coordinate in world (virtual) pixels.
|
---@param posY number -- Y coordinate in world (virtual) pixels.
|
||||||
---@return NoitaEntity|nil
|
---@return NoitaEntity|nil
|
||||||
function EntityAPI.Load(filename, posX, posY)
|
function EntityAPI.Load(filename, posX, posY)
|
||||||
local entityID = EntityLoad(filename, posX, posY)
|
return EntityAPI.WrapID(EntityLoad(filename, posX, posY))
|
||||||
if entityID == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = entityID }, NoitaEntity)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -135,11 +58,7 @@ end
|
|||||||
---@param posY number -- Y coordinate in world (virtual) pixels.
|
---@param posY number -- Y coordinate in world (virtual) pixels.
|
||||||
---@return NoitaEntity|nil
|
---@return NoitaEntity|nil
|
||||||
function EntityAPI.LoadEndGameItem(filename, posX, posY)
|
function EntityAPI.LoadEndGameItem(filename, posX, posY)
|
||||||
local entityID = EntityLoadEndGameItem(filename, posX, posY)
|
return EntityAPI.WrapID(EntityLoadEndGameItem(filename, posX, posY))
|
||||||
if entityID == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = entityID }, NoitaEntity)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -169,11 +88,7 @@ end
|
|||||||
---@param name string
|
---@param name string
|
||||||
---@return NoitaEntity|nil
|
---@return NoitaEntity|nil
|
||||||
function EntityAPI.CreateNew(name)
|
function EntityAPI.CreateNew(name)
|
||||||
local entityID = EntityCreateNew(name)
|
return EntityAPI.WrapID(EntityCreateNew(name))
|
||||||
if entityID == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = entityID }, NoitaEntity)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -192,10 +107,7 @@ end
|
|||||||
---@return NoitaComponent|nil
|
---@return NoitaComponent|nil
|
||||||
function NoitaEntity:AddComponent(componentTypeName, tableOfComponentValues)
|
function NoitaEntity:AddComponent(componentTypeName, tableOfComponentValues)
|
||||||
local componentID = EntityAddComponent(self.ID, componentTypeName, tableOfComponentValues)
|
local componentID = EntityAddComponent(self.ID, componentTypeName, tableOfComponentValues)
|
||||||
if componentID == nil then
|
return ComponentAPI.WrapID(componentID)
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = componentID }, NoitaComponent)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -210,7 +122,7 @@ function NoitaEntity:GetAllComponents()
|
|||||||
local componentIDs = EntityGetAllComponents(self.ID) or {}
|
local componentIDs = EntityGetAllComponents(self.ID) or {}
|
||||||
local result = {}
|
local result = {}
|
||||||
for _, componentID in ipairs(componentIDs) do
|
for _, componentID in ipairs(componentIDs) do
|
||||||
table.insert(result, setmetatable({ ID = componentID }, NoitaComponent))
|
table.insert(result, ComponentAPI.WrapID(componentID))
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@ -228,7 +140,7 @@ function NoitaEntity:GetComponents(componentTypeName, tag)
|
|||||||
end
|
end
|
||||||
local result = {}
|
local result = {}
|
||||||
for _, componentID in ipairs(componentIDs) do
|
for _, componentID in ipairs(componentIDs) do
|
||||||
table.insert(result, setmetatable({ ID = componentID }, NoitaComponent))
|
table.insert(result, ComponentAPI.WrapID(componentID))
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@ -244,10 +156,7 @@ function NoitaEntity:GetFirstComponent(componentTypeName, tag)
|
|||||||
else
|
else
|
||||||
componentID = EntityGetFirstComponent(self.ID, componentTypeName)
|
componentID = EntityGetFirstComponent(self.ID, componentTypeName)
|
||||||
end
|
end
|
||||||
if componentID == nil then
|
return ComponentAPI.WrapID(componentID)
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = componentID }, NoitaComponent)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---Sets the transform of the entity.
|
---Sets the transform of the entity.
|
||||||
@ -288,7 +197,7 @@ function NoitaEntity:GetAllChildren()
|
|||||||
local entityIDs = EntityGetAllChildren(self.ID) or {}
|
local entityIDs = EntityGetAllChildren(self.ID) or {}
|
||||||
local result = {}
|
local result = {}
|
||||||
for _, entityID in ipairs(entityIDs) do
|
for _, entityID in ipairs(entityIDs) do
|
||||||
table.insert(result, setmetatable({ ID = entityID }, NoitaEntity))
|
table.insert(result, EntityAPI.WrapID(entityID))
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@ -296,18 +205,13 @@ end
|
|||||||
---
|
---
|
||||||
---@return NoitaEntity|nil
|
---@return NoitaEntity|nil
|
||||||
function NoitaEntity:GetParent()
|
function NoitaEntity:GetParent()
|
||||||
local entityID = EntityGetParent(self.ID)
|
return EntityAPI.WrapID(EntityGetParent(self.ID))
|
||||||
if entityID == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = entityID }, NoitaEntity)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---Returns the given entity if it has no parent, otherwise walks up the parent hierarchy to the topmost parent and returns it.
|
---Returns the given entity if it has no parent, otherwise walks up the parent hierarchy to the topmost parent and returns it.
|
||||||
---@return NoitaEntity
|
---@return NoitaEntity|nil
|
||||||
function NoitaEntity:GetRootEntity()
|
function NoitaEntity:GetRootEntity()
|
||||||
local entityID = EntityGetRootEntity(self.ID)
|
return EntityAPI.WrapID(EntityGetRootEntity(self.ID))
|
||||||
return setmetatable({ ID = entityID }, NoitaEntity)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -360,7 +264,7 @@ function EntityAPI.GetWithTag(tag)
|
|||||||
local entityIDs = EntityGetWithTag(tag) or {}
|
local entityIDs = EntityGetWithTag(tag) or {}
|
||||||
local result = {}
|
local result = {}
|
||||||
for _, entityID in ipairs(entityIDs) do
|
for _, entityID in ipairs(entityIDs) do
|
||||||
table.insert(result, setmetatable({ ID = entityID }, NoitaEntity))
|
table.insert(result, EntityAPI.WrapID(entityID))
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@ -374,7 +278,7 @@ function EntityAPI.GetInRadius(posX, posY, radius)
|
|||||||
local entityIDs = EntityGetInRadius(posX, posY, radius) or {}
|
local entityIDs = EntityGetInRadius(posX, posY, radius) or {}
|
||||||
local result = {}
|
local result = {}
|
||||||
for _, entityID in ipairs(entityIDs) do
|
for _, entityID in ipairs(entityIDs) do
|
||||||
table.insert(result, setmetatable({ ID = entityID }, NoitaEntity))
|
table.insert(result, EntityAPI.WrapID(entityID))
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@ -389,7 +293,7 @@ function EntityAPI.GetInRadiusWithTag(posX, posY, radius, tag)
|
|||||||
local entityIDs = EntityGetInRadiusWithTag(posX, posY, radius, tag) or {}
|
local entityIDs = EntityGetInRadiusWithTag(posX, posY, radius, tag) or {}
|
||||||
local result = {}
|
local result = {}
|
||||||
for _, entityID in ipairs(entityIDs) do
|
for _, entityID in ipairs(entityIDs) do
|
||||||
table.insert(result, setmetatable({ ID = entityID }, NoitaEntity))
|
table.insert(result, EntityAPI.WrapID(entityID))
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@ -399,22 +303,14 @@ end
|
|||||||
---@param posY number -- X coordinate in world (virtual) pixels.
|
---@param posY number -- X coordinate in world (virtual) pixels.
|
||||||
---@return NoitaEntity|nil
|
---@return NoitaEntity|nil
|
||||||
function EntityAPI.GetClosest(posX, posY)
|
function EntityAPI.GetClosest(posX, posY)
|
||||||
local entityID = EntityGetClosest(posX, posY)
|
return EntityAPI.WrapID(EntityGetClosest(posX, posY))
|
||||||
if entityID == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = entityID }, NoitaEntity)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
---@param name string
|
---@param name string
|
||||||
---@return NoitaEntity|nil
|
---@return NoitaEntity|nil
|
||||||
function EntityAPI.GetWithName(name)
|
function EntityAPI.GetWithName(name)
|
||||||
local entityID = EntityGetWithName(name)
|
return EntityAPI.WrapID(EntityGetWithName(name))
|
||||||
if entityID == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = entityID }, NoitaEntity)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -442,61 +338,6 @@ function NoitaEntity:GetFilename()
|
|||||||
return EntityGetFilename(self.ID)
|
return EntityGetFilename(self.ID)
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
|
||||||
---@param tag string
|
|
||||||
function NoitaComponent:AddTag(tag)
|
|
||||||
return ComponentAddTag(self.ID, tag)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
---@param tag string
|
|
||||||
function NoitaComponent:RemoveTag(tag)
|
|
||||||
return ComponentRemoveTag(self.ID, tag)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
---@param tag string
|
|
||||||
---@return boolean
|
|
||||||
function NoitaComponent:HasTag(tag)
|
|
||||||
return ComponentHasTag(self.ID, tag)
|
|
||||||
end
|
|
||||||
|
|
||||||
---Returns one or many values matching the type or subtypes of the requested field.
|
|
||||||
---Reports error and returns nil if the field type is not supported or field was not found.
|
|
||||||
---@param fieldName string
|
|
||||||
---@return any|nil
|
|
||||||
function NoitaComponent:GetValue(fieldName)
|
|
||||||
return ComponentGetValue2(self.ID, fieldName) -- TODO: Rework Noita API to handle vectors, and return a vector instead of some shitty multi value result
|
|
||||||
end
|
|
||||||
|
|
||||||
---Sets the value of a field. Value(s) should have a type matching the field type.
|
|
||||||
---Reports error if the values weren't given in correct type, the field type is not supported, or the component does not exist.
|
|
||||||
---@param fieldName string
|
|
||||||
---@param ... any|nil -- Vectors use one argument per dimension.
|
|
||||||
function NoitaComponent:SetValue(fieldName, ...)
|
|
||||||
return ComponentSetValue2(self.ID, fieldName, ...) -- TODO: Rework Noita API to handle vectors, and use a vector instead of shitty multi value arguments
|
|
||||||
end
|
|
||||||
|
|
||||||
---Returns one or many values matching the type or subtypes of the requested field in a component subobject.
|
|
||||||
---Reports error and returns nil if the field type is not supported or 'object_name' is not a metaobject.
|
|
||||||
---
|
|
||||||
---Reporting errors means that it spams the stdout with messages, instead of using the lua error handling. Thanks Nolla.
|
|
||||||
---@param objectName string
|
|
||||||
---@param fieldName string
|
|
||||||
---@return any|nil
|
|
||||||
function NoitaComponent:ObjectGetValue(objectName, fieldName)
|
|
||||||
return ComponentObjectGetValue2(self.ID, objectName, fieldName) -- TODO: Rework Noita API to handle vectors, and return a vector instead of some shitty multi value result
|
|
||||||
end
|
|
||||||
|
|
||||||
---Sets the value of a field in a component subobject. Value(s) should have a type matching the field type.
|
|
||||||
---Reports error if the values weren't given in correct type, the field type is not supported or 'object_name' is not a metaobject.
|
|
||||||
---@param objectName string
|
|
||||||
---@param fieldName string
|
|
||||||
---@param ... any|nil -- Vectors use one argument per dimension.
|
|
||||||
function NoitaComponent:ObjectSetValue(objectName, fieldName, ...)
|
|
||||||
return ComponentObjectSetValue2(self.ID, objectName, fieldName, ...) -- TODO: Rework Noita API to handle vectors, and use a vector instead of shitty multi value arguments
|
|
||||||
end
|
|
||||||
|
|
||||||
---Creates a component of type 'component_type_name' and adds it to 'entity_id'.
|
---Creates a component of type 'component_type_name' and adds it to 'entity_id'.
|
||||||
---'table_of_component_values' should be a string-indexed table, where keys are field names and values are field values of correct type.
|
---'table_of_component_values' should be a string-indexed table, where keys are field names and values are field values of correct type.
|
||||||
---The value setting works like ComponentObjectSetValue2(), with the exception that multivalue types are not supported.
|
---The value setting works like ComponentObjectSetValue2(), with the exception that multivalue types are not supported.
|
||||||
@ -507,116 +348,30 @@ end
|
|||||||
---@return NoitaComponent|nil
|
---@return NoitaComponent|nil
|
||||||
function NoitaEntity:EntityAddComponent(componentTypeName, tableOfComponentValues)
|
function NoitaEntity:EntityAddComponent(componentTypeName, tableOfComponentValues)
|
||||||
local componentID = EntityAddComponent2(self.ID, componentTypeName, tableOfComponentValues)
|
local componentID = EntityAddComponent2(self.ID, componentTypeName, tableOfComponentValues)
|
||||||
if componentID == nil then
|
return ComponentAPI.WrapID(componentID)
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return setmetatable({ ID = componentID }, NoitaComponent)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
---@param arrayMemberName string
|
|
||||||
---@param typeStoredInVector "int"|"float"|"string"
|
|
||||||
---@return number
|
|
||||||
function NoitaComponent:GetVectorSize(arrayMemberName, typeStoredInVector)
|
|
||||||
return ComponentGetVectorSize(self.ID, arrayMemberName, typeStoredInVector)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
---@param arrayName string
|
|
||||||
---@param typeStoredInVector "int"|"float"|"string"
|
|
||||||
---@param index number
|
|
||||||
---@return number|number|string|nil
|
|
||||||
function NoitaComponent:GetVectorValue(arrayName, typeStoredInVector, index)
|
|
||||||
return ComponentGetVectorValue(self.ID, arrayName, typeStoredInVector, index)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
---@param arrayName string
|
|
||||||
---@param typeStoredInVector "int"|"float"|"string"
|
|
||||||
---@return number[]|number|string|nil
|
|
||||||
function NoitaComponent:GetVector(arrayName, typeStoredInVector)
|
|
||||||
return ComponentGetVector(self.ID, arrayName, typeStoredInVector)
|
|
||||||
end
|
|
||||||
|
|
||||||
---Returns true if the given component exists and is enabled, else false.
|
|
||||||
---@return boolean
|
|
||||||
function NoitaComponent:GetIsEnabled()
|
|
||||||
return ComponentGetIsEnabled(self.ID)
|
|
||||||
end
|
|
||||||
|
|
||||||
---Returns a string-indexed table of string.
|
|
||||||
---@return table<string, string>|nil
|
|
||||||
function NoitaComponent:GetMembers()
|
|
||||||
return ComponentGetMembers(self.ID)
|
|
||||||
end
|
|
||||||
|
|
||||||
---Returns a string-indexed table of string or nil.
|
|
||||||
---@param objectName string
|
|
||||||
---@return table<string, string>|nil
|
|
||||||
function NoitaComponent:ObjectGetMembers(objectName)
|
|
||||||
return ComponentObjectGetMembers(self.ID, objectName)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
---@return string string
|
|
||||||
function NoitaComponent:GetTypeName()
|
|
||||||
return ComponentGetTypeName(self.ID)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: Add missing Noita API methods and functions.
|
-- TODO: Add missing Noita API methods and functions.
|
||||||
|
|
||||||
---
|
-------------------------
|
||||||
---@param strength number
|
-- JSON Implementation --
|
||||||
---@param position Vec2|nil -- Defaults to camera position if not set.
|
-------------------------
|
||||||
function CameraAPI.Screenshake(strength, position)
|
|
||||||
if position == nil then
|
|
||||||
return GameScreenshake(strength)
|
|
||||||
end
|
|
||||||
return GameScreenshake(strength, position.x, position.y)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TODO: Add missing Noita API methods and functions.
|
---MarshalJSON implements the JSON marshaler interface.
|
||||||
|
---@return string
|
||||||
---Returns the center position of the viewport in world/virtual coordinates.
|
function NoitaEntity:MarshalJSON()
|
||||||
---@return Vec2
|
local result = {
|
||||||
function CameraAPI.Pos()
|
name = self:GetName(),
|
||||||
return Vec2(GameGetCameraPos())
|
filename = self:GetFilename(),
|
||||||
end
|
tags = self:GetTags(),
|
||||||
|
children = self:GetAllChildren(),
|
||||||
---Sets the center position of the viewport in world/virtual coordinates.
|
components = self:GetAllComponents(),
|
||||||
---@param position Vec2
|
transform = {},
|
||||||
function CameraAPI.SetPos(position)
|
|
||||||
return GameSetCameraPos(position.x, position.y)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
---@param isFree boolean
|
|
||||||
function CameraAPI.SetCameraFree(isFree)
|
|
||||||
return GameSetCameraFree(isFree)
|
|
||||||
end
|
|
||||||
|
|
||||||
---Returns the camera boundaries rectangle in world/virtual coordinates.
|
|
||||||
---This may not be 100% pixel perfect with regards to what you see on the screen.
|
|
||||||
---@return Vec2 topLeft
|
|
||||||
---@return Vec2 bottomRight
|
|
||||||
function CameraAPI.Bounds()
|
|
||||||
local x, y, w, h = GameGetCameraBounds()
|
|
||||||
return Vec2(x, y), Vec2(x + w, y + h)
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------
|
|
||||||
-- Noita API root --
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
---@class NoitaAPI
|
|
||||||
local api = {
|
|
||||||
Component = ComponentAPI,
|
|
||||||
Entity = EntityAPI,
|
|
||||||
Camera = CameraAPI,
|
|
||||||
MetaTables = {
|
|
||||||
Component = NoitaComponent,
|
|
||||||
Entity = NoitaEntity,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return api
|
result.transform.x, result.transform.y, result.transform.rotation, result.transform.scaleX, result.transform.scaleY = self:GetTransform()
|
||||||
|
|
||||||
|
return json.Marshal(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
return EntityAPI
|
@ -3,8 +3,8 @@
|
|||||||
-- This software is released under the MIT License.
|
-- This software is released under the MIT License.
|
||||||
-- https://opensource.org/licenses/MIT
|
-- https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
---@type NoitaAPI
|
---@type NoitaEntityAPI
|
||||||
local noitaAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api.lua")
|
local EntityAPI = dofile_once("mods/noita-mapcap/files/libraries/noita-api/entity.lua")
|
||||||
|
|
||||||
local oldPerkSpawn = perk_spawn
|
local oldPerkSpawn = perk_spawn
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ local oldPerkSpawn = perk_spawn
|
|||||||
---@param dontRemoveOtherPerks boolean
|
---@param dontRemoveOtherPerks boolean
|
||||||
---@return NoitaEntity|nil
|
---@return NoitaEntity|nil
|
||||||
function perk_spawn(x, y, perkID, dontRemoveOtherPerks)
|
function perk_spawn(x, y, perkID, dontRemoveOtherPerks)
|
||||||
local entity = noitaAPI.Entity.WrapID(oldPerkSpawn(x, y, perkID, dontRemoveOtherPerks))
|
local entity = EntityAPI.WrapID(oldPerkSpawn(x, y, perkID, dontRemoveOtherPerks))
|
||||||
if entity == nil then return end
|
if entity == nil then return end
|
||||||
|
|
||||||
-- Remove the SpriteOffsetAnimatorComponent components from the entity.
|
-- Remove the SpriteOffsetAnimatorComponent components from the entity.
|
||||||
|
3
init.lua
3
init.lua
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
dofile("mods/noita-mapcap/files/init.lua")
|
dofile("mods/noita-mapcap/files/init.lua")
|
||||||
|
|
||||||
|
---Called in order upon loading game.
|
||||||
|
function OnModInit() end
|
||||||
|
|
||||||
function OnPlayerSpawned(player_entity)
|
function OnPlayerSpawned(player_entity)
|
||||||
--EntityLoad("mods/noita-mapcap/files/luacomponent.xml") -- ffi isn't accessible from inside lua components, scrap that idea
|
--EntityLoad("mods/noita-mapcap/files/luacomponent.xml") -- ffi isn't accessible from inside lua components, scrap that idea
|
||||||
modGUI = GuiCreate()
|
modGUI = GuiCreate()
|
||||||
|
Loading…
Reference in New Issue
Block a user