written_books/init.lua

235 lines
7.1 KiB
Lua

-- This mod add a function to add written books to the treasurer
--
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local worldpath = minetest.get_worldpath()
-- Load support for intllib.
local S, NS
if intllib and intllib.make_gettext_pair then
S, NS = dofile(modpath.."/intllib.lua")
else S, NS = function(s) return s, s end
end
-- Request read/write access to files
local ie = minetest.request_insecure_environment()
assert(ie, "You must allow `"..modname.."` in `secure.trusted_mods`")
local private = { }
private.open = ie.io.open
private.mkdir = ie.core.mkdir
-- Define langage (code from intllib mod)
local LANG = minetest.settings:get("language")
if not (LANG and (LANG ~= "")) then LANG = os.getenv("LANG") end
if not (LANG and (LANG ~= "")) then LANG = "en" end
LANG = LANG:sub(1, 2)
written_books = {}
local bookslist = {}
local max_text_size = 10000
local max_title_size = 80
local short_title_size = 35
local lpp = 14 --14 -- Lines per book's page
local patterns = {
{ "title", "-- title : " },
{ "author", "-- author : " },
-- { "description", "-- description : "},
}
local bookpath = modpath.."/books"
local no_title = "Untitled Book"
local no_owner = minetest.formspec_escape("...")
-- Add books not based on default book to bookslist
written_books.add_book_to_list = function(itemstack, prob, pre, booktype)
if not itemstack then return end
if not prob then prob = 0.1 end
if not pre then pre = 4 end
if not booktype then booktype = "default" end
bookslist[#bookslist+1] = { itemstack, prob, pre, booktype }
end
-- Add written book to bookslist
written_books.register_book = function(dt, prob, pre, booktype)
if not ( dt and dt.title and dt.text ) then return end
local text
-- Get a stack of one book
local bookstack = ItemStack("default:book_written")
-- Open stack meta
local meta = bookstack:get_meta()
-- Set book meta
local data = meta:to_table().fields
data.title = dt.title:sub(1, max_title_size)
text = dt.text:sub(1, max_text_size)
text = text:gsub("\r\n", "\n"):gsub("\r", "\n")
text = string.gsub(text,"<!--(.-)-->", "") -- Remove comments
text = string.gsub(text,"%!%[.-%]%(.-%)", "") -- Remove images links
data.text = text
data.owner = dt.owner
local short_title = dt.title
-- Don't bother triming the title if the trailing dots would make it longer
if #short_title > short_title_size + 3 then
short_title = short_title:sub(1, short_title_size) .. "..."
end
local crd = ""
if data.owner ~= no_owner then crd = "by "..data.owner end
data.description = "\""..short_title.."\""..crd
data.page = 1
data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp)
meta:from_table({ fields = data })
-- Convert back to itemstack (string)
local wbook = bookstack:to_string()
-- Send to treasurer
-- (name, rarity, preciousness, count, wear, groups)
-- treasurer.register_treasure("default:book",0.1,4)
-- treasurer.register_treasure(wbook,0.1,4,nil)
written_books.add_book_to_list(wbook, prob, pre, booktype)
end
written_books.register_book_alernate = {}
dofile(modpath.."/alt_scroll.lua")
-- Add written book from file content
written_books.register_book_from_file = function(fileinfo, prob, pre, booktype)
local filetext, filepath, f, getinfos, alernate_book, owner, title
local headcomment = true
if type(fileinfo) == "string" then filepath = fileinfo
elseif type(fileinfo) == "table" and fileinfo.basename then
local fbasename = fileinfo.basename
local fpath = fileinfo.path or bookpath
local fext = fileinfo.ext or ".md"
local lg = fileinfo.lang or LANG
local fp = fpath..'/'..fbasename..'.'..lg..'.'..fext
filepath = fpath..'/'..fbasename..'.'..fext
alernate_book = fileinfo.alernate
headcomment = fileinfo.header or true
f = private.open(fp)
else return end
local filetable = {}
local infos = {}
-- Read file to get its content
if not f then f = private.open(filepath)end
if not f then filetext = "Sorry, there was a problem while trying to read the file..."
else
--
-- Get infos
--
local l = 1
local lmax = 6
local maxlen = 59
for line in f:lines() do
-- Search for file infos at the beginning of the file
if headcomment and l < lmax then
-- Look for pattern indicating infos
for _,v in ipairs(patterns) do
if string.match(line,v[2]) then
local k = v[1]
infos[k] = string.gsub(line,v[2],"")
break
end
end
-- Count lines to stop after a few lines
l = l + 1
end
--if comment then next end
--elseif string.match("<!--")
--Resize strings
-- Test if string is too long
while true do
local len = string.len(line)
if len > maxlen then
-- Get a resized substring
local sub = string.sub(line,1,maxlen)
-- Match the longest sequence finishing with a space in this substring
local match = string.match(sub, "^(.*%s)")
-- If no match, ... split anyways
if not match then match = sub end
-- Get length of this new substring
local matchlen = string.len(match)
-- Add it to table
filetable[#filetable+1] = match
-- Refefine line
line = string.sub(line, matchlen + 1, len )
else
filetable[#filetable+1] = line
break
end
end
end
-- filetext = f:read("*all")
f:close()
end
if title == nil or title == "" then title = infos.title end
if title == nil or title == "" then title = no_title end
if owner == nil or owner == "" then owner = infos.author end
if owner == nil or owner == "" then owner = no_owner end
local dt = {}
dt.title = title
dt.owner = owner
filetext = table.concat(filetable, "\n")
dt.text = filetext
dt.filetable = filetable
if ( not dt.text ) or ( dt.text == "" ) then
print("No text for file "..dump(filepath) )
print("Here are file infos transmitted to the function : "..dump(fileinfo) )
return
end
local alt = written_books.register_book_alernate or {}
if alernate_book and alt[alernate_book] then
print("Registering scroll : "..dump(dt.title) )
alt[alernate_book](dt, prob, pre, booktype)
else
print("Registering book : "..dump(dt.title) )
written_books.register_book(dt, prob, pre, booktype)
end
end
written_books.select_random_books = function(books_amount,minpre,maxpre,books_types)
if type(books_amount) ~= "number" then books_amount = 1 end
-- Reduce the booklist to requiered preciouness
local l = {}
if type(minpre) == "number" and type(maxpre) == "number" then
for _,v in ipairs(bookslist) do
if ( v[3] == nil ) or ( v[3] >= minpre and v[3] <= maxpre ) then l[#l+1] = v end
end
else l = bookslist
end
-- Reduce the booklist to requiered book types
local m = {}
if type(book_types) == "table" then
for _,v in ipairs(l) do
for _,t in ipairs(book_types) do
if v[4] == t then m[#m+1] = v end
end
end
else m = l
end
-- Randomly pick et as many element of the list as requierd
-- TODO account for probability
local bk = {}
for i = 1, books_amount do
local r = math.random(1,#m)
bk[#bk+1] = m[r][1]
end
return bk
end
------------------------------------------------------------------------
-- Execute register_books file -------------------------------------
--dofile(modpath.."/register_books.lua")
--dofile(modpath.."/register_books_others.lua")