From 8e03d7ded6441b26e9d44102c0cd2ee39f9e90bc Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Sun, 30 Jun 2013 07:12:02 +0200 Subject: [PATCH] Sync with indev branch, bump version to 0.4.7 --- aaa_recipeshook/depends.txt | 1 - aaa_recipeshook/init.lua | 29 - technic/alloy_furnaces_commons.lua | 12 +- technic/battery_box.lua | 693 +++++++++--------- technic/battery_box_hv.lua | 331 +++++++++ technic/battery_box_mv.lua | 631 ++++++++-------- technic/chainsaw.lua | 303 ++++++-- technic/cnc.lua | 312 ++++++++ technic/cnc_api.lua | 372 ++++++++++ technic/cnc_nodes.lua | 70 ++ technic/config.lua | 49 +- technic/depends.txt | 3 +- technic/down_converter_hv.lua | 225 ++++++ technic/down_converter_mv.lua | 226 ++++++ technic/geothermal.lua | 4 +- technic/grinder.lua | 91 ++- technic/init.lua | 21 +- technic/items.lua | 30 + technic/mining_drill.lua | 11 +- technic/rubber.lua | 26 +- technic/solar_array_hv.lua | 93 +++ technic/solar_array_lv.lua | 94 +++ technic/solar_array_mv.lua | 95 +++ technic/solar_panel.lua | 37 +- technic/sonic_screwdriver.lua | 2 +- technic/textures/technic_cnc_bottom.png | Bin 0 -> 2006 bytes technic/textures/technic_cnc_cylinder.png | Bin 0 -> 456 bytes .../technic_cnc_cylinder_horizontal.png | Bin 0 -> 463 bytes .../textures/technic_cnc_element_cross.png | Bin 0 -> 415 bytes technic/textures/technic_cnc_element_edge.png | Bin 0 -> 409 bytes technic/textures/technic_cnc_element_end.png | Bin 0 -> 391 bytes .../textures/technic_cnc_element_straight.png | Bin 0 -> 412 bytes technic/textures/technic_cnc_element_t.png | Bin 0 -> 389 bytes technic/textures/technic_cnc_front.png | Bin 0 -> 2000 bytes technic/textures/technic_cnc_front_active.png | Bin 0 -> 2216 bytes technic/textures/technic_cnc_full.png | Bin 0 -> 372 bytes technic/textures/technic_cnc_half.png | Bin 0 -> 460 bytes .../technic_cnc_milling_background.png | Bin 0 -> 78748 bytes .../textures/technic_cnc_onecurvededge.png | Bin 0 -> 507 bytes technic/textures/technic_cnc_pyramid.png | Bin 0 -> 480 bytes technic/textures/technic_cnc_side.png | Bin 0 -> 1922 bytes technic/textures/technic_cnc_slope.png | Bin 0 -> 437 bytes technic/textures/technic_cnc_slope_edge.png | Bin 0 -> 419 bytes .../technic_cnc_slope_edge_upsdwn.png | Bin 0 -> 486 bytes .../textures/technic_cnc_slope_inner_edge.png | Bin 0 -> 497 bytes .../technic_cnc_slope_inner_edge_upsdwn.png | Bin 0 -> 605 bytes technic/textures/technic_cnc_slope_lying.png | Bin 0 -> 548 bytes technic/textures/technic_cnc_slope_upsdwn.png | Bin 0 -> 440 bytes technic/textures/technic_cnc_sphere.png | Bin 0 -> 532 bytes technic/textures/technic_cnc_spike.png | Bin 0 -> 556 bytes technic/textures/technic_cnc_stick.png | Bin 0 -> 320 bytes technic/textures/technic_cnc_top.png | Bin 0 -> 2137 bytes technic/textures/technic_cnc_top_active.png | Bin 0 -> 2214 bytes .../textures/technic_cnc_twocurvededge.png | Bin 0 -> 768 bytes .../technic_hv_battery_box_bottom.png | Bin 0 -> 653 bytes .../textures/technic_hv_battery_box_side0.png | Bin 0 -> 777 bytes .../textures/technic_hv_battery_box_top.png | Bin 0 -> 792 bytes technic/textures/technic_hv_cable.png | Bin 0 -> 1705 bytes technic/textures/technic_hv_cable_wield.png | Bin 0 -> 601 bytes .../technic_hv_down_converter_bottom.png | Bin 0 -> 653 bytes .../technic_hv_down_converter_side.png | Bin 0 -> 609 bytes .../technic_hv_down_converter_top.png | Bin 0 -> 653 bytes .../technic_hv_solar_array_bottom.png | Bin 0 -> 574 bytes .../textures/technic_hv_solar_array_side.png | Bin 0 -> 709 bytes .../textures/technic_hv_solar_array_top.png | Bin 0 -> 777 bytes technic/textures/technic_hv_transformer.png | Bin 0 -> 1801 bytes .../technic_lv_solar_array_bottom.png | Bin 0 -> 579 bytes .../textures/technic_lv_solar_array_side.png | Bin 0 -> 465 bytes .../textures/technic_lv_solar_array_top.png | Bin 0 -> 743 bytes technic/textures/technic_lv_transformer.png | Bin 0 -> 1821 bytes technic/textures/technic_mv_cable_wield.png | Bin 2996 -> 531 bytes .../technic_mv_down_converter_bottom.png | Bin 0 -> 738 bytes .../technic_mv_down_converter_side.png | Bin 0 -> 670 bytes .../technic_mv_down_converter_top.png | Bin 0 -> 738 bytes .../technic_mv_solar_array_bottom.png | Bin 0 -> 574 bytes .../textures/technic_mv_solar_array_side.png | Bin 0 -> 628 bytes .../textures/technic_mv_solar_array_top.png | Bin 0 -> 728 bytes .../technic_hv_solar_array_bottom.png | Bin 0 -> 2019 bytes .../technic_hv_solar_array_side.png | Bin 0 -> 1772 bytes .../technicx32/technic_hv_solar_array_top.png | Bin 0 -> 2855 bytes .../technicx32/technic_hv_transformer.png | Bin 0 -> 1789 bytes .../technic_lv_solar_array_bottom.png | Bin 0 -> 2019 bytes .../technic_lv_solar_array_side.png | Bin 0 -> 1772 bytes .../technicx32/technic_lv_solar_array_top.png | Bin 0 -> 2728 bytes .../technicx32/technic_lv_transformer.png | Bin 0 -> 1809 bytes .../technic_mv_solar_array_bottom.png | Bin 0 -> 2019 bytes .../technic_mv_solar_array_side.png | Bin 0 -> 1772 bytes .../technicx32/technic_mv_solar_array_top.png | Bin 0 -> 2784 bytes technic/tree_tap.lua | 13 +- technic/wires_hv.lua | 398 ++++++++++ unified_inventory/api.lua | 210 +++--- unified_inventory/depends.txt | 3 +- .../textures/ui_furnace_inventory.png | Bin 0 -> 7697 bytes .../textures/ui_main_inventory.png | Bin 0 -> 8617 bytes .../textures/ui_wooden_chest_inventory.png | Bin 0 -> 8065 bytes 95 files changed, 3406 insertions(+), 979 deletions(-) delete mode 100644 aaa_recipeshook/depends.txt delete mode 100644 aaa_recipeshook/init.lua create mode 100644 technic/battery_box_hv.lua create mode 100644 technic/cnc.lua create mode 100644 technic/cnc_api.lua create mode 100644 technic/cnc_nodes.lua create mode 100644 technic/down_converter_hv.lua create mode 100644 technic/down_converter_mv.lua create mode 100644 technic/solar_array_hv.lua create mode 100644 technic/solar_array_lv.lua create mode 100644 technic/solar_array_mv.lua create mode 100644 technic/textures/technic_cnc_bottom.png create mode 100644 technic/textures/technic_cnc_cylinder.png create mode 100644 technic/textures/technic_cnc_cylinder_horizontal.png create mode 100644 technic/textures/technic_cnc_element_cross.png create mode 100644 technic/textures/technic_cnc_element_edge.png create mode 100644 technic/textures/technic_cnc_element_end.png create mode 100644 technic/textures/technic_cnc_element_straight.png create mode 100644 technic/textures/technic_cnc_element_t.png create mode 100644 technic/textures/technic_cnc_front.png create mode 100644 technic/textures/technic_cnc_front_active.png create mode 100644 technic/textures/technic_cnc_full.png create mode 100644 technic/textures/technic_cnc_half.png create mode 100644 technic/textures/technic_cnc_milling_background.png create mode 100644 technic/textures/technic_cnc_onecurvededge.png create mode 100644 technic/textures/technic_cnc_pyramid.png create mode 100644 technic/textures/technic_cnc_side.png create mode 100644 technic/textures/technic_cnc_slope.png create mode 100644 technic/textures/technic_cnc_slope_edge.png create mode 100644 technic/textures/technic_cnc_slope_edge_upsdwn.png create mode 100644 technic/textures/technic_cnc_slope_inner_edge.png create mode 100644 technic/textures/technic_cnc_slope_inner_edge_upsdwn.png create mode 100644 technic/textures/technic_cnc_slope_lying.png create mode 100644 technic/textures/technic_cnc_slope_upsdwn.png create mode 100644 technic/textures/technic_cnc_sphere.png create mode 100644 technic/textures/technic_cnc_spike.png create mode 100644 technic/textures/technic_cnc_stick.png create mode 100644 technic/textures/technic_cnc_top.png create mode 100644 technic/textures/technic_cnc_top_active.png create mode 100644 technic/textures/technic_cnc_twocurvededge.png create mode 100644 technic/textures/technic_hv_battery_box_bottom.png create mode 100644 technic/textures/technic_hv_battery_box_side0.png create mode 100644 technic/textures/technic_hv_battery_box_top.png create mode 100644 technic/textures/technic_hv_cable.png create mode 100644 technic/textures/technic_hv_cable_wield.png create mode 100644 technic/textures/technic_hv_down_converter_bottom.png create mode 100644 technic/textures/technic_hv_down_converter_side.png create mode 100644 technic/textures/technic_hv_down_converter_top.png create mode 100644 technic/textures/technic_hv_solar_array_bottom.png create mode 100644 technic/textures/technic_hv_solar_array_side.png create mode 100644 technic/textures/technic_hv_solar_array_top.png create mode 100644 technic/textures/technic_hv_transformer.png create mode 100644 technic/textures/technic_lv_solar_array_bottom.png create mode 100644 technic/textures/technic_lv_solar_array_side.png create mode 100644 technic/textures/technic_lv_solar_array_top.png create mode 100644 technic/textures/technic_lv_transformer.png create mode 100644 technic/textures/technic_mv_down_converter_bottom.png create mode 100644 technic/textures/technic_mv_down_converter_side.png create mode 100644 technic/textures/technic_mv_down_converter_top.png create mode 100644 technic/textures/technic_mv_solar_array_bottom.png create mode 100644 technic/textures/technic_mv_solar_array_side.png create mode 100644 technic/textures/technic_mv_solar_array_top.png create mode 100644 technic/textures/technicx32/technic_hv_solar_array_bottom.png create mode 100644 technic/textures/technicx32/technic_hv_solar_array_side.png create mode 100644 technic/textures/technicx32/technic_hv_solar_array_top.png create mode 100644 technic/textures/technicx32/technic_hv_transformer.png create mode 100644 technic/textures/technicx32/technic_lv_solar_array_bottom.png create mode 100644 technic/textures/technicx32/technic_lv_solar_array_side.png create mode 100644 technic/textures/technicx32/technic_lv_solar_array_top.png create mode 100644 technic/textures/technicx32/technic_lv_transformer.png create mode 100644 technic/textures/technicx32/technic_mv_solar_array_bottom.png create mode 100644 technic/textures/technicx32/technic_mv_solar_array_side.png create mode 100644 technic/textures/technicx32/technic_mv_solar_array_top.png create mode 100644 technic/wires_hv.lua create mode 100644 unified_inventory/textures/ui_furnace_inventory.png create mode 100644 unified_inventory/textures/ui_main_inventory.png create mode 100644 unified_inventory/textures/ui_wooden_chest_inventory.png diff --git a/aaa_recipeshook/depends.txt b/aaa_recipeshook/depends.txt deleted file mode 100644 index 8b13789..0000000 --- a/aaa_recipeshook/depends.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/aaa_recipeshook/init.lua b/aaa_recipeshook/init.lua deleted file mode 100644 index 733edd1..0000000 --- a/aaa_recipeshook/init.lua +++ /dev/null @@ -1,29 +0,0 @@ -crafts_table ={} -crafts_table_count=0 -UI_recipes_hook=true - --- override minetest.register_craft -local minetest_register_craft = minetest.register_craft -minetest.register_craft = function (options) - register_craft(options) - if options.type=="alloy" or options.type=="grinding" then return end - minetest_register_craft(options) -end - --- register_craft -register_craft = function(options) - if options.output == nil then - return - end - local itemstack = ItemStack(options.output) - if itemstack:is_empty() then - return - end - if crafts_table[itemstack:get_name()]==nil then - crafts_table[itemstack:get_name()] = {} - end - table.insert(crafts_table[itemstack:get_name()],options) - crafts_table_count=crafts_table_count+1 -end - - diff --git a/technic/alloy_furnaces_commons.lua b/technic/alloy_furnaces_commons.lua index e058d56..9c9c42a 100644 --- a/technic/alloy_furnaces_commons.lua +++ b/technic/alloy_furnaces_commons.lua @@ -19,14 +19,12 @@ alloy_recipes[registered_recipes_count].src2_count=count1 alloy_recipes[registered_recipes_count].dst_name=string3 alloy_recipes[registered_recipes_count].dst_count=count3 registered_recipes_count=registered_recipes_count+1 -if UI_recipes_hook then - minetest.register_craft({ +if unified_inventory then + unified_inventory.register_craft({ type = "alloy", output = string3.." "..count3, - recipe = { - {string1.." "..count1}, - {string2.." "..count2}, - } + items = {string1.." "..count1,string2.." "..count2}, + width = 2, }) end end @@ -38,4 +36,4 @@ register_alloy_recipe ("default:steel_ingot",3, "technic:chromium_ingot",1, "tec register_alloy_recipe ("technic:copper_dust",2, "technic:zinc_dust",1, "technic:brass_dust",3) register_alloy_recipe ("moreores:copper_ingot",2, "technic:zinc_ingot",1, "technic:brass_ingot",3) register_alloy_recipe ("default:sand",2, "technic:coal_dust",2, "technic:silicon_wafer",1) -register_alloy_recipe ("technic:silicon_wafer",1, "technic:mithril_dust",1, "technic:doped_silicon_wafer",1) +register_alloy_recipe ("technic:silicon_wafer",1, "technic:gold_dust",1, "technic:doped_silicon_wafer",1) diff --git a/technic/battery_box.lua b/technic/battery_box.lua index 0e08d74..5726053 100644 --- a/technic/battery_box.lua +++ b/technic/battery_box.lua @@ -1,408 +1,393 @@ -LV_machines = {} -registered_LV_machines_count=0 - -function register_LV_machine (string1,string2) -registered_LV_machines_count=registered_LV_machines_count+1 -LV_machines[registered_LV_machines_count]={} -LV_machines[registered_LV_machines_count].machine_name=string1 -LV_machines[registered_LV_machines_count].machine_type=string2 +-- register LV machines here +local LV_machines = {} +function register_LV_machine(string1,string2) + LV_machines[string1] = string2 end power_tools ={} registered_power_tools_count=0 function register_power_tool (string1,max_charge) -registered_power_tools_count=registered_power_tools_count+1 -power_tools[registered_power_tools_count]={} -power_tools[registered_power_tools_count].tool_name=string1 -power_tools[registered_power_tools_count].max_charge=max_charge + registered_power_tools_count=registered_power_tools_count+1 + power_tools[registered_power_tools_count]={} + power_tools[registered_power_tools_count].tool_name=string1 + power_tools[registered_power_tools_count].max_charge=max_charge end - register_power_tool ("technic:battery",10000) register_power_tool ("technic:red_energy_crystal",100000) register_power_tool ("technic:green_energy_crystal",250000) register_power_tool ("technic:blue_energy_crystal",500000) minetest.register_craft({ - output = 'technic:battery 1', - recipe = { - {'default:wood', 'moreores:copper_ingot', 'default:wood'}, - {'default:wood', 'moreores:tin_ingot', 'default:wood'}, - {'default:wood', 'moreores:copper_ingot', 'default:wood'}, - } -}) + output = 'technic:battery 1', + recipe = { + {'default:wood', 'moreores:copper_ingot', 'default:wood'}, + {'default:wood', 'moreores:tin_ingot', 'default:wood'}, + {'default:wood', 'moreores:copper_ingot', 'default:wood'}, + } + }) minetest.register_craft({ - output = 'technic:battery_box 1', - recipe = { - {'technic:battery', 'default:wood', 'technic:battery'}, - {'technic:battery', 'moreores:copper_ingot', 'technic:battery'}, - {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, - } -}) + output = 'technic:battery_box 1', + recipe = { + {'technic:battery', 'default:wood', 'technic:battery'}, + {'technic:battery', 'moreores:copper_ingot', 'technic:battery'}, + {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, + } + }) minetest.register_tool("technic:battery", -{description = "RE Battery", -inventory_image = "technic_battery.png", -tool_capabilities = {load=0,max_drop_level=0, groupcaps={fleshy={times={}, uses=10000, maxlevel=0}}}}) + {description = "RE Battery", + inventory_image = "technic_battery.png", + tool_capabilities = {load=0,max_drop_level=0, groupcaps={fleshy={times={}, uses=10000, maxlevel=0}}}}) minetest.register_craftitem("technic:battery_box", { - description = "Battery box", - stack_max = 99, -}) + description = "Battery box", + stack_max = 99, + }) battery_box_formspec = - "invsize[8,9;]".. - "image[1,1;1,2;technic_power_meter_bg.png]".. - "list[current_name;src;3,1;1,1;]".. - "image[4,1;1,1;technic_battery_reload.png]".. - "list[current_name;dst;5,1;1,1;]".. - "label[0,0;Battery box]".. - "label[3,0;Charge]".. - "label[5,0;Discharge]".. - "label[1,3;Power level]".. - "list[current_player;main;0,5;8,4;]" - -minetest.register_node("technic:battery_box", { - description = "Battery box", - tiles = {"technic_battery_box_top.png", "technic_battery_box_bottom.png", "technic_battery_box_side0.png", - "technic_battery_box_side0.png", "technic_battery_box_side0.png", "technic_battery_box_side0.png"}, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, - sounds = default.node_sound_wood_defaults(), - technic_power_machine=1, - last_side_shown=0, - drop="technic:battery_box", - on_construct = function(pos) - local meta = minetest.env:get_meta(pos) - meta:set_string("infotext", "Battery box") - meta:set_float("technic_power_machine", 1) - meta:set_string("formspec", battery_box_formspec) - local inv = meta:get_inventory() - inv:set_size("src", 1) - inv:set_size("dst", 1) - battery_charge = 0 - max_charge = 60000 - last_side_shown=0 - end, - can_dig = function(pos,player) - local meta = minetest.env:get_meta(pos); - local inv = meta:get_inventory() - if not inv:is_empty("dst") then - return false - elseif not inv:is_empty("src") then - return false - end - return true - end, -}) + "invsize[8,9;]".. + "image[1,1;1,2;technic_power_meter_bg.png]".. + "list[current_name;src;3,1;1,1;]".. + "image[4,1;1,1;technic_battery_reload.png]".. + "list[current_name;dst;5,1;1,1;]".. + "label[0,0;Battery box]".. + "label[3,0;Charge]".. + "label[5,0;Discharge]".. + "label[1,3;Power level]".. + "list[current_player;main;0,5;8,4;]" + +minetest.register_node( + "technic:battery_box", { + description = "LV Battery Box", + tiles = {"technic_battery_box_top.png", "technic_battery_box_bottom.png", "technic_battery_box_side0.png", + "technic_battery_box_side0.png", "technic_battery_box_side0.png", "technic_battery_box_side0.png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + drop="technic:battery_box", + on_construct = function(pos) + if pos == nil then return end + local meta = minetest.env:get_meta(pos) + local inv = meta:get_inventory() + meta:set_string("infotext", "Battery box") + meta:set_float("technic_power_machine", 1) + meta:set_string("formspec", battery_box_formspec) + meta:set_float("internal_EU_buffer", 0) + meta:set_float("internal_EU_buffer_size", 60000) + inv:set_size("src", 1) + inv:set_size("dst", 1) + end, + can_dig = function(pos,player) + if pos == nil then return end + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + if not inv:is_empty("dst") then + return false + elseif not inv:is_empty("src") then + return false + end + return true + end, + }) for i=1,8,1 do -minetest.register_node("technic:battery_box"..i, { - description = "Battery box", - tiles = {"technic_battery_box_top.png", "technic_battery_box_bottom.png", "technic_battery_box_side0.png^technic_power_meter"..i..".png", - "technic_battery_box_side0.png^technic_power_meter"..i..".png", "technic_battery_box_side0.png^technic_power_meter"..i..".png", "technic_battery_box_side0.png^technic_power_meter"..i..".png"}, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1}, - sounds = default.node_sound_wood_defaults(), - technic_power_machine=1, - last_side_shown=0, - drop="technic:battery_box", - on_construct = function(pos) - local meta = minetest.env:get_meta(pos) - meta:set_string("infotext", "Battery box") - meta:set_float("technic_power_machine", 1) - meta:set_string("formspec", battery_box_formspec) - local inv = meta:get_inventory() - inv:set_size("src", 1) - inv:set_size("dst", 1) - battery_charge = 0 - max_charge = 60000 - last_side_shown=0 - end, - can_dig = function(pos,player) - local meta = minetest.env:get_meta(pos); - local inv = meta:get_inventory() - if not inv:is_empty("dst") then - return false - elseif not inv:is_empty("src") then - return false - end - return true - end, -}) + minetest.register_node( + "technic:battery_box"..i, { + description = "LV Battery Box", + tiles = {"technic_battery_box_top.png", "technic_battery_box_bottom.png", "technic_battery_box_side0.png^technic_power_meter"..i..".png", + "technic_battery_box_side0.png^technic_power_meter"..i..".png", "technic_battery_box_side0.png^technic_power_meter"..i..".png", "technic_battery_box_side0.png^technic_power_meter"..i..".png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1}, + sounds = default.node_sound_wood_defaults(), + drop="technic:battery_box", + on_construct = function(pos) + if pos == nil then return end + local meta = minetest.env:get_meta(pos) + local inv = meta:get_inventory() + meta:set_string("infotext", "Battery box") + meta:set_float("technic_power_machine", 1) + meta:set_string("formspec", battery_box_formspec) + meta:set_float("internal_EU_buffer", 0) + meta:set_float("internal_EU_buffer_size", 60000) + inv:set_size("src", 1) + inv:set_size("dst", 1) + end, + can_dig = function(pos,player) + if pos == nil then return end + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + if not inv:is_empty("dst") then + return false + elseif not inv:is_empty("src") then + return false + end + return true + end, + }) end -LV_nodes_visited = {} - function get_RE_item_load (load1,max_load) -if load1==0 then load1=65535 end -local temp = 65536-load1 -temp= temp/65535*max_load -return math.floor(temp + 0.5) + if load1==0 then load1=65535 end + local temp = 65536-load1 + temp= temp/65535*max_load + return math.floor(temp + 0.5) end function set_RE_item_load (load1,max_load) -if load1 == 0 then return 65535 end -local temp=load1/max_load*65535 -temp=65536-temp -return math.floor(temp) + if load1 == 0 then return 65535 end + local temp=load1/max_load*65535 + temp=65536-temp + return math.floor(temp) end function set_RE_wear (item_stack,load1,max_load) -local temp=65536-math.floor(load1/max_load*65535) -item_stack["wear"]=tostring(temp) -return item_stack + local temp=65536-math.floor(load1/max_load*65535) + item_stack["wear"]=tostring(temp) + return item_stack end -minetest.register_abm({ - nodenames = {"technic:battery_box","technic:battery_box1","technic:battery_box2","technic:battery_box3","technic:battery_box4", - "technic:battery_box5","technic:battery_box6","technic:battery_box7","technic:battery_box8"}, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - local meta = minetest.env:get_meta(pos) - charge= meta:get_int("battery_charge") - max_charge= 60000 - local i=math.ceil((charge/max_charge)*8) - if i>8 then i=8 end - j=meta:get_float("last_side_shown") - if i~=j then - if i>0 then hacky_swap_node(pos,"technic:battery_box"..i) - elseif i==0 then hacky_swap_node(pos,"technic:battery_box") end - meta:set_float("last_side_shown",i) - end - ---loading registered power tools - local inv = meta:get_inventory() - if inv:is_empty("src")==false then - local srcstack = inv:get_stack("src", 1) - local src_item=srcstack:to_table() - local src_meta=get_item_meta(src_item["metadata"]) - - local item_max_charge=nil - for i=1,registered_power_tools_count,1 do - if power_tools[i].tool_name==src_item["name"] then - src_meta=get_item_meta(src_item["metadata"]) - if src_meta==nil then - src_meta={} - src_meta["technic_power_tool"]=true - src_meta["charge"]=0 - else - if src_meta["technic_power_tool"]==nil then - src_meta["technic_power_tool"]=true - src_meta["charge"]=0 - end - end - item_max_charge=power_tools[i].max_charge - end +minetest.register_abm( + {nodenames = {"technic:battery_box","technic:battery_box1","technic:battery_box2","technic:battery_box3","technic:battery_box4", + "technic:battery_box5","technic:battery_box6","technic:battery_box7","technic:battery_box8"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.env:get_meta(pos) + local max_charge = 60000 -- Set maximum charge for the device here + local charge = meta:get_int("internal_EU_buffer") + + -- Select node textures + local i=math.ceil((charge/max_charge)*8) + if i > 8 then i = 8 end + local j = meta:get_float("last_side_shown") + if i~=j then + if i>0 then hacky_swap_node(pos,"technic:battery_box"..i) + elseif i==0 then hacky_swap_node(pos,"technic:battery_box") end + meta:set_float("last_side_shown",i) end - if item_max_charge then - load1=src_meta["charge"] - load_step=1000 - if load10 then - if charge-load_step<0 then load_step=charge end - if load1+load_step>item_max_charge then load_step=item_max_charge-load1 end - load1=load1+load_step - charge=charge-load_step - set_RE_wear(src_item,load1,item_max_charge) - src_meta["charge"]=load1 - src_item["metadata"]=set_item_meta(src_meta) - inv:set_stack("src", 1, src_item) - end - meta:set_int("battery_charge",charge) - end - end - --- dischargin registered power tools - if inv:is_empty("dst") == false then - srcstack = inv:get_stack("dst", 1) - src_item=srcstack:to_table() - local src_meta=get_item_meta(src_item["metadata"]) - local item_max_charge=nil - for i=1,registered_power_tools_count,1 do - if power_tools[i].tool_name==src_item["name"] then - src_meta=get_item_meta(src_item["metadata"]) - if src_meta==nil then - src_meta={} - src_meta["technic_power_tool"]=true - src_meta["charge"]=0 - else - if src_meta["technic_power_tool"]==nil then - src_meta["technic_power_tool"]=true - src_meta["charge"]=0 - end - end - item_max_charge=power_tools[i].max_charge - end - end - - if item_max_charge then - local load1=src_meta["charge"] - load_step=1000 - if load1>0 and chargemax_charge then load_step=max_charge-charge end - if load1-load_step<0 then load_step=load1 end - load1=load1-load_step - charge=charge+load_step - set_RE_wear(src_item,load1,item_max_charge) - src_meta["charge"]=load1 - src_item["metadata"]=set_item_meta(src_meta) - inv:set_stack("dst", 1, src_item) - end - end + --charge registered power tools + local inv = meta:get_inventory() + if inv:is_empty("src")==false then + local srcstack = inv:get_stack("src", 1) + local src_item=srcstack:to_table() + local src_meta=get_item_meta(src_item["metadata"]) + + local item_max_charge=nil + for i=1,registered_power_tools_count,1 do + if power_tools[i].tool_name==src_item["name"] then + src_meta=get_item_meta(src_item["metadata"]) + if src_meta==nil then + src_meta={} + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + else + if src_meta["technic_power_tool"]==nil then + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + end + end + -- Do the charging + local item_max_charge = power_tools[i].max_charge + local load1 = src_meta["charge"] + local load_step = 1000 -- how much to charge per tick + if load10 then + if charge-load_step<0 then load_step=charge end + if load1+load_step>item_max_charge then load_step=item_max_charge-load1 end + load1=load1+load_step + charge=charge-load_step + set_RE_wear(src_item,load1,item_max_charge) + src_meta["charge"]=load1 + src_item["metadata"]=set_item_meta(src_meta) + inv:set_stack("src", 1, src_item) + end + meta:set_int("internal_EU_buffer",charge) + break + end + end end - meta:set_int("battery_charge",charge) + -- discharging registered power tools + if inv:is_empty("dst") == false then + srcstack = inv:get_stack("dst", 1) + src_item=srcstack:to_table() + local src_meta=get_item_meta(src_item["metadata"]) + local item_max_charge=nil + for i=1,registered_power_tools_count,1 do + if power_tools[i].tool_name==src_item["name"] then + src_meta=get_item_meta(src_item["metadata"]) + if src_meta==nil then + src_meta={} + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + else + if src_meta["technic_power_tool"]==nil then + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + end + end + local item_max_charge = power_tools[i].max_charge + local load1 = src_meta["charge"] + local load_step = 4000 -- how much to discharge per tick + if load1>0 and chargemax_charge then load_step=max_charge-charge end + if load1-load_step<0 then load_step=load1 end + load1=load1-load_step + charge=charge+load_step + set_RE_wear(src_item,load1,item_max_charge) + src_meta["charge"]=load1 + src_item["metadata"]=set_item_meta(src_meta) + inv:set_stack("dst", 1, src_item) + end + meta:set_int("internal_EU_buffer",charge) + break + end + end + end - local load = math.floor(charge/60000 * 100) - meta:set_string("formspec", + local load = math.floor(charge/60000 * 100) + meta:set_string("formspec", battery_box_formspec.. - "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:".. - (load)..":technic_power_meter_fg.png]") - - local pos1={} - - pos1.y=pos.y-1 - pos1.x=pos.x - pos1.z=pos.z - - - meta1 = minetest.env:get_meta(pos1) - if meta1:get_float("cablelike")~=1 then return end - - local LV_nodes = {} - local PR_nodes = {} - local RE_nodes = {} - - LV_nodes[1]={} - LV_nodes[1].x=pos1.x - LV_nodes[1].y=pos1.y - LV_nodes[1].z=pos1.z - LV_nodes[1].visited=false - - -table_index=1 - repeat - check_LV_node (PR_nodes,RE_nodes,LV_nodes,table_index) - table_index=table_index+1 - if LV_nodes[table_index]==nil then break end - until false - - -local pos1={} -i=1 - repeat - if PR_nodes[i]==nil then break end -- gettin power from all connected producers - pos1.x=PR_nodes[i].x - pos1.y=PR_nodes[i].y - pos1.z=PR_nodes[i].z - local meta1 = minetest.env:get_meta(pos1) - local internal_EU_buffer=meta1:get_float("internal_EU_buffer") - if charge0 then - charge=charge+charge_to_take - internal_EU_buffer=internal_EU_buffer-charge_to_take - meta1:set_float("internal_EU_buffer",internal_EU_buffer) - end - end - i=i+1 - until false - -if charge>max_charge then charge=max_charge end - -i=1 - repeat - if RE_nodes[i]==nil then break end - pos1.x=RE_nodes[i].x -- loading all conected machines buffers - pos1.y=RE_nodes[i].y - pos1.z=RE_nodes[i].z - local meta1 = minetest.env:get_meta(pos1) - local internal_EU_buffer=meta1:get_float("internal_EU_buffer") - local internal_EU_buffer_size=meta1:get_float("internal_EU_buffer_size") - - local charge_to_give=200 - if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then - charge_to_give=internal_EU_buffer_size-internal_EU_buffer - end - if charge-charge_to_give<0 then charge_to_give=charge end - - internal_EU_buffer=internal_EU_buffer+charge_to_give - meta1:set_float("internal_EU_buffer",internal_EU_buffer) - charge=charge-charge_to_give; - - i=i+1 - until false - charge=math.floor(charge) - charge_string=tostring(charge) - meta:set_string("infotext", "Battery box: "..charge_string.."/"..max_charge); - meta:set_int("battery_charge",charge) + "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:".. + (load)..":technic_power_meter_fg.png]" + ) + + -- Next index the surrounding network the get the producers and receivers on the power grid + local pos1={} + pos1.y=pos.y-1 + pos1.x=pos.x + pos1.z=pos.z + + meta1 = minetest.env:get_meta(pos1) + if meta1:get_float("cablelike")~=1 then return end + + local LV_nodes = {} + local PR_nodes = {} + local RE_nodes = {} + local BA_nodes = {} + + LV_nodes[1]={} + LV_nodes[1].x=pos1.x + LV_nodes[1].y=pos1.y + LV_nodes[1].z=pos1.z + LV_nodes[1].visited=false + + local table_index=1 + repeat + check_LV_node(PR_nodes,RE_nodes,BA_nodes,LV_nodes,table_index) + table_index=table_index+1 + if LV_nodes[table_index]==nil then break end + until false + + + -- Get power from all connected producers + local pr_pos + for _,pr_pos in ipairs(PR_nodes) do + local meta1 = minetest.env:get_meta(pr_pos) + local internal_EU_buffer = meta1:get_float("internal_EU_buffer") + local charge_to_take = 200 + if charge0 then + charge=charge+charge_to_take + internal_EU_buffer=internal_EU_buffer-charge_to_take + meta1:set_float("internal_EU_buffer",internal_EU_buffer) + end + end + end + if charge>max_charge then charge=max_charge end + + -- Provide power to all connected receivers + local re_pos + for _,re_pos in ipairs(RE_nodes) do + local meta1 = minetest.env:get_meta(re_pos) + local internal_EU_buffer = meta1:get_float("internal_EU_buffer") + local internal_EU_buffer_size = meta1:get_float("internal_EU_buffer_size") + local charge_to_give = math.min(200, charge/table.getn(RE_nodes)) + if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then + charge_to_give=internal_EU_buffer_size-internal_EU_buffer + end + if charge-charge_to_give<0 then charge_to_give=charge end + + internal_EU_buffer=internal_EU_buffer+charge_to_give + meta1:set_float("internal_EU_buffer",internal_EU_buffer) + charge=charge-charge_to_give; + end + charge=math.floor(charge) + meta:set_string("infotext", "LV Battery box: "..charge.."/"..max_charge); + meta:set_int("internal_EU_buffer",charge) + end + }) + +-- Register as a battery type +-- Battery type machines function as power reservoirs and can both receive and give back power +register_LV_machine("technic:battery_box","BA") +for i=1,8,1 do + register_LV_machine("technic:battery_box"..i,"BA") end -}) function add_new_cable_node (LV_nodes,pos1) - local i=1 - repeat - if LV_nodes[i]==nil then break end - if pos1.x==LV_nodes[i].x and pos1.y==LV_nodes[i].y and pos1.z==LV_nodes[i].z then return false end - i=i+1 - until false - LV_nodes[i]={} - LV_nodes[i].x=pos1.x - LV_nodes[i].y=pos1.y - LV_nodes[i].z=pos1.z - LV_nodes[i].visited=false - return true + if LV_nodes == nil then return true end + local i=1 + repeat + if LV_nodes[i]==nil then break end + if pos1.x==LV_nodes[i].x and pos1.y==LV_nodes[i].y and pos1.z==LV_nodes[i].z then return false end + i=i+1 + until false + LV_nodes[i]={} + LV_nodes[i].x=pos1.x + LV_nodes[i].y=pos1.y + LV_nodes[i].z=pos1.z + return true end -function check_LV_node (PR_nodes,RE_nodes,LV_nodes,i) - local pos1={} - pos1.x=LV_nodes[i].x - pos1.y=LV_nodes[i].y - pos1.z=LV_nodes[i].z - LV_nodes[i].visited=true - new_node_added=false - - pos1.x=pos1.x+1 - check_LV_node_subp (PR_nodes,RE_nodes,LV_nodes,pos1) - pos1.x=pos1.x-2 - check_LV_node_subp (PR_nodes,RE_nodes,LV_nodes,pos1) - pos1.x=pos1.x+1 - - pos1.y=pos1.y+1 - check_LV_node_subp (PR_nodes,RE_nodes,LV_nodes,pos1) - pos1.y=pos1.y-2 - check_LV_node_subp (PR_nodes,RE_nodes,LV_nodes,pos1) - pos1.y=pos1.y+1 - - pos1.z=pos1.z+1 - check_LV_node_subp (PR_nodes,RE_nodes,LV_nodes,pos1) - pos1.z=pos1.z-2 - check_LV_node_subp (PR_nodes,RE_nodes,LV_nodes,pos1) - pos1.z=pos1.z+1 -return new_node_added +function check_LV_node(PR_nodes,RE_nodes,BA_nodes,LV_nodes,i) + local pos1={} + pos1.x=LV_nodes[i].x + pos1.y=LV_nodes[i].y + pos1.z=LV_nodes[i].z + + pos1.x=pos1.x+1 + check_LV_node_subp (PR_nodes,RE_nodes,BA_nodes,LV_nodes,pos1) + pos1.x=pos1.x-2 + check_LV_node_subp (PR_nodes,RE_nodes,BA_nodes,LV_nodes,pos1) + pos1.x=pos1.x+1 + + pos1.y=pos1.y+1 + check_LV_node_subp (PR_nodes,RE_nodes,BA_nodes,LV_nodes,pos1) + pos1.y=pos1.y-2 + check_LV_node_subp (PR_nodes,RE_nodes,BA_nodes,LV_nodes,pos1) + pos1.y=pos1.y+1 + + pos1.z=pos1.z+1 + check_LV_node_subp (PR_nodes,RE_nodes,BA_nodes,LV_nodes,pos1) + pos1.z=pos1.z-2 + check_LV_node_subp (PR_nodes,RE_nodes,BA_nodes,LV_nodes,pos1) + pos1.z=pos1.z+1 + return new_node_added end -function check_LV_node_subp (PR_nodes,RE_nodes,LV_nodes,pos1) -meta = minetest.env:get_meta(pos1) -if meta:get_float("cablelike")==1 then new_node_added=add_new_cable_node(LV_nodes,pos1) end -for i in ipairs(LV_machines) do - if minetest.env:get_node(pos1).name == LV_machines[i].machine_name then - if LV_machines[i].machine_type == "PR" then - new_node_added=add_new_cable_node(PR_nodes,pos1) - end - if LV_machines[i].machine_type == "RE" then - new_node_added=add_new_cable_node(RE_nodes,pos1) - end - end -end +function check_LV_node_subp (PR_nodes,RE_nodes,BA_nodes,LV_nodes,pos1) + local meta = minetest.env:get_meta(pos1) + local name = minetest.env:get_node(pos1).name + if meta:get_float("cablelike")==1 then + add_new_cable_node(LV_nodes,pos1) + elseif LV_machines[name] then + --print(name.." is a "..LV_machines[name]) + if LV_machines[name] == "PR" then + add_new_cable_node(PR_nodes,pos1) + elseif LV_machines[name] == "RE" then + add_new_cable_node(RE_nodes,pos1) + elseif LV_machines[name] == "BA" then + add_new_cable_node(BA_nodes,pos1) + end + end end diff --git a/technic/battery_box_hv.lua b/technic/battery_box_hv.lua new file mode 100644 index 0000000..16aead9 --- /dev/null +++ b/technic/battery_box_hv.lua @@ -0,0 +1,331 @@ +-- register MV machines here +technic.HV_machines = {} +local HV_machines = technic.HV_machines +function register_HV_machine(string1,string2) + technic.HV_machines[string1] = string2 +end + +minetest.register_craft({ + output = 'technic:hv_battery_box 1', + recipe = { + {'technic:mv_battery_box', 'technic:mv_battery_box', 'mv_technic:battery_box'}, + {'technic:mv_battery_box', 'technic:hv_transformer', 'mv_technic:battery_box'}, + {'', 'technic:hv_cable', ''}, + } + }) + +hv_battery_box_formspec = + "invsize[8,9;]".. + "image[1,1;1,2;technic_power_meter_bg.png]".. + "list[current_name;src;3,1;1,1;]".. + "image[4,1;1,1;technic_battery_reload.png]".. + "list[current_name;dst;5,1;1,1;]".. + "label[0,0;HV Battery Box]".. + "label[3,0;Charge]".. + "label[5,0;Discharge]".. + "label[1,3;Power level]".. + "list[current_player;main;0,5;8,4;]" + +minetest.register_node( + "technic:hv_battery_box", { + description = "HV Battery Box", + tiles = {"technic_hv_battery_box_top.png", "technic_hv_battery_box_bottom.png", "technic_hv_battery_box_side0.png", + "technic_hv_battery_box_side0.png", "technic_hv_battery_box_side0.png", "technic_hv_battery_box_side0.png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + drop="technic:hv_battery_box", + on_construct = function(pos) + if pos==nil then return end + local meta = minetest.env:get_meta(pos) + local inv = meta:get_inventory() + meta:set_string("infotext", "HV Battery Box") + meta:set_float("technic_hv_power_machine", 1) + meta:set_string("formspec", battery_box_formspec) + inv:set_size("src", 1) + inv:set_size("dst", 1) + end, + can_dig = function(pos,player) + if pos==nil then return end + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + if not inv:is_empty("dst") then + return false + elseif not inv:is_empty("src") then + return false + end + return true + end, + }) + +for i=1,8,1 do + minetest.register_node( + "technic:hv_battery_box"..i, { + description = "HV Battery Box", + tiles = {"technic_hv_battery_box_top.png", "technic_hv_battery_box_bottom.png", "technic_hv_battery_box_side0.png^technic_power_meter"..i..".png", + "technic_hv_battery_box_side0.png^technic_power_meter"..i..".png", "technic_hv_battery_box_side0.png^technic_power_meter"..i..".png", "technic_hv_battery_box_side0.png^technic_power_meter"..i..".png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1}, + sounds = default.node_sound_wood_defaults(), + paramtype="light", + light_source=9, + drop="technic:hv_battery_box", + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + local inv = meta:get_inventory() + meta:set_string("infotext", "HV Battery box") + meta:set_float("technic_hv_power_machine", 1) + meta:set_string("formspec", battery_box_formspec) + inv:set_size("src", 1) + inv:set_size("dst", 1) + end, + can_dig = function(pos,player) + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + if not inv:is_empty("dst") then + return false + elseif not inv:is_empty("src") then + return false + end + return true + end, + }) +end + +minetest.register_abm( + {nodenames = {"technic:hv_battery_box","technic:hv_battery_box1","technic:hv_battery_box2","technic:hv_battery_box3","technic:hv_battery_box4", + "technic:hv_battery_box5","technic:hv_battery_box6","technic:hv_battery_box7","technic:hv_battery_box8" + }, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.env:get_meta(pos) + local max_charge = 1500000 + local charge = meta:get_int("internal_EU_buffer") + + -- Select node textures + local i = math.ceil((charge/max_charge)*8) + if i > 8 then i = 8 end + local j = meta:get_float("last_side_shown") + if i~=j then + if i>0 then hacky_swap_node(pos,"technic:hv_battery_box"..i) + elseif i==0 then hacky_swap_node(pos,"technic:hv_battery_box") end + meta:set_float("last_side_shown",i) + end + + --charge registered power tools + local inv = meta:get_inventory() + if inv:is_empty("src")==false then + local srcstack = inv:get_stack("src", 1) + local src_item=srcstack:to_table() + local src_meta=get_item_meta(src_item["metadata"]) + + for i=1,registered_power_tools_count,1 do + if power_tools[i].tool_name==src_item["name"] then + src_meta=get_item_meta(src_item["metadata"]) + if src_meta==nil then + src_meta={} + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + else + if src_meta["technic_power_tool"]==nil then + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + end + end + -- Do the charging + local item_max_charge = power_tools[i].max_charge + local load1 = src_meta["charge"] + local load_step = 16000 -- how much to charge per tick + if load10 then + if charge-load_step<0 then load_step=charge end + if load1+load_step>item_max_charge then load_step=item_max_charge-load1 end + load1=load1+load_step + charge=charge-load_step + set_RE_wear(src_item,load1,item_max_charge) + src_meta["charge"]=load1 + src_item["metadata"]=set_item_meta(src_meta) + inv:set_stack("src", 1, src_item) + end + meta:set_int("internal_EU_buffer",charge) + break + end + end + end + + -- discharging registered power tools + if inv:is_empty("dst") == false then + srcstack = inv:get_stack("dst", 1) + src_item=srcstack:to_table() + local src_meta=get_item_meta(src_item["metadata"]) + local item_max_charge=nil + for i=1,registered_power_tools_count,1 do + if power_tools[i].tool_name==src_item["name"] then + src_meta=get_item_meta(src_item["metadata"]) + if src_meta==nil then + src_meta={} + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + else + if src_meta["technic_power_tool"]==nil then + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + end + end + local item_max_charge = power_tools[i].max_charge + local load1 = src_meta["charge"] + local load_step = 16000 -- how much to discharge per tick + if load1>0 and chargemax_charge then load_step=max_charge-charge end + if load1-load_step<0 then load_step=load1 end + load1=load1-load_step + charge=charge+load_step + set_RE_wear(src_item,load1,item_max_charge) + src_meta["charge"]=load1 + src_item["metadata"]=set_item_meta(src_meta) + inv:set_stack("dst", 1, src_item) + end + meta:set_int("internal_EU_buffer",charge) + break + end + end + end + + + local load = math.floor((charge/1500000) * 100) + meta:set_string("formspec", + hv_battery_box_formspec.. + "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:".. + (load)..":technic_power_meter_fg.png]" + ) + + -- Next index the surrounding network the get the producers and receivers on the + local pos1={} + pos1.y=pos.y-1 + pos1.x=pos.x + pos1.z=pos.z + + meta1 = minetest.env:get_meta(pos1) + if meta1:get_float("hv_cablelike")~=1 then return end + + local HV_nodes = {} + local PR_nodes = {} + local RE_nodes = {} + local BA_nodes = {} + + HV_nodes[1]={} + HV_nodes[1].x=pos1.x + HV_nodes[1].y=pos1.y + HV_nodes[1].z=pos1.z + HV_nodes[1].visited=false + + local table_index=1 + repeat + check_HV_node (PR_nodes,RE_nodes,BA_nodes,HV_nodes,table_index) + table_index=table_index+1 + if HV_nodes[table_index]==nil then break end + until false + + -- Get power from all connected producers + local pr_pos + for _,pr_pos in ipairs(PR_nodes) do + local meta1 = minetest.env:get_meta(pr_pos) + local internal_EU_buffer = meta1:get_float("internal_EU_buffer") + local charge_to_take = 4000 + if charge0 then + charge=charge+charge_to_take + internal_EU_buffer=internal_EU_buffer-charge_to_take + meta1:set_float("internal_EU_buffer",internal_EU_buffer) + end + end + end + + if charge>max_charge then charge=max_charge end + + -- Provide power to all connected receivers + local re_pos + for _,re_pos in ipairs(RE_nodes) do + local meta1 = minetest.env:get_meta(re_pos) + local internal_EU_buffer = meta1:get_float("internal_EU_buffer") + local internal_EU_buffer_size = meta1:get_float("internal_EU_buffer_size") + local charge_to_give = math.min(4000, charge/table.getn(RE_nodes)) + if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then + charge_to_give=internal_EU_buffer_size-internal_EU_buffer + end + if charge-charge_to_give<0 then charge_to_give=charge end + + internal_EU_buffer=internal_EU_buffer+charge_to_give + meta1:set_float("internal_EU_buffer",internal_EU_buffer) + charge=charge-charge_to_give; + end + charge=math.floor(charge) + meta:set_string("infotext", "MV Battery box: "..charge.."/"..max_charge); + meta:set_int("internal_EU_buffer",charge) + end + }) + +-- Register as a battery type +-- Battery type machines function as power reservoirs and can both receive and give back power +register_HV_machine("technic:hv_battery_box","BA") +for i=1,8,1 do + register_HV_machine("technic:hv_battery_box"..i,"BA") +end + +function add_new_HVcable_node (HV_nodes,pos1) + if HV_nodes == nil then return true end + local i=1 + repeat + if HV_nodes[i]==nil then break end + if pos1.x==HV_nodes[i].x and pos1.y==HV_nodes[i].y and pos1.z==HV_nodes[i].z then return false end + i=i+1 + until false + HV_nodes[i]={} + HV_nodes[i].x=pos1.x + HV_nodes[i].y=pos1.y + HV_nodes[i].z=pos1.z + return true +end + +function check_HV_node(PR_nodes,RE_nodes,BA_nodes,HV_nodes,i) + local pos1={} + pos1.x=HV_nodes[i].x + pos1.y=HV_nodes[i].y + pos1.z=HV_nodes[i].z + + pos1.x=pos1.x+1 + check_HV_node_subp (PR_nodes,RE_nodes,BA_nodes,HV_nodes,pos1) + pos1.x=pos1.x-2 + check_HV_node_subp (PR_nodes,RE_nodes,BA_nodes,HV_nodes,pos1) + pos1.x=pos1.x+1 + + pos1.y=pos1.y+1 + check_HV_node_subp (PR_nodes,RE_nodes,BA_nodes,HV_nodes,pos1) + pos1.y=pos1.y-2 + check_HV_node_subp (PR_nodes,RE_nodes,BA_nodes,HV_nodes,pos1) + pos1.y=pos1.y+1 + + pos1.z=pos1.z+1 + check_HV_node_subp (PR_nodes,RE_nodes,BA_nodes,HV_nodes,pos1) + pos1.z=pos1.z-2 + check_HV_node_subp (PR_nodes,RE_nodes,BA_nodes,HV_nodes,pos1) + pos1.z=pos1.z+1 +end + +function check_HV_node_subp (PR_nodes,RE_nodes,BA_nodes,HV_nodes,pos1) + local meta = minetest.env:get_meta(pos1) + local name = minetest.env:get_node(pos1).name + if meta:get_float("hv_cablelike")==1 then + add_new_HVcable_node(HV_nodes,pos1) + elseif HV_machines[name] then + --print(name.." is a "..HV_machines[name]) + if HV_machines[name] == "PR" then + add_new_HVcable_node(PR_nodes,pos1) + elseif HV_machines[name] == "RE" then + add_new_HVcable_node(RE_nodes,pos1) + elseif HV_machines[name] == "BA" then + add_new_HVcable_node(BA_nodes,pos1) + end + end +end diff --git a/technic/battery_box_mv.lua b/technic/battery_box_mv.lua index 8fc6dc7..86c445c 100644 --- a/technic/battery_box_mv.lua +++ b/technic/battery_box_mv.lua @@ -1,355 +1,338 @@ -MV_machines = {} - -registered_MV_machines_count=0 - -function register_MV_machine (string1,string2) -registered_MV_machines_count=registered_MV_machines_count+1 -MV_machines[registered_MV_machines_count]={} -MV_machines[registered_MV_machines_count].machine_name=string1 -MV_machines[registered_MV_machines_count].machine_type=string2 +-- register MV machines here +technic.MV_machines = {} +--local MV_machines = {} +local MV_machines = technic.MV_machines +function register_MV_machine(string1,string2) + technic.MV_machines[string1] = string2 end -minetest.register_craft({ - output = 'technic:mv_battery_box 1', - recipe = { - {'technic:battery_box', 'technic:battery_box', 'technic:battery_box'}, - {'technic:battery_box', 'technic:mv_transformer', 'technic:battery_box'}, - {'', 'technic:mv_cable', ''}, - } -}) +minetest.register_craft( + { + output = 'technic:mv_battery_box 1', + recipe = { + {'technic:battery_box', 'technic:battery_box', 'technic:battery_box'}, + {'technic:battery_box', 'technic:mv_transformer', 'technic:battery_box'}, + {'', 'technic:mv_cable', ''}, + } + }) mv_battery_box_formspec = - "invsize[8,9;]".. - "image[1,1;1,2;technic_power_meter_bg.png]".. - "list[current_name;src;3,1;1,1;]".. - "image[4,1;1,1;technic_battery_reload.png]".. - "list[current_name;dst;5,1;1,1;]".. - "label[0,0;MV_Battery box]".. - "label[3,0;Charge]".. - "label[5,0;Discharge]".. - "label[1,3;Power level]".. - "list[current_player;main;0,5;8,4;]" - -minetest.register_node("technic:mv_battery_box", { - description = "MV Battery Box", - tiles = {"technic_mv_battery_box_top.png", "technic_mv_battery_box_bottom.png", "technic_mv_battery_box_side0.png", - "technic_mv_battery_box_side0.png", "technic_mv_battery_box_side0.png", "technic_mv_battery_box_side0.png"}, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, - sounds = default.node_sound_wood_defaults(), - technic_mv_power_machine=1, - last_side_shown=0, - drop="technic:mv_battery_box", - on_construct = function(pos) - local meta = minetest.env:get_meta(pos) - meta:set_string("infotext", "MV Battery box") - meta:set_float("technic_mv_power_machine", 1) - meta:set_string("formspec", battery_box_formspec) - local inv = meta:get_inventory() - inv:set_size("src", 1) - inv:set_size("dst", 1) - battery_charge = 0 - max_charge = 300000 - last_side_shown=0 - end, - can_dig = function(pos,player) - local meta = minetest.env:get_meta(pos); - local inv = meta:get_inventory() - if not inv:is_empty("dst") then - return false - elseif not inv:is_empty("src") then - return false + "invsize[8,9;]".. + "image[1,1;1,2;technic_power_meter_bg.png]".. + "list[current_name;src;3,1;1,1;]".. + "image[4,1;1,1;technic_battery_reload.png]".. + "list[current_name;dst;5,1;1,1;]".. + "label[0,0;MV_Battery box]".. + "label[3,0;Charge]".. + "label[5,0;Discharge]".. + "label[1,3;Power level]".. + "list[current_player;main;0,5;8,4;]" + +minetest.register_node( + "technic:mv_battery_box", { + description = "MV Battery Box", + tiles = {"technic_mv_battery_box_top.png", "technic_mv_battery_box_bottom.png", "technic_mv_battery_box_side0.png", + "technic_mv_battery_box_side0.png", "technic_mv_battery_box_side0.png", "technic_mv_battery_box_side0.png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + drop = "technic:mv_battery_box", + on_construct = function(pos) + if pos==nil then return end + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + meta:set_string("infotext", "MV Battery box") + meta:set_float("technic_mv_power_machine", 1) + meta:set_string("formspec", battery_box_formspec) + meta:set_float("internal_EU_buffer", 0) + meta:set_float("internal_EU_buffer_size", 300000) + inv:set_size("src", 1) + inv:set_size("dst", 1) + end, + can_dig = function(pos,player) + if pos==nil then return end + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + if not inv:is_empty("dst") then + return false + elseif not inv:is_empty("src") then + return false + end + return true end - return true - end, -}) + }) for i=1,8,1 do -minetest.register_node("technic:mv_battery_box"..i, { - description = "MV Battery Box", - tiles = {"technic_mv_battery_box_top.png", "technic_mv_battery_box_bottom.png", "technic_mv_battery_box_side0.png^technic_power_meter"..i..".png", - "technic_mv_battery_box_side0.png^technic_power_meter"..i..".png", "technic_mv_battery_box_side0.png^technic_power_meter"..i..".png", "technic_mv_battery_box_side0.png^technic_power_meter"..i..".png"}, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1}, - sounds = default.node_sound_wood_defaults(), - technic_power_machine=1, - last_side_shown=0, - drop="technic:mv_battery_box", - on_construct = function(pos) - local meta = minetest.env:get_meta(pos) - meta:set_string("infotext", "MV Battery box") - meta:set_float("technic_mv_power_machine", 1) - meta:set_string("formspec", battery_box_formspec) - local inv = meta:get_inventory() - inv:set_size("src", 1) - inv:set_size("dst", 1) - battery_charge = 0 - max_charge = 300000 - last_side_shown=0 - end, - can_dig = function(pos,player) - local meta = minetest.env:get_meta(pos); - local inv = meta:get_inventory() - if not inv:is_empty("dst") then - return false - elseif not inv:is_empty("src") then - return false - end - return true - end, -}) + minetest.register_node( + "technic:mv_battery_box"..i, { + description = "MV Battery Box", + tiles = {"technic_mv_battery_box_top.png", "technic_mv_battery_box_bottom.png", "technic_mv_battery_box_side0.png^technic_power_meter"..i..".png", + "technic_mv_battery_box_side0.png^technic_power_meter"..i..".png", "technic_mv_battery_box_side0.png^technic_power_meter"..i..".png", "technic_mv_battery_box_side0.png^technic_power_meter"..i..".png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1}, + sounds = default.node_sound_wood_defaults(), + drop = "technic:mv_battery_box", + on_construct = function(pos) + if pos==nil then return end + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + meta:set_string("infotext", "MV Battery box") + meta:set_float("technic_mv_power_machine", 1) + meta:set_string("formspec", battery_box_formspec) + meta:set_float("internal_EU_buffer", 0) + meta:set_float("internal_EU_buffer_size", 300000) + inv:set_size("src", 1) + inv:set_size("dst", 1) + end, + can_dig = function(pos,player) + if pos==nil then return end + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + if not inv:is_empty("dst") then + return false + elseif not inv:is_empty("src") then + return false + end + return true + end + }) end - -MV_nodes_visited = {} - - -minetest.register_abm({ - nodenames = {"technic:mv_battery_box","technic:mv_battery_box1","technic:mv_battery_box2","technic:mv_battery_box3","technic:mv_battery_box4", - "technic:mv_battery_box5","technic:mv_battery_box6","technic:mv_battery_box7","technic:mv_battery_box8" - }, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - local meta = minetest.env:get_meta(pos) - charge= meta:get_int("battery_charge") - max_charge= 300000 - local i=math.ceil((charge/max_charge)*8) - if i>8 then i=8 end - j=meta:get_float("last_side_shown") - if i~=j then - if i>0 then hacky_swap_node(pos,"technic:mv_battery_box"..i) - elseif i==0 then hacky_swap_node(pos,"technic:mv_battery_box") end - meta:set_float("last_side_shown",i) - end - ---loading registered power tools - local inv = meta:get_inventory() - if inv:is_empty("src")==false then - local srcstack = inv:get_stack("src", 1) - local src_item=srcstack:to_table() - local src_meta=get_item_meta(src_item["metadata"]) - - local item_max_charge=nil - for i=1,registered_power_tools_count,1 do - if power_tools[i].tool_name==src_item["name"] then - src_meta=get_item_meta(src_item["metadata"]) - if src_meta==nil then - src_meta={} - src_meta["technic_power_tool"]=true - src_meta["charge"]=0 - else - if src_meta["technic_power_tool"]==nil then - src_meta["technic_power_tool"]=true - src_meta["charge"]=0 - end - end - item_max_charge=power_tools[i].max_charge - end - end - - if item_max_charge then - load1=src_meta["charge"] - load_step=4000 - if load10 then - if charge-load_step<0 then load_step=charge end - if load1+load_step>item_max_charge then load_step=item_max_charge-load1 end - load1=load1+load_step - charge=charge-load_step - set_RE_wear(src_item,load1,item_max_charge) - src_meta["charge"]=load1 - src_item["metadata"]=set_item_meta(src_meta) - inv:set_stack("src", 1, src_item) - end - meta:set_int("battery_charge",charge) - end - end - --- dischargin registered power tools - if inv:is_empty("dst") == false then - srcstack = inv:get_stack("dst", 1) - src_item=srcstack:to_table() - local src_meta=get_item_meta(src_item["metadata"]) - local item_max_charge=nil - for i=1,registered_power_tools_count,1 do - if power_tools[i].tool_name==src_item["name"] then - src_meta=get_item_meta(src_item["metadata"]) - if src_meta==nil then - src_meta={} - src_meta["technic_power_tool"]=true - src_meta["charge"]=0 - else - if src_meta["technic_power_tool"]==nil then - src_meta["technic_power_tool"]=true - src_meta["charge"]=0 - end - end - item_max_charge=power_tools[i].max_charge - end +minetest.register_abm( + {nodenames = {"technic:mv_battery_box","technic:mv_battery_box1","technic:mv_battery_box2","technic:mv_battery_box3","technic:mv_battery_box4", + "technic:mv_battery_box5","technic:mv_battery_box6","technic:mv_battery_box7","technic:mv_battery_box8" + }, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.env:get_meta(pos) + local max_charge = 300000 -- Set maximum charge for the device here + local charge = meta:get_int("internal_EU_buffer") + + -- Select node textures + local i = math.ceil((charge/max_charge)*8) + if i > 8 then i = 8 end + local j = meta:get_float("last_side_shown") + if i~=j then + if i>0 then hacky_swap_node(pos,"technic:mv_battery_box"..i) + elseif i==0 then hacky_swap_node(pos,"technic:mv_battery_box") end + meta:set_float("last_side_shown",i) end - if item_max_charge then - local load1=src_meta["charge"] - load_step=4000 - if load1>0 and chargemax_charge then load_step=max_charge-charge end - if load1-load_step<0 then load_step=load1 end - load1=load1-load_step - charge=charge+load_step - set_RE_wear(src_item,load1,item_max_charge) - src_meta["charge"]=load1 - src_item["metadata"]=set_item_meta(src_meta) - inv:set_stack("dst", 1, src_item) - end + --charge registered power tools + local inv = meta:get_inventory() + if inv:is_empty("src")==false then + local srcstack = inv:get_stack("src", 1) + local src_item=srcstack:to_table() + local src_meta=get_item_meta(src_item["metadata"]) + + -- Power tools should really be made into a hash table to avoid linear search. But the list is short so okay... + for i=1,registered_power_tools_count,1 do + if power_tools[i].tool_name==src_item["name"] then + -- What is this code doing? Setting tool properties if not set already???? + src_meta=get_item_meta(src_item["metadata"]) + if src_meta==nil then + src_meta={} + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + else + if src_meta["technic_power_tool"]==nil then + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + end + end + -- Do the charging + local item_max_charge = power_tools[i].max_charge + local load1 = src_meta["charge"] + local load_step = 4000 -- how much to charge per tick + if load10 then + if charge-load_step<0 then load_step=charge end + if load1+load_step>item_max_charge then load_step=item_max_charge-load1 end + load1=load1+load_step + charge=charge-load_step + set_RE_wear(src_item,load1,item_max_charge) + src_meta["charge"] = load1 + src_item["metadata"] = set_item_meta(src_meta) + inv:set_stack("src", 1, src_item) + end + meta:set_int("internal_EU_buffer",charge) + break + end + end end + + -- discharging registered power tools + if inv:is_empty("dst") == false then + srcstack = inv:get_stack("dst", 1) + src_item=srcstack:to_table() + local src_meta=get_item_meta(src_item["metadata"]) + local item_max_charge=nil + for i=1,registered_power_tools_count,1 do + if power_tools[i].tool_name==src_item["name"] then + src_meta=get_item_meta(src_item["metadata"]) + if src_meta==nil then + src_meta={} + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + else + if src_meta["technic_power_tool"]==nil then + src_meta["technic_power_tool"]=true + src_meta["charge"]=0 + end + end + local item_max_charge = power_tools[i].max_charge + local load1 = src_meta["charge"] + local load_step = 4000 -- how much to discharge per tick + if load1>0 and chargemax_charge then load_step=max_charge-charge end + if load1-load_step<0 then load_step=load1 end + load1=load1-load_step + charge=charge+load_step + set_RE_wear(src_item,load1,item_max_charge) + src_meta["charge"]=load1 + src_item["metadata"]=set_item_meta(src_meta) + inv:set_stack("dst", 1, src_item) + end + meta:set_int("internal_EU_buffer",charge) + break + end + end end - - meta:set_int("battery_charge",charge) - local load = math.floor((charge/300000) * 100) - meta:set_string("formspec", + local load = math.floor((charge/300000) * 100) + meta:set_string("formspec", mv_battery_box_formspec.. - "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:".. - (load)..":technic_power_meter_fg.png]" - ) - - local pos1={} - - pos1.y=pos.y-1 - pos1.x=pos.x - pos1.z=pos.z + "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:".. + (load)..":technic_power_meter_fg.png]" + ) + -- Next index the surrounding network the get the producers and receivers on the power grid + local pos1 = {} + pos1.y = pos.y-1 + pos1.x = pos.x + pos1.z = pos.z - meta1 = minetest.env:get_meta(pos1) - if meta1:get_float("mv_cablelike")~=1 then return end + meta1 = minetest.env:get_meta(pos1) + if meta1:get_float("mv_cablelike")~=1 then return end local MV_nodes = {} local PR_nodes = {} local RE_nodes = {} + local BA_nodes = {} + + MV_nodes[1] = {} + MV_nodes[1].x = pos1.x + MV_nodes[1].y = pos1.y + MV_nodes[1].z = pos1.z + + local table_index=1 + repeat + check_MV_node(PR_nodes,RE_nodes,BA_nodes,MV_nodes,table_index) + table_index=table_index+1 + if MV_nodes[table_index]==nil then break end + until false + + -- Get power from all connected producers + local pr_pos + for _,pr_pos in ipairs(PR_nodes) do + local meta1 = minetest.env:get_meta(pr_pos) + local internal_EU_buffer = meta1:get_float("internal_EU_buffer") + local charge_to_take = 1000 + if charge0 then + charge=charge+charge_to_take + internal_EU_buffer=internal_EU_buffer-charge_to_take + meta1:set_float("internal_EU_buffer",internal_EU_buffer) + end + end + end - MV_nodes[1]={} - MV_nodes[1].x=pos1.x - MV_nodes[1].y=pos1.y - MV_nodes[1].z=pos1.z - MV_nodes[1].visited=false - -table_index=1 - repeat - check_MV_node (PR_nodes,RE_nodes,MV_nodes,table_index) - table_index=table_index+1 - if MV_nodes[table_index]==nil then break end - until false - - -local pos1={} -i=1 - repeat - if PR_nodes[i]==nil then break end -- gettin power from all connected producers - pos1.x=PR_nodes[i].x - pos1.y=PR_nodes[i].y - pos1.z=PR_nodes[i].z - local meta1 = minetest.env:get_meta(pos1) - local internal_EU_buffer=meta1:get_float("internal_EU_buffer") - if charge0 then - charge=charge+charge_to_take - internal_EU_buffer=internal_EU_buffer-charge_to_take - meta1:set_float("internal_EU_buffer",internal_EU_buffer) - end - end - i=i+1 - until false - -if charge>max_charge then charge=max_charge end - -i=1 - repeat - if RE_nodes[i]==nil then break end - pos1.x=RE_nodes[i].x -- loading all conected machines buffers - pos1.y=RE_nodes[i].y - pos1.z=RE_nodes[i].z - local meta1 = minetest.env:get_meta(pos1) - local internal_EU_buffer=meta1:get_float("internal_EU_buffer") - local internal_EU_buffer_size=meta1:get_float("internal_EU_buffer_size") - - local charge_to_give=1000 - if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then - charge_to_give=internal_EU_buffer_size-internal_EU_buffer - end - if charge-charge_to_give<0 then charge_to_give=charge end - - internal_EU_buffer=internal_EU_buffer+charge_to_give - meta1:set_float("internal_EU_buffer",internal_EU_buffer) - charge=charge-charge_to_give; - - i=i+1 - until false - charge=math.floor(charge) - charge_string=tostring(charge) - meta:set_string("infotext", "Battery box: "..charge_string.."/"..max_charge); - meta:set_int("battery_charge",charge) - + if charge>max_charge then charge=max_charge end + + -- Provide power to all connected receivers + local re_pos + for _,re_pos in ipairs(RE_nodes) do + local meta1 = minetest.env:get_meta(re_pos) + local internal_EU_buffer = meta1:get_float("internal_EU_buffer") + local internal_EU_buffer_size = meta1:get_float("internal_EU_buffer_size") + local charge_to_give = math.min(1000, charge/table.getn(RE_nodes)) + if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then + charge_to_give=internal_EU_buffer_size-internal_EU_buffer + end + if charge-charge_to_give<0 then charge_to_give=charge end + + internal_EU_buffer=internal_EU_buffer+charge_to_give + meta1:set_float("internal_EU_buffer",internal_EU_buffer) + charge=charge-charge_to_give; + end + charge=math.floor(charge) + meta:set_string("infotext", "MV Battery box: "..charge.."/"..max_charge); + meta:set_int("internal_EU_buffer",charge) + end + }) + +-- Register as a battery type +-- Battery type machines function as power reservoirs and can both receive and give back power +register_MV_machine("technic:mv_battery_box","BA") +for i=1,8,1 do + register_MV_machine("technic:mv_battery_box"..i,"BA") end -}) function add_new_MVcable_node (MV_nodes,pos1) -local i=1 - repeat - if MV_nodes[i]==nil then break end - if pos1.x==MV_nodes[i].x and pos1.y==MV_nodes[i].y and pos1.z==MV_nodes[i].z then return false end - i=i+1 - until false -MV_nodes[i]={} -MV_nodes[i].x=pos1.x -MV_nodes[i].y=pos1.y -MV_nodes[i].z=pos1.z -MV_nodes[i].visited=false -return true + if MV_nodes == nil then return true end + local i=1 + repeat + if MV_nodes[i]==nil then break end + if pos1.x==MV_nodes[i].x and pos1.y==MV_nodes[i].y and pos1.z==MV_nodes[i].z then return false end + i=i+1 + until false + MV_nodes[i]={} + MV_nodes[i].x=pos1.x + MV_nodes[i].y=pos1.y + MV_nodes[i].z=pos1.z + return true end -function check_MV_node (PR_nodes,RE_nodes,MV_nodes,i) - local pos1={} - pos1.x=MV_nodes[i].x - pos1.y=MV_nodes[i].y - pos1.z=MV_nodes[i].z - MV_nodes[i].visited=true - new_node_added=false - - pos1.x=pos1.x+1 - check_MV_node_subp (PR_nodes,RE_nodes,MV_nodes,pos1) - pos1.x=pos1.x-2 - check_MV_node_subp (PR_nodes,RE_nodes,MV_nodes,pos1) - pos1.x=pos1.x+1 - - pos1.y=pos1.y+1 - check_MV_node_subp (PR_nodes,RE_nodes,MV_nodes,pos1) - pos1.y=pos1.y-2 - check_MV_node_subp (PR_nodes,RE_nodes,MV_nodes,pos1) - pos1.y=pos1.y+1 - - pos1.z=pos1.z+1 - check_MV_node_subp (PR_nodes,RE_nodes,MV_nodes,pos1) - pos1.z=pos1.z-2 - check_MV_node_subp (PR_nodes,RE_nodes,MV_nodes,pos1) - pos1.z=pos1.z+1 -return new_node_added +function check_MV_node(PR_nodes,RE_nodes,BA_nodes,MV_nodes,i) + local pos1={} + pos1.x=MV_nodes[i].x + pos1.y=MV_nodes[i].y + pos1.z=MV_nodes[i].z + + pos1.x=pos1.x+1 + check_MV_node_subp(PR_nodes,RE_nodes,BA_nodes,MV_nodes,pos1) + pos1.x=pos1.x-2 + check_MV_node_subp(PR_nodes,RE_nodes,BA_nodes,MV_nodes,pos1) + pos1.x=pos1.x+1 + + pos1.y=pos1.y+1 + check_MV_node_subp(PR_nodes,RE_nodes,BA_nodes,MV_nodes,pos1) + pos1.y=pos1.y-2 + check_MV_node_subp(PR_nodes,RE_nodes,BA_nodes,MV_nodes,pos1) + pos1.y=pos1.y+1 + + pos1.z=pos1.z+1 + check_MV_node_subp(PR_nodes,RE_nodes,BA_nodes,MV_nodes,pos1) + pos1.z=pos1.z-2 + check_MV_node_subp(PR_nodes,RE_nodes,BA_nodes,MV_nodes,pos1) + pos1.z=pos1.z+1 end -function check_MV_node_subp (PR_nodes,RE_nodes,MV_nodes,pos1) -meta = minetest.env:get_meta(pos1) -if meta:get_float("mv_cablelike")==1 then new_node_added=add_new_MVcable_node(MV_nodes,pos1) end -for i in ipairs(MV_machines) do - if minetest.env:get_node(pos1).name == MV_machines[i].machine_name then - if MV_machines[i].machine_type == "PR" then - new_node_added=add_new_MVcable_node(PR_nodes,pos1) - end - if MV_machines[i].machine_type == "RE" then - new_node_added=add_new_MVcable_node(RE_nodes,pos1) - end - end -end +function check_MV_node_subp (PR_nodes,RE_nodes,BA_nodes,MV_nodes,pos1) + local meta = minetest.env:get_meta(pos1) + local name = minetest.env:get_node(pos1).name + if meta:get_float("mv_cablelike")==1 then + add_new_MVcable_node(MV_nodes,pos1) + elseif MV_machines[name] then + --print(name.." is a "..MV_machines[name]) + if MV_machines[name] == "PR" then + add_new_MVcable_node(PR_nodes,pos1) + elseif MV_machines[name] == "RE" then + add_new_MVcable_node(RE_nodes,pos1) + elseif MV_machines[name] == "BA" then + add_new_MVcable_node(BA_nodes,pos1) + end + end end - diff --git a/technic/chainsaw.lua b/technic/chainsaw.lua index 2c3fbf5..5b3b05b 100644 --- a/technic/chainsaw.lua +++ b/technic/chainsaw.lua @@ -1,63 +1,268 @@ -chainsaw_max_charge=30000 +-- Configuration +local chainsaw_max_charge = 30000 -- 30000 - Maximum charge of the saw +local chainsaw_charge_per_node = 12 -- 12 - Gives 2500 nodes on a single charge (about 50 complete normal trees) +local chainsaw_leaves = true -- true - Cut down entire trees, leaves and all + register_power_tool ("technic:chainsaw",chainsaw_max_charge) minetest.register_tool("technic:chainsaw", { - description = "Chainsaw", - inventory_image = "technic_chainsaw.png", - stack_max = 1, - on_use = function(itemstack, user, pointed_thing) - if pointed_thing.type=="node" then - item=itemstack:to_table() - local meta=get_item_meta(item["metadata"]) - if meta==nil then return end --tool not charghed - if meta["charge"]==nil then return end - charge=meta["charge"] - charge_to_take=600; - if charge-charge_to_take>0 then - charge_to_take=chainsaw_dig_it(minetest.get_pointed_thing_position(pointed_thing, above),user,charge_to_take) - charge=charge-charge_to_take; - set_RE_wear(item,charge,chainsaw_max_charge) - meta["charge"]=charge - item["metadata"]=set_item_meta(meta) - itemstack:replace(item) - return itemstack - end - end - end, + description = "Chainsaw", + inventory_image = "technic_chainsaw.png", + stack_max = 1, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type=="node" then + item=itemstack:to_table() + local meta=get_item_meta(item["metadata"]) + if meta==nil then return end --tool not charged + if meta["charge"]==nil then return end + -- Send current charge to digging function so that the chainsaw will stop after digging a number of nodes. + local charge=meta["charge"] + if charge < chainsaw_charge_per_node then return end -- only cut if charged + + charge=chainsaw_dig_it(minetest.get_pointed_thing_position(pointed_thing, above),user,charge) + set_RE_wear(item,charge,chainsaw_max_charge) + meta["charge"]=charge + item["metadata"]=set_item_meta(meta) + itemstack:replace(item) + return itemstack + end + end, }) minetest.register_craft({ - output = 'technic:chainsaw', - recipe = { - {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:battery'}, - {'technic:stainless_steel_ingot', 'technic:motor', 'technic:battery'}, - {'','','moreores:copper_ingot'}, - } + output = 'technic:chainsaw', + recipe = { + {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:battery'}, + {'technic:stainless_steel_ingot', 'technic:motor', 'technic:battery'}, + {'','','moreores:copper_ingot'}, + } }) +-- The default stuff +local timber_nodenames={["default:jungletree"] = true, + ["default:papyrus"] = true, + ["default:cactus"] = true, + ["default:tree"] = true, + ["default:apple"] = true +} + +if chainsaw_leaves == true then + timber_nodenames["default:leaves"] = true +end + +-- Support moretrees if it is there +if( minetest.get_modpath("moretrees") ~= nil ) then + timber_nodenames["moretrees:apple_tree_trunk"] = true + timber_nodenames["moretrees:apple_tree_trunk_sideways"] = true + timber_nodenames["moretrees:beech_trunk"] = true + timber_nodenames["moretrees:beech_trunk_sideways"] = true + timber_nodenames["moretrees:birch_trunk"] = true + timber_nodenames["moretrees:birch_trunk_sideways"] = true + timber_nodenames["moretrees:fir_trunk"] = true + timber_nodenames["moretrees:fir_trunk_sideways"] = true + timber_nodenames["moretrees:oak_trunk"] = true + timber_nodenames["moretrees:oak_trunk_sideways"] = true + timber_nodenames["moretrees:palm_trunk"] = true + timber_nodenames["moretrees:palm_trunk_sideways"] = true + timber_nodenames["moretrees:pine_trunk"] = true + timber_nodenames["moretrees:pine_trunk_sideways"] = true + timber_nodenames["moretrees:rubber_tree_trunk"] = true + timber_nodenames["moretrees:rubber_tree_trunk_sideways"] = true + timber_nodenames["moretrees:rubber_tree_trunk_empty"] = true + timber_nodenames["moretrees:rubber_tree_trunk_sideways_empty"] = true + timber_nodenames["moretrees:sequoia_trunk"] = true + timber_nodenames["moretrees:sequoia_trunk_sideways"] = true + timber_nodenames["moretrees:spruce_trunk"] = true + timber_nodenames["moretrees:spruce_trunk_sideways"] = true + timber_nodenames["moretrees:willow_trunk"] = true + timber_nodenames["moretrees:willow_trunk_sideways"] = true + timber_nodenames["moretrees:jungletree_trunk"] = true + timber_nodenames["moretrees:jungletree_trunk_sideways"] = true + + if chainsaw_leaves == true then + timber_nodenames["moretrees:apple_tree_leaves"] = true + timber_nodenames["moretrees:oak_leaves"] = true + timber_nodenames["moretrees:sequoia_leaves"] = true + timber_nodenames["moretrees:birch_leaves"] = true + timber_nodenames["moretrees:birch_leaves"] = true + timber_nodenames["moretrees:palm_leaves"] = true + timber_nodenames["moretrees:spruce_leaves"] = true + timber_nodenames["moretrees:spruce_leaves"] = true + timber_nodenames["moretrees:pine_leaves"] = true + timber_nodenames["moretrees:willow_leaves"] = true + timber_nodenames["moretrees:rubber_tree_leaves"] = true + timber_nodenames["moretrees:jungletree_leaves_green"] = true + timber_nodenames["moretrees:jungletree_leaves_yellow"] = true + timber_nodenames["moretrees:jungletree_leaves_red"] = true + end +end + +-- Support growing_trees if it is there +if( minetest.get_modpath("growing_trees") ~= nil ) then + timber_nodenames["growing_trees:trunk"] = true + timber_nodenames["growing_trees:medium_trunk"] = true + timber_nodenames["growing_trees:big_trunk"] = true + timber_nodenames["growing_trees:trunk_top"] = true + timber_nodenames["growing_trees:trunk_sprout"] = true + timber_nodenames["growing_trees:branch_sprout"] = true + timber_nodenames["growing_trees:branch"] = true + timber_nodenames["growing_trees:branch_xmzm"] = true + timber_nodenames["growing_trees:branch_xpzm"] = true + timber_nodenames["growing_trees:branch_xmzp"] = true + timber_nodenames["growing_trees:branch_xpzp"] = true + timber_nodenames["growing_trees:branch_zz"] = true + timber_nodenames["growing_trees:branch_xx"] = true + + if chainsaw_leaves == true then + timber_nodenames["growing_trees:leaves"] = true + end +end + +-- Support growing_cactus if it is there +if( minetest.get_modpath("growing_cactus") ~= nil ) then + timber_nodenames["growing_cactus:sprout"] = true + timber_nodenames["growing_cactus:branch_sprout_vertical"] = true + timber_nodenames["growing_cactus:branch_sprout_vertical_fixed"] = true + timber_nodenames["growing_cactus:branch_sprout_xp"] = true + timber_nodenames["growing_cactus:branch_sprout_xm"] = true + timber_nodenames["growing_cactus:branch_sprout_zp"] = true + timber_nodenames["growing_cactus:branch_sprout_zm"] = true + timber_nodenames["growing_cactus:trunk"] = true + timber_nodenames["growing_cactus:branch_trunk"] = true + timber_nodenames["growing_cactus:branch"] = true + timber_nodenames["growing_cactus:branch_xp"] = true + timber_nodenames["growing_cactus:branch_xm"] = true + timber_nodenames["growing_cactus:branch_zp"] = true + timber_nodenames["growing_cactus:branch_zm"] = true + timber_nodenames["growing_cactus:branch_zz"] = true + timber_nodenames["growing_cactus:branch_xx"] = true +end + +-- Support farming_plus if it is there +if( minetest.get_modpath("farming_plus") ~= nil ) then + if chainsaw_leaves == true then + timber_nodenames["farming_plus:cocoa_leaves"] = true + end +end + +-- Table for saving what was sawed down +local produced + +-- Saw down trees entry point +chainsaw_dig_it = function(pos, player,current_charge) + local remaining_charge=current_charge + + -- Save the currently installed dropping mechanism so we can restore it. + local original_handle_node_drops = minetest.handle_node_drops + + -- A bit of trickery here: use a different node drop callback + -- and restore the original afterwards. + minetest.handle_node_drops = chainsaw_handle_node_drops + + -- clear result and start sawing things down + produced = {} + remaining_charge = recursive_dig(pos, remaining_charge, player) + minetest.sound_play("chainsaw", {pos = pos, gain = 1.0, max_hear_distance = 10,}) + + -- Restore the original noder drop handler + minetest.handle_node_drops = original_handle_node_drops + + -- Now drop items for the player + local number, produced_item, p + for produced_item,number in pairs(produced) do + --print("ADDING ITEM: " .. produced_item .. " " .. number) + -- Drop stacks of 99 or less + p = { + x = pos.x + math.random()*4, + y = pos.y, + z = pos.z + math.random()*4 + } + while number > 99 do + minetest.env:add_item(p, produced_item .. " 99") + p = { + x = pos.x + math.random()*4, + y = pos.y, + z = pos.z + math.random()*4 + } + number = number - 99 + end + minetest.env:add_item(p, produced_item .. " " .. number) + end + return remaining_charge +end + +-- Override the default handling routine to be able to count up the +-- items sawed down so that we can drop them i an nice single stack +chainsaw_handle_node_drops = function(pos, drops, digger) + -- Add dropped items to list of collected nodes + local _, dropped_item + for _, dropped_item in ipairs(drops) do + if produced[dropped_item] == nil then + produced[dropped_item] = 1 + else + produced[dropped_item] = produced[dropped_item] + 1 + end + end +end +-- This function does all the hard work. Recursively we dig the node at hand +-- if it is in the table and then search the surroundings for more stuff to dig. +recursive_dig = function(pos, remaining_charge, player) + local node=minetest.env:get_node(pos) + local i=1 + -- Lookup node name in timber table: + if timber_nodenames[node.name] ~= nil then + -- Return if we are out of power + if remaining_charge < chainsaw_charge_per_node then + return 0 + end + local np + -- wood found - cut it. + minetest.env:dig_node(pos) + remaining_charge=remaining_charge-chainsaw_charge_per_node + -- check surroundings and run recursively if any charge left + np={x=pos.x+1, y=pos.y, z=pos.z} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x+1, y=pos.y, z=pos.z+1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x+1, y=pos.y, z=pos.z-1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end -timber_nodenames={"default:jungletree", "default:papyrus", "default:cactus", "default:tree"} + np={x=pos.x-1, y=pos.y, z=pos.z} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x-1, y=pos.y, z=pos.z+1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x-1, y=pos.y, z=pos.z-1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end -function chainsaw_dig_it (pos, player,charge_to_take) - charge_to_take=0 - local node=minetest.env:get_node(pos) - local i=1 - while timber_nodenames[i]~=nil do - if node.name==timber_nodenames[i] then - charge_to_take=600 - np={x=pos.x, y=pos.y, z=pos.z} - while minetest.env:get_node(np).name==timber_nodenames[i] do - minetest.env:remove_node(np) - minetest.env:add_item(np, timber_nodenames[i]) - np={x=np.x, y=np.y+1, z=np.z} - end - minetest.sound_play("chainsaw", {pos = pos, gain = 1.0, max_hear_distance = 10,}) - return charge_to_take - end - i=i+1 - end + np={x=pos.x, y=pos.y+1, z=pos.z} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end -return charge_to_take + np={x=pos.x, y=pos.y, z=pos.z+1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + np={x=pos.x, y=pos.y, z=pos.z-1} + if timber_nodenames[minetest.env:get_node(np).name] ~= nil then + remaining_charge = recursive_dig(np, remaining_charge) + end + return remaining_charge + end + -- Nothing sawed down + return remaining_charge end diff --git a/technic/cnc.lua b/technic/cnc.lua new file mode 100644 index 0000000..4976502 --- /dev/null +++ b/technic/cnc.lua @@ -0,0 +1,312 @@ +-- Technic CNC v1.0 by kpo +-- Based on the NonCubic Blocks MOD v1.4 by yves_de_beck + +-- Idea: +-- Somehw have a tabbed/paged panel if the number of shapes should expand +-- beyond what is available in the panel today. +-- I could imagine some form of API allowing modders to come with their own node +-- box definitions and easily stuff it in the this machine for production. +local shape = {} +local onesize_products = { + slope = 2, + slope_edge = 1, + slope_inner_edge = 1, + pyramid = 2, + spike = 1, + cylinder = 2, + sphere = 1, + stick = 8, + slope_upsdown = 2, + slope_edge_upsdown = 1, + slope_inner_edge_upsdown = 1, + cylinder_horizontal = 2, + slope_lying = 2, + onecurvededge = 1, + twocurvededge = 1, +} +local twosize_products = { + element_straight = 4, + element_end = 2, + element_cross = 1, + element_t = 1, + element_edge = 2, +} + +--cnc_recipes ={} +--registered_cnc_recipes_count=1 +-- +--function register_cnc_recipe (string1,string2) +-- cnc_recipes[registered_cnc_recipes_count]={} +-- cnc_recipes[registered_cnc_recipes_count].src_name=string1 +-- cnc_recipes[registered_cnc_recipes_count].dst_name=string2 +-- registered_cnc_recipes_count=registered_cnc_recipes_count+1 +-- if unified_inventory then +-- unified_inventory.register_craft({ +-- type = "cnc milling", +-- output = string2, +-- items = {string1}, +-- width = 0, +-- }) +-- end +--end + +local cnc_formspec = + "invsize[9,11;]".. + "label[1,0;Choose Milling Program:]".. + "image_button[1,0.5;1,1;technic_cnc_slope.png;slope; ]".. + "image_button[2,0.5;1,1;technic_cnc_slope_edge.png;slope_edge; ]".. + "image_button[3,0.5;1,1;technic_cnc_slope_inner_edge.png;slope_inner_edge; ]".. + "image_button[4,0.5;1,1;technic_cnc_pyramid.png;pyramid; ]".. + "image_button[5,0.5;1,1;technic_cnc_spike.png;spike; ]".. + "image_button[6,0.5;1,1;technic_cnc_cylinder.png;cylinder; ]".. + "image_button[7,0.5;1,1;technic_cnc_sphere.png;sphere; ]".. + "image_button[8,0.5;1,1;technic_cnc_stick.png;stick; ]".. + + "image_button[1,1.5;1,1;technic_cnc_slope_upsdwn.png;slope_upsdown; ]".. + "image_button[2,1.5;1,1;technic_cnc_slope_edge_upsdwn.png;slope_edge_upsdown; ]".. + "image_button[3,1.5;1,1;technic_cnc_slope_inner_edge_upsdwn.png;slope_inner_edge_upsdown; ]".. + "image_button[4,1.5;1,1;technic_cnc_cylinder_horizontal.png;cylinder_horizontal; ]".. + + "image_button[1,2.5;1,1;technic_cnc_slope_lying.png;slope_lying; ]".. + "image_button[2,2.5;1,1;technic_cnc_onecurvededge.png;onecurvededge; ]".. + "image_button[3,2.5;1,1;technic_cnc_twocurvededge.png;twocurvededge; ]".. + + "label[1,3.5;Slim Elements half / normal height:]".. + + "image_button[1,4;1,0.5;technic_cnc_full.png;full; ]".. + "image_button[1,4.5;1,0.5;technic_cnc_half.png;half; ]".. + "image_button[2,4;1,1;technic_cnc_element_straight.png;element_straight; ]".. + "image_button[3,4;1,1;technic_cnc_element_end.png;element_end; ]".. + "image_button[4,4;1,1;technic_cnc_element_cross.png;element_cross; ]".. + "image_button[5,4;1,1;technic_cnc_element_t.png;element_t; ]".. + "image_button[6,4;1,1;technic_cnc_element_edge.png;element_edge; ]".. + + "label[0, 5.5;In:]".. + "list[current_name;src;0.5,5.5;1,1;]".. + "label[4, 5.5;Out:]".. + "list[current_name;dst;5,5.5;4,1;]".. + + "list[current_player;main;0,7;8,4;]" + + +local cnc_power_formspec= + "label[0,3;Power]".. + "image[0,1;1,2;technic_power_meter_bg.png]" + +local size = 1; + +-- The form handler is declared here because we need it in both the inactive and active modes +-- in order to be able to change programs wile it is running. +local form_handler = function(pos, formname, fields, sender) + -- REGISTER MILLING PROGRAMS AND OUTPUTS: + ------------------------------------------ + -- Program for half/full size + if fields["full"] then + size = 1 + return + end + + if fields["half"] then + size = 2 + return + end + + -- Resolve the node name and the number of items to make + local meta = minetest.env:get_meta(pos) + local inv = meta:get_inventory() + local inputstack = inv:get_stack("src", 1) + local inputname = inputstack:get_name() + local multiplier = 0 + for k, _ in pairs(fields) do + -- Set a multipier for the half/full size capable blocks + if twosize_products[k] ~= nil then + multiplier = size*twosize_products[k] + else + multiplier = onesize_products[k] + end + + if onesize_products[k] ~= nil or twosize_products[k] ~= nil then + meta:set_float( "cnc_multiplier", multiplier) + meta:set_string("cnc_user", sender:get_player_name()) + end + + if onesize_products[k] ~= nil or (twosize_products[k] ~= nil and size==2) then + meta:set_string("cnc_product", inputname .. "_technic_cnc_" .. k) + print(inputname .. "_technic_cnc_" .. k) + break + end + + if twosize_products[k] ~= nil and size==1 then + meta:set_string("cnc_product", inputname .. "_technic_cnc_" .. k .. "_double") + print(inputname .. "_technic_cnc_" .. k .. "_double") + break + end + end + return + end -- callback function + +-- The actual block inactive state +minetest.register_node("technic:cnc", { + description = "CNC Milling Machine", + tiles = {"technic_cnc_top.png", "technic_cnc_bottom.png", "technic_cnc_side.png", + "technic_cnc_side.png", "technic_cnc_side.png", "technic_cnc_front.png"}, + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + + }, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + }, + groups = {cracky=2}, + legacy_facedir_simple = true, + technic_power_machine=1, + internal_EU_buffer=0; + internal_EU_buffer_size=5000; + cnc_time = 0; + src_time = 0; -- fixme + + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_string("infotext", "CNC Machine Inactive") + meta:set_float("technic_power_machine", 1) + meta:set_float("internal_EU_buffer", 0) + meta:set_float("internal_EU_buffer_size", 5000) + meta:set_string("formspec", cnc_formspec..cnc_power_formspec) + meta:set_float("cnc_time", 0) + + local inv = meta:get_inventory() + inv:set_size("src", 1) + inv:set_size("dst", 4) + end, + + can_dig = function(pos,player) + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + if not inv:is_empty("src") or not inv:is_empty("dst") then + minetest.chat_send_player(player:get_player_name(), "CNC machine cannot be removed because it is not empty"); + return false + end + return true + end, + + on_receive_fields = form_handler, + }) + +-- Active state block +minetest.register_node("technic:cnc_active", { + description = "CNC Machine", + tiles = {"technic_cnc_top_active.png", "technic_cnc_bottom.png", "technic_cnc_side.png", + "technic_cnc_side.png", "technic_cnc_side.png", "technic_cnc_front_active.png"}, + paramtype2 = "facedir", + groups = {cracky=2,not_in_creative_inventory=1}, + legacy_facedir_simple = true, + can_dig = function(pos,player) + local meta = minetest.env:get_meta(pos); + local inv = meta:get_inventory() + if not inv:is_empty("src") or not inv:is_empty("dst") then + minetest.chat_send_player(player:get_player_name(), "CNC machine cannot be removed because it is not empty"); + return false + end + return true + end, + on_receive_fields = form_handler, +}) + +-- Action code performing the transformation +minetest.register_abm( + { + nodenames = {"technic:cnc","technic:cnc_active"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.env:get_meta(pos) + local charge= meta:get_float("internal_EU_buffer") + local max_charge= meta:get_float("internal_EU_buffer_size") + local cnc_cost=350 + + local load = math.floor((charge/max_charge)*100) + meta:set_string("formspec", cnc_formspec.. + "image[0,1;1,2;technic_power_meter_bg.png^[lowpart:".. + (load)..":technic_power_meter_fg.png]" + ) + + local inv = meta:get_inventory() + local srclist = inv:get_list("src") + if inv:is_empty("src") then + meta:set_float("cnc_on",0) + meta:set_string("cnc_product", "") -- Reset the program + end + + if (meta:get_float("cnc_on") == 1) then + if charge>=cnc_cost then + charge=charge-cnc_cost; + meta:set_float("internal_EU_buffer",charge) + meta:set_float("src_time", meta:get_float("src_time") + 1) + if meta:get_float("src_time") >= meta:get_float("cnc_time") then + local product = meta:get_string("cnc_product") + if inv:room_for_item("dst",product) then + -- CNC does the transformation + ------------------------------ + if minetest.registered_nodes[product] ~= nil then + inv:add_item("dst",product .. " " .. meta:get_float("cnc_multiplier")) + srcstack = inv:get_stack("src", 1) + srcstack:take_item() + inv:set_stack("src",1,srcstack) + if inv:is_empty("src") then + meta:set_float("cnc_on",0) + meta:set_string("cnc_product", "") -- Reset the program +-- print("cnc product reset") + end + else + minetest.chat_send_player(meta:get_string("cnc_user"), "CNC machine does not know how to handle this material. Please remove it."); + end + else + minetest.chat_send_player(meta:get_string("cnc_user"), "CNC inventory full!") + end + meta:set_float("src_time", 0) + end + end + end + + if (meta:get_float("cnc_on")==0) then + if not inv:is_empty("src") then + local product = meta:get_string("cnc_product") + if minetest.registered_nodes[product] ~= nil then + meta:set_float("cnc_on",1) + hacky_swap_node(pos,"technic:cnc_active") + meta:set_string("infotext", "CNC Machine Active") + cnc_time=3 + meta:set_float("cnc_time",cnc_time) + meta:set_float("src_time", 0) + return + end + else + hacky_swap_node(pos,"technic:cnc") + meta:set_string("infotext", "CNC Machine Inactive") + end + end + end + }) + +register_LV_machine ("technic:cnc","RE") +register_LV_machine ("technic:cnc_active","RE") +------------------------- + +-- CNC Machine Recipe +------------------------- +minetest.register_craft({ + output = 'technic:cnc', + recipe = { + {'default:glass', 'technic:diamond_drill_head', 'default:glass'}, + {'technic:control_logic_unit', 'technic:motor', 'default:steel_ingot'}, + {'default:steel_ingot', 'default:copper_ingot', 'default:steel_ingot'}, + }, + }) +------------------------- \ No newline at end of file diff --git a/technic/cnc_api.lua b/technic/cnc_api.lua new file mode 100644 index 0000000..2d5e305 --- /dev/null +++ b/technic/cnc_api.lua @@ -0,0 +1,372 @@ +-- API for the technic CNC machine +-- Again code is adapted from the NonCubic Blocks MOD v1.4 by yves_de_beck +technic_cnc_api = {} + +-- HERE YOU CAN CHANGE THE DETAIL-LEVEL: +---------------------------------------- +technic_cnc_api.detail_level = 16 -- 16; 1-32 + +-- REGISTER NONCUBIC FORMS, CREATE MODELS AND RECIPES: +------------------------------------------------------ +local cnc_sphere = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + local sehne + for i = 1, detail-1 do + sehne = math.sqrt(0.25 - (((i/detail)-0.5)^2)) + nodebox[i]={-sehne, (i/detail)-0.5, -sehne, sehne, (i/detail)+(1/detail)-0.5, sehne} + end + return nodebox + end + +local cnc_cylinder_horizontal = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + local sehne + for i = 1, detail-1 do + sehne = math.sqrt(0.25 - (((i/detail)-0.5)^2)) + nodebox[i]={-0.5, (i/detail)-0.5, -sehne, 0.5, (i/detail)+(1/detail)-0.5, sehne} + end + return nodebox + end + +local cnc_cylinder = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + local sehne + for i = 1, detail-1 do + sehne = math.sqrt(0.25 - (((i/detail)-0.5)^2)) + nodebox[i]={(i/detail)-0.5, -0.5, -sehne, (i/detail)+(1/detail)-0.5, 0.5, sehne} + end + return nodebox + end + +local cnc_twocurvededge = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level*2 + local sehne + for i = (detail/2)-1, detail-1 do + sehne = math.sqrt(0.25 - (((i/detail)-0.5)^2)) + nodebox[i]={-sehne, -0.5, -sehne, 0.5, (i/detail)+(1/detail)-0.5, 0.5} + end + return nodebox + end + +local cnc_onecurvededge = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level*2 + local sehne + for i = (detail/2)-1, detail-1 do + sehne = math.sqrt(0.25 - (((i/detail)-0.5)^2)) + nodebox[i]={-0.5, -0.5, -sehne, 0.5, (i/detail)+(1/detail)-0.5, 0.5} + end + return nodebox + end + +local cnc_spike = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + for i = 0, detail-1 do + nodebox[i+1]={(i/detail/2)-0.5, (i/detail/2)-0.5, (i/detail/2)-0.5, 0.5-(i/detail/2), (i/detail)-0.5+(1/detail), 0.5-(i/detail/2)} +end + return nodebox + end + +local cnc_pyramid = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level/2 + for i = 0, detail-1 do + nodebox[i+1]={(i/detail/2)-0.5, (i/detail/2)-0.5, (i/detail/2)-0.5, 0.5-(i/detail/2), (i/detail/2)-0.5+(1/detail), 0.5-(i/detail/2)} + end + return nodebox + end + +local cnc_slope_inner_edge_upsdown = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + for i = 0, detail-1 do + nodebox[i+1]={0.5-(i/detail)-(1/detail), (i/detail)-0.5, -0.5, 0.5, (i/detail)-0.5+(1/detail), 0.5} + nodebox[i+detail+1]={-0.5, (i/detail)-0.5, 0.5-(i/detail)-(1/detail), 0.5, (i/detail)-0.5+(1/detail), 0.5} + end + return nodebox + end + +local cnc_slope_edge_upsdown = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + for i = 0, detail-1 do + nodebox[i+1]={(-1*(i/detail))+0.5-(1/detail), (i/detail)-0.5, (-1*(i/detail))+0.5-(1/detail), 0.5, (i/detail)-0.5+(1/detail), 0.5} + end + return nodebox + end + +local cnc_slope_inner_edge = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + for i = 0, detail-1 do + nodebox[i+1]={(i/detail)-0.5, -0.5, -0.5, 0.5, (i/detail)-0.5+(1/detail), 0.5} + nodebox[i+detail+1]={-0.5, -0.5, (i/detail)-0.5, 0.5, (i/detail)-0.5+(1/detail), 0.5} + end + return nodebox + end + +local cnc_slope_edge = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + for i = 0, detail-1 do + nodebox[i+1]={(i/detail)-0.5, -0.5, (i/detail)-0.5, 0.5, (i/detail)-0.5+(1/detail), 0.5} + end + return nodebox + end + +local cnc_slope_upsdown = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + for i = 0, detail-1 do + nodebox[i+1]={-0.5, (i/detail)-0.5, (-1*(i/detail))+0.5-(1/detail), 0.5, (i/detail)-0.5+(1/detail), 0.5} + end + return nodebox + end + +local cnc_slope_lying = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + for i = 0, detail-1 do + nodebox[i+1]={(i/detail)-0.5, -0.5, (i/detail)-0.5, (i/detail)-0.5+(1/detail), 0.5 , 0.5} + end + return nodebox + end + +local cnc_slope = + function() + local nodebox = {} + local detail = technic_cnc_api.detail_level + for i = 0, detail-1 do + nodebox[i+1]={-0.5, (i/detail)-0.5, (i/detail)-0.5, 0.5, (i/detail)-0.5+(1/detail), 0.5} + end + return nodebox + end + +-- Define slope boxes for the various nodes +------------------------------------------- +technic_cnc_api.cnc_programs = { + {suffix = "technic_cnc_stick", + nodebox = {-0.15, -0.5, -0.15, 0.15, 0.5, 0.15}, + desc = "Stick"}, + + {suffix = "technic_cnc_element_end_double", + nodebox = {-0.3, -0.5, -0.3, 0.3, 0.5, 0.5}, + desc = "Element End Double"}, + + {suffix = "technic_cnc_element_cross_double", + nodebox = { + {0.3, -0.5, -0.3, 0.5, 0.5, 0.3}, + {-0.3, -0.5, -0.5, 0.3, 0.5, 0.5}, + {-0.5, -0.5, -0.3, -0.3, 0.5, 0.3}}, + desc = "Element Cross Double"}, + + {suffix = "technic_cnc_element_t_double", + nodebox = { + {-0.3, -0.5, -0.5, 0.3, 0.5, 0.3}, + {-0.5, -0.5, -0.3, -0.3, 0.5, 0.3}, + {0.3, -0.5, -0.3, 0.5, 0.5, 0.3}}, + desc = "Element T Double"}, + + {suffix = "technic_cnc_element_edge_double", + nodebox = { + {-0.3, -0.5, -0.5, 0.3, 0.5, 0.3}, + {-0.5, -0.5, -0.3, -0.3, 0.5, 0.3}}, + desc = "Element Edge Double"}, + + {suffix = "technic_cnc_element_straight_double", + nodebox = {-0.3, -0.5, -0.5, 0.3, 0.5, 0.5}, + desc = "Element Straight Double"}, + + {suffix = "technic_cnc_element_end", + nodebox = {-0.3, -0.5, -0.3, 0.3, 0, 0.5}, + desc = "Element End"}, + + {suffix = "technic_cnc_element_cross", + nodebox = { + {0.3, -0.5, -0.3, 0.5, 0, 0.3}, + {-0.3, -0.5, -0.5, 0.3, 0, 0.5}, + {-0.5, -0.5, -0.3, -0.3, 0, 0.3}}, + desc = "Element Cross"}, + + {suffix = "technic_cnc_element_t", + nodebox = { + {-0.3, -0.5, -0.5, 0.3, 0, 0.3}, + {-0.5, -0.5, -0.3, -0.3, 0, 0.3}, + {0.3, -0.5, -0.3, 0.5, 0, 0.3}}, + desc = "Element T"}, + + {suffix = "technic_cnc_element_edge", + nodebox = { + {-0.3, -0.5, -0.5, 0.3, 0, 0.3}, + {-0.5, -0.5, -0.3, -0.3, 0, 0.3}}, + desc = "Element Edge"}, + + {suffix = "technic_cnc_element_straight", + nodebox = {-0.3, -0.5, -0.5, 0.3, 0, 0.5}, + desc = "Element Straight"}, + + {suffix = "technic_cnc_sphere", + nodebox = cnc_sphere(), + desc = "Sphere"}, + + {suffix = "technic_cnc_cylinder_horizontal", + nodebox = cnc_cylinder_horizontal(), + desc = "Cylinder Horizontal"}, + + {suffix = "technic_cnc_cylinder", + nodebox = cnc_cylinder(), + desc = ""}, + + {suffix = "technic_cnc_twocurvededge", + nodebox = cnc_twocurvededge(), + desc = "One Curved Edge Block"}, + + {suffix = "technic_cnc_onecurvededge", + nodebox = cnc_onecurvededge(), + desc = "Two Curved Edge Block"}, + + {suffix = "technic_cnc_spike", + nodebox = cnc_spike(), + desc = "Spike"}, + + {suffix = "technic_cnc_pyramid", + nodebox = cnc_pyramid(), + desc = "Pyramid"}, + + {suffix = "technic_cnc_slope_inner_edge_upsdown", + nodebox = cnc_slope_inner_edge_upsdown(), + desc = "Slope Upside Down Inner Edge"}, + + {suffix = "technic_cnc_slope_edge_upsdown", + nodebox = cnc_slope_edge_upsdown(), + desc = "Slope Upside Down Edge"}, + + {suffix = "technic_cnc_slope_inner_edge", + nodebox = cnc_slope_inner_edge(), + desc = "Slope Inner Edge"}, + + {suffix = "technic_cnc_slope_edge", + nodebox = cnc_slope_edge(), + desc = "Slope Edge"}, + + {suffix = "technic_cnc_slope_upsdown", + nodebox = cnc_slope_upsdown(), + desc = "Slope Upside Down"}, + + {suffix = "technic_cnc_slope_lying", + nodebox = cnc_slope_lying(), + desc = "Slope Lying"}, + + {suffix = "technic_cnc_slope", + nodebox = cnc_slope(), + desc = "Slope"}, +-- {suffix = "", +-- nodebox =}, +} + +-- Allow disabling certain programs for some node. Default is allowing all types for all nodes +technic_cnc_api.cnc_programs_disable = { + -- ["default:brick"] = {"technic_cnc_stick"}, -- Example: Disallow the stick for brick + -- ... + ["default:dirt"] = {"technic_cnc_sphere", "technic_cnc_slope_upsdown", "technic_cnc_edge", + "technic_cnc_inner_edge", "technic_cnc_slope_edge_upsdown", "technic_cnc_slope_inner_edge_upsdown", + "technic_cnc_stick", "technic_cnc_cylinder_horizontal"} +} + +-- Generic function for registering all the different node types +function technic_cnc_api.register_cnc_program(recipeitem, suffix, nodebox, groups, images, description) + minetest.register_node(":" .. recipeitem .. "_" .. suffix, { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + paramtype2 = "facedir", + walkable = true, + selection_box = { + type = "fixed", + fixed = nodebox + }, + node_box = { + type = "fixed", + fixed = nodebox + }, + groups = groups, + }) +end + +-- function to iterate over all the programs the CNC machine knows +function technic_cnc_api.register_all(recipeitem, groups, images, description) + for _, data in ipairs(technic_cnc_api.cnc_programs) do + -- Disable node creation for disabled node types for some material + local do_register = true + if technic_cnc_api.cnc_programs_disable[recipeitem] ~= nil then + for __, disable in ipairs(technic_cnc_api.cnc_programs_disable[recipeitem]) do + if disable == data.suffix then + do_register = false + end + end + end + -- Create the node if it passes the test + if do_register then + technic_cnc_api.register_cnc_program(recipeitem, data.suffix, data.nodebox, groups, images, description.." "..data.desc) + end + end +end + + +-- REGISTER NEW TECHNIC_CNC_API's PART 2: technic_cnc_api.register_element_end(subname, recipeitem, groups, images, desc_element_xyz) +----------------------------------------------------------------------------------------------------------------------- +function technic_cnc_api.register_slope_edge_etc(recipeitem, groups, images, desc_slope, desc_slope_lying, desc_slope_upsdown, desc_slope_edge, desc_slope_inner_edge, desc_slope_upsdwn_edge, desc_slope_upsdwn_inner_edge, desc_pyramid, desc_spike, desc_onecurvededge, desc_twocurvededge, desc_cylinder, desc_cylinder_horizontal, desc_sphere, desc_element_straight, desc_element_edge, desc_element_t, desc_element_cross, desc_element_end) + + technic_cnc_api.register_slope(recipeitem, groups, images, desc_slope) + technic_cnc_api.register_slope_lying(recipeitem, groups, images, desc_slope_lying) + technic_cnc_api.register_slope_upsdown(recipeitem, groups, images, desc_slope_upsdown) + technic_cnc_api.register_slope_edge(recipeitem, groups, images, desc_slope_edge) + technic_cnc_api.register_slope_inner_edge(recipeitem, groups, images, desc_slope_inner_edge) + technic_cnc_api.register_slope_edge_upsdown(recipeitem, groups, images, desc_slope_upsdwn_edge) + technic_cnc_api.register_slope_inner_edge_upsdown(recipeitem, groups, images, desc_slope_upsdwn_inner_edge) + technic_cnc_api.register_pyramid(recipeitem, groups, images, desc_pyramid) + technic_cnc_api.register_spike(recipeitem, groups, images, desc_spike) + technic_cnc_api.register_onecurvededge(recipeitem, groups, images, desc_onecurvededge) + technic_cnc_api.register_twocurvededge(recipeitem, groups, images, desc_twocurvededge) + technic_cnc_api.register_cylinder(recipeitem, groups, images, desc_cylinder) + technic_cnc_api.register_cylinder_horizontal(recipeitem, groups, images, desc_cylinder_horizontal) + technic_cnc_api.register_sphere(recipeitem, groups, images, desc_sphere) + technic_cnc_api.register_element_straight(recipeitem, groups, images, desc_element_straight) + technic_cnc_api.register_element_edge(recipeitem, groups, images, desc_element_edge) + technic_cnc_api.register_element_t(recipeitem, groups, images, desc_element_t) + technic_cnc_api.register_element_cross(recipeitem, groups, images, desc_element_cross) + technic_cnc_api.register_element_end(recipeitem, groups, images, desc_element_end) +end + +-- REGISTER STICKS: noncubic.register_xyz(recipeitem, groups, images, desc_element_xyz) +------------------------------------------------------------------------------------------------------------ +function technic_cnc_api.register_stick_etc(recipeitem, groups, images, desc_stick) + technic_cnc_api.register_stick(recipeitem, groups, images, desc_stick) +end + +function technic_cnc_api.register_elements(recipeitem, groups, images, desc_element_straight_double, desc_element_edge_double, desc_element_t_double, desc_element_cross_double, desc_element_end_double) + technic_cnc_api.register_element_straight_double(recipeitem, groups, images, desc_element_straight_double) + technic_cnc_api.register_element_edge_double(recipeitem, groups, images, desc_element_edge_double) + technic_cnc_api.register_element_t_double(recipeitem, groups, images, desc_element_t_double) + technic_cnc_api.register_element_cross_double(recipeitem, groups, images, desc_element_cross_double) + technic_cnc_api.register_element_end_double(recipeitem, groups, images, desc_element_end_double) +end diff --git a/technic/cnc_nodes.lua b/technic/cnc_nodes.lua new file mode 100644 index 0000000..3d263b9 --- /dev/null +++ b/technic/cnc_nodes.lua @@ -0,0 +1,70 @@ +-- REGISTER MATERIALS AND PROPERTIES FOR NONCUBIC ELEMENTS: +----------------------------------------------------------- +-- DIRT +------- +technic_cnc_api.register_all("default:dirt", + {snappy=2,choppy=2,oddly_breakable_by_hand=3,not_in_creative_inventory=1}, + {"default_grass.png", "default_dirt.png", "default_grass.png"}, + "Dirt") +technic_cnc_api.cnc_programs_disable["default:dirt"] = {"technic_cnc_sphere", "technic_cnc_slope_upsdown", + "technic_cnc_edge", "technic_cnc_inner_edge", + "technic_cnc_slope_edge_upsdown", "technic_cnc_slope_inner_edge_upsdown", + "technic_cnc_stick", "technic_cnc_cylinder_horizontal"} + +-- TREE +------- +technic_cnc_api.register_all("default:tree", + {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1}, + {"default_tree.png"}, + "Wooden") + +-- WOOD +------- +technic_cnc_api.register_all("default:wood", + {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1}, + {"default_wood.png"}, + "Wooden") +-- STONE +-------- +technic_cnc_api.register_all("default:stone", + {cracky=3,not_in_creative_inventory=1}, + {"default_stone.png"}, + "Stone") +-- COBBLE +--------- +technic_cnc_api.register_all("default:cobble", + {cracky=3,not_in_creative_inventory=1}, + {"default_cobble.png"}, + "Cobble") +-- BRICK +-------- +technic_cnc_api.register_all("default:brick", + {cracky=3,not_in_creative_inventory=1}, + {"default_brick.png"}, + "Brick") + +-- SANDSTONE +------------ +technic_cnc_api.register_all("default:sandstone", + {crumbly=2,cracky=2,not_in_creative_inventory=1}, + {"default_sandstone.png"}, + "Sandstone") + +-- LEAVES +--------- +technic_cnc_api.register_all("default:leaves", + {snappy=2,choppy=2,oddly_breakable_by_hand=3,not_in_creative_inventory=1}, + {"default_leaves.png"}, + "Leaves") +-- TREE +------- +technic_cnc_api.register_all("default:tree", + {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3,wood=1,not_in_creative_inventory=1}, + {"default_tree.png"}, + "Tree") +-- STEEL +-------- +technic_cnc_api.register_all("default:steel", + {snappy=1,bendy=2,cracky=1,melty=2,level=2,not_in_creative_inventory=1}, + {"default_steel_block.png"}, + "Steel") diff --git a/technic/config.lua b/technic/config.lua index f237968..f546cf6 100644 --- a/technic/config.lua +++ b/technic/config.lua @@ -1,7 +1,42 @@ -enable_technic_inventory=true -enable_mining_drill=true -enable_mining_laser=true -enable_flashlight=true -enable_rubber_tree_generation=true -enable_marble_generation=true -enable_granite_generation=true +technic.config = {} + +technic.config.loaded = {} + +technic.config.default = { + enable_mining_drill = "true", + enable_mining_laser = "true", + enable_flashlight = "true", + enable_item_drop = "true", + enable_item_pickup = "true", + enable_rubber_tree_generation = "true", + enable_marble_generation = "true", + enable_granite_generation = "true" +} + +function technic.config:load(filename) + file, error = io.open(filename, "r") + if error then return end + local line = file:read("*l") + while line do + local found, _, setting, value = line:find("^([^#%s=]+)%s?=%s?([^%s#]+)") + if found then + self.loaded[setting] = value + end + line = file:read("*l") + end + file:close() +end + +technic.config:load(minetest.get_worldpath().."/technic.conf") + +function technic.config:get(setting) + if self.loaded[setting] then + return self.loaded[setting] + else + return self.default[setting] + end +end + +function technic.config:getBool(setting) + return string.lower(self:get(setting)) == "true" +end diff --git a/technic/depends.txt b/technic/depends.txt index f034c60..7d2e8c3 100644 --- a/technic/depends.txt +++ b/technic/depends.txt @@ -2,5 +2,4 @@ default moreores pipeworks mesecons -technic_worldgen - +moretrees diff --git a/technic/down_converter_hv.lua b/technic/down_converter_hv.lua new file mode 100644 index 0000000..0e2e16d --- /dev/null +++ b/technic/down_converter_hv.lua @@ -0,0 +1,225 @@ +-- The HV down converter will step down HV EUs to MV EUs +-- If we take the solar panel as calibration then the +-- 1 HVEU = 5 MVEU as we stack 5 MV arrays to get a HV array. +-- The downconverter does of course have a conversion loss. +-- This loses 30% of the power. +-- The converter does not store any energy by itself. +minetest.register_node("technic:down_converter_hv", { + description = "HV Down Converter", + tiles = {"technic_hv_down_converter_top.png", "technic_hv_down_converter_bottom.png", "technic_hv_down_converter_side.png", + "technic_hv_down_converter_side.png", "technic_hv_down_converter_side.png", "technic_hv_down_converter_side.png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + drawtype = "nodebox", + paramtype = "light", + is_ground_content = true, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + }, + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_float("technic_hv_power_machine", 1) + meta:set_float("technic_mv_power_machine", 1) + meta:set_float("internal_EU_buffer",0) + meta:set_float("internal_EU_buffer_size",0) + meta:set_string("infotext", "HV Down Converter") + meta:set_float("active", false) + end, + }) + +minetest.register_craft({ + output = 'technic:down_converter_hv 1', + recipe = { + {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot','technic:stainless_steel_ingot'}, + {'technic:hv_transformer', 'technic:hv_cable', 'technic:mv_transformer'}, + {'technic:hv_cable', 'technic:rubber', 'technic:mv_cable'}, + } +}) + +minetest.register_abm( + {nodenames = {"technic:down_converter_hv"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + -- HV->MV conversion factor + local hv_mv_factor = 5 + -- The maximun charge a single converter can handle. Let's set this to + -- what 5 HV solar arrays can produce - 30% loss (2880*5*0.7) + local max_charge = 10080*hv_mv_factor + + local meta = minetest.env:get_meta(pos) + local meta1 = nil + local pos1 = {} + local available_charge = 0 -- counted in MV units + local used_charge = 0 -- counted in MV units + + -- Index all HV nodes connected to the network + -- HV cable comes in through the bottom + pos1.y = pos.y-1 + pos1.x = pos.x + pos1.z = pos.z + meta1 = minetest.env:get_meta(pos1) + if meta1:get_float("hv_cablelike")~=1 then return end + + local HV_nodes = {} -- HV type + local HV_PR_nodes = {} -- HV type + local HV_BA_nodes = {} -- HV type + + HV_nodes[1] = {} + HV_nodes[1].x = pos1.x + HV_nodes[1].y = pos1.y + HV_nodes[1].z = pos1.z + + local table_index = 1 + repeat + check_HV_node(HV_PR_nodes,nil,HV_BA_nodes,HV_nodes,table_index) + table_index = table_index + 1 + if HV_nodes[table_index] == nil then break end + until false + + --print("HV_nodes: PR="..table.getn(HV_PR_nodes).." BA="..table.getn(HV_BA_nodes)) + + -- Index all MV nodes connected to the network + -- MV cable comes out of the top + pos1.y = pos.y+1 + pos1.x = pos.x + pos1.z = pos.z + meta1 = minetest.env:get_meta(pos1) + if meta1:get_float("mv_cablelike")~=1 then return end + + local MV_nodes = {} -- MV type + local MV_RE_nodes = {} -- MV type + local MV_BA_nodes = {} -- MV type + + MV_nodes[1] = {} + MV_nodes[1].x = pos1.x + MV_nodes[1].y = pos1.y + MV_nodes[1].z = pos1.z + + table_index = 1 + repeat + check_MV_node(nil,MV_RE_nodes,MV_BA_nodes,MV_nodes,table_index) + table_index = table_index + 1 + if MV_nodes[table_index] == nil then break end + until false + + --print("MV_nodes: RE="..table.getn(MV_RE_nodes).." BA="..table.getn(MV_BA_nodes)) + + -- First get available power from all the attached HV suppliers + -- Get the supplier internal EU buffer and read the EUs from it + -- No update yet! + local pos1 +-- FIXME: Until further leave the producers out of it and just let the batteries be the hub +-- for _,pos1 in ipairs(HV_PR_nodes) do +-- meta1 = minetest.env:get_meta(pos1) +-- local internal_EU_buffer = meta1:get_float("internal_EU_buffer") +-- available_charge = available_charge + meta1:get_float("internal_EU_buffer") * hv_mv_factor +-- -- Limit conversion capacity +-- if available_charge > max_charge then +-- available_charge = max_charge +-- break +-- end +-- end +-- --print("Available_charge PR:"..available_charge) + + for _,pos1 in ipairs(HV_BA_nodes) do + meta1 = minetest.env:get_meta(pos1) + local internal_EU_buffer = meta1:get_float("internal_EU_buffer") + available_charge = available_charge + meta1:get_float("internal_EU_buffer") * hv_mv_factor + -- Limit conversion capacity + if available_charge > max_charge then + available_charge = max_charge + break + end + end + --print("Available_charge PR+BA:"..available_charge) + + -- Calculate total number of receivers: + local MV_receivers = table.getn(MV_RE_nodes)+table.getn(MV_BA_nodes) + + -- Next supply power to all connected MV machines + -- Get the power receiver internal EU buffer and give EUs to it + -- Note: for now leave out RE type machines until producers distribute power themselves even without a battery +-- for _,pos1 in ipairs(MV_RE_nodes) do +-- local meta1 = minetest.env:get_meta(pos1) +-- local internal_EU_buffer = meta1:get_float("internal_EU_buffer") +-- local internal_EU_buffer_size = meta1:get_float("internal_EU_buffer_size") +-- local charge_to_give = math.min(4000, available_charge/MV_receivers) -- power rating limit on the MV wire +-- -- How much can this unit take? +-- if internal_EU_buffer+charge_to_give > internal_EU_buffer_size then +-- charge_to_give=internal_EU_buffer_size-internal_EU_buffer +-- end +-- -- If we are emptying the supply take the remainder +-- if available_charge internal_EU_buffer_size then + charge_to_give=internal_EU_buffer_size-internal_EU_buffer + end + --print("charge_to_give2:"..charge_to_give) + -- If we are emptying the supply take the remainder + if available_charge 0 then + internal_EU_buffer = internal_EU_buffer-charge_to_take + meta1:set_float("internal_EU_buffer",internal_EU_buffer) + end + end + + if used_charge>0 then + meta:set_string("infotext", "HV Down Converter is active (HV:"..available_charge.."/MV:"..used_charge..")"); + meta:set_float("active",1) -- used for setting textures someday maybe + else + meta:set_string("infotext", "HV Down Converter is inactive (HV:"..available_charge.."/MV:"..used_charge..")"); + meta:set_float("active",0) -- used for setting textures someday maybe + return + end + end, +}) + +-- This machine does not store energy it receives energy from the HV side and outputs it on the MV side +register_HV_machine ("technic:down_converter_hv","RE") +register_MV_machine ("technic:down_converter_hv","PR") diff --git a/technic/down_converter_mv.lua b/technic/down_converter_mv.lua new file mode 100644 index 0000000..1d26630 --- /dev/null +++ b/technic/down_converter_mv.lua @@ -0,0 +1,226 @@ +-- The MV down converter will step down MV EUs to LV EUs +-- If we take the solar panel as calibration then the +-- 1 MVEU = 5 LVEU as we stack 5 LV arrays to get an MV array. +-- The downconverter does of course have a conversion loss. +-- This loses 30% of the power. +-- The converter does not store any energy by itself. +minetest.register_node( + "technic:down_converter_mv", { + description = "MV Down Converter", + tiles = {"technic_mv_down_converter_top.png", "technic_mv_down_converter_bottom.png", "technic_mv_down_converter_side.png", + "technic_mv_down_converter_side.png", "technic_mv_down_converter_side.png", "technic_mv_down_converter_side.png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + drawtype = "nodebox", + paramtype = "light", + is_ground_content = true, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + }, + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_float("technic_mv_power_machine", 1) + meta:set_float("technic_power_machine", 1) + meta:set_float("internal_EU_buffer",0) + meta:set_float("internal_EU_buffer_size",0) + meta:set_string("infotext", "MV Down Converter") + meta:set_float("active", false) + end, + }) + +minetest.register_craft({ + output = 'technic:down_converter_mv 1', + recipe = { + {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot','technic:stainless_steel_ingot'}, + {'technic:mv_transformer', 'technic:mv_cable', 'technic:lv_transformer'}, + {'technic:mv_cable', 'technic:rubber', 'technic:lv_cable'}, + } +}) + +minetest.register_abm( + {nodenames = {"technic:down_converter_mv"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + -- MV->LV conversion factor + local mv_lv_factor = 5 + -- The maximun charge a single converter can handle. Let's set this to + -- what 5 MV solar arrays can produce - 30% loss (720*5*0.7) + local max_charge = 2520*mv_lv_factor + + local meta = minetest.env:get_meta(pos) + local meta1 = nil + local pos1 = {} + local available_charge = 0 -- counted in LV units + local used_charge = 0 -- counted in LV units + + -- Index all MV nodes connected to the network + -- MV cable comes in through the bottom + pos1.y = pos.y-1 + pos1.x = pos.x + pos1.z = pos.z + meta1 = minetest.env:get_meta(pos1) + if meta1:get_float("mv_cablelike")~=1 then return end + + local MV_nodes = {} -- MV type + local MV_PR_nodes = {} -- MV type + local MV_BA_nodes = {} -- MV type + + MV_nodes[1] = {} + MV_nodes[1].x = pos1.x + MV_nodes[1].y = pos1.y + MV_nodes[1].z = pos1.z + + local table_index = 1 + repeat + check_MV_node(MV_PR_nodes,nil,MV_BA_nodes,MV_nodes,table_index) + table_index = table_index + 1 + if MV_nodes[table_index] == nil then break end + until false + + --print("MV_nodes: PR="..table.getn(MV_PR_nodes).." BA="..table.getn(MV_BA_nodes)) + + -- Index all LV nodes connected to the network + -- LV cable comes out of the top + pos1.y = pos.y+1 + pos1.x = pos.x + pos1.z = pos.z + meta1 = minetest.env:get_meta(pos1) + if meta1:get_float("cablelike")~=1 then return end + + local LV_nodes = {} -- LV type + local LV_RE_nodes = {} -- LV type + local LV_BA_nodes = {} -- LV type + + LV_nodes[1] = {} + LV_nodes[1].x = pos1.x + LV_nodes[1].y = pos1.y + LV_nodes[1].z = pos1.z + + table_index = 1 + repeat + check_LV_node(nil,LV_RE_nodes,LV_BA_nodes,LV_nodes,table_index) + table_index = table_index + 1 + if LV_nodes[table_index] == nil then break end + until false + + --print("LV_nodes: RE="..table.getn(LV_RE_nodes).." BA="..table.getn(LV_BA_nodes)) + + -- First get available power from all the attached MV suppliers + -- Get the supplier internal EU buffer and read the EUs from it + -- No update yet! + local pos1 +-- FIXME: Until further leave the producers out of it and just let the batteries be the hub +-- for _,pos1 in ipairs(MV_PR_nodes) do +-- meta1 = minetest.env:get_meta(pos1) +-- local internal_EU_buffer = meta1:get_float("internal_EU_buffer") +-- available_charge = available_charge + meta1:get_float("internal_EU_buffer") * mv_lv_factor +-- -- Limit conversion capacity +-- if available_charge > max_charge then +-- available_charge = max_charge +-- break +-- end +-- end +-- print("Available_charge PR:"..available_charge) + + for _,pos1 in ipairs(MV_BA_nodes) do + meta1 = minetest.env:get_meta(pos1) + local internal_EU_buffer = meta1:get_float("internal_EU_buffer") + available_charge = available_charge + meta1:get_float("internal_EU_buffer") * mv_lv_factor + -- Limit conversion capacity + if available_charge > max_charge then + available_charge = max_charge + break + end + end + --print("Available_charge PR+BA:"..available_charge) + + -- Calculate total number of receivers: + local LV_receivers = table.getn(LV_RE_nodes)+table.getn(LV_BA_nodes) + + -- Next supply power to all connected LV machines + -- Get the power receiver internal EU buffer and give EUs to it + -- Note: for now leave out RE type machines until producers distribute power themselves even without a battery +-- for _,pos1 in ipairs(LV_RE_nodes) do +-- local meta1 = minetest.env:get_meta(pos1) +-- local internal_EU_buffer = meta1:get_float("internal_EU_buffer") +-- local internal_EU_buffer_size = meta1:get_float("internal_EU_buffer_size") +-- local charge_to_give = math.min(1000, available_charge/LV_receivers) -- power rating limit on the LV wire +-- -- How much can this unit take? +-- if internal_EU_buffer+charge_to_give > internal_EU_buffer_size then +-- charge_to_give=internal_EU_buffer_size-internal_EU_buffer +-- end +-- -- If we are emptying the supply take the remainder +-- if available_charge internal_EU_buffer_size then + charge_to_give=internal_EU_buffer_size-internal_EU_buffer + end + --print("charge_to_give2:"..charge_to_give) + -- If we are emptying the supply take the remainder + if available_charge 0 then + internal_EU_buffer = internal_EU_buffer-charge_to_take + meta1:set_float("internal_EU_buffer",internal_EU_buffer) + end + end + + if used_charge>0 then + meta:set_string("infotext", "MV Down Converter is active (MV:"..available_charge.."/LV:"..used_charge..")"); + meta:set_float("active",1) -- used for setting textures someday maybe + else + meta:set_string("infotext", "MV Down Converter is inactive (MV:"..available_charge.."/LV:"..used_charge..")"); + meta:set_float("active",0) -- used for setting textures someday maybe + return + end + end, +}) + +-- This machine does not store energy it receives energy from the MV side and outputs it on the LV side +register_MV_machine ("technic:down_converter_mv","RE") +register_LV_machine ("technic:down_converter_mv","PR") diff --git a/technic/geothermal.lua b/technic/geothermal.lua index 93aa423..dccabf4 100644 --- a/technic/geothermal.lua +++ b/technic/geothermal.lua @@ -4,8 +4,8 @@ minetest.register_craft({ output = 'technic:geothermal', recipe = { {'default:stone', 'default:stone', 'default:stone'}, - {'moreores:copper_ingot', 'technic:diamond', 'moreores:copper_ingot'}, - {'default:stone', 'moreores:copper_ingot', 'default:stone'}, + {'default:copper_ingot', 'default:diamond', 'default:copper_ingot'}, + {'default:stone', 'default:copper_ingot', 'default:stone'}, } }) diff --git a/technic/grinder.lua b/technic/grinder.lua index 851352b..07baa05 100644 --- a/technic/grinder.lua +++ b/technic/grinder.lua @@ -7,11 +7,12 @@ grinder_recipes[registered_grinder_recipes_count]={} grinder_recipes[registered_grinder_recipes_count].src_name=string1 grinder_recipes[registered_grinder_recipes_count].dst_name=string2 registered_grinder_recipes_count=registered_grinder_recipes_count+1 -if UI_recipes_hook then - minetest.register_craft({ +if unified_inventory then + unified_inventory.register_craft({ type = "grinding", output = string2, - recipe = string1, + items = {string1}, + width = 0, }) end end @@ -20,26 +21,36 @@ register_grinder_recipe("default:stone","default:sand") register_grinder_recipe("default:cobble","default:gravel") register_grinder_recipe("default:gravel","default:dirt") register_grinder_recipe("default:desert_stone","default:desert_sand") -register_grinder_recipe("default:iron_lump","technic:iron_dust 2") -register_grinder_recipe("default:coal_lump","technic:coal_dust 2") -register_grinder_recipe("moreores:copper_lump","technic:copper_dust 2") +register_grinder_recipe("default:iron_lump","technic:iron_dust 2") +register_grinder_recipe("default:steel_ingot","technic:iron_dust 1") +register_grinder_recipe("default:coal_lump","technic:coal_dust 2") register_grinder_recipe("default:copper_lump","technic:copper_dust 2") -register_grinder_recipe("moreores:tin_lump","technic:tin_dust 2") +register_grinder_recipe("default:copper_ingot","technic:copper_dust 1") +register_grinder_recipe("default:gold_lump","technic:gold_dust 2") +register_grinder_recipe("default:gold_ingot","technic:gold_dust 1") +--register_grinder_recipe("default:bronze_ingot","technic:bronze_dust 1") -- Dust does not exist yet +--register_grinder_recipe("home_decor:brass_ingot","technic:brass_dust 1") -- needs check for the mod +register_grinder_recipe("moreores:tin_lump","technic:tin_dust 2") +register_grinder_recipe("moreores:tin_ingot","technic:tin_dust 1") register_grinder_recipe("moreores:silver_lump","technic:silver_dust 2") -register_grinder_recipe("moreores:gold_lump","technic:gold_dust 2") -register_grinder_recipe("default:gold_lump","technic:gold_dust 2") -register_grinder_recipe("moreores:mithril_lump","technic:mithril_dust 2") -register_grinder_recipe("technic:chromium_lump","technic:chromium_dust 2") -register_grinder_recipe("technic:zinc_lump","technic:zinc_dust 2") -register_grinder_recipe("technic:coal_dust","dye:black 2") -register_grinder_recipe("default:cactus","dye:green 2") -register_grinder_recipe("default:dry_shrub","dye:brown 2") -register_grinder_recipe("flowers:flower_geranium","dye:blue 2") -register_grinder_recipe("flowers:flower_dandelion_white","dye:white 2") -register_grinder_recipe("flowers:flower_dandelion_yellow","dye:yellow 2") -register_grinder_recipe("flowers:flower_tulip","dye:orange 2") -register_grinder_recipe("flowers:flower_rose","dye:red 2") -register_grinder_recipe("flowers:flower_viola","dye:violet 2") +register_grinder_recipe("moreores:silver_ingot","technic:silver_dust 1") +register_grinder_recipe("moreores:mithril_lump","technic:mithril_dust 2") +register_grinder_recipe("moreores:mithril_ingot","technic:mithril_dust 1") +register_grinder_recipe("technic:chromium_lump","technic:chromium_dust 2") +register_grinder_recipe("technic:chromium_ingot","technic:chromium_dust 1") +register_grinder_recipe("technic:stainless_steel_ingot","stainless_steel_dust 1") +register_grinder_recipe("technic:brass_ingot","technic:brass_dust 1") +register_grinder_recipe("technic:zinc_lump","technic:zinc_dust 2") +register_grinder_recipe("technic:zinc_ingot","technic:zinc_dust 1") +register_grinder_recipe("technic:coal_dust","dye:black 2") +register_grinder_recipe("default:cactus","dye:green 2") +register_grinder_recipe("default:dry_shrub","dye:brown 2") +register_grinder_recipe("flowers:flower_geranium","dye:blue 2") +register_grinder_recipe("flowers:flower_dandelion_white","dye:white 2") +register_grinder_recipe("flowers:flower_dandelion_yellow","dye:yellow 2") +register_grinder_recipe("flowers:flower_tulip","dye:orange 2") +register_grinder_recipe("flowers:flower_rose","dye:red 2") +register_grinder_recipe("flowers:flower_viola","dye:violet 2") minetest.register_craftitem( "technic:coal_dust", { description = "Coal Dust", @@ -57,7 +68,7 @@ minetest.register_craft({ type = "cooking", output = "default:steel_ingot", recipe = "technic:iron_dust", -}) +}) minetest.register_craftitem( "technic:copper_dust", { description = "Copper Dust", @@ -68,7 +79,7 @@ minetest.register_craft({ type = "cooking", output = "moreores:copper_ingot", recipe = "technic:copper_dust", -}) +}) minetest.register_craftitem( "technic:tin_dust", { description = "Tin Dust", @@ -79,7 +90,7 @@ minetest.register_craft({ type = "cooking", output = "moreores:tin_ingot", recipe = "technic:tin_dust", -}) +}) minetest.register_craftitem( "technic:silver_dust", { description = "Silver Dust", @@ -90,7 +101,7 @@ minetest.register_craft({ type = "cooking", output = "moreores:silver_ingot", recipe = "technic:silver_dust", -}) +}) minetest.register_craftitem( "technic:gold_dust", { description = "Gold Dust", @@ -101,7 +112,7 @@ minetest.register_craft({ type = "cooking", output = "moreores:gold_ingot", recipe = "technic:gold_dust", -}) +}) minetest.register_craftitem( "technic:mithril_dust", { description = "Mithril Dust", @@ -112,7 +123,7 @@ minetest.register_craft({ type = "cooking", output = "moreores:mithril_ingot", recipe = "technic:mithril_dust", -}) +}) minetest.register_craftitem( "technic:chromium_dust", { description = "Chromium Dust", @@ -123,7 +134,7 @@ minetest.register_craft({ type = "cooking", output = "technic:chromium_ingot", recipe = "technic:chromium_dust", -}) +}) minetest.register_craftitem( "technic:bronze_dust", { description = "Bronze Dust", @@ -134,7 +145,7 @@ minetest.register_craft({ type = "cooking", output = "moreores:bronze_ingot", recipe = "technic:bronze_dust", -}) +}) minetest.register_craftitem( "technic:brass_dust", { description = "Brass Dust", @@ -145,7 +156,7 @@ minetest.register_craft({ type = "cooking", output = "technic:brass_ingot", recipe = "technic:brass_dust", -}) +}) minetest.register_craftitem( "technic:stainless_steel_dust", { description = "Stainless Steel Dust", @@ -156,7 +167,7 @@ minetest.register_craft({ type = "cooking", output = "technic:stainless_steel_ingot", recipe = "technic:stainless_steel_dust", -}) +}) minetest.register_craftitem( "technic:zinc_dust", { description = "Zinc Dust", @@ -167,7 +178,7 @@ minetest.register_craft({ type = "cooking", output = "technic:zinc_ingot", recipe = "technic:zinc_dust", -}) +}) minetest.register_alias("grinder", "technic:grinder") minetest.register_craft({ @@ -182,7 +193,7 @@ minetest.register_craft({ minetest.register_craftitem("technic:grinder", { description = "Grinder", stack_max = 99, -}) +}) grinder_formspec = "invsize[8,9;]".. @@ -279,7 +290,7 @@ minetest.register_abm({ local inv = meta:get_inventory() local srclist = inv:get_list("src") - if inv:is_empty("src") then meta:set_float("grinder_on",0) end + if inv:is_empty("src") then meta:set_float("grinder_on",0) end if (meta:get_float("grinder_on") == 1) then if charge>=grind_cost then @@ -288,7 +299,7 @@ minetest.register_abm({ meta:set_float("src_time", meta:get_float("src_time") + 1) if meta:get_float("src_time") >= meta:get_float("grind_time") then -- check if there's room for output in "dst" list - grinded = get_grinded_item (inv:get_stack("src", 1)) + grinded = get_grinded_item (inv:get_stack("src", 1)) if inv:room_for_item("dst",grinded) then -- Put result in "dst" list inv:add_item("dst", grinded) @@ -296,7 +307,7 @@ minetest.register_abm({ srcstack = inv:get_stack("src", 1) srcstack:take_item() inv:set_stack("src", 1, srcstack) - if inv:is_empty("src") then meta:set_float("grinder_on",0) end + if inv:is_empty("src") then meta:set_float("grinder_on",0) end else print("Grinder inventory full!") end @@ -305,10 +316,10 @@ minetest.register_abm({ end end if (meta:get_float("grinder_on")==0) then - local grinded=nil + local grinded=nil if not inv:is_empty("src") then grinded = get_grinded_item (inv:get_stack("src", 1)) - if grinded then + if grinded then meta:set_float("grinder_on",1) hacky_swap_node(pos,"technic:grinder_active") meta:set_string("infotext", "Grinder Active") @@ -317,13 +328,13 @@ minetest.register_abm({ meta:set_float("src_time", 0) return end - else + else hacky_swap_node(pos,"technic:grinder") meta:set_string("infotext", "Grinder Inactive") end end end -}) +}) function get_grinded_item (items) new_item =nil diff --git a/technic/init.lua b/technic/init.lua index 58e0488..2248295 100644 --- a/technic/init.lua +++ b/technic/init.lua @@ -2,6 +2,8 @@ -- namespace: technic -- (c) 2012-2013 by RealBadAngel +technic = {} + modpath=minetest.get_modpath("technic") --Read technic config file @@ -18,6 +20,7 @@ dofile(modpath.."/battery_box.lua") dofile(modpath.."/alloy_furnaces_commons.lua") dofile(modpath.."/alloy_furnace.lua") dofile(modpath.."/solar_panel.lua") +dofile(modpath.."/solar_array_lv.lua") dofile(modpath.."/geothermal.lua") dofile(modpath.."/water_mill.lua") dofile(modpath.."/electric_furnace.lua") @@ -25,19 +28,29 @@ dofile(modpath.."/tool_workshop.lua") dofile(modpath.."/music_player.lua") dofile(modpath.."/generator.lua") dofile(modpath.."/grinder.lua") +dofile(modpath.."/cnc.lua") +dofile(modpath.."/cnc_api.lua") +dofile(modpath.."/cnc_nodes.lua") --MV machines dofile(modpath.."/wires_mv.lua") dofile(modpath.."/battery_box_mv.lua") -dofile(modpath.."/solar_panel_mv.lua") +dofile(modpath.."/solar_array_mv.lua") +dofile(modpath.."/down_converter_mv.lua") dofile(modpath.."/electric_furnace_mv.lua") dofile(modpath.."/alloy_furnace_mv.lua") dofile(modpath.."/forcefield.lua") +--HV machines +dofile(modpath.."/wires_hv.lua") +dofile(modpath.."/battery_box_hv.lua") +dofile(modpath.."/solar_array_hv.lua") +dofile(modpath.."/down_converter_hv.lua") + --Tools -if enable_mining_drill==true then dofile(modpath.."/mining_drill.lua") end -if enable_mining_laser==true then dofile(modpath.."/mining_laser_mk1.lua") end -if enable_flashlight==true then dofile(modpath.."/flashlight.lua") end +if technic.config:getBool("enable_mining_drill") then dofile(modpath.."/mining_drill.lua") end +if technic.config:getBool("enable_mining_laser") then dofile(modpath.."/mining_laser_mk1.lua") end +if technic.config:getBool("enable_flashlight") then dofile(modpath.."/flashlight.lua") end dofile(modpath.."/cans.lua") dofile(modpath.."/chainsaw.lua") dofile(modpath.."/tree_tap.lua") diff --git a/technic/items.lua b/technic/items.lua index 7d18570..66c5c85 100644 --- a/technic/items.lua +++ b/technic/items.lua @@ -160,6 +160,21 @@ minetest.register_craft({ } }) +minetest.register_craftitem( "technic:lv_transformer", { + description = "Low Voltage Transformer", + inventory_image = "technic_lv_transformer.png", + on_place_on_ground = minetest.craftitem_place_item, +}) + +minetest.register_craft({ + output = 'technic:lv_transformer', + recipe = { + {'default:iron_lump', 'default:iron_lump', 'default:iron_lump'}, + {'technic:copper_coil', 'default:iron_lump', 'technic:copper_coil'}, + {'default:iron_lump', 'default:iron_lump', 'default:iron_lump'}, + } +}) + minetest.register_craftitem( "technic:mv_transformer", { description = "Medium Voltage Transformer", inventory_image = "technic_mv_transformer.png", @@ -175,6 +190,21 @@ minetest.register_craft({ } }) +minetest.register_craftitem( "technic:hv_transformer", { + description = "High Voltage Transformer", + inventory_image = "technic_hv_transformer.png", + on_place_on_ground = minetest.craftitem_place_item, +}) + +minetest.register_craft({ + output = 'technic:hv_transformer', + recipe = { + {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot'}, + {'technic:copper_coil', 'technic:stainless_steel_ingot', 'technic:copper_coil'}, + {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot'}, + } +}) + minetest.register_craftitem( "technic:control_logic_unit", { description = "Control Logic Unit", inventory_image = "technic_control_logic_unit.png", diff --git a/technic/mining_drill.lua b/technic/mining_drill.lua index 86c18ac..33a8e5a 100644 --- a/technic/mining_drill.lua +++ b/technic/mining_drill.lua @@ -217,11 +217,11 @@ minetest.register_tool("technic:mining_drill", { stack_max = 1, on_use = function(itemstack, user, pointed_thing) if pointed_thing.type=="node" then - item=itemstack:to_table() + local item=itemstack:to_table() local meta=get_item_meta(item["metadata"]) if meta==nil then return end --tool not charghed if meta["charge"]==nil then return end - charge=meta["charge"] + local charge=meta["charge"] if charge-mining_drill_power_usage>0 then charge_to_take=drill_dig_it(minetest.get_pointed_thing_position(pointed_thing, above),user,1,1) charge =charge-mining_drill_power_usage; @@ -287,7 +287,7 @@ function mining_drill_mk2_handler (itemstack,user,pointed_thing) local keys=user:get_player_control() local player_name=user:get_player_name() local item=itemstack:to_table() - meta=get_item_meta(item["metadata"]) + local meta=get_item_meta(item["metadata"]) if meta==nil or keys["sneak"]==true then return mining_drill_mk2_setmode(user,itemstack) end if meta["mode"]==nil then return mining_drill_mk2_setmode(user,itemstack) end if pointed_thing.type~="node" then return end @@ -309,14 +309,13 @@ function mining_drill_mk3_handler (itemstack,user,pointed_thing) local keys=user:get_player_control() local player_name=user:get_player_name() local item=itemstack:to_table() - meta=get_item_meta(item["metadata"]) + local meta=get_item_meta(item["metadata"]) if meta==nil or keys["sneak"]==true then return mining_drill_mk3_setmode(user,itemstack) end if meta["mode"]==nil then return mining_drill_mk3_setmode(user,itemstack) end if pointed_thing.type~="node" then return end if meta["charge"]==nil then return end - charge=meta["charge"] + local charge=meta["charge"] if charge-mining_drill_power_usage>0 then - print(dump(meta)) local charge_to_take=drill_dig_it(minetest.get_pointed_thing_position(pointed_thing, above),user,3,meta["mode"]) charge=charge-charge_to_take; if charge<0 then charge=0 end diff --git a/technic/rubber.lua b/technic/rubber.lua index 0e530ff..6ec9731 100644 --- a/technic/rubber.lua +++ b/technic/rubber.lua @@ -88,14 +88,12 @@ minetest.register_abm({ end }) -minetest.register_on_generated(function(minp, maxp, blockseed) - if math.random(1, 100) > 5 then - return - end - local tmp = {x=(maxp.x-minp.x)/2+minp.x, y=(maxp.y-minp.y)/2+minp.y, z=(maxp.z-minp.z)/2+minp.z} - local pos = minetest.env:find_node_near(tmp, maxp.x-minp.x, {"default:dirt_with_grass"}) - if pos ~= nil then - rubber_tree={ +if technic.config:getBool("enable_rubber_tree_generation") then + minetest.register_on_generated(function(minp, maxp, blockseed) + if math.random(1, 100) > 5 then + return + end + local rubber_tree={ axiom="FFFFA", rules_a="[&FFBFA]////[&BFFFA]////[&FBFFA]", rules_b="[&FFA]////[&FFA]////[&FFA]", @@ -107,10 +105,14 @@ minetest.register_on_generated(function(minp, maxp, blockseed) thin_trunks=false; fruit_tree=false, fruit="" - } - minetest.env:spawn_tree({x=pos.x, y=pos.y+1, z=pos.z},rubber_tree) - end -end) + } + local tmp = {x=(maxp.x-minp.x)/2+minp.x, y=(maxp.y-minp.y)/2+minp.y, z=(maxp.z-minp.z)/2+minp.z} + local pos = minetest.env:find_node_near(tmp, maxp.x-minp.x, {"default:dirt_with_grass"}) + if pos ~= nil then + minetest.env:spawn_tree({x=pos.x, y=pos.y+1, z=pos.z}, rubber_tree) + end + end) +end -- ========= FUEL ========= diff --git a/technic/solar_array_hv.lua b/technic/solar_array_hv.lua new file mode 100644 index 0000000..e159248 --- /dev/null +++ b/technic/solar_array_hv.lua @@ -0,0 +1,93 @@ +-- The high voltage solar array is an assembly of medium voltage arrays. +-- The assembly can deliver high voltage levels and is a 20% less efficient +-- compared to 5 individual medium voltage arrays due to losses in the transformer. +-- However high voltage is supplied. +-- Solar arrays are not able to store large amounts of energy. +minetest.register_node("technic:solar_array_hv", { + tiles = {"technic_hv_solar_array_top.png", "technic_hv_solar_array_bottom.png", "technic_hv_solar_array_side.png", + "technic_hv_solar_array_side.png", "technic_hv_solar_array_side.png", "technic_hv_solar_array_side.png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + description="HV Solar Array", + active = false, + technic_hv_power_machine=1, + internal_EU_buffer=0; + internal_EU_buffer_size=3000; + drawtype = "nodebox", + paramtype = "light", + is_ground_content = true, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_float("technic_hv_power_machine", 1) + meta:set_float("internal_EU_buffer", 0) + meta:set_float("internal_EU_buffer_size", 3000) + + meta:set_string("infotext", "HV Solar Array") + meta:set_float("active", false) + end, +}) + +minetest.register_craft({ + output = 'technic:solar_array_hv 1', + recipe = { + {'technic:solar_array_mv', 'technic:solar_array_mv','technic:solar_array_mv'}, + {'technic:solar_array_mv', 'technic:hv_transformer','technic:solar_array_mv'}, + {'default:steel_ingot', 'technic:hv_cable', 'default:steel_ingot'}, + + } +}) + +minetest.register_abm( + {nodenames = {"technic:solar_array_hv"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + -- The action here is to make the solar array produce power + -- Power is dependent on the light level and the height above ground + -- 130m and above is optimal as it would be above cloud level. + -- Height gives 1/4 of the effect, light 3/4. Max. effect is 2880EU for the array. + -- There are many ways to cheat by using other light sources like lamps. + -- As there is no way to determine if light is sunlight that is just a shame. + -- To take care of some of it solar panels do not work outside daylight hours or if + -- built below -10m + local pos1={} + pos1.y=pos.y+1 + pos1.x=pos.x + pos1.z=pos.z + + local light = minetest.env:get_node_light(pos1, nil) + local time_of_day = minetest.env:get_timeofday() + local meta = minetest.env:get_meta(pos) + if light == nil then light = 0 end + -- turn on array only during day time and if sufficient light + -- I know this is counter intuitive when cheating by using other light sources. + if light >= 12 and time_of_day>=0.24 and time_of_day<=0.76 and pos.y > -10 then + local internal_EU_buffer = meta:get_float("internal_EU_buffer") + local internal_EU_buffer_size = meta:get_float("internal_EU_buffer_size") + local charge_to_give = math.floor(light*(light*9.6+pos1.y/130*48)) + if charge_to_give<0 then charge_to_give=0 end + if charge_to_give>2880 then charge_to_give=2880 end + if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then + charge_to_give=internal_EU_buffer_size-internal_EU_buffer + end + meta:set_string("infotext", "Solar Array is active ("..charge_to_give.."EU)") + meta:set_float("active",1) + internal_EU_buffer=internal_EU_buffer+charge_to_give + meta:set_float("internal_EU_buffer",internal_EU_buffer) + + else + meta:set_string("infotext", "Solar Array is inactive"); + meta:set_float("active",0) + end + end, +}) + +register_HV_machine ("technic:solar_array_hv","PR") diff --git a/technic/solar_array_lv.lua b/technic/solar_array_lv.lua new file mode 100644 index 0000000..f657814 --- /dev/null +++ b/technic/solar_array_lv.lua @@ -0,0 +1,94 @@ +-- The solar array is an assembly of panels into a powerful array +-- The assembly can deliver more energy than the individual panel because +-- of the transformer unit which converts the panel output variations into +-- a stable supply. +-- Solar arrays are not able to store large amounts of energy. +-- The LV arrays are used to make medium voltage arrays. +minetest.register_node("technic:solar_array_lv", { + tiles = {"technic_lv_solar_array_top.png", "technic_lv_solar_array_bottom.png", "technic_lv_solar_array_side.png", + "technic_lv_solar_array_side.png", "technic_lv_solar_array_side.png", "technic_lv_solar_array_side.png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + description="LV Solar Array", + active = false, + technic_power_machine=1, + internal_EU_buffer=0; + internal_EU_buffer_size=1000; + drawtype = "nodebox", + paramtype = "light", + is_ground_content = true, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_float("technic_power_machine", 1) + meta:set_float("internal_EU_buffer", 0) + meta:set_float("internal_EU_buffer_size", 1000) + + meta:set_string("infotext", "LV Solar Array") + meta:set_float("active", false) + end, +}) + +minetest.register_craft({ + output = 'technic:solar_array_lv 1', + recipe = { + {'technic:solar_panel', 'technic:solar_panel', 'technic:solar_panel'}, + {'technic:solar_panel', 'technic:lv_transformer', 'technic:solar_panel'}, + {'default:steel_ingot', 'technic:lv_cable', 'default:steel_ingot'}, + + } +}) + +minetest.register_abm( + {nodenames = {"technic:solar_array_lv"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + -- The action here is to make the solar array produce power + -- Power is dependent on the light level and the height above ground + -- 130m and above is optimal as it would be above cloud level. + -- Height gives 1/4 of the effect, light 3/4. Max. effect is 160EU for the array. + -- There are many ways to cheat by using other light sources like lamps. + -- As there is no way to determine if light is sunlight that is just a shame. + -- To take care of some of it solar arrays do not work outside daylight hours or if + -- built below -10m + local pos1={} + pos1.y=pos.y+1 + pos1.x=pos.x + pos1.z=pos.z + + local light = minetest.env:get_node_light(pos1, nil) + local time_of_day = minetest.env:get_timeofday() + local meta = minetest.env:get_meta(pos) + if light == nil then light = 0 end + -- turn on array only during day time and if sufficient light + -- I know this is counter intuitive when cheating by using other light sources. + if light >= 12 and time_of_day>=0.24 and time_of_day<=0.76 and pos.y > -10 then + local internal_EU_buffer = meta:get_float("internal_EU_buffer") + local internal_EU_buffer_size = meta:get_float("internal_EU_buffer_size") + local charge_to_give = math.floor(light*(light*0.5333+pos1.y/130*2.6667)) + if charge_to_give<0 then charge_to_give=0 end + if charge_to_give>160 then charge_to_give=160 end + if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then + charge_to_give=internal_EU_buffer_size-internal_EU_buffer + end + meta:set_string("infotext", "Solar Array is active ("..charge_to_give.."EU)") + meta:set_float("active",1) + internal_EU_buffer=internal_EU_buffer+charge_to_give + meta:set_float("internal_EU_buffer",internal_EU_buffer) + + else + meta:set_string("infotext", "Solar Array is inactive"); + meta:set_float("active",0) + end + end, +}) + +register_LV_machine ("technic:solar_array_lv","PR") diff --git a/technic/solar_array_mv.lua b/technic/solar_array_mv.lua new file mode 100644 index 0000000..abcc027 --- /dev/null +++ b/technic/solar_array_mv.lua @@ -0,0 +1,95 @@ +-- The medium voltage solar array is an assembly of low voltage arrays. +-- The assembly can deliver medium voltage levels and is a 10% less efficient +-- compared to 5 individual low voltage arrays due to losses in the transformer. +-- However medium voltage is supplied. +-- Solar arrays are not able to store large amounts of energy. +-- The MV arrays are used to make high voltage arrays. +minetest.register_node("technic:solar_array_mv", { + tiles = {"technic_mv_solar_array_top.png", "technic_mv_solar_array_bottom.png", "technic_mv_solar_array_side.png", + "technic_mv_solar_array_side.png", "technic_mv_solar_array_side.png", "technic_mv_solar_array_side.png"}, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + description="MV Solar Array", + active = false, + technic_mv_power_machine=1, + internal_EU_buffer=0; + internal_EU_buffer_size=1000; + drawtype = "nodebox", + paramtype = "light", + is_ground_content = true, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_float("technic_mv_power_machine", 1) + meta:set_float("internal_EU_buffer", 0) + meta:set_float("internal_EU_buffer_size", 1000) + + meta:set_string("infotext", "MV Solar Array") + meta:set_float("active", false) + end, +}) + +minetest.register_craft({ + output = 'technic:solar_array_mv 1', + recipe = { + {'technic:solar_array_lv', 'technic:solar_array_lv','technic:solar_array_lv'}, + {'technic:solar_array_lv', 'technic:mv_transformer','technic:solar_array_lv'}, + {'default:steel_ingot', 'technic:mv_cable', 'default:steel_ingot'}, + + } +}) + +minetest.register_abm( + {nodenames = {"technic:solar_array_mv"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + -- The action here is to make the solar array produce power + -- Power is dependent on the light level and the height above ground + -- 130m and above is optimal as it would be above cloud level. + -- Height gives 1/4 of the effect, light 3/4. Max. effect is 720EU for the array. + -- There are many ways to cheat by using other light sources like lamps. + -- As there is no way to determine if light is sunlight that is just a shame. + -- To take care of some of it solar panels do not work outside daylight hours or if + -- built below -10m + local pos1={} + pos1.y=pos.y+1 + pos1.x=pos.x + pos1.z=pos.z + + local light = minetest.env:get_node_light(pos1, nil) + local time_of_day = minetest.env:get_timeofday() + local meta = minetest.env:get_meta(pos) + if light == nil then light = 0 end + -- turn on array only during day time and if sufficient light + -- I know this is counter intuitive when cheating by using other light sources. + if light >= 12 and time_of_day>=0.24 and time_of_day<=0.76 and pos.y > -10 then + local internal_EU_buffer = meta:get_float("internal_EU_buffer") + local internal_EU_buffer_size = meta:get_float("internal_EU_buffer_size") + local charge_to_give = math.floor(light*(light*2.4+pos1.y/130*12)) + if charge_to_give<0 then charge_to_give=0 end + if charge_to_give>720 then charge_to_give=720 end + if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then + charge_to_give=internal_EU_buffer_size-internal_EU_buffer + end + meta:set_string("infotext", "Solar Array is active ("..charge_to_give.."EU)") + meta:set_float("active",1) + internal_EU_buffer=internal_EU_buffer+charge_to_give + meta:set_float("internal_EU_buffer",internal_EU_buffer) + -- Idea: How about letting solar panels provide power without battery boxes? + -- This could provide an even distribution to all receivers. + else + meta:set_string("infotext", "Solar Array is inactive"); + meta:set_float("active",0) + end + end, +}) + +register_MV_machine ("technic:solar_array_mv","PR") diff --git a/technic/solar_panel.lua b/technic/solar_panel.lua index 93f2b63..5b53f5f 100644 --- a/technic/solar_panel.lua +++ b/technic/solar_panel.lua @@ -1,3 +1,6 @@ +-- Solar panels are the building blocks of LV solar arrays +-- They can however also be used separately but with reduced efficiency due to the missing transformer. +-- Individual panels are 20% less efficient than when the panels are combined into full arrays. minetest.register_node("technic:solar_panel", { tiles = {"technic_solar_panel_top.png", "technic_solar_panel_bottom.png", "technic_solar_panel_side.png", "technic_solar_panel_side.png", "technic_solar_panel_side.png", "technic_solar_panel_side.png"}, @@ -7,7 +10,7 @@ minetest.register_node("technic:solar_panel", { active = false, technic_power_machine=1, internal_EU_buffer=0; - internal_EU_buffer_size=1000; + internal_EU_buffer_size=160; drawtype = "nodebox", paramtype = "light", is_ground_content = true, @@ -23,7 +26,7 @@ minetest.register_node("technic:solar_panel", { local meta = minetest.env:get_meta(pos) meta:set_float("technic_power_machine", 1) meta:set_float("internal_EU_buffer", 0) - meta:set_float("internal_EU_buffer_size", 1000) + meta:set_float("internal_EU_buffer_size", 160) meta:set_string("infotext", "Solar Panel") meta:set_float("active", false) @@ -34,7 +37,7 @@ minetest.register_craft({ output = 'technic:solar_panel 1', recipe = { {'technic:doped_silicon_wafer', 'technic:doped_silicon_wafer','technic:doped_silicon_wafer'}, - {'technic:doped_silicon_wafer', 'moreores:copper_ingot','technic:doped_silicon_wafer'}, + {'technic:doped_silicon_wafer', 'technic:lv_cable', 'technic:doped_silicon_wafer'}, {'technic:doped_silicon_wafer', 'technic:doped_silicon_wafer','technic:doped_silicon_wafer'}, } @@ -42,29 +45,39 @@ minetest.register_craft({ minetest.register_abm( {nodenames = {"technic:solar_panel"}, - interval = 1, - chance = 1, + interval = 1, + chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - + -- The action here is to make the solar panel prodice power + -- Power is dependent on the light level and the height above ground + -- 130m and above is optimal as it would be above cloud level. + -- Height gives 1/4 of the effect, light 3/4. Max. effect is 26EU. + -- There are many ways to cheat by using other light sources like lamps. + -- As there is no way to determine if light is sunlight that is just a shame. + -- To take care of some of it solar panels do not work outside daylight hours or if + -- built below -10m local pos1={} pos1.y=pos.y+1 pos1.x=pos.x pos1.z=pos.z local light = minetest.env:get_node_light(pos1, nil) + local time_of_day = minetest.env:get_timeofday() local meta = minetest.env:get_meta(pos) if light == nil then light = 0 end - if light >= 12 then - meta:set_string("infotext", "Solar Panel is active ") - meta:set_float("active",1) + -- turn on panel only during day time and if sufficient light + -- I know this is counter intuitive when cheating by using other light sources underground. + if light >= 12 and time_of_day>=0.24 and time_of_day<=0.76 and pos.y > -10 then local internal_EU_buffer=meta:get_float("internal_EU_buffer") local internal_EU_buffer_size=meta:get_float("internal_EU_buffer_size") - local charge_to_give=40+(pos1.y/250*40) -- make solar energy depending on height + local charge_to_give=math.floor(light*(light*0.0867+pos1.y/130*0.4333)) if charge_to_give<0 then charge_to_give=0 end - if charge_to_give>160 then charge_to_give=160 end + if charge_to_give>26 then charge_to_give=26 end if internal_EU_buffer+charge_to_give>internal_EU_buffer_size then - charge_to_give=internal_EU_buffer_size-internal_EU_buffer + charge_to_give=internal_EU_buffer_size-internal_EU_buffer end + meta:set_string("infotext", "Solar Panel is active ("..charge_to_give.."EU)") + meta:set_float("active",1) internal_EU_buffer=internal_EU_buffer+charge_to_give meta:set_float("internal_EU_buffer",internal_EU_buffer) diff --git a/technic/sonic_screwdriver.lua b/technic/sonic_screwdriver.lua index 523b253..97ec446 100644 --- a/technic/sonic_screwdriver.lua +++ b/technic/sonic_screwdriver.lua @@ -52,7 +52,7 @@ minetest.register_tool("technic:sonic_screwdriver", { minetest.register_craft({ output = "technic:sonic_screwdriver", recipe = { - {"technic:diamond"}, + {"default:diamond"}, {"technic:battery"}, {"technic:stainless_steel_ingot"} } diff --git a/technic/textures/technic_cnc_bottom.png b/technic/textures/technic_cnc_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..e600cb1de24947b81b8bdc0111b8efa44becf544 GIT binary patch literal 2006 zcmV;{2Pyc8P){yZmA))XA8$k7>e}Zi^~&|*Y(24ND_c*?8teR>QtoT5eHo{I8*hEv z_Wtg(TkCnv>^1lEaq&C%Ii7S@53bW2RR^- zjk*#gXfub1e9in`6W>cOnaGzE|D~3`meSjGL>8A-&}0Q*0@`@KwWDVMB*2Wr#QH73 ze`R3hM`4rUZRpc&>N5)ysl4AG&@lFok2_f+ZDe6Tj(%Qyf4jYr3DZCKykrh1LQ-A; zkO5f%Rts4Z1kvV9)MQ6W%yi}Z7XTwJpqk*Y5cyU}c_Dr9beu=%qSYP#=2(}}gdEno zaou#bpk;)%3VlW|t%d8-DVUS&x_3fbW@UJPe*riTxM9N$#CIYrA_qWiXQcduGqbd? zW|`~CiON3G{QT{HD^;_x&&u@`@b3Krz-Fdb zF-_wLLjH+h0Zjg)q@WEVAzSS@p@B3bE;-)!gH6{ss35?u` z%K9Y{tR>7IUjQ}^Rd_282w<9qrwF}nREm` zSR71c6rO7bV5EU8x!*ScPi{1jV&ntqCsheLRBmR2hMBlVg-2CrDu~RKCM$vsXEM1U zxCuH1yOVNj-h-RfuvW_aGdKW$0r0Rw4Y#ZH`+t8&dP9I5rj5$q%9;btEjcrmmZ_iT z6?UD~&!=%o$9ca8s6>TGlhvZ}C}=ad>AZmY0&q~HMpalGY2^S@nBeNVU)<9d^od)) z9%pD^BU8HM?fu3B7 zZ!4CB)9u$4SrCjVHTCMiL#-Iax^Ztt%x1%~ZMzMK%DT;z=@1#q>V*3TmGcE46ZMRX znVJC=S2Mza+YT)U(Zkoa(j|#*rz37;Nox_NdzqDKc|vqV?X$DIziAnd&;NCBg> zJ0)y&p_Ok&q_I#^az*WLp?}kAD*-CiFIj;~BvC=Pg9L z1HvrYoMzVAZ53_BxYShn*^cE7gTZ<=kqeXxr|oB?Dk)OX>v{rkgF{uru}w@HHgf6O z>59@+andj|o_%1?H@v^tv;ebY^a2g9ZfGfCBzCnhp3lL=jV@?VKvB!o_=vLQTKBWe zvcl4);Wn|cbAxu?PQU_Y)Kj#1%*cwcvTVb3>IWKMonz z@I2u0h-!l``?=0&e`wGWDQ9}Jq#pnKO^G>fX~&w4osrUHO`(*1CbR;@t`W?SUZAaN zMpl3+TS2Gas|gKef(lC~(hqtKC9V;%uIXlx6%QaI0@i$V!i%XY_~%}Wy%);!q-T8V zhAYiR3cRU-EX;n2an?4WpxUT7EP6a5TASSwF%k6=>zwtVi6}>m$WNmckOw&@%ur~* z(3q;@9aZ)cA&1PQGq@ol1tHDK*=}^r2IL4J4yNcb0UUHDaJ1R7u+Xr5*Ml>w*XH5BiQ1{qLzq)O{S;wEfx zef;J@#K+rGc)Cr*IUfG)Xx8(}eGiH{C%sln@Xd7XI<4E8(rL;ep$~{;vQ314^xHi%raM*#H0l07*qoM6N<$f@Pk|5dZ)H literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_cylinder.png b/technic/textures/technic_cnc_cylinder.png new file mode 100644 index 0000000000000000000000000000000000000000..06da024b91b5839c9135c2c8b87fb6a53ee01ffd GIT binary patch literal 456 zcmV;(0XP1MP)lv6%>6+Xs-rb=2S|pb%5=fmEZV)>HuoPfj>3C9&qUM7H2wc z^&##F_woIwfX{}iU5J8h1uxce@XC}o2MFQzP}FRNn85+4KH$SE09HE$sG#6ED)~J? zKk3c`at*8m*A?(C=vNB}V8r?;C;`$6&8f%W0Q3M%@(#0*D<~+3VYZ>5IY3^$2Oyo4 zp@NsH_@@fC02V^quSgESaGpwgGr6{hxFOI|@D!Ik{dsT~fOKO(R}Z|$?UYm`pd7Jn z3dU?m2Ph~30@UsSnR?;>Hyzw*qX*Slqo4q$*ZSa)TLHUuw|Fm(=O)cTS{&IXV|<_& y;?jrkIEl~;P)SfqIXI4^-3EGGO$>MVJ=+^lMa9`J4O<-m00003ieY#{#}~Tsofn@i`E593TTW9uUA_69579(*d3>Anj(Pc~bO# zCRVgZE%pU8z+JH240_<8V7dT$;f4T`TS+|UlE=*rme_kR5g+B9Xy;w$5YTFFhhuLu z)c_Uux@4?iP6Dg~S!ge7kS^M;XmPc$M0=V;dul+pO$!`cTLO4>7nb6&04Cr}22<^M zHu?&1a{v-^bnc1$pyq)_EF{UI09S1A)}F`n(*Vc`5g(eYCci4415}u+9x+=)F(gy1 zT@Bu%r;ubB)1=cRV$Bb0ulXIobzSHE1O3yqlIC#2{Wm>>$%zVH-L(J!002ovPDHLk FV1leSym0^k literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_element_cross.png b/technic/textures/technic_cnc_element_cross.png new file mode 100644 index 0000000000000000000000000000000000000000..f2ad0b79ddafba3d275341800bd610a429ff2b4a GIT binary patch literal 415 zcmV;Q0bu@#P)>makflA+Lf$RqS z23QYh7vKyyDLh zBx_hX=%5IUZ2_J$o@Qm~&Zy=UeEcHBTrzTiH8}E32Mp@jO~nQ{TtKTF!C?XhaCm?T z-2Vdl_Pbm>E>F)S5kjkK`HMBK1+WoJ1$Z9D=F|)UZD$hQTxKdWHn&GaBP=f#f002ov JPDHLkV1kXQqt^fc literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_element_edge.png b/technic/textures/technic_cnc_element_edge.png new file mode 100644 index 0000000000000000000000000000000000000000..e6104cf3b258057fe1cb99d52c780222d53540c7 GIT binary patch literal 409 zcmV;K0cQS*P)G}BwEvoe(^A$4Pn4F%< z5!eJa_RLIBJDz8PGeK zD8P*cp23jh#&_{!fq61OVs$-kp=Qk35=R{v#9JMECm|MMEIE_Y%q5gqh&id1U~z&! zjq_0+#g;&1+zmfb{~-Zb;JB!631S~Spv79(0)sZHE+%JQ>U!dIBE^~jr3jN*+!Mh9 luIuXe0{wfj@A!s4+CGrJX;{@Do!9^X002ovPDHLkV1i4boGJhS literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_element_straight.png b/technic/textures/technic_cnc_element_straight.png new file mode 100644 index 0000000000000000000000000000000000000000..1648b7b2a5d4702f3ba5c0dbfa7e834f78f61f8b GIT binary patch literal 412 zcmV;N0b~A&P)P~J!5VsBbS(asU&TTIE_AjG00tV+u z?Hkwx7FK2^XzkB4!I_{n0qga%5B^1hVXCL;UJGtkVnRtr6xsxs!)X$&3PfS)d3R}6 z1D4`)X_|mm6nA}^W)ZLj%)R|xeKP}F;!MEmu$UMnw;x}H30B92$94+zxaWafYB9Nh zdk!eU65KOD1+E|P4n@Dkl2U2=l^DS>rR@Vma6)p!1EmE6G}Xb+!CZo1zx&1Z12Q;d z(b@-Ch&y%!# z`6)$V(WynLM=|mTJCs=wBiBMNP3yXjyMca;55Qw0Wt42BK%rBb1rvgavVH!XCdMm$S!=y9#vAa(H(Cnb@dk|ql%g;DLfi7o?jXZ%tir|VS!TToR%s@wGd-+>oOIeFFs6AEBhHZTtOPh;gI zQp*Xx{?WyNs{va$`0VFE#8E&7PA@Pd2RNO;6HXtnz&#g;i)Z(-Yh;pix;Ebv&nric z->Og!kO>n3<6&(27k8-#ft-g{)?VDY5CtTML}eN2A;rK8CL~DRF#ZT)m+0Y+WAo4! jigQly0s4VVQl<45wk-ZGPM&bL00000NkvXXu0mjflC7KR literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_front.png b/technic/textures/technic_cnc_front.png new file mode 100644 index 0000000000000000000000000000000000000000..6cc049004708b6f0c262a99e1818838300d2efd6 GIT binary patch literal 2000 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 literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_full.png b/technic/textures/technic_cnc_full.png new file mode 100644 index 0000000000000000000000000000000000000000..d551a454feaf0b3adfcc86cec34da759c731207b GIT binary patch literal 372 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 literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_onecurvededge.png b/technic/textures/technic_cnc_onecurvededge.png new file mode 100644 index 0000000000000000000000000000000000000000..46779fd6167b3b844183f90ba4997afbbb192ff6 GIT binary patch literal 507 zcmVPx#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$AGPjWzeE%1YST7KQjex!t)c`ptY#(l_YG4m89m_$Afg@m&(u;r=I4Vsx&=QxQ zyDmEm=!JuzBya|2bDuJdKw|h`qT6bV8CFs4+S;sh_pSocs z)|NKm+<=nwa-0iLf{XjQ0()`h2}*!5jfKXxj-zrR)T5i*EQX6fDPPhFk6#Q zKm?~+7poE#0@HfBo**##sZDX;xz`4!re{Z=l59CA8bNv;FBB& xmG9FHMDI@kD8&^C?)$!O1N|;@_TOv4?LT5tyL}w(&U*j=002ovPDHLkV1lmk#v%X! literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_pyramid.png b/technic/textures/technic_cnc_pyramid.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc3322e5f729cb43591f4b8a999e7ced0ecbf09 GIT binary patch literal 480 zcmV<60U!Q}P)l3-W5--?a|+v_q)+@9UO^U_W!X5*T0wBBW46A2;BF9 z^h1MyfMNb(Kw54e0l*x`ksR8VrUR(Ka^M$B6U+8Q8-OJk))NL3Ui&<-n3tgyKr4*i z$5X@e9A`rsfi*Y@NSGY>JkrEmPO|{4h4J^JynxXD(jx;ep z(-eRaIGz?y5T6Zb4*OW4d=jroB7joA5egISL&9O-K;B+7d7x6S5spwA>^(UY`4110 zyx;g2)=GOll8vXC{R*}2kpqF^!UMwv8a5)Soz|w85M`SlTJ!V#c1}JkR~!K;M5&I=;id+I|3p W0^oF6IUle90000Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$AGPjWzeEj=)?2wU^4=(x^fy^o#Z|JjBnb4(boUJZ z`1c;ij z=B2cuA6n*Ko-%ul?6JmonP;9^ShKXLAKT9Q^X)CxChmLoC;v++wPnsNkC_8Xo2IFa zX=>9rw(Ire-rTzHT^l)|l+tDn$gC+j2Y_|k0z};ap6RGZEx3Wn|W>=QyYhg z0Jm0;`UJ48L^n=t*+2@2KJ~5ddNu-#kt}oky|B(q?Z?h$na$1C%H~^}vr!G~u>x`; zN)MXb1Q>%l4%VzoTiJ7*xSsM8z-*fMj7B~Tt^fYLy}iFjv_|zSjoZGoLKenxX#2KD ziZ{xWhMs3rWFcMpcI*eylR@@NBftTY$YvqS0lZSyWqJar>mFrDY!Zvv(DaSN2x?Mp zeMz@Ktlvrrj97kL-%jpvjpt13&~<#1Apj(TS>(-J_!!{8GxuN%S$S|^r_P%fSrpkY z<$c#?4ye27%|V*;IHE+~zI|(|=ih#OE_234IVztAfSiepjW-x>YWCaN&hrRBxez%l z-T*bi4LAAx`SXAN2-;GsvQ6f(_JpC zuN>~W#Kv%fb^Q+rSNP4L%5)F_Tngz%dCj8ozRURmpc36K+cgp*Qf4bz*df)%W=1(v ziiL+J2=@^VNYrr@(2EKRy4(S=RgmWdy4=nyDWpydIv-&3PBs?Y@ON-vgV@8X6Y6xy z^iqb614B9hT8ZA2W$*KV`qt4hdJZcl-Ew2)_k;(`TvwtxV`lw;Ukp6~!3||=nRM3$ z&S+SV5_qwv=GHQk8V}J_RDlQme7kYK3*sI0ht+zr?ux~(a6$(R;QXG3)H>Gcs;<*N zy33!j=W#vS0$CR_yCdnR3UD*Yk|m4HM+*hi!6M6JGue=(hn=_Uhd5w)6QI^tA6SU0 z*82e~>Dgp8ht6D|7apKI=j|5S{T&>L(gNZsLk?F~rfGtqp=D||p$Zi;V9B9-x>-R& zDxu&BE14UU-=v$`?`U7J%2`FJpoJ2q9^>J@*6#BM&a2v90AMVpS*zv2gbi1sKS;Zp zR{LQ{dIIHfKA30B1yDQS{adq15YBH8D=(yTPS6J;pn3;)5b)EAy@BjjSS%3-=L4d- z-t>O6ayOM^^ssw&I3WXt@>mf>(BQW4q&|}>9*12XeN*bIf`0BtwgP!H63efi}t>stg(b&tZ?Q&DG55WR}3T< zh>OGrCaM_Y09F9zEb-(3>?{nT_<>hIKv<(&ufzF%NRc%maz$ zGO>xx%XbFHw~cI7-X~lagDoU0n2a(G*2@vHV{aJ=>|oxIAFAmAAW%`$-mzMDgY}~i z5}_09jz^3%88dMLtc#HyGda%~REshs_1+hpe2|#lw>0;b-UWEGwlY!6gXfEhEt7g4 zOvl}&gY~{(sAFW~Fd_&@WwX+3^n|t4`Y6+KJ`obZdnv@Aa)?#bvM06sF~|Bh$>2HIyn1UV!Z07*qo IM6N<$g7Jiq4gdfE literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_slope.png b/technic/textures/technic_cnc_slope.png new file mode 100644 index 0000000000000000000000000000000000000000..083ae18cead58a9184bd67530aeafe610e9d7298 GIT binary patch literal 437 zcmV;m0ZRUfP)4D zo3T!BIziXKRXD7*@%zu{fAK0@tcw97?sXuA8v(P&c@0uUs5Ajr?rl_6<~7)FM4OreXIS^Ssm1%g%ZJ`M@xCjT*G+9! foXV%WVb%8!Ki5#NA|S~n00000NkvXXu0mjf9OS!A literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_slope_edge.png b/technic/textures/technic_cnc_slope_edge.png new file mode 100644 index 0000000000000000000000000000000000000000..785adf6531fb5a95b387869ed590d354d071666b GIT binary patch literal 419 zcmV;U0bKrxP)=13A3=}IIiuvm3S2Fm2Y?DFyD)N zV3N{y0Y~BhW&(P^YUxp&s>Gf+u49;h-Y^Z0O>hKCTiR+HoC&-tEB>rH%y>g#@P%^? zcb;Zdrk!3$iYxE=PC;jZ!g+BIwv}FeVk!i}MYK?iyB>&J^JXRRSd5VG9I(aueQy9t z)1)0jj>5m}0JfkQXu~-#9^t~DpXuy8SlwFJ)o%g)cpCOT+%M<~`~W~B_g~(faa{la N002ovPDHLkV1jjZu+9Jg literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_slope_edge_upsdwn.png b/technic/textures/technic_cnc_slope_edge_upsdwn.png new file mode 100644 index 0000000000000000000000000000000000000000..5adb788b795553448a74f32234eb12a0b152343b GIT binary patch literal 486 zcmV@P)-G35m*7E zDXP~xv;o+O`wdL#^)j*o*a^e*RG{3O1>hixm$n*t+&?owW1KoLa_NNd=I!sm z6?^kqpjhe;!2wbQ(&;ivGYjOf>I8G+ZvYKQK+#1@I|PhfF?1%t9Bdef$+j|iVx`iW z0b9~U9DJz#IwW~&f;B_Ldkujeb}f*Xox=(PAtIZ$8U0ts{|@ZU5|Wj*h&&C*OOH^g z-%PiemNens3g98dSL-)PE2^}~LsD=`Wd__WKsrd7l7`Ibb>JROh>QAlxGVA=u|e>=5CKlk|uIGXR1piP47y2dEy cT~p(>FB3e%#bcOwwEzGB07*qoM6N<$f*QunI{*Lx literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_slope_inner_edge.png b/technic/textures/technic_cnc_slope_inner_edge.png new file mode 100644 index 0000000000000000000000000000000000000000..906dd2548b63cd146bcb3374293ddb3a7543e1e0 GIT binary patch literal 497 zcmVjl1O?K=K^ASUKmfXf-`}Di^3={f`jk! z^i*ILmIcmmBCv{s>m%t&xFvuZ&K!f4Bs~e*$>CaAS(9Xu7Em8^d=c+lG)1r)P@b*Q z?t&ADmwTYrBkcJov$m0fKqzM+JwS`~`aA)&(&WHcV#zV6{bHWz4Cqg64&3*>zUht7 n=enX^_ul?!+?BuouD7-yOl{;`+yuDy00000NkvXXu0mjfjFa2c literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_slope_inner_edge_upsdwn.png b/technic/textures/technic_cnc_slope_inner_edge_upsdwn.png new file mode 100644 index 0000000000000000000000000000000000000000..0ae0e14ddd6400f190469173534ae2fb8e8f45ee GIT binary patch literal 605 zcmV-j0;2tiP)SC+y6v1=45!R_Tg|K!GA0^zOqx02;X32S?}ONCyy1 z4Fck&2Z12&Hb{``#%T_KNaHil=|elf;7wg6?%k_}w!qYQ^aj!E>r7Cf_XMNJ5b*Z^ z(WU|UTo%Pb^CFd*YmsTXFx{BI8Uz9+6m2p&v&0IJ z<~R=MbpaE|aaww2i3dpSp}-9r;bs7PtA;wLWNH=;28scrjY^qbh4x?wZZ`1NKTlYO zqkYab&B%4pvHVF?bF7Wn-tUL=U;vmB>z3GqbCnnv(YJ}0m6Z~#XcX#7(1YysIT!Bd z__}F(6G#sLIn5(Mdan-#DOG}nfXK9CEMv`5$;&+rXd$gNmZ6%`zY0VL!ddQI@~;93 zR?`gkL2E=i(vzt*$Va1?PvF|>f&yhp*>Ns;7^n>v1USHnMJz#^f4|8^&OVk&T0jlg zztabR;|L}IWvR6U`_qV3p-DiFM1U6S`uqi8JFnriDWkae+$a;go=m*BQkS%C+g5g> rTN=^rAK&pd&pB~cLj@T9qT>30-TN_gAA!CT00000NkvXXu0mjfP2CS$ literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_slope_lying.png b/technic/textures/technic_cnc_slope_lying.png new file mode 100644 index 0000000000000000000000000000000000000000..377769a7f2d0c28cf411134146fb6d5e9d13b89c GIT binary patch literal 548 zcmV+<0^9wGP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$AGPjWzeEE32oCLI7gvtt_B>i;!gOxBfdJV%cg%G9y zzQ;|gMnG`3WQ$-Ou+TFv3eGQDyIzu{9&irh<+sOfCX4H~)Ns77-EkMd7?^!m23p}_ z0{khLdO$J9e-#3HLEg>tL1qH(0hZ_b48SAcwi9Us@JJ|M#wP&n;*vz*9+#>liU4xs zTfxR$`%|%YUFZ{lfP-o@y=ag>=XjN8LSckKIji2c%stEaWyX^{f6gO}?VsugA9Z^L zXWiQYMZH56q00Yzx^`C=Gxlr@YPiDze`mR2u_Wn$o-D3akY$A)@RS$Kb(a|r zpss(|oG}Qv4%iix`k?EdI|iwqEif&+ literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_slope_upsdwn.png b/technic/textures/technic_cnc_slope_upsdwn.png new file mode 100644 index 0000000000000000000000000000000000000000..b802b60db0e329dddc96884da31bd597d8e8c925 GIT binary patch literal 440 zcmV;p0Z0CcP)w5W*3X?{nhyK)`5p zwf!Zi)5T(Zcio+!wILAW;9QS10G43%w{hqokb|mSBf|~=H8^?c1wad!y!1@q3>+`b z25=^dKjI6(t6}Z3I|QCfUn%jb6rXV&f+J5yj{4vW;S#b7{H=y_^Q16#f~6VXikeXP zz@=Rd?7>t(P1$K`wbGgZ^Z4TLfJ-glyi``vDCRzOw3swC0QPXAQ9J@Im6MyCS&4h2 zyoThYHzh#~#$}f#H#I?;s$@{$WFL~1gxd#O*FmBQk@i-Z6Yg>#oj+?pz%2vf`I90s zZYdCV1={aiBv=|qG(9&7(y7U1g0)2153Cl`%=kT+@5SSPplx{r?*z38XxryLxbM5) i59s;j-SHRxXnO-cQtO1vAaX7M00003v?#Bj2nR*28_Y2?M-;+mSo0uB>$2druzw4i1^)78bZP}A1n4DioMaNqZJ|ABr@)inPvc>M{6 W_hHLH!dDsq0000?H^6s{au38*-x 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 literal 0 HcmV?d00001 diff --git a/technic/textures/technic_cnc_twocurvededge.png b/technic/textures/technic_cnc_twocurvededge.png new file mode 100644 index 0000000000000000000000000000000000000000..3219a901a9d59300b06564f0e1fa84b81f8f1eec GIT binary patch literal 768 zcmV+b1ONPqP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$AGPjWzeErp|W5NgmFR0UKQfr8jd z5RKIw*5<|`?Sm>HXC74Kd^A*Wa^3^F%FzsvK~Xr^18*t5%(wSfV22(YASJ+psi#%^ zNHbvTd7$_)%oc)a3L2)=x0P?2Jh0LVw=B^0%)S!!(&AcG?((az8%w84NWm15UcG&3UB z>eNL6h4zImaZVu}R!gmAxGF$a?u`I(in$-5eML*u^WmBRvYG${D1iNTR%&gv#j)Ij z)vz4aBL!;Vnkg8^(7T;J|G13}rY z@Tm0bALX;xpEoohhzV*+SA!`%6I7rIR1pK?~cCg+;Y-8Ps>%tTzdJjrt+Cgd69y9@8?Wz>6W zmn7eP`URy+a}9{PuoAw1^9$@oK4KXRI91TgNE$kdM@)YF>1Td>^E?KfYu zkBxWNNu2>Ibc3TxXDySe;pQAq2iG-;83aN6@h5Rj#0&yNp|j{Llv*|Dndt7=Z6IA- zbMoPt8wL1gu#_Sy*zTwdTXBid)#PI`GdONLw|&Rmd3ip_nq(FLx;f%2B_|7e+No-E zCOwq<-~aH{>o3{2XIzBswsZaaA2H)&8@ro|!bOD!%mh0&#&CY9Ul9ZzP+8Ppg$?8B zY7E|6H(!RloeW7z^+p=00000NkvXXu0mjfouVKV literal 0 HcmV?d00001 diff --git a/technic/textures/technic_hv_battery_box_side0.png b/technic/textures/technic_hv_battery_box_side0.png new file mode 100644 index 0000000000000000000000000000000000000000..fffd8eaa561b18485900a9899520329a116f0e4c GIT binary patch literal 777 zcmV+k1NQuhP)YDqQc_5Wv#5})F{UTbUB^#sEd62-fcd$QIF|u#N)#2& z+r%^(!`UTK*KxCJDOL137ZF~xi8eK88z=`A(H+XoA;o${Sr73P(Ad)kaOv-;QE?UO z$reR5LWWhpt^{SgG31@a9vf!?OBpxEyk{W*?$|P8?z}bG<$m)zMPmq{V$N=tc(AkJ z?i)8(0N`f08M(_nkO~GI%r1ENX3gGsliXz@Dm*?u2%Zhh(AArOg9s6Gwhs2GCmZC} zSe!Jd!Q(NlwFy^cd~`sF14zJ#;rmMPXVPOKN7D8Z_&=Rl%0%Qo;0OTwHc>`oLML)mREFvEZ!WMKGcXQ`tDcm ze*S};A~{9A{pl~hfBu4DxIkJ#MB}}o#DH02<}gKU0OuQ99N+x#JFQj5aYRHI`kuSr zUhvMNOQsMI?@((YR)cZ<1-5gu<}AeW2=YEGzUpMBD9)DaPlZeX0lS`S)bhApu| zTo!6htfw=rHmnsy8u#oleeZZ}xWrkDwHE6-OgA9DqxA!MU1@6|hRA7i4?t;!R9F0} z(TbOiwJ8dk+Ju}dB_&!cq zNFn$H}gLW WI#dbF@1UUo0000Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RY1RDoBECSMZ5C8xMJ4r-AR9M4Z zS4n%@I1^xB17z3>}@;t|5o8a4vLO&^7 zMuq1u5vr<^JDN7dkNbJ``Du@$D4?}QRaFRGipxlk53_;~iCkXSHCi9zJW%X1Dmb@? zwHA4vLu-xhnBezC;rc=G<0(Z^6fnlX7=zOvDb9n!{I2l*r-I@@Q50|?Mn5SGS9&0H zsT?%MAan_aSz){>y!CXs)*9AYSZfiEboqFr>Ya~JmL;mHf-wfZi!sa!^9NP$L$)N~ zyBL>|g8ii6Lxe2Lq`LLv!>r(31g$lUF-VdGt=r);DopP*me%bg@ia{lj&%NVAB*!b zj4@DUS;B_|{X~bytAY^2?Ho;}2U_U7wkBQ9FT8r+K(9ExNx$`l!*7AV!5&B8tJW}O8#K`j; zWm&>n3l}K4@wOz#V6N*L>g6W|&cia(s;cPmV@gP#Xl8A@M_t!)d3Rirzkblnxhq<0 zI2YlqUn&n>Du6e};J=^uP)wx|D6_IG>9CJ5-RSZ8U7>XmilUGUoR9GPLY?U+1@HIL znX)W}P25@MW9h6h1}?-Ht_o_n11`^Vq-hGq#4s;xa6Xcm^I^sWp*fO=t+fapb%xLL z{bgCAC<=7P6w{58Q(yl|kY$;){q#pJRAMx5D!ZfkcTbNWPbnTA9#GfyJ-NMLqMztI zCsvjv9-AGp>8kMKRY6&61(B`a<1*6YgjP~89!+=JR_1&xBhy;LcUwR=?GANaOY2>T zgvysup=o2Hp|uvyNAmbE6C1c{tu?w+hPQsoXJ07b!AXjl{loQrTCsI8ZA5hEikA3b3Sb%gn8{XdP94 z9$6%fuTl(_Mbu9(kT4NfMN0iPr6fEyJwv@Bi$e zilRW8rf`n5|Lwl*G|gV5mo4=?toMaQLGwJv@w6BhV}ikItre;+@=TVmXeR%!-3ih( zmFilz%zP~}VoYJ7^4ijw&b;h!az3P@BkHl)9{%*W6HC@wqjfvc_P2haT9S}nbf;xg zB21(kK)VoQyi(`ZJ0jb<`rmgt*iQ=GF%idF8xJodK17=ZbItR9QfQig$^KVW75u%k ztdP73F%f}SO+fS>eF&pPzJ4fd8GiibRI(L>ov9wRb^3}_-49{O8sOyKq%d5iUW3+L-&rgwTuiw5aG;Ok>(w9Fex$&y- z`itW0ed6gk64(3rs?fSr98qhHFJEJvM}>a?6YArLvYKQW00000NkvXXu0mjfG!sCl literal 0 HcmV?d00001 diff --git a/technic/textures/technic_hv_cable_wield.png b/technic/textures/technic_hv_cable_wield.png new file mode 100644 index 0000000000000000000000000000000000000000..7b9ca5888de17da6042d4dd96b2a06b84a511475 GIT binary patch literal 601 zcmV-f0;c_mP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RY1RDo611_6Zh5!Ho>q$gGR9M69 zl+A9_P!NUB+?1wC?TCf%xN5iX2)qO00qTSuD;C6&*v0M+K@$n_3f&;2rm*D|cnBnR ztXP1Q(AfE@4-4D*p+u;Af0Csu9cj+Fb7u@xR8&+{RP5m7#G|#A)>?)=my1leWd22w zL*LIewU%M8wWaqXhraL8SEaRgX3!ga$ICmZ^U z(53JD)WWff$3v!98@I z&dsaWxp^`L;=Y5?WgQ{{00`PC&WFD@%$;?(j0igORX7sZKWxI(YJf2iBey&7>-!HN z4~RWu@b=vpA{)g=4FCj5oEGL~XQIA?kD~^F3?vYA<~ZN#jDzP7ej?8tF zizLN-I>RzaAyVGl#nq?*5rHuVK|95uFi(nS$;|-~vwD_I{r!hJZ_*hS$!z8GUzW@V zuH1xjpvHd>ocdI?^gNH<(Eazos=fOb#AgoGTB<6Kjx76;vs$x7CJcM)aK3LD#kY0U nd`*v!Jyt)qii(Pgie3Bx#KS2Eb2~;<00000NkvXXu0mjf25=5J literal 0 HcmV?d00001 diff --git a/technic/textures/technic_hv_down_converter_bottom.png b/technic/textures/technic_hv_down_converter_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..996b2d4cfdcd63908ee512b0f2165c090f861e7b GIT binary patch literal 653 zcmV;80&@L{P)(7T;J|G13}rY z@Tm0bALX;xpEoohhzV*+SA!`%6I7rIR1pK?~cCg+;Y-8Ps>%tTzdJjrt+Cgd69y9@8?Wz>6W zmn7eP`URy+a}9{PuoAw1^9$@oK4KXRI91TgNE$kdM@)YF>1Td>^E?KfYu zkBxWNNu2>Ibc3TxXDySe;pQAq2iG-;83aN6@h5Rj#0&yNp|j{Llv*|Dndt7=Z6IA- zbMoPt8wL1gu#_Sy*zTwdTXBid)#PI`GdONLw|&Rmd3ip_nq(FLx;f%2B_|7e+No-E zCOwq<-~aH{>o3{2XIzBswsZaaA2H)&8@ro|!bOD!%mh0&#&CY9Ul9ZzP+8Ppg$?8B zY7E|6H(!RloeW7z^+p=00000NkvXXu0mjfouVKV literal 0 HcmV?d00001 diff --git a/technic/textures/technic_hv_down_converter_side.png b/technic/textures/technic_hv_down_converter_side.png new file mode 100644 index 0000000000000000000000000000000000000000..ab904f1c14f4d6c5c1e001499032a330684b44ef GIT binary patch literal 609 zcmV-n0-pVeP)sj50q#je zK~y-)b(249R6!KQfA`*b@8u6<30ub{iU^8==~oQc=2KXRU%=9Upr1ml{RCDP%9a*Z zHWr38LaGoph3@WqbFalD>zc5)nK>}`%*;9G%FSoPfB*zBK}`t{FeTayD&P*PhzgM% z1fq4MG7`m;f+28gW^@-Qi+CIT|gnAc!fp zR-s}FPLbhC<1*PYw#^!?44-wR@F+qFJUQE=+fWWq4>&%1a7}|ZKi)%QPT)%d)_XC0^z0g5V-9d9!}??6`eBW7h)i0njm6fZG|Hlt0#)~b~RsV)Q& zASzgsP^pZFKtu=+^0Zw^kaPK-)(J_5sF28xtv9#_pZZ^~<)GIeGC3c?Iqa`P@9vO? zqcb7`?;I5s0#K8S=6`-)#g|q_o5{cD#YWGLbdGG)3!hi{zX;OLQ?xR&2O2pbg2?{g z&CBV#`T|su+ECLnOnBh)j{6@@@OGEiTT4OOx(w0*hacbJ?QJ6eK~tGpx%K=}h?PlOWI>Z#Y$cHwGJZ*_C5EcFcr*Zx28Y`Dj00000NkvXXu0mjfvhV^= literal 0 HcmV?d00001 diff --git a/technic/textures/technic_hv_down_converter_top.png b/technic/textures/technic_hv_down_converter_top.png new file mode 100644 index 0000000000000000000000000000000000000000..996b2d4cfdcd63908ee512b0f2165c090f861e7b GIT binary patch literal 653 zcmV;80&@L{P)(7T;J|G13}rY z@Tm0bALX;xpEoohhzV*+SA!`%6I7rIR1pK?~cCg+;Y-8Ps>%tTzdJjrt+Cgd69y9@8?Wz>6W zmn7eP`URy+a}9{PuoAw1^9$@oK4KXRI91TgNE$kdM@)YF>1Td>^E?KfYu zkBxWNNu2>Ibc3TxXDySe;pQAq2iG-;83aN6@h5Rj#0&yNp|j{Llv*|Dndt7=Z6IA- zbMoPt8wL1gu#_Sy*zTwdTXBid)#PI`GdONLw|&Rmd3ip_nq(FLx;f%2B_|7e+No-E zCOwq<-~aH{>o3{2XIzBswsZaaA2H)&8@ro|!bOD!%mh0&#&CY9Ul9ZzP+8Ppg$?8B zY7E|6H(!RloeW7z^+p=00000NkvXXu0mjfouVKV literal 0 HcmV?d00001 diff --git a/technic/textures/technic_hv_solar_array_bottom.png b/technic/textures/technic_hv_solar_array_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..596e79a37334030ce3ebe9790a26adeff94da6c9 GIT binary patch literal 574 zcmV-E0>S->P)pHNyHksIQMtuDhB45Ws)U! zRMZY;baV&z(!uXr>zS;rm?cCftj$1}Gq_5@j{_kP zlvu&n=Rs8hPs-=3!2)+d4GvF4Ob})E!3?P1jaCQWPeoA5nNYWr=LzyrKsWvAh(Mo$ zCuc?AZYTqEff_kyW^@F_`)F(ifrBWLjJ+1KcfuUqfghPUI&MO(4?7on-xv)&uM4;T zr6im4aC)mGhr@-G6Uw5L!rt(Dy>S(CQp^=yYcpfx3b9~efX-}9L97Pa7;aAnwKQrrvD>%ZDCC41f$3P-O;!easVhQBPC$MLCXZokQ37qhb z@ICqc*N+Q{`0SV%$Lk`#|CyiOec+#e|HMM#?b~R*aXh*25p-uSicjbHI58C`nDKa4gn(ti zU5L>*Ukz4cEoUvLZP3TywE`t)$`(-z8|UfdR6rN)Y?w}tZwE0aV!lypCz&vpl9G{g zW_UwTto6#G;~0n{F)(})G|*c^ms7T#(Hj;5S8LyW+9FWVZQrqAOn0Izwq&$=5e)iNg$VvF#}5iJ{Qkd=ejDnY+TpLaELK8hN6$- zKsDgrA;9oSj5}L4l0||l_uW|T9FK2IABZgGyogCrWMQh*F7yU#bguK@Y8{bDt(`U# zgn%sJe!tU)V`)bKeY5XKP%H?l6A8*zA{GN*j{|U^F={2{NUIk)25LPC5lmGOZ-fvL z9WWOiVGL(41xpFR*>a!{WejJ{!Br=FDd?C=8-fN%7I7aS%4nV8aJ?$^>Rh!G)DaQZ zGJ-5n&|Xj8?1l)mAz1vr)GVNM&Lj9p00080Nkl^Q-~ zm%Y8O-Pzrlc`10hhd%%QDKaK0ZmtdfdVTo(=NGmVJc@i-P$qzrr(fMpA}u+TR%%Uw zQJ{pXM!0`;;$3A6s#Y#X*N03+;pQ!obkQMDBrLeLxvo_Nai`Tu5?>XqxCw+q5Flce zendoH8gH#ba%VU!Yj=8lY$^lBkD;x5M1hu_7dfSH{*tqdk62( zxiAzaFL*Y|89-T>-+%j+31!Y+BMW7xTV0$prK@o|&$ZUddPETD=d|iY^zEyK(N-`M^!okN_4*$EO)OyzH@Z+3;pif zZ#WQ2JTO?4_`}OL5QMCm6en->>Uy1?Kl^$s&vTC;1@X@Dq#Xr9BC=vWhbp&=xojjL zB;|q-!sB+DPFAnZ z#(I3SzaxZV5AWUH`h0ltG0lqwdVIOFXU^WcSyr4JpmXC_e|#DT+uIMO<9|iaAim;B z6zuLDP(TgB(8`+;I^yyXAwGY*OK~1Y*LVNk@mOi)%ZmO7K`mtTbXr9g00000NkvXX Hu0mjfxUgI& literal 0 HcmV?d00001 diff --git a/technic/textures/technic_hv_transformer.png b/technic/textures/technic_hv_transformer.png new file mode 100644 index 0000000000000000000000000000000000000000..e1d4c98a05365c406a77d2bdaf9c662a8853325f GIT binary patch literal 1801 zcmV+k2ln`hP)geXWCAMNed+v1xskD#6V(B*c zX$r<-Pz1uV-V1w5vZb6r0CQseb9N_nYqt%&fd!pgVi(* zT(FXu`2TdW_J{xPthM&qd&B?LhJLVd69BiZU;pkJKm72+0NlD|+uXIg?qB`yYj@xE zle6L>X9^Au4zgy=8a8g-Hc;%Ix$E_~d}S0EY;B5G81623_t96MeEPyIcWxZ{uK?V- zY4azd&hD*2u{6)yK#li8{UlLyl16QUg|o^;p>3Y1>A}f~^z&=h+<5S;0c_f|>C4gV zz8^Qkyk;hlVpgX$HA=oZOmA12Mzu;5gd87vomuDfYh;U3oit;i=9gac)zz=QT>x`> zKviv$IWmt}6$GI~N~_kOR!vAV2y-z#-Ms`!EW>{}MBYwz6^f&WcJCN``u5w_Ukz~Q z`gQLNAd2(U!Wgmy>QjK_$Y_o7?1j{_fK)A&N(G>IsnB>Ie1AXD% z8*aII>(|z;mv>Zx4Lf#y*u=S?TM?|a_)M8nLB>zgqb+8HV3Rt>kG?`_c1%$0rL)|J zG@CTs6ensK(ZHotUO%a0&H9Ef&AslX#aB!F0N=ZFdv`G}qdCoZ?ZET&&Y6$vJC`vN z&~jLi!bF^-+Uf@M)<=Yn{<|XsFxSu zx-Wu`S@^7pkF11Ai*lhTGb8)hj{T23xA~_JeBgAy;Pk+yOP9&LgO8E-p0w4XRE#-s zXpoUT3+ew?DTJ$0RV-mQb)NbYczRi&%Mm*pTjk)R&l6W;n{6_ z8L1w}`a0p^D#7r@xOsI{V^RmPRRSROj=CDGI*cmDdkzdAz5jGCdnSOD%P;)8@xCh# z1B}4LM1^1c`YGnyG9UTIS9nj)Oy0lfea!4FasNGkX7Q3TaTpUc>Lh{1sp6-H3aSuf zDdHU@t-)VDvcLA08E7;b2Rp)GK%F8I&`~N-YSsDeGf(m2?+>u(vSswn?Wd!EiVM#9 z8&7RNOvgYUSA1*mNZR?B%rseL}-;{ z=uaFTK0st*mM?0uV8;1W{4mn=XbDsm<1%m=VuMpXQ7V<>Ew>>+XGcMtbE-N$DU2~R zBBg3lh=rCm$j1;QdAh^d%<4KwEH4we1jI}Os3#C`C|;rN8Ct!1_3^dzU7#YzjS z87dLtEmi|Wg+de|B$y}y8xc8~-a8T?&SAYnnKlM+B4pa;VFd8rCCgr_d5bef1y4u{ z2oA8JrIoaBJ_QXB^#p1Wny7#`hRlXIV+mY_S5U7+LC`+H_1_(w$aVI7vStdBh{0%z z2#A1p9_Jk{b2OVx!YDd*q9j3t2T~i5+7NFHieS`Ztqs}+xaGPp^6gDKADO#w@th<- z>)DzqfH8{x>jbmb5(FXMx#{e@@rPavajT9|k9bE0WMUXo^Jx13Ke`Km@sX3qZ`yL- z^0CCO@K_H9?>z>=3Wz!cMT}s)Lrj3EqN=EKWC~H1kV_g!(yF%&@K4=%$ByZ1`R@Hs z{Qb(oXhLV)ooEM04kxOi6|4!Ej0(*A(8sAnWl&Ee$dN=b=^K53FUnONA_(LXdaR9(Av z?SBSvCT+fF&+aK3T^m?Yyq8ElPDHaX5}g=-=(+LwHJ2pg&2{V6y}c5&qlflA$n{_N z?5e7j#S>0PaT#O@so2&;wRY{g)vG@BL8+h7{H*GZ?{5I$_C5Q5xZ%DBp1fi2qh)~Y r+qb`aPq}^j_MQ6PxpU|L#>4j?u}lFySv`Eh00000NkvXXu0mjfYgKPd literal 0 HcmV?d00001 diff --git a/technic/textures/technic_lv_solar_array_bottom.png b/technic/textures/technic_lv_solar_array_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..9e888e3011a8b619589b83266fa39877c56a9060 GIT binary patch literal 579 zcmV-J0=)f+P)< z02C1Ctpor7010qNS#tmY4yynF4yyr0}+8D022`y=qgePf{+lx7$K^g6m&H!B#>BZ zG0Tl@V%;G?AwofQZN%Ioh0AXj3>@dd^?K#gr!VA6s*3I&>ev{Q z5ddJQZa)0?al{qe-QDs2{l9$v{D9kdBXT$KWKFxL5W&kAFS)}+wBMLJuqY2-6LYG z1w3&J9v;5&_T4}H@$658>2AJXzf*N01}#ip7SaSpA~J~xzCGNqo3CH4qfa#mF27$m zk7KfM)(o&`LuQUOHX*Ra6(MpZ3T^w0GzoQiY=q%keR6t=3emOW3n*eQDcFIdJyB+( z=q}tQS3-++@1GgCimJlhv^^r@9c7z7PugR0*N!ew)kyQ5>paO!=%&u;`3dcoQh5(C RaP|NI002ovPDHLkV1mM@_{RVM literal 0 HcmV?d00001 diff --git a/technic/textures/technic_lv_solar_array_side.png b/technic/textures/technic_lv_solar_array_side.png new file mode 100644 index 0000000000000000000000000000000000000000..b22447ef68825d1731660a1c1b3c6c5af543bb5b GIT binary patch literal 465 zcmV;?0WSWDP)qLpk;0OPzs>xVu$@?{3L>$KR z4R{Ye(=>mHJzhzWiNVLYc#Eu#*g*g?oOP|FC-FzQLf|=ii1RJdynM?-8A_-N_aKdF zAqN7e-Svw&!-xo4e}0#jgL|A?-;?oBHcoej$6d4dtILs$D9;2iAlk23m%CTc5^$#k zz!|8Iw}wFpR6NZ>fhw--7FtS(Bl^IJns}NVq**))r~h~bbf&2) zG*Y*A7+?Me)P)StFOlm<`38f50YOv5D~SrI8Re;?6H~Vc7_(#c#X3mnhddK4BhLtt z(ShqgdBGWsB&N|?WD(d9q%&ihBodZq5QI+MBzEWqe@x>K{&dISA4~-800000NkvXX Hu0mjfYM9WK literal 0 HcmV?d00001 diff --git a/technic/textures/technic_lv_solar_array_top.png b/technic/textures/technic_lv_solar_array_top.png new file mode 100644 index 0000000000000000000000000000000000000000..cabd315d2f1fa54e79e918533b63d835c57e19fe GIT binary patch literal 743 zcmV?P)nkkrqXQe?dcj0F)7Qh=L{!H8mB81}R9S0Ye}~AO?eN0ugKP zuDyHTGsE}cCm-H1=K{3rTbtj0fBf-h_uHl8l%)b`5{~r!_qGOE95B^g5XVRk2?3)d zef-B?>@M1sne7<7ZkmyQ4gJW(2n}4gbNyNzWz^4y`Cy<;Iqdfc7$5;qDdzwVpfC|J zxVg7iw{moNSTz+@RZ-W=MJYSGd!{Y-UO|5i+!oLn$phs{6g+xzY$9putD@xjqHsiY zS$*~8edIpE&mcL_81$G^Pw{VOi%A@potlw1U1B_bqdiXmQtJu|L|ZZKA@6|vNIV8? z4KPUFZdUhv1^_FT3eg3oJ@iP-QccZ5Fb6O)*wW@tQ>nY5wnJ$Ku6Uob|1}ZFXStk`@nKvKFkp_-2w{_0c$gAt`1R z(kY`MN1Jjqo(Jy!J zyjm268U-Fyga@N6^nsZxmrH62vpG_R%)}_IQqVs;TWnli6X~|MCr3vI?7*q$#o{b~ zemtGelYFAhEs9UN&XC^9FWV^p+O+D_eto>}eMGax{KoFK55w7f8U}2*-!`8Mekb;W z$~V)Kd#9(%-O0_6DNg%@!hlAT002ovPDHLkV1kpSOBw(G literal 0 HcmV?d00001 diff --git a/technic/textures/technic_lv_transformer.png b/technic/textures/technic_lv_transformer.png new file mode 100644 index 0000000000000000000000000000000000000000..613b1962059f74b5fb04ffb0f857776724557560 GIT binary patch literal 1821 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 Ef(NcA%m4rY literal 0 HcmV?d00001 diff --git a/technic/textures/technic_mv_down_converter_top.png b/technic/textures/technic_mv_down_converter_top.png new file mode 100644 index 0000000000000000000000000000000000000000..a61066045e69a3957d960ab08593e28ea0cfa2e6 GIT binary patch literal 738 zcmV<80v-K{P)$3&$UJfsbMn4>gb>)ajTj@P6fP+-3;^iG=bL$^l!7g#AR>qe&RTNLl$@F7nG_@YzLQeo-!ES<#z5~#&SMfc7}@s&5n)?5UOxRpEhob;a7hWJ6z`s%ZkR=c-WtO& z;Jrsae}>*DXW?rZqiHCVQun*$oJlERwbr!W>9z9d<%MAwD7BE{h#W$#m3f}1EwipG zz4x13T2pJq*7M{jg>f9wNH^$ti zmV$MTx7SxYJuXTmt%71ymb=4rw?hcS->P)pHNyHksIQMtuDhB45Ws)U! zRMZY;baV&z(!uXr>zS;rm?cCftj$1}Gq_5@j{_kP zlvu&n=Rs8hPs-=3!2)+d4GvF4Ob})E!3?P1jaCQWPeoA5nNYWr=LzyrKsWvAh(Mo$ zCuc?AZYTqEff_kyW^@F_`)F(ifrBWLjJ+1KcfuUqfghPUI&MO(4?7on-xv)&uM4;T zr6im4aC)mGhr@-G6Uw5L!rt(Dy>S(CQp^=yYcpfx3b9~efX-} z%dzA{5J1tJpHfNcX~r&WAlR}b0wY)u!44a60M8h`ey#dsC5u^eO*mKn`s3F`3b6(* z&h>fo=RberRapwz7gm%E`0dA^IgdggjlEXZ0?$-d!W=O2X0JQ{*I6MV`TBg&MzUA% zwH6~1Hv`!yp8WpPFCa=E4bhFr#pa7S2BW>X?_?o_6*I~91m@1it05R(g$SV(=l$6sJDEWyv_2Vg@|nh7EBjGUw}baP zsM`*j^moT~aecceb)(b=tqnF8Rw~=()LNO*5ftyEkqiO{QKT3%5>sRJj%KhQCv$Y% zjJx;mK0PrSdYmV2&WfN&a%@g-H^pIdq11x1*!P`Gcs!oC3biQaimsK+NL(QnER4Dz z%w?n)v69#4;JzDmKe+EVGoX~poQi&27pg|Y0D~EeQcjNQY+f)`o~M%$Tp!<9F%e1D zx+$BYNaCurA&d?=2lxBp?gNoUYlFTvFhf#!KA(&k_;weC8@dr@Rh9Uxq z1|?Dyk;o{CY~sW*#01~n-re5p?2nnp_rZ7He#ue>z=!+S9y~eu{^uW^>nM@V3aJ=? z?tJ=rmg<18?gFg=B_Ifh;^f(jSKc*U(&pK6%RQ+gbJ8NZ=qlB3+E^xau_=wwI_f+#D)uGp ze3A<%K!e|~K;het0u{d-te%@>ka*E~7S}(TJh^v7nmX&zIZsLkv7}h)oY)HpSO}y< z>7iz3b`DTrh%!b1LF@&f>}{nRVbXL9Y^k!)s|FaQgM24%+Ez&!sZhu9qF4|iHm1Hf zser{AHm>z#FdoNEX;*Kts;qEA5^V}ol@)499y!)J>S?>S$(5-5$3$17R@gL82cv%L zI?wK4dTnvO=Yx zHl5NMLjXc#3^FyJFZXsw&UNGQjkB{8l0tgt*UNc6+_@}@(RjE!9u>aOOS|{s?qHY= zRtbCCd4B%vkx~&Zmc`AntJ1?V_ym(cy>BxCwgi6_>V`P8y)$&f&T$iZD1n`yoW*n0000< KMNUMnLSTZ1erHqw literal 0 HcmV?d00001 diff --git a/technic/textures/technicx32/technic_hv_solar_array_bottom.png b/technic/textures/technicx32/technic_hv_solar_array_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..94c82220d17121439939c1b88985aea891b76a69 GIT binary patch literal 2019 zcmV<92ORi`P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m4F01m4Gj_kzz00007bV*G`2iyw* z7cUx+Q&eIA00(19L_t(o!*!QU%Ph%pg`bGXtm^LfevCfA#@1+~h5Q2y($)whfw9ql zHMT+4QcLR(*b-s}WEgqi`rf(k+g+6z5ne=f&q&4vwd(53$P*{dIVnH>#V?XfG7~Zp zRWcF;tTj}Xh(JW}IcdEg-$H~Vs*sQ*0)XH?QMLMS1|&d&2r-@GL;8B6WdvqMijd)` z7?=Qwh$5n>Dd|pMRuF**BAok5qKahT5iIM9hM{UiOuDX&eZ#Di5l9m<18be|Ndw4C zL zR>&x-ikKk?+6>8p$;=+@X_uA#cBAkC6@g6DjEF#0!3?CD5{SZWF{HOdOmS=N3uxNmIZgGuP5dh4-#7Mh$_}vaRQJjRk#`2JL7sq zLXB7(lIWCUtP>zz3UYK7b#=8QzNHWR&**O>c$@Jqht z&b=sA8bYx8w?8v+65gy%j1RhzfJtYiw1q0v~OSwv=W> zBr6wuPQsntuY^xBf))|Ud6ZCxORId)!s@|LIbfr`Ltjp@$5@5KjE zM3QYExI5d+OHG0qbL?1e*zC9u09u3-QLvGa83)vXSSuw{>Xd#c=F@5Apa1Pw%-gNlAHmpnNEq8*h)RQ&G_!`PG3Uh0;1HD*VUB@WE9OS< zAD?~B>3rtH^~yGO-hcRtS5Hs$-r2{bsjzPwPvyW>%0GM5 z8hu$25yqIfJ3dAcy0rtOK+Le-5VMkEReQLdSu2wfK~)*sc61%ir}YtTlK)%8vaZZI z@d*4*xNu~GHO1%rx?52m(nRElVI@F5Cv90C(aXmqMfl>~|L}(|zTnNbzr}a{`g{@dSAP{ylHrzU9^B!uyXOQGx&Z?>|;xQKj|HcDt4Mgdd`ogjYe$ zS|i-)r2g7|$TP=IZ@r3eFEu-e zWJka-?Ikw*PG1&que>-Xa||M)Hjg-3plC!8N6hvkDvf=hs$4&QUFvL^11~zOJ;TAMviEK4(SbBW%QU0QTFB{dzrQ8TQ+i z?RG=7E*Fu9#ZoRew(UW%drXTcLu>2G9cdr+ZAR3@)i?_(f*i7}+8z4J~Re!HRF>S`7OIM}kFt+72n*Y&9{%tK1= zYB_xz_r!sqjEIB%{h^?Rz=DshVp!|=9ApI6`=j`}nu(M*n-vlVTYZj)LW(N;UZW;j z^DJ5r=FCHsDp6IzuwQTZ9LLBFVhqHr((;_Rm(@2B!48ItD7!nEQR($|D@T(?h7cJj z4Uw{D_b5aX9GGK2+G2RzmGm&7C}XPm4_aUDc|h>+GMGau(;aJ#zAT97!#M7*&%xL> zeAK1G-Rm9!$K^FiPh!@l`i(;7zLOcuvD13ve*tr#O^<7`YHR=i002ovPDHLkV1i5_ B;l2O> literal 0 HcmV?d00001 diff --git a/technic/textures/technicx32/technic_hv_solar_array_side.png b/technic/textures/technicx32/technic_hv_solar_array_side.png new file mode 100644 index 0000000000000000000000000000000000000000..d39d3d81e462c2f4dfca86ec7563893195bca47b GIT binary patch literal 1772 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m4F01m4Gj_kzz00007bV*G`2iyw* z7cVlU=KPod00wMHL_t(o!&R4CcH}q?L@z*)O1r!FGrO4C|2nGdlt=*c0ZOj+kMrn3 z5rIHNQ2z7Z|0S7ZCS)S2^;@7dLsf|k1i^h_*6ThH?uaS?nTZI1;A^3+)w>bw2S9{y z=l<)j7nTvU)<_XD9MuLQkcp}yswhf^W8*+XAfgr$0Ra(3GH?&ZYt+YEBYe^AV9t|f zos2+4$Ou~R#9G+T?gi0$v6+#XWCYq;A!CNSle?nl8K?px7$1Xhr@sanPKKgQIP3#o z3q+B~U2FhZ8xYm1wlzcqZH)wkMEB0gz>b6K{f!`np%k>*jEF#6wWHQBY7wDX+XW@k z1W{pK6TcRw`=h8JBG?!|(6>g+$%-H|QNXOz%<#3yOqw-X9|fx!^Sb`UB~hiBA==1r z=5-OPTBxmI_rui!*)7;R&SZRi;J<$%`Ln@-`M~FVNZ5KuL}+HH2uMAjnNM5i`;CgS z{GyrB%rK^=< zGim!d1L*yLOniBDeop|v`1~X@33qZ6)_Sj(duLr&ZEjZ??zCRKiA=`lCq!_5eW9&! zeSeb?WNWPR#A;R-nM$)_rmM*aaGTMOqn=e|T^A3TH}qnL_5P6W`1~y1xO0Ag z6KmCIM+CheXwwp&-J2W6H5Yvh)><^PpAn1z5v+I2jI|cld-WdBR%3d8e?2XT2y}03 z%?St^?px7n^lIdi*wy78zmI?Z*(B>oYqZ|!$3b|Yz0=2dM(;-N{rgvmU_?y^u&#^9 zd<3JGBT4mqenAeGo<1wvL&DUe$8G$=w)KqCklu7Je`|`&& zZ4CMth$^qY|0>9j18Mq`1EdPb2qJ<$27UC0oT|EKK3KCvOAy-VkXdGQ%PCn-)_Ui; zu3C$4^TM zqnEM)K8pj8kNJfA&;Q*95y3M__bONgU28s2kJrZ|JnOoC@*EJp9^KCj)_Icdynp{@ zty#hn`Pj1TiL&1DHCfvSZs+t>Vx+AZ83k{wS!y+BLAP1E=B!NT@d(rI7$D5|oAdi? zyQpBt@vrLdcGhGG@RK(!NmRGFm?08R(7d^E_x{O=R+}z?D)!$}YrSK~QAntAeSf27 zL^x|+%=eqTgKZ|JqR$A5DovH~@qxC+`20jwA4R-ncfQ~F?T#Yl8G9_(oVYu$zy1as zX^otdwNbqTX{>6g-9!o?*2F$OnRD{$o%gR_d-QgUc7M_kf1C~OEU?b=2`lIK7tI_je^?5n|Ol>ko^a=UMme1C9vk)xLfl zs3?+!&^*trz6-mfv+N*I>2~Z7C-3jCa<60)Q;^om2i8L7e8TC!LhBgBj$(Ekv@!7a zH|)uXsFZ9stIGxNXni6nq|}V32i8Z~Dv)zNNSTfjpWWYip4b>%?>D-G==t@v4^hJF z^Alh5i2#-n#6D-(7^oTV-@hT^M{cv^Gcw6JtB-RcD$F>GkiFNnJ$^O@>pYp)weMBi ztap5GzK&*p9LX{hpBL=ezZH@#$rU05tinrp5LCE~C6z075Xtwuev1@hb5`r3T6Zg~ zi3m+=G10}fy*t9W-tQ+wq*Ul=X2ecNL=aakeB{I#P0@SRy7VJor# O0000DK_@!=j)P0@X{Mf>g@q&D<-cWA6%WZ2EA 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 FV1k4YPv!ss literal 0 HcmV?d00001 diff --git a/technic/textures/technicx32/technic_hv_transformer.png b/technic/textures/technicx32/technic_hv_transformer.png new file mode 100644 index 0000000000000000000000000000000000000000..7794644fba52b375b9c2fea8f04dc1a3dccb3d2a GIT binary patch literal 1789 zcmV z)P~4y#U>{HpLX_s`2Vuk+Iy`9|5qJ)YV}$GR`&J1zs9?F?*`!Ub?Z8wTD^A3Kc8*e zviZ7r$kjIc`}^tb?d6->f6;XlwI3$d&W|vRqbP^b)`qOM;8(}qx^3^H4-NlU0Qy$< ze@0r{*XQ#2X`Zt#m)1n8=ShuWG>Mr#xk%^{pC5NeOPA9x_4Yn|^tu78S-b9Qs$=@I z$~lKajPIjH28qT8ncUJ$wOl6fe1?Y4(>9~i1-c;RlDg=-{M>~PEcwg31yJwYh`m7T z${2|iiE~91kVQo$4f#P{PS`0y3`yMMviZNrvK$9R`%To@cq7J z?+u{I6Ji~JNpY1j$~uP6jnLfIMLF|Gon~}&6q{DadkLMLQxHkz%-}Ipa&BH{M}9}| zV=LBweOaHpw-Bt~aF;~ki=q@olR{!R??>3uMOsK{@MPBqjYY_RZGLGK0ou3<=yv5{Q#@itZnfdawB<{GI;19Q#x+MwN2-;2!#u0 z@heq^2T#&H`(~IB5C193Wau@wN3|4DkCG-SNfg@@Bi{I>k2_3 zP{_bxPVU=Ia{3LrS_4XlU!*M=Ln4KH^E5Yq_;$|TFr7X7g~NY}Y0EcJX`F?b{6Qi= zB6TTR8Npcm=2poyHooxe^SfVL_59wCTod5-xjpjN6DM%ilGb91g^+WnPcr)JmyonX zI)4_!d-ro-_fhWrL^pFjIg93L-6TyNgrSn~w^R=tMn2TSoS?)X_WcpTFeWv`StOi<@&f>pFapoR zWhsdTn@?GSIDd-5k(>jH++6#_Pu}^MfrfbMJ%G2(@CIDsj%k&&Dy%qD_VcoO4K)lF#M*x&W%x z>d^+@>vF~+;?YoyDAp?cZvSsMeCQyz+|fgOM<)%PW8Bhpf)_Rq&@iKokAJ!csd;#w z25a%sgxCwn!hkT1!DiG2kY@G>zI+NST5HlYB@mDH<|4j!Bm=K=a_}I53hBAEM%Sd- zjM_nhN{woy@U0<3VU)&cjb}2n2w|}(*GxiyNez)0W1MpnKZR0?YTziV6hfiqs^mlP zk~}T`6xy1P63Q{OHDq3ZLGWyb336C#u?~_f8(6Yr$xvMY<vp8EN~}v5FTk4VSgB%xOca?YoC9qQxwJ+mO4s!f0SuRu0qY!EYG{|?BtWc2 zI}dR}6a)wfDhNOa1V$#_j(A|-ereXCZHAwvXp@q;I*Sp&2j=t~8MhjvloKpIDIgd? z`#h-dzal(XO38<$@EtBXE2yQy$h^XsZ7A72H)#vg57vwG`uFMVsro<@L;8#lgxqukD&JFl!a fZQAs|G5G!siW~h8)U-(*00000NkvXXu0mjfh`C(- literal 0 HcmV?d00001 diff --git a/technic/textures/technicx32/technic_lv_solar_array_bottom.png b/technic/textures/technicx32/technic_lv_solar_array_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..94c82220d17121439939c1b88985aea891b76a69 GIT binary patch literal 2019 zcmV<92ORi`P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m4F01m4Gj_kzz00007bV*G`2iyw* z7cUx+Q&eIA00(19L_t(o!*!QU%Ph%pg`bGXtm^LfevCfA#@1+~h5Q2y($)whfw9ql zHMT+4QcLR(*b-s}WEgqi`rf(k+g+6z5ne=f&q&4vwd(53$P*{dIVnH>#V?XfG7~Zp zRWcF;tTj}Xh(JW}IcdEg-$H~Vs*sQ*0)XH?QMLMS1|&d&2r-@GL;8B6WdvqMijd)` z7?=Qwh$5n>Dd|pMRuF**BAok5qKahT5iIM9hM{UiOuDX&eZ#Di5l9m<18be|Ndw4C zL zR>&x-ikKk?+6>8p$;=+@X_uA#cBAkC6@g6DjEF#0!3?CD5{SZWF{HOdOmS=N3uxNmIZgGuP5dh4-#7Mh$_}vaRQJjRk#`2JL7sq zLXB7(lIWCUtP>zz3UYK7b#=8QzNHWR&**O>c$@Jqht z&b=sA8bYx8w?8v+65gy%j1RhzfJtYiw1q0v~OSwv=W> zBr6wuPQsntuY^xBf))|Ud6ZCxORId)!s@|LIbfr`Ltjp@$5@5KjE zM3QYExI5d+OHG0qbL?1e*zC9u09u3-QLvGa83)vXSSuw{>Xd#c=F@5Apa1Pw%-gNlAHmpnNEq8*h)RQ&G_!`PG3Uh0;1HD*VUB@WE9OS< zAD?~B>3rtH^~yGO-hcRtS5Hs$-r2{bsjzPwPvyW>%0GM5 z8hu$25yqIfJ3dAcy0rtOK+Le-5VMkEReQLdSu2wfK~)*sc61%ir}YtTlK)%8vaZZI z@d*4*xNu~GHO1%rx?52m(nRElVI@F5Cv90C(aXmqMfl>~|L}(|zTnNbzr}a{`g{@dSAP{ylHrzU9^B!uyXOQGx&Z?>|;xQKj|HcDt4Mgdd`ogjYe$ zS|i-)r2g7|$TP=IZ@r3eFEu-e zWJka-?Ikw*PG1&que>-Xa||M)Hjg-3plC!8N6hvkDvf=hs$4&QUFvL^11~zOJ;TAMviEK4(SbBW%QU0QTFB{dzrQ8TQ+i z?RG=7E*Fu9#ZoRew(UW%drXTcLu>2G9cdr+ZAR3@)i?_(f*i7}+8z4J~Re!HRF>S`7OIM}kFt+72n*Y&9{%tK1= zYB_xz_r!sqjEIB%{h^?Rz=DshVp!|=9ApI6`=j`}nu(M*n-vlVTYZj)LW(N;UZW;j z^DJ5r=FCHsDp6IzuwQTZ9LLBFVhqHr((;_Rm(@2B!48ItD7!nEQR($|D@T(?h7cJj z4Uw{D_b5aX9GGK2+G2RzmGm&7C}XPm4_aUDc|h>+GMGau(;aJ#zAT97!#M7*&%xL> zeAK1G-Rm9!$K^FiPh!@l`i(;7zLOcuvD13ve*tr#O^<7`YHR=i002ovPDHLkV1i5_ B;l2O> literal 0 HcmV?d00001 diff --git a/technic/textures/technicx32/technic_lv_solar_array_side.png b/technic/textures/technicx32/technic_lv_solar_array_side.png new file mode 100644 index 0000000000000000000000000000000000000000..d39d3d81e462c2f4dfca86ec7563893195bca47b GIT binary patch literal 1772 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 literal 0 HcmV?d00001 diff --git a/technic/textures/technicx32/technic_mv_solar_array_bottom.png b/technic/textures/technicx32/technic_mv_solar_array_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..94c82220d17121439939c1b88985aea891b76a69 GIT binary patch literal 2019 zcmV<92ORi`P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m4F01m4Gj_kzz00007bV*G`2iyw* z7cUx+Q&eIA00(19L_t(o!*!QU%Ph%pg`bGXtm^LfevCfA#@1+~h5Q2y($)whfw9ql zHMT+4QcLR(*b-s}WEgqi`rf(k+g+6z5ne=f&q&4vwd(53$P*{dIVnH>#V?XfG7~Zp zRWcF;tTj}Xh(JW}IcdEg-$H~Vs*sQ*0)XH?QMLMS1|&d&2r-@GL;8B6WdvqMijd)` z7?=Qwh$5n>Dd|pMRuF**BAok5qKahT5iIM9hM{UiOuDX&eZ#Di5l9m<18be|Ndw4C zL zR>&x-ikKk?+6>8p$;=+@X_uA#cBAkC6@g6DjEF#0!3?CD5{SZWF{HOdOmS=N3uxNmIZgGuP5dh4-#7Mh$_}vaRQJjRk#`2JL7sq zLXB7(lIWCUtP>zz3UYK7b#=8QzNHWR&**O>c$@Jqht z&b=sA8bYx8w?8v+65gy%j1RhzfJtYiw1q0v~OSwv=W> zBr6wuPQsntuY^xBf))|Ud6ZCxORId)!s@|LIbfr`Ltjp@$5@5KjE zM3QYExI5d+OHG0qbL?1e*zC9u09u3-QLvGa83)vXSSuw{>Xd#c=F@5Apa1Pw%-gNlAHmpnNEq8*h)RQ&G_!`PG3Uh0;1HD*VUB@WE9OS< zAD?~B>3rtH^~yGO-hcRtS5Hs$-r2{bsjzPwPvyW>%0GM5 z8hu$25yqIfJ3dAcy0rtOK+Le-5VMkEReQLdSu2wfK~)*sc61%ir}YtTlK)%8vaZZI z@d*4*xNu~GHO1%rx?52m(nRElVI@F5Cv90C(aXmqMfl>~|L}(|zTnNbzr}a{`g{@dSAP{ylHrzU9^B!uyXOQGx&Z?>|;xQKj|HcDt4Mgdd`ogjYe$ zS|i-)r2g7|$TP=IZ@r3eFEu-e zWJka-?Ikw*PG1&que>-Xa||M)Hjg-3plC!8N6hvkDvf=hs$4&QUFvL^11~zOJ;TAMviEK4(SbBW%QU0QTFB{dzrQ8TQ+i z?RG=7E*Fu9#ZoRew(UW%drXTcLu>2G9cdr+ZAR3@)i?_(f*i7}+8z4J~Re!HRF>S`7OIM}kFt+72n*Y&9{%tK1= zYB_xz_r!sqjEIB%{h^?Rz=DshVp!|=9ApI6`=j`}nu(M*n-vlVTYZj)LW(N;UZW;j z^DJ5r=FCHsDp6IzuwQTZ9LLBFVhqHr((;_Rm(@2B!48ItD7!nEQR($|D@T(?h7cJj z4Uw{D_b5aX9GGK2+G2RzmGm&7C}XPm4_aUDc|h>+GMGau(;aJ#zAT97!#M7*&%xL> zeAK1G-Rm9!$K^FiPh!@l`i(;7zLOcuvD13ve*tr#O^<7`YHR=i002ovPDHLkV1i5_ B;l2O> literal 0 HcmV?d00001 diff --git a/technic/textures/technicx32/technic_mv_solar_array_side.png b/technic/textures/technicx32/technic_mv_solar_array_side.png new file mode 100644 index 0000000000000000000000000000000000000000..d39d3d81e462c2f4dfca86ec7563893195bca47b GIT binary patch literal 1772 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 m9FEEt#4_Nl#Z%!D$NvNUq{J+VK9K$Z00000 then hacky_swap_node(pos1,"technic:hv_cable"..rule) end + meta=minetest.env:get_meta(pos1) + meta:set_float("x2",x2) + end + + pos1.x=pos1.x-2 + if minetest.env:get_meta(pos1):get_float("hv_cablelike")==1 then + x1=0 + x2=minetest.env:get_meta(pos1):get_float("x2") + y1=minetest.env:get_meta(pos1):get_float("y1") + y2=minetest.env:get_meta(pos1):get_float("y2") + z1=minetest.env:get_meta(pos1):get_float("z1") + z2=minetest.env:get_meta(pos1):get_float("z2") + rule=make_rule_number(x1,x2,y1,y2,z1,z2) + if rule==0 then hacky_swap_node(pos1,"technic:hv_cable") end + if rule>0 then hacky_swap_node(pos1,"technic:hv_cable"..rule) end + meta=minetest.env:get_meta(pos1) + meta:set_float("x1",x1) + end + pos1.x=pos1.x+1 + + pos1.y=pos1.y+1 + if minetest.env:get_meta(pos1):get_float("hv_cablelike")==1 then + y2=0 + x1=minetest.env:get_meta(pos1):get_float("x1") + x2=minetest.env:get_meta(pos1):get_float("x2") + y1=minetest.env:get_meta(pos1):get_float("y1") + z1=minetest.env:get_meta(pos1):get_float("z1") + z2=minetest.env:get_meta(pos1):get_float("z2") + rule=make_rule_number(x1,x2,y1,y2,z1,z2) + if rule==0 then hacky_swap_node(pos1,"technic:hv_cable") end + if rule>0 then hacky_swap_node(pos1,"technic:hv_cable"..rule) end + meta=minetest.env:get_meta(pos1) + meta:set_float("y2",y2) + end + + pos1.y=pos1.y-2 + if minetest.env:get_meta(pos1):get_float("hv_cablelike")==1 then + y1=0 + x1=minetest.env:get_meta(pos1):get_float("x1") + x2=minetest.env:get_meta(pos1):get_float("x2") + y2=minetest.env:get_meta(pos1):get_float("y2") + z1=minetest.env:get_meta(pos1):get_float("z1") + z2=minetest.env:get_meta(pos1):get_float("z2") + rule=make_rule_number(x1,x2,y1,y2,z1,z2) + if rule==0 then hacky_swap_node(pos1,"technic:hv_cable") end + if rule>0 then hacky_swap_node(pos1,"technic:hv_cable"..rule) end + meta=minetest.env:get_meta(pos1) + meta:set_float("y1",y1) + end + pos1.y=pos1.y+1 + + pos1.z=pos1.z+1 + if minetest.env:get_meta(pos1):get_float("hv_cablelike")==1 then + z2=0 + x1=minetest.env:get_meta(pos1):get_float("x1") + x2=minetest.env:get_meta(pos1):get_float("x2") + y1=minetest.env:get_meta(pos1):get_float("y1") + y2=minetest.env:get_meta(pos1):get_float("y2") + z1=minetest.env:get_meta(pos1):get_float("z1") + rule=make_rule_number(x1,x2,y1,y2,z1,z2) + if rule==0 then hacky_swap_node(pos1,"technic:hv_cable") end + if rule>0 then hacky_swap_node(pos1,"technic:hv_cable"..rule) end + meta=minetest.env:get_meta(pos1) + meta:set_float("z2",z2) + end + + pos1.z=pos1.z-2 + if minetest.env:get_meta(pos1):get_float("hv_cablelike")==1 then + z1=0 + x1=minetest.env:get_meta(pos1):get_float("x1") + x2=minetest.env:get_meta(pos1):get_float("x2") + y1=minetest.env:get_meta(pos1):get_float("y1") + y2=minetest.env:get_meta(pos1):get_float("y2") + z2=minetest.env:get_meta(pos1):get_float("z2") + rule=make_rule_number(x1,x2,y1,y2,z1,z2) + if rule==0 then hacky_swap_node(pos1,"technic:hv_cable") end + if rule>0 then hacky_swap_node(pos1,"technic:hv_cable"..rule) end + meta=minetest.env:get_meta(pos1) + meta:set_float("z1",z1) + end + pos1.y=pos1.y+1 + +end + diff --git a/unified_inventory/api.lua b/unified_inventory/api.lua index 029ae68..02c08e9 100644 --- a/unified_inventory/api.lua +++ b/unified_inventory/api.lua @@ -10,6 +10,8 @@ unified_inventory.filtered_items_list = {} unified_inventory.activefilter = {} unified_inventory.alternate = {} unified_inventory.current_item = {} +unified_inventory.crafts_table ={} +unified_inventory.crafts_table_count=0 -- default inventory page unified_inventory.default = "craft" @@ -26,8 +28,18 @@ minetest.after(0.01, function() if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then table.insert(unified_inventory.items_list, name) + local recipes=minetest.get_all_craft_recipes(name) + if unified_inventory.crafts_table[name]==nil then + unified_inventory.crafts_table[name] = {} + end + if recipes then + for i=1,#recipes,1 do + table.insert(unified_inventory.crafts_table[name],recipes[i]) + end + end end end + --print(dump(unified_inventory.crafts_table)) table.sort(unified_inventory.items_list) unified_inventory.items_list_size = #unified_inventory.items_list print ("Unified Inventory. inventory size: "..unified_inventory.items_list_size) @@ -37,7 +49,6 @@ end) minetest.register_on_joinplayer(function(player) local player_name = player:get_player_name() unified_inventory.players[player_name]={} - unified_inventory.players[player_name]["sound_volume"]=minetest.setting_get("sound_volume")*10 unified_inventory.current_index[player_name] = 1 unified_inventory.filtered_items_list[player_name] = {} unified_inventory.filtered_items_list[player_name] = unified_inventory.items_list @@ -47,8 +58,8 @@ minetest.register_on_joinplayer(function(player) unified_inventory.alternate[player_name] = 1 unified_inventory.current_item[player_name] =nil unified_inventory.set_inventory_formspec(player,unified_inventory.get_formspec(player, unified_inventory.default)) - ---crafting guide inventories + +--crafting guide inventories local inv = minetest.create_detached_inventory(player:get_player_name().."craftrecipe",{ allow_put = function(inv, listname, index, stack, player) return 0 @@ -64,8 +75,8 @@ local inv = minetest.create_detached_inventory(player:get_player_name().."craftr return 0 end, }) - inv:set_size("output", 1) - inv:set_size("build", 3*3) +inv:set_size("output", 1) +inv:set_size("build", 3*3) -- refill slot unified_inventory.refill = minetest.create_detached_inventory(player_name.."refill", { @@ -82,7 +93,6 @@ unified_inventory.refill = minetest.create_detached_inventory(player_name.."refi end, }) unified_inventory.refill:set_size("main", 1) -end) -- trash slot unified_inventory.trash = minetest.create_detached_inventory("trash", { @@ -100,24 +110,18 @@ unified_inventory.trash = minetest.create_detached_inventory("trash", { end, }) unified_inventory.trash:set_size("main", 1) +end) -- set_inventory_formspec unified_inventory.set_inventory_formspec = function(player,formspec) if player then - if minetest.setting_getbool("creative_mode") then - -- if creative mode is on then wait a bit - minetest.after(0.01,function() - player:set_inventory_formspec(formspec) - end) - else player:set_inventory_formspec(formspec) - end end end -- get_formspec unified_inventory.get_formspec = function(player,page) - if player==nil then return "" end + if player==nil then return "" end local player_name = player:get_player_name() unified_inventory.current_page[player_name]=page @@ -206,9 +210,9 @@ unified_inventory.get_formspec = function(player,page) formspec = formspec.."label[2,0;"..item_name.."]" local alternates = 0 local alternate = unified_inventory.alternate[player_name] - local crafts = crafts_table[item_name] + local crafts = unified_inventory.crafts_table[item_name] - if crafts ~= nil then + if crafts ~= nil and #crafts>0 then alternates = #crafts local craft = crafts[alternate] local method = "Crafting" @@ -440,7 +444,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if item_name then local alternates = 0 local alternate=unified_inventory.alternate[player_name] - local crafts = crafts_table[item_name] + local crafts = unified_inventory.crafts_table[item_name] if crafts ~= nil then alternates = #crafts end @@ -537,134 +541,63 @@ end -- update_recipe unified_inventory.update_recipe = function(player, stack_name, alternate) - --print("Lookup:"..stack_name) local inv = minetest.get_inventory({type="detached", name=player:get_player_name().."craftrecipe"}) for i=0,inv:get_size("build"),1 do inv:set_stack("build", i, nil) end - inv:set_stack("cook", 1, nil) - inv:set_stack("fuel", 1, nil) - - inv:set_stack("output", 1, stack_name) - local def + inv:set_stack("output", 1, nil) alternate = tonumber(alternate) or 1 - local crafts = crafts_table[stack_name] - if crafts == nil then - --minetest.chat_send_player(player:get_player_name(), "no recipe available for "..stack_name) - return - end + local crafts = unified_inventory.crafts_table[stack_name] + print(dump(crafts)) + local next=next + if next(crafts) == nil then return end -- no craft recipes if alternate < 1 or alternate > #crafts then alternate = 1 end local craft = crafts[alternate] - --print (dump(craft)) - --minetest.chat_send_player(player:get_player_name(), "recipe for "..stack_name..": "..dump(craft)) - - local itemstack = ItemStack(craft.output) - inv:set_stack("output", 1, itemstack) - + inv:set_stack("output", 1, craft.output) + local items=craft.items -- cook, fuel, grinding recipes if craft.type == "cooking" or craft.type == "fuel" or craft.type == "grinding" then - def=unified_inventory.find_item_def(craft.recipe) + def=unified_inventory.find_item_def(craft["items"][1]) if def then inv:set_stack("build", 1, def) end return end - - -- build (shaped or shapeless) - if craft.recipe[1] then - def=unified_inventory.find_item_def(craft.recipe[1]) - if def then - inv:set_stack("build", 1, def) - else - def=unified_inventory.find_item_def(craft.recipe[1][1]) - if def then - inv:set_stack("build", 1, def) - end - def=unified_inventory.find_item_def(craft.recipe[1][2]) - if def then - inv:set_stack("build", 2, def) - end - def=unified_inventory.find_item_def(craft.recipe[1][3]) - if def then - inv:set_stack("build", 3, def) - end - end - end - if craft.recipe[2] then - def=unified_inventory.find_item_def(craft.recipe[2]) - if def then - inv:set_stack("build", 2, def) - else - def=unified_inventory.find_item_def(craft.recipe[2][1]) - if def then - inv:set_stack("build", 4, def) - end - def=unified_inventory.find_item_def(craft.recipe[2][2]) - if def then - inv:set_stack("build", 5, def) - end - def=unified_inventory.find_item_def(craft.recipe[2][3]) - if def then - inv:set_stack("build", 6, def) - end - end - end - - if craft.recipe[3] then - def=unified_inventory.find_item_def(craft.recipe[3]) - if def then - inv:set_stack("build", 3, def) - else - def=unified_inventory.find_item_def(craft.recipe[3][1]) - if def then - inv:set_stack("build", 7, def) - end - def=unified_inventory.find_item_def(craft.recipe[3][2]) - if def then - inv:set_stack("build", 8, def) - end - def=unified_inventory.find_item_def(craft.recipe[3][3]) - if def then - inv:set_stack("build", 9, def) - end + if craft.width==0 then + local build_table={1,2,3} + for i=1,3,1 do + if craft.items[i] then + def=unified_inventory.find_item_def(craft.items[i]) + if def then inv:set_stack("build", build_table[i], def) end end end - if craft.recipe[4] then - def=unified_inventory.find_item_def(craft.recipe[4]) - if def then - inv:set_stack("build", 4, def) - end end - if craft.recipe[5] then - def=unified_inventory.find_item_def(craft.recipe[5]) - if def then - inv:set_stack("build", 5, def) + if craft.width==1 then + local build_table={1,4,7} + for i=1,3,1 do + if craft.items[i] then + def=unified_inventory.find_item_def(craft.items[i]) + if def then inv:set_stack("build", build_table[i], def) end end end - if craft.recipe[6] then - def=unified_inventory.find_item_def(craft.recipe[6]) - if def then - inv:set_stack("build", 6, def) - end end - if craft.recipe[7] then - def=unified_inventory.find_item_def(craft.recipe[7]) - if def then - inv:set_stack("build", 7, def) + if craft.width==2 then + local build_table={1,2,4,5,7,8} + for i=1,6,1 do + if craft.items[i] then + def=unified_inventory.find_item_def(craft.items[i]) + if def then inv:set_stack("build", build_table[i], def) end end end - if craft.recipe[8] then - def=unified_inventory.find_item_def(craft.recipe[8]) - if def then - inv:set_stack("build", 8, def) - end end - if craft.recipe[9] then - def=unified_inventory.find_item_def(craft.recipe[9]) - if def then - inv:set_stack("build", 9, def) + if craft.width==3 then + for i=1,9,1 do + if craft.items[i] then + def=unified_inventory.find_item_def(craft.items[i]) + if def then inv:set_stack("build", i, def) end + end end end end @@ -674,14 +607,39 @@ if type(def1)=="string" then if string.find(def1, "group:") then def1=string.gsub(def1, "group:", "") def1=string.gsub(def1, '\"', "") - for name,def in pairs(minetest.registered_items) do - if def.groups[def1] == 1 and def.groups.not_in_creative_inventory ~= 1 then - return def - end - end + local items=unified_inventory.items_in_group(def1) + return items[1] else - return def1 + return def1 end end return nil end + +unified_inventory.items_in_group = function(group) + local items = {} + for name, item in pairs(minetest.registered_items) do + for _, g in ipairs(group:split(',')) do + if item.groups[g] then + table.insert(items,name) + end + end + end + return items +end + +-- register_craft +unified_inventory.register_craft = function(options) + if options.output == nil then + return + end + local itemstack = ItemStack(options.output) + if itemstack:is_empty() then + return + end + if unified_inventory.crafts_table[itemstack:get_name()]==nil then + unified_inventory.crafts_table[itemstack:get_name()] = {} + end + table.insert(unified_inventory.crafts_table[itemstack:get_name()],options) + --crafts_table_count=crafts_table_count+1 +end diff --git a/unified_inventory/depends.txt b/unified_inventory/depends.txt index 8b79558..8b13789 100644 --- a/unified_inventory/depends.txt +++ b/unified_inventory/depends.txt @@ -1,2 +1 @@ -aaa_recipeshook -creative + diff --git a/unified_inventory/textures/ui_furnace_inventory.png b/unified_inventory/textures/ui_furnace_inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..410e2b288f8320eea79c8912075f837aecea8d08 GIT binary patch literal 7697 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 literal 0 HcmV?d00001 diff --git a/unified_inventory/textures/ui_main_inventory.png b/unified_inventory/textures/ui_main_inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..d17d5384f14dbaadc410fcd37c566bc9e78f9294 GIT binary patch literal 8617 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 literal 0 HcmV?d00001 -- 2.30.2