gutenburg/init.lua

206 lines
5.4 KiB
Lua

-- Gutenberg init.lua
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
gutenberg = {}
gutenberg.path = minetest.get_modpath(minetest.get_current_modname())
local world_path = minetest.get_worldpath()
gutenberg.cache_path = world_path .. '/book_cache/'
local files = {}
for _, filename in pairs(minetest.get_dir_list(gutenberg.path.."/books/")) do
if filename:find('%.txt$') then
files[#files+1] = filename
end
end
--local lpp = 21 -- Lines per book's page
local lpp = 18 -- Lines per book's page
local function book_on_use(itemstack, user)
local player_name = user:get_player_name()
local data = minetest.deserialize(itemstack:get_metadata())
local item_name = itemstack:get_name()
local book = gutenberg.books[item_name]
if not book then
return
end
local page = 1
if data and data.page then
page = data.page
end
local formspec = ""
local lines, string = {}, ""
local file = item_name:gsub('gutenberg:book_', '') .. string.format('%04d', page) .. '.txt'
local f = io.open(gutenberg.cache_path..'/'..file, 'r')
if not f then
return
end
local text = f:read('*a')
f:close()
for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do
lines[#lines+1] = str
end
formspec = "size[11,10]" .. default.gui_bg ..
--formspec = "size[9,8]" .. default.gui_bg ..
default.gui_bg_img ..
"label[0.5,0.5;by " .. book.author .. "]" ..
"tablecolumns[color;text]" ..
"tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
"table[0.4,0;7,0.5;title;#FFFF00," .. minetest.formspec_escape(book.title) .. "]" ..
"textarea[0.5,1.5;10.5,9;;" ..
--"textarea[0.5,1.5;8.5,7;;" ..
minetest.formspec_escape(string ~= "" and string or text) .. ";]" ..
"button[2.4,9.6;0.8,0.8;book_prev;<]" ..
"label[3.2,9.7;Page " .. page .. " of " .. book.page_max .. "]" ..
"button[5.9,9.6;0.8,0.8;book_next;>]"
--"button[2.4,7.6;0.8,0.8;book_prev;<]" ..
--"label[3.2,7.7;Page " .. page .. " of " .. book.page_max .. "]" ..
--"button[4.9,7.6;0.8,0.8;book_next;>]"
minetest.show_formspec(player_name, "gutenberg:book_gutenberg", formspec)
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "gutenberg:book_gutenberg" then return end
local stack = player:get_wielded_item()
if fields.book_next or fields.book_prev then
local book = gutenberg.books[stack:get_name()]
if not book then
return
end
local data = minetest.deserialize(stack:get_metadata())
if not data or not data.page then
data = {}
data.page = 1
data.page_max = book.page_max
end
if fields.book_next then
data.page = data.page + 1
if data.page > data.page_max then
data.page = 1
end
else
data.page = data.page - 1
if data.page == 0 then
data.page = data.page_max
end
end
local data_str = minetest.serialize(data)
stack:set_metadata(data_str)
book_on_use(stack, player)
end
player:set_wielded_item(stack)
end)
gutenberg.books = {}
local titles = {}
for _, file in pairs(files) do
if file:find('^[a-zA-Z0-9%._]+$') then
local f = io.open(gutenberg.path..'/books/'..file, 'r')
if f then
for non = 1, 1 do
local book = {}
local text = f:read('*a')
f:seek('set')
text = text:gsub('\r', '')
for tit in text:gmatch('Title: ([^\n]+)') do
book.title = tit
end
for aut in text:gmatch('Author: ([^\n]+)') do
book.author = aut
end
if not (book.title and book.author) then
book.title = file:gsub('%.txt$', '')
book.author = 'Unknown'
end
local page_max = 0
local line = 1
local page = 1
local page_text = {}
for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do
if page > lpp then
line = 1
local cache_file = file:gsub('%.txt$', '') .. string.format('%04d', page_max) .. '.txt'
local full_cache_file = gutenberg.cache_path..'/'..cache_file
local fo = io.open(full_cache_file, 'w')
if not fo then
gutenberg.cache_path = world_path
full_cache_file = gutenberg.cache_path..'/'..cache_file
fo = io.open(full_cache_file, 'w')
end
if fo then
fo:write(table.concat(page_text, '\n'))
fo:close()
else
break
end
page_text = {}
page_max = page_max + 1
page = 1
end
page_text[#page_text+1] = str
page = page + 1
end
book.page_max = page_max
local node = 'gutenberg:book_'..file:gsub('%.txt', '')
gutenberg.books[node] = book
titles[#titles+1] = node
minetest.register_craftitem(node, {
description = book.title..' by '..book.author,
inventory_image = "default_book_written.png",
groups = {book = 1, not_in_creative_inventory = 1},
stack_max = 1,
on_use = book_on_use,
})
end
f:close()
end
end
end
minetest.register_craftitem('gutenberg:book_gutenberg', {
description = '??? A book ???',
inventory_image = "default_book_written.png",
groups = {book = 1, not_in_creative_inventory = 1},
stack_max = 1,
})
minetest.register_craft({
output = 'gutenberg:book_gutenberg',
recipe = {
{'default:paper', '', ''},
{'', 'default:paper', ''},
{'', '', 'default:paper'},
}
})
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
if #titles < 1 or itemstack:get_name() ~= "gutenberg:book_gutenberg" then
return
end
itemstack:replace(titles[math.random(#titles)])
end)