First Searchable Store, paging, and Create functionality

master
ExeVirus 2020-12-20 23:30:29 -05:00
parent 10f4a0cd00
commit c0bdce08f9
6 changed files with 207 additions and 180 deletions

53
api.lua
View File

@ -18,21 +18,20 @@ function adv_core.load_pouch(name)
return pouch return pouch
end end
function adv_core.player_can_afford_object(name, object_name) function adv_core.player_can_afford_object(name, object_name)
local objectTable = minetest.deserialize(adv_core.mod_storage:get_string("objectTable")) or {} local objectTable = adv_core.objectTable or {}
if objectTable.object_name == nil then if objectTable[object_name] == nil then
return false return false
end end
--load player pouch --load player pouch
local player_pouch = adv_core.load_pouch(name) local player_pouch = adv_core.load_pouch(name)
local fire_ok = player_pouch.fire >= objectTable.object_name.fire local fire_ok = player_pouch.fire >= objectTable[object_name].fire
local water_ok = player_pouch.water >= objectTable.object_name.water local water_ok = player_pouch.water >= objectTable[object_name].water
local earth_ok = player_pouch.earth >= objectTable.object_name.earth local earth_ok = player_pouch.earth >= objectTable[object_name].earth
local water_ok = player_pouch.air >= objectTable.object_name.air local air_ok = player_pouch.air >= objectTable[object_name].air
if fire_ok and water_ok and earth_ok and air_ok then if fire_ok and water_ok and earth_ok and air_ok then
return true return true
else else
@ -106,42 +105,26 @@ function adv_core.take_from_player(name, fire, water, earth, air)
end end
end end
local num_pages = 0 adv_core.num_objects = 0
local num_objects = 0 adv_core.objectTable = {}
function adv_core.register_object(object_name, lfire, lwater, learth, lair) 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 object name is taken, Error out
if objectTable.object_name ~= nil then if adv_core.objectTable[object_name] ~= nil then
minetest.log("Unable to add " .. object_name .. " to adventure core object list, name already taken") minetest.log("error","Unable to add " .. object_name .. " to adventure core object list, name already taken")
return false return false
end end
--add to table --add to table
objectTable.object_name = { adv_core.objectTable[object_name] = {
fire = lfire, fire = lfire,
water = lwater, water = lwater,
earth = learth, earth = learth,
air = lair, air = lair,
} }
objectTable.num_objects = objectTable.num_objects+1 adv_core.num_objects = adv_core.num_objects+1
adv_core.mod_storage:set_string("objectTable", minetest.serialize(objectTable))
return true return true
end 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" --"fire","water","earth","air"
function adv_core.spawn_element(element_type, pos) function adv_core.spawn_element(element_type, pos)
if element_type == "fire" then if element_type == "fire" then
@ -153,4 +136,12 @@ function adv_core.spawn_element(element_type, pos)
elseif element_type == "air" then elseif element_type == "air" then
minetest.add_entity(pos, "adventure_core:air_element", nil) minetest.add_entity(pos, "adventure_core:air_element", nil)
end end
end 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

View File

@ -10,7 +10,7 @@ if adv_core.setting("enable_chat_commands",true) then
privs = {interact = true}, privs = {interact = true},
func = function(name) 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 return true
end, end,
}) })
@ -65,4 +65,5 @@ end
minetest.show_formspec(name, "adventure_core:guidebook", adv_core.guide_formspec(name)) minetest.show_formspec(name, "adventure_core:guidebook", adv_core.guide_formspec(name))
return true return true
end, end,
}) })

View File

@ -64,7 +64,7 @@ local function reward_player(player_name, element_type)
elseif element_type == "air" then elseif element_type == "air" then
player_pouch.air = player_pouch.air + 1 player_pouch.air = player_pouch.air + 1
minetest.chat_send_player(player_name, 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 end
--store it back --store it back

View File

@ -11,72 +11,59 @@ function adv_core.guide_formspec(name)
--Display Guide (scrollable formspec) --Display Guide (scrollable formspec)
local formspec = { local formspec = {
"formspec_version[3]", "formspec_version[3]",
"size[8,12]", "size[9,11.5]",
"position[0.5,0.5]", "position[0.5,0.5]",
"anchor[0.5,0.5]", "anchor[0.5,0.5]",
"no_prepend[]", "no_prepend[]",
"bgcolor[#EAD994FF;both;#00000080]", "bgcolor[#EAD994FF;both;#00000080]",
"box[0.6,0.4;6.8,1.2;#00000030]", "box[1.12,0.2;6.8,1.2;#00000030]",
"image[0.7,0.5;6.6,1;title.png]", "image[1.2,0.3;6.6,1;title.png]",
"box[2.73,2.77;0.55,0.4;#00000030]", --fire "box[2.22,2.49;0.55,0.4;#00000030]", --fire
"box[3.35,2.77;0.75,0.4;#00000030]", --water "box[2.82,2.49;0.75,0.4;#00000030]", --water
"box[4.15,2.77;0.7,0.4;#00000030]", --earth "box[3.63,2.49;0.7,0.4;#00000030]", --earth
"box[4.87,2.77;0.41,0.4;#00000030]", --air "box[4.35,2.49;0.41,0.4;#00000030]", --air
"image[2.8,5.2;0.5,0.5;fire.png]", "image[3.06,4.57;0.5,0.5;fire.png]",
"button[6.12,4.24;1.5,0.5;play;This Sound]", "hypertext[0.3,1.5;8.4,9.5;;",
"style_type[label;noclip=true]", "<global halign=center color=#000 size=12 font=Regular>",
"label[1,2;",black, " ----------- Adventure Core is a discovery mod! ----------- \n",
"----------- Adventure Core is a discovery mod! -----------\n", black, "<global halign=left>",
"]", "You are encourged to search far and wide in search of the\n",
"label[0.3,2.5;",black, "Four Elements: <style color=#F00> Fire </style><style color=#00F>Water </style>",
"You are encourged to search far and wide in search of the\n", black, "<style color=#0F0>Earth </style><style color=#FF0>Air </style>\n",
" Four Elements: ",red," Fire ", blue, "Water ", green, "Earth ", yellow, "Air\n\n",black, "These elements are found more commonly the futher you wander,\n",
"These elements are found more commonly the further you wander,\n",black, "dig, and climb from spawn, and you must be ready for:\n", --This sound
"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",
"When you hear it, an element has just spawned near you!\n",black, "Look for something like glowing and floating above the terrain.\n",
"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",
"Click/Punch to capture it, and you have collected a piece of element!\n",black, "To view how much you have collected ",
}
"To view how much element you have collected ", --optional display based on settings, very handy
} if adv_core.setting("enable_chat_commands",true) then
--optional display based on settings, very handy table.insert(formspec, "type '/pouch' in chat, or\n")
if adv_core.setting("enable_chat_commands",true) then end
table.insert(formspec, "type '/pouch' in chat, or\n") table.insert(formspec, "craft a 'guidebook'.\n")
table.insert(formspec, black) table.insert(formspec, "<global halign=center>\n There is also a Adventure shop!\n")
end if adv_core.setting("enable_adventure_shop",true) then
table.insert(formspec, "craft a 'guidebook'.\n\n") if adv_core.setting("enable_chat_commands",true) then
table.insert(formspec, black) table.insert(formspec, "You can craft this shop, or use the '/shop' command.\n")
table.insert(formspec, " There is also a Adventure shop!\n") else
table.insert(formspec, black) table.insert(formspec, "You can craft this shop and place it in the world.\n")
if adv_core.setting("enable_adventure_shop",true) then end
if adv_core.setting("enable_chat_commands",true) then else
table.insert(formspec, "You can craft this shop, or use the '/shop' command.\n") if adv_core.setting("enable_chat_commands",true) then
table.insert(formspec, black) table.insert(formspec, "You can use the '/shop' command to access it.\n")
else else
table.insert(formspec, "You can craft this shop and place it in the world.\n") table.insert(formspec, "You will have to search the map for these special places.\n")
table.insert(formspec, black) end
end end
else table.insert(formspec, "There, you can buy unique objects and items.\n\n")
if adv_core.setting("enable_chat_commands",true) then
table.insert(formspec, "You can use the '/shop' command to access it.\n") if(minetest.get_modpath("default")) ~= nil and adv_core.setting("enable_spawn_biome", true) then
table.insert(formspec, black) table.insert(formspec, "Hint: Elements will spawn according to what biome you are in.\n\n")
else end
table.insert(formspec, "You will have to search the map for these special places.\n") table.insert(formspec, "------------- Happy Adventuring! -------------")
table.insert(formspec, black) table.insert(formspec, "]")
end table.insert(formspec, "button[6.8,3.5;1.5,0.5;play;TryMe]")
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, "]")
return table.concat(formspec, "") return table.concat(formspec, "")
end end
@ -111,12 +98,16 @@ end
function adv_core.store_formspec(name, page, search, selected) function adv_core.store_formspec(name, page, search, selected)
--how to sort: --how to sort:
--https://stackoverflow.com/questions/17436947/how-to-iterate-through-table-in-lua --https://stackoverflow.com/questions/17436947/how-to-iterate-through-table-in-lua
local objectTable = minetest.deserialize(adv_core.mod_storage:get_string("objectTable")) or {} page = tonumber(page)
local num_pages = adv_core.get_num_pages() search = tostring(search)
local num_objects = adv_core.get_num_objects() selected = tostring(selected)
local objectTable = adv_core.objectTable
minetest.chat_send_all("Objects: " .. num_objects) 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 = { local formspec = {
"formspec_version[3]", "formspec_version[3]",
"size[16,12]", "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,4.6;0.5,0.5;water.png]",
"image[0.35,6.0;0.5,0.5;earth.png]", "image[0.35,6.0;0.5,0.5;earth.png]",
"image[0.35,7.4;0.5,0.5;air.png]", "image[0.35,7.4;0.5,0.5;air.png]",
"hypertext[0.3,3.9;1.5,1;;<global halign=left size=16 font=regular color=#F00> ", pouch.fire, "]",
"hypertext[0.3,5.3;1.5,1;;<global halign=left size=16 font=regular color=#00F> ", pouch.water, "]",
"hypertext[0.3,6.8;1.5,1;;<global halign=left size=16 font=regular color=#0F0> ", pouch.earth, "]",
"hypertext[0.3,8.1;1.5,1;;<global halign=left size=16 font=regular color=#FF0> ", pouch.air, "]",
--Search Bar --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.1,10;0.6,0.6;search.png;do_search;]",
"image_button[14.8,10;0.6,0.6;clear.png;reset_search;]", "image_button[14.8,10;0.6,0.6;clear.png;reset_search;]",
--Paging --Paging
"label[11,1;Page ", page , " of " , num_pages , "]", --hypertext element is set based on if search is used
"image_button[11.3,0.2;0.6,0.6;prev.png;next_page;]", "field[0,0;0,0;page;;",page,"]",
"image_button[12.3,0.2;0.6,0.6;next.png;previous_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 matched = {}
local unmatched = {} local unmatched = {}
if search ~= nil and search ~= "" then if search ~= nil and search ~= "" then
--Separate --Separate
for object in pairs(objectTable) do for object in pairs(objectTable) do
if string.find(object, search) == nil then if string.find(object, search) ~= nil then
unmatched[#unmatched+1] = object
else
matched[#matched+1] = object matched[#matched+1] = object
end end
end end
--Sort A-Z --Sort A-Z
table.sort(unmatched);
table.sort(matched); table.sort(matched);
num_pages = math.floor(#matched/64+1)
local num_matched = #matched if page > num_pages then page = num_pages end
--Add unmatched to matched --add hypertext element:
for i = 1, #unmatched do formspec[#formspec+1] = "hypertext[8,1.1;8,1;;<global halign=center size=20 font=normal color=#000> Page "
matched[#matched+1] = unmatched[i] formspec[#formspec+1] = page
end formspec[#formspec+1] = " of "
formspec[#formspec+1] = num_pages
local defs = minetest.registered_nodes formspec[#formspec+1] = "]"
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 for i = (page-1)*64+1, math.min(page*64,#matched) do
local row = math.floor(index / 6) local index = i - (page-1)*64-1 --index is for finding row-column
local column = index - row*6 local row = math.floor(index / 8)
if i < (num_matched+2) then local column = index - row*8
--Display Blue
formspec[#formspec+1] = "item_image_button[column*0.6+9,row*0.6+2;0.5,0.5;" formspec[#formspec+1] = "item_image_button["
formspec[#formspec+1] = matched[i] formspec[#formspec+1] = column*0.95+8.1
formspec[#formspec+1] = ";select;" formspec[#formspec+1] = ","
formspec[#formspec+1] = matched[i] formspec[#formspec+1] = row*0.95+2
formspec[#formspec+1] = ";]," formspec[#formspec+1] = ";0.9,0.9;"
formspec[#formspec+1] = matched[i]
else formspec[#formspec+1] = ";"
--Display Normal formspec[#formspec+1] = adv_core.escape_for_formspec(matched[i])
formspec[#formspec+1] = "item_image_button[column*0.6+9,row*0.6+2;0.5,0.5;" formspec[#formspec+1] = ";]"
formspec[#formspec+1] = matched[i] formspec[#formspec+1] = "tooltip["
formspec[#formspec+1] = ";select;" formspec[#formspec+1] = adv_core.escape_for_formspec(matched[i])
formspec[#formspec+1] = matched[i] formspec[#formspec+1] = ";"
formspec[#formspec+1] = ";]," formspec[#formspec+1] = matched[i]
end formspec[#formspec+1] = ";#000;#FFF]"
--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],")
end end
else --Display Normally else --Display Normally
minetest.chat_send_all("Normal List")
--Show number of pages
formspec[#formspec+1] = "hypertext[8,1.1;8,1;;<global halign=center size=20 font=normal color=#000> 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 for object in pairs(objectTable) do
minetest.chat_send_all(object)
unmatched[#unmatched+1] = object unmatched[#unmatched+1] = object
end end
table.sort(unmatched); table.sort(unmatched);
minetest.chat_send_all(#unmatched) for i=1,#unmatched do
minetest.chat_send_all(unmatched[i])
for i = (page-1)*72+1, math.min(page*72+1,#unmatched) do end
local index = i - (page-1)*72-1 --index is for finding row-column
minetest.chat_send_all(index) --Display current page
local row = math.floor(index / 6) for i = (page-1)*64+1, math.min(page*64,#unmatched) do
local column = index - row*6 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 --Display Normal
formspec[#formspec+1] = "item_image_button[column*0.6+9,row*0.6+2;0.5,0.5;" formspec[#formspec+1] = "item_image_button["
formspec[#formspec+1] = matched[i] formspec[#formspec+1] = column*0.95+8.1
formspec[#formspec+1] = ";select;" formspec[#formspec+1] = ","
formspec[#formspec+1] = matched[i] formspec[#formspec+1] = row*0.95+2
formspec[#formspec+1] = ";]," 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
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 --Selected Item Display
if objectTable.selected ~= nil then if selected ~= nil and selected ~= "" then
--Show item --show item
--Show Cost 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;;<global halign=left size=16 font=regular color=#000> 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 --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 end
-- Number of pages is always the same, search function will separate them into -- Number of pages is always the same, search function will separate them into
@ -239,6 +260,7 @@ end
-- formspec callbacks -- formspec callbacks
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
local name = player:get_player_name() local name = player:get_player_name()
local page = fields.page or 1
if formname ~= "adventure_core:store" and formname ~= "adventure_core:guidebook" then if formname ~= "adventure_core:store" and formname ~= "adventure_core:guidebook" then
return return
end end
@ -246,9 +268,22 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.play then if fields.play then
minetest.sound_play("adv_core_spawn_sound", {to_player = name, gain=0.8}) minetest.sound_play("adv_core_spawn_sound", {to_player = name, gain=0.8})
end end
else -- must be store elseif formname == "adventure_core:store" then
if fields.create and fields.selected then if fields.quit then
return
end 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
end) end)

View File

@ -1,9 +1,9 @@
-- __ ____ _ _ ____ __ _ ____ _ _ ____ ____ ___ __ ____ ____ -- __ ____ _ _ ____ __ _ ____ _ _ ____ ____ ___ __ ____ ____
-- / _\( \/ )( ( __| ( (_ _) )( ( _ ( __) / __) ( _ ( __) -- / _\( \/ )( ( __| ( (_ _) )( ( _ ( __) / __) ( _ ( __)
-- / \) D (\ \/ /) _)/ / )( ) \/ () /) _) ( (_( O ) /) _) -- / \) D (\ \/ /) _)/ / )( ) \/ () /) _) ( (_( O ) /) _)
-- \_/\_(____/ \__/(____)_)__)(__)\____(__\_|____) \___)__(__\_|____) -- \_/\_(____/ \__/(____)_)__)(__)\____(__\_|____) \___)__(__\_|____)
-- --
-- Core Mod by ExeVirus -- Aventure Core Mod by ExeVirus
-- Font used in title: Graceful -- Font used in title: Graceful
-- --
-- See https://github.com/ExeVirus/adventure_core/wiki for more information -- See https://github.com/ExeVirus/adventure_core/wiki for more information

View File

@ -1,8 +1,8 @@
-- REGISTER -- 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 -- ---Register the round rock
-- minetest.register_node("rocks:".. name .."_round", { -- minetest.register_node("rocks:".. name .."_round", {