2019-08-02 12:25:24 -07:00
local S = minetest.get_translator ( )
local F = minetest.formspec_escape
2019-08-01 14:26:17 -07:00
2019-08-02 18:55:34 -07:00
local has_doc = minetest.get_modpath ( " doc_items " )
2019-08-02 12:25:24 -07:00
gtextitems = { }
2019-08-04 06:13:15 -07:00
-- gtextitem item group
-- This item is blank (stackable, no metadata yet).
2019-08-02 12:25:24 -07:00
gtextitems.GROUP_BLANK = 1
2019-08-04 06:13:15 -07:00
-- This item is written (not stackable, has metadata).
2019-08-02 12:25:24 -07:00
gtextitems.GROUP_WRITTEN = 2
2019-08-02 18:55:34 -07:00
if has_doc then
doc.sub . items.register_factoid ( nil , " use " , function ( itemstring , def )
local ret = { }
local g = minetest.get_item_group ( itemstring , " gtextitem " )
if g > 0 then
table.insert ( ret , S " This item can be written in when used (punched with). " )
if g == gtextitems.GROUP_WRITTEN then
2019-08-02 19:06:23 -07:00
table.insert ( ret , S ( " It can be copied by crafting with another empty @1. " , minetest.registered_items [ def._gtextitems_def . itemname ] . description ) )
2019-08-02 18:55:34 -07:00
end
end
return table.concat ( ret , " \n " )
end )
end
2019-08-04 06:13:15 -07:00
-- When punching, display the formspec.
2019-08-02 12:25:24 -07:00
function gtextitems . on_use ( stack , player )
local playername = player : get_player_name ( )
local gtm = gtextitems.get_item ( stack )
if not gtm then
return stack
end
local formspec = " "
.. " size[8,8] "
.. " real_coordinates[true] "
.. ( " field[0.1,0.35;7.8,0.5;title;%s;%s] " ) : format ( F ( S " Title: " ) , F ( gtm.title ) )
.. " field_close_on_enter[title;false] "
.. ( " textarea[0.1,1.2;7.8,6;text;%s;%s] " ) : format ( F ( S " Text: " ) , F ( gtm.text ) )
.. " field_close_on_enter[text;false] "
2019-08-04 06:13:15 -07:00
-- Only display the auther when it is set.
2019-08-03 10:28:02 -07:00
.. ( ( minetest.get_item_group ( stack : get_name ( ) , " gtextitem " ) == gtextitems.GROUP_BLANK or # gtm.author == 0 ) and " " or ( " label[0.1,7.5;%s] " ) : format ( F ( S ( " Last written by @1 " , gtm.author ) ) ) )
2019-08-02 19:13:12 -07:00
.. ( " button_exit[6.75,7.4;1,0.5;save;%s] " ) : format ( F ( S " Write " ) )
2019-08-02 12:25:24 -07:00
minetest.show_formspec ( playername , " gtextitems:formspec " , formspec )
return stack
end
minetest.register_on_player_receive_fields ( function ( player , formname , fields )
if formname ~= " gtextitems:formspec " then
return
end
if not fields.save then
return
end
2019-08-04 06:13:15 -07:00
-- The wielded item will be the gtextitem.
2019-08-02 12:25:24 -07:00
local wielded = player : get_wielded_item ( )
2019-08-04 06:13:15 -07:00
-- Ensure it's a valid item.
2019-08-02 12:25:24 -07:00
if not gtextitems.get_item ( wielded ) then
return
end
2019-08-04 06:13:15 -07:00
-- Create a new stack of the written item.
2019-08-02 12:25:24 -07:00
local def = minetest.registered_items [ wielded : get_name ( ) ] . _gtextitems_def
local stack = ItemStack ( def.writtenname )
stack = gtextitems.set_item ( stack , {
author = player : get_player_name ( ) ,
2019-11-17 08:00:17 -08:00
author_type = " player " ,
2019-08-02 12:25:24 -07:00
title = fields.title ,
text = fields.text ,
} )
2019-08-04 06:13:15 -07:00
-- Take one item from wielded (if blank, then one from the stack, otherwise the whole written stack).
2019-08-02 12:25:24 -07:00
wielded : take_item ( 1 )
player : set_wielded_item ( wielded )
2019-08-04 06:13:15 -07:00
-- Add the edited item. If it was originally a written item or single item stack, this will simply replace the item removed from wielded earlier.
2019-08-02 12:25:24 -07:00
minetest.add_item ( player : get_pos ( ) , player : get_inventory ( ) : add_item ( " main " , stack ) )
return true
end )
2019-08-04 06:13:15 -07:00
-- gtextitem data structure.
2019-08-02 12:25:24 -07:00
local default = {
2019-11-17 08:00:17 -08:00
-- Who last modified this? If blank, then disregard.
2019-08-03 10:28:02 -07:00
author = " " ,
2019-11-17 08:00:17 -08:00
-- What kind of thing modified this?
--- Should be "player" if the author is a player name.
author_type = " " ,
2019-08-02 12:25:24 -07:00
title = " Untitled " ,
text = " " ,
2019-08-06 10:59:25 -07:00
-- Was this produced by copying?
copy = false ,
-- Unique ID. Preserved over copies, reset on editing.
id = nil ,
2019-08-02 12:25:24 -07:00
}
2019-08-04 06:13:15 -07:00
-- Add data to a gtextitem and sets description.
2019-08-02 12:25:24 -07:00
function gtextitems . set_item ( stack , data )
stack : get_meta ( ) : set_string ( " gtextitem " , minetest.serialize ( data ) )
2019-08-06 10:59:25 -07:00
stack : get_meta ( ) : set_string ( " description " , S ( " '@1' by @2@3 " , gtextitems.get_item ( stack ) . title , gtextitems.get_item ( stack ) . author , data.copy and S " (Copy) " or " " ) )
2019-08-02 12:25:24 -07:00
return stack
end
2019-08-04 06:13:15 -07:00
-- Get a gtextitem's data. Returns nil if the item is not a gtextitem.
2019-08-02 12:25:24 -07:00
function gtextitems . get_item ( stack )
if minetest.get_item_group ( stack : get_name ( ) , " gtextitem " ) == 0 then
return nil
end
local d = stack : get_meta ( ) : get_string ( " gtextitem " )
2019-08-08 15:34:21 -07:00
return b.t . combine ( default , ( # d > 0 ) and minetest.deserialize ( d ) or { } )
2019-08-02 12:25:24 -07:00
end
2019-08-04 06:13:15 -07:00
-- Sets a gtextitem written node's data.
2019-08-03 08:00:09 -07:00
function gtextitems . set_node ( pos , data )
local nn = minetest.get_node ( pos ) . name
2019-08-04 06:13:15 -07:00
-- Only written nodes can be set.
2019-08-03 08:00:09 -07:00
if minetest.get_item_group ( nn , " gtextitem " ) ~= gtextitems.GROUP_WRITTEN then
minetest.log ( " warning " , ( " Tried to gtextitems.set_node invalid node (%s) at (%s). " ) : format ( nn , minetest.pos_to_string ( pos ) ) )
return
end
-- Construct "fake" stack.
local stack = gtextitems.set_item ( ItemStack ( nn ) , data )
local meta = minetest.get_meta ( pos )
meta : set_string ( " gtextitem " , stack : get_meta ( ) : get_string ( " gtextitem " ) )
meta : set_string ( " infotext " , stack : get_meta ( ) : get_string ( " description " ) )
local gtm = gtextitems.get_item ( stack )
meta : set_string ( " formspec " , " size[8,8] "
.. " real_coordinates[true] "
.. ( " label[0.1,0.35;%s] " ) : format ( F ( gtm.title ) )
2019-08-03 10:28:02 -07:00
.. ( " textarea[0.1,1.2;7.8,6.2;;;%s] " ) : format ( F ( gtm.text ) )
.. ( ( # gtm.author == 0 ) and " " or ( " label[0.1,7.5;%s] " ) : format ( F ( S ( " Last written by @1 " , gtm.author ) ) ) )
2019-08-03 08:00:09 -07:00
)
end
2020-09-09 10:58:29 -07:00
-- Get a gtextitem written node's data; returns nil if not a valid node or valid data
function gtextitems . get_node ( pos )
if minetest.get_item_group ( minetest.get_node ( pos ) . name , " gtextitem " ) == gtextitems.GROUP_WRITTEN then
return minetest.deserialize ( minetest.get_meta ( pos ) : get_string ( " gtextitem " ) )
end
end
2019-08-03 07:38:57 -07:00
local function register_node ( name , def )
2019-08-04 06:13:15 -07:00
-- Override def with functions to save and load metadata when converting between item and node.
2019-08-08 15:34:21 -07:00
local def = b.t . combine ( def , {
2019-08-03 07:38:57 -07:00
preserve_metadata = function ( pos , oldnode , oldmeta , drops )
for _ , drop in ipairs ( drops ) do
if minetest.get_item_group ( drop : get_name ( ) , " gtextitem " ) == gtextitems.GROUP_WRITTEN then
drop : get_meta ( ) : set_string ( " gtextitem " , oldmeta.gtextitem )
drop : get_meta ( ) : set_string ( " description " , oldmeta.infotext )
end
end
end ,
after_place_node = function ( pos , _ , stack )
-- Don't set any metadata if this is just a blank item.
if minetest.get_item_group ( stack : get_name ( ) , " gtextitem " ) == gtextitems.GROUP_BLANK then
return
end
2019-08-03 08:00:09 -07:00
gtextitems.set_node ( pos , gtextitems.get_item ( stack ) )
2019-08-03 07:38:57 -07:00
end ,
} )
minetest.register_node ( " : " .. name , def )
end
2019-08-02 12:25:24 -07:00
function gtextitems . register ( name , def )
2019-08-08 15:34:21 -07:00
def = b.t . combine ( {
2019-08-04 06:13:15 -07:00
-- Item names.
2019-08-02 12:25:24 -07:00
itemname = name ,
writtenname = name .. " _written " ,
2019-08-04 06:13:15 -07:00
-- Register as a node?
2019-08-03 07:38:57 -07:00
node = false ,
2019-08-02 12:25:24 -07:00
} , def , {
2019-08-04 06:13:15 -07:00
-- Base item override.
2019-08-08 15:34:21 -07:00
item = b.t . combine ( {
2019-08-02 12:25:24 -07:00
description = S " Writable Item " ,
on_use = gtextitems.on_use ,
} , def.item or { } ) ,
2019-08-04 06:13:15 -07:00
-- Additional written item overrides.
2019-08-08 15:34:21 -07:00
written = b.t . combine ( {
2019-08-02 12:25:24 -07:00
description = S " Written Item " ,
on_use = gtextitems.on_use ,
stack_max = 1 ,
} , def.written or { } ) ,
} )
def.item . _gtextitems_def = def
2019-08-08 15:34:21 -07:00
def.item . groups = b.t . combine ( {
2019-08-02 12:25:24 -07:00
gtextitem = gtextitems.GROUP_BLANK ,
} , def.item . groups or { } )
2019-08-08 15:34:21 -07:00
def.written . groups = b.t . combine ( def.item . groups , {
2019-08-02 12:25:24 -07:00
gtextitem = gtextitems.GROUP_WRITTEN ,
} , def.written . groups or { } )
2019-08-03 07:38:57 -07:00
if def.node then
register_node ( def.itemname , def.item )
2019-08-08 15:34:21 -07:00
register_node ( def.writtenname , b.t . combine ( def.item , def.written ) )
2019-08-03 07:38:57 -07:00
else
minetest.register_craftitem ( " : " .. def.itemname , def.item )
2019-08-08 15:34:21 -07:00
minetest.register_craftitem ( " : " .. def.writtenname , b.t . combine ( def.item , def.written ) )
2019-08-03 07:38:57 -07:00
end
2019-08-02 19:06:23 -07:00
2019-08-04 06:13:15 -07:00
-- Register shapeless copying recipe.
2019-08-02 19:06:23 -07:00
minetest.register_craft {
output = def.writtenname ,
type = " shapeless " ,
recipe = { def.itemname , def.writtenname } ,
}
2019-08-04 06:13:15 -07:00
-- When copy-crafting, copy metadata and restore the old written item.
2019-08-02 19:06:23 -07:00
minetest.register_on_craft ( function ( stack , player , old_grid , craft_inv )
if stack : get_name ( ) ~= def.writtenname then
return
end
2019-08-04 06:13:15 -07:00
-- Locate the item to copy.
2019-08-02 19:06:23 -07:00
for i = 1 , craft_inv : get_size ( " craft " ) do
if old_grid [ i ] : get_name ( ) == def.writtenname then
2019-08-08 15:34:21 -07:00
stack = gtextitems.set_item ( stack , b.t . combine ( gtextitems.get_item ( old_grid [ i ] ) , { copy = true } ) )
2019-08-02 19:06:23 -07:00
craft_inv : set_stack ( " craft " , i , old_grid [ i ] )
2019-08-02 19:26:31 -07:00
break
2019-08-02 19:06:23 -07:00
end
end
2019-08-02 19:26:31 -07:00
return stack
end )
2019-08-04 06:13:15 -07:00
-- Same as above, but for prediction. Don't restore the old written item.
2019-08-02 19:26:31 -07:00
minetest.register_craft_predict ( function ( stack , player , old_grid , craft_inv )
if stack : get_name ( ) ~= def.writtenname then
return
end
for i = 1 , craft_inv : get_size ( " craft " ) do
if old_grid [ i ] : get_name ( ) == def.writtenname then
2019-08-08 15:34:21 -07:00
stack = gtextitems.set_item ( stack , b.t . combine ( gtextitems.get_item ( old_grid [ i ] ) , { copy = true } ) )
2019-08-02 19:26:31 -07:00
break
end
end
return stack
2019-08-02 19:06:23 -07:00
end )
2019-08-02 12:25:24 -07:00
end