2019-02-21 19:08:30 +02:00
local max_text_length = 4500 -- TODO: Increase to 12800 when scroll bar was added to written book
local max_title_length = 64
2017-02-02 00:15:23 +02:00
-- Book
minetest.register_craftitem ( " mcl_books:book " , {
description = " Book " ,
2017-03-10 04:06:33 +02:00
_doc_items_longdesc = " Books are used to make bookshelves and book and quills. " ,
2017-02-02 00:15:23 +02:00
inventory_image = " default_book.png " ,
stack_max = 64 ,
2019-02-06 13:04:58 +02:00
groups = { book = 1 , craftitem = 1 } ,
2017-02-02 00:15:23 +02:00
} )
2017-07-26 20:16:32 +03:00
if minetest.get_modpath ( " mcl_core " ) and minetest.get_modpath ( " mcl_mobitems " ) then
minetest.register_craft ( {
type = ' shapeless ' ,
output = ' mcl_books:book ' ,
recipe = { ' mcl_core:paper ' , ' mcl_core:paper ' , ' mcl_core:paper ' , ' mcl_mobitems:leather ' , }
} )
end
2017-02-02 00:15:23 +02:00
2017-06-06 02:22:52 +03:00
-- Get the included text out of the book item
-- itemstack: Book item
-- meta: Meta of book (optional)
local get_text = function ( itemstack )
-- Grab the text
local meta = itemstack : get_meta ( )
local text = meta : get_string ( " text " )
-- Backwards-compability with MCL2 0.21.0
-- Remember that get_metadata is deprecated since MT 0.4.16!
if text == nil or text == " " then
local meta_legacy = itemstack : get_metadata ( )
if itemstack : get_name ( ) == " mcl_books:written_book " then
local des = minetest.deserialize ( meta_legacy )
if des then
text = des.text
end
else
text = meta_legacy
end
end
-- Security check
if not text then
text = " "
end
return text
end
2017-06-06 03:00:36 +03:00
local make_description = function ( title , author , generation )
local desc
if generation == 0 then
desc = string.format ( " “%s” " , title )
elseif generation == 1 then
desc = string.format ( " Copy of “%s” " , title )
elseif generation == 2 then
desc = string.format ( " Copy of Copy of “%s” " , title )
else
desc = " Tattered Book "
end
desc = desc .. " \n " .. core.colorize ( " #AAAAAA " , string.format ( " by %s " , author ) )
return desc
end
2019-02-21 19:08:30 +02:00
local cap_text_length = function ( text , max_length )
return string.sub ( text , 1 , max_length )
end
2017-02-02 00:36:53 +02:00
local write = function ( itemstack , user , pointed_thing )
2017-03-02 16:44:31 +02:00
-- Call on_rightclick if the pointed node defines it
if pointed_thing.type == " node " then
local node = minetest.get_node ( pointed_thing.under )
if user and not user : get_player_control ( ) . sneak then
if minetest.registered_nodes [ node.name ] and minetest.registered_nodes [ node.name ] . on_rightclick then
return minetest.registered_nodes [ node.name ] . on_rightclick ( pointed_thing.under , node , user , itemstack ) or itemstack
end
end
end
2017-06-06 02:22:52 +03:00
local text = get_text ( itemstack )
2017-02-02 01:54:51 +02:00
local formspec = " size[8,9] " ..
" background[-0.5,-0.5;9,10;mcl_books_book_bg.png] " ..
2017-07-26 21:07:06 +03:00
" textarea[0.75,0.1;7.25,9;text;; " .. minetest.formspec_escape ( text ) .. " ] " ..
" button[0.75,7.95;3,1;sign;Sign] " ..
" button_exit[4.25,7.95;3,1;ok;Done] "
2017-02-02 01:54:51 +02:00
minetest.show_formspec ( user : get_player_name ( ) , " mcl_books:writable_book " , formspec )
end
local read = function ( itemstack , user , pointed_thing )
2017-03-02 16:44:31 +02:00
-- Call on_rightclick if the pointed node defines it
if pointed_thing.type == " node " then
local node = minetest.get_node ( pointed_thing.under )
if user and not user : get_player_control ( ) . sneak then
if minetest.registered_nodes [ node.name ] and minetest.registered_nodes [ node.name ] . on_rightclick then
return minetest.registered_nodes [ node.name ] . on_rightclick ( pointed_thing.under , node , user , itemstack ) or itemstack
end
end
end
2017-06-06 02:22:52 +03:00
local text = get_text ( itemstack )
2017-02-02 00:36:53 +02:00
local formspec = " size[8,9] " ..
" background[-0.5,-0.5;9,10;mcl_books_book_bg.png] " ..
2017-07-26 21:07:06 +03:00
" textarea[0.75,0.1;7.25,9;; " .. core.colorize ( " #000000 " , minetest.formspec_escape ( text ) ) .. " ;] " ..
" button_exit[2.25,7.95;3,1;ok;Done] "
2017-02-02 01:54:51 +02:00
minetest.show_formspec ( user : get_player_name ( ) , " mcl_books:written_book " , formspec )
2017-02-02 00:36:53 +02:00
end
2017-02-02 00:15:23 +02:00
-- Book and Quill
minetest.register_craftitem ( " mcl_books:writable_book " , {
description = " Book and Quill " ,
2017-03-10 04:06:33 +02:00
_doc_items_longdesc = " This item can be used to write down some notes. " ,
2019-02-21 19:08:30 +02:00
_doc_items_usagehelp = " Hold it in the hand, then rightclick to read the current notes and edit then. You can edit the text as often as you like. You can also sign the book which turns it into a written book which you can stack, but it can't be edited anymore. " .. " \n " ..
" A book can hold up to 4500 characters. The title length is limited to 64 characters. " ,
2017-02-02 00:15:23 +02:00
inventory_image = " mcl_books_book_writable.png " ,
groups = { book = 1 } ,
stack_max = 1 ,
2017-02-02 00:36:53 +02:00
on_place = write ,
on_secondary_use = write ,
2017-02-02 00:15:23 +02:00
} )
minetest.register_on_player_receive_fields ( function ( player , formname , fields )
if ( ( formname == " mcl_books:writable_book " ) and fields and fields.text ) then
local stack = player : get_wielded_item ( )
if ( stack : get_name ( ) and ( stack : get_name ( ) == " mcl_books:writable_book " ) ) then
2017-06-06 02:22:52 +03:00
local meta = stack : get_meta ( )
2019-02-21 19:08:30 +02:00
local text = cap_text_length ( fields.text , max_text_length )
2017-02-02 01:54:51 +02:00
if fields.ok then
2019-02-21 19:08:30 +02:00
meta : set_string ( " text " , text )
2017-06-06 02:22:52 +03:00
player : set_wielded_item ( stack )
2017-02-02 01:54:51 +02:00
elseif fields.sign then
2019-02-21 19:08:30 +02:00
meta : set_string ( " text " , text )
2017-06-06 02:22:52 +03:00
player : set_wielded_item ( stack )
2017-02-02 02:35:44 +02:00
2017-02-02 01:54:51 +02:00
local name = player : get_player_name ( )
local formspec = " size[8,9] " ..
" background[-0.5,-0.5;9,10;mcl_books_book_bg.png] " ..
2017-07-26 21:07:06 +03:00
" field[0.75,1;7.25,1;title; " .. core.colorize ( " #000000 " , " Enter book title: " ) .. " ;] " ..
" label[0.75,1.5; " .. core.colorize ( " #404040 " , minetest.formspec_escape ( " by " .. name ) ) .. " ] " ..
" label[0.75,6.95; " .. core.colorize ( " #000000 " , " Note: The book will no longer " ) .. " \n " .. core.colorize ( " #000000 " , " be editable after signing. " ) .. " ] " ..
" button_exit[0.75,7.95;3,1;sign;Sign and Close] " ..
" button[4.25,7.95;3,1;cancel;Cancel] "
2017-02-02 01:54:51 +02:00
minetest.show_formspec ( player : get_player_name ( ) , " mcl_books:signing " , formspec )
end
end
elseif ( ( formname == " mcl_books:signing " ) and fields and fields.sign and fields.title ) then
local newbook = ItemStack ( " mcl_books:written_book " )
local book = player : get_wielded_item ( )
local name = player : get_player_name ( )
if book : get_name ( ) == " mcl_books:writable_book " then
2019-02-21 19:08:30 +02:00
local title = fields.title
if string.len ( title ) == 0 then
title = " Nameless Book "
2017-02-02 01:54:51 +02:00
end
2019-02-21 19:08:30 +02:00
title = cap_text_length ( title , max_title_length )
2017-06-06 02:22:52 +03:00
local meta = newbook : get_meta ( )
2019-02-21 19:08:30 +02:00
local text = cap_text_length ( get_text ( book ) , max_text_length )
meta : set_string ( " title " , title )
2017-06-06 02:22:52 +03:00
meta : set_string ( " author " , name )
meta : set_string ( " text " , text )
2019-02-21 19:08:30 +02:00
meta : set_string ( " description " , make_description ( title , name , 0 ) )
2017-06-06 02:52:50 +03:00
-- The book copy counter. 0 = original, 1 = copy of original, 2 = copy of copy of original, …
meta : set_int ( " generation " , 0 )
2017-06-06 02:22:52 +03:00
2017-02-02 01:54:51 +02:00
player : set_wielded_item ( newbook )
else
minetest.log ( " error " , " [mcl_books] " .. name .. " failed to sign a book! " )
2017-02-02 00:15:23 +02:00
end
2017-02-02 02:21:35 +02:00
elseif ( ( formname == " mcl_books:signing " ) and fields and fields.cancel ) then
local book = player : get_wielded_item ( )
if book : get_name ( ) == " mcl_books:writable_book " then
2017-03-30 06:11:16 +03:00
write ( book , player , { type = " nothing " } )
2017-02-02 02:21:35 +02:00
end
2017-02-02 00:15:23 +02:00
end
end )
2017-07-26 20:16:32 +03:00
if minetest.get_modpath ( " mcl_dye " ) and minetest.get_modpath ( " mcl_mobitems " ) then
minetest.register_craft ( {
type = " shapeless " ,
output = " mcl_books:writable_book " ,
recipe = { " mcl_books:book " , " mcl_dye:black " , " mcl_mobitems:feather " } ,
} )
end
2017-02-02 00:15:23 +02:00
2017-02-02 01:54:51 +02:00
-- Written Book
minetest.register_craftitem ( " mcl_books:written_book " , {
description = " Written Book " ,
2017-03-10 04:06:33 +02:00
_doc_items_longdesc = " Written books contain some text written by someone. They can be read and copied, but not edited. " ,
2017-06-06 03:54:40 +03:00
_doc_items_usagehelp = [ [ Hold it in your hand , then rightclick to read the book .
2017-06-06 03:57:03 +03:00
To copy the text of the written book , place it into the crafting grid together with a book and quill ( or multiple of those ) and craft . The written book will not be consumed . Copies of copies can not be copied . ] ] ,
2017-02-02 01:54:51 +02:00
inventory_image = " mcl_books_book_written.png " ,
2018-02-02 06:13:26 +02:00
groups = { not_in_creative_inventory = 1 , book = 1 , no_rename = 1 } ,
2017-06-06 03:48:36 +03:00
stack_max = 16 ,
2017-02-02 01:54:51 +02:00
on_place = read ,
on_secondary_use = read
} )
2017-02-02 02:04:31 +02:00
-- Copy books
2017-06-06 03:48:36 +03:00
-- This adds 8 recipes
local baq = " mcl_books:writable_book "
local wb = " mcl_books:written_book "
local recipes = {
{ wb , baq } ,
{ baq , baq , wb } ,
{ baq , baq , wb , baq } ,
{ baq , baq , baq , baq , wb } ,
{ baq , baq , baq , baq , wb , baq } ,
{ baq , baq , baq , baq , wb , baq , baq } ,
{ baq , baq , baq , baq , wb , baq , baq , baq } ,
{ baq , baq , baq , baq , wb , baq , baq , baq , baq } ,
}
for r =# recipes , 1 , - 1 do
minetest.register_craft ( {
type = " shapeless " ,
output = " mcl_books:written_book " .. r ,
recipe = recipes [ r ] ,
} )
end
2017-02-02 02:04:31 +02:00
2017-06-06 03:25:22 +03:00
minetest.register_craft_predict ( function ( itemstack , player , old_craft_grid , craft_inv )
if itemstack : get_name ( ) ~= " mcl_books:written_book " then
return
end
local original
local index
for i = 1 , player : get_inventory ( ) : get_size ( " craft " ) do
if old_craft_grid [ i ] : get_name ( ) == " mcl_books:written_book " then
original = old_craft_grid [ i ]
index = i
end
end
if not original then
return
end
local ometa = original : get_meta ( )
local generation = ometa : get_int ( " generation " )
2017-06-06 03:30:28 +03:00
2017-06-06 03:25:22 +03:00
-- Check generation, don't allow crafting with copy of copy of book
if generation >= 2 then
return ItemStack ( " " )
2017-06-06 03:30:28 +03:00
else
-- Valid copy. Let's update the description field of the result item
-- so it is properly displayed in the crafting grid.
local imeta = itemstack : get_meta ( )
2019-02-21 19:08:30 +02:00
local title = cap_text_length ( ometa : get_string ( " title " ) , max_title_length )
2017-06-06 03:30:28 +03:00
local author = ometa : get_string ( " author " )
-- Increase book generation and update description
generation = generation + 1
if generation < 1 then
generation = 1
end
local desc = make_description ( title , author , generation )
imeta : set_string ( " description " , desc )
return itemstack
2017-06-06 03:25:22 +03:00
end
end )
2017-02-02 02:04:31 +02:00
minetest.register_on_craft ( function ( itemstack , player , old_craft_grid , craft_inv )
if itemstack : get_name ( ) ~= " mcl_books:written_book " then
return
end
local original
local index
for i = 1 , player : get_inventory ( ) : get_size ( " craft " ) do
if old_craft_grid [ i ] : get_name ( ) == " mcl_books:written_book " then
original = old_craft_grid [ i ]
index = i
end
end
if not original then
return
end
2017-06-06 02:22:52 +03:00
-- copy of the book
local text = get_text ( original )
if not text or text == " " then
local copymeta = original : get_metadata ( )
itemstack : set_metadata ( copymeta )
else
local ometa = original : get_meta ( )
2017-06-06 03:25:22 +03:00
local generation = ometa : get_int ( " generation " )
-- No copy of copy of copy of book allowed
if generation >= 2 then
return ItemStack ( " " )
end
-- Copy metadata
2017-06-06 02:22:52 +03:00
local imeta = itemstack : get_meta ( )
2019-02-21 19:08:30 +02:00
local title = cap_text_length ( ometa : get_string ( " title " ) , max_title_length )
2017-06-06 02:52:50 +03:00
local author = ometa : get_string ( " author " )
imeta : set_string ( " title " , title )
imeta : set_string ( " author " , author )
2019-02-21 19:08:30 +02:00
imeta : set_string ( " text " , cap_text_length ( text , max_text_length ) )
2017-06-06 02:52:50 +03:00
-- Increase book generation and update description
generation = generation + 1
if generation < 1 then
generation = 1
end
2017-06-06 03:00:36 +03:00
local desc = make_description ( title , author , generation )
2017-06-06 02:52:50 +03:00
imeta : set_string ( " description " , desc )
imeta : set_int ( " generation " , generation )
2017-06-06 02:22:52 +03:00
end
2017-02-02 02:04:31 +02:00
-- put the book with metadata back in the craft grid
craft_inv : set_stack ( " craft " , index , original )
end )
2017-07-26 20:16:32 +03:00
local wood_sound
if minetest.get_modpath ( " mcl_sounds " ) then
wood_sound = mcl_sounds.node_sound_wood_defaults ( )
end
2017-02-02 00:15:23 +02:00
-- Bookshelf
minetest.register_node ( " mcl_books:bookshelf " , {
description = " Bookshelf " ,
2017-03-18 19:01:28 +02:00
_doc_items_longdesc = " Bookshelves are used for decoration. " ,
2017-07-15 12:31:38 +03:00
tiles = { " mcl_books_bookshelf_top.png " , " mcl_books_bookshelf_top.png " , " default_bookshelf.png " } ,
2017-02-02 00:15:23 +02:00
stack_max = 64 ,
is_ground_content = false ,
2017-03-11 06:34:58 +02:00
groups = { handy = 1 , axey = 1 , flammable = 3 , building_block = 1 , material_wood = 1 } ,
2017-02-02 00:15:23 +02:00
drop = " mcl_books:book 3 " ,
2017-07-26 20:16:32 +03:00
sounds = wood_sound ,
2017-02-22 17:03:59 +02:00
_mcl_blast_resistance = 7.5 ,
2017-02-27 02:13:03 +02:00
_mcl_hardness = 1.5 ,
2017-02-02 00:15:23 +02:00
} )
minetest.register_craft ( {
output = ' mcl_books:bookshelf ' ,
recipe = {
{ ' group:wood ' , ' group:wood ' , ' group:wood ' } ,
{ ' mcl_books:book ' , ' mcl_books:book ' , ' mcl_books:book ' } ,
{ ' group:wood ' , ' group:wood ' , ' group:wood ' } ,
}
} )
minetest.register_craft ( {
type = " fuel " ,
2017-02-13 15:33:16 +02:00
recipe = " mcl_books:bookshelf " ,
2017-02-02 00:15:23 +02:00
burntime = 15 ,
} )