summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthe lemons <citrons@mondecitronne.com>2022-02-13 21:27:19 -0600
committerthe lemons <citrons@mondecitronne.com>2022-02-13 21:27:19 -0600
commit399ea8f2310e319bcfb604714f72f1b6e57669a4 (patch)
tree76bcf2ae464f86260edcf1fdf16628782957c1f3
parent69b1cf9dcd2bb561f2349e10e558a5e117b3ff3c (diff)
inventory is now working
* UI displays actual inventory * inventory items can be added to hotbar slots * game events are hooked to use vzxv inventory instead of default inventory
-rw-r--r--mods/vzxv/event.lua8
-rw-r--r--mods/vzxv_inv/init.lua230
-rw-r--r--mods/vzxv_inv/ui.lua86
-rw-r--r--mods/vzxv_itemstacks/init.lua1
4 files changed, 275 insertions, 50 deletions
diff --git a/mods/vzxv/event.lua b/mods/vzxv/event.lua
index faabd97..c4471a4 100644
--- a/mods/vzxv/event.lua
+++ b/mods/vzxv/event.lua
@@ -2,9 +2,7 @@
vzxv.event = {}
function vzxv.event.create()
- local e = {}
- setmetatable(e, vzxv.event)
- return e
+ return setmetatable({}, {__index = vzxv.event})
end
function vzxv.event:register(func)
@@ -20,7 +18,7 @@ function vzxv.event:trigger(...)
for f in pairs(self) do
v = {f(...)}
end
- return table.unpack(v)
+ return unpack(v)
end
-- iterate through all of the event handlers' results
@@ -29,6 +27,6 @@ function vzxv.event:trigger_each(...)
local bee = {...}
return function()
local f = p()
- if f then return f(table.unpack(bee)) end
+ if f then return f(unpack(bee)) end
end
end
diff --git a/mods/vzxv_inv/init.lua b/mods/vzxv_inv/init.lua
index e83374d..c5bf6f0 100644
--- a/mods/vzxv_inv/init.lua
+++ b/mods/vzxv_inv/init.lua
@@ -1,6 +1,232 @@
-minetest.register_on_player_inventory_action(function(player,action,inv,info)
- print(player,action,inv,info)
+function vzxv.get_inventory(player)
+ local m = player:get_meta()
+ local str = m:get_string "items"
+ local items = str and minetest.deserialize(str)
+ if not items then
+ return {}
+ end
+
+ local stacks = {}
+ for _, stack in ipairs(items) do
+ table.insert(stacks, ItemStack(stack))
+ end
+ return stacks
+end
+
+vzxv.on_inventory_update = vzxv.event.create()
+
+function vzxv.update_inventory(player, items)
+ local new_items = {}
+ for _, stack in ipairs(items) do
+ if not stack:is_empty() then
+ table.insert(new_items, stack:to_string())
+ end
+ end
+ local m = player:get_meta()
+ m:set_string("items", minetest.serialize(new_items))
+
+ local inv = vzxv.get_inventory(player)
+ vzxv.on_inventory_update:trigger(player, inv)
+
+ vzxv.update_hotbar(player)
+end
+
+local function match(a, b)
+ a = ItemStack(a)
+ b = ItemStack(b)
+ -- ignore item stack limits
+ a:set_count(1)
+ b:set_count(1)
+ return not a:is_empty() and not b:is_empty() and a:item_fits(b)
+end
+
+function vzxv.inventory_idx(player, stack)
+ local inv = vzxv.get_inventory(player)
+ for i, inv_stack in ipairs(inv) do
+ if match(inv_stack, stack) then
+ return i
+ end
+ end
+end
+
+function vzxv.update_hotbar(player)
+ local hotbar = player:get_inventory()
+ local inv = vzxv.get_inventory(player)
+ for i=1,8 do
+ local hotbar_stack = hotbar:get_stack("main", i)
+ if not hotbar_stack:is_empty() then
+ local idx = vzxv.inventory_idx(player, hotbar_stack)
+ if idx then
+ hotbar_stack:set_count(inv[idx]:get_count())
+ else
+ hotbar_stack:set_count(0)
+ end
+ hotbar:set_stack("main", i, hotbar_stack)
+ end
+ end
+end
+
+-- add a stack from the inventory at idx to the hotbar
+function vzxv.add_to_hotbar(player, idx, make_room)
+ local hotbar = player:get_inventory()
+ local inv = vzxv.get_inventory(player)
+ for i=1,8 do
+ local stack = hotbar:get_stack("main", i)
+ if match(stack, inv[idx]) then
+ -- stack is already in hotbar
+ return i
+ elseif stack:is_empty() then
+ hotbar:set_stack("main", i, inv[idx])
+ return i
+ end
+ end
+ if make_room then
+ for i=7,1,-1 do
+ local stack = hotbar:get_stack("main", i)
+ hotbar:set_stack("main", i + 1, stack)
+ end
+ hotbar:set_stack("main", 1, inv[idx])
+ return 1
+ end
+end
+
+-- item is given to player
+-- TODO: weight limit
+function vzxv.give_items(player, stack)
+ if stack:is_empty() then return 0 end
+ local inv = vzxv.get_inventory(player)
+ local idx = vzxv.inventory_idx(player, stack)
+ if idx then
+ inv[idx]:set_count(inv[idx]:get_count() + stack:get_count())
+ else
+ table.insert(inv, ItemStack(stack))
+ end
+ vzxv.update_inventory(player, inv)
+ return stack:get_count()
+end
+
+-- player actively collects item
+function vzxv.collect_items(player, stack)
+ if stack:is_empty() then return 0 end
+ local count = vzxv.give_items(player, stack)
+ local idx = vzxv.inventory_idx(player, stack)
+ if idx then
+ vzxv.add_to_hotbar(player, idx)
+ end
+ return count
+end
+
+-- set require_all to require that all that at least the amount of items being
+-- removed exist in the inventory
+function vzxv.remove_items(player, stack, require_all)
+ if stack:is_empty() then return 0 end
+ local idx = vzxv.inventory_idx(player, stack)
+ if not idx then return 0 end
+ local inv = vzxv.get_inventory(player)
+
+ if require_all and inv[idx]:get_count() < stack:get_count() then
+ return 0
+ end
+
+ local taken = inv[idx]:take_item(stack:get_count())
+ vzxv.update_inventory(inv)
+ return taken
+end
+
+minetest.register_allow_player_inventory_action(function(player,action,inv,info)
+ if action == "move" then
+ local from = inv:get_stack(info.from_list, info.from_index)
+ -- prevent player from splitting stacks
+ if info.count == from:get_count() then
+ return
+ end
+ end
+ return 0
+end)
+
+function minetest.handle_node_drops(pos, drops, digger)
+ local rejected = {}
+ for _, drop in ipairs(drops) do
+ drop = ItemStack(drop)
+ local accepted = vzxv.collect_items(digger, drop)
+ if drop:get_count() - accepted ~= 0 then
+ table.insert(rejected, drop:peek_item(drop:get_count() - accepted))
+ end
+ end
+ -- delay this until after the node has been set to air
+ minetest.after(0, function()
+ for _, stack in ipairs(rejected) do
+ vzxv.drop(pos, stack)
+ end
+ end)
+end
+
+minetest.register_on_joinplayer(function(player)
+ vzxv.update_hotbar(player)
end)
+minetest.register_on_placenode(function(_, _, placer, _, stack)
+ local inv = vzxv.get_inventory(placer)
+ local idx = vzxv.inventory_idx(placer, stack)
+ if idx then
+ inv[idx]:set_count(stack:get_count() - 1)
+ vzxv.update_inventory(placer, inv)
+ end
+end)
+
+local function give_command(player_name, item, count)
+ if not player_name then return false end
+ if not item then return false end
+
+ local player = minetest.get_player_by_name(player_name)
+ if not player then return false, "unknown player" end
+ count = count and tonumber(count) or 1
+
+ local stack = ItemStack(item)
+ stack:set_count(count)
+ local count = vzxv.collect_items(player, stack)
+
+ return true, ("gave %s %s to %s"):format(count, item, player_name)
+end
+
+minetest.override_chatcommand("give", {
+ params = "<player> <item> [<count>]",
+ description = "give item to player",
+ privs = {give = true},
+ func = function(name, param)
+ local args = {}
+ for arg in param:gmatch "(%S+)" do
+ table.insert(args, arg)
+ end
+ return give_command(unpack(args))
+ end,
+})
+
+minetest.override_chatcommand("giveme", {
+ params = "<item> [<count>]",
+ description = "give item to you",
+ privs = {give = true},
+ func = function(name, param)
+ local args = {}
+ for arg in param:gmatch "(%S+)" do
+ table.insert(args, arg)
+ end
+ return give_command(name, unpack(args))
+ end,
+})
+
+minetest.register_chatcommand("clear", {
+ params = "<player>",
+ description = "clear inventory of player",
+ privs = {debug = true},
+ func = function(name, param)
+ local player = minetest.get_player_by_name(param)
+ if not player then return false, "unknown player" end
+ vzxv.update_inventory(player, {})
+ return true, "inventory cleared"
+ end,
+})
+
vzxv.include "ui.lua"
+
diff --git a/mods/vzxv_inv/ui.lua b/mods/vzxv_inv/ui.lua
index b227267..431bff1 100644
--- a/mods/vzxv_inv/ui.lua
+++ b/mods/vzxv_inv/ui.lua
@@ -1,41 +1,20 @@
-local dummy_inventory = {
- {name = "vzxv:dirt", count = 56},
- {name = "vzxv:moistdirt", count = 340},
- {name = "vzxv:grass", count = 99},
- {name = "vzxv:moistgrass", count = 99},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:metalaxe", count = 34},
- {name = "vzxv:woodaxe", count = 34},
- {name = "vzxv:stoneaxe", count = 34},
- {name = "vzxv:metalspade", count = 34},
- {name = "vzxv:woodspade", count = 34},
- {name = "vzxv:stonespade", count = 34},
- {name = "vzxv:woodadze", count = 34},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
- {name = "vzxv:apioform", count = 20},
-}
+-- TODO: removing items from hotbar
local inv_state = {}
local per_page = 8
+local function sort_inv(inv)
+ table.sort(inv, function(a, b)
+ return a:get_short_description() < b:get_short_description()
+ end)
+end
+
local function inventory_item(offsx, offsy, item, idx)
- item_image({offsx, offsy}, {1, 1}, item.name)
- label({offsx + 0.75, offsy + 0.9}, item.count)
- label({offsx + 1.25, offsy + 0.5}, item.name)
+ item_image({offsx, offsy}, {1, 1}, item:get_name())
+ label({offsx + 0.75, offsy + 0.9}, item:get_count())
+ label({offsx + 1.25, offsy + 0.5}, item:get_short_description())
image_button(
{offsx + 5.25, offsy + 0.25}, {0.5, 0.5},
"vzxvplus.png", "item:" .. idx, ""
@@ -43,9 +22,9 @@ local function inventory_item(offsx, offsy, item, idx)
end
vzxv.formspec(inventory_item)
-local inventory = vzxv.formspec(function(state)
+local inventory = vzxv.formspec(function(state, inv)
formspec_version(4)
- if #dummy_inventory < per_page then
+ if #inv <= per_page then
size{8, 11.25}
else
size{14.25, 11.25}
@@ -57,20 +36,20 @@ local inventory = vzxv.formspec(function(state)
end
local p = state.page * per_page
for i = p + 1, p + per_page do
- if i > #dummy_inventory then break end
- inventory_item(1.75, (i - p) * 1.25, dummy_inventory[i], i)
+ if i > #inv then break end
+ inventory_item(1.75, (i - p) * 1.25, inv[i], i)
end
- if #dummy_inventory > per_page then
+ if #inv > per_page then
p = p + per_page
for i = p + 1, p + per_page do
- if i > #dummy_inventory then break end
- inventory_item(8.25, (i - p) * 1.25, dummy_inventory[i], i)
+ if i > #inv then break end
+ inventory_item(8.25, (i - p) * 1.25, inv[i], i)
end
end
if state.page ~= 0 then
image_button({12, 0.37}, {1, 0.5}, "vzxvprev.png", "prev", "")
end
- if p + per_page < #dummy_inventory then
+ if p + per_page < #inv then
image_button({13, 0.37}, {1, 0.5}, "vzxvnext.png", "next", "")
end
end)
@@ -78,7 +57,9 @@ end)
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
inv_state[name] = {page = 0}
- player:set_inventory_formspec(inventory(inv_state[name]))
+ local inv = vzxv.get_inventory(player)
+ sort_inv(inv)
+ player:set_inventory_formspec(inventory(inv_state[name], inv))
end)
minetest.register_on_leaveplayer(function(player)
@@ -89,15 +70,34 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "" then return end
local state = inv_state[player:get_player_name()]
+ local inv = vzxv.get_inventory(player)
+ sort_inv(inv)
+
if fields.next then
state.page = state.page + 1
end
if fields.prev then
state.page = state.page - 1
end
- if (state.page + 1) * per_page > #dummy_inventory or state.page < 0 then
- state.page = 1
+ if (state.page + 1) * per_page > #inv or state.page < 0 then
+ state.page = 0
+ end
+
+ for k in pairs(fields) do
+ local idx = k:match "^item:(%d+)$"
+ idx = idx and tonumber(idx)
+ if idx and inv[idx] then
+ local real_idx = vzxv.inventory_idx(player, inv[idx])
+ vzxv.add_to_hotbar(player, real_idx, true)
+ end
end
- player:set_inventory_formspec(inventory(state))
+ player:set_inventory_formspec(inventory(state, inv))
end)
+
+vzxv.on_inventory_update:register(function (player, inv)
+ sort_inv(inv)
+ local state = inv_state[player:get_player_name()]
+ player:set_inventory_formspec(inventory(state, inv))
+end)
+
diff --git a/mods/vzxv_itemstacks/init.lua b/mods/vzxv_itemstacks/init.lua
index 407d8f1..fcff59c 100644
--- a/mods/vzxv_itemstacks/init.lua
+++ b/mods/vzxv_itemstacks/init.lua
@@ -20,6 +20,7 @@ vzxv.mundane_block("vzxv_itemstacks:item","Item","apioform",{
},
})
+-- TODO: handle dropping into nonair block correctly
function vzxv.drop(pos, stack)
minetest.set_node(pos, {name="vzxv_itemstacks:item"})
vzxv.set_container_stack(pos, stack)