diff --git a/basic_machines/autocrafter.lua b/basic_machines/autocrafter.lua new file mode 100644 index 0000000..e357030 --- /dev/null +++ b/basic_machines/autocrafter.lua @@ -0,0 +1,415 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + The autocrafter is derived from pipeworks: + Copyright (C) 2004 Sam Hocevar WTFPL + + TA2/TA3/TA4 Autocrafter + +]]-- + +-- for lazy programmers +local S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local P = minetest.string_to_pos +local M = minetest.get_meta +-- Techage Related Data +local TRD = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).techage end + +-- Load support for intllib. +local MP = minetest.get_modpath("techage") +local I,_ = dofile(MP.."/intllib.lua") + +local STANDBY_TICKS = 10 +local COUNTDOWN_TICKS = 10 +local CYCLE_TIME = 4 + +local function formspec(self, pos, mem) + return "size[8,9.2]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;recipe;0,0;3,3;]".. + "image[2.9,1;1,1;techage_form_arrow.png]".. + "image[3.8,0;1,1;"..techage.get_power_image(pos, mem).."]".. + "list[context;output;3.8,1;1,1;]".. + "image_button[3.8,2;1,1;".. self:get_state_button_image(mem) ..";state_button;]".. + "list[context;src;0,3.2;8,2;]".. + "list[context;dst;5,0;3,3;]".. + "list[current_player;main;0,5.4;8,4;]" .. + "listring[current_player;main]".. + "listring[context;src]" .. + "listring[current_player;main]".. + "listring[context;dst]" .. + "listring[current_player;main]".. + default.get_hotbar_bg(0, 4) +end + +local function count_index(invlist) + local index = {} + for _, stack in pairs(invlist) do + if not stack:is_empty() then + local stack_name = stack:get_name() + index[stack_name] = (index[stack_name] or 0) + stack:get_count() + end + end + return index +end + +-- caches some recipe data +local autocrafterCache = {} + +local function get_craft(pos, inventory, hash) + hash = hash or minetest.hash_node_position(pos) + local craft = autocrafterCache[hash] + if not craft then + local recipe = inventory:get_list("recipe") + local output, decremented_input = minetest.get_craft_result( + {method = "normal", width = 3, items = recipe}) + craft = {recipe = recipe, consumption=count_index(recipe), + output = output, decremented_input = decremented_input} + autocrafterCache[hash] = craft + end + return craft +end + +local function autocraft(pos, trd, mem, inventory, craft) + if not craft then return false end + local output_item = craft.output.item + + -- check if we have enough room in dst + if not inventory:room_for_item("dst", output_item) then + trd.State:blocked(pos, mem) + return + end + local consumption = craft.consumption + local inv_index = count_index(inventory:get_list("src")) + -- check if we have enough material available + for itemname, number in pairs(consumption) do + if (not inv_index[itemname]) or inv_index[itemname] < number then + trd.State:idle(pos, mem) + return + end + end + -- consume material + for itemname, number in pairs(consumption) do + for i = 1, number do -- We have to do that since remove_item does not work if count > stack_max + inventory:remove_item("src", ItemStack(itemname)) + end + end + + -- craft the result into the dst inventory and add any "replacements" as well + inventory:add_item("dst", output_item) + for i = 1, 9 do + inventory:add_item("dst", craft.decremented_input.items[i]) + end + + trd.State:keep_running(pos, mem, COUNTDOWN_TICKS) +end + + +local function keep_running(pos, elapsed) + local mem = tubelib2.get_mem(pos) + local trd = TRD(pos) + local inv = M(pos):get_inventory() + local craft = get_craft(pos, inv) + local output_item = craft.output.item + autocraft(pos, trd, mem, inv, craft) + return trd.State:is_active(mem) +end + +-- note, that this function assumes allready being updated to virtual items +-- and doesn't handle recipes with stacksizes > 1 +local function after_recipe_change(pos, inventory) + local mem = tubelib2.get_mem(pos) + local trd = TRD(pos) + -- if we emptied the grid, there's no point in keeping it running or cached + if inventory:is_empty("recipe") then + autocrafterCache[minetest.hash_node_position(pos)] = nil + inventory:set_stack("output", 1, "") + trd.State:stop(pos, mem) + return + end + local recipe = inventory:get_list("recipe") + + local hash = minetest.hash_node_position(pos) + local craft = autocrafterCache[hash] + + if craft then + -- check if it changed + local cached_recipe = craft.recipe + for i = 1, 9 do + if recipe[i]:get_name() ~= cached_recipe[i]:get_name() then + autocrafterCache[hash] = nil -- invalidate recipe + craft = nil + break + end + end + end + + craft = craft or get_craft(pos, inventory, hash) + local output_item = craft.output.item + inventory:set_stack("output", 1, output_item) + trd.State:stop(pos, mem) +end + +-- clean out unknown items and groups, which would be handled like unknown items in the crafting grid +-- if minetest supports query by group one day, this might replace them +-- with a canonical version instead +local function normalize(item_list) + for i = 1, #item_list do + local name = item_list[i] + if not minetest.registered_items[name] then + item_list[i] = "" + end + end + return item_list +end + +local function on_output_change(pos, inventory, stack) + if not stack then + inventory:set_list("output", {}) + inventory:set_list("recipe", {}) + else + local input = minetest.get_craft_recipe(stack:get_name()) + if not input.items or input.type ~= "normal" then return end + local items, width = normalize(input.items), input.width + local item_idx, width_idx = 1, 1 + for i = 1, 9 do + if width_idx <= width then + inventory:set_stack("recipe", i, items[item_idx]) + item_idx = item_idx + 1 + else + inventory:set_stack("recipe", i, ItemStack("")) + end + width_idx = (width_idx < 3) and (width_idx + 1) or 1 + end + -- we'll set the output slot in after_recipe_change to the actual result of the new recipe + end + after_recipe_change(pos, inventory) +end + + +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + local inv = minetest.get_meta(pos):get_inventory() + local trd = TRD(pos) + if listname == "recipe" then + stack:set_count(1) + inv:set_stack(listname, index, stack) + after_recipe_change(pos, inv) + return 0 + elseif listname == "output" then + on_output_change(pos, inv, stack) + return 0 + elseif listname == "src" and trd.State:get_state(M(pos)) == techage.STANDBY then + trd.State:start(pos, M(pos)) + end + return stack:get_count() +end + +local function allow_metadata_inventory_take(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end +-- upgrade_autocrafter(pos) + local inv = minetest.get_meta(pos):get_inventory() + if listname == "recipe" then + inv:set_stack(listname, index, ItemStack("")) + after_recipe_change(pos, inv) + return 0 + elseif listname == "output" then + on_output_change(pos, inv, nil) + return 0 + end + return stack:get_count() +end + +local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + local inv = minetest.get_meta(pos):get_inventory() + local stack = inv:get_stack(from_list, from_index) + + if to_list == "output" then + on_output_change(pos, inv, stack) + return 0 + elseif from_list == "output" then + on_output_change(pos, inv, nil) + if to_list ~= "recipe" then + return 0 + end -- else fall through to recipe list handling + end + + if from_list == "recipe" or to_list == "recipe" then + if from_list == "recipe" then + inv:set_stack(from_list, from_index, ItemStack("")) + end + if to_list == "recipe" then + stack:set_count(1) + inv:set_stack(to_list, to_index, stack) + end + after_recipe_change(pos, inv) + return 0 + end + + return count +end + +local function on_receive_fields(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + local mem = tubelib2.get_mem(pos) + TRD(pos).State:state_button_event(pos, mem, fields) +end + +local function can_dig(pos, player) + if minetest.is_protected(pos, player:get_player_name()) then + return false + end + local inv = M(pos):get_inventory() + return inv:is_empty("dst") and inv:is_empty("src") +end + +local tiles = {} +-- '#' will be replaced by the stage number +-- '{power}' will be replaced by the power PNG +tiles.pas = { + -- up, down, right, left, back, front + "techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#_top.png", + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png", + "techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#.png", +} +tiles.act = { + -- up, down, right, left, back, front + { + image = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#_top.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.5, + }, + }, + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png", + { + image = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.5, + }, + }, + { + image = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.5, + }, + }, +} +tiles.def = { + -- up, down, right, left, back, front + "techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#_top.png", + "techage_filling_ta#.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png^techage_appl_defect.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png^techage_appl_defect.png", + "techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#.png^techage_appl_defect.png", + "techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#.png^techage_appl_defect.png", +} + +local tubing = { + on_pull_item = function(pos, in_dir, num) + local meta = minetest.get_meta(pos) + if meta:get_int("pull_dir") == in_dir then + local inv = M(pos):get_inventory() + return techage.get_items(inv, "dst", num) + end + end, + on_push_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + if meta:get_int("push_dir") == in_dir or in_dir == 5 then + local inv = M(pos):get_inventory() + return techage.put_items(inv, "src", stack) + end + end, + on_unpull_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + if meta:get_int("pull_dir") == in_dir then + local inv = M(pos):get_inventory() + return techage.put_items(inv, "dst", stack) + end + end, + on_recv_message = function(pos, topic, payload) + local resp = TRD(pos).State:on_receive_message(pos, topic, payload) + if resp then + return resp + else + return "unsupported" + end + end, + on_node_load = function(pos) + TRD(pos).State:on_node_load(pos) + end, + on_node_repair = function(pos) + return TRD(pos).State:on_node_repair(pos) + end, +} + +local node_name_ta2, node_name_ta3, node_name_ta4 = + techage.register_consumer("autocrafter", I("Autocrafter"), tiles, { + drawtype = "normal", + cycle_time = CYCLE_TIME, + standby_ticks = STANDBY_TICKS, + has_item_meter = true, + aging_factor = 10, + formspec = formspec, + tubing = tubing, + after_place_node = function(pos, placer) + local inv = M(pos):get_inventory() + inv:set_size("src", 2*8) + inv:set_size("recipe", 3*3) + inv:set_size("dst", 3*3) + inv:set_size("output", 1) + end, + can_dig = can_dig, + node_timer = keep_running, + on_receive_fields = on_receive_fields, + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, + groups = {choppy=2, cracky=2, crumbly=2}, + sounds = default.node_sound_wood_defaults(), + num_items = {0,1,2,4}, + power_consumption = {0,2,3,4}, + }) + +minetest.register_craft({ + output = node_name_ta2, + recipe = { + {"group:wood", "default:diamond", "group:wood"}, + {"techage:tubeS", "basic_materials:gear_steel", "techage:tubeS"}, + {"group:wood", "techage:iron_ingot", "group:wood"}, + }, +}) diff --git a/basic_machines/basalt.lua b/basic_machines/basalt.lua new file mode 100644 index 0000000..f61c5a4 --- /dev/null +++ b/basic_machines/basalt.lua @@ -0,0 +1,85 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + Basalt as result from the lava/water generator + +]]-- + + +-- Replace default:stone with techage:basalt which is less valuable for ore generation. +default.cool_lava = function(pos, node) + if node.name == "default:lava_source" then + minetest.set_node(pos, {name = "default:obsidian"}) + else -- Lava flowing + minetest.set_node(pos, {name = "techage:basalt_stone"}) + end + minetest.sound_play("default_cool_lava", + {pos = pos, max_hear_distance = 16, gain = 0.25}) +end + +minetest.register_node("techage:basalt_stone", { + description = "Basalt Stone", + tiles = {"default_stone.png^[brighten"}, + groups = {cracky = 3, stone = 1}, + drop = "default:silver_sand", + sounds = default.node_sound_stone_defaults(), +}) +minetest.register_node("techage:basalt_stone_brick", { + description = "Basalt Stone Brick", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_stone_brick.png^[brighten"}, + is_ground_content = false, + groups = {cracky = 2, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("techage:basalt_stone_block", { + description = "Basalt Stone Block", + tiles = {"default_stone_block.png^[brighten"}, + is_ground_content = false, + groups = {cracky = 2, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("techage:basalt_gravel", { + description = "Basalt Gravel", + tiles = {"default_gravel.png^[brighten"}, + groups = {crumbly = 2, falling_node = 1}, + sounds = default.node_sound_gravel_defaults(), +}) + +minetest.register_node("techage:sieved_basalt_gravel", { + description = "Sieved Basalt Gravel", + tiles = {"default_gravel.png^[brighten"}, + groups = {crumbly = 2, falling_node = 1, not_in_creative_inventory=1}, + sounds = default.node_sound_gravel_defaults(), +}) + +minetest.register_craft({ + output = "techage:basalt_stone_brick 4", + recipe = { + {"techage:basalt_stone", "techage:basalt_stone"}, + {"techage:basalt_stone", "techage:basalt_stone"}, + } +}) + +minetest.register_craft({ + output = "techage:basalt_stone_block 9", + recipe = { + {"techage:basalt_stone", "techage:basalt_stone", "techage:basalt_stone"}, + {"techage:basalt_stone", "techage:basalt_stone", "techage:basalt_stone"}, + {"techage:basalt_stone", "techage:basalt_stone", "techage:basalt_stone"}, + } +}) + +techage.add_grinder_recipe({input="techage:basalt_stone", output="techage:basalt_gravel"}) +techage.add_grinder_recipe({input="techage:basalt_gravel", output="default:clay"}) +techage.add_grinder_recipe({input="techage:sieved_basalt_gravel", output="default:clay"}) diff --git a/basic_machines/blackhole.lua b/basic_machines/blackhole.lua new file mode 100644 index 0000000..f99fff2 --- /dev/null +++ b/basic_machines/blackhole.lua @@ -0,0 +1,65 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + The autocrafter is derived from pipeworks: + Copyright (C) 2004 Sam Hocevar WTFPL + + All items disappear. + +]]-- + +minetest.register_node("techage:blackhole", { + description = "Techage Black Hole", + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3.png", + "techage_filling_ta3.png^techage_frame_ta3.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_blackhole.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_blackhole.png^techage_appl_inp.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_blackhole.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_blackhole.png", + }, + + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + local node = minetest.get_node(pos) + meta:set_int("push_dir", techage.side_to_indir("L", node.param2)) + meta:set_string("infotext","Techage Black Hole (let items disappear)") + end, + + on_rotate = screwdriver.disallow, + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), +}) + + + +minetest.register_craft({ + output = "techage:blackhole", + recipe = { + {"group:wood", "", "group:wood"}, + {"tubelib:tubeS", "default:coal_lump", ""}, + {"group:wood", "", "group:wood"}, + }, +}) + +techage.register_node("techage:blackhole", {}, { + on_pull_item = nil, -- not needed + on_unpull_item = nil, -- not needed + + on_push_item = function(pos, in_dir, stack) + local meta = minetest.get_meta(pos) + if meta:get_int("push_dir") == in_dir then + return true + end + end, +}) diff --git a/basic_machines/forceload.lua b/basic_machines/forceload.lua new file mode 100644 index 0000000..0f214bb --- /dev/null +++ b/basic_machines/forceload.lua @@ -0,0 +1,218 @@ +--[[ + + Tube Library + ============ + + Copyright (C) 2017-2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + forceload.lua: + +]]-- + +-- for lazy programmers +local S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local P = minetest.string_to_pos +local M = minetest.get_meta + +local function calc_area(pos) + local xpos = (math.floor(pos.x / 16) * 16) + local ypos = (math.floor(pos.y / 16) * 16) + local zpos = (math.floor(pos.z / 16) * 16) + local pos1 = {x=xpos, y=ypos, z=zpos} + local pos2 = {x=xpos+15, y=ypos+15, z=zpos+15} + return pos1, pos2 +end + +local function in_list(list, x) + local pos1 = calc_area(x) + for _,v in ipairs(list) do + local pos2 = calc_area(v) + if vector.equals(pos1, pos2) then return true end + end + return false +end + +local function remove_list_elem(list, x) + local n = nil + for idx, v in ipairs(list) do + if vector.equals(v, x) then + n = idx + break + end + end + if n then + table.remove(list, n) + end + return list +end + +local function chat(player, text) + minetest.chat_send_player(player:get_player_name(), "[Tubelib] "..text) +end + +local function get_node_lvm(pos) + local node = minetest.get_node_or_nil(pos) + if node then + return node + end + local vm = minetest.get_voxel_manip() + local MinEdge, MaxEdge = vm:read_from_map(pos, pos) + local data = vm:get_data() + local param2_data = vm:get_param2_data() + local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge}) + local idx = area:index(pos.x, pos.y, pos.z) + node = { + name = minetest.get_name_from_content_id(data[idx]), + param2 = param2_data[idx] + } + return node +end + +local function add_pos(pos, player) + local lPos = minetest.deserialize(player:get_attribute("tubelib_forceload_blocks")) or {} + if not in_list(lPos, pos) and #lPos < tubelib.max_num_forceload_blocks then + lPos[#lPos+1] = pos + player:set_attribute("tubelib_forceload_blocks", minetest.serialize(lPos)) + return true + end + return false +end + +local function del_pos(pos, player) + local lPos = minetest.deserialize(player:get_attribute("tubelib_forceload_blocks")) or {} + lPos = remove_list_elem(lPos, pos) + player:set_attribute("tubelib_forceload_blocks", minetest.serialize(lPos)) +end + +local function get_pos_list(player) + return minetest.deserialize(player:get_attribute("tubelib_forceload_blocks")) or {} +end + +local function set_pos_list(player, lPos) + player:set_attribute("tubelib_forceload_blocks", minetest.serialize(lPos)) +end + +local function get_data(pos, player) + local pos1, pos2 = calc_area(pos) + local num = #minetest.deserialize(player:get_attribute("tubelib_forceload_blocks")) or 0 + local max = tubelib.max_num_forceload_blocks + return pos1, pos2, num, max +end + +local function formspec(player) + local lPos = get_pos_list(player) + local tRes = {} + tRes[1] = "size[7,9]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "label[0,0;List of your Forceload Blocks:]" + + for idx,pos in ipairs(lPos) do + local pos1, pos2 = calc_area(pos) + local ypos = 0.2 + idx * 0.4 + tRes[#tRes+1] = "label[0,"..ypos..";"..idx.."]" + tRes[#tRes+1] = "label[0.8,"..ypos..";"..S(pos1).."]" + tRes[#tRes+1] = "label[3.2,"..ypos..";to]" + tRes[#tRes+1] = "label[4,"..ypos..";"..S(pos2).."]" + end + return table.concat(tRes) +end + + +minetest.register_node("tubelib:forceload", { + description = "Tubelib Forceload Block", + tiles = { + -- up, down, right, left, back, front + 'tubelib_front.png', + 'tubelib_front.png', + { + image = "tubelib_forceload.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.5, + }, + }, + }, + + after_place_node = function(pos, placer, itemstack) + if add_pos(pos, placer) then + minetest.forceload_block(pos, true) + local pos1, pos2, num, max = get_data(pos, placer) + M(pos):set_string("infotext", "Area "..S(pos1).." to "..S(pos2).." loaded!\n".. + "Punch the block to make the area visible.") + chat(placer, "Area ("..num.."/"..max..") "..S(pos1).." to "..S(pos2).." loaded!") + tubelib.mark_region(placer:get_player_name(), pos1, pos2) + M(pos):set_string("owner", placer:get_player_name()) + else + chat(placer, "Area already loaded or max. number of Forceload Blocks reached!") + minetest.remove_node(pos) + return itemstack + end + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + local player = minetest.get_player_by_name(oldmetadata.fields.owner) + if player then + del_pos(pos, player) + end + minetest.forceload_free_block(pos, true) + tubelib.unmark_region(oldmetadata.fields.owner) + end, + + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if M(pos):get_string("owner") == clicker:get_player_name() or + minetest.check_player_privs(clicker:get_player_name(), "server") then + local s = formspec(clicker) + minetest.show_formspec(clicker:get_player_name(), "tubelib:forceload", s) + end + end, + + on_punch = function(pos, node, puncher, pointed_thing) + local pos1, pos2 = calc_area(pos) + tubelib.switch_region(puncher:get_player_name(), pos1, pos2) + end, + + paramtype = "light", + sunlight_propagates = true, + groups = {choppy=2, cracky=2, crumbly=2, + not_in_creative_inventory = tubelib.max_num_forceload_blocks == 0 and 1 or 0}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), +}) + + +if tubelib.max_num_forceload_blocks > 0 then + minetest.register_craft({ + output = "tubelib:forceload", + recipe = { + {"group:wood", "", "group:wood"}, + {"", "basic_materials:energy_crystal_simple", ""}, + {"group:wood", "tubelib:wlanchip", "group:wood"}, + }, + }) +end + +minetest.register_on_joinplayer(function(player) + local lPos = {} + for _,pos in ipairs(get_pos_list(player)) do + local node = get_node_lvm(pos) + if node.name == "tubelib:forceload" then + minetest.forceload_block(pos, true) + lPos[#lPos+1] = pos + end + end + set_pos_list(player, lPos) +end) + +minetest.register_on_leaveplayer(function(player) + for _,pos in ipairs(get_pos_list(player)) do + minetest.forceload_free_block(pos, true) + end +end) diff --git a/basic_machines/gravelsieve.lua b/basic_machines/gravelsieve.lua index c6db90b..cb57faa 100644 --- a/basic_machines/gravelsieve.lua +++ b/basic_machines/gravelsieve.lua @@ -76,41 +76,47 @@ end -- determine ore based on the calculated probability -local function get_random_ore() +local function get_random_gravel_ore() for ore, probability in pairs(techage.ore_probability) do if math.random(probability) == 1 then - local item = ItemStack(ore) - return item + return ItemStack(ore) end end + if math.random(2) == 1 then + return ItemStack("default:gravel") + else + return ItemStack("techage:sieved_gravel") + end +end + +local function get_random_basalt_ore() + if math.random(40) == 1 then + return ItemStack("default:coal_lump") + elseif math.random(40) == 1 then + return ItemStack("default:iron_lump") + elseif math.random(2) == 1 then + return ItemStack("techage:basalt_gravel") + else + return ItemStack("techage:sieved_basalt_gravel") + end end local function sieving(pos, trd, mem, inv) - local gravel = ItemStack("default:gravel") - - if not inv:contains_item("src", gravel) then + local src, dst + if inv:contains_item("src", ItemStack("techage:basalt_gravel")) then + dst, src = get_random_basalt_ore(), ItemStack("techage:basalt_gravel") + elseif inv:contains_item("src", ItemStack("default:gravel")) then + dst, src = get_random_gravel_ore(), ItemStack("default:gravel") + else trd.State:idle(pos, mem) return end - - local dst = get_random_ore() - if not dst then - -- move gravel or sieved gravel to dst - mem.gravel_cnt = (mem.gravel_cnt or 0) + 1 - if (mem.gravel_cnt % 2) == 0 then - dst = gravel - else - dst = ItemStack("techage:sieved_gravel") - end - end if not inv:room_for_item("dst", dst) then - --trd.State:blocked(pos, mem) trd.State:idle(pos, mem) return end - inv:add_item("dst", dst) - inv:remove_item("src", gravel) + inv:remove_item("src", src) trd.State:keep_running(pos, mem, COUNTDOWN_TICKS) end diff --git a/basic_machines/grinder.lua b/basic_machines/grinder.lua index bd6a496..7854256 100644 --- a/basic_machines/grinder.lua +++ b/basic_machines/grinder.lua @@ -283,9 +283,8 @@ techage.add_grinder_recipe({input="default:cobble", output="default:gravel"}) techage.add_grinder_recipe({input="default:desert_cobble", output="default:gravel"}) techage.add_grinder_recipe({input="default:mossycobble", output="default:gravel"}) techage.add_grinder_recipe({input="default:gravel", output="default:sand"}) -techage.add_grinder_recipe({input="gravelsieve:sieved_gravel", output="default:sand"}) +techage.add_grinder_recipe({input="techage:sieved_gravel", output="default:sand"}) techage.add_grinder_recipe({input="default:coral_skeleton", output="default:silver_sand"}) -techage.add_grinder_recipe({input="tubelib:basalt_stone", output="default:silver_sand"}) if minetest.global_exists("skytest") then techage.add_grinder_recipe({input="default:desert_sand", output="skytest:dust"}) diff --git a/basic_machines/mark.lua b/basic_machines/mark.lua new file mode 100644 index 0000000..73328db --- /dev/null +++ b/basic_machines/mark.lua @@ -0,0 +1,93 @@ +--[[ + + Tube Library + ============ + + Copyright (C) 2019 Joachim Stolberg + Code derived from wordedit (sfan5, Anthony Zhang (Uberi/Temperest), and Brett O'Donnell (cornernote)) + + LGPLv2.1+ + See LICENSE.txt for more information + + mark.lua: + +]]-- + +local marker_region = {} + +function tubelib.unmark_region(name) + if marker_region[name] ~= nil then --marker already exists + --wip: make the area stay loaded somehow + for _, entity in ipairs(marker_region[name]) do + entity:remove() + end + marker_region[name] = nil + end +end + +function tubelib.mark_region(name, pos1, pos2) + + tubelib.unmark_region(name) + + local thickness = 0.2 + local sizex, sizey, sizez = (1 + pos2.x - pos1.x) / 2, (1 + pos2.y - pos1.y) / 2, (1 + pos2.z - pos1.z) / 2 + local markers = {} + + --XY plane markers + for _, z in ipairs({pos1.z - 0.5, pos2.z + 0.5}) do + local marker = minetest.add_entity({x=pos1.x + sizex - 0.5, y=pos1.y + sizey - 0.5, z=z}, "tubelib:region_cube") + if marker ~= nil then + marker:set_properties({ + visual_size={x=sizex * 2, y=sizey * 2}, + collisionbox = {-sizex, -sizey, -thickness, sizex, sizey, thickness}, + }) + marker:get_luaentity().player_name = name + table.insert(markers, marker) + end + end + + --YZ plane markers + for _, x in ipairs({pos1.x - 0.5, pos2.x + 0.5}) do + local marker = minetest.add_entity({x=x, y=pos1.y + sizey - 0.5, z=pos1.z + sizez - 0.5}, "tubelib:region_cube") + if marker ~= nil then + marker:set_properties({ + visual_size={x=sizez * 2, y=sizey * 2}, + collisionbox = {-thickness, -sizey, -sizez, thickness, sizey, sizez}, + }) + marker:setyaw(math.pi / 2) + marker:get_luaentity().player_name = name + table.insert(markers, marker) + end + end + + marker_region[name] = markers +end + +function tubelib.switch_region(name, pos1, pos2) + if marker_region[name] ~= nil then --marker already exists + tubelib.unmark_region(name) + else + tubelib.mark_region(name, pos1, pos2) + end +end + +minetest.register_entity(":tubelib:region_cube", { + initial_properties = { + visual = "upright_sprite", + visual_size = {x=1.1, y=1.1}, + textures = {"tubelib_cube.png"}, + use_texture_alpha = true, + visual_size = {x=10, y=10}, + physical = false, + }, + on_step = function(self, dtime) + if marker_region[self.player_name] == nil then + self.object:remove() + return + end + end, + on_punch = function(self, hitter) + tubelib.unmark_region(self.player_name) + end, +}) + diff --git a/basic_machines/pusher.lua b/basic_machines/pusher.lua index 3490f53..5af0531 100644 --- a/basic_machines/pusher.lua +++ b/basic_machines/pusher.lua @@ -42,7 +42,7 @@ local function pushing(pos, trd, meta, mem) local push_dir = meta:get_int("push_dir") local items = techage.pull_items(pos, pull_dir, trd.num_items) if items ~= nil then - if techage.push_items(pos, push_dir, items) == false then + if techage.push_items(pos, push_dir, items) ~= true then -- place item back techage.unpull_items(pos, pull_dir, items) trd.State:blocked(pos, mem) diff --git a/basis/junction.lua b/basis/junction.lua index 3691ae7..143551d 100644 --- a/basis/junction.lua +++ b/basis/junction.lua @@ -63,11 +63,13 @@ function techage.register_junction(name, size, boxes, network, node) node.is_ground_content = false node.drop = name.."0" - minetest.register_node(name..idx, node) + minetest.register_node(name..idx, table.copy(node)) network:add_secondary_node_names({name..idx}) end end + + function techage.junction_type(conn) local val = 0 for idx = 1,6 do diff --git a/basis/lib.lua b/basis/lib.lua index 34c6377..07b1d2d 100644 --- a/basis/lib.lua +++ b/basis/lib.lua @@ -1,3 +1,26 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + Helper functions + +]]-- + +-- for lazy programmers +local S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local P = minetest.string_to_pos +local M = minetest.get_meta + +-- Load support for intllib. +local MP = minetest.get_modpath("techage") +local I,_ = dofile(MP.."/intllib.lua") + function techage.range(val, min, max) val = tonumber(val) if val < min then return min end @@ -12,3 +35,22 @@ function techage.one_of(val, selection) return selection[1] end +-- +-- Functions used to hide electric cable and biogas pipes +-- +-- Overridden method of tubelib2! +function techage.get_primary_node_param2(pos, dir) + local npos = vector.add(pos, tubelib2.Dir6dToVector[dir or 0]) + local param2 = M(npos):get_int("tl2_param2") + if param2 ~= 0 then + return param2, npos + end +end + +-- Overridden method of tubelib2! +function techage.is_primary_node(pos, dir) + local npos = vector.add(pos, tubelib2.Dir6dToVector[dir or 0]) + local param2 = M(npos):get_int("tl2_param2") + return param2 ~= 0 +end + diff --git a/init.lua b/init.lua index 43b3553..01ca74f 100644 --- a/init.lua +++ b/init.lua @@ -25,13 +25,16 @@ else dofile(MP.."/basis/guide.lua") -- construction guide dofile(MP.."/basis/power.lua") -- power distribution dofile(MP.."/basis/node_states.lua") -- state model - dofile(MP.."/basis/trowel.lua") -- hidden networks dofile(MP.."/basis/junction.lua") -- network junction box dofile(MP.."/basis/tubes.lua") -- tubelib replacement dofile(MP.."/basis/command.lua") -- tubelib replacement dofile(MP.."/basis/consumer.lua") -- consumer base model dofile(MP.."/basis/firebox.lua") -- common firebox functions - + + -- Tools + dofile(MP.."/tools/trowel.lua") + --dofile(MP.."/tools/repairkit.lua") + -- Power networks dofile(MP.."/power/drive_axle.lua") dofile(MP.."/power/steam_pipe.lua") @@ -62,15 +65,19 @@ else dofile(MP.."/steam_engine/flywheel.lua") dofile(MP.."/steam_engine/gearbox.lua") dofile(MP.."/steam_engine/consumer.lua") - dofile(MP.."/steam_engine/battery.lua") -- Basic Machines dofile(MP.."/basic_machines/pusher.lua") + dofile(MP.."/basic_machines/blackhole.lua") dofile(MP.."/basic_machines/legacy_nodes.lua") dofile(MP.."/basic_machines/grinder.lua") dofile(MP.."/basic_machines/distributor.lua") dofile(MP.."/basic_machines/gravelsieve.lua") dofile(MP.."/basic_machines/chest.lua") + dofile(MP.."/basic_machines/autocrafter.lua") + if techage.basalt_stone_enabled then + dofile(MP.."/basic_machines/basalt.lua") + end -- Coal power station dofile(MP.."/coal_power_station/firebox.lua") @@ -82,8 +89,9 @@ else + dofile(MP.."/test/battery.lua") --dofile(MP.."/test/test.lua") - --dofile(MP.."/test/generator.lua") + dofile(MP.."/test/generator.lua") --dofile(MP.."/test/consumer.lua") diff --git a/iron_age/hammer.lua b/iron_age/hammer.lua index 62a12a6..80fc415 100644 --- a/iron_age/hammer.lua +++ b/iron_age/hammer.lua @@ -38,7 +38,7 @@ minetest.register_tool("techage:hammer_bronze", { full_punch_interval = 1.0, max_drop_level=1, groupcaps={ - cracky = {times={[1]=5.00, [2]=2.0, [3]=1.0}, uses=30, maxlevel=2}, + cracky = {times={[1]=5.00, [2]=2.0, [3]=1.0}, uses=50, maxlevel=2}, }, damage_groups = {fleshy=4}, }, @@ -57,7 +57,7 @@ minetest.register_tool("techage:hammer_steel", { full_punch_interval = 1.0, max_drop_level=1, groupcaps={ - cracky = {times={[1]=4.00, [2]=1.60, [3]=0.80}, uses=30, maxlevel=2}, + cracky = {times={[1]=4.00, [2]=1.60, [3]=0.80}, uses=60, maxlevel=2}, }, damage_groups = {fleshy=4}, }, @@ -76,7 +76,7 @@ minetest.register_tool("techage:hammer_mese", { full_punch_interval = 0.9, max_drop_level=3, groupcaps={ - cracky = {times={[1]=2.4, [2]=1.2, [3]=0.60}, uses=40, maxlevel=3}, + cracky = {times={[1]=2.4, [2]=1.2, [3]=0.60}, uses=80, maxlevel=3}, }, damage_groups = {fleshy=5}, }, @@ -95,7 +95,7 @@ minetest.register_tool("techage:hammer_diamond", { full_punch_interval = 0.9, max_drop_level=3, groupcaps={ - cracky = {times={[1]=2.0, [2]=1.0, [3]=0.50}, uses=40, maxlevel=3}, + cracky = {times={[1]=2.0, [2]=1.0, [3]=0.50}, uses=100, maxlevel=3}, }, damage_groups = {fleshy=5}, }, @@ -108,7 +108,7 @@ minetest.register_tool("techage:hammer_diamond", { }) minetest.register_craft({ - output = "techage:hammer_bronze", + output = "techage:hammer_bronze 2", recipe = { {"default:bronze_ingot", "group:stick", "default:bronze_ingot"}, {"default:bronze_ingot", "group:stick", "default:bronze_ingot"}, @@ -116,7 +116,7 @@ minetest.register_craft({ } }) minetest.register_craft({ - output = "techage:hammer_steel", + output = "techage:hammer_steel 2", recipe = { {"default:steel_ingot", "group:stick", "default:steel_ingot"}, {"default:steel_ingot", "group:stick", "default:steel_ingot"}, @@ -124,7 +124,7 @@ minetest.register_craft({ } }) minetest.register_craft({ - output = "techage:hammer_mese", + output = "techage:hammer_mese 2", recipe = { {"default:mese_crystal", "group:stick", "default:mese_crystal"}, {"default:mese_crystal", "group:stick", "default:mese_crystal"}, @@ -132,7 +132,7 @@ minetest.register_craft({ } }) minetest.register_craft({ - output = "techage:hammer_diamond", + output = "techage:hammer_diamond 2", recipe = { {"default:diamond", "group:stick", "default:diamond"}, {"default:diamond", "group:stick", "default:diamond"}, diff --git a/iron_age/recipes.lua b/iron_age/recipes.lua index 4bf4416..9591eb3 100644 --- a/iron_age/recipes.lua +++ b/iron_age/recipes.lua @@ -26,13 +26,6 @@ techage.ironage_register_recipe({ time = 8, }) -techage.ironage_register_recipe({ - output = "default:clay", - recipe = {"techage:sieved_gravel"}, - heat = 3, - time = 3, -}) - techage.ironage_register_recipe({ output = "techage:iron_ingot", recipe = {"default:iron_lump"}, diff --git a/power/electric_cable.lua b/power/electric_cable.lua index 65523b4..09c20fc 100644 --- a/power/electric_cable.lua +++ b/power/electric_cable.lua @@ -21,7 +21,6 @@ local M = minetest.get_meta local MP = minetest.get_modpath("techage") local I,_ = dofile(MP.."/intllib.lua") - local Cable = tubelib2.Tube:new({ dirs_to_check = {1,2,3,4,5,6}, max_tube_length = 1000, @@ -128,7 +127,8 @@ minetest.register_node("techage:electric_cableA", { paramtype = "light", sunlight_propagates = true, is_ground_content = false, - groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1}, + groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, + techage_trowel = 1, not_in_creative_inventory = 1}, sounds = default.node_sound_defaults(), drop = "techage:electric_cableS", }) @@ -148,17 +148,13 @@ local Boxes = { } techage.register_junction("techage:electric_junction", 2/8, Boxes, techage.ElectricCable, { - description = "Electricity Junction Box", + description = I("TA4 Electricity Junction Box"), tiles = {"techage_electric_junction.png"}, groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1}, sounds = default.node_sound_defaults(), techage = { power_network = techage.ElectricCable, }, - description = "Electricity Junction Box", - tiles = {"techage_electric_junction.png"}, - groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1}, - sounds = default.node_sound_defaults(), after_place_node = distributor.after_place_node, after_dig_node = distributor.after_dig_node, diff --git a/sounds/techage_steamengine.ogg b/sounds/techage_steamengine.ogg index ad98cd9..649a3de 100644 Binary files a/sounds/techage_steamengine.ogg and b/sounds/techage_steamengine.ogg differ diff --git a/steam_engine/cylinder.lua b/steam_engine/cylinder.lua index ed4b022..6cec750 100644 --- a/steam_engine/cylinder.lua +++ b/steam_engine/cylinder.lua @@ -53,19 +53,10 @@ local function start_cylinder(pos, on) if on and mem.running then consumer.turn_power_on(pos, POWER_CONSUMPTION) swap_node(pos, "techage:cylinder_on") - mem.handle = minetest.sound_play("techage_steamengine", { - pos = pos, - max_hear_distance = 4, - gain = 0.7, - loop = true}) return true else consumer.turn_power_on(pos, 0) swap_node(pos, "techage:cylinder") - if mem.handle then - minetest.sound_stop(mem.handle) - mem.handle = nil - end end return false end @@ -164,18 +155,3 @@ minetest.register_craft({ {"default:wood", "techage:iron_ingot", "basic_materials:steel_bar"}, }, }) - -minetest.register_lbm({ - label = "[techage] Steam engine sound", - name = "techage:steam_engine", - nodenames = {"techage:cylinder_on"}, - run_at_every_load = true, - action = function(pos, node) - local mem = tubelib2.get_mem(pos) - mem.handle = minetest.sound_play("techage_steamengine", { - pos = pos, - max_hear_distance = 4, - gain = 0.7, - loop = true}) - end -}) diff --git a/steam_engine/flywheel.lua b/steam_engine/flywheel.lua index 774a44c..f4f1d7e 100644 --- a/steam_engine/flywheel.lua +++ b/steam_engine/flywheel.lua @@ -56,13 +56,28 @@ local function can_start(pos, mem, state) return start_cylinder(pos, true) end +local function play_sound(pos) + local mem = tubelib2.get_mem(pos) + mem.handle = minetest.sound_play("techage_steamengine", { + pos = pos, + gain = 0.5, + max_hear_distance = 10}) + minetest.after(2, play_sound, pos) +end + local function start_node(pos, mem, state) + print("start_node") generator.turn_power_on(pos, POWER_CAPACITY) + play_sound(pos) end local function stop_node(pos, mem, state) start_cylinder(pos, false) generator.turn_power_on(pos, 0) + if mem.handle then + minetest.sound_stop(mem.handle) + mem.handle = nil + end end local State = techage.NodeStates:new({ @@ -248,3 +263,14 @@ minetest.register_craft({ {"default:wood", "techage:iron_ingot", "basic_materials:steel_bar"}, }, }) + +minetest.register_lbm({ + label = "[techage] Steam engine sound", + name = "techage:steam_engine", + nodenames = {"techage:flywheel_on"}, + run_at_every_load = true, + action = function(pos, node) + play_sound(pos) + end +}) + diff --git a/steam_engine/battery.lua b/test/battery.lua similarity index 100% rename from steam_engine/battery.lua rename to test/battery.lua diff --git a/electric/consumer.lua b/test/consumer.lua similarity index 100% rename from electric/consumer.lua rename to test/consumer.lua diff --git a/electric/generator.lua b/test/generator.lua similarity index 100% rename from electric/generator.lua rename to test/generator.lua diff --git a/basic_machines/perf_test.lua b/test/perf_test.lua similarity index 100% rename from basic_machines/perf_test.lua rename to test/perf_test.lua diff --git a/electric/test.lua b/test/test.lua similarity index 100% rename from electric/test.lua rename to test/test.lua diff --git a/textures/techage_appl_autocrafter.png b/textures/techage_appl_autocrafter.png new file mode 100644 index 0000000..763e7bc Binary files /dev/null and b/textures/techage_appl_autocrafter.png differ diff --git a/textures/techage_appl_autocrafter4.png b/textures/techage_appl_autocrafter4.png new file mode 100644 index 0000000..90853e7 Binary files /dev/null and b/textures/techage_appl_autocrafter4.png differ diff --git a/textures/techage_appl_blackhole.png b/textures/techage_appl_blackhole.png new file mode 100644 index 0000000..b85a201 Binary files /dev/null and b/textures/techage_appl_blackhole.png differ diff --git a/tools/repairkit.lua b/tools/repairkit.lua new file mode 100644 index 0000000..4aba31e --- /dev/null +++ b/tools/repairkit.lua @@ -0,0 +1,92 @@ +--[[ + + Tube Library + ============ + + Copyright (C) 2017-2018 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + repairkit.lua: +]]-- + +-- for lazy programmers +local S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local P = minetest.string_to_pos +local M = minetest.get_meta + +local function destroy_node(itemstack, placer, pointed_thing) + if pointed_thing.type == "node" then + local pos = pointed_thing.under + if not minetest.is_protected(pos, placer:get_player_name()) then + M(pos):set_int("tubelib_aging", 999999) + end + end +end + +local function repair_node(itemstack, user, pointed_thing) + local pos = pointed_thing.under + if pos then + if tubelib.repair_node(pos) then + minetest.chat_send_player(user:get_player_name(), "[Tubelib] Node repaired") + itemstack:take_item() + return itemstack + end + end + return +end + +local function read_state(itemstack, user, pointed_thing) + local pos = pointed_thing.under + if pos then + local number = tubelib.get_node_number(pos) + if number then + local state = tubelib.send_request(number, "state", nil) + local counter = tubelib.send_request(number, "counter", nil) + local aging = tubelib.send_request(number, "aging", nil) + if state and counter and aging then + if type(counter) ~= "number" then counter = "unknown" end + minetest.chat_send_player(user:get_player_name(), "[Tubelib] state ="..state..", counter = "..counter..", aging = "..aging) + end + end + end +end + +minetest.register_craftitem("tubelib:repairkit", { + description = "Tubelib Repair Kit", + inventory_image = "tubelib_repairkit.png", + wield_image = "tubelib_repairkit.png^[transformR270", + groups = {cracky=1, book=1}, + on_use = repair_node, + node_placement_prediction = "", +}) + + +minetest.register_node("tubelib:end_wrench", { + description = "Tubelib End Wrench (use = read status, place = destroy)", + inventory_image = "tubelib_end_wrench.png", + wield_image = "tubelib_end_wrench.png", + groups = {cracky=1, book=1}, + on_use = read_state, + on_place = destroy_node, + node_placement_prediction = "", +}) + +minetest.register_craft({ + output = "tubelib:repairkit", + recipe = { + {"", "basic_materials:gear_steel", ""}, + {"", "tubelib:end_wrench", ""}, + {"", "basic_materials:oil_extract", ""}, + }, +}) + +minetest.register_craft({ + output = "tubelib:end_wrench 4", + recipe = { + {"", "", "default:steel_ingot"}, + {"", "default:tin_ingot", ""}, + {"default:steel_ingot", "", ""}, + }, +}) diff --git a/basis/trowel.lua b/tools/trowel.lua similarity index 88% rename from basis/trowel.lua rename to tools/trowel.lua index 3553530..8a82e33 100644 --- a/basis/trowel.lua +++ b/tools/trowel.lua @@ -24,22 +24,6 @@ local I,_ = dofile(MP.."/intllib.lua") -- used by other tools: dug_node[player_name] = pos techage.dug_node = {} --- Overridden method of tubelib2! -function techage.get_primary_node_param2(pos, dir) - local npos = vector.add(pos, tubelib2.Dir6dToVector[dir or 0]) - local param2 = M(npos):get_int("tl2_param2") - if param2 ~= 0 then - return param2, npos - end -end - --- Overridden method of tubelib2! -function techage.is_primary_node(pos, dir) - local npos = vector.add(pos, tubelib2.Dir6dToVector[dir or 0]) - local param2 = M(npos):get_int("tl2_param2") - return param2 ~= 0 -end - -- Determine if one node in the surrounding is a hidden tube/cable/pipe local function other_hidden_nodes(pos, node_name) return M({x=pos.x+1, y=pos.y, z=pos.z}):get_string(node_name) ~= "" or @@ -112,6 +96,7 @@ minetest.register_on_dignode(function(pos, oldnode, digger) techage.ElectricCable:after_dig_node(pos, oldnode, digger) techage.BiogasPipe:after_dig_node(pos, oldnode, digger) else + -- store pos for other tools without own 'register_on_dignode' techage.dug_node[digger:get_player_name()] = pos end end)