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
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
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},
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,
})
})

View File

@ -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

View File

@ -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;;",
"<global halign=center color=#000 size=12 font=Regular>",
" ----------- Adventure Core is a discovery mod! ----------- \n",
"<global halign=left>",
"You are encourged to search far and wide in search of the\n",
"Four Elements: <style color=#F00> Fire </style><style color=#00F>Water </style>",
"<style color=#0F0>Earth </style><style color=#FF0>Air </style>\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, "<global halign=center>\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;;<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
"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;;<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] = "]"
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;;<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
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;;<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
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)

View File

@ -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

View File

@ -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", {