1 -- This mod provides the visible text on signs library used by Home Decor
2 -- and perhaps other mods at some point in the future. Forked from thexyz's/
3 -- PilzAdam's original text-on-signs mod and rewritten by Vanessa Ezekowitz
7 -- { delta = {entity position for 0° yaw}, exact yaw expression }
8 -- { delta = {entity position for 180° yaw}, exact yaw expression }
9 -- { delta = {entity position for 270° yaw}, exact yaw expression }
10 -- { delta = {entity position for 90° yaw}, exact yaw expression }
15 signs_lib
.modpath
= minetest
.get_modpath("signs_lib")
17 signs_lib
.wall_sign_model
= {
20 fixed
= {-0.4375, -0.25, 0.4375, 0.4375, 0.375, 0.5}
23 {delta
= {x
= 0, y
= 0.07, z
= 0.43 }, yaw
= 0},
24 {delta
= {x
= 0.43, y
= 0.07, z
= 0 }, yaw
= math
.pi
/ -2},
25 {delta
= {x
= 0, y
= 0.07, z
= -0.43 }, yaw
= math
.pi
},
26 {delta
= {x
= -0.43, y
= 0.07, z
= 0 }, yaw
= math
.pi
/ 2},
30 signs_lib
.yard_sign_model
= {
34 {-0.4375, -0.25, -0.0625, 0.4375, 0.375, 0},
35 {-0.0625, -0.5, -0.0625, 0.0625, -0.1875, 0},
39 {delta
= {x
= 0, y
= 0.07, z
= -0.068}, yaw
= 0},
40 {delta
= {x
= -0.068, y
= 0.07, z
= 0 }, yaw
= math
.pi
/ -2},
41 {delta
= {x
= 0, y
= 0.07, z
= 0.068}, yaw
= math
.pi
},
42 {delta
= {x
= 0.068, y
= 0.07, z
= 0 }, yaw
= math
.pi
/ 2},
46 signs_lib
.hanging_sign_model
= {
50 {-0.4375, -0.3125, -0.0625, 0.4375, 0.3125, 0},
51 {-0.4375, 0.25, -0.03125, 0.4375, 0.5, -0.03125},
55 {delta
= {x
= 0, y
= -0.02, z
= -0.063}, yaw
= 0},
56 {delta
= {x
= -0.063, y
= -0.02, z
= 0 }, yaw
= math
.pi
/ -2},
57 {delta
= {x
= 0, y
= -0.02, z
= 0.063}, yaw
= math
.pi
},
58 {delta
= {x
= 0.063, y
= -0.02, z
= 0 }, yaw
= math
.pi
/ 2},
62 signs_lib
.sign_post_model
= {
66 {-0.4375, -0.25, -0.1875, 0.4375, 0.375, -0.125},
67 {-0.125, -0.5, -0.125, 0.125, 0.5, 0.125},
71 {delta
= {x
= 0, y
= 0.07, z
= -0.188}, yaw
= 0},
72 {delta
= {x
= -0.188, y
= 0.07, z
= 0 }, yaw
= math
.pi
/ -2},
73 {delta
= {x
= 0, y
= 0.07, z
= 0.188 }, yaw
= math
.pi
},
74 {delta
= {x
= 0.188, y
= 0.07, z
= 0 }, yaw
= math
.pi
/ 2},
78 local S
= minetest
.get_translator("signs_lib")
80 -- the list of standard sign nodes
82 signs_lib
.sign_node_list
= {
83 "signs_lib:sign_wall",
84 "signs_lib:sign_yard",
85 "signs_lib:sign_hanging",
86 "signs_lib:sign_wall_green",
87 "signs_lib:sign_wall_yellow",
88 "signs_lib:sign_wall_red",
89 "signs_lib:sign_wall_white_red",
90 "signs_lib:sign_wall_white_black",
91 "signs_lib:sign_wall_locked"
96 function signs_lib
.table_copy(t
)
98 for k
, v
in pairs(t
) do
99 if type(v
) == "table" then
100 nt
[k
] = signs_lib
.table_copy(v
)
110 if minetest
.get_modpath("unified_inventory") or not minetest
.settings
:get_bool("creative_mode") then
111 signs_lib
.expect_infinite_stacks
= false
113 signs_lib
.expect_infinite_stacks
= true
118 local MP
= minetest
.get_modpath("signs_lib")
120 -- Used by `build_char_db' to locate the file.
121 local FONT_FMT
= "%s/hdf_%02x.png"
123 -- Simple texture name for building text texture.
124 local FONT_FMT_SIMPLE
= "hdf_%02x.png"
126 -- Path to the textures.
127 local TP
= MP
.."/textures"
129 local TEXT_SCALE
= {x
=0.8, y
=0.5}
131 -- Lots of overkill here. KISS advocates, go away, shoo! ;) -- kaeza
133 local PNG_HDR
= string.char(0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)
135 -- Read the image size from a PNG file.
136 -- Returns image_w, image_h.
137 -- Only the LSB is read from each field!
138 local function read_char_size(c
)
139 local filename
= FONT_FMT
:format(TP
, c
)
140 local f
= io
.open(filename
, "rb")
142 local hdr
= f
:read(8)
143 if hdr
~= PNG_HDR
then
152 return ws
:byte(), hs
:byte()
155 -- Set by build_char_db()
159 -- Size of the canvas, in characters.
160 -- Please note that CHARS_PER_LINE is multiplied by the average character
161 -- width to get the total width of the canvas, so for proportional fonts,
162 -- either more or fewer characters may fit on a line.
163 local CHARS_PER_LINE
= 30
164 local NUMBER_OF_LINES
= 6
166 -- 6 rows, max 80 chars per, plus a bit of fudge to
167 -- avoid excess trimming (e.g. due to color codes)
169 local MAX_INPUT_CHARS
= 600
171 -- This holds the individual character widths.
172 -- Indexed by the actual character (e.g. charwidth["A"])
173 local charwidth
= { }
175 -- File to cache the font size to.
176 local CHARDB_FILE
= minetest
.get_worldpath().."/signs_lib_chardb"
178 -- helper functions to trim sign text input/output
180 local function trim_input(text
)
181 return text
:sub(1, math
.min(MAX_INPUT_CHARS
, text
:len()))
184 -- Returns true if any file differs from cached one.
185 local function check_random_chars()
187 local c
= math
.random(32, 126)
188 local w
, h
= read_char_size(c
)
190 -- File is not a PNG... wut?
191 if not (w
and h
) then return true end
193 local ch
= string.char(c
)
194 if (not charwidth
[ch
]) -- Char is not cached.
195 or (charwidth
[ch
] ~= w
) -- Width differs.
196 or (LINE_HEIGHT
and (LINE_HEIGHT
~= h
)) -- Height differs
198 -- In any case, file is different; rebuild cache.
202 -- OK, our superficial check passed. If the textures are messed up,
203 -- it's not our problem.
207 local function build_char_db()
212 -- To calculate average char width.
213 local total_width
= 0
216 -- Try to load cached data to avoid heavy disk I/O.
218 local cdbf
= io
.open(CHARDB_FILE
, "rt")
221 minetest
.log("info", "[signs_lib] Reading cached character database.")
222 for line
in cdbf
:lines() do
223 local ch
, w
= line
:match("(0x[0-9A-Fa-f]+)%s+([0-9][0-9]*)")
225 local c
= tonumber(ch
)
230 elseif (c
>= 32) and (c
< 127) then
231 charwidth
[string.char(c
)] = w
232 total_width
= total_width
+ w
233 char_count
= char_count
+ 1
240 -- Check some random characters to see if the file on disk differs
241 -- from the cached one. If so, then ditch cached data and rebuild
242 -- (font probably was changed).
243 if check_random_chars() then
245 minetest
.log("info", "[signs_lib] "
246 .."Font seems to have changed. Rebuilding cache."
250 minetest
.log("warning", "[signs_lib] "
251 .."Could not find font line height in cached DB. Trying brute force."
256 if not LINE_HEIGHT
then
257 -- OK, something went wrong... try brute force loading from texture files.
265 local w
, h
= read_char_size(c
)
267 local ch
= string.char(c
)
269 total_width
= total_width
+ w
270 char_count
= char_count
+ 1
271 if not LINE_HEIGHT
then LINE_HEIGHT
= h
end
275 if not LINE_HEIGHT
then
276 error("Could not find font line height.")
281 -- XXX: Is there a better way to calc this?
282 SIGN_WIDTH
= math
.floor((total_width
/ char_count
) * CHARS_PER_LINE
)
284 -- Try to save cached list back to disk.
286 local e
-- Note: `cdbf' is already declared local above.
287 cdbf
, e
= io
.open(CHARDB_FILE
, "wt")
289 minetest
.log("warning", "[signs_lib] Could not save cached char DB: "..(e
or ""))
293 cdbf
:write(("0x00 %d\n"):format(LINE_HEIGHT
))
295 local w
= charwidth
[string.char(c
)]
297 cdbf
:write(("0x%02X %d\n"):format(c
, w
))
304 local sign_groups
= {sign
=1, choppy
=2, dig_immediate
=2}
305 local sign_wall_groups
= {sign
=1, sign_wall
=1, choppy
=2, dig_immediate
=2}
307 local fences_with_sign
= { }
309 -- some local helper functions
311 local function split_lines_and_words_old(text
)
314 if not text
then return end
315 for word
in text
:gmatch("%S+") do
317 table.insert(lines
, line
)
318 if #lines
>= NUMBER_OF_LINES
then break end
320 elseif word
== "\\|" then
321 table.insert(line
, "|")
323 table.insert(line
, word
)
326 table.insert(lines
, line
)
330 local function split_lines_and_words(text
)
331 if not text
then return end
333 for _
, line
in ipairs(text
:split("\n")) do
334 table.insert(lines
, line
:split(" "))
339 local math_max
= math
.max
341 local function fill_line(x
, y
, w
, c
)
344 for xx
= 0, math
.max(0, w
-16), 16 do
345 table.insert(tex
, (":%d,%d=slc_%s.png"):format(x
+ xx
, y
, c
))
347 if ((w
% 16) > 0) and (w
> 16) then
348 table.insert(tex
, (":%d,%d=slc_%s.png"):format(x
+ w
- 16, y
, c
))
350 return table.concat(tex
)
353 local function make_line_texture(line
, lineno
)
362 -- We check which chars are available here.
363 for word_i
, word
in ipairs(line
) do
369 local c
= word
:sub(i
, i
)
371 local cc
= tonumber(word
:sub(i
+1, i
+1), 16)
377 local w
= charwidth
[c
]
379 width
= width
+ w
+ 1
380 if width
>= (SIGN_WIDTH
- charwidth
[" "]) then
383 maxw
= math_max(width
, maxw
)
385 if #chars
< MAX_INPUT_CHARS
then
386 table.insert(chars
, {
388 tex
=FONT_FMT_SIMPLE
:format(c
:byte()),
389 col
=("%X"):format(cur_color
),
392 ch_offs
= ch_offs
+ w
397 width
= width
+ charwidth
[" "] + 1
398 maxw
= math_max(width
, maxw
)
399 table.insert(words
, { chars
=chars
, w
=ch_offs
})
402 -- Okay, we actually build the "line texture" here.
406 local start_xpos
= math
.floor((SIGN_WIDTH
- maxw
) / 2)
408 local xpos
= start_xpos
409 local ypos
= (LINE_HEIGHT
* lineno
)
413 for word_i
, word
in ipairs(words
) do
414 local xoffs
= (xpos
- start_xpos
)
415 if (xoffs
> 0) and ((xoffs
+ word
.w
) > maxw
) then
416 table.insert(texture
, fill_line(xpos
, ypos
, maxw
, "n"))
418 ypos
= ypos
+ LINE_HEIGHT
420 if lineno
>= NUMBER_OF_LINES
then break end
421 table.insert(texture
, fill_line(xpos
, ypos
, maxw
, cur_color
))
423 for ch_i
, ch
in ipairs(word
.chars
) do
424 if ch
.col
~= cur_color
then
426 table.insert(texture
, fill_line(xpos
+ ch
.off
, ypos
, maxw
, cur_color
))
428 table.insert(texture
, (":%d,%d=%s"):format(xpos
+ ch
.off
, ypos
, ch
.tex
))
430 table.insert(texture
, (":%d,%d=hdf_20.png"):format(xpos
+ word
.w
, ypos
))
431 xpos
= xpos
+ word
.w
+ charwidth
[" "]
432 if xpos
>= (SIGN_WIDTH
+ charwidth
[" "]) then break end
435 table.insert(texture
, fill_line(xpos
, ypos
, maxw
, "n"))
436 table.insert(texture
, fill_line(start_xpos
, ypos
+ LINE_HEIGHT
, maxw
, "n"))
438 return table.concat(texture
), lineno
441 local function make_sign_texture(lines
)
442 local texture
= { ("[combine:%dx%d"):format(SIGN_WIDTH
, LINE_HEIGHT
* NUMBER_OF_LINES
) }
445 if lineno
>= NUMBER_OF_LINES
then break end
446 local linetex
, ln
= make_line_texture(lines
[i
], lineno
)
447 table.insert(texture
, linetex
)
450 table.insert(texture
, "^[makealpha:0,0,0")
451 return table.concat(texture
, "")
454 local function set_obj_text(obj
, text
, new
)
455 local split
= new
and split_lines_and_words
or split_lines_and_words_old
457 textures
={make_sign_texture(split(text
))},
458 visual_size
= TEXT_SCALE
,
462 signs_lib
.construct_sign
= function(pos
, locked
)
463 local meta
= minetest
.get_meta(pos
)
467 "textarea[0,-0.3;6.5,3;text;;${text}]"..
468 "button_exit[2,3.4;2,1;ok;Write]"..
469 "background[-0.5,-0.5;7,5;bg_signs_lib.jpg]")
470 meta
:set_string("infotext", "")
473 signs_lib
.destruct_sign
= function(pos
)
474 local objects
= minetest
.get_objects_inside_radius(pos
, 0.5)
475 for _
, v
in ipairs(objects
) do
476 local e
= v
:get_luaentity()
477 if e
and e
.name
== "signs_lib:text" then
483 local function make_infotext(text
)
484 text
= trim_input(text
)
485 local lines
= split_lines_and_words(text
) or {}
487 for _
, line
in ipairs(lines
) do
488 table.insert(lines2
, (table.concat(line
, " "):gsub("#[0-9a-fA-F]", ""):gsub("##", "#")))
490 return table.concat(lines2
, "\n")
493 signs_lib
.update_sign
= function(pos
, fields
, owner
)
494 local meta
= minetest
.get_meta(pos
)
499 fields
.text
= trim_input(fields
.text
)
502 if owner
then ownstr
= "Locked sign, owned by "..owner
.."\n" end
504 meta
:set_string("infotext", ownstr
..make_infotext(fields
.text
).." ")
505 meta
:set_string("text", fields
.text
)
506 meta
:set_int("__signslib_new_format", 1)
509 new
= (meta
:get_int("__signslib_new_format") ~= 0)
511 local text
= meta
:get_string("text")
512 if text
== nil then return end
513 local objects
= minetest
.get_objects_inside_radius(pos
, 0.5)
515 for _
, v
in ipairs(objects
) do
516 local e
= v
:get_luaentity()
517 if e
and e
.name
== "signs_lib:text" then
521 set_obj_text(v
, text
, new
)
530 -- if there is no entity
532 local signnode
= minetest
.get_node(pos
)
533 if signnode
.name
== "signs_lib:sign_yard" then
534 sign_info
= signs_lib
.yard_sign_model
.textpos
[minetest
.get_node(pos
).param2
+ 1]
535 elseif signnode
.name
== "signs_lib:sign_hanging" then
536 sign_info
= signs_lib
.hanging_sign_model
.textpos
[minetest
.get_node(pos
).param2
+ 1]
537 elseif minetest
.get_item_group(signnode
.name
, "sign_wall") == 1 then
538 sign_info
= signs_lib
.wall_sign_model
.textpos
[minetest
.get_node(pos
).param2
+ 1]
539 else -- ...it must be a sign on a fence post.
540 sign_info
= signs_lib
.sign_post_model
.textpos
[minetest
.get_node(pos
).param2
+ 1]
542 if sign_info
== nil then
545 local text
= minetest
.add_entity({x
= pos
.x
+ sign_info
.delta
.x
,
546 y
= pos
.y
+ sign_info
.delta
.y
,
547 z
= pos
.z
+ sign_info
.delta
.z
}, "signs_lib:text")
548 text
:set_yaw(sign_info
.yaw
)
551 -- What kind of sign do we need to place, anyway?
553 function signs_lib
.determine_sign_type(itemstack
, placer
, pointed_thing
, locked
)
555 name
= minetest
.get_node(pointed_thing
.under
).name
556 if fences_with_sign
[name
] then
557 if minetest
.is_protected(pointed_thing
.under
, placer
:get_player_name()) then
558 minetest
.record_protection_violation(pointed_thing
.under
,
559 placer
:get_player_name())
563 name
= minetest
.get_node(pointed_thing
.above
).name
564 local def
= minetest
.registered_nodes
[name
]
565 if not def
.buildable_to
then
568 if minetest
.is_protected(pointed_thing
.above
, placer
:get_player_name()) then
569 minetest
.record_protection_violation(pointed_thing
.above
,
570 placer
:get_player_name())
575 local node
=minetest
.get_node(pointed_thing
.under
)
577 if minetest
.registered_nodes
[node
.name
] and minetest
.registered_nodes
[node
.name
].on_rightclick
then
578 return minetest
.registered_nodes
[node
.name
].on_rightclick(pointed_thing
.under
, node
, placer
, itemstack
)
580 local above
= pointed_thing
.above
581 local under
= pointed_thing
.under
582 local dir
= {x
= under
.x
- above
.x
,
583 y
= under
.y
- above
.y
,
584 z
= under
.z
- above
.z
}
586 local wdir
= minetest
.dir_to_wallmounted(dir
)
588 local placer_pos
= placer
:get_pos()
591 x
= above
.x
- placer_pos
.x
,
592 y
= above
.y
- placer_pos
.y
,
593 z
= above
.z
- placer_pos
.z
597 local fdir
= minetest
.dir_to_facedir(dir
)
599 local pt_name
= minetest
.get_node(under
).name
600 local signname
= itemstack
:get_name()
602 if fences_with_sign
[pt_name
] and signname
== "signs_lib:sign_wall" then
603 minetest
.add_node(under
, {name
= fences_with_sign
[pt_name
], param2
= fdir
})
604 elseif wdir
== 0 and signname
== "signs_lib:sign_wall" then
605 minetest
.add_node(above
, {name
= "signs_lib:sign_hanging", param2
= fdir
})
606 elseif wdir
== 1 and signname
== "signs_lib:sign_wall" then
607 minetest
.add_node(above
, {name
= "signs_lib:sign_yard", param2
= fdir
})
608 else -- it must be a wooden or metal wall sign.
609 minetest
.add_node(above
, {name
= signname
, param2
= fdir
})
611 local meta
= minetest
.get_meta(above
)
612 local owner
= placer
:get_player_name()
613 meta
:set_string("owner", owner
)
617 if not signs_lib
.expect_infinite_stacks
then
618 itemstack
:take_item()
624 function signs_lib
.receive_fields(pos
, formname
, fields
, sender
, lock
)
625 if minetest
.is_protected(pos
, sender
:get_player_name()) then
626 minetest
.record_protection_violation(pos
,
627 sender
:get_player_name())
630 local lockstr
= lock
and "locked " or ""
631 if fields
and fields
.text
and fields
.ok
then
632 minetest
.log("action", ("%s wrote \"%s\" to "..lockstr
.."sign at %s"):format(
633 (sender
:get_player_name() or ""),
635 minetest
.pos_to_string(pos
)
638 signs_lib
.update_sign(pos
, fields
, sender
:get_player_name())
640 signs_lib
.update_sign(pos
, fields
)
645 minetest
.register_node("signs_lib:sign_wall", {
646 description
= S("Wooden Sign"),
647 _tt_help
= S("Write text on it"),
648 inventory_image
= "default_sign_wall.png",
649 wield_image
= "default_sign_wall.png",
650 is_ground_content
= false,
651 node_placement_prediction
= "",
653 sunlight_propagates
= true,
654 paramtype2
= "facedir",
655 drawtype
= "nodebox",
656 node_box
= signs_lib
.wall_sign_model
.nodebox
,
657 tiles
= {"signs_top.png", "signs_bottom.png", "signs_side.png", "signs_side.png", "signs_back.png", "signs_front.png"},
658 groups
= sign_wall_groups
,
660 on_place
= function(itemstack
, placer
, pointed_thing
)
661 return signs_lib
.determine_sign_type(itemstack
, placer
, pointed_thing
)
663 on_construct
= function(pos
)
664 signs_lib
.construct_sign(pos
)
666 on_destruct
= function(pos
)
667 signs_lib
.destruct_sign(pos
)
669 on_receive_fields
= function(pos
, formname
, fields
, sender
)
670 signs_lib
.receive_fields(pos
, formname
, fields
, sender
)
672 on_punch
= function(pos
, node
, puncher
)
673 signs_lib
.update_sign(pos
)
676 sounds
= hades_sounds
.node_sound_wood_defaults(),
679 minetest
.register_node("signs_lib:sign_yard", {
681 sunlight_propagates
= true,
682 is_ground_content
= false,
683 paramtype2
= "facedir",
684 drawtype
= "nodebox",
685 node_box
= signs_lib
.yard_sign_model
.nodebox
,
688 fixed
= {-0.4375, -0.5, -0.0625, 0.4375, 0.375, 0}
690 tiles
= {"signs_top.png", "signs_bottom.png", "signs_side.png", "signs_side.png", "signs_back.png", "signs_front.png"},
691 groups
= sign_groups
,
692 drop
= "signs_lib:sign_wall",
694 on_construct
= function(pos
)
695 signs_lib
.construct_sign(pos
)
697 on_destruct
= function(pos
)
698 signs_lib
.destruct_sign(pos
)
700 on_receive_fields
= function(pos
, formname
, fields
, sender
)
701 signs_lib
.receive_fields(pos
, formname
, fields
, sender
)
703 on_punch
= function(pos
, node
, puncher
)
704 signs_lib
.update_sign(pos
)
707 sounds
= hades_sounds
.node_sound_wood_defaults(),
710 minetest
.register_node("signs_lib:sign_hanging", {
712 sunlight_propagates
= true,
713 is_ground_content
= false,
714 paramtype2
= "facedir",
715 drawtype
= "nodebox",
716 node_box
= signs_lib
.hanging_sign_model
.nodebox
,
719 fixed
= {-0.45, -0.275, -0.049, 0.45, 0.5, 0.049}
722 "signs_hanging_top.png",
723 "signs_hanging_bottom.png",
724 "signs_hanging_side.png",
725 "signs_hanging_side.png",
726 "signs_hanging_back.png",
727 "signs_hanging_front.png"
729 groups
= sign_groups
,
730 drop
= "signs_lib:sign_wall",
732 on_construct
= function(pos
)
733 signs_lib
.construct_sign(pos
)
735 on_destruct
= function(pos
)
736 signs_lib
.destruct_sign(pos
)
738 on_receive_fields
= function(pos
, formname
, fields
, sender
)
739 signs_lib
.receive_fields(pos
, formname
, fields
, sender
)
741 on_punch
= function(pos
, node
, puncher
)
742 signs_lib
.update_sign(pos
)
745 sounds
= hades_sounds
.node_sound_wood_defaults(),
750 minetest
.register_privilege("sign_editor", "Can edit all locked signs")
752 minetest
.register_node("signs_lib:sign_wall_locked", {
753 description
= S("Locked Wooden Sign"),
754 _tt_help
= S("Write text on it, owned by placer"),
755 inventory_image
= "signs_locked_inv.png",
756 wield_image
= "signs_locked_inv.png",
757 is_ground_content
= false,
758 node_placement_prediction
= "",
760 sunlight_propagates
= true,
761 paramtype2
= "facedir",
762 drawtype
= "nodebox",
763 node_box
= signs_lib
.wall_sign_model
.nodebox
,
765 "signs_top_locked.png",
766 "signs_bottom_locked.png",
767 "signs_side_locked.png",
768 "signs_side_locked.png",
770 "signs_front_locked.png"
772 groups
= sign_wall_groups
,
773 on_place
= function(itemstack
, placer
, pointed_thing
)
774 return signs_lib
.determine_sign_type(itemstack
, placer
, pointed_thing
, true)
776 on_construct
= function(pos
)
777 signs_lib
.construct_sign(pos
, true)
779 on_destruct
= function(pos
)
780 signs_lib
.destruct_sign(pos
)
782 on_receive_fields
= function(pos
, formname
, fields
, sender
)
783 local meta
= minetest
.get_meta(pos
)
784 local owner
= meta
:get_string("owner")
785 local pname
= sender
:get_player_name() or ""
786 if pname
~= owner
and pname
~= minetest
.settings
:get("name")
787 and not minetest
.check_player_privs(pname
, {sign_editor
=true}) then
790 signs_lib
.receive_fields(pos
, formname
, fields
, sender
, true)
792 on_punch
= function(pos
, node
, puncher
)
793 signs_lib
.update_sign(pos
)
795 can_dig
= function(pos
, player
)
796 local meta
= minetest
.get_meta(pos
)
797 local owner
= meta
:get_string("owner")
798 local pname
= player
:get_player_name()
799 return pname
== owner
or pname
== minetest
.settings
:get("name")
800 or minetest
.check_player_privs(pname
, {sign_editor
=true})
803 sounds
= hades_sounds
.node_sound_wood_defaults(),
806 -- metal, colored signs
808 local sign_colors
= { "green", "yellow", "red", "white_red", "white_black" }
809 local sign_descs
= { S("Green Steel Sign"), S("Yellow Steel Sign"), S("Red Steel Sign"), S("White Steel Sign with Red Border"), S("White Steel Sign with Black Border") }
811 for i
, color
in ipairs(sign_colors
) do
812 minetest
.register_node("signs_lib:sign_wall_"..color
, {
813 description
= sign_descs
[i
],
814 _tt_help
= S("Write text on it"),
815 inventory_image
= "signs_"..color
.."_inv.png",
816 is_ground_content
= false,
817 wield_image
= "signs_"..color
.."_inv.png",
818 node_placement_prediction
= "",
820 sunlight_propagates
= true,
821 paramtype2
= "facedir",
822 drawtype
= "nodebox",
823 node_box
= signs_lib
.wall_sign_model
.nodebox
,
825 "signs_metal_tb.png",
826 "signs_metal_tb.png",
827 "signs_metal_sides.png",
828 "signs_metal_sides.png",
829 "signs_metal_back.png",
830 "signs_"..color
.."_front.png"
832 groups
= sign_wall_groups
,
833 on_place
= function(itemstack
, placer
, pointed_thing
)
834 return signs_lib
.determine_sign_type(itemstack
, placer
, pointed_thing
)
836 on_construct
= function(pos
)
837 signs_lib
.construct_sign(pos
)
839 on_destruct
= function(pos
)
840 signs_lib
.destruct_sign(pos
)
842 on_receive_fields
= function(pos
, formname
, fields
, sender
)
843 signs_lib
.receive_fields(pos
, formname
, fields
, sender
)
845 on_punch
= function(pos
, node
, puncher
)
846 signs_lib
.update_sign(pos
)
849 sounds
= hades_sounds
.node_sound_metal_defaults(),
853 local signs_text_on_activate
855 signs_text_on_activate
= function(self
)
856 local meta
= minetest
.get_meta(self
.object
:get_pos())
857 local text
= meta
:get_string("text")
858 local new
= (meta
:get_int("__signslib_new_format") ~= 0)
860 text
= trim_input(text
)
861 set_obj_text(self
.object
, text
, new
)
865 minetest
.register_entity("signs_lib:text", {
868 visual
= "upright_sprite",
870 on_activate
= signs_text_on_activate
,
873 -- And the good stuff here! :-)
877 -- restore signs' text after /clearobjects and the like
879 minetest
.register_abm({
880 label
= "Respawn sign text",
881 nodenames
= signs_lib
.sign_node_list
,
884 action
= function(pos
, node
, active_object_count
, active_object_count_wider
)
885 signs_lib
.update_sign(pos
)
889 minetest
.register_craft({
890 output
= "signs_lib:sign_wall",
892 {"group:wood", "group:wood", "group:wood"},
893 {"group:wood", "group:wood", "group:wood"},
894 {"", "group:stick", ""},
898 minetest
.register_craft({
900 recipe
= "signs_lib:sign_wall",
906 minetest
.register_craft({
907 output
= "signs_lib:sign_wall_locked",
909 {"group:wood", "group:wood", "group:wood"},
910 {"hades_core:steel_ingot", "group:wood", "group:wood"},
911 {"", "group:stick", ""},
917 minetest
.register_craft({
918 output
= "signs_lib:sign_wall_locked",
920 {"signs_lib:sign_wall"},
921 {"hades_core:steel_ingot"},
925 minetest
.register_craft({
927 recipe
= "signs_lib:sign_wall_locked",
931 -- craft recipes for the metal signs
933 minetest
.register_craft( {
934 output
= "signs_lib:sign_wall_green 4",
936 { "dye:dark_green", "dye:white", "dye:dark_green" },
937 { "hades_core:steel_ingot", "hades_core:steel_ingot", "hades_core:steel_ingot" }
940 minetest
.register_craft( {
941 output
= "signs_lib:sign_wall_yellow 4",
943 { "dye:yellow", "dye:black", "dye:yellow" },
944 { "hades_core:steel_ingot", "hades_core:steel_ingot", "hades_core:steel_ingot" }
947 minetest
.register_craft( {
948 output
= "signs_lib:sign_wall_red 4",
950 { "dye:red", "dye:white", "dye:red" },
951 { "hades_core:steel_ingot", "hades_core:steel_ingot", "hades_core:steel_ingot" }
954 minetest
.register_craft( {
955 output
= "signs_lib:sign_wall_white_red 4",
957 { "dye:white", "dye:red", "dye:white" },
958 { "hades_core:steel_ingot", "hades_core:steel_ingot", "hades_core:steel_ingot" }
961 minetest
.register_craft( {
962 output
= "signs_lib:sign_wall_white_black 4",
964 { "dye:white", "dye:black", "dye:white" },
965 { "hades_core:steel_ingot", "hades_core:steel_ingot", "hades_core:steel_ingot" }
968 if minetest
.settings
:get("log_mods") then
969 minetest
.log("action", "signs loaded")