letters = { {"al", "au", "a", "A"}, {"bl", "bu", "b", "B"}, {"cl", "cu", "c", "C"}, {"dl", "du", "d", "D"}, {"el", "eu", "e", "E"}, {"fl", "fu", "f", "F"}, {"gl", "gu", "g", "G"}, {"hl", "hu", "h", "H"}, {"il", "iu", "i", "I"}, {"jl", "ju", "j", "J"}, {"kl", "ku", "k", "K"}, {"ll", "lu", "l", "L"}, {"ml", "mu", "m", "M"}, {"nl", "nu", "n", "N"}, {"ol", "ou", "o", "O"}, {"pl", "pu", "p", "P"}, {"ql", "qu", "q", "Q"}, {"rl", "ru", "r", "R"}, {"sl", "su", "s", "S"}, {"tl", "tu", "t", "T"}, {"ul", "uu", "u", "U"}, {"vl", "vu", "v", "V"}, {"wl", "wu", "w", "W"}, {"xl", "xu", "x", "X"}, {"yl", "yu", "y", "Y"}, {"zl", "zu", "z", "Z"}, } letters_reversed = {} for i, t in ipairs(letters) do letters_reversed[t[3]] = i end letter_cutter = {} letter_cutter.known_nodes = {} letter_cutter.show_item_list = dofile( minetest.get_modpath(minetest.get_current_modname())..'/itemlist.lua') function letters.register_letters(modname, subname, from_node, description, tiles, def) def = def and table.copy(def) or {} --default node def.drawtype = "signlike" def.paramtype = "light" def.paramtype2 = def.paramtype2 or "wallmounted" def.sunlight_propagates = true def.is_ground_content = false def.walkable = false def.selection_box = { type = "wallmounted" --wall_top = --wall_bottom = --wall_side = } def.groups = def.groups or { not_in_creative_inventory = 1, not_in_craft_guide = 1, oddly_breakable_by_hand = 1, attached_node = 1 } def.legacy_wallmounted = false for _, row in ipairs(letters) do def = table.copy(def) def.description = description.. " " ..row[3] def.inventory_image = tiles.. "^letters_" ..row[1].. "_overlay.png^[makealpha:255,126,126" def.wield_image = def.inventory_image def.tiles = {def.inventory_image} minetest.register_node(":" ..modname..":"..subname.. "_letter_" ..row[1],def) def = table.copy(def) def.description = description.. " " ..row[4] def.inventory_image = tiles.. "^letters_" ..row[2].. "_overlay.png^[makealpha:255,126,126" def.wield_image = def.inventory_image def.tiles = {def.inventory_image} minetest.register_node(":" ..modname..":"..subname.. "_letter_" ..row[2], def) --[[minetest.register_craft({ output = from_node, recipe = { {modname..":"..name, modname..":"..name, modname..":"..name}, {modname..":"..name, modname..":"..name, modname..":"..name}, {modname..":"..name, modname..":"..name, modname..":"..name}, }, })--]] end letter_cutter.known_nodes[from_node] = {modname, subname} end cost = 0.110 letter_cutter.names_lower = { {"letter_al"}, {"letter_bl"}, {"letter_cl"}, {"letter_dl"}, {"letter_el"}, {"letter_fl"}, {"letter_gl"}, {"letter_hl"}, {"letter_il"}, {"letter_jl"}, {"letter_kl"}, {"letter_ll"}, {"letter_ml"}, {"letter_nl"}, {"letter_ol"}, {"letter_pl"}, {"letter_ql"}, {"letter_rl"}, {"letter_sl"}, {"letter_tl"}, {"letter_ul"}, {"letter_vl"}, {"letter_wl"}, {"letter_xl"}, {"letter_yl"}, {"letter_zl"}, } letter_cutter.names_upper = { {"letter_au"}, {"letter_bu"}, {"letter_cu"}, {"letter_du"}, {"letter_eu"}, {"letter_fu"}, {"letter_gu"}, {"letter_hu"}, {"letter_iu"}, {"letter_ju"}, {"letter_ku"}, {"letter_lu"}, {"letter_mu"}, {"letter_nu"}, {"letter_ou"}, {"letter_pu"}, {"letter_qu"}, {"letter_ru"}, {"letter_su"}, {"letter_tu"}, {"letter_uu"}, {"letter_vu"}, {"letter_wu"}, {"letter_xu"}, {"letter_yu"}, {"letter_zu"}, } function letter_cutter:get_output_inv_lower(modname, subname, amount, max) local list = {} if amount < 1 then return list end for i, t in ipairs(letter_cutter.names_lower) do table.insert(list, modname .. ":" .. subname .. "_" .. t[1] .. " " .. math.min(math.floor(amount/cost), max)) end return list end function letter_cutter:get_output_inv_upper(modname, subname, amount, max) local list = {} if amount < 1 then return list end for i, t in ipairs(letter_cutter.names_upper) do table.insert(list, modname .. ":" .. subname .. "_" .. t[1] .. " " .. math.min(math.floor(amount/cost), max)) end return list end function letter_cutter:reset_lower(pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() inv:set_list("input", {}) inv:set_list("output", {}) meta:set_int("anz", 0) meta:set_string("infotext", "Letter Cutter (Lower) is empty (owned by ".. meta:get_string("owner")..")") end function letter_cutter:reset_upper(pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() inv:set_list("input", {}) inv:set_list("output", {}) meta:set_int("anz", 0) meta:set_string("infotext", "Letter Cutter (Upper) is empty (owned by ".. meta:get_string("owner")..")") end function letter_cutter:update_inventory_lower(pos, amount) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() amount = meta:get_int("anz") + amount if amount < 1 then -- If the last block is taken out. self:reset_lower(pos) return end local stack = inv:get_stack("input", 1) if stack:is_empty() then self:reset_lower(pos) return end local node_name = stack:get_name() or "" local name_parts = letter_cutter.known_nodes[node_name] or "" local modname = name_parts[1] or "" local material = name_parts[2] or "" inv:set_list("input", { node_name.. " " .. math.floor(amount) }) -- Display: inv:set_list("output", self:get_output_inv_lower(modname, material, amount, meta:get_int("max_offered"))) -- Store how many microblocks are available: meta:set_int("anz", amount) meta:set_string("infotext", "Letter Cutter (Lower) is working (owned by ".. meta:get_string("owner")..")") end function letter_cutter:update_inventory_upper(pos, amount) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() amount = meta:get_int("anz") + amount if amount < 1 then -- If the last block is taken out. self:reset_upper(pos) return end local stack = inv:get_stack("input", 1) if stack:is_empty() then self:reset_upper(pos) return end local node_name = stack:get_name() or "" local name_parts = letter_cutter.known_nodes[node_name] or "" local modname = name_parts[1] or "" local material = name_parts[2] or "" inv:set_list("input", { node_name.. " " .. math.floor(amount) }) -- Display: inv:set_list("output", self:get_output_inv_upper(modname, material, amount, meta:get_int("max_offered"))) -- Store how many microblocks are available: meta:set_int("anz", amount) meta:set_string("infotext", "Letter Cutter (Upper) is working (owned by ".. meta:get_string("owner")..")") end function letter_cutter.allow_metadata_inventory_move( pos, from_list, from_index, to_list, to_index, count, player) return 0 end -- Only input- and recycle-slot are intended as input slots: function letter_cutter.allow_metadata_inventory_put( pos, listname, index, stack, player) -- The player is not allowed to put something in there: if listname == "output" then return 0 end local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local stackname = stack:get_name() local count = stack:get_count() -- Only accept certain blocks as input which are known to be craftable into stairs: if listname == "input" then if not inv:is_empty("input") and inv:get_stack("input", index):get_name() ~= stackname then return 0 end for name, t in pairs(letter_cutter.known_nodes) do if name == stackname and inv:room_for_item("input", stack) then return count end end return 0 end end function letter_cutter.on_metadata_inventory_put_lower( pos, listname, index, stack, player) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local stackname = stack:get_name() local count = stack:get_count() if listname == "input" then letter_cutter:update_inventory_lower(pos, count) end end function letter_cutter.on_metadata_inventory_put_upper( pos, listname, index, stack, player) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local stackname = stack:get_name() local count = stack:get_count() if listname == "input" then letter_cutter:update_inventory_upper(pos, count) end end function letter_cutter.on_metadata_inventory_take_lower( pos, listname, index, stack, player) if listname == "output" then -- We do know how much each block at each position costs: letter_cutter:update_inventory_lower(pos, 8 * -cost) elseif listname == "input" then -- Each normal (= full) block taken costs 8 microblocks: letter_cutter:update_inventory_lower(pos, 8 * -stack:get_count()) end -- The recycle field plays no role here since it is processed immediately. end function letter_cutter.on_metadata_inventory_take_upper( pos, listname, index, stack, player) if listname == "output" then -- We do know how much each block at each position costs: letter_cutter:update_inventory_upper(pos, 8 * -cost) elseif listname == "input" then -- Each normal (= full) block taken costs 8 microblocks: letter_cutter:update_inventory_upper(pos, 8 * -stack:get_count()) end -- The recycle field plays no role here since it is processed immediately. end function letter_cutter.remove_from_input(pos, origname, count) local node = minetest.get_node(pos) local meta = minetest.get_meta(pos) local cutterinv = meta:get_inventory() local removed = cutterinv:remove_item("input", origname .. " " .. tostring(count)) if node.name == "letters:letter_cutter_upper" then letter_cutter:update_inventory_upper(pos, -removed:get_count()) else letter_cutter:update_inventory_lower(pos, -removed:get_count()) end end gui_slots = "listcolors[#606060AA;#808080;#101010;#202020;#FFF]" local function update_cutter_formspec(pos) local meta = minetest.get_meta(pos) meta:set_string("formspec", "size[11,9]" ..gui_slots.. "label[0,0;Input\nmaterial]" .. "list[current_name;input;1.5,0;1,1;]" .. "list[current_name;output;2.8,0;8,4;]" .. "button[0,1;2.5,1;itemlist;Cuttable materials]" .. "list[current_player;main;1.5,5;8,4;]" .. "field[0.5,4.3;3,1;text;Enter text;${text}]" .. "button[3.5,4;2,1;make_text;Make text]" .. "label[5.5,4.2;" .. minetest.formspec_escape(meta:get_string("message")) .. "]") end local function cut_from_text(pos, input_text, player) local playername = player:get_player_name() local node = minetest.get_node(pos) local meta = minetest.get_meta(pos) local cutterinv = meta:get_inventory() local cutterinput = cutterinv:get_list("input") local cuttercount = cutterinput[1]:get_count() if cuttercount < 1 then meta:set_string("message", "No materials.") update_cutter_formspec(pos) return end local origname = cutterinput[1]:get_name() local playerinv = player:get_inventory() local playermain = playerinv:get_list("main") meta:set_string("text", input_text) local totalcost = 0 local throwawayinv = minetest.create_detached_inventory("letter_cutter:throwaway", {}, playername) throwawayinv:set_size("main", playerinv:get_size("main")) throwawayinv:set_list("main", playerinv:get_list("main")) for i = 1, #input_text do local char = input_text:sub(i, i) if char:match("[%u%l]") then local isupper = char == char:upper() local charset = isupper and letter_cutter.names_upper or letter_cutter.names_lower local lettername = origname .. "_" .. charset[letters_reversed[char:lower()]][1] if cuttercount < totalcost + cost then meta:set_string("message", "Not enough materials.") update_cutter_formspec(pos) minetest.remove_detached_inventory("letter_cutter:throwaway") return end if lettername and not throwawayinv:room_for_item("main", lettername) then meta:set_string("message", "Not enough room.") update_cutter_formspec(pos) minetest.remove_detached_inventory("letter_cutter:throwaway") return end totalcost = totalcost + cost throwawayinv:add_item("main", lettername) end end meta:set_string("message", "Successfully added letters to inventory.") update_cutter_formspec(pos) letter_cutter.remove_from_input(pos, origname, tostring(math.ceil(totalcost))) playerinv:set_list("main", throwawayinv:get_list("main")) minetest.remove_detached_inventory("letter_cutter:throwaway") end function letter_cutter.on_construct_lower(pos) local meta = minetest.get_meta(pos) update_cutter_formspec(pos) meta:set_int("anz", 0) -- No microblocks inside yet. meta:set_string("max_offered", 9) -- How many items of this kind are offered by default? meta:set_string("infotext", "Letter Cutter (Lower) is empty") meta:set_string("text", "") meta:set_string("message", "") local inv = meta:get_inventory() inv:set_size("input", 1) -- Input slot for full blocks of material x. inv:set_size("output", 4*8) -- 4x8 versions of stair-parts of material x. letter_cutter:reset_lower(pos) end function letter_cutter.on_construct_upper(pos) local meta = minetest.get_meta(pos) update_cutter_formspec(pos) meta:set_int("anz", 0) -- No microblocks inside yet. meta:set_string("max_offered", 9) -- How many items of this kind are offered by default? meta:set_string("infotext", "Letter Cutter (Upper) is empty") meta:set_string("text", "") meta:set_string("message", "") local inv = meta:get_inventory() inv:set_size("input", 1) -- Input slot for full blocks of material x. inv:set_size("output", 4*8) -- 4x8 versions of stair-parts of material x. letter_cutter:reset_upper(pos) end function letter_cutter.can_dig(pos,player) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() if not inv:is_empty("input") then return false end return true end function letter_cutter.on_receive_fields(pos, formname, fields, sender) if fields.itemlist then local list = {} for name, t in pairs(letter_cutter.known_nodes) do list[#list+1] = name end letter_cutter.show_item_list(sender, 'Cuttable materials', list, pos) return end if fields.make_text and fields.text then cut_from_text(pos, fields.text, sender) return end end minetest.register_node("letters:letter_cutter_lower", { description = "Lower Case Leter Cutter", drawtype = "nodebox", node_box = { type = "fixed", fixed = { {-0.4375, -0.5, -0.4375, -0.3125, 0.125, -0.3125}, -- NodeBox1 {-0.4375, -0.5, 0.3125, -0.3125, 0.125, 0.4375}, -- NodeBox2 {0.3125, -0.5, 0.3125, 0.4375, 0.125, 0.4375}, -- NodeBox3 {0.3125, -0.5, -0.4375, 0.4375, 0.125, -0.3125}, -- NodeBox4 {-0.5, 0.0625, -0.5, 0.5, 0.25, 0.5}, -- NodeBox5 {-0.125, 0.25, 0.125, 0.125, 0.3125, 0.1875}, -- NodeBox6 {0.125, 0.25, 0.0625, 0.1875, 0.3125, 0.125}, -- NodeBox7 {0.1875, 0.25, -0.1875, 0.25, 0.3125, 0.1875}, -- NodeBox8 {-0.1875, 0.25, 0.0625, -0.125, 0.3125, 0.125}, -- NodeBox9 {-0.25, 0.25, -0.1875, -0.1875, 0.3125, 0.0625}, -- NodeBox10 {-0.1875, 0.25, -0.25, -0.125, 0.3125, -0.1875}, -- NodeBox11 {-0.125, 0.25, -0.3125, 0.125, 0.3125, -0.25}, -- NodeBox12 {0.125, 0.25, -0.25, 0.375, 0.3125, -0.1875}, -- NodeBox13 {0.3125, 0.25, -0.1875, 0.375, 0.3125, -0.125}, -- NodeBox14 }, }, tiles = {"letters_letter_cutter_lower_top.png", "default_tree.png", "letters_letter_cutter_side.png"}, paramtype = "light", sunlight_propagates = true, paramtype2 = "facedir", groups = {choppy = 2,oddly_breakable_by_hand = 2}, sounds = default.node_sound_wood_defaults(), on_construct = letter_cutter.on_construct_lower, can_dig = letter_cutter.can_dig, -- Set the owner of this circular saw. after_place_node = function(pos, placer) local meta = minetest.get_meta(pos) local owner = placer and placer:get_player_name() or "" meta:set_string("owner", owner) meta:set_string("infotext", "Letter Cutter (Lower) is empty (owned by " ..meta:get_string("owner")..")") end, allow_metadata_inventory_move = letter_cutter.allow_metadata_inventory_move, -- Only input- and recycle-slot are intended as input slots: allow_metadata_inventory_put = letter_cutter.allow_metadata_inventory_put, -- Taking is allowed from all slots (even the internal microblock slot). Moving is forbidden. -- Putting something in is slightly more complicated than taking anything because we have to make sure it is of a suitable material: on_metadata_inventory_put = letter_cutter.on_metadata_inventory_put_lower, on_metadata_inventory_take = letter_cutter.on_metadata_inventory_take_lower, on_receive_fields = letter_cutter.on_receive_fields, }) minetest.register_craft({ output = "letters:letter_cutter_lower", recipe = { {"default:tree", "default:tree", "default:tree"}, {"default:wood", "default:steel_ingot", "default:wood"}, {"default:tree", "", "default:tree"}, }, }) minetest.register_node("letters:letter_cutter_upper", { description = "Upper Case Leter Cutter", drawtype = "nodebox", node_box = { type = "fixed", fixed = { {-0.4375, -0.5, -0.4375, -0.3125, 0.125, -0.3125}, -- NodeBox1 {-0.4375, -0.5, 0.3125, -0.3125, 0.125, 0.4375}, -- NodeBox2 {0.3125, -0.5, 0.3125, 0.4375, 0.125, 0.4375}, -- NodeBox3 {0.3125, -0.5, -0.4375, 0.4375, 0.125, -0.3125}, -- NodeBox4 {-0.5, 0.0625, -0.5, 0.5, 0.25, 0.5}, -- NodeBox5 {0.1875, 0.25, -0.125, 0.125, 0.3125, -0.3125}, -- NodeBox6 {0.125, 0.25, 0.125, 0.0625, 0.3125, -0.125}, -- NodeBox7 {0.0625, 0.25, 0.3125, -0.0625, 0.3125, 0.0625}, -- NodeBox8 {-0.0625, 0.25, 0.125, -0.125, 0.3125, -0.125}, -- NodeBox9 {-0.125, 0.25, -0.125, -0.1875, 0.3125, -0.3125}, -- NodeBox10 {0.125, 0.25, -0.125, -0.125, 0.3125, -0.1875}, -- NodeBox11 }, }, tiles = {"letters_letter_cutter_upper_top.png", "default_tree.png", "letters_letter_cutter_side.png"}, paramtype = "light", sunlight_propagates = true, paramtype2 = "facedir", groups = {choppy = 2,oddly_breakable_by_hand = 2}, sounds = default.node_sound_wood_defaults(), on_construct = letter_cutter.on_construct_upper, can_dig = letter_cutter.can_dig, -- Set the owner of this circular saw. after_place_node = function(pos, placer) local meta = minetest.get_meta(pos) local owner = placer and placer:get_player_name() or "" meta:set_string("owner", owner) meta:set_string("infotext", "Letter Cutter (Upper) is empty (owned by " ..meta:get_string("owner")..")") end, allow_metadata_inventory_move = letter_cutter.allow_metadata_inventory_move, -- Only input- and recycle-slot are intended as input slots: allow_metadata_inventory_put = letter_cutter.allow_metadata_inventory_put, -- Taking is allowed from all slots (even the internal microblock slot). Moving is forbidden. -- Putting something in is slightly more complicated than taking anything because we have to make sure it is of a suitable material: on_metadata_inventory_put = letter_cutter.on_metadata_inventory_put_upper, on_metadata_inventory_take = letter_cutter.on_metadata_inventory_take_upper, on_receive_fields = letter_cutter.on_receive_fields, }) minetest.register_craft({ output = "letters:letter_cutter_upper", recipe = { {"default:tree", "default:tree", "default:tree"}, {"default:wood", "default:steel_ingot", "default:wood"}, {"default:tree", "default:steel_ingot", "default:tree"}, }, }) dofile(minetest.get_modpath("letters").."/registrations.lua")