全站通知:

插件编写:物品栏和背包

阅读

    

2020-10-18更新

    

最新编辑:pevernow

阅读:

  

更新日期:2020-10-18

  

最新编辑:pevernow

来自MinetestWIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索
页面贡献者 :
pevernow

在这一章节中,你将知道如何使用和控制背包,或许是玩家的背包(物品库),或者是节点中的物品库,或者是独立的物品库。

什么是物品库(或者是玩家背包)?

一个物品栏是清单中单个单元格后面的数据。<br/>
库存是库存列表的集合,每个列表都是物品栏的二维网格。清单在清单的上下文中简称为清单。当玩家和节点最多只有一个物品库时,物品库的重点是允许多个网格。<br/>

物品栏

物品栏有三个组件。<br/>
项名称可以是已注册项的项名称、别名或未知项名称。当用户卸载mods或mods在没有预防措施(如注册别名)的情况下删除项时,未知项很常见。

print(stack:get_name())
stack:set_name("default:dirt")

if not stack:is_known() then
    print("Is an unknown item!")
end

计数将始终为0或更大。通过正常的游戏,计数应该不超过项目堆栈最大的堆栈大小(stack_max)。但是,管理命令和错误模式可能导致堆栈超过最大大小。

print(stack:get_stack_max())

ItemStack可以为空,在这种情况下,计数将为0。

print(stack:get_count())
stack:set_count(10)

可以使用ItemStack函数以多种方式构造ItemStack。

ItemStack() -- name="", count=0
ItemStack("default:pick_stone") -- count=1
ItemStack("default:stone 30")
ItemStack({ name = "default:wood", count = 10 })

项目元数据是有关该项目的数据的不受限制的键值存储。键值意味着您使用一个名称(称为键)来访问数据(称为值)。有些键有特殊的含义,例如description,用于对每个堆栈项进行描述。这将在元数据和存储一章中详细介绍。

物品库的位置

物品库位置是背包存储的位置和方式。物品库位置有三种类型:player、node和detached。物品库直接绑定到一个而且只有一个位置-更新库存将导致它立即更新。<br>
节点清单与特定节点(如胸部)的位置相关。必须加载节点,因为它存储在节点元数据(未翻译)中。

local inv = minetest.get_inventory({ type="node", pos={x=1, y=2, z=3} })

上面得到一个物品库引用,通常称为InvRef。物品库引用用于操作库存。引用意味着数据实际上并不存储在该对象中,而是直接就地更新数据。<br>
举个例子:

local location = inv:get_location()

玩家物品库可以类似地获得或使用玩家参考。玩家必须在线才能访问他们的物品库。

local inv = minetest.get_inventory({ type="player", name="player1" })
-- or
local inv = player:get_inventory()

独立库存物品库是独立于参与者或节点的物品库。独立物品库也不会在重新启动时保存。需要先创建独立物品库,然后才能使用它们——这个将在稍后讨论。

local inv = minetest.get_inventory({
    type="detached", name="inventory_name" })

与其他类型的库存不同,必须首先创建分离的库存:

minetest.create_detached_inventory("inventory_name")

createdetachedinventory函数接受3个参数,只需要第一个参数。第二个参数采用回调表,该表可用于控制玩家如何与物品库交互:

-- Input only detached inventory
minetest.create_detached_inventory("inventory_name", {
    allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
        return count -- allow moving
    end,

    allow_put = function(inv, listname, index, stack, player)
        return stack:get_count() -- allow putting
    end,

    allow_take = function(inv, listname, index, stack, player)
        return -1 -- don't allow taking
    end,

    on_put = function(inv, listname, index, stack, player)
        minetest.chat_send_all(player:get_player_name() ..
            " gave " .. stack:to_string() ..
            " to the donation chest at " .. minetest.pos_to_str(pos))
    end,
})

权限回调——以allow_开头的回调返回要传输的项目数,其中-1用于完全阻止传输。<br>
操作回调——以on_为开头——没有返回值,无法阻止传输。

列表

物品库列表是一个概念,用于允许多个网格存储在一个位置。这对玩家来说尤其有用,因为所有游戏都有一些常见的列表,例如主目录和工艺槽。

大小和宽度

列表有一个大小(网格中单元格的总数)和一个宽度(仅在引擎中使用)。在窗口中绘制清单时不使用列表的宽度,因为窗口后面的代码决定要使用的宽度。

if inv:set_size("main", 32) then
    inv:set_width("main", 8)
    print("size:  " .. inv.get_size("main"))
    print("width: " .. inv:get_width("main"))
else
    print("Error! Invalid itemname or size to set_size()")
end

如果列表名或大小无效,则set_size将失败并返回false。例如,新大小可能太小,无法容纳库存中的所有当前项。

检查内容

is_empty可用于查看列表是否包含任何项:

if inv:is_empty("main") then
    print("The list is empty!")
end

contains_item can be used to see if a list contains a specific item.

修改库存和物品栏

添加到一个列表中

要将项添加到名为"main"的列表中,同时考虑最大堆栈大小,请执行以下操作:

local stack    = ItemStack("default:stone 99")
local leftover = inv:add_item("main", stack)
if leftover:get_count() > 0 then
    print("Inventory is full! " ..
            leftover:get_count() .. " items weren't added")
end

拿东西

从一个列表中移除某样东西:

local taken = inv:remove_item("main", stack)
print("Took " .. taken:get_count())

操作物品栏

你可以先修改单个物品栏:

local stack = inv:get_stack(listname, 0)

然后通过设置属性或使用与stack_size相关的方法修改它们:

local stack    = ItemStack("default:stone 50")
local to_add   = ItemStack("default:stone 100")
local leftover = stack:add_item(to_add)
local taken    = stack:take_item(19)

print("Could not add"  .. leftover:get_count() .. " of the items.")
-- ^ will be 51

print("Have " .. stack:get_count() .. " items")
-- ^ will be 80
--   min(50+100, stack_max) - 19 = 80
--     where stack_max = 99

add_item将向物品栏添加项并返回任何无法添加的项。take_item将占用最多的项目数,但可能占用较少的项目数,并返回所占用的物品栏。
最后,设定物品栏:

inv:set_stack(listname, 0, stack)

磨损

工具可能有磨损;磨损显示进度条,完全磨损时会使工具彻底报废。磨损值最高为65535;磨损越高,工具磨损越严重。<br>
磨损可以使用add_wear()get_wear()set_wear(wear)进行操作。

local stack = ItemStack("default:pick_mese")
local max_uses = 10

-- This is done automatically when you use a tool that digs things
-- It increases the wear of an item by one use.
stack:add_wear(65535 / (max_uses - 1))

挖掘节点时,工具的磨损量可能取决于正在挖掘的节点。因此,max_uses的用途因挖掘的对象而异。

Lua表

物品栏和库存可以转换为表和表。这对于复制和批量操作很有用。

-- Entire inventory
local data = inv1:get_lists()
inv2:set_lists(data)

-- One list
local listdata = inv1:get_list("main")
inv2:set_list("main", listdata)

get_lists()返回的列表表如下:

{
    list_one = {
        ItemStack,
        ItemStack,
        ItemStack,
        ItemStack,
        -- inv:get_size("list_one") elements
    },
    list_two = {
        ItemStack,
        ItemStack,
        ItemStack,
        ItemStack,
        -- inv:get_size("list_two") elements
    }
}

get_list()将返回单个列表作为物品栏列表。<br>
需要注意的一点是,上面的set方法不会改变列表的大小。这意味着您可以通过将列表设置为空表来清除列表,并且不会减小其大小:

inv:set_list("main", {})


回城链接(目录)