Skip to content

Commit

Permalink
Player Inventory: Refactoring: refactoring & make Main as Tab. Closes l…
Browse files Browse the repository at this point in the history
  • Loading branch information
alek13 committed Sep 28, 2024
1 parent 27abcfd commit 9a7ea34
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 102 deletions.
2 changes: 1 addition & 1 deletion mods/lord/Player/lord_inventory/init.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@


minetest.mod(function(mod)
require("inventory")
require("inventory").init(mod)
end)
108 changes: 73 additions & 35 deletions mods/lord/Player/lord_inventory/src/inventory.lua
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@

local main_form = require("inventory.main_form")
require("inventory.bags_form")
local PlayerForm = require('inventory.Form')
require("inventory.Form.bags_form")

--- This collection of forms passed into `inventory.Form` & replaces standard `opened_for` var of `Personal` mixin.
--- @see inventory.Form:on_register()
--- @type inventory.Form[]|table<string,inventory.Form>
local player_forms = {}

local inventory = {}

inventory = {} -- luacheck: ignore unused global variable inventory

local function register_api()
_G.inventory = {
--- @param player Player
--- @return inventory.Form
for_player = function(player)
local name = player:get_player_name()
if not player_forms[name] then
player_forms[name] = PlayerForm:new(player)
end

return player_forms[name]
end
}
end


local preview = {}
--- Previews by player name.
--- Has fields {skin="<string>", clothes="<string>", armor="<string>"}
--- @type table<string,table>
inventory.preview = {}

--- @param player Player
--- @param preview_name string
--- @param texture string
function inventory.set_preview(player, preview_name, texture)
--- @type table<string,{skin:string,clothes:string,armor:string}>
preview.for_player = {}

--- @param player Player
--- @param part_name string
--- @param texture string
function preview.set_part(player, part_name, texture)
local player_name = player:get_player_name()
if not inventory.preview[player_name] then
inventory.preview[player_name] = {}
if not preview.for_player[player_name] then
preview.for_player[player_name] = {}
end

inventory.preview[player_name][preview_name] = texture
preview.for_player[player_name][part_name] = texture
end

--- @param player_name string
---
--- @return string
function inventory.overlay_previews(player_name)
local previews = inventory.preview[player_name]
function preview.compile_overlay(player_name)
local previews = preview.for_player[player_name]
local overlaid_previews = "" .. previews.skin
if previews.clothing and previews.clothing ~= "" then
overlaid_previews = overlaid_previews .. "^" .. previews.clothing
Expand All @@ -39,10 +60,11 @@ function inventory.overlay_previews(player_name)
end

--- @param player Player
inventory.update = function(player)
function preview.update_on_form(player)
local name = player:get_player_name()
local formspec = main_form.get_spec(name, inventory.overlay_previews(name))
player:set_inventory_formspec(formspec)
inventory.for_player(player)
:set_main_preview(preview.compile_overlay(name))
:refresh()
end

--- @param player Player
Expand All @@ -60,26 +82,42 @@ local function overlay_equip_previews(player, kind)
return table.concat(previews, "^")
end

equipment.on_load(function(player, kind)
inventory.set_preview(player, kind, overlay_equip_previews(player, kind))
end)
equipment.on_load_all(function(player)
inventory.set_preview(player, "skin", multiskin:get_preview(player:get_player_name()))
inventory.update(player)
end)
local function register_equipment_changes()
equipment.on_load(function(player, kind)
preview.set_part(player, kind, overlay_equip_previews(player, kind))
end)
equipment.on_load_all(function(player)
preview.set_part(player, "skin", multiskin:get_preview(player:get_player_name()))
preview.update_on_form(player)
end)

-- When *any* equipment changed (armor or clothing),
-- we need to update player inventory form to redraw player preview in it.
equipment.on_change(function(player, kind, event, slot, item)
local player_name = player:get_player_name()
inventory.preview[player_name][kind] = overlay_equip_previews(player, kind)
-- When *any* equipment changed (armor or clothing),
-- we need to update player inventory form to redraw player preview in it.
equipment.on_change(function(player, kind, event, slot, item)
local player_name = player:get_player_name()
preview.for_player[player_name][kind] = overlay_equip_previews(player, kind)

inventory.update(player)
end)
preview.update_on_form(player)
end)
end

--- Bags Form (& other forms) 'main' button handler: -----------------------------------------------------
-- TODO: move/remove this (move to appropriate forms, if needed; remove here)
minetest.register_on_player_receive_fields(function(player, form_name, fields)
if fields.main then
local name = player:get_player_name()
minetest.show_formspec(name, "main", main_form.get_spec(name, inventory.overlay_previews(name)))
inventory.for_player(player):open()
end
end)


return {
--- @param mod minetest.Mod
init = function(mod)
register_api()

-- `player_forms` passed into callback `inventory.Form:on_register(callback)` by `Base` form.
PlayerForm:register(player_forms)

register_equipment_changes()
end
}
71 changes: 71 additions & 0 deletions mods/lord/Player/lord_inventory/src/inventory/Form.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
local MainTab = require('inventory.Form.MainTab')
--local AboutTab = require('inventory.Form.BagsTab') TODO #1698
--local AboutTab = require('inventory.Form.AboutTab') TODO #1701


--- @class inventory.Form: base_classes.Form.Mixin.WithTabs
local Form = base_classes.Form:personal():with_tabs():extended({
--- @const
--- @type string
NAME = "",

player_name = '',

--- @type table<string,number>
tab = { MAIN = 1, ABOUT = 2, },
--- @type number
current_tab = 1,
--- Replaces by player forms collection in Form.on_register callback
--- @see inventory.Form:on_register() @ below.
--- @type inventory.Form[]|table<string,inventory.Form>
opened_for = {},
})

function Form:get_spec_head()
return 'size[8,8.5]'
end

--- @param player Player
function Form:instantiate(player)
self
:add_tab(MainTab:new(self))
--:add_tab(AboutTab:new(self))
:refresh()
end

--- @param preview string
--- @return inventory.Form
function Form:set_main_preview(preview)
--- @type inventory.Form.MainTab
local main_tab = self.tabs[self.tab.MAIN]
main_tab:set_preview(preview)

return self
end

function Form:refresh()
minetest.get_player_by_name(self.player_name):set_inventory_formspec(self:get_spec())
end

--- @param fields table
function Form:handle(fields)
end

--- @param self inventory.Form
--- @param player_forms_collection inventory.Form[]|table<string,inventory.Form>
Form.on_register(function(self, player_forms_collection)
-- To open some-kind our custom inventory for player, MT provides `player:set_inventory_formspec(spec)` function.
-- And then MT by itself catch pressed `i` button & opens form with that spec.
-- So, we never/nowhere calls `Form:open()`.
-- But! Mixin `WithTabs` creates an instance exactly in `Form:open()` and put it into `Form.opened_for[player_name]`
-- Then this var used to get the instance of the player to handle.
-- But the `Form:open()` is never/nowhere calls.
-- So we need to creates this instances manually and somehow put into `Form.opened_for[player_name]`.
-- We already do it in `_G.inventory.for_player`. (see `inventory.lua`)
-- And here we just replace this `Form.opened_for` array with that `player_forms_collection`.
-- So `WithTabs` mixin works with the same collection as `_G.inventory.for_player`
Form.opened_for = player_forms_collection
end)


return Form
84 changes: 84 additions & 0 deletions mods/lord/Player/lord_inventory/src/inventory/Form/MainTab.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
local S = minetest.get_translator('lord_inventory')


--- Trash / Recycle Bin
local detached_inv_trash = minetest.create_detached_inventory('trash', {
allow_put = function(inv, listname, index, stack, player)
return stack:get_count()
end,
on_put = function(inv, listname, index, stack, player)
inv:set_stack(listname, index, '')
end,
})
detached_inv_trash:set_size('main', 1)
--- /

--- Form Spec Template
local formspec_template = ''
-- Armor slots
.. 'image[0,0;1,1;lottarmor_helmet.png]'
.. 'image[0,1;1,1;lottarmor_chestplate.png]'
.. 'image[0,2;1,1;lottarmor_leggings.png]'
.. 'image[0,3;1,1;lottarmor_boots.png]'
.. 'list[detached:{{armor_slots}};armor;0,0;1,4;]'
-- Clothes slots
.. 'image[3,0;1,1;lottarmor_helmet.png]'
.. 'image[3,1;1,1;lottarmor_shirt.png]'
.. 'image[3,2;1,1;lottarmor_trousers.png]'
.. 'image[3,3;1,1;lottarmor_shoes.png]'
.. 'list[detached:{{clothing_slots}};clothing;3,0;1,4;]'
.. 'image[4,0;1,1;lottarmor_cloak.png]'
.. 'list[detached:{{clothing_slots}};clothing;4,0;1,1;4]'
-- Preview & Shield
.. 'image[1.16,0.25;2,4;{{armor_preview}}]'
.. 'image[2,2;1,1;lottarmor_shield.png]'
.. 'list[detached:{{armor_slots}};armor;2,2;1,1;4]'
-- Crafting
.. 'image[5.05,0;3.5,1;lottarmor_crafting.png]'
.. 'list[current_player;craft;4,1;3,3;]'
.. 'list[current_player;craftpreview;7,2;1,1;]'
-- Bags & Trash
.. 'image_button[7,1;1,1;bags.png;bags;]'
.. 'image[7,3;1,1;lottarmor_trash.png]'
.. 'list[detached:trash;main;7,3;1,1;]'
-- Player inventory content
.. 'list[current_player;main;0,4.25;8,1;]'
.. 'list[current_player;main;0,5.5;8,3;8]'
-- options
.. 'listring[current_player;main]'
.. 'listring[current_player;craft]'
--- /


--- @class inventory.Form.MainTab: base_classes.Form.Element.Tab
local MainTab = base_classes.Form.Element.Tab:extended({
title = S('Main'),
--- @type inventory.Form parent form
form = nil,
--- @type string
template = formspec_template,
--- @type string
preview = ''
})

--- @param preview
--- @return self|inventory.Form.MainTab
function MainTab:set_preview(preview)
self.preview = preview

return self
end

function MainTab:get_spec()
local armor_inv_name = equipment.get_inventory_name(self.form.player_name, equipment.Kind.ARMOR)
local clothing_inv_name = equipment.get_inventory_name(self.form.player_name, equipment.Kind.CLOTHING)
local formspec = self.template
formspec = formspec:replace('{{armor_slots}}', armor_inv_name)
formspec = formspec:replace('{{clothing_slots}}', clothing_inv_name)
formspec = formspec:replace('{{armor_preview}}', self.preview)

return formspec
end


return MainTab
66 changes: 0 additions & 66 deletions mods/lord/Player/lord_inventory/src/inventory/main_form.lua

This file was deleted.

0 comments on commit 9a7ea34

Please sign in to comment.