info_booth/init.lua

150 lines
4.9 KiB
Lua

info_booth = bgml.mod.begin()
info_booth.tables = {}
-- Add a page.
function info_booth.set_page(category, page, title, content, top)
if not info_booth.tables[category] then
info_booth.tables[category] = {
pages = {},
titles = {},
order = {},
}
end
info_booth.tables[category].pages[page] = content
info_booth.tables[category].titles[page] = title
if top then
table.insert(info_booth.tables[category].order, 1, page)
else
table.insert(info_booth.tables[category].order, page)
end
end
local players = {}
-- Display a page.
function info_booth.display(category, page, name)
local sel = 1
for i,p in ipairs(info_booth.tables[category].order) do
if p == page then
sel = i
break
end
end
local n = {}
for _,p in ipairs(info_booth.tables[category].order) do
local title = info_booth.tables[category].titles[p]
table.insert(n, engine.formspec_escape(title))
end
-- Text processing borrowed from Wuzzy's MIT-licensed doc mod.
local TEXT_LINELENGTH = 80
-- Inserts line breaks into a single paragraph and collapses all whitespace (including newlines)
-- into spaces
local linebreaker_single = function(text, linelength)
if linelength == nil then
linelength = TEXT_LINELENGTH
end
local remain = linelength
local res = {}
local line = {}
local split = function(s)
local res = {}
for w in string.gmatch(s, "%S+") do
res[#res+1] = w
end
return res
end
for _, word in ipairs(split(text)) do
if string.len(word) + 1 > remain then
table.insert(res, table.concat(line, " "))
line = { word }
remain = linelength - string.len(word)
else
table.insert(line, word)
remain = remain - (string.len(word) + 1)
end
end
table.insert(res, table.concat(line, " "))
return table.concat(res, "\n")
end
-- Inserts automatic line breaks into an entire text and preserves existing newlines
local linebreaker = function(text, linelength)
local out = ""
for s in string.gmatch(text, "([^\n]*)") do
local l = linebreaker_single(s, linelength)
out = out .. l
if(string.len(l) == 0) then
out = out .. "\n"
end
end
-- Remove last newline
if string.len(out) >= 1 then
out = string.sub(out, 1, string.len(out) - 1)
end
return out
end
-- Inserts text suitable for a textlist (including automatic word-wrap)
local text_for_textlist = function(text, linelength)
text = linebreaker(text, linelength)
text = minetest.formspec_escape(text)
text = string.gsub(text, "\n", ",")
return text
end
local content = info_booth.tables[category].pages[page]
if type(content) == "function" then
content = content(engine.get_player_by_name(name))
end
local formspec = "size[12,7]"
.. "textlist[-0.25,0;4,7;page;" .. table.concat(n, ",") .. ";" .. sel .. "]"
.. "tablecolumns[text]"
.. "tableoptions[background=#000000FF;highlight=#000000FF;border=false]"
.. "table[4,0;8,7;text;" .. text_for_textlist(content) .. "]"
players[name] = category
engine.show_formspec(name, "info_booth:display", formspec)
end
-- Register a booth node.
function info_booth.register(node, category, main, title)
engine.register_node(node, {
description = title,
tiles = {"info_booth_side.png", "info_booth_side.png", "info_booth_side.png", "info_booth_side.png", "info_booth_side.png", "info_booth_front.png"},
paramtype2 = "facedir",
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2},
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = engine.get_meta(pos)
meta:set_string("infotext", title)
end,
on_rightclick = function(pos, _, clicker)
info_booth.display(category, main, clicker:get_player_name())
end,
})
end
engine.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "info_booth:display" then
return false
end
if fields.page then
local index = engine.explode_textlist_event(fields.page).index
local category = players[player:get_player_name()]
local page = info_booth.tables[category].order[index]
if page then
info_booth.display(category, page, player:get_player_name())
end
end
return true
end)
info_booth.ready()