commit 66f64f90c992dc06493f253237325700281f4e55 Author: Leslie Krause Date: Fri Feb 21 17:42:00 2020 -0500 Build 01 - initial beta version diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..94badcf --- /dev/null +++ b/README.txt @@ -0,0 +1,193 @@ +Books Redux Mod v1.0 +By Leslie Krause + +Books Redux is full rewrite of default books from Minetest Game, offering players a rich +selection of books and papers for in-game communication. + + * Choose from 4 different cover and page styles for books + * Choose from 12 different page styles for papers + * Choose from a wide variety of background color schemes + * Page sizes can range from small, large, wide, and tall + * Bookmarks can be added, removed, or recalled on-the-fly + * Edits to books and papers can be previewed before saving + * Simple page navigation for editing and viewing books + * All content is encrypted using a 128-bit block cipher + * Legacy books can still be viewed in compatibility mode + +Even better still, books and papers are both easily craftable using the same traditional +recipes as before: 3 papyrus for one paper, and 3 paper for one book. + +With so many possible combinations of sizes, colors, and styles, the design possibilities +are virtually endless! Moreover, custom layout and formatting of text is also possible +using the Bedrock Markup Language. In fact, the editor for books and papers should be +very familiar to those accustomed to the Signs Redux mod. + +https://forum.minetest.net/viewtopic.php?f=9&t=23955 + +Of course, plain-text messages are acceptable as well, as they will render exactly as +they are input, without any fancy colors or styles. Then again, that would be boring ;) + +Now for an important word about security.... + +Last year one of my more vigilant players made me aware that it is possible for anyone +to inspect locked chests on servers with only basic CSM knowledge. This means that +confidential information in written books is vulnerable to intrusion. + +Fortunately, Books Redux addresses this very concern by encrypting the content of all +written books and written papers via the Simple Cipher mod. This means that if anyone +gains access to a copy of the map, without the server operator's private key, they +won't be able to examine the personal correspondence of other players. + +Currently there is no way to automatically convert legacy books to the new format. It +must be done manually by copying and pasting text into a new book. + + +Repository +---------------------- + +Browse source code: + https://bitbucket.org/sorcerykid/books_rx + +Download archive: + https://bitbucket.org/sorcerykid/books_rx/get/master.zip + https://bitbucket.org/sorcerykid/books_rx/get/master.tar.gz + +Compatability +---------------------- + +Minetest 0.4.15+ required + +Dependencies +---------------------- + +Default Mod (required) + https://github.com/minetest-game-mods/default + +ActiveFormspecs Mod (required) + https://bitbucket.org/sorcerykid/formspecs + +Bedrock Markup Language Mod (required) + https://bitbucket.org/sorcerykid/markup + +Safety Deposit Mod (required) + https://bitbucket.org/sorcerykid/safety_deposit + +Installation +---------------------- + + 1) Unzip the archive into the mods directory of your game + 2) Rename the books_rx-master directory to "books_rx" + + +Source Code License +---------------------------------------------------------- + +GNU Lesser General Public License v3 (LGPL-3.0) + +Copyright (c) 2019-2020, Leslie E. Krause + +This program is free software; you can redistribute it and/or modify it under the terms of +the GNU Lesser General Public License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Lesser General Public License for more details. + +http://www.gnu.org/licenses/lgpl-2.1.html + + +Multimedia License (textures, sounds, and models) +---------------------------------------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) + + /textures/default_paper_written.png + obtained from https://github.com/Mossmanikin/memorandum + by Mossmanikin + modified by sorcerykid + + /textures/book_classic_cover.png + obtained from https://www.onlygfx.com/7-old-book-open-textures-jpg/ + by zolee + modified by sorcerykid + + /textures/book_classic_front.png + obtained from https://colorlava.com/freebies/book-cover-texture-designs/ + modified by sorcerykid + + /textures/book_plain_cover.png + obtained from https://www.onlygfx.com/7-old-book-open-textures-jpg/ + by zolee + modified by sorcerykid + + /textures/book_plain_front.png + obtained from https://colorlava.com/freebies/book-cover-texture-designs/ + modified by sorcerykid + + /textures/book_vintage_cover.png + obtained from https://www.onlygfx.com/7-old-book-open-textures-jpg/ + by zolee + modified by sorcerykid + + /textures/book_vintage_front.png + obtained from https://colorlava.com/freebies/book-cover-texture-designs/ + modified by sorcerykid + + /textures/paper_classic1.png + obtained from http://designbeep.com/2012/09/24/40-free-high-resolution-old-book-textures-for-designers/ + modified by sorcerykid + + /textures/paper_classic2.png + obtained from http://designbeep.com/2012/09/24/40-free-high-resolution-old-book-textures-for-designers/ + modified by sorcerykid + + /textures/paper_plain1.png + obtained from http://designbeep.com/2012/09/24/40-free-high-resolution-old-book-textures-for-designers/ + modified by sorcerykid + + /textures/paper_plain2.png + obtained from http://designbeep.com/2012/09/24/40-free-high-resolution-old-book-textures-for-designers/ + modified by sorcerykid + + /textures/paper_vintage1.png + obtained from http://designbeep.com/2012/09/24/40-free-high-resolution-old-book-textures-for-designers/ + modified by sorcerykid + + /textures/paper_vintage2.png + obtained from http://designbeep.com/2012/09/24/40-free-high-resolution-old-book-textures-for-designers/ + modified by sorcerykid + + /textures/paper_vintage3.png + obtained from http://designbeep.com/2012/09/24/40-free-high-resolution-old-book-textures-for-designers/ + modified by sorcerykid + + /textures/paper_vintage4.png + obtained from http://designbeep.com/2012/09/24/40-free-high-resolution-old-book-textures-for-designers/ + modified by sorcerykid + + +You are free to: +Share — copy and redistribute the material in any medium or format. +Adapt — remix, transform, and build upon the material for any purpose, even commercially. +The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + +Attribution — You must give appropriate credit, provide a link to the license, and +indicate if changes were made. You may do so in any reasonable manner, but not in any way +that suggests the licensor endorses you or your use. + +No additional restrictions — You may not apply legal terms or technological measures that +legally restrict others from doing anything the license permits. + +Notices: + +You do not have to comply with the license for elements of the material in the public +domain or where your use is permitted by an applicable exception or limitation. +No warranties are given. The license may not give you all of the permissions necessary +for your intended use. For example, other rights such as publicity, privacy, or moral +rights may limit how you use the material. + +For more details: +http://creativecommons.org/licenses/by-sa/3.0/ diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..685ffc0 --- /dev/null +++ b/config.lua @@ -0,0 +1,13 @@ +max_book_title_length = 50 +max_book_message_length = 800 +max_book_content_length = 5000 +max_paper_subject_length = 50 +max_paper_message_length = 800 +default_book_title = "Untitled" +default_book_scale = "small" +default_book_style = "plain" +default_book_color = "white" +default_paper_subject = "Untitled" +default_paper_scale = "small" +default_paper_style = "plain" +default_paper_color = "white" diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..08f180e --- /dev/null +++ b/depends.txt @@ -0,0 +1,4 @@ +default +markup +safety_deposit +config diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..bddce8a --- /dev/null +++ b/init.lua @@ -0,0 +1,727 @@ +-------------------------------------------------------- +-- Minetest :: Books Redux Mod (books_rx) +-- +-- See README.txt for licensing and other information. +-- Copyright (c) 2019-2020, Leslie E. Krause +-- +-- ./games/minetest_game/mods/books_rx/init.lua +-------------------------------------------------------- + +local config = minetest.load_config( ) + +local fs = minetest.formspec_escape +local open_book_viewer, open_book_editor, open_paper_viewer, open_paper_editor + +----------------------- + +function open_defbook_viewer( player_name, owner, title, text ) + + local function get_formspec( ) + local formspec = "size[8.0,8.5]" .. + default.gui_bg .. + default.gui_bg_img .. + "label[0.3,0.2;Title:]" .. + "label[1.5,0.2;" .. title .. "]" .. + "label[0.3,0.8;By:]" .. + "label[1.5,0.8;" .. owner .. "]" .. + "textarea[0.5,1.5;7.6,7.0;content;;" .. minetest.formspec_escape( text ) .. "]" .. + "button_exit[3.0,7.8;2.0,0.8;close;Close]" + + return formspec + end + + minetest.create_form( nil, player_name, get_formspec( ) ) +end + +function open_book_viewer( player_name, oldtime, owner, title, scale, style, color, pages, marks, page_idx, vars, is_preview ) + + local book_scales = { + small = { width = 12.0, height = 8.5 }, + tall = { width = 12.0, height = 11.0 }, + large = { width = 15.5, height = 11.0 }, + wide = { width = 15.5, height = 8.5 }, + } + local book_colors = { + gray = "#333333", + brown = "#663300", + teal = "#006633", + purple = "#330066", + olive = "#336600", + indigo = "#003366", + maroon = "#660033", + red = "#660000", + green = "#006600", + blue = "#000066", + } + local mark_ver = 1 + + local function add_bookmark( ) + if not table.get_index( marks, page_idx ) then + table.insert( marks, page_idx ) + table.sort( marks ) + end + end + + local function del_bookmark( ) + local idx = table.get_index( marks, page_idx ) + if idx then + table.remove( marks, idx ) + end + end + + local function get_formspec( ) + local page_width = book_scales[ scale ].width / 2 + local page_height = book_scales[ scale ].height + + local foot_x1 = ( page_width - 4.5 ) / 2 + 0.3 -- horz pos of left-hand footer + local foot_x2 = page_width + ( page_width - 4.5 ) / 2 - 0.3 -- horz pos of right-hand footer + local foot_y = page_height - 1.3 -- vert pos of both footers + + if page_idx == 1 then + -- render background and controls of front cover + local formspec = + string.format( "size[%0.2f,%0.2f]", page_width, page_height ) .. + default.gui_bg .. + string.format( "background[0.0,0.0;%0.2f,%0.2f;%s;false]", page_width, page_height, + fs( "book_" .. style .. "_front.png^[colorize:" .. book_colors[ color ] .. "66^[noalpha" ) ) .. + + string.format( "%s[%0.2f,%0.2f;2.0,1.0;close;Close]", + is_preview and "button" or "button_exit", foot_x1 + 0.8, foot_y ) .. + string.format( "button[%0.2f,%0.2f;1.0,1.0;next_page;>>]", + foot_x1 + 2.7, foot_y ) + + -- render front cover content + local page_x1 = 0.8 + local page_y1 = 0.5 + local page_x2 = page_x1 + page_width - 1.4 + local page_y2 = page_y1 + page_height - 1.5 + + formspec = formspec .. + markup.get_formspec_string( markup.parse_message( pages[ page_idx ], vars ), + page_x1, page_y1, page_x2, page_y2, "#666666", "#CCCCCC" ) + + return formspec + else + -- render background and controls of page + local mark_idx = table.get_index( marks, page_idx ) + + local formspec = + string.format( "size[%0.2f,%0.2f]", page_width * 2, page_height ) .. + default.gui_bg .. + string.format( "background[0.0,0.0;%0.2f,%0.2f;%s;false]", page_width, page_height, + fs( "book_" .. style .. "_cover.png^[colorize:" .. book_colors[ color ] .. "66^[noalpha" ) ) .. + + string.format( "background[%0.2f,0.0;%0.2f,%0.2f;%s;false]", page_width, page_width, page_height, + fs( "book_" .. style .. "_cover.png^[transformFX^[colorize:" .. book_colors[ color ] .. "66^[noalpha" ) ) .. + + string.format( "button[%0.2f,%0.2f;1.0,1.0;prev_page;<<]", foot_x2, foot_y ) .. + string.format( "button[%0.2f,%0.2f;1.0,1.0;next_page;>>]", foot_x2 + 1.0, foot_y ) .. + string.format( "%s[%0.2f,%0.2f;2.0,1.0;close;Close]", + is_preview and "button" or "button_exit", foot_x2 + 2.5, foot_y ) .. + + string.format( "label[%0.2f,%0.2f;Bookmarks:]", foot_x1, foot_y + 0.2 ) + + if #marks > 0 then + formspec = formspec .. + string.format( "dropdown[%0.2f,%0.2f;1.8,1.0;marks_%d;,%s;%d;true]", foot_x1 + 1.5, foot_y + 0.1, mark_ver, + table.join( marks, ",", function ( a, b ) return "Page " .. b - 1 end ), + mark_idx and mark_idx + 1 or 1 ) + else + formspec = formspec .. + string.format( "dropdown[%0.2f,%0.2f;1.8,1.0;marks;;1;true]", foot_x1 + 1.5, foot_y + 0.1 ) + end + if mark_idx then + formspec = formspec .. + string.format( "button[%0.2f,%0.2f;1.2,1.0;del_mark;Del]", foot_x1 + 3.3, foot_y ) + else + formspec = formspec .. + string.format( "button[%0.2f,%0.2f;1.2,1.0;add_mark;Add]", foot_x1 + 3.3, foot_y ) + end + + -- render left-hand page content + local page_x1 = 1.0 + local page_y1 = 0.5 + local page_x2 = page_x1 + page_width - 1.4 + local page_y2 = page_y1 + page_height - 1.8 + + local text_colors = { + gray = "#999999", + cyan = "#00EEEE", + magenta = "#EE00EE", + yellow = "#EEEE00", + red = "#CC0000", + green = "#00CC00", + blue = "#0000CC", + brown = "#CC9900", + teal = "#00CC99", + purple = "#9900CC", + olive = "#99CC00", + indigo = "#0099CC", + maroon = "#CC0099", + } + + formspec = formspec .. + markup.get_formspec_string( markup.parse_message( pages[ page_idx ], vars, { colors = text_colors } ), + page_x1, page_y1, page_x2, page_y2, "#666666", "#CCCCCC" ) + + if pages[ page_idx + 1 ] then + -- render right-hand page content, if it exists + page_x1 = page_x1 + page_width - 0.6 + page_x2 = page_x2 + page_width - 0.6 + + formspec = formspec .. markup.get_formspec_string( markup.parse_message( pages[ page_idx + 1 ], vars ), + page_x1, page_y1, page_x2, page_y2, "#666666", "#CCCCCC" ) + end + + return formspec + end + end + + local function on_close( meta, player, fields ) + local fields_marks = fields[ "marks_" .. mark_ver ] + + if fields.close then + if is_preview then + open_book_editor( player_name, oldtime, owner, title, scale, style, color, pages, page_idx, vars ) + + elseif mark_ver > 1 then + local itemstack = player:get_wielded_item( ) + local player_inv = player:get_inventory( ) + local data = { + oldtime = oldtime, + owner = owner, + title = title, + scale = scale, + style = style, + color = color, + pages = pages, + marks = marks, + } + safety_deposit.encrypt_metadata( itemstack, data ) + player:set_wielded_item( itemstack ) + + minetest.chat_send_player( player_name, "Your bookmarks were updated!" ) + end + + elseif fields.next_page then + if page_idx < #pages then + page_idx = page_idx + 1 + minetest.update_form( player_name, get_formspec( ) ) + end + + elseif fields.prev_page then + if page_idx > 1 then + page_idx = page_idx - 1 + minetest.update_form( player_name, get_formspec( ) ) + end + + elseif fields.add_mark then + mark_ver = mark_ver + 1 + add_bookmark( page_idx ) + minetest.update_form( player_name, get_formspec( ) ) + + elseif fields.del_mark then + mark_ver = mark_ver + 1 + del_bookmark( page_idx ) + minetest.update_form( player_name, get_formspec( ) ) + + elseif fields_marks then -- overcome bug with dropdowns not updating values in older clients + page_idx = marks[ fields_marks - 1 ] or 1 + minetest.update_form( player_name, get_formspec( ) ) + end + end + + -- basic sanity check for proper inputs + if not book_scales[ scale ] then scale = config.default_book_scale end + if not book_colors[ color ] then color = config.default_book_color end + if page_idx < 1 or page_idx > #pages then page_idx = 1 end + + minetest.create_form( nil, player_name, get_formspec( ), on_close, is_preview and minetest.FORMSPEC_SIGSTOP or nil ) +end + +function open_book_editor( player_name, oldtime, owner, title, scale, style, color, pages, page_idx, vars ) + + local function sanitize( buf ) + return string.trim( string.gsub( buf, ".", { ["\r"] = "\n", ["\t"] = " ", ["\f"] = "?", ["\b"] = "?" } ) ) .. "\n" + end + + local function get_formspec( ) + local book_scales = { "small", "large", "tall", "wide" } + local book_colors = { "gray", "brown", "teal", "purple", "olive", "indigo", "maroon", "red", "green", "blue" } + local book_styles = { "plain", "fancy", "classic", "vintage" } + + -- book texture filenames: + -- books_cover_