From fbb51835b382d8869b8e77c4be6844f46e51bfaa Mon Sep 17 00:00:00 2001 From: AFCMS Date: Sat, 10 Sep 2022 01:06:10 +0200 Subject: [PATCH] survival inventory tabs API + mcl_gamemode --- mods/HUD/mcl_experience/init.lua | 33 ++-- mods/HUD/mcl_experience/mod.conf | 1 + mods/HUD/mcl_inventory/API.md | 0 mods/HUD/mcl_inventory/creative.lua | 259 ++++++++++++++++++---------- mods/HUD/mcl_inventory/init.lua | 180 ++----------------- mods/HUD/mcl_inventory/mod.conf | 5 + mods/HUD/mcl_inventory/survival.lua | 219 +++++++++++++++++++++++ mods/PLAYER/mcl_gamemode/init.lua | 106 ++++++++++++ mods/PLAYER/mcl_gamemode/mod.conf | 1 + 9 files changed, 539 insertions(+), 265 deletions(-) create mode 100644 mods/HUD/mcl_inventory/API.md create mode 100644 mods/HUD/mcl_inventory/survival.lua create mode 100644 mods/PLAYER/mcl_gamemode/init.lua create mode 100644 mods/PLAYER/mcl_gamemode/mod.conf diff --git a/mods/HUD/mcl_experience/init.lua b/mods/HUD/mcl_experience/init.lua index 359e68918..47e48d36c 100644 --- a/mods/HUD/mcl_experience/init.lua +++ b/mods/HUD/mcl_experience/init.lua @@ -147,13 +147,13 @@ function mcl_experience.throw_xp(pos, total_xp) obj:set_velocity(vector.new( math.random(-2, 2) * math.random(), - math.random( 2, 5), + math.random(2, 5), math.random(-2, 2) * math.random() )) i = i + xp j = j + 1 - table.insert(obs,obj) + table.insert(obs, obj) end return obs end @@ -179,18 +179,18 @@ function mcl_experience.setup_hud(player) if not minetest.is_creative_enabled(player:get_player_name()) then hud_bars[player] = player:hud_add({ hud_elem_type = "image", - position = {x = 0.5, y = 1}, - offset = {x = (-9 * 28) - 3, y = -(48 + 24 + 16 - 5)}, - scale = {x = 0.35, y = 0.375}, - alignment = {x = 1, y = 1}, + position = { x = 0.5, y = 1 }, + offset = { x = (-9 * 28) - 3, y = -(48 + 24 + 16 - 5) }, + scale = { x = 0.35, y = 0.375 }, + alignment = { x = 1, y = 1 }, z_index = 11, }) hud_levels[player] = player:hud_add({ hud_elem_type = "text", - position = {x = 0.5, y = 1}, + position = { x = 0.5, y = 1 }, number = 0x80FF20, - offset = {x = 0, y = -(48 + 24 + 24)}, + offset = { x = 0, y = -(48 + 24 + 24) }, z_index = 12, }) end @@ -221,7 +221,7 @@ function mcl_experience.update(player) end function mcl_experience.register_on_add_xp(func, priority) - table.insert(mcl_experience.on_add_xp, {func = func, priority = priority or 0}) + table.insert(mcl_experience.on_add_xp, { func = func, priority = priority or 0 }) end -- callbacks @@ -232,9 +232,9 @@ minetest.register_on_joinplayer(function(player) end) minetest.register_on_leaveplayer(function(player) - hud_bars[player] = nil - hud_levels[player] = nil - caches[player] = nil + hud_bars[player] = nil + hud_levels[player] = nil + caches[player] = nil end) minetest.register_on_dieplayer(function(player) @@ -247,3 +247,12 @@ end) minetest.register_on_mods_loaded(function() table.sort(mcl_experience.on_add_xp, function(a, b) return a.priority < b.priority end) end) + +mcl_gamemode.register_on_gamemode_change(function(player, old_gamemode, new_gamemode) + if new_gamemode == "survival" then + mcl_experience.setup_hud(player) + mcl_experience.update(player) + elseif new_gamemode == "creative" then + mcl_experience.remove_hud(player) + end +end) diff --git a/mods/HUD/mcl_experience/mod.conf b/mods/HUD/mcl_experience/mod.conf index 211249b30..a8e992c06 100644 --- a/mods/HUD/mcl_experience/mod.conf +++ b/mods/HUD/mcl_experience/mod.conf @@ -1,3 +1,4 @@ name = mcl_experience author = oilboi description = eXPerience mod +depends = mcl_gamemode diff --git a/mods/HUD/mcl_inventory/API.md b/mods/HUD/mcl_inventory/API.md new file mode 100644 index 000000000..e69de29bb diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index 32bb226f0..c18b559b1 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -11,7 +11,8 @@ local inventory_lists = {} --local mod_player = minetest.get_modpath("mcl_player") -- Create tables -local builtin_filter_ids = {"blocks","deco","redstone","rail","food","tools","combat","mobs","brew","matr","misc","all"} +local builtin_filter_ids = { "blocks", "deco", "redstone", "rail", "food", "tools", "combat", "mobs", "brew", "matr", + "misc", "all" } for _, f in pairs(builtin_filter_ids) do inventory_lists[f] = {} end @@ -31,17 +32,26 @@ end --[[ Populate all the item tables. We only do this once. Note this code must be executed after loading all the other mods in order to work. ]] minetest.register_on_mods_loaded(function() - for name,def in pairs(minetest.registered_items) do - if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then + for name, def in pairs(minetest.registered_items) do + if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and + def.description ~= "" then local function is_redstone(def) - return def.mesecons or def.groups.mesecon or def.groups.mesecon_conductor_craftable or def.groups.mesecon_effecor_off + return def.mesecons or def.groups.mesecon or def.groups.mesecon_conductor_craftable or + def.groups.mesecon_effecor_off end + local function is_tool(def) return def.groups.tool or (def.tool_capabilities and def.tool_capabilities.damage_groups == nil) end + local function is_weapon_or_armor(def) - return def.groups.weapon or def.groups.weapon_ranged or def.groups.ammo or def.groups.combat_item or ((def.groups.armor_head or def.groups.armor_torso or def.groups.armor_legs or def.groups.armor_feet or def.groups.horse_armor) and def.groups.non_combat_armor ~= 1) + return def.groups.weapon or def.groups.weapon_ranged or def.groups.ammo or def.groups.combat_item or + ( + ( + def.groups.armor_head or def.groups.armor_torso or def.groups.armor_legs or def.groups.armor_feet or + def.groups.horse_armor) and def.groups.non_combat_armor ~= 1) end + -- Is set to true if it was added in any category besides misc local nonmisc = false if def.groups.building_block then @@ -122,11 +132,12 @@ end local function set_inv_search(filter, player) local playername = player:get_player_name() - local inv = minetest.get_inventory({type="detached", name="creative_"..playername}) + local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. playername }) local creative_list = {} local lang = minetest.get_player_information(playername).lang_code - for name,def in pairs(minetest.registered_items) do - if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then + for name, def in pairs(minetest.registered_items) do + if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and + def.description ~= "" then if filter_item(string.lower(def.name), def.description, lang, filter) then table.insert(creative_list, name) end @@ -149,7 +160,7 @@ end local function set_inv_page(page, player) local playername = player:get_player_name() - local inv = minetest.get_inventory({type="detached", name="creative_"..playername}) + local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. playername }) inv:set_size("main", 0) local creative_list = {} if inventory_lists[page] then -- Standard filter @@ -162,7 +173,7 @@ end local function init(player) local playername = player:get_player_name() - minetest.create_detached_inventory("creative_"..playername, { + minetest.create_detached_inventory("creative_" .. playername, { allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) if minetest.is_creative_enabled(playername) then return count @@ -200,7 +211,7 @@ local trash = minetest.create_detached_inventory("trash", { trash:set_size("main", 1) local noffset = {} -- numeric tab offset -local offset = {} -- string offset: +local offset = {} -- string offset: local boffset = {} -- local hoch = {} local filtername = {} @@ -238,9 +249,9 @@ next_noffset("mobs") next_noffset("matr") next_noffset("inv", true) -for k,v in pairs(noffset) do +for k, v in pairs(noffset) do offset[k] = tostring(v[1]) .. "," .. tostring(v[2]) - boffset[k] = tostring(v[1]+0.19) .. "," .. tostring(v[2]+0.25) + boffset[k] = tostring(v[1] + 0.19) .. "," .. tostring(v[2] + 0.25) end hoch["blocks"] = "" @@ -299,7 +310,7 @@ local function set_stack_size(player, n) player:get_meta():set_int("mcl_inventory:switch_stack", n) end -minetest.register_on_joinplayer(function (player) +minetest.register_on_joinplayer(function(player) if get_stack_size(player) == 0 then set_stack_size(player, 64) end @@ -310,14 +321,26 @@ function mcl_inventory.set_creative_formspec(player) if not players[playername] then return end local start_i = players[playername].start_i - local pagenum = start_i / (9*5) + 1 + local pagenum = start_i / (9 * 5) + 1 local name = players[playername].page local inv_size = players[playername].inv_size local filter = players[playername].filter - local pagemax = math.max(1, math.floor((inv_size-1) / (9*5) + 1)) + + if not inv_size then + if page == "nix" then + local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. playername }) + inv_size = inv:get_size("main") + elseif page and page ~= "inv" then + inv_size = #(inventory_lists[page]) + else + inv_size = 0 + end + end + local pagemax = math.max(1, math.floor((inv_size - 1) / (9 * 5) + 1)) + local name = "nix" local main_list - local listrings = "listring[detached:creative_"..playername..";main]".. - "listring[current_player;main]".. + local listrings = "listring[detached:creative_" .. playername .. ";main]" .. + "listring[current_player;main]" .. "listring[detached:trash;main]" local inv_bg = "crafting_inventory_creative.png" @@ -349,7 +372,7 @@ function mcl_inventory.set_creative_formspec(player) -- Survival inventory slots main_list = "list[current_player;main;0,3.75;9,3;9]" .. mcl_formspec.get_itemslot_bg(0, 3.75, 9, 3) .. - + -- Armor "list[current_player;armor;2.5,1.3;1,1;1]" .. "list[current_player;armor;2.5,2.75;1,1;2]" .. @@ -362,46 +385,46 @@ function mcl_inventory.set_creative_formspec(player) "list[current_player;offhand;1.5,2.025;1,1]" .. mcl_formspec.get_itemslot_bg(1.5, 2.025, 1, 1) .. armor_slot_imgs .. - + -- Player preview mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "") .. - + -- Crafting guide button "image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]" .. - "tooltip[__mcl_craftguide;"..F(S("Recipe book")) .. "]" .. - + "tooltip[__mcl_craftguide;" .. F(S("Recipe book")) .. "]" .. + -- Help button "image_button[9,2;1,1;doc_button_icon_lores.png;__mcl_doc;]" .. "tooltip[__mcl_doc;" .. F(S("Help")) .. "]" .. - - -- Achievements button + + -- Advancements button "image_button[9,3;1,1;mcl_achievements_button.png;__mcl_achievements;]" .. --"style_type[image_button;border=;bgimg=;bgimg_pressed=]" .. - "tooltip[__mcl_achievements;"..F(S("Advancements")) .. "]" .. - + "tooltip[__mcl_achievements;" .. F(S("Advancements")) .. "]" .. + -- Switch stack size button "image_button[9,4;1,1;default_apple.png;__switch_stack;]" .. "label[9.4,4.4;" .. F(C("#FFFFFF", stack_size ~= 1 and stack_size or "")) .. "]" .. "tooltip[__switch_stack;" .. F(S("Switch stack size")) .. "]" - + -- Skins button if minetest.global_exists("mcl_skins") then main_list = main_list .. "image_button[9,5;1,1;mcl_skins_button.png;__mcl_skins;]" .. - "tooltip[__mcl_skins;"..F(S("Select player skin")) .. "]" + "tooltip[__mcl_skins;" .. F(S("Select player skin")) .. "]" end -- For shortcuts listrings = listrings .. - "listring[detached:"..playername.."_armor;armor]".. + "listring[detached:" .. playername .. "_armor;armor]" .. "listring[current_player;main]" else -- Creative inventory slots - main_list = "list[detached:creative_"..playername..";main;0,1.75;9,5;"..tostring(start_i).."]".. - mcl_formspec.get_itemslot_bg(0,1.75,9,5).. - -- Page buttons - "label[9.0,5.5;"..F(S("@1/@2", pagenum, pagemax)).."]".. - "image_button[9.0,6.0;0.7,0.7;crafting_creative_prev.png;creative_prev;]".. + main_list = "list[detached:creative_" .. playername .. ";main;0,1.75;9,5;" .. tostring(start_i) .. "]" .. + mcl_formspec.get_itemslot_bg(0, 1.75, 9, 5) .. + -- Page buttons + "label[9.0,5.5;" .. F(S("@1/@2", pagenum, pagemax)) .. "]" .. + "image_button[9.0,6.0;0.7,0.7;crafting_creative_prev.png;creative_prev;]" .. "image_button[9.5,6.0;0.7,0.7;crafting_creative_next.png;creative_next;]" end @@ -423,65 +446,65 @@ function mcl_inventory.set_creative_formspec(player) local function tab(current_tab, this_tab) local bg_img if current_tab == this_tab then - bg_img = "crafting_creative_active"..hoch[this_tab]..".png" + bg_img = "crafting_creative_active" .. hoch[this_tab] .. ".png" else - bg_img = "crafting_creative_inactive"..hoch[this_tab]..".png" + bg_img = "crafting_creative_inactive" .. hoch[this_tab] .. ".png" end - return - "style["..this_tab..";border=false;bgimg=;bgimg_pressed=]".. - "item_image_button[" .. boffset[this_tab] ..";1,1;"..tab_icon[this_tab]..";"..this_tab..";]".. + return "style[" .. this_tab .. ";border=false;bgimg=;bgimg_pressed=]" .. + "item_image_button[" .. boffset[this_tab] .. ";1,1;" .. tab_icon[this_tab] .. ";" .. this_tab .. ";]" .. "image[" .. offset[this_tab] .. ";1.5,1.44;" .. bg_img .. "]" end + local caption = "" if name ~= "inv" and filtername[name] then - caption = "label[0,1.2;"..F(minetest.colorize("#313131", filtername[name])).."]" + caption = "label[0,1.2;" .. F(minetest.colorize("#313131", filtername[name])) .. "]" end - local formspec = "size[10,9.3]".. - "no_prepend[]".. - mcl_vars.gui_nonbg..mcl_vars.gui_bg_color.. - "background[-0.19,-0.25;10.5,9.87;"..inv_bg.."]".. - "label[-5,-5;"..name.."]".. + local formspec = "size[10,9.3]" .. + "no_prepend[]" .. + mcl_vars.gui_nonbg .. mcl_vars.gui_bg_color .. + "background[-0.19,-0.25;10.5,9.87;" .. inv_bg .. "]" .. + "label[-5,-5;" .. name .. "]" .. tab(name, "blocks") .. - "tooltip[blocks;"..F(filtername["blocks"]).."]".. + "tooltip[blocks;" .. F(filtername["blocks"]) .. "]" .. tab(name, "deco") .. - "tooltip[deco;"..F(filtername["deco"]).."]".. + "tooltip[deco;" .. F(filtername["deco"]) .. "]" .. tab(name, "redstone") .. - "tooltip[redstone;"..F(filtername["redstone"]).."]".. + "tooltip[redstone;" .. F(filtername["redstone"]) .. "]" .. tab(name, "rail") .. - "tooltip[rail;"..F(filtername["rail"]).."]".. + "tooltip[rail;" .. F(filtername["rail"]) .. "]" .. tab(name, "misc") .. - "tooltip[misc;"..F(filtername["misc"]).."]".. + "tooltip[misc;" .. F(filtername["misc"]) .. "]" .. tab(name, "nix") .. - "tooltip[nix;"..F(filtername["nix"]).."]".. - caption.. - "list[current_player;main;0,7;9,1;]".. - mcl_formspec.get_itemslot_bg(0,7,9,1).. - main_list.. + "tooltip[nix;" .. F(filtername["nix"]) .. "]" .. + caption .. + "list[current_player;main;0,7;9,1;]" .. + mcl_formspec.get_itemslot_bg(0, 7, 9, 1) .. + main_list .. tab(name, "food") .. - "tooltip[food;"..F(filtername["food"]).."]".. + "tooltip[food;" .. F(filtername["food"]) .. "]" .. tab(name, "tools") .. - "tooltip[tools;"..F(filtername["tools"]).."]".. + "tooltip[tools;" .. F(filtername["tools"]) .. "]" .. tab(name, "combat") .. - "tooltip[combat;"..F(filtername["combat"]).."]".. + "tooltip[combat;" .. F(filtername["combat"]) .. "]" .. tab(name, "mobs") .. - "tooltip[mobs;"..F(filtername["mobs"]).."]".. + "tooltip[mobs;" .. F(filtername["mobs"]) .. "]" .. tab(name, "brew") .. - "tooltip[brew;"..F(filtername["brew"]).."]".. + "tooltip[brew;" .. F(filtername["brew"]) .. "]" .. tab(name, "matr") .. - "tooltip[matr;"..F(filtername["matr"]).."]".. + "tooltip[matr;" .. F(filtername["matr"]) .. "]" .. tab(name, "inv") .. - "tooltip[inv;"..F(filtername["inv"]).."]".. - "list[detached:trash;main;9,7;1,1;]".. - mcl_formspec.get_itemslot_bg(9,7,1,1).. - "image[9,7;1,1;crafting_creative_trash.png]".. + "tooltip[inv;" .. F(filtername["inv"]) .. "]" .. + "list[detached:trash;main;9,7;1,1;]" .. + mcl_formspec.get_itemslot_bg(9, 7, 1, 1) .. + "image[9,7;1,1;crafting_creative_trash.png]" .. listrings if name == "nix" then - formspec = formspec .. "field[5.3,1.34;4,0.75;search;;"..minetest.formspec_escape(filter).."]" + formspec = formspec .. "field[5.3,1.34;4,0.75;search;;" .. minetest.formspec_escape(filter) .. "]" formspec = formspec .. "field_close_on_enter[search;false]" end - if pagenum then formspec = formspec .. "p"..tostring(pagenum) end + if pagenum then formspec = formspec .. "p" .. tostring(pagenum) end player:set_inventory_formspec(formspec) end @@ -500,50 +523,50 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.blocks then if players[name].page == "blocks" then return end - set_inv_page("blocks",player) + set_inv_page("blocks", player) page = "blocks" elseif fields.deco then if players[name].page == "deco" then return end - set_inv_page("deco",player) + set_inv_page("deco", player) page = "deco" elseif fields.redstone then if players[name].page == "redstone" then return end - set_inv_page("redstone",player) + set_inv_page("redstone", player) page = "redstone" elseif fields.rail then if players[name].page == "rail" then return end - set_inv_page("rail",player) + set_inv_page("rail", player) page = "rail" elseif fields.misc then if players[name].page == "misc" then return end - set_inv_page("misc",player) + set_inv_page("misc", player) page = "misc" elseif fields.nix then - set_inv_page("all",player) + set_inv_page("all", player) page = "nix" elseif fields.food then if players[name].page == "food" then return end - set_inv_page("food",player) + set_inv_page("food", player) page = "food" elseif fields.tools then if players[name].page == "tools" then return end - set_inv_page("tools",player) + set_inv_page("tools", player) page = "tools" elseif fields.combat then if players[name].page == "combat" then return end - set_inv_page("combat",player) + set_inv_page("combat", player) page = "combat" elseif fields.mobs then if players[name].page == "mobs" then return end - set_inv_page("mobs",player) + set_inv_page("mobs", player) page = "mobs" elseif fields.brew then if players[name].page == "brew" then return end - set_inv_page("brew",player) + set_inv_page("brew", player) page = "brew" elseif fields.matr then if players[name].page == "matr" then return end - set_inv_page("matr",player) + set_inv_page("matr", player) page = "matr" elseif fields.inv then if players[name].page == "inv" then return end @@ -552,7 +575,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) set_inv_page("all", player) page = "nix" elseif fields.search and not fields.creative_next and not fields.creative_prev then - set_inv_search(string.lower(fields.search),player) + set_inv_search(string.lower(fields.search), player) page = "nix" elseif fields.__switch_stack then local switch = 1 @@ -570,20 +593,20 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local start_i = players[name].start_i if fields.creative_prev then - start_i = start_i - 9*5 + start_i = start_i - 9 * 5 elseif fields.creative_next then - start_i = start_i + 9*5 + start_i = start_i + 9 * 5 else -- Reset scroll bar if not scrolled start_i = 0 end if start_i < 0 then - start_i = start_i + 9*5 + start_i = start_i + 9 * 5 end local inv_size if page == "nix" then - local inv = minetest.get_inventory({type="detached", name="creative_"..name}) + local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. name }) inv_size = inv:get_size("main") elseif page and page ~= "inv" then inv_size = #(inventory_lists[page]) @@ -593,7 +616,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) players[name].inv_size = inv_size if start_i >= inv_size then - start_i = start_i - 9*5 + start_i = start_i - 9 * 5 end if start_i < 0 or start_i >= inv_size then start_i = 0 @@ -606,13 +629,66 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) players[name].filter = "" end - mcl_inventory.set_creative_formspec(player) + mcl_inventory.set_creative_formspec(player, start_i, start_i / (9 * 5) + 1, inv_size, false, page, filter) end) -minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) - return placer and placer:is_player() and minetest.is_creative_enabled(placer:get_player_name()) -end) +if minetest.is_creative_enabled("") then + minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) + -- Place infinite nodes, except for shulker boxes + local group = minetest.get_item_group(itemstack:get_name(), "shulker_box") + return group == 0 or group == nil + end) + + function minetest.handle_node_drops(pos, drops, digger) + if not digger or not digger:is_player() then + for _, item in ipairs(drops) do + minetest.add_item(pos, item) + end + end + local inv = digger:get_inventory() + if inv then + for _, item in ipairs(drops) do + if not inv:contains_item("main", item, true) then + inv:add_item("main", item) + end + end + end + end + + mcl_inventory.update_inventory_formspec = function(player) + local page + + local name = player:get_player_name() + + if players[name].page then + page = players[name].page + else + page = "nix" + end + + -- Figure out current scroll bar from formspec + --local formspec = player:get_inventory_formspec() + local start_i = players[name].start_i + + local inv_size + if page == "nix" then + local inv = minetest.get_inventory({ type = "detached", name = "creative_" .. name }) + inv_size = inv:get_size("main") + elseif page and page ~= "inv" then + inv_size = #(inventory_lists[page]) + else + inv_size = 0 + end + + local filter = players[name].filter + if filter == nil then + filter = "" + end + + mcl_inventory.set_creative_formspec(player, start_i, start_i / (9 * 5) + 1, inv_size, false, page, filter) + end +end minetest.register_on_joinplayer(function(player) -- Initialize variables and inventory @@ -629,7 +705,8 @@ minetest.register_on_joinplayer(function(player) end) minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info) - if minetest.is_creative_enabled(player:get_player_name()) and get_stack_size(player) == 64 and action == "put" and inventory_info.listname == "main" then + if minetest.is_creative_enabled(player:get_player_name()) and get_stack_size(player) == 64 and action == "put" and + inventory_info.listname == "main" then local stack = inventory_info.stack stack:set_count(stack:get_stack_max()) player:get_inventory():set_stack("main", inventory_info.index, stack) diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index b9b952e97..ca019fae8 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -300,6 +300,9 @@ local F = minetest.formspec_escape mcl_inventory = {} +dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/creative.lua") +dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/survival.lua") + --local mod_player = minetest.get_modpath("mcl_player") --local mod_craftguide = minetest.get_modpath("mcl_craftguide") @@ -363,90 +366,9 @@ local function set_inventory(player, armor_change_only) return end - local inv = player:get_inventory() - inv:set_width("craft", 2) - inv:set_size("craft", 4) - local armor_slots = { "helmet", "chestplate", "leggings", "boots" } - local armor_slot_imgs = "" - - for a = 1, 4 do - if inv:get_stack("armor", a + 1):is_empty() then - armor_slot_imgs = armor_slot_imgs .. - "image[0.375," .. (0.375 + (a - 1) * 1.25) .. ";1,1;mcl_inventory_empty_armor_slot_" .. armor_slots[a] .. ".png]" - end - end - - if inv:get_stack("offhand", 1):is_empty() then - armor_slot_imgs = armor_slot_imgs .. "image[5.375,4.125;1,1;mcl_inventory_empty_armor_slot_shield.png]" - end - - local form = table.concat({ - "formspec_version[6]", - "size[11.75,10.9]", - - --Armor slots - mcl_formspec.get_itemslot_bg_v4(0.375, 0.375, 1, 4), - "list[current_player;armor;0.375,0.375;1,1;1]", - "list[current_player;armor;0.375,1.625;1,1;2]", - "list[current_player;armor;0.375,2.875;1,1;3]", - "list[current_player;armor;0.375,4.125;1,1;4]", - - --Main inventory - mcl_formspec.get_itemslot_bg_v4(0.375, 5.575, 9, 3), - "list[current_player;main;0.375,5.575;9,3;9]", - - --Hotbar - mcl_formspec.get_itemslot_bg_v4(0.375, 9.525, 9, 1), - "list[current_player;main;0.375,9.525;9,1;]", - - --Player model - "image[1.57,0.343;3.62,4.85;mcl_inventory_background9.png;2]", - mcl_player.get_player_formspec_model(player, 1.57, 0.4, 3.62, 4.85, ""), - - --Offhand - mcl_formspec.get_itemslot_bg_v4(5.375, 4.125, 1, 1), - "list[current_player;offhand;5.375,4.125;1,1]", - - armor_slot_imgs, - - --Craft grid - "label[6.61,0.5;" .. F(minetest.colorize(mcl_formspec.label_color, S("Crafting"))) .. "]", - - mcl_formspec.get_itemslot_bg_v4(6.625, 0.875, 2, 2), - "list[current_player;craft;6.625,0.875;2,2]", - - "image[9.125,1.5;1,1;crafting_formspec_arrow.png]", - - mcl_formspec.get_itemslot_bg_v4(10.375, 1.5, 1, 1), - "list[current_player;craftpreview;10.375,1.5;1,1;]", - - --Crafting guide button - "image_button[6.575,4.075;1.1,1.1;craftguide_book.png;__mcl_craftguide;]", - "tooltip[__mcl_craftguide;" .. F(S("Recipe book")) .. "]", - - --Help button - "image_button[7.825,4.075;1.1,1.1;doc_button_icon_lores.png;__mcl_doc;]", - "tooltip[__mcl_doc;" .. F(S("Help")) .. "]", - - --Skins button - "image_button[9.075,4.075;1.1,1.1;mcl_skins_button.png;__mcl_skins;]", - "tooltip[__mcl_skins;" .. F(S("Select player skin")) .. "]", - - --Achievements button - "image_button[10.325,4.075;1.1,1.1;mcl_achievements_button.png;__mcl_achievements;]", - "tooltip[__mcl_achievements;" .. F(S("Achievements")) .. "]", - - --Listring - "listring[current_player;main]", - "listring[current_player;armor]", - "listring[current_player;main]", - "listring[current_player;craft]", - "listring[current_player;main]", - }) - - player:set_inventory_formspec(form) + player:set_inventory_formspec(mcl_inventory.build_survival_formspec(player)) end -- Drop items in craft grid and reset inventory on closing @@ -508,87 +430,21 @@ minetest.register_on_joinplayer(function(player) return_fields(player, "enchanting_lapis") end) - -dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/creative.lua") - -local mt_is_creative_enabled = minetest.is_creative_enabled - -function minetest.is_creative_enabled(name) - if mt_is_creative_enabled(name) then return true end - if not name then return false end - local p = minetest.get_player_by_name(name) - if p then - return p:get_meta():get_string("gamemode") == "creative" +---@param player ObjectRef +function mcl_inventory.update_inventory(player) + local player_gamemode = mcl_gamemode.get_gamemode(player) + if player_gamemode == "creative" then + --if armor_change_only then + -- Stay on survival inventory plage if only the armor has been changed + -- mcl_inventory.set_creative_formspec(player, 0, 0, nil, nil, "inv") + --else + mcl_inventory.set_creative_formspec(player, 0, 1) + --end + elseif player_gamemode == "survival" then + player:set_inventory_formspec(mcl_inventory.build_survival_formspec(player)) end - return false end ---Insta "digging" nodes in gamemode-creative -minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing) - if not puncher or not puncher:is_player() then return end - if minetest.is_creative_enabled() then return end - local name = puncher:get_player_name() - if not minetest.is_creative_enabled(name) then return end - if pointed_thing.type ~= "node" then return end - local def = minetest.registered_nodes[node.name] - if def then - if def.on_destruct then def.on_destruct(pos) end - minetest.remove_node(pos) - return true - end +mcl_gamemode.register_on_gamemode_change(function(player, old_gamemode, new_gamemode) + set_inventory(player) end) - ---Don't subtract from inv when placing in gamemode-creative -minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing) - if placer and placer:is_player() and minetest.is_creative_enabled(placer:get_player_name()) then return true end -end) - -local function in_table(n, h) - for k, v in pairs(h) do - if v == n then return true end - end - return false -end - -local gamemodes = { - "survival", - "creative" -} - -function mcl_inventory.player_set_gamemode(p, g) - local m = p:get_meta() - m:set_string("gamemode", g) - if g == "survival" then - mcl_experience.setup_hud(p) - mcl_experience.update(p) - elseif g == "creative" then - mcl_experience.remove_hud(p) - end - set_inventory(p) -end - -minetest.register_chatcommand("gamemode", { - params = S("[] []"), - description = S("Change gamemode (survival/creative) for yourself or player"), - privs = { server = true }, - func = function(n, param) - -- Full input validation ( just for @erlehmann <3 ) - local p = minetest.get_player_by_name(n) - local args = param:split(" ") - if args[2] ~= nil then - p = minetest.get_player_by_name(args[2]) - end - if not p then - return false, S("Player not online") - end - if args[1] ~= nil and not in_table(args[1], gamemodes) then - return false, S("Gamemode " .. args[1] .. " does not exist.") - elseif args[1] ~= nil then - mcl_inventory.player_set_gamemode(p, args[1]) - end - --Result message - show effective game mode - local gm = p:get_meta():get_string("gamemode") - if gm == "" then gm = gamemodes[1] end - return true, S("Gamemode for player ") .. n .. S(": " .. gm) - end -}) diff --git a/mods/HUD/mcl_inventory/mod.conf b/mods/HUD/mcl_inventory/mod.conf index e42213d4f..80aab2ab1 100644 --- a/mods/HUD/mcl_inventory/mod.conf +++ b/mods/HUD/mcl_inventory/mod.conf @@ -1,5 +1,10 @@ name = mcl_inventory author = BlockMen description = Adds the player inventory and creative inventory. +<<<<<<< HEAD depends = mcl_init, mcl_formspec, mcl_enchanting, mcl_player optional_depends = mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting, mcl_craftguide +======= +depends = mcl_init, mcl_formspec, mcl_enchanting, mcl_gamemode +optional_depends = mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting, mcl_craftguide, mcl_player +>>>>>>> a2429154d (survival inventory tabs API + mcl_gamemode) diff --git a/mods/HUD/mcl_inventory/survival.lua b/mods/HUD/mcl_inventory/survival.lua new file mode 100644 index 000000000..99c8cf839 --- /dev/null +++ b/mods/HUD/mcl_inventory/survival.lua @@ -0,0 +1,219 @@ +---@diagnostic disable need-check-nil + +local table = table +local ipairs = ipairs + +local S = minetest.get_translator("mcl_inventory") +local F = minetest.formspec_escape + +---@type {id: string, description: string, item_icon: string, build: (fun(player: ObjectRef): string), handle: fun(player: ObjectRef, fields: table), access: (fun(player): boolean), show_inventory: boolean}[] +mcl_inventory.registered_survival_inventory_tabs = {} + +---@param def {id: string, description: string, item_icon: string, build: (fun(player: ObjectRef): string), handle: fun(player: ObjectRef, fields: table), access: (fun(player): boolean), show_inventory: boolean} +function mcl_inventory.register_survival_inventory_tab(def) + if #mcl_inventory.registered_survival_inventory_tabs == 7 then + error("Too much tabs registered!") + end + + assert(def.id) + assert(def.description) + assert(def.item_icon) + assert(def.build) + assert(def.handle) + + if not def.access then + function def.access(player) + return true + end + end + + if def.show_inventory == nil then + def.show_inventory = true + end + + table.insert(mcl_inventory.registered_survival_inventory_tabs, def) +end + +local player_current_tab = {} + +minetest.register_on_joinplayer(function(player, last_login) + player_current_tab[player] = "main" +end) + +minetest.register_on_leaveplayer(function(player, timed_out) + player_current_tab[player] = nil +end) + +---@param player ObjectRef +---@param content string +---@param inventory boolean +---@param tabname string +function build_page(player, content, inventory, tabname) + local tab_buttons = "style_type[image;noclip=true]" + + if #mcl_inventory.registered_survival_inventory_tabs ~= 1 then + for i, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do + local btn_name = "tab_" .. d.id + + tab_buttons = tab_buttons .. table.concat({ + "style[" .. btn_name .. ";border=false;bgimg=;bgimg_pressed=;noclip=true]", + "image[" .. + (0.2 + (i - 1) * 1.6) .. + ",-1.34;1.5,1.44;" .. (tabname == d.id and "crafting_creative_active.png" or "crafting_creative_inactive.png") .. + "]", + "item_image_button[" .. (0.44 + (i - 1) * 1.6) .. ",-1.1;1,1;" .. d.item_icon .. ";" .. btn_name .. ";]", + }) + end + end + + return table.concat({ + "formspec_version[6]", + "size[11.75,10.9]", + + inventory and table.concat({ + --Main inventory + mcl_formspec.get_itemslot_bg_v4(0.375, 5.575, 9, 3), + "list[current_player;main;0.375,5.575;9,3;9]", + + --Hotbar + mcl_formspec.get_itemslot_bg_v4(0.375, 9.525, 9, 1), + "list[current_player;main;0.375,9.525;9,1;]" + }) or "", + + content, + tab_buttons, + }) +end + +local main_page_static = table.concat({ + --Armor slots + mcl_formspec.get_itemslot_bg_v4(0.375, 0.375, 1, 4), + "list[current_player;armor;0.375,0.375;1,1;1]", + "list[current_player;armor;0.375,1.625;1,1;2]", + "list[current_player;armor;0.375,2.875;1,1;3]", + "list[current_player;armor;0.375,4.125;1,1;4]", + + --Player model background + "image[1.57,0.343;3.62,4.85;mcl_inventory_background9.png;2]", + + --Offhand + mcl_formspec.get_itemslot_bg_v4(5.375, 4.125, 1, 1), + "list[current_player;offhand;5.375,4.125;1,1]", + + --Craft grid + "label[6.61,0.5;" .. F(minetest.colorize(mcl_formspec.label_color, S("Crafting"))) .. "]", + + mcl_formspec.get_itemslot_bg_v4(6.625, 0.875, 2, 2), + "list[current_player;craft;6.625,0.875;2,2]", + + "image[9.125,1.5;1,1;crafting_formspec_arrow.png]", + + mcl_formspec.get_itemslot_bg_v4(10.375, 1.5, 1, 1), + "list[current_player;craftpreview;10.375,1.5;1,1;]", + + --Crafting guide button + "image_button[6.575,4.075;1.1,1.1;craftguide_book.png;__mcl_craftguide;]", + "tooltip[__mcl_craftguide;" .. F(S("Recipe book")) .. "]", + + --Help button + "image_button[7.825,4.075;1.1,1.1;doc_button_icon_lores.png;__mcl_doc;]", + "tooltip[__mcl_doc;" .. F(S("Help")) .. "]", + + --Skins button + "image_button[9.075,4.075;1.1,1.1;mcl_skins_button.png;__mcl_skins;]", + "tooltip[__mcl_skins;" .. F(S("Select player skin")) .. "]", + + --Achievements button + "image_button[10.325,4.075;1.1,1.1;mcl_achievements_button.png;__mcl_achievements;]", + "tooltip[__mcl_achievements;" .. F(S("Achievements")) .. "]", + + --Listring + "listring[current_player;main]", + "listring[current_player;armor]", + "listring[current_player;main]", + "listring[current_player;craft]", + "listring[current_player;main]", +}) + +mcl_inventory.register_survival_inventory_tab({ + id = "main", + description = "Main Inventory", + item_icon = "mcl_crafting_table:crafting_table", + show_inventory = true, + build = function(player) + local inv = player:get_inventory() + + local armor_slots = { "helmet", "chestplate", "leggings", "boots" } + local armor_slot_imgs = "" + + for a = 1, 4 do + if inv:get_stack("armor", a + 1):is_empty() then + armor_slot_imgs = armor_slot_imgs .. + "image[0.375," .. (0.375 + (a - 1) * 1.25) .. ";1,1;mcl_inventory_empty_armor_slot_" .. armor_slots[a] .. ".png]" + end + end + + if inv:get_stack("offhand", 1):is_empty() then + armor_slot_imgs = armor_slot_imgs .. "image[5.375,4.125;1,1;mcl_inventory_empty_armor_slot_shield.png]" + end + return main_page_static .. armor_slot_imgs .. mcl_player.get_player_formspec_model(player, 1.57, 0.4, 3.62, 4.85, "") + end, + handle = function() end, +}) + +-- +mcl_inventory.register_survival_inventory_tab({ + id = "test", + description = "Test", + item_icon = "mcl_core:stone", + show_inventory = true, + build = function(player) + return "label[1,1;Hello hello]button[2,2;2,2;Hello;hey]" + end, + handle = function(player, fields) + print(dump(fields)) + end, +}) + +---@param player ObjectRef +function mcl_inventory.build_survival_formspec(player) + local inv = player:get_inventory() + + inv:set_width("craft", 2) + inv:set_size("craft", 4) + + local tab = player_current_tab[player] + + local tab_def = nil + + for _, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do + if tab == d.id then + tab_def = d + break + end + end + + local form = build_page(player, tab_def.build(player), tab_def.show_inventory, tab) + + return form +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname == "" and #mcl_inventory.registered_survival_inventory_tabs ~= 1 and + mcl_gamemode.get_gamemode(player) == "survival" then + for _, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do + if fields["tab_" .. d.id] and d.access(player) then + player_current_tab[player] = d.id + mcl_inventory.update_inventory(player) + return + end + end + + for _, d in ipairs(mcl_inventory.registered_survival_inventory_tabs) do + if player_current_tab[player] == d.id and d.access(player) then + d.handle(player, fields) + return + end + end + end +end) diff --git a/mods/PLAYER/mcl_gamemode/init.lua b/mods/PLAYER/mcl_gamemode/init.lua new file mode 100644 index 000000000..7ac814073 --- /dev/null +++ b/mods/PLAYER/mcl_gamemode/init.lua @@ -0,0 +1,106 @@ +---@diagnostic disable lowercase-global + +local S = minetest.get_translator("mcl_gamemode") + +mcl_gamemode = {} + +mcl_gamemode.gamemodes = { + "survival", + "creative", +} + +---@param n any +---@param h table +---@return boolean +local function in_table(n, h) + for k, v in pairs(h) do + if v == n then return true end + end + return false +end + +---@type fun(player: ObjectRef, old_gamemode: '"survival"'|'"creative"', new_gamemode: '"survival"'|'"creative"')[] +mcl_gamemode.registered_on_gamemode_change = {} + +---@param func fun(player: ObjectRef, old_gamemode: '"survival"'|'"creative"', new_gamemode: '"survival"'|'"creative"') +function mcl_gamemode.register_on_gamemode_change(func) + table.insert(mcl_gamemode.registered_on_gamemode_change, func) +end + +---@param player ObjectRef +---@param gamemode '"survival"'|'"creative"' +function mcl_gamemode.set_gamemode(player, gamemode) + local meta = player:get_meta() + local old_gamemode = meta:get_string("gamemode") + meta:set_string("gamemode", gamemode) + for _, f in ipairs(mcl_gamemode.registered_on_gamemode_change) do + f(player, old_gamemode, gamemode) + end +end + +local mt_is_creative_enabled = minetest.is_creative_enabled + +---@param player ObjectRef +---@return '"survival"'|'"creative"' +function mcl_gamemode.get_gamemode(player) + if mt_is_creative_enabled(player:get_player_name()) then + return "creative" + end + return player:get_meta():get_string("gamemode") +end + +function minetest.is_creative_enabled(name) + if mt_is_creative_enabled(name) then return true end + if not name then return false end + local p = minetest.get_player_by_name(name) + if p then + return p:get_meta():get_string("gamemode") == "creative" + end + return false +end + +-- Insta "digging" nodes in gamemode-creative +minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing) + if not puncher or not puncher:is_player() then return end + if minetest.is_creative_enabled() then return end + local name = puncher:get_player_name() + if not minetest.is_creative_enabled(name) then return end + if pointed_thing.type ~= "node" then return end + local def = minetest.registered_nodes[node.name] + if def then + if def.on_destruct then def.on_destruct(pos) end + minetest.remove_node(pos) + return true + end +end) + +-- Don't subtract from inv when placing in gamemode-creative +minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing) + if placer and placer:is_player() and minetest.is_creative_enabled(placer:get_player_name()) then return true end +end) + +minetest.register_chatcommand("gamemode", { + params = S("[] []"), + description = S("Change gamemode (survival/creative) for yourself or player"), + privs = { server = true }, + func = function(n, param) + -- Full input validation ( just for @erlehmann <3 ) + local p = minetest.get_player_by_name(n) + local args = param:split(" ") + if args[2] ~= nil then + p = minetest.get_player_by_name(args[2]) + end + if not p then + return false, S("Player not online") + end + if args[1] ~= nil and not in_table(args[1], gamemodes) then + return false, S("Gamemode " .. args[1] .. " does not exist.") + elseif args[1] ~= nil then + mcl_inventory.player_set_gamemode(p, args[1]) + end + --Result message - show effective game mode + local gm = p:get_meta():get_string("gamemode") + if gm == "" then gm = gamemodes[1] end + return true, S("Gamemode for player ") .. n .. S(": " .. gm) + end +}) diff --git a/mods/PLAYER/mcl_gamemode/mod.conf b/mods/PLAYER/mcl_gamemode/mod.conf new file mode 100644 index 000000000..03eade707 --- /dev/null +++ b/mods/PLAYER/mcl_gamemode/mod.conf @@ -0,0 +1 @@ +name = mcl_gamemode \ No newline at end of file