default: Improves reading and writing to books. (#2656)

* Allow anyone to write to a book without any text and title.
* Allows saving books without any text or title.
* Adds a "Read" and "Write" tab to written owned books.

Fixes #1743
This commit is contained in:
orbea 2021-09-04 21:37:27 +00:00 committed by GitHub
parent 92701885d0
commit 21e5f68292
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -3,6 +3,46 @@
-- support for MT game translation. -- support for MT game translation.
local S = default.get_translator local S = default.get_translator
local esc = minetest.formspec_escape
local formspec_size = "size[8,8]"
local function formspec_core(tab)
if tab == nil then tab = 1 else tab = tostring(tab) end
return "tabheader[0,0;book_header;" ..
esc(S("Write")) .. "," ..
esc(S("Read")) .. ";" ..
tab .. ";false;false]"
end
local function formspec_write(title, text)
return "field[0.5,1;7.5,0;title;" .. esc(S("Title:")) .. ";" ..
esc(title) .. "]" ..
"textarea[0.5,1.5;7.5,7;text;" .. esc(S("Contents:")) .. ";" ..
esc(text) .. "]" ..
"button_exit[2.5,7.5;3,1;save;" .. esc(S("Save")) .. "]"
end
local function formspec_read(owner, title, string, text, page, page_max)
return "label[0.5,0.5;" .. esc(S("by @1", owner)) .. "]" ..
"tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[0.4,0;7,0.5;title;#FFFF00," .. esc(title) .. "]" ..
"textarea[0.5,1.5;7.5,7;;" ..
esc(string ~= "" and string or text) .. ";]" ..
"button[2.4,7.6;0.8,0.8;book_prev;<]" ..
"label[3.2,7.7;" .. esc(S("Page @1 of @2", page, page_max)) .. "]" ..
"button[4.9,7.6;0.8,0.8;book_next;>]"
end
local function formspec_string(lpp, page, lines, string)
for i = ((lpp * page) - lpp) + 1, lpp * page do
if not lines[i] then break end
string = string .. lines[i] .. "\n"
end
return string
end
local tab_number
local lpp = 14 -- Lines per book's page local lpp = 14 -- Lines per book's page
local function book_on_use(itemstack, user) local function book_on_use(itemstack, user)
local player_name = user:get_player_name() local player_name = user:get_player_name()
@ -19,8 +59,8 @@ local function book_on_use(itemstack, user)
local data = meta:to_table().fields local data = meta:to_table().fields
if data.owner then if data.owner then
title = data.title title = data.title or ""
text = data.text text = data.text or ""
owner = data.owner owner = data.owner
for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do
@ -30,37 +70,26 @@ local function book_on_use(itemstack, user)
if data.page then if data.page then
page = data.page page = data.page
page_max = data.page_max page_max = data.page_max
string = formspec_string(lpp, page, lines, string)
for i = ((lpp * page) - lpp) + 1, lpp * page do
if not lines[i] then break end
string = string .. lines[i] .. "\n"
end
end end
end end
local formspec local formspec
local esc = minetest.formspec_escape if title == "" and text == "" then
if owner == player_name then formspec = formspec_write(title, text)
formspec = "size[8,8]" .. elseif owner == player_name then
"field[0.5,1;7.5,0;title;" .. esc(S("Title:")) .. ";" .. local tab = tab_number or 1
esc(title) .. "]" .. if tab == 2 then
"textarea[0.5,1.5;7.5,7;text;" .. esc(S("Contents:")) .. ";" .. formspec = formspec_core(tab) ..
esc(text) .. "]" .. formspec_read(owner, title, string, text, page, page_max)
"button_exit[2.5,7.5;3,1;save;" .. esc(S("Save")) .. "]"
else else
formspec = "size[8,8]" .. formspec = formspec_core(tab) .. formspec_write(title, text)
"label[0.5,0.5;" .. esc(S("by @1", owner)) .. "]" .. end
"tablecolumns[color;text]" .. else
"tableoptions[background=#00000000;highlight=#00000000;border=false]" .. formspec = formspec_read(owner, title, string, text, page, page_max)
"table[0.4,0;7,0.5;title;#FFFF00," .. esc(title) .. "]" ..
"textarea[0.5,1.5;7.5,7;;" ..
minetest.formspec_escape(string ~= "" and string or text) .. ";]" ..
"button[2.4,7.6;0.8,0.8;book_prev;<]" ..
"label[3.2,7.7;" .. esc(S("Page @1 of @2", page, page_max)) .. "]" ..
"button[4.9,7.6;0.8,0.8;book_next;>]"
end end
minetest.show_formspec(player_name, "default:book", formspec) minetest.show_formspec(player_name, "default:book", formspec_size .. formspec)
return itemstack return itemstack
end end
@ -69,12 +98,37 @@ local max_title_size = 80
local short_title_size = 35 local short_title_size = 35
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "default:book" then return end if formname ~= "default:book" then return end
local player_name = player:get_player_name()
local inv = player:get_inventory() local inv = player:get_inventory()
local stack = player:get_wielded_item() local stack = player:get_wielded_item()
local data = stack:get_meta():to_table().fields
if fields.save and fields.title and fields.text local title = data.title or ""
and fields.title ~= "" and fields.text ~= "" then local text = data.text or ""
local new_stack, data
if fields.book_header ~= nil and data.owner == player_name then
local contents
local tab = tonumber(fields.book_header)
if tab == 1 then
contents = formspec_core(tab) ..
formspec_write(title, text)
elseif tab == 2 then
local lines, string = {}, ""
for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do
lines[#lines+1] = str
end
string = formspec_string(lpp, data.page, lines, string)
contents = formspec_read(player_name, title, string,
text, data.page, data.page_max)
end
tab_number = tab
local formspec = formspec_size .. formspec_core(tab) .. contents
minetest.show_formspec(player_name, "default:book", formspec)
return
end
if fields.save and fields.title and fields.text then
local new_stack
if stack:get_name() ~= "default:book_written" then if stack:get_name() ~= "default:book_written" then
local count = stack:get_count() local count = stack:get_count()
if count == 1 then if count == 1 then
@ -83,11 +137,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
stack:set_count(count - 1) stack:set_count(count - 1)
new_stack = ItemStack("default:book_written") new_stack = ItemStack("default:book_written")
end end
else
data = stack:get_meta():to_table().fields
end end
if data and data.owner and data.owner ~= player:get_player_name() then if data.owner ~= player_name and title ~= "" and text ~= "" then
return return
end end
@ -117,8 +169,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
elseif fields.book_next or fields.book_prev then elseif fields.book_next or fields.book_prev then
local data = stack:get_meta():to_table().fields if not data.page then
if not data or not data.page then
return return
end end