123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- local vadd = vector.add
- local floor, pi = math.floor, math.pi
- local sign_positions = {
- [0] = {{x = 0, y = 0.18, z = -0.07}, pi},
- [1] = {{x = -0.07, y = 0.18, z = 0}, pi * 0.5},
- [2] = {{x = 0, y = 0.18, z = 0.07}, 0},
- [3] = {{x = 0.07, y = 0.18, z = 0}, pi * 1.5}
- }
- local wall_sign_positions = {
- [0] = {{x = 0.43, y = -0.005, z = 0}, pi * 0.5},
- [1] = {{x = -0.43, y = -0.005, z = 0}, pi * 1.5},
- [2] = {{x = 0, y = -0.005, z = 0.43}, pi},
- [3] = {{x = 0, y = -0.005, z = -0.43}, 0}
- }
- local function generate_sign_line_texture(str, row)
- local leftover = floor((20 - #str) * 16 / 2)
- local texture = ""
- for i = 1, 20 do
- local char = str:byte(i)
- if char and (char >= 32 and char <= 126) then
- texture = texture .. ":" .. (i - 1) * 16 + leftover .. ","
- .. row * 20 .. "=signs_" .. char .. ".png"
- end
- end
- return texture
- end
- local function find_any(str, pair, start)
- local ret = 0 -- 0 if not found (indices start at 1)
- for _, needle in pairs(pair) do
- local first = str:find(needle, start)
- if first then
- if ret == 0 or first < ret then
- ret = first
- end
- end
- end
- return ret
- end
- local disposable_chars = {["\n"] = true, ["\r"] = true, ["\t"] = true, [" "] = true}
- local wrap_chars = {"\n", "\r", "\t", " ", "-", "/", ";", ":", ",", ".", "?", "!"}
- local slugify = dofile(minetest.get_modpath("signs") .. "/slugify.lua")
- local function generate_sign_texture(str)
- if not str or str == "" then
- return "blank.png"
- end
- local row = 0
- local texture = "[combine:" .. 16 * 20 .. "x100"
- local result = {}
- -- Transliterate text
- str = slugify(str)
- while #str > 0 do
- if row > 4 then
- break
- end
- local wrap_i = 0
- local keep_i = 0 -- The last character that was kept
- while wrap_i < #str do
- wrap_i = find_any(str, wrap_chars, wrap_i + 1)
- if wrap_i > 20 then
- if keep_i > 1 then
- wrap_i = keep_i
- else
- wrap_i = 20
- end
- break
- elseif wrap_i == 0 then
- if #str <= 20 then
- wrap_i = #str
- elseif keep_i > 0 then
- wrap_i = keep_i
- else
- wrap_i = #str
- end
- break
- elseif str:sub(wrap_i, wrap_i) == "\n" then
- break
- end
- if not disposable_chars[str:sub(wrap_i, wrap_i)] then
- keep_i = wrap_i
- elseif wrap_i > 1 and not disposable_chars[str:sub(wrap_i - 1, wrap_i - 1)] then
- keep_i = wrap_i - 1
- end
- end
- if wrap_i > 20 then
- wrap_i = 20
- end
- local start_remove = 0
- if disposable_chars[str:sub(1, 1)] then
- start_remove = 1
- end
- local end_remove = 0
- if disposable_chars[str:sub(wrap_i, wrap_i)] then
- end_remove = 1
- end
- local line_string = str:sub(1 + start_remove, wrap_i - end_remove)
- str = str:sub(wrap_i + 1)
- if line_string ~= "" then
- result[row] = line_string
- end
- row = row + 1
- end
- local empty = 0
- if row == 1 then
- empty = 2
- elseif row < 4 then
- empty = 1
- end
- for r, s in pairs(result) do
- texture = texture .. generate_sign_line_texture(s, r + empty)
- end
- return texture
- end
- minetest.register_entity("signs:sign_text", {
- visual = "upright_sprite",
- visual_size = {x = 0.7, y = 0.6},
- collisionbox = {0},
- pointable = false,
- on_activate = function(self)
- local ent = self.object
- local pos = ent:get_pos()
- -- remove entity for missing sign
- local node_name = minetest.get_node(pos).name
- if not node_name == "signs:sign" and not node_name == "signs:wall_sign" then
- ent:remove()
- return
- end
- local meta = minetest.get_meta(pos)
- local meta_texture = meta:get_string("sign_texture")
- local texture
- if meta_texture and meta_texture ~= "" then
- texture = meta_texture
- else
- local meta_text = meta:get_string("sign_text")
- if meta_text and meta_text ~= "" then
- texture = generate_sign_texture(meta_text)
- else
- texture = "blank.png"
- end
- meta:set_string("sign_texture", texture)
- end
- ent:set_properties({
- textures = {texture, "blank.png"}
- })
- end
- })
- local function check_text(pos)
- local meta = minetest.get_meta(pos)
- local text = meta:get_string("sign_text")
- local objects = minetest.get_objects_inside_radius(pos, 0.5)
- if text and text ~= "" then
- local count = 0
- for _, obj in pairs(objects) do
- local ent = obj:get_luaentity()
- if ent and ent.name == "signs:sign_text" then
- count = count + 1
- if count > 1 then
- obj:remove()
- end
- end
- end
- if count == 0 then
- local node = minetest.get_node(pos)
- local p2 = node.param2 or -1
- local sign_pos = sign_positions
- if node.name == "signs:wall_sign" then
- p2 = p2 - 2
- sign_pos = wall_sign_positions
- end
- if p2 > 3 or p2 < 0 then return end
- local obj = minetest.add_entity(
- vadd(pos, sign_pos[p2][1]), "signs:sign_text")
- obj:set_yaw(sign_pos[p2][2])
- end
- else
- for _, obj in pairs(objects) do
- local ent = obj:get_luaentity()
- if ent and ent.name == "signs:sign_text" then
- obj:remove()
- end
- end
- end
- end
- minetest.register_lbm({
- label = "Check for sign text",
- name = "signs:sign_text",
- nodenames = {"signs:sign", "signs:wall_sign"},
- run_at_every_load = true,
- action = check_text
- })
- local function construct(pos)
- local meta = minetest.get_meta(pos)
- meta:set_string("formspec", "size[5,3]" ..
- "textarea[1.15,0.3;3.3,2;Dtext;" .. "Enter your text:" .. ";${sign_text}]" ..
- "button_exit[0.85,2;3.3,1;;" .. "Save" .. "]")
- end
- local function destruct(pos)
- for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
- local ent = obj:get_luaentity()
- if ent and ent.name == "signs:sign_text" then
- obj:remove()
- end
- end
- end
- local function receive_fields(pos, _, fields, sender, wall)
- local text = fields.Dtext
- if not text then return end
- if minetest.is_protected(pos, sender:get_player_name()) then
- return
- end
- text = text:sub(1, 256)
- local p2 = minetest.get_node(pos).param2
- local sign_pos = sign_positions
- if wall then
- p2 = p2 - 2
- sign_pos = wall_sign_positions
- end
- if not p2 or p2 > 3 or p2 < 0 then return end
- local sign
- for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
- local ent = obj:get_luaentity()
- if ent and ent.name == "signs:sign_text" then
- sign = obj
- break
- end
- end
- if not sign then
- sign = minetest.add_entity(
- vadd(pos, sign_pos[p2][1]), "signs:sign_text")
- else
- sign:set_pos(vadd(pos, sign_pos[p2][1]))
- end
- local texture = generate_sign_texture(text)
- sign:set_properties({
- textures = {texture, "blank.png"}
- })
- sign:set_yaw(sign_pos[p2][2])
- local meta = minetest.get_meta(pos)
- meta:set_string("sign_text", text)
- meta:set_string("sign_texture", texture)
- meta:set_string("infotext", text)
- end
- minetest.register_node("signs:sign", {
- description = "Sign",
- tiles = {"signs_wood.png"},
- drawtype = "nodebox",
- paramtype = "light",
- paramtype2 = "facedir",
- node_placement_prediction = "",
- sunlight_propagates = true,
- node_box = {
- type = "fixed",
- fixed = {
- {-0.375, -0.125, -0.063, 0.375, 0.5, 0.063},
- {-0.063, -0.5, -0.063, 0.063, -0.125, 0.063}
- }
- },
- groups = {oddly_breakable_by_hand = 1, choppy = 3, attached_node = 1},
- on_place = function(itemstack, placer, pointed_thing)
- if pointed_thing.type == "node" then
- local under = pointed_thing.under
- local node = minetest.get_node(under)
- local node_def = minetest.registered_nodes[node.name]
- if node_def and node_def.on_rightclick and
- not (placer and placer:is_player() and
- placer:get_player_control().sneak) then
- return node_def.on_rightclick(under, node, placer, itemstack,
- pointed_thing) or itemstack
- end
- local undery = pointed_thing.under.y
- local posy = pointed_thing.above.y
- local _, result
- if undery < posy then -- Floor sign
- itemstack, result = minetest.item_place(itemstack,
- placer, pointed_thing)
- elseif undery == posy then -- Wall sign
- _, result = minetest.item_place(ItemStack("signs:wall_sign"),
- placer, pointed_thing)
- if result and not (creative and creative.is_enabled_for and
- creative.is_enabled_for(placer)) then
- itemstack:take_item()
- end
- end
- if result then
- minetest.sound_play({name = "default_place_node_hard"},
- {pos = pointed_thing.above})
- end
- end
- return itemstack
- end,
- on_construct = construct,
- on_destruct = destruct,
- on_punch = check_text,
- on_receive_fields = receive_fields
- })
- minetest.register_node("signs:wall_sign", {
- tiles = {"signs_wood.png"},
- drawtype = "nodebox",
- paramtype = "light",
- paramtype2 = "wallmounted",
- node_box = {
- type = "wallmounted",
- wall_side = {-0.5, -0.313, -0.438, -0.438, 0.313, 0.438}
- },
- drop = "signs:sign",
- walkable = false,
- groups = {oddly_breakable_by_hand = 1, choppy = 3,
- not_in_creative_inventory = 1, attached_node = 1},
- on_construct = construct,
- on_destruct = destruct,
- on_punch = check_text,
- on_receive_fields = function(pos, _, fields, sender)
- receive_fields(pos, _, fields, sender, true)
- end
- })
- minetest.register_craft({
- output = "signs:sign 3",
- recipe = {
- {"group:wood", "group:wood", "group:wood"},
- {"group:wood", "group:wood", "group:wood"},
- {"", "group:stick", ""}
- }
- })
- minetest.register_craft({
- type = "fuel",
- recipe = "signs:sign",
- burntime = 10
- })
|