From c0bdce08f964f90081029babf05842c08ce8af29 Mon Sep 17 00:00:00 2001 From: ExeVirus Date: Sun, 20 Dec 2020 23:30:29 -0500 Subject: [PATCH] First Searchable Store, paging, and Create functionality --- api.lua | 53 ++++---- chat_commands.lua | 5 +- elements.lua | 2 +- formspecs.lua | 315 +++++++++++++++++++++++++--------------------- init.lua | 6 +- register.lua | 6 +- 6 files changed, 207 insertions(+), 180 deletions(-) diff --git a/api.lua b/api.lua index 7cb09cc..311c85d 100644 --- a/api.lua +++ b/api.lua @@ -18,21 +18,20 @@ function adv_core.load_pouch(name) return pouch end - function adv_core.player_can_afford_object(name, object_name) - local objectTable = minetest.deserialize(adv_core.mod_storage:get_string("objectTable")) or {} - if objectTable.object_name == nil then + local objectTable = adv_core.objectTable or {} + if objectTable[object_name] == nil then return false end --load player pouch local player_pouch = adv_core.load_pouch(name) - local fire_ok = player_pouch.fire >= objectTable.object_name.fire - local water_ok = player_pouch.water >= objectTable.object_name.water - local earth_ok = player_pouch.earth >= objectTable.object_name.earth - local water_ok = player_pouch.air >= objectTable.object_name.air - + local fire_ok = player_pouch.fire >= objectTable[object_name].fire + local water_ok = player_pouch.water >= objectTable[object_name].water + local earth_ok = player_pouch.earth >= objectTable[object_name].earth + local air_ok = player_pouch.air >= objectTable[object_name].air + if fire_ok and water_ok and earth_ok and air_ok then return true else @@ -106,42 +105,26 @@ function adv_core.take_from_player(name, fire, water, earth, air) end end -local num_pages = 0 -local num_objects = 0 - +adv_core.num_objects = 0 +adv_core.objectTable = {} function adv_core.register_object(object_name, lfire, lwater, learth, lair) - local objectTable = minetest.deserialize(adv_core.mod_storage:get_string("objectTable")) or {} - if objectTable.num_objects == nil then objectTable.num_objects = 0 end --if object name is taken, Error out - if objectTable.object_name ~= nil then - minetest.log("Unable to add " .. object_name .. " to adventure core object list, name already taken") + if adv_core.objectTable[object_name] ~= nil then + minetest.log("error","Unable to add " .. object_name .. " to adventure core object list, name already taken") return false end --add to table - objectTable.object_name = { + adv_core.objectTable[object_name] = { fire = lfire, water = lwater, earth = learth, air = lair, } - objectTable.num_objects = objectTable.num_objects+1 - - adv_core.mod_storage:set_string("objectTable", minetest.serialize(objectTable)) + adv_core.num_objects = adv_core.num_objects+1 return true end -function adv_core.get_num_pages() - --get number of registered objects - num_pages = math.floor(num_objects / 6 / 12) + 1 - - return num_pages -end - -function adv_core.get_num_objects() - return num_objects -end - --"fire","water","earth","air" function adv_core.spawn_element(element_type, pos) if element_type == "fire" then @@ -153,4 +136,12 @@ function adv_core.spawn_element(element_type, pos) elseif element_type == "air" then minetest.add_entity(pos, "adventure_core:air_element", nil) end -end \ No newline at end of file +end + +--Credit to Unified Inventory for how to fix this: +function adv_core.escape_for_formspec(item_name) + return string.gsub(item_name, "([^A-Za-z0-9])", function (c) return string.format("_%d_", string.byte(c)) end) +end +function adv_core.remove_formspec_escapes(item_name) + return string.gsub(item_name, "_([0-9]+)_", function (v) return string.char(v) end) +end diff --git a/chat_commands.lua b/chat_commands.lua index 40d1188..a5ef04e 100644 --- a/chat_commands.lua +++ b/chat_commands.lua @@ -10,7 +10,7 @@ if adv_core.setting("enable_chat_commands",true) then privs = {interact = true}, func = function(name) - minetest.show_formspec(name, "adventure_core:store", adv_core.store_formspec(name, 1, "", "")) + minetest.show_formspec(name, "adventure_core:store", adv_core.store_formspec(name, 1, "wood", "default:apple")) return true end, }) @@ -65,4 +65,5 @@ end minetest.show_formspec(name, "adventure_core:guidebook", adv_core.guide_formspec(name)) return true end, - }) \ No newline at end of file + }) + \ No newline at end of file diff --git a/elements.lua b/elements.lua index 441c163..aae9dca 100644 --- a/elements.lua +++ b/elements.lua @@ -64,7 +64,7 @@ local function reward_player(player_name, element_type) elseif element_type == "air" then player_pouch.air = player_pouch.air + 1 minetest.chat_send_player(player_name, - minetest.get_color_escape_sequence("yellow") .. " Air: " .. player_pouch.air) + minetest.get_color_escape_sequence("yellow") .. " air: " .. player_pouch.air) end --store it back diff --git a/formspecs.lua b/formspecs.lua index 320d2d1..be7b3bd 100644 --- a/formspecs.lua +++ b/formspecs.lua @@ -11,72 +11,59 @@ function adv_core.guide_formspec(name) --Display Guide (scrollable formspec) local formspec = { "formspec_version[3]", - "size[8,12]", + "size[9,11.5]", "position[0.5,0.5]", "anchor[0.5,0.5]", "no_prepend[]", "bgcolor[#EAD994FF;both;#00000080]", - "box[0.6,0.4;6.8,1.2;#00000030]", - "image[0.7,0.5;6.6,1;title.png]", - "box[2.73,2.77;0.55,0.4;#00000030]", --fire - "box[3.35,2.77;0.75,0.4;#00000030]", --water - "box[4.15,2.77;0.7,0.4;#00000030]", --earth - "box[4.87,2.77;0.41,0.4;#00000030]", --air - "image[2.8,5.2;0.5,0.5;fire.png]", - "button[6.12,4.24;1.5,0.5;play;This Sound]", - "style_type[label;noclip=true]", - "label[1,2;",black, - "----------- Adventure Core is a discovery mod! -----------\n", black, - "]", - "label[0.3,2.5;",black, - "You are encourged to search far and wide in search of the\n", black, - " Four Elements: ",red," Fire ", blue, "Water ", green, "Earth ", yellow, "Air\n\n",black, - "These elements are found more commonly the further you wander,\n",black, - "dig, and climb from spawn, and you must be ready for:\n",black, --This sound - "When you hear it, an element has just spawned near you!\n",black, - "Look for something like glowing and floating above the terrain.\n",black, - "Click/Punch to capture it, and you have collected a piece of element!\n",black, - - "To view how much element you have collected ", - } - --optional display based on settings, very handy - if adv_core.setting("enable_chat_commands",true) then - table.insert(formspec, "type '/pouch' in chat, or\n") - table.insert(formspec, black) - end - table.insert(formspec, "craft a 'guidebook'.\n\n") - table.insert(formspec, black) - table.insert(formspec, " There is also a Adventure shop!\n") - table.insert(formspec, black) - if adv_core.setting("enable_adventure_shop",true) then - if adv_core.setting("enable_chat_commands",true) then - table.insert(formspec, "You can craft this shop, or use the '/shop' command.\n") - table.insert(formspec, black) - else - table.insert(formspec, "You can craft this shop and place it in the world.\n") - table.insert(formspec, black) - end - else - if adv_core.setting("enable_chat_commands",true) then - table.insert(formspec, "You can use the '/shop' command to access it.\n") - table.insert(formspec, black) - else - table.insert(formspec, "You will have to search the map for these special places.\n") - table.insert(formspec, black) - end - end - table.insert(formspec, " There, you can buy unique objects and items.\n\n") - table.insert(formspec, black) - - if(minetest.get_modpath("default")) ~= nil and adv_core.setting("enable_spawn_biome", true) then - table.insert(formspec, "Hint: Elements will spawn according to what biome you are in.\n\n") - table.insert(formspec, black) - end - --table.insert(formspec, "" - table.insert(formspec, " ------------- Happy Adventuring! -------------") - table.insert(formspec, "]") - - + "box[1.12,0.2;6.8,1.2;#00000030]", + "image[1.2,0.3;6.6,1;title.png]", + "box[2.22,2.49;0.55,0.4;#00000030]", --fire + "box[2.82,2.49;0.75,0.4;#00000030]", --water + "box[3.63,2.49;0.7,0.4;#00000030]", --earth + "box[4.35,2.49;0.41,0.4;#00000030]", --air + "image[3.06,4.57;0.5,0.5;fire.png]", + "hypertext[0.3,1.5;8.4,9.5;;", + "", + " ----------- Adventure Core is a discovery mod! ----------- \n", + "", + "You are encourged to search far and wide in search of the\n", + "Four Elements: ", + "\n", + "These elements are found more commonly the futher you wander,\n", + "dig, and climb from spawn, and you must be ready for:\n", --This sound + "When you hear it, an element has just spawned near you!\n", + "Look for something like glowing and floating above the terrain.\n", + "Click/Punch to capture it, and you have collected a piece of element!\n", + "To view how much you have collected ", + } + --optional display based on settings, very handy + if adv_core.setting("enable_chat_commands",true) then + table.insert(formspec, "type '/pouch' in chat, or\n") + end + table.insert(formspec, "craft a 'guidebook'.\n") + table.insert(formspec, "\n There is also a Adventure shop!\n") + if adv_core.setting("enable_adventure_shop",true) then + if adv_core.setting("enable_chat_commands",true) then + table.insert(formspec, "You can craft this shop, or use the '/shop' command.\n") + else + table.insert(formspec, "You can craft this shop and place it in the world.\n") + end + else + if adv_core.setting("enable_chat_commands",true) then + table.insert(formspec, "You can use the '/shop' command to access it.\n") + else + table.insert(formspec, "You will have to search the map for these special places.\n") + end + end + table.insert(formspec, "There, you can buy unique objects and items.\n\n") + + if(minetest.get_modpath("default")) ~= nil and adv_core.setting("enable_spawn_biome", true) then + table.insert(formspec, "Hint: Elements will spawn according to what biome you are in.\n\n") + end + table.insert(formspec, "------------- Happy Adventuring! -------------") + table.insert(formspec, "]") + table.insert(formspec, "button[6.8,3.5;1.5,0.5;play;TryMe]") return table.concat(formspec, "") end @@ -111,12 +98,16 @@ end function adv_core.store_formspec(name, page, search, selected) --how to sort: --https://stackoverflow.com/questions/17436947/how-to-iterate-through-table-in-lua - local objectTable = minetest.deserialize(adv_core.mod_storage:get_string("objectTable")) or {} - local num_pages = adv_core.get_num_pages() - local num_objects = adv_core.get_num_objects() - - minetest.chat_send_all("Objects: " .. num_objects) - + page = tonumber(page) + search = tostring(search) + selected = tostring(selected) + local objectTable = adv_core.objectTable + local num_objects = adv_core.num_objects + local num_pages = math.floor(num_objects / 64)+1 + local pouch = adv_core.load_pouch(name) + minetest.chat_send_all(minetest.serialize(pouch)) + if page > num_pages then page = num_pages end + local formspec = { "formspec_version[3]", "size[16,12]", @@ -133,100 +124,130 @@ function adv_core.store_formspec(name, page, search, selected) "image[0.35,4.6;0.5,0.5;water.png]", "image[0.35,6.0;0.5,0.5;earth.png]", "image[0.35,7.4;0.5,0.5;air.png]", + "hypertext[0.3,3.9;1.5,1;; ", pouch.fire, "]", + "hypertext[0.3,5.3;1.5,1;; ", pouch.water, "]", + "hypertext[0.3,6.8;1.5,1;; ", pouch.earth, "]", + "hypertext[0.3,8.1;1.5,1;; ", pouch.air, "]", --Search Bar - "field[9.0,10;6,0.6;search;;]", + "field[9.0,10;5,0.6;search;;",search,"]", + "field_close_on_enter[search;false]", "image_button[14.1,10;0.6,0.6;search.png;do_search;]", "image_button[14.8,10;0.6,0.6;clear.png;reset_search;]", --Paging - "label[11,1;Page ", page , " of " , num_pages , "]", - "image_button[11.3,0.2;0.6,0.6;prev.png;next_page;]", - "image_button[12.3,0.2;0.6,0.6;next.png;previous_page;]", + --hypertext element is set based on if search is used + "field[0,0;0,0;page;;",page,"]", + "image_button[11.3,0.5;0.6,0.6;prev.png;previous_page;]", + "image_button[12.3,0.5;0.6,0.6;next.png;next_page;]", } - - if num_objects > 0 then + + --Rows and Columns of Items + if num_objects > 0 then local matched = {} local unmatched = {} if search ~= nil and search ~= "" then --Separate for object in pairs(objectTable) do - if string.find(object, search) == nil then - unmatched[#unmatched+1] = object - else + if string.find(object, search) ~= nil then matched[#matched+1] = object end end --Sort A-Z - table.sort(unmatched); table.sort(matched); - - local num_matched = #matched - --Add unmatched to matched - for i = 1, #unmatched do - matched[#matched+1] = unmatched[i] - end - - local defs = minetest.registered_nodes - for i = (page-1)*72+1, math.min(page*72+1,#matched) do - local index = i - (page-1)*72-1 --index is for finding row-column - local row = math.floor(index / 6) - local column = index - row*6 - if i < (num_matched+2) then - --Display Blue - formspec[#formspec+1] = "item_image_button[column*0.6+9,row*0.6+2;0.5,0.5;" - formspec[#formspec+1] = matched[i] - formspec[#formspec+1] = ";select;" - formspec[#formspec+1] = matched[i] - formspec[#formspec+1] = ";]," - - else - --Display Normal - formspec[#formspec+1] = "item_image_button[column*0.6+9,row*0.6+2;0.5,0.5;" - formspec[#formspec+1] = matched[i] - formspec[#formspec+1] = ";select;" - formspec[#formspec+1] = matched[i] - formspec[#formspec+1] = ";]," - end - --table.concat(formspec, "image_button[row*0.6,column*0.6;0.5,0.5;" .. node_def[object].inv_img .. ";select;".. object .."],") - --table.concat(formspec, "tooltip[blah;blah],") + num_pages = math.floor(#matched/64+1) + if page > num_pages then page = num_pages end + --add hypertext element: + formspec[#formspec+1] = "hypertext[8,1.1;8,1;; Page " + formspec[#formspec+1] = page + formspec[#formspec+1] = " of " + formspec[#formspec+1] = num_pages + formspec[#formspec+1] = "]" + + for i = (page-1)*64+1, math.min(page*64,#matched) do + local index = i - (page-1)*64-1 --index is for finding row-column + local row = math.floor(index / 8) + local column = index - row*8 + + formspec[#formspec+1] = "item_image_button[" + formspec[#formspec+1] = column*0.95+8.1 + formspec[#formspec+1] = "," + formspec[#formspec+1] = row*0.95+2 + formspec[#formspec+1] = ";0.9,0.9;" + formspec[#formspec+1] = matched[i] + formspec[#formspec+1] = ";" + formspec[#formspec+1] = adv_core.escape_for_formspec(matched[i]) + formspec[#formspec+1] = ";]" + formspec[#formspec+1] = "tooltip[" + formspec[#formspec+1] = adv_core.escape_for_formspec(matched[i]) + formspec[#formspec+1] = ";" + formspec[#formspec+1] = matched[i] + formspec[#formspec+1] = ";#000;#FFF]" end else --Display Normally - minetest.chat_send_all("Normal List") + + --Show number of pages + formspec[#formspec+1] = "hypertext[8,1.1;8,1;; Page " + formspec[#formspec+1] = page + formspec[#formspec+1] = " of " + formspec[#formspec+1] = num_pages + formspec[#formspec+1] = "]" + + --sort A-Z for object in pairs(objectTable) do - minetest.chat_send_all(object) unmatched[#unmatched+1] = object end table.sort(unmatched); - minetest.chat_send_all(#unmatched) - - for i = (page-1)*72+1, math.min(page*72+1,#unmatched) do - local index = i - (page-1)*72-1 --index is for finding row-column - minetest.chat_send_all(index) - local row = math.floor(index / 6) - local column = index - row*6 + for i=1,#unmatched do + minetest.chat_send_all(unmatched[i]) + end + + --Display current page + for i = (page-1)*64+1, math.min(page*64,#unmatched) do + local index = i - (page-1)*64-1 --index is for finding row-column + --minetest.chat_send_all(index) + local row = math.floor(index / 8) + local column = index - row*8 --Display Normal - formspec[#formspec+1] = "item_image_button[column*0.6+9,row*0.6+2;0.5,0.5;" - formspec[#formspec+1] = matched[i] - formspec[#formspec+1] = ";select;" - formspec[#formspec+1] = matched[i] - formspec[#formspec+1] = ";]," + formspec[#formspec+1] = "item_image_button[" + formspec[#formspec+1] = column*0.95+8.1 + formspec[#formspec+1] = "," + formspec[#formspec+1] = row*0.95+2 + formspec[#formspec+1] = ";0.9,0.9;" + formspec[#formspec+1] = unmatched[i] + formspec[#formspec+1] = ";" + formspec[#formspec+1] = adv_core.escape_for_formspec(unmatched[i]) + formspec[#formspec+1] = ";]" + formspec[#formspec+1] = "tooltip[" + formspec[#formspec+1] = adv_core.escape_for_formspec(unmatched[i]) + formspec[#formspec+1] = ";" + formspec[#formspec+1] = unmatched[i] + formspec[#formspec+1] = ";#000;#FFF]" end - end + end end - - - - - --Columns and Rows of objects - --Get object list - --Perform Search, if applicable. - --Recombine the matched and unmatched object groups after sorting a-z. - --Display current page of objects as from starting page value to either end of array or end of page value - + --Selected Item Display - if objectTable.selected ~= nil then - --Show item - --Show Cost + if selected ~= nil and selected ~= "" then + --show item + formspec[#formspec+1] = "item_image_button[2,2;4,4;" + formspec[#formspec+1] = selected + formspec[#formspec+1] = ";;]" + --Show Costs + formspec[#formspec+1] = "hypertext[1.7,6;7,1;; Fire: " + formspec[#formspec+1] = objectTable[selected].fire + formspec[#formspec+1] = " Water: " + formspec[#formspec+1] = objectTable[selected].water + formspec[#formspec+1] = " Earth: " + formspec[#formspec+1] = objectTable[selected].earth + formspec[#formspec+1] = " Air: " + formspec[#formspec+1] = objectTable[selected].air + formspec[#formspec+1] = "]" --Show "Create" button + if adv_core.player_can_afford_object(name, selected) then + formspec[#formspec+1] = "button[3,7;2,1.5;create;Create]" + else + formspec[#formspec+1] = "button[2,7;4,1.5;;Can't Afford]" + formspec[#formspec+1] = "box[2,7;4,1.5;#8008]" + end end -- Number of pages is always the same, search function will separate them into @@ -239,6 +260,7 @@ end -- formspec callbacks minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() + local page = fields.page or 1 if formname ~= "adventure_core:store" and formname ~= "adventure_core:guidebook" then return end @@ -246,9 +268,22 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.play then minetest.sound_play("adv_core_spawn_sound", {to_player = name, gain=0.8}) end - else -- must be store - if fields.create and fields.selected then - - end + elseif formname == "adventure_core:store" then + if fields.quit then + return + end + local search = fields.search or "" + if fields.reset_search then + search = "" + elseif fields.next_page then + page = page+1 + elseif fields.previous_page then + page = page-1 + page = math.max(1, page) + end + if fields.key_enter_field == "search" then + minetest.show_formspec(name, "adventure_core:store", adv_core.store_formspec(name, page, search, "default:apple")) + end + minetest.show_formspec(name, "adventure_core:store", adv_core.store_formspec(name, page, search, "default:apple")) end end) \ No newline at end of file diff --git a/init.lua b/init.lua index 631f1d1..c34d70f 100644 --- a/init.lua +++ b/init.lua @@ -1,9 +1,9 @@ --- __ ____ _ _ ____ __ _ ____ _ _ ____ ____ ___ __ ____ ____ --- / _\( \/ )( ( __| ( (_ _) )( ( _ ( __) / __) ( _ ( __) +-- __ ____ _ _ ____ __ _ ____ _ _ ____ ____ ___ __ ____ ____ +-- / _\( \/ )( ( __| ( (_ _) )( ( _ ( __) / __) ( _ ( __) -- / \) D (\ \/ /) _)/ / )( ) \/ () /) _) ( (_( O ) /) _) -- \_/\_(____/ \__/(____)_)__)(__)\____(__\_|____) \___)__(__\_|____) -- --- Core Mod by ExeVirus +-- Aventure Core Mod by ExeVirus -- Font used in title: Graceful -- -- See https://github.com/ExeVirus/adventure_core/wiki for more information diff --git a/register.lua b/register.lua index 8ebb801..0711d38 100644 --- a/register.lua +++ b/register.lua @@ -1,8 +1,8 @@ -- REGISTER +for node in pairs(minetest.registered_nodes) do + adv_core.register_object(node, 0, 0, 1, 1) +end -adv_core.register_object("default:dirt", 0, 0, 1, 0) -adv_core.register_object("default:dirt_with_grass", 0, 1, 1, 0) -adv_core.register_object("default:water", 0, 1, 0, 0) -- ---Register the round rock -- minetest.register_node("rocks:".. name .."_round", {