Introduce classes and reusable OOP

This commit is contained in:
Juraj Vajda 2022-10-21 15:24:25 -04:00
parent b5b4e33348
commit cea205400e
3 changed files with 135 additions and 33 deletions

136
api.lua
View File

@ -1,3 +1,17 @@
---Check if table contains value
---@param table table
---@param value string|number
---@return boolean
local function table_contains(table, value)
for _, v in ipairs(table) do
if v == value then
return true
end
end
return false
end
---Merge two tables with key/value pair ---Merge two tables with key/value pair
---@param t1 table ---@param t1 table
---@param t2 table ---@param t2 table
@ -53,10 +67,19 @@ local XBowsEntityDef = {}
XBowsEntityDef.__index = XBowsEntityDef XBowsEntityDef.__index = XBowsEntityDef
setmetatable(XBowsEntityDef, XBows) setmetatable(XBowsEntityDef, XBows)
---Check if creative is enabled or if player has creative priv
---@param self XBows
---@param name string
---@return boolean
function XBows.is_creative(self, name) function XBows.is_creative(self, name)
return self.creative or minetest.check_player_privs(name, {creative = true}) return self.creative or minetest.check_player_privs(name, {creative = true})
end end
---Updates `allowed_ammunition` definition on already registered item, so MODs can add new ammunitions to this list.
---@param self XBows
---@param name string
---@param allowed_ammunition string[]
---@return nil
function XBows.update_bow_allowed_ammunition(self, name, allowed_ammunition) function XBows.update_bow_allowed_ammunition(self, name, allowed_ammunition)
local _name = 'x_bows:'..name local _name = 'x_bows:'..name
local def = self.registered_bows[_name] local def = self.registered_bows[_name]
@ -77,6 +100,7 @@ function XBows.update_bow_allowed_ammunition(self, name, allowed_ammunition)
end end
---Reset charged bow to uncharged bow, this will return the arrow item to the inventory also ---Reset charged bow to uncharged bow, this will return the arrow item to the inventory also
---@param self XBows
---@param player ObjectRef Player Ref ---@param player ObjectRef Player Ref
---@param includeWielded? boolean Will include reset for wielded bow also. default: `false` ---@param includeWielded? boolean Will include reset for wielded bow also. default: `false`
---@return nil ---@return nil
@ -119,6 +143,7 @@ function XBows.reset_charged_bow(self, player, includeWielded)
end end
---Register bows ---Register bows
---@param self XBows
---@param name string ---@param name string
---@param def ItemDef | BowItemDefCustom ---@param def ItemDef | BowItemDefCustom
---@param override? boolean MOD everride ---@param override? boolean MOD everride
@ -246,6 +271,7 @@ function XBows.register_bow(self, name, def, override)
end end
---Register arrows ---Register arrows
---@param self XBows
---@param name string ---@param name string
---@param def ItemDef | ArrowItemDefCustom ---@param def ItemDef | ArrowItemDefCustom
---@return boolean|nil ---@return boolean|nil
@ -304,6 +330,7 @@ function XBows.register_arrow(self, name, def)
end end
---Register quivers ---Register quivers
---@param self XBows
---@param name string ---@param name string
---@param def ItemDef | QuiverItemDefCustom ---@param def ItemDef | QuiverItemDefCustom
---@return boolean|nil ---@return boolean|nil
@ -401,7 +428,8 @@ function XBows.register_quiver(self, name, def)
end end
end end
---Loads bow ---Load bow
---@param self XBows
---@param itemstack ItemStack ---@param itemstack ItemStack
---@param user ObjectRef ---@param user ObjectRef
---@param pointed_thing PointedThingDef ---@param pointed_thing PointedThingDef
@ -520,7 +548,8 @@ function XBows.load(self, itemstack, user, pointed_thing)
return itemstack return itemstack
end end
---Shoots the bow ---Shoot bow
---@param self XBows
---@param itemstack ItemStack ---@param itemstack ItemStack
---@param user ObjectRef ---@param user ObjectRef
---@param pointed_thing? PointedThingDef ---@param pointed_thing? PointedThingDef
@ -682,6 +711,11 @@ function XBows.shoot(self, itemstack, user, pointed_thing)
return itemstack return itemstack
end end
---Add new particle to XBow registration
---@param self XBows
---@param name string
---@param def ParticlespawnerDef|ParticlespawnerDefCustom
---@return nil
function XBows.register_particle_effect(self, name, def) function XBows.register_particle_effect(self, name, def)
if self.registered_particle_spawners[name] then if self.registered_particle_spawners[name] then
minetest.log('warning', 'Particle effect "' .. name .. '" already exists and will not be overwritten.') minetest.log('warning', 'Particle effect "' .. name .. '" already exists and will not be overwritten.')
@ -691,13 +725,17 @@ function XBows.register_particle_effect(self, name, def)
self.registered_particle_spawners[name] = def self.registered_particle_spawners[name] = def
end end
---Get particle effect from registered spawners table
---@param self XBows
---@param name string
---@param pos Vector
---@return number|boolean
function XBows.get_particle_effect_for_arrow(self, name, pos) function XBows.get_particle_effect_for_arrow(self, name, pos)
local def = self.registered_particle_spawners[name] local def = self.registered_particle_spawners[name]
if not def then if not def then
minetest.log('warning', 'Particle effect "' .. name .. '" is not registered.') minetest.log('warning', 'Particle effect "' .. name .. '" is not registered.')
return return false
end end
def.custom = def.custom or {} def.custom = def.custom or {}
@ -707,6 +745,11 @@ function XBows.get_particle_effect_for_arrow(self, name, pos)
return minetest.add_particlespawner(def--[[@as ParticlespawnerDef]]) return minetest.add_particlespawner(def--[[@as ParticlespawnerDef]])
end end
---Check if ammunition is allowed to charge this weapon
---@param self XBows
---@param weapon_name string
---@param ammo_name string
---@return boolean
function XBows.is_allowed_ammunition(self, weapon_name, ammo_name) function XBows.is_allowed_ammunition(self, weapon_name, ammo_name)
local x_bows_weapon_def = self.registered_bows[weapon_name] local x_bows_weapon_def = self.registered_bows[weapon_name]
@ -722,21 +765,7 @@ function XBows.is_allowed_ammunition(self, weapon_name, ammo_name)
return false return false
end end
return XBows.table_contains(x_bows_weapon_def.custom.allowed_ammunition, ammo_name) return table_contains(x_bows_weapon_def.custom.allowed_ammunition, ammo_name)
end
---Check if table contains value
---@param table table
---@param value string|number
---@return boolean
function XBows.table_contains(table, value)
for _, v in ipairs(table) do
if v == value then
return true
end
end
return false
end end
---- ----
@ -782,7 +811,13 @@ local function get_obj_box(obj)
return box return box
end end
function XBowsEntityDef.on_activate(self, selfObj, staticdata) ---Function receive a "luaentity" table as `self`. Called when the object is instantiated.
---@param self EntityDef|EntityDefCustom|XBows
---@param selfObj table
---@param staticdata string
---@param dtime_s? integer|number
---@return nil
function XBowsEntityDef.on_activate(self, selfObj, staticdata, dtime_s)
if not selfObj or not staticdata or staticdata == '' then if not selfObj or not staticdata or staticdata == '' then
selfObj.object:remove() selfObj.object:remove()
return return
@ -839,6 +874,11 @@ function XBowsEntityDef.on_activate(self, selfObj, staticdata)
end end
end end
---Function receive a "luaentity" table as `self`. Called when the object dies.
---@param self XBows
---@param selfObj table
---@param killer ObjectRef|nil
---@return nil
function XBowsEntityDef.on_death(self, selfObj, killer) function XBowsEntityDef.on_death(self, selfObj, killer)
if not selfObj._old_pos then if not selfObj._old_pos then
selfObj.object:remove() selfObj.object:remove()
@ -848,6 +888,11 @@ function XBowsEntityDef.on_death(self, selfObj, killer)
minetest.item_drop(ItemStack(selfObj._arrow_name), nil, vector.round(selfObj._old_pos)) minetest.item_drop(ItemStack(selfObj._arrow_name), nil, vector.round(selfObj._old_pos))
end end
--- Function receive a "luaentity" table as `self`. Called on every server tick, after movement and collision processing. `dtime`: elapsed time since last call. `moveresult`: table with collision info (only available if physical=true).
---@param self XBows
---@param selfObj table
---@param dtime number
---@return nil
function XBowsEntityDef.on_step(self, selfObj, dtime) function XBowsEntityDef.on_step(self, selfObj, dtime)
local pos = selfObj.object:get_pos() local pos = selfObj.object:get_pos()
selfObj._old_pos = selfObj._old_pos or pos selfObj._old_pos = selfObj._old_pos or pos
@ -1236,6 +1281,15 @@ function XBowsEntityDef.on_step(self, selfObj, dtime)
selfObj._old_pos = pos selfObj._old_pos = pos
end end
---Function receive a "luaentity" table as `self`. Called when somebody punches the object. Note that you probably want to handle most punches using the automatic armor group system. Can return `true` to prevent the default damage mechanism.
---@param self XBows
---@param selfObj table
---@param puncher ObjectRef|nil
---@param time_from_last_punch number|integer|nil
---@param tool_capabilities ToolCapabilitiesDef
---@param dir Vector
---@param damage number|integer
---@return boolean
function XBowsEntityDef.on_punch(self, selfObj, puncher, time_from_last_punch, tool_capabilities, dir, damage) function XBowsEntityDef.on_punch(self, selfObj, puncher, time_from_last_punch, tool_capabilities, dir, damage)
local wood_sound_def = default.node_sound_wood_defaults() local wood_sound_def = default.node_sound_wood_defaults()
@ -1247,6 +1301,10 @@ function XBowsEntityDef.on_punch(self, selfObj, puncher, time_from_last_punch, t
return false return false
end end
---Register new projectile entity
---@param self XBows
---@param name string
---@param def XBowsEntityDef
function XBows.register_entity(self, name, def) function XBows.register_entity(self, name, def)
if not def._custom then if not def._custom then
def._custom = {} def._custom = {}
@ -1301,9 +1359,10 @@ end
---- ----
---Close one or all open quivers in players inventory ---Close one or all open quivers in players inventory
---@param self XBowsQuiver
---@param player ObjectRef ---@param player ObjectRef
---@param quiver_id? string If `nil` then all open quivers will be closed ---@param quiver_id? string If `nil` then all open quivers will be closed
---@returns nil ---@return nil
function XBowsQuiver.close_quiver(self, player, quiver_id) function XBowsQuiver.close_quiver(self, player, quiver_id)
local player_inv = player:get_inventory() local player_inv = player:get_inventory()
@ -1329,6 +1388,7 @@ function XBowsQuiver.close_quiver(self, player, quiver_id)
end end
---Swap item in player inventory indicating open quiver. Preserve all ItemStack definition and meta. ---Swap item in player inventory indicating open quiver. Preserve all ItemStack definition and meta.
---@param self XBowsQuiver
---@param from_stack ItemStack transfer data from this item ---@param from_stack ItemStack transfer data from this item
---@param to_item_name string transfer data to this item ---@param to_item_name string transfer data to this item
---@return ItemStack ItemStack replacement item ---@return ItemStack ItemStack replacement item
@ -1423,7 +1483,9 @@ function XBowsQuiver.get_itemstack_arrow_from_quiver(self, player)
end end
---Remove all added HUDs ---Remove all added HUDs
---@param self XBowsQuiver
---@param player ObjectRef ---@param player ObjectRef
---@return nil
function XBowsQuiver.remove_hud(self, player) function XBowsQuiver.remove_hud(self, player)
local player_name = player:get_player_name() local player_name = player:get_player_name()
@ -1451,6 +1513,12 @@ function XBowsQuiver.remove_hud(self, player)
end end
---@todo implement hud_change? ---@todo implement hud_change?
---Update or create quiver HUD
---@param self XBowsQuiver
---@param player ObjectRef
---@param inv_list ItemStack[]
---@param idx? number
---@return nil
function XBowsQuiver.udate_or_create_hud(self, player, inv_list, idx) function XBowsQuiver.udate_or_create_hud(self, player, inv_list, idx)
local _idx = idx or 1 local _idx = idx or 1
local player_name = player:get_player_name() local player_name = player:get_player_name()
@ -1549,6 +1617,12 @@ function XBowsQuiver.udate_or_create_hud(self, player, inv_list, idx)
end, player)) end, player))
end end
---Get existing detached inventory or create new one
---@param self XBowsQuiver
---@param quiver_id string
---@param player_name string
---@param quiver_items? string
---@return InvRef|unknown
function XBowsQuiver.get_or_create_detached_inv(self, quiver_id, player_name, quiver_items) function XBowsQuiver.get_or_create_detached_inv(self, quiver_id, player_name, quiver_items)
local detached_inv local detached_inv
@ -1635,7 +1709,8 @@ function XBowsQuiver.get_or_create_detached_inv(self, quiver_id, player_name, qu
return detached_inv return detached_inv
end end
---create formspec ---Create formspec
---@param self XBowsQuiver
---@param name string name of the form ---@param name string name of the form
---@return string ---@return string
function XBowsQuiver.get_formspec(self, name) function XBowsQuiver.get_formspec(self, name)
@ -1672,7 +1747,8 @@ function XBowsQuiver.get_formspec(self, name)
return formspec return formspec
end end
---convert inventory of itemstacks to serialized string ---Convert inventory of itemstacks to serialized string
---@param self XBowsQuiver
---@param inv InvRef ---@param inv InvRef
---@return {['inv_string']: string, ['content_description']: string} ---@return {['inv_string']: string, ['content_description']: string}
function XBowsQuiver.get_string_from_inv(self, inv) function XBowsQuiver.get_string_from_inv(self, inv)
@ -1695,9 +1771,11 @@ function XBowsQuiver.get_string_from_inv(self, inv)
} }
end end
---set items from serialized string to inventory ---Set items from serialized string to inventory
---@param self XBowsQuiver
---@param inv InvRef inventory to add items to ---@param inv InvRef inventory to add items to
---@param str string previously stringified inventory of itemstacks ---@param str string previously stringified inventory of itemstacks
---@return nil
function XBowsQuiver.set_string_to_inv(self, inv, str) function XBowsQuiver.set_string_to_inv(self, inv, str)
local t = minetest.deserialize(str) local t = minetest.deserialize(str)
@ -1708,6 +1786,12 @@ function XBowsQuiver.set_string_to_inv(self, inv, str)
end end
end end
---Save quiver inventory to itemstack meta
---@param self XBowsQuiver
---@param inv InvRef
---@param player ObjectRef
---@param quiver_is_closed? boolean
---@return nil
function XBowsQuiver.save(self, inv, player, quiver_is_closed) function XBowsQuiver.save(self, inv, player, quiver_is_closed)
local player_inv = player:get_inventory() local player_inv = player:get_inventory()
local inv_loc = inv:get_location() local inv_loc = inv:get_location()
@ -1738,7 +1822,8 @@ function XBowsQuiver.save(self, inv, player, quiver_is_closed)
end end
end end
---check if we are allowing actions in the correct quiver inventory ---Check if we are allowing actions in the correct quiver inventory
---@param self XBowsQuiver
---@param inv InvRef ---@param inv InvRef
---@param player ObjectRef ---@param player ObjectRef
---@return boolean ---@return boolean
@ -1763,6 +1848,7 @@ function XBowsQuiver.quiver_can_allow(self, inv, player)
end end
---Open quiver ---Open quiver
---@param self XBowsQuiver
---@param itemstack ItemStack ---@param itemstack ItemStack
---@param user ObjectRef ---@param user ObjectRef
---@return ItemStack ---@return ItemStack

View File

@ -3,13 +3,13 @@
---Entity definition ---Entity definition
---@class EntityDef ---@class EntityDef
---@field initial_properties ObjectProperties A table of object properties. The properties in this table are applied to the object once when it is spawned. `dtime_s` is the time passed since the object was unloaded, which can be used for updating the entity state. ---@field initial_properties ObjectProperties A table of object properties. The properties in this table are applied to the object once when it is spawned. `dtime_s` is the time passed since the object was unloaded, which can be used for updating the entity state.
---@field on_activate fun(self: table, staticdata: string, dtime_s: integer|number) Function receive a "luaentity" table as `self`. Called when the object is instantiated. ---@field on_activate fun(self: table, staticdata: string, dtime_s: integer|number): nil Function receive a "luaentity" table as `self`. Called when the object is instantiated.
---@field on_deactivate fun(self: table, removal: boolean): nil Function receive a "luaentity" table as `self`. Called when the object is about to get removed or unloaded. `removal`: boolean indicating whether the object is about to get removed. Calling `object:remove()` on an active object will call this with `removal=true`. The mapblock the entity resides in being unloaded will call this with `removal=false`. Note that this won't be called if the object hasn't been activated in the first place. In particular, `minetest.clear_objects({mode = "full"})` won't call this, whereas `minetest.clear_objects({mode = "quick"})` might call this. ---@field on_deactivate fun(self: table, removal: boolean): nil Function receive a "luaentity" table as `self`. Called when the object is about to get removed or unloaded. `removal`: boolean indicating whether the object is about to get removed. Calling `object:remove()` on an active object will call this with `removal=true`. The mapblock the entity resides in being unloaded will call this with `removal=false`. Note that this won't be called if the object hasn't been activated in the first place. In particular, `minetest.clear_objects({mode = "full"})` won't call this, whereas `minetest.clear_objects({mode = "quick"})` might call this.
---@field on_step fun(self: table, dtime: integer|number, moveresult?: table) Function receive a "luaentity" table as `self`. Called on every server tick, after movement and collision processing. `dtime`: elapsed time since last call. `moveresult`: table with collision info (only available if physical=true). ---@field on_step fun(self: table, dtime: integer|number, moveresult?: table): nil Function receive a "luaentity" table as `self`. Called on every server tick, after movement and collision processing. `dtime`: elapsed time since last call. `moveresult`: table with collision info (only available if physical=true).
---@field on_punch fun(self: table, puncher: ObjectRef|nil, time_from_last_punch: number|integer|nil, tool_capabilities: ToolCapabilitiesDef|nil, dir: Vector, damage: number|integer): boolean|nil Function receive a "luaentity" table as `self`. Called when somebody punches the object. Note that you probably want to handle most punches using the automatic armor group system. Can return `true` to prevent the default damage mechanism. ---@field on_punch fun(self: table, puncher: ObjectRef|nil, time_from_last_punch: number|integer|nil, tool_capabilities: ToolCapabilitiesDef|nil, dir: Vector, damage: number|integer): boolean|nil Function receive a "luaentity" table as `self`. Called when somebody punches the object. Note that you probably want to handle most punches using the automatic armor group system. Can return `true` to prevent the default damage mechanism.
---@field on_death fun(self: table, killer: ObjectRef|nil): nil Function receive a "luaentity" table as `self`. Called when the object dies. ---@field on_death fun(self: table, killer: ObjectRef|nil): nil Function receive a "luaentity" table as `self`. Called when the object dies.
---@field on_rightclick fun(self: table, clicker: ObjectRef): nil Function receive a "luaentity" table as `self`. Called when `clicker` pressed the 'place/use' key while pointing to the object (not neccessarily an actual rightclick). `clicker`: an `ObjectRef` (may or may not be a player) ---@field on_rightclick fun(self: table, clicker: ObjectRef): nil Function receive a "luaentity" table as `self`. Called when `clicker` pressed the 'place/use' key while pointing to the object (not neccessarily an actual rightclick). `clicker`: an `ObjectRef` (may or may not be a player)
---@field on_attach_child fun(self: table, child: ObjectRef): nil Function receive a "luaentity" table as `self`. `child`: an `ObjectRef` of the child that attaches ---@field on_attach_child fun(self: table, child: ObjectRef): nil Function receive a "luaentity" table as `self`. `child`: an `ObjectRef` of the child that attaches
---@field on_detach_child fun(self: table, child: ObjectRef): nil Function receive a "luaentity" table as `self`. `child`: an `ObjectRef` of the child that detaches ---@field on_detach_child fun(self: table, child: ObjectRef): nil Function receive a "luaentity" table as `self`. `child`: an `ObjectRef` of the child that detaches
---@field on_detach fun(self: table, parent: ObjectRef|nil) Function receive a "luaentity" table as `self`. `parent`: an `ObjectRef` (can be `nil`) from where it got detached. This happens before the parent object is removed from the world. ---@field on_detach fun(self: table, parent: ObjectRef|nil): nil Function receive a "luaentity" table as `self`. `parent`: an `ObjectRef` (can be `nil`) from where it got detached. This happens before the parent object is removed from the world.
---@field get_staticdata fun(self: table) Function receive a "luaentity" table as `self`. Should return a string that will be passed to `on_activate` when the object is instantiated the next time. ---@field get_staticdata fun(self: table) Function receive a "luaentity" table as `self`. Should return a string that will be passed to `on_activate` when the object is instantiated the next time.

View File

@ -13,11 +13,19 @@
---@field settings table ---@field settings table
---@field quiver table Quiver class ---@field quiver table Quiver class
---@field charge_sound_after_job table<string, JobTable> ---@field charge_sound_after_job table<string, JobTable>
---@field is_allowed_ammunition fun(self: XBows, weapon_name: string, ammo_name: string): boolean ---Check if ammunition is allowed to charge this weapon ---@field is_allowed_ammunition fun(self: XBows, weapon_name: string, ammo_name: string): boolean Check if ammunition is allowed to charge this weapon
---@field is_creative fun(self: XBows, name: string): boolean Check if creative is enabled or if player has creative priv ---@field is_creative fun(self: XBows, name: string): boolean Check if creative is enabled or if player has creative priv
---@field register_particle_effect fun(self: XBows, name: string, def: ParticlespawnerDef|ParticlespawnerDefCustom): nil ---@field get_particle_effect_for_arrow fun(self: XBows, name: string, pos: Vector): number|boolean Get particle effect from registered spawners table
---@field get_particle_effect_for_arrow fun(self: XBows, name: string, pos: Vector): number
---@field register_entity fun(self: EntityDef|XBows, name: string, def: XBowsEntityDef): nil Register new projectile entity ---@field register_entity fun(self: EntityDef|XBows, name: string, def: XBowsEntityDef): nil Register new projectile entity
---@field update_bow_allowed_ammunition fun(self: XBows, name: string, def: string[]): nil Updates `allowed_ammunition` definition on already registered item, so MODs can add new ammunitions to this list.
---@field reset_charged_bow fun(self: XBows, player: ObjectRef, includeWielded?: boolean): nil Reset charged bow to uncharged bow, this will return the arrow item to the inventory also
---@field register_bow fun(self: XBows, name: string, def: ItemDef | BowItemDefCustom, mod_override?: boolean): boolean|nil Register new bow/gun.
---@field register_arrow fun(self: XBows, name: string, def: ItemDef | ArrowItemDefCustom): boolean|nil Register new arrow/projectile.
---@field register_quiver fun(self: XBows, name: string, def: ItemDef | ArrowItemDefCustom): boolean|nil Register new quiver.
---@field load fun(self: XBows, itemstack: ItemStack, user: ObjectRef, pointed_thing: PointedThingDef): ItemStack Load bow
---@field shoot fun(self: XBows, itemstack: ItemStack, user: ObjectRef, pointed_thing?: PointedThingDef): ItemStack Shoot bow
---@field register_particle_effect fun(self: XBows, name: string, def: ParticlespawnerDef|ParticlespawnerDefCustom): nil Add new particle to XBow registration
---@field open_quiver fun(self: XBowsQuiver, itemstack: ItemStack, user: ObjectRef): ItemStack Open quiver
---XBowsQuiver class extended from XBows ---XBowsQuiver class extended from XBows
@ -25,9 +33,17 @@
---@class XBowsQuiverBase ---@class XBowsQuiverBase
---@field hud_item_ids table ---@field hud_item_ids table
---@field after_job table<string, JobTable> ---@field after_job table<string, JobTable>
---@field udate_or_create_hud fun(self: XBowsQuiver, player: ObjectRef, inv_list: ItemStack[], idx?: number): nil Update or create HUD ---@field udate_or_create_hud fun(self: XBowsQuiver, player: ObjectRef, inv_list: ItemStack[], idx?: number): nil Update or create quiver HUD
---@field get_or_create_detached_inv fun(self: XBowsQuiver, quiver_id: string, player_name: string, quiver_items?: string): InvRef Get existing detached inventory or create new one ---@field get_or_create_detached_inv fun(self: XBowsQuiver, quiver_id: string, player_name: string, quiver_items?: string): InvRef|unknown Get existing detached inventory or create new one
---@field save fun(self: XBowsQuiver, inv: InvRef, player: ObjectRef, quiver_is_closed?: boolean): nil Save quiver inventory to itemstack meta ---@field save fun(self: XBowsQuiver, inv: InvRef, player: ObjectRef, quiver_is_closed?: boolean): nil Save quiver inventory to itemstack meta
---@field close_quiver fun(self: XBowsQuiver, player: ObjectRef, quiver_id?: string): nil Close one or all open quivers in players inventory
---@field get_replacement_item fun(self: XBowsQuiver, from_stack: ItemStack, to_item_name: string): ItemStack Swap item in player inventory indicating open quiver. Preserve all ItemStack definition and meta.
---@field get_itemstack_arrow_from_quiver fun(self: XBowsQuiver, player: ObjectRef, to_item_name: string): {["found_arrow_stack"]: ItemStack|nil, ["quiver_id"]: string|nil, ["quiver_name"]: string|nil, ["found_arrow_stack_idx"]: number} Gets arrow from quiver
---@field remove_hud fun(self: XBowsQuiver, player: ObjectRef): nil Remove all added HUDs
---@field get_formspec fun(self: XBowsQuiver, name: string): string Create formspec
---@field get_string_from_inv fun(self: XBowsQuiver, inv: InvRef): {['inv_string']: string, ['content_description']: string} Convert inventory of itemstacks to serialized string
---@field set_string_to_inv fun(self: XBowsQuiver, inv: InvRef, str: string): nil Set items from serialized string to inventory
---@field quiver_can_allow fun(self: XBowsQuiver, inv: InvRef, player: ObjectRef): boolean Check if we are allowing actions in the correct quiver inventory
---Custom field in ParticlespawnerDef ---Custom field in ParticlespawnerDef