diff options
author | the lemons <citrons@mondecitronne.com> | 2022-02-13 21:27:19 -0600 |
---|---|---|
committer | the lemons <citrons@mondecitronne.com> | 2022-02-13 21:27:19 -0600 |
commit | 399ea8f2310e319bcfb604714f72f1b6e57669a4 (patch) | |
tree | 76bcf2ae464f86260edcf1fdf16628782957c1f3 | |
parent | 69b1cf9dcd2bb561f2349e10e558a5e117b3ff3c (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.lua | 8 | ||||
-rw-r--r-- | mods/vzxv_inv/init.lua | 230 | ||||
-rw-r--r-- | mods/vzxv_inv/ui.lua | 86 | ||||
-rw-r--r-- | mods/vzxv_itemstacks/init.lua | 1 |
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) |