2015-06-29 20:55:56 +03:00
-- Font: 04.jp.org
-- load characters map
2017-07-25 03:20:37 +03:00
local chars_file = io.open ( minetest.get_modpath ( " mcl_signs " ) .. " /characters " , " r " )
2015-06-29 20:55:56 +03:00
local charmap = { }
if not chars_file then
2017-07-25 03:20:37 +03:00
minetest.log ( " error " , " [mcl_signs] : character map file not found " )
2015-06-29 20:55:56 +03:00
else
2017-07-25 00:59:49 +03:00
while true do
local char = chars_file : read ( " *l " )
if char == nil then
break
end
local img = chars_file : read ( " *l " )
chars_file : read ( " *l " )
charmap [ char ] = img
end
2015-06-29 20:55:56 +03:00
end
2017-01-24 03:31:49 +02:00
-- CONSTANTS
2017-07-25 02:33:06 +03:00
local SIGN_WIDTH = 115
local SIGN_PADDING = 14
2017-01-24 03:31:49 +02:00
2017-07-25 02:57:05 +03:00
local LINE_LENGTH = 15
2017-01-24 03:31:49 +02:00
local NUMBER_OF_LINES = 4
local LINE_HEIGHT = 14
local CHAR_WIDTH = 5
local string_to_array = function ( str )
local tab = { }
for i = 1 , string.len ( str ) do
table.insert ( tab , string.sub ( str , i , i ) )
end
return tab
end
2017-07-25 01:38:10 +03:00
local string_to_line_array = function ( str )
2017-01-24 03:31:49 +02:00
local tab = { }
local current = 1
2017-07-25 01:38:10 +03:00
local linechar = 1
2017-01-24 03:31:49 +02:00
tab [ 1 ] = " "
for _ , char in ipairs ( string_to_array ( str ) ) do
2017-07-25 01:38:10 +03:00
-- New line
if char == " \n " then
current = current + 1
2017-01-24 03:31:49 +02:00
tab [ current ] = " "
2017-07-25 01:38:10 +03:00
linechar = 1
-- This check cuts off overlong lines
elseif linechar <= LINE_LENGTH then
tab [ current ] = tab [ current ] .. char
linechar = linechar + 1
2017-01-24 03:31:49 +02:00
end
end
return tab
end
local create_lines = function ( text )
local line_num = 1
local tab = { }
2017-07-25 01:38:10 +03:00
for _ , line in ipairs ( string_to_line_array ( text ) ) do
if line_num > NUMBER_OF_LINES then
break
2017-01-24 03:31:49 +02:00
end
2017-07-25 01:38:10 +03:00
table.insert ( tab , line )
line_num = line_num + 1
2017-01-24 03:31:49 +02:00
end
return tab
end
local generate_line = function ( s , ypos )
2017-07-25 00:59:49 +03:00
local i = 1
local parsed = { }
local width = 0
local chars = 0
2017-07-25 01:38:10 +03:00
while chars <= LINE_LENGTH and i <= # s do
2017-07-25 00:59:49 +03:00
local file = nil
if charmap [ s : sub ( i , i ) ] ~= nil then
file = charmap [ s : sub ( i , i ) ]
i = i + 1
elseif i < # s and charmap [ s : sub ( i , i + 1 ) ] ~= nil then
file = charmap [ s : sub ( i , i + 1 ) ]
i = i + 2
else
2017-07-25 03:20:37 +03:00
minetest.log ( " warning " , " [mcl_signs] Unknown symbol in ' " .. s .. " ' at " .. i .. " (probably " .. s : sub ( i , i ) .. " ) " )
2017-07-25 00:59:49 +03:00
i = i + 1
end
if file ~= nil then
width = width + CHAR_WIDTH
table.insert ( parsed , file )
chars = chars + 1
end
end
width = width - 1
local texture = " "
2017-07-25 02:33:06 +03:00
local xpos = math.floor ( ( SIGN_WIDTH - SIGN_PADDING - width ) / 2 )
2017-07-25 00:59:49 +03:00
for i = 1 , # parsed do
texture = texture .. " : " .. xpos .. " , " .. ypos .. " = " .. parsed [ i ] .. " .png "
xpos = xpos + CHAR_WIDTH + 1
end
return texture
2017-01-24 03:31:49 +02:00
end
local generate_texture = function ( lines )
2017-07-25 01:06:06 +03:00
local texture = " [combine: " .. SIGN_WIDTH .. " x " .. SIGN_WIDTH
2017-07-25 01:38:10 +03:00
local ypos = 9
2017-07-25 00:59:49 +03:00
for i = 1 , # lines do
texture = texture .. generate_line ( lines [ i ] , ypos )
ypos = ypos + LINE_HEIGHT
end
return texture
2017-01-24 03:31:49 +02:00
end
2017-07-25 00:36:18 +03:00
local n = 7 / 16 - 1 / 128
2015-06-29 20:55:56 +03:00
local signs = {
2017-07-25 00:59:49 +03:00
{ delta = { x = 0 , y = 0 , z = n } , yaw = 0 } ,
{ delta = { x = n , y = 0 , z = 0 } , yaw = math.pi / - 2 } ,
{ delta = { x = 0 , y = 0 , z = - n } , yaw = math.pi } ,
{ delta = { x = - n , y = 0 , z = 0 } , yaw = math.pi / 2 } ,
2015-06-29 20:55:56 +03:00
}
2017-07-25 01:52:37 +03:00
local m = 1 / 32 + 1 / 128
2017-07-25 00:36:18 +03:00
2015-06-29 20:55:56 +03:00
local signs_yard = {
2017-07-25 00:59:49 +03:00
{ delta = { x = 0 , y = 0 , z = - m } , yaw = 0 } ,
{ delta = { x = - m , y = 0 , z = 0 } , yaw = math.pi / - 2 } ,
{ delta = { x = 0 , y = 0 , z = m } , yaw = math.pi } ,
{ delta = { x = m , y = 0 , z = 0 } , yaw = math.pi / 2 } ,
2015-06-29 20:55:56 +03:00
}
2017-07-25 04:06:25 +03:00
local sign_groups = { handy = 1 , axey = 1 , flammable = 1 , deco_block = 1 , material_wood = 1 , attached_node = 1 }
2015-06-29 20:55:56 +03:00
local destruct_sign = function ( pos )
2017-07-25 00:59:49 +03:00
local objects = minetest.get_objects_inside_radius ( pos , 0.5 )
for _ , v in ipairs ( objects ) do
2017-07-25 03:20:37 +03:00
if v : get_entity_name ( ) == " mcl_signs:text " then
2017-07-25 00:59:49 +03:00
v : remove ( )
end
end
2015-06-29 20:55:56 +03:00
end
local update_sign = function ( pos , fields , sender )
2017-07-25 00:59:49 +03:00
local meta = minetest.get_meta ( pos )
2017-07-25 02:17:30 +03:00
if not meta then
return
end
2015-06-29 20:55:56 +03:00
local text = meta : get_string ( " text " )
2017-07-25 02:35:29 +03:00
if fields and ( text == " " and fields.text ) then
2015-06-29 20:55:56 +03:00
meta : set_string ( " text " , fields.text )
2017-07-25 01:38:10 +03:00
text = fields.text
2015-06-29 20:55:56 +03:00
end
2017-07-25 02:25:54 +03:00
if text == nil then
text = " "
end
2017-07-25 00:59:49 +03:00
local objects = minetest.get_objects_inside_radius ( pos , 0.5 )
for _ , v in ipairs ( objects ) do
2017-07-25 03:20:37 +03:00
if v : get_entity_name ( ) == " mcl_signs:text " then
2017-07-25 00:59:49 +03:00
v : set_properties ( { textures = { generate_texture ( create_lines ( text ) ) } } )
2015-06-29 20:55:56 +03:00
return
2017-07-25 00:59:49 +03:00
end
end
2015-06-29 20:55:56 +03:00
-- if there is no entity
local sign_info
2017-07-25 03:20:37 +03:00
if minetest.get_node ( pos ) . name == " mcl_signs:standing_sign " then
2017-01-11 19:21:46 +02:00
sign_info = signs_yard [ minetest.get_node ( pos ) . param2 + 1 ]
2017-07-25 03:20:37 +03:00
elseif minetest.get_node ( pos ) . name == " mcl_signs:wall_sign " then
2017-01-11 19:21:46 +02:00
sign_info = signs [ minetest.get_node ( pos ) . param2 + 1 ]
2015-06-29 20:55:56 +03:00
end
if sign_info == nil then
return
end
2017-07-25 01:38:10 +03:00
local text_entity = minetest.add_entity ( { x = pos.x + sign_info.delta . x ,
2015-06-29 20:55:56 +03:00
y = pos.y + sign_info.delta . y ,
2017-07-25 03:20:37 +03:00
z = pos.z + sign_info.delta . z } , " mcl_signs:text " )
2017-07-25 01:38:10 +03:00
text_entity : setyaw ( sign_info.yaw )
2015-06-29 20:55:56 +03:00
end
2017-07-25 02:56:04 +03:00
local show_formspec = function ( player , pos )
2017-07-25 03:00:55 +03:00
minetest.show_formspec (
player : get_player_name ( ) ,
2017-07-25 03:20:37 +03:00
" mcl_signs:set_text_ " .. pos.x .. " _ " .. pos.y .. " _ " .. pos.z ,
2017-07-25 03:00:55 +03:00
" size[6,3]textarea[0.25,0.25;6,1.5;text;Edit sign text:;]label[0,1.5;Maximum line length: 15 \n Maximum lines: 4]button_exit[0,2.5;6,1;submit;Done] "
)
2017-07-25 02:56:04 +03:00
end
minetest.register_on_player_receive_fields ( function ( player , formname , fields )
2017-07-25 03:20:37 +03:00
if formname : find ( " mcl_signs:set_text_ " ) == 1 then
local x , y , z = formname : match ( " mcl_signs:set_text_(.-)_(.-)_(.*) " )
2017-07-25 02:56:04 +03:00
local pos = { x = tonumber ( x ) , y = tonumber ( y ) , z = tonumber ( z ) }
if not pos or not pos.x or not pos.y or not pos.z then return end
update_sign ( pos , fields , player )
end
end )
2017-07-25 03:20:37 +03:00
minetest.register_node ( " mcl_signs:wall_sign " , {
2017-07-25 00:59:49 +03:00
description = " Sign " ,
2017-03-11 20:33:03 +02:00
_doc_items_longdesc = " Signs can be written and come in two variants: Wall sign and sign on a sign post. Signs can be placed on the top and the sides of other blocks, but not below them. " ,
2017-07-25 03:09:30 +03:00
_doc_items_usagehelp = " Place the sign at the side to build a wall sign, place it on top of another block to build a sign with a sign post. \n After placing the sign, you can write something on it. You have 4 lines of text with up to 15 characters for each line; anything beyond these limits is lost. The text can not be changed once it has been written; you have to break and place the sign again. " ,
2017-07-25 00:59:49 +03:00
inventory_image = " default_sign.png " ,
2015-06-29 20:55:56 +03:00
walkable = false ,
2017-01-04 23:36:51 +02:00
is_ground_content = false ,
2017-07-25 00:59:49 +03:00
wield_image = " default_sign.png " ,
node_placement_prediction = " " ,
paramtype = " light " ,
2015-06-29 20:55:56 +03:00
sunlight_propagates = true ,
2017-07-25 04:06:25 +03:00
paramtype2 = " wallmounted " ,
2017-07-25 00:59:49 +03:00
drawtype = " nodebox " ,
2017-07-25 04:06:25 +03:00
node_box = { type = " wallmounted " , wall_side = { - 0.499 , - 1 / 16 , - 7 / 16 , - 7 / 16 , 7 / 16 , 7 / 16 } } ,
tiles = { " signs_wall.png " } ,
2017-07-25 00:59:49 +03:00
groups = sign_groups ,
2017-01-17 00:34:40 +02:00
stack_max = 16 ,
2017-02-11 19:46:23 +02:00
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
2015-06-29 20:55:56 +03:00
2017-07-25 00:59:49 +03:00
on_place = function ( itemstack , placer , pointed_thing )
local above = pointed_thing.above
local under = pointed_thing.under
2017-03-02 17:20:19 +02:00
2017-07-25 00:59:49 +03:00
-- Use pointed node's on_rightclick function first, if present
local node = minetest.get_node ( under )
if placer and not placer : 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 , placer , itemstack ) or itemstack
end
2017-03-02 17:20:19 +02:00
end
2017-07-25 00:59:49 +03:00
local dir = { x = under.x - above.x ,
y = under.y - above.y ,
z = under.z - above.z }
2015-06-29 20:55:56 +03:00
2017-07-25 00:59:49 +03:00
-- Only build when it's legal
local abovenodedef = minetest.registered_nodes [ minetest.get_node ( above ) . name ]
if not abovenodedef or abovenodedef.buildable_to == false then
return itemstack
end
2017-02-22 00:05:57 +02:00
2017-07-25 00:59:49 +03:00
local wdir = minetest.dir_to_wallmounted ( dir )
2015-06-29 20:55:56 +03:00
2017-07-25 00:59:49 +03:00
local placer_pos = placer : getpos ( )
if placer_pos then
dir = {
x = above.x - placer_pos.x ,
y = above.y - placer_pos.y ,
z = above.z - placer_pos.z
}
end
2015-06-29 20:55:56 +03:00
2017-07-25 00:59:49 +03:00
local fdir = minetest.dir_to_facedir ( dir )
2015-06-29 20:55:56 +03:00
2017-07-25 00:59:49 +03:00
local sign_info
2017-07-25 02:56:04 +03:00
local place_pos
2017-07-25 00:59:49 +03:00
if wdir == 0 then
--how would you add sign to ceiling?
2017-07-25 02:56:04 +03:00
return itemstack
2017-07-25 00:59:49 +03:00
elseif wdir == 1 then
2017-07-25 02:56:04 +03:00
place_pos = above
2017-07-25 03:44:40 +03:00
local stand = ItemStack ( itemstack )
stand : set_name ( " mcl_signs:standing_sign " )
local _ , success = minetest.item_place_node ( stand , placer , pointed_thing , fdir )
if not success then
return itemstack
end
2017-07-25 00:59:49 +03:00
sign_info = signs_yard [ fdir + 1 ]
else
2017-07-25 02:56:04 +03:00
place_pos = above
2017-07-25 04:06:25 +03:00
local _ , success = minetest.item_place_node ( itemstack , placer , pointed_thing , wdir )
2017-07-25 03:44:40 +03:00
if not success then
return itemstack
end
2017-07-25 00:59:49 +03:00
sign_info = signs [ fdir + 1 ]
end
local text = minetest.add_entity ( {
2017-07-25 02:56:04 +03:00
x = place_pos.x + sign_info.delta . x ,
y = place_pos.y + sign_info.delta . y ,
2017-07-25 03:20:37 +03:00
z = place_pos.z + sign_info.delta . z } , " mcl_signs:text " )
2017-07-25 00:59:49 +03:00
text : setyaw ( sign_info.yaw )
2015-06-29 20:55:56 +03:00
2017-07-25 02:56:04 +03:00
if not minetest.setting_getbool ( " creative_mode " ) then
itemstack : take_item ( )
end
minetest.sound_play ( { name = " default_place_node_hard " , gain = 1.0 } , { pos = place_pos } )
show_formspec ( placer , place_pos )
2017-07-25 00:59:49 +03:00
return itemstack
end ,
2017-07-25 02:56:04 +03:00
on_destruct = destruct_sign ,
2017-07-25 00:59:49 +03:00
on_receive_fields = function ( pos , formname , fields , sender )
update_sign ( pos , fields , sender )
end ,
2015-06-29 20:55:56 +03:00
on_punch = function ( pos , node , puncher )
update_sign ( pos )
end ,
2017-02-27 02:45:25 +02:00
_mcl_hardness = 1 ,
_mcl_blast_resistance = 5 ,
2015-06-29 20:55:56 +03:00
} )
2017-07-25 03:20:37 +03:00
minetest.register_node ( " mcl_signs:standing_sign " , {
2017-07-25 00:59:49 +03:00
paramtype = " light " ,
2015-06-29 20:55:56 +03:00
sunlight_propagates = true ,
walkable = false ,
2017-01-04 23:36:51 +02:00
is_ground_content = false ,
2017-07-25 00:59:49 +03:00
paramtype2 = " facedir " ,
drawtype = " nodebox " ,
node_box = { type = " fixed " , fixed = {
2017-07-25 01:52:37 +03:00
{ - 7 / 16 , - 1 / 16 , - 1 / 32 , 7 / 16 , 7 / 16 , 1 / 32 } ,
{ - 1 / 16 , - 0.5 , - 1 / 32 , 1 / 16 , - 1 / 16 , 1 / 32 } ,
2017-07-25 00:59:49 +03:00
} } ,
2017-07-25 04:08:32 +03:00
selection_box = { type = " fixed " , fixed = { - 7 / 16 , - 0.5 , - 1 / 32 , 7 / 16 , 7 / 16 , 1 / 32 } } ,
2017-07-25 00:59:49 +03:00
tiles = { " signs_top.png " , " signs_bottom.png " , " signs_side.png " , " signs_side.png " , " signs_back.png " , " signs_front.png " } ,
groups = sign_groups ,
2017-07-25 03:20:37 +03:00
drop = " mcl_signs:wall_sign " ,
2017-01-17 00:34:40 +02:00
stack_max = 16 ,
2017-02-11 19:46:23 +02:00
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
2015-06-29 20:55:56 +03:00
2017-07-25 02:56:04 +03:00
on_destruct = destruct_sign ,
2017-07-25 00:59:49 +03:00
on_receive_fields = function ( pos , formname , fields , sender )
update_sign ( pos , fields , sender )
end ,
2015-06-29 20:55:56 +03:00
on_punch = function ( pos , node , puncher )
update_sign ( pos )
end ,
2017-02-27 02:45:25 +02:00
_mcl_hardness = 1 ,
_mcl_blast_resistance = 5 ,
2015-06-29 20:55:56 +03:00
} )
2017-07-25 03:20:37 +03:00
minetest.register_entity ( " mcl_signs:text " , {
2017-07-25 00:59:49 +03:00
collisionbox = { 0 , 0 , 0 , 0 , 0 , 0 } ,
visual = " upright_sprite " ,
textures = { } ,
2017-07-25 02:01:50 +03:00
physical = false ,
collide_with_objects = false ,
2017-07-25 00:59:49 +03:00
on_activate = function ( self )
local meta = minetest.get_meta ( self.object : getpos ( ) )
local text = meta : get_string ( " text " )
2017-07-25 02:01:50 +03:00
self.object : set_properties ( {
textures = { generate_texture ( create_lines ( text ) ) } ,
} )
self.object : set_armor_groups ( { immortal = 1 } )
2017-07-25 00:59:49 +03:00
end
2015-06-29 20:55:56 +03:00
} )
if minetest.setting_get ( " log_mods " ) then
2017-07-25 03:20:37 +03:00
minetest.log ( " action " , " [mcl_signs] loaded " )
2015-06-29 20:55:56 +03:00
end
2017-01-10 07:46:56 +02:00
minetest.register_craft ( {
type = " fuel " ,
2017-07-25 03:20:37 +03:00
recipe = " mcl_signs:wall_sign " ,
2017-01-10 07:46:56 +02:00
burntime = 10 ,
} )
2017-02-16 22:47:47 +02:00
minetest.register_craft ( {
2017-07-25 03:20:37 +03:00
output = ' mcl_signs:wall_sign 3 ' ,
2017-02-16 22:47:47 +02:00
recipe = {
{ ' group:wood ' , ' group:wood ' , ' group:wood ' } ,
{ ' group:wood ' , ' group:wood ' , ' group:wood ' } ,
{ ' ' , ' mcl_core:stick ' , ' ' } ,
}
} )
2017-03-20 19:12:05 +02:00
if minetest.get_modpath ( " doc " ) then
2017-07-25 03:20:37 +03:00
doc.add_entry_alias ( " nodes " , " mcl_signs:wall_sign " , " nodes " , " mcl_signs:standing_sign " )
2017-03-20 19:12:05 +02:00
end
2017-07-25 03:20:37 +03:00
minetest.register_alias ( " signs:sign_wall " , " mcl_signs:wall_sign " )
minetest.register_alias ( " signs:sign_yard " , " mcl_signs:standing_sign " )