Move node itemstacks from meta inv to field

Node inventories are sent to clients, while metadata
fields are automatically set private by the server
and not sent to clients.  Not using node meta
inventories may help reduce the amount of data
sent to clients, especially in storage-heavy areas
where we were duplicating the work of sending the
inventory data not used on the client, as well as the
visible item entities.

Automatically convert old-format data to new upon
reading.

Also, needed to provide some APIs for sane access
to data in serialized format, and another way to
signal that a node can accept a stack other than
the size of inventory[solo]
This commit is contained in:
Aaron Suen 2021-04-10 09:00:39 -04:00
parent f91bc9d2a1
commit d414c1f3b0
3 changed files with 40 additions and 30 deletions

View File

@ -46,12 +46,29 @@ function nodecore.stack_merge(dest, src)
return src
end
function nodecore.node_inv(pos)
return minetest.get_meta(pos):get_inventory()
end
local metakey = "ncitem"
function nodecore.stack_get(pos)
return nodecore.node_inv(pos):get_stack("solo", 1)
local meta = minetest.get_meta(pos)
local str = meta:get_string(metakey)
if str and str ~= "" then return ItemStack(str) end
local inv = meta:get_inventory()
local stack = inv:get_stack("solo", 1)
if stack:is_empty() then return stack end
meta:set_string(metakey, stack:to_string())
inv:set_size("solo", 0)
return stack
end
function nodecore.stack_get_serial(metatable)
local str = metatable
str = str and str.fields
str = str and str[metakey]
if str and str ~= "" then return ItemStack(str) end
local inv = metatable.inventory
inv = inv and inv.solo
inv = inv and inv[1]
if inv and inv ~= "" then return ItemStack(inv) end
end
local function update(pos, ...)
@ -64,12 +81,14 @@ function nodecore.stack_set(pos, stack, player)
nodecore.log("action", string_format("%s sets stack %q at %s",
player:get_player_name(), shortdesc(stack), minetest.pos_to_string(pos)))
end
return update(pos, nodecore.node_inv(pos):set_stack("solo", 1, ItemStack(stack)))
return update(pos, minetest.get_meta(pos):set_string(metakey,
ItemStack(stack):to_string()))
end
function nodecore.stack_add(pos, stack, player)
local node = minetest.get_node(pos)
local def = minetest.registered_items[node.name] or {}
if not def.can_have_itemstack then return end
if def.stack_allow then
local ret = def.stack_allow(pos, node, stack)
if ret == false then return stack end
@ -79,13 +98,8 @@ function nodecore.stack_add(pos, stack, player)
local donate = stack:get_count()
local item = nodecore.stack_get(pos)
local exist = item:get_count()
local left
if item:is_empty() then
left = nodecore.node_inv(pos):add_item("solo", stack)
else
left = nodecore.stack_merge(item, stack)
nodecore.stack_set(pos, item)
end
local left = nodecore.stack_merge(item, stack)
nodecore.stack_set(pos, item)
local remain = left:get_count()
if donate ~= remain then
if player then

View File

@ -148,15 +148,12 @@ nodecore.register_globalstep("visinv check", function()
-- NODE REGISTRATION HELPERS
function nodecore.visinv_on_construct(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("solo", 1)
nodecore.visinv_update_ents(pos)
return nodecore.visinv_update_ents(pos)
end
function nodecore.visinv_after_destruct(pos)
nodecore.visinv_update_ents(pos)
nodecore.fallcheck(pos)
return nodecore.fallcheck(pos)
end
nodecore.register_on_register_item(function(_, def)
@ -165,6 +162,7 @@ nodecore.register_on_register_item(function(_, def)
def.groups = def.groups or {}
if def.groups.visinv then
def.can_have_itemstack = true
def.on_construct = def.on_construct or nodecore.visinv_on_construct
def.after_destruct = def.after_destruct or nodecore.visinv_after_destruct
end

View File

@ -1,21 +1,19 @@
-- LUALOCALS < ---------------------------------------------------------
local ItemStack, minetest, nodecore
= ItemStack, minetest, nodecore
local minetest, nodecore
= minetest, nodecore
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
nodecore.register_falling_node_on_setnode(function(self, node, meta)
if node and node.name == modname .. ":stack"
and meta and meta.inventory and meta.inventory.solo then
local stack = ItemStack(meta.inventory.solo[1] or "")
if not stack:is_empty() then
local pos = self.object:get_pos()
if not pos then return end
local ent = minetest.add_item(pos, stack)
if ent then ent:set_velocity(self.object:get_velocity()) end
self.object:remove()
return true
end
if not (node and node.name == modname .. ":stack") then return end
local stack = nodecore.stack_get_serial(meta)
if not stack:is_empty() then
local pos = self.object:get_pos()
if not pos then return end
local ent = minetest.add_item(pos, stack)
if ent then ent:set_velocity(self.object:get_velocity()) end
self.object:remove()
return true
end
end)