Changed power distribution method and streamlined the various existing machines.
authorkpoppel <poulsen.kim@gmail.com>
Mon, 1 Jul 2013 22:03:36 +0000 (00:03 +0200)
committerkpoppel <poulsen.kim@gmail.com>
Mon, 1 Jul 2013 22:03:36 +0000 (00:03 +0200)
An electrical network now requires a switching station to work. This statin is the one
resolving the network collecting power and distributing it again.
Added up/down converter. It is kind of finished. It can be updated with a slot for an upgrade
but so far it works without by resolving the types of wires above and below the box.
Tool and machine registering changed to use a table with key+value instead of the iterative method it used to have.
The power radiator changed to be able to send up to 3000MV EUs in a radius of 6.

This update will most likely require existing networks to be dug up and placed again. Also the
switching station must be added.

33 files changed:
technic/alloy_furnace.lua
technic/alloy_furnace_mv.lua
technic/alloy_furnaces_commons.lua
technic/battery_box.lua
technic/battery_box_hv.lua
technic/battery_box_mv.lua
technic/cans.lua
technic/chainsaw.lua
technic/cnc.lua
technic/electric_furnace.lua
technic/electric_furnace_mv.lua
technic/flashlight.lua
technic/forcefield.lua
technic/generator.lua
technic/geothermal.lua
technic/grinder.lua
technic/grinder_gloopores.lua
technic/init.lua
technic/lighting.lua
technic/mining_drill.lua
technic/mining_laser_mk1.lua
technic/music_player.lua
technic/power_radiator.lua
technic/register_machine_and_tool.lua [new file with mode: 0644]
technic/solar_array_hv.lua
technic/solar_array_lv.lua
technic/solar_array_mv.lua
technic/solar_panel.lua
technic/sonic_screwdriver.lua
technic/supply_converter.lua [new file with mode: 0644]
technic/switching_station.lua [new file with mode: 0644]
technic/tool_workshop.lua
technic/water_mill.lua

index 149688e858cf52e7c0702376d2882cfc907946e1..d36b93cbda344d6642aee9125270876fa0635f90 100644 (file)
@@ -1,12 +1,14 @@
+-- LV Alloy furnace
 minetest.register_craft({
        output = 'technic:coal_alloy_furnace',
        recipe = {
                {'default:brick', 'default:brick', 'default:brick'},
-               {'default:brick', '', 'default:brick'},
+               {'default:brick', '',              'default:brick'},
                {'default:brick', 'default:brick', 'default:brick'},
        }
 })
 
+-- FIXME: kpoppel: I'd like to introduce an induction heating element here...
 minetest.register_craft({
        output = 'technic:alloy_furnace',
        recipe = {
@@ -16,193 +18,178 @@ minetest.register_craft({
        }
 })
 
--- LV alloy furnace
-
-alloy_furnace_formspec =
-       "invsize[8,9;]"..
-       "image[1,1;1,2;technic_power_meter_bg.png]"..
-       "list[current_name;src;3,1;1,1;]"..
-       "list[current_name;src2;3,2;1,1;]"..
-       "list[current_name;dst;5,1;2,2;]"..
-       "list[current_player;main;0,5;8,4;]"..
-       "label[0,0;Electric Alloy Furnace]"..
-       "label[1,3;Power level]"
-       
-minetest.register_node("technic:alloy_furnace", {
-       description = "Electric alloy furnace",
-       tiles = {"technic_alloy_furnace_top.png", "technic_machine_bottom.png", "technic_alloy_furnace_side.png",
-               "technic_alloy_furnace_side.png", "technic_alloy_furnace_side.png", "technic_alloy_furnace_front.png"},
-       paramtype2 = "facedir",
-       groups = {cracky=2},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_stone_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       interal_EU_buffer_size=2000;
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_float("technic_power_machine", 1)
-               meta:set_string("formspec", alloy_furnace_formspec)
-               meta:set_string("infotext", "Electric Alloy furnace")
-               local inv = meta:get_inventory()
-               inv:set_size("src", 1)
-               inv:set_size("src2", 1)
-               inv:set_size("dst", 4)
-               local EU_used  = 0
-               local furnace_is_cookin = 0
-               local cooked = nil
-               meta:set_float("internal_EU_buffer",0)
-               meta:set_float("internal_EU_buffer_size",2000)
-               meta:set_float("tube_time", 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 end
-               if not inv:is_empty("src") then
-                       return false end
-               if not inv:is_empty("src2") then
-                       return false end
-               return true
-       end,
+local alloy_furnace_formspec =
+   "invsize[8,9;]"..
+   "list[current_name;src;3,1;1,1;]"..
+   "list[current_name;src2;3,2;1,1;]"..
+   "list[current_name;dst;5,1;2,2;]"..
+   "list[current_player;main;0,5;8,4;]"..
+   "label[0,0;Electric Alloy Furnace]"
+
+minetest.register_node(
+   "technic:alloy_furnace",
+   {
+      description = "Electric alloy furnace",
+      tiles = {"technic_alloy_furnace_top.png", "technic_machine_bottom.png", "technic_alloy_furnace_side.png",
+              "technic_alloy_furnace_side.png", "technic_alloy_furnace_side.png", "technic_alloy_furnace_front.png"},
+      paramtype2 = "facedir",
+      groups = {cracky=2},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_stone_defaults(),
+      on_construct = function(pos)
+                       local meta = minetest.env:get_meta(pos)
+                       meta:set_string("infotext", "Electric Alloy furnace")
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_string("formspec", alloy_furnace_formspec)
+                       local inv = meta:get_inventory()
+                       inv:set_size("src", 1)
+                       inv:set_size("src2", 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("src2") or not inv:is_empty("dst") then
+                     minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                     return false
+                  else
+                     return true
+                  end
+               end,
 })
 
-minetest.register_node("technic:alloy_furnace_active", {
-       description = "Alloy Furnace",
-       tiles = {"technic_alloy_furnace_top.png", "technic_machine_bottom.png", "technic_alloy_furnace_side.png",
-               "technic_alloy_furnace_side.png", "technic_alloy_furnace_side.png", "technic_alloy_furnace_front_active.png"},
-       paramtype2 = "facedir",
-       light_source = 8,
-       drop = "technic:alloy_furnace",
-       groups = {cracky=2,not_in_creative_inventory=1},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_stone_defaults(),
-       internal_EU_buffer=0;
-       interal_EU_buffer_size=2000;
-       technic_power_machine=1,
-       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_abm({
-       nodenames = {"technic:alloy_furnace","technic:alloy_furnace_active"},
-       interval = 1,
-       chance = 1,
-       
-       action = function(pos, node, active_object_count, active_object_count_wider)
-
-               local meta = minetest.env:get_meta(pos)
-               internal_EU_buffer=meta:get_float("internal_EU_buffer")
-               internal_EU_buffer_size=meta:get_float("internal_EU_buffer")
-               local load = math.floor(internal_EU_buffer/2000 * 100)
-               meta:set_string("formspec",
-                               "invsize[8,9;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                               (load)..":technic_power_meter_fg.png]"..
-                               "list[current_name;src;3,1;1,1;]"..
-                               "list[current_name;src2;3,2;1,1;]"..
-                               "list[current_name;dst;5,1;2,2;]"..
-                               "list[current_player;main;0,5;8,4;]"..
-                               "label[0,0;Electric Alloy Furnace]"..
-                               "label[1,3;Power level]")
-
-               local inv = meta:get_inventory()
-
-               local furnace_is_cookin = meta:get_int("furnace_is_cookin")
-
-               local srclist = inv:get_list("src")
-               local srclist2 = inv:get_list("src2")
-
-               srcstack = inv:get_stack("src", 1)
-               if srcstack then src_item1=srcstack:to_table() end
-               srcstack = inv:get_stack("src2", 1)
-               if srcstack then src_item2=srcstack:to_table() end
-               dst_index=nil
-
-               if src_item1 and src_item2 then 
-                               dst_index=get_cook_result(src_item1,src_item2) 
-                               end
-
-
-               if (furnace_is_cookin == 1) then
-                       if internal_EU_buffer>=150 then
-                       internal_EU_buffer=internal_EU_buffer-150;
-                       meta:set_float("internal_EU_buffer",internal_EU_buffer)
-                       meta:set_float("src_time", meta:get_float("src_time") + 1)
-                       if dst_index and meta:get_float("src_time") >= 4 then
-                               -- check if there's room for output in "dst" list
-                               dst_stack={}
-                               dst_stack["name"]=alloy_recipes[dst_index].dst_name
-                               dst_stack["count"]=alloy_recipes[dst_index].dst_count
-                               if inv:room_for_item("dst",dst_stack) then
-                                       -- Put result in "dst" list
-                                       inv:add_item("dst",dst_stack)
-                                       -- take stuff from "src" list
-                                       for i=1,alloy_recipes[dst_index].src1_count,1 do
-                                               srcstack = inv:get_stack("src", 1)
-                                               srcstack:take_item()
-                                               inv:set_stack("src", 1, srcstack)
-                                               end
-                                       for i=1,alloy_recipes[dst_index].src2_count,1 do
-                                               srcstack = inv:get_stack("src2", 1)
-                                               srcstack:take_item()
-                                               inv:set_stack("src2", 1, srcstack)
-                                               end
-
-
-                               else
-                                       print("Furnace inventory full!")
-                               end
-                               meta:set_string("src_time", 0)
-                       end
-                       end     
-               end
-
-               if dst_index and meta:get_int("furnace_is_cookin")==0 then
-                       hacky_swap_node(pos,"technic:alloy_furnace_active")
-                       meta:set_string("infotext","Electric Alloy Furnace active")
-                       meta:set_int("furnace_is_cookin",1)
-                       meta:set_string("src_time", 0)
-                       return
-                       end
-
-               if meta:get_int("furnace_is_cookin")==0 or dst_index==nil then
-                       hacky_swap_node(pos,"technic:alloy_furnace")
-                       meta:set_string("infotext","Electric Alloy Furnace inactive")
-                       meta:set_int("furnace_is_cookin",0)
-                       meta:set_string("src_time", 0)
-               end
-       
-end,           
-})
-
-function get_cook_result(src_item1, src_item2)
-local counter=registered_recipes_count-1
-for i=1, counter,1 do
-if     alloy_recipes[i].src1_name==src_item1["name"] and
-       alloy_recipes[i].src2_name==src_item2["name"] and
-       alloy_recipes[i].src1_count<=src_item1["count"] and
-       alloy_recipes[i].src2_count<=src_item2["count"] 
-       then return i end
-end
-return nil
-end
-
-register_LV_machine ("technic:alloy_furnace","RE")
-register_LV_machine ("technic:alloy_furnace_active","RE")
-
---coal driven alloy furnace:
-
+minetest.register_node(
+   "technic:alloy_furnace_active",
+   {
+      description = "Alloy Furnace",
+      tiles = {"technic_alloy_furnace_top.png", "technic_machine_bottom.png", "technic_alloy_furnace_side.png",
+              "technic_alloy_furnace_side.png", "technic_alloy_furnace_side.png", "technic_alloy_furnace_front_active.png"},
+      paramtype2 = "facedir",
+      light_source = 8,
+      drop = "technic:alloy_furnace",
+      groups = {cracky=2,not_in_creative_inventory=1},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_stone_defaults(),
+      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("src2") or not inv:is_empty("dst") then
+                     minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                     return false
+                  else
+                     return true
+                  end
+               end,
+   })
+
+minetest.register_abm(
+   { nodenames = {"technic:alloy_furnace","technic:alloy_furnace_active"},
+     interval = 1,
+     chance   = 1,
+     action = function(pos, node, active_object_count, active_object_count_wider)
+                local meta         = minetest.env:get_meta(pos)
+                local eu_input     = meta:get_int("LV_EU_input")
+                local state        = meta:get_int("state")
+                local next_state   = state
+
+                -- Machine information
+                local machine_name         = "Electric Alloy Furnace"
+                local machine_node         = "technic:alloy_furnace"
+                local machine_state_demand = { 50, 600 }
+
+                -- Setup meta data if it does not exist. state is used as an indicator of this
+                if state == 0 then
+                   meta:set_int("state", 1)
+                   meta:set_int("LV_EU_demand", machine_state_demand[1])
+                   meta:set_int("LV_EU_input", 0)
+                   meta:set_int("tube_time", 0)
+                   return
+                end
+                        
+                -- Power off automatically if no longer connected to a switching station
+                technic.switching_station_timeout_count(pos, "LV")
+                        
+                -- State machine
+                if eu_input == 0 then
+                   -- Unpowered - go idle
+                   hacky_swap_node(pos, machine_node)
+                   meta:set_string("infotext", machine_name.." Unpowered")
+                   next_state = 1
+                elseif eu_input == machine_state_demand[state] then
+                   -- Powered - do the state specific actions
+                           
+                   -- Execute always if powered logic
+                   local inv    = meta:get_inventory()
+                   local empty  = 1
+                   local recipe = nil
+                   local result = nil
+
+                   -- Get what to cook if anything
+                   local srcstack  = inv:get_stack("src", 1)
+                   local src2stack = inv:get_stack("src2", 1)
+                   local src_item1 = nil
+                   local src_item2 = nil
+                   if srcstack and src2stack then
+                      src_item1 = srcstack:to_table()
+                      src_item2 = src2stack:to_table()
+                      empty     = 0
+                   end
+              
+                   if src_item1 and src_item2 then
+                      recipe = technic.get_alloy_recipe(src_item1,src_item2)
+                   end
+                   if recipe then
+                      result = { name=recipe.dst_name, count=recipe.dst_count}
+                   end
+
+                   if recipe then
+                      print("recipe "..recipe.dst_name.." : result "..result.name.." : empty "..empty.." : src_item1 "..src_item1.name.." : src_item2 "..src_item2.name)
+                   end
+
+                   if state == 1 then
+                      hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Idle")
+                      
+                      if empty == 0 and recipe and inv:room_for_item("dst", result) then
+                         meta:set_string("infotext", machine_name.." Active")
+                         meta:set_string("src_time", 0)
+                         next_state = 2
+                      end
+
+                   elseif state == 2 then
+                      hacky_swap_node(pos, machine_node.."_active")
+                      meta:set_int("src_time", meta:get_int("src_time") + 1)
+                      if meta:get_int("src_time") == 4 then -- 4 ticks per output
+                         meta:set_string("src_time", 0)
+                         -- check if there's room for output in "dst" list and that we have the materials
+                         if recipe and inv:room_for_item("dst", result) then
+                            -- Take stuff from "src" list
+                            srcstack:take_item(recipe.src1_count)
+                            inv:set_stack("src", 1, srcstack)
+                            src2stack:take_item(recipe.src2_count)
+                            inv:set_stack("src2", 1, src2stack)
+                          -- Put result in "dst" list
+                            inv:add_item("dst",result)
+                         else
+                            next_state = 1
+                         end
+                      end
+                   end
+                   -- Change state?
+                   if next_state ~= state then
+                      meta:set_int("LV_EU_demand", machine_state_demand[next_state])
+                      meta:set_int("state", next_state)
+                   end
+                end
+             end,
+  })
+
+technic.register_LV_machine ("technic:alloy_furnace","RE")
+technic.register_LV_machine ("technic:alloy_furnace_active","RE")
+
+--------------------------------------------------
+-- coal driven alloy furnace. This uses no EUs:
+--------------------------------------------------
 coal_alloy_furnace_formspec =
        "size[8,9]"..
        "label[0,0;Alloy Furnace]"..
@@ -212,7 +199,7 @@ coal_alloy_furnace_formspec =
        "list[current_name;src2;3,1;1,1;]"..
        "list[current_name;dst;5,1;2,2;]"..
        "list[current_player;main;0,5;8,4;]"
-       
+
 minetest.register_node("technic:coal_alloy_furnace", {
        description = "Alloy Furnace",
        tiles = {"technic_coal_alloy_furnace_top.png", "technic_coal_alloy_furnace_bottom.png", "technic_coal_alloy_furnace_side.png",
@@ -230,9 +217,6 @@ minetest.register_node("technic:coal_alloy_furnace", {
                inv:set_size("src", 1)
                inv:set_size("src2", 1)
                inv:set_size("dst", 4)
-               local furnace_is_cookin = 0
-               local dst_index = nil
-
        end,
        can_dig = function(pos,player)
                local meta = minetest.env:get_meta(pos);
@@ -268,10 +252,10 @@ minetest.register_abm({
        nodenames = {"technic:coal_alloy_furnace","technic:coal_alloy_furnace_active"},
        interval = 1,
        chance = 1,
-       
+
        action = function(pos, node, active_object_count, active_object_count_wider)
                local meta = minetest.env:get_meta(pos)
-               for i, name in ipairs({
+               for i, name in pairs({
                                "fuel_totaltime",
                                "fuel_time",
                                "src_totaltime",
@@ -282,108 +266,101 @@ minetest.register_abm({
                        end
                end
 
-               local inv = meta:get_inventory()
+               local inv    = meta:get_inventory()
+               local recipe = nil
 
-               srcstack = inv:get_stack("src", 1)
+               -- Get what to cook if anything
+               local srcstack = inv:get_stack("src", 1)
                if srcstack then src_item1=srcstack:to_table() end
-               srcstack = inv:get_stack("src2", 1)
-               if srcstack then src_item2=srcstack:to_table() end
-               dst_index=nil
-
-               if src_item1 and src_item2 then 
-                               dst_index=get_cook_result(src_item1,src_item2) 
-                               end     
                
-               local was_active = false
+               local src2stack = inv:get_stack("src2", 1)
+               if src2stack then src_item2=src2stack:to_table() end
                
+               if src_item1 and src_item2 then
+                  recipe = technic.get_alloy_recipe(src_item1,src_item2)
+               end
+
+               local was_active = false
+
                if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
-                       was_active = true
-                       meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
-                       meta:set_float("src_time", meta:get_float("src_time") + 1)
-                       if dst_index and meta:get_float("src_time") >= 5 then
-                               -- check if there's room for output in "dst" list
-                               dst_stack={}
-                               dst_stack["name"]=alloy_recipes[dst_index].dst_name
-                               dst_stack["count"]=alloy_recipes[dst_index].dst_count                   
-                               if inv:room_for_item("dst",dst_stack) then
-                                       -- Put result in "dst" list
-                                       inv:add_item("dst", dst_stack)
-                                       -- take stuff from "src" list
-                                       for i=1,alloy_recipes[dst_index].src1_count,1 do
-                                               srcstack = inv:get_stack("src", 1)
-                                               srcstack:take_item()
-                                               inv:set_stack("src", 1, srcstack)
-                                               end
-                                       for i=1,alloy_recipes[dst_index].src2_count,1 do
-                                               srcstack = inv:get_stack("src2", 1)
-                                               srcstack:take_item()
-                                               inv:set_stack("src2", 1, srcstack)
-                                               end
-                               else
-                                       print("Furnace inventory full!")
-                               end
-                               meta:set_string("src_time", 0)
-                       end
+                  was_active = true
+                  meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
+                  meta:set_float("src_time", meta:get_float("src_time") + 1)
+                  if recipe and meta:get_float("src_time") == 6 then
+                     -- check if there's room for output in "dst" list
+                     local dst_stack = { name=recipe.dst_name, count=recipe.dst_count}
+                     if inv:room_for_item("dst",dst_stack) then
+                        -- Take stuff from "src" list
+                        srcstack:take_item(recipe.src1_count)
+                        inv:set_stack("src", 1, srcstack)
+                        src2stack:take_item(recipe.src2_count)
+                        inv:set_stack("src2", 1, src2stack)
+                        -- Put result in "dst" list
+                        inv:add_item("dst",dst_stack)
+                     else
+                        print("Furnace inventory full!") -- Silly code...
+                     end
+                     meta:set_string("src_time", 0)
+                  end
                end
                
                if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
-                       local percent = math.floor(meta:get_float("fuel_time") /
-                                       meta:get_float("fuel_totaltime") * 100)
-                       meta:set_string("infotext","Furnace active: "..percent.."%")
-                       hacky_swap_node(pos,"technic:coal_alloy_furnace_active")
-                       meta:set_string("formspec",
-                               "size[8,9]"..
-                               "label[0,0;Electric Alloy Furnace]"..
-                               "image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:"..
-                                               (100-percent)..":default_furnace_fire_fg.png]"..
-                               "list[current_name;fuel;2,3;1,1;]"..
-                               "list[current_name;src;2,1;1,1;]"..
-                               "list[current_name;src2;3,1;1,1;]"..
-                               "list[current_name;dst;5,1;2,2;]"..
-                               "list[current_player;main;0,5;8,4;]")
-                       return
+                  local percent = math.floor(meta:get_float("fuel_time") /
+                                          meta:get_float("fuel_totaltime") * 100)
+                  meta:set_string("infotext","Furnace active: "..percent.."%")
+                  hacky_swap_node(pos,"technic:coal_alloy_furnace_active")
+                  meta:set_string("formspec",
+                                  "size[8,9]"..
+                                     "label[0,0;Electric Alloy Furnace]"..
+                                     "image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:"..
+                                     (100-percent)..":default_furnace_fire_fg.png]"..
+                                  "list[current_name;fuel;2,3;1,1;]"..
+                                  "list[current_name;src;2,1;1,1;]"..
+                                  "list[current_name;src2;3,1;1,1;]"..
+                                  "list[current_name;dst;5,1;2,2;]"..
+                                  "list[current_player;main;0,5;8,4;]")
+                  return
                end
 
-               local fuel = nil
-               local fuellist = inv:get_list("fuel")
-               
+               -- FIXME: Make this look more like the electrical version.
+               -- This code refetches the recipe to see if it can be done again after the iteration
                srcstack = inv:get_stack("src", 1)
                if srcstack then src_item1=srcstack:to_table() end
                srcstack = inv:get_stack("src2", 1)
                if srcstack then src_item2=srcstack:to_table() end
-               dst_index=nil
+               if src_item1 and src_item2 then
+                  recipe = technic.get_alloy_recipe(src_item1,src_item2)
+               end
 
-               if src_item1 and src_item2 then 
-                               dst_index=get_cook_result(src_item1,src_item2) 
-                               end
-               
-               
-               if fuellist then
-                       fuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
+               if recipe==nil then
+                  if was_active then
+                     meta:set_string("infotext","Furnace is empty")
+                     hacky_swap_node(pos,"technic:coal_alloy_furnace")
+                     meta:set_string("formspec", coal_alloy_furnace_formspec)
+                  end
+                  return
                end
 
-               if fuel.time <= 0 then
-                       meta:set_string("infotext","Furnace out of fuel")
-                       hacky_swap_node(pos,"technic:coal_alloy_furnace")
-                       meta:set_string("formspec", coal_alloy_furnace_formspec)
-                       return
+               -- Next take a hard look at the fuel situation
+               local fuel = nil
+               local fuellist = inv:get_list("fuel")
+
+               if fuellist then
+                  fuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
                end
 
-               if dst_index==nil then
-                       if was_active then
-                               meta:set_string("infotext","Furnace is empty")
-                               hacky_swap_node(pos,"technic:coal_alloy_furnace")
-                               meta:set_string("formspec", coal_alloy_furnace_formspec)
-                       end
-                       return
+               if fuel.time <= 0 then
+                  meta:set_string("infotext","Furnace out of fuel")
+                  hacky_swap_node(pos,"technic:coal_alloy_furnace")
+                  meta:set_string("formspec", coal_alloy_furnace_formspec)
+                  return
                end
 
                meta:set_string("fuel_totaltime", fuel.time)
                meta:set_string("fuel_time", 0)
-               
+
                local stack = inv:get_stack("fuel", 1)
                stack:take_item()
                inv:set_stack("fuel", 1, stack)
-       
-end,           
-})
+            end,
+     })
index 1d78f6e6ec4a7070b262d4524863e840ec9b23dc..cadcb67b3048d39db15fe8ec5c8ffeab5110492a 100644 (file)
@@ -9,262 +9,451 @@ minetest.register_craft({
        }
 })
 
-MV_alloy_furnace_formspec =
+local mv_alloy_furnace_formspec =
        "invsize[8,10;]"..
        "label[0,0;MV Alloy Furnace]"..
-       "image[1,1;1,2;technic_power_meter_bg.png]"..
-       "label[1,2.8;Power level]"..
-       "list[current_name;src;3,1;1,2;]"..
+        "list[current_name;src;3,1;1,2;]"..
        "list[current_name;dst;5,1;2,2;]"..
        "list[current_player;main;0,6;8,4;]"..
        "list[current_name;upgrade1;1,4;1,1;]"..
        "list[current_name;upgrade2;2,4;1,1;]"..
        "label[1,5;Upgrade Slots]"
        
-minetest.register_node("technic:mv_alloy_furnace", {
-       description = "MV Alloy Furnace",
-       tiles = {"technic_mv_alloy_furnace_top.png", "technic_mv_alloy_furnace_bottom.png", "technic_mv_alloy_furnace_side_tube.png",
-               "technic_mv_alloy_furnace_side_tube.png", "technic_mv_alloy_furnace_side.png", "technic_mv_alloy_furnace_front.png"},
-       paramtype2 = "facedir",
-       groups = {cracky=2, tubedevice=1,tubedevice_receiver=1},
-       tube={insert_object=function(pos,node,stack,direction)
-                       local meta=minetest.env:get_meta(pos)
-                       local inv=meta:get_inventory()
-                               return inv:add_item("src",stack)
-               end,
-               can_insert=function(pos,node,stack,direction)
+minetest.register_node(
+   "technic:mv_alloy_furnace",
+   {description = "MV Alloy Furnace",
+    tiles = {"technic_mv_alloy_furnace_top.png", "technic_mv_alloy_furnace_bottom.png", "technic_mv_alloy_furnace_side_tube.png",
+            "technic_mv_alloy_furnace_side_tube.png", "technic_mv_alloy_furnace_side.png", "technic_mv_alloy_furnace_front.png"},
+    paramtype2 = "facedir",
+    groups = {cracky=2, tubedevice=1,tubedevice_receiver=1},
+    tube={insert_object=function(pos,node,stack,direction)
+                          local meta=minetest.env:get_meta(pos)
+                          local inv=meta:get_inventory()
+                          return inv:add_item("src",stack)
+                       end,
+         can_insert=function(pos,node,stack,direction)
                        local meta=minetest.env:get_meta(pos)
                        local inv=meta:get_inventory()
                        return inv:room_for_item("src",stack)
-               end,
-               },
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_stone_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       interal_EU_buffer_size=2000;
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_float("technic_power_machine", 1)
-               meta:set_string("formspec", mv_alloy_furnace_formspec)
-               meta:set_string("infotext", "MV Electric Alloy furnace")
-               local inv = meta:get_inventory()
-               inv:set_size("src", 2)
-               inv:set_size("dst", 4)
-               inv:set_size("upgrade1", 1)
-               inv:set_size("upgrade2", 1)
-               local EU_used  = 0
-               local furnace_is_cookin = 0
-               local cooked = nil
-               meta:set_float("internal_EU_buffer",0)
-               meta:set_float("internal_EU_buffer_size",2000)
-
-       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 end
-               if not inv:is_empty("src") then
-                       return false end
-               if not inv:is_empty("upgrade1") then
-                       return false end
-               if not inv:is_empty("upgrade2") then
-                       return false end
-               return true
-       end,
+                    end,
+       },
+    legacy_facedir_simple = true,
+    sounds = default.node_sound_stone_defaults(),
+    on_construct = function(pos)
+                     local meta = minetest.env:get_meta(pos)
+                     meta:set_string("infotext", "MV Alloy furnace")
+                     meta:set_float("technic_mv_power_machine", 1)
+                     meta:set_int("tube_time",  0)
+                     meta:set_string("formspec", mv_alloy_furnace_formspec)
+                     local inv = meta:get_inventory()
+                     inv:set_size("src", 2)
+                     inv:set_size("dst", 4)
+                     inv:set_size("upgrade1", 1)
+                     inv:set_size("upgrade2", 1)
+                  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") or not inv:is_empty("upgrade1") or not inv:is_empty("upgrade2") then
+                   minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                   return false
+                else
+                   return true
+                end
+             end,
 })
 
-minetest.register_node("technic:mv_alloy_furnace_active", {
-       description = "MV Alloy Furnace",
-       tiles = {"technic_mv_alloy_furnace_top.png", "technic_mv_alloy_furnace_bottom.png", "technic_mv_alloy_furnace_side_tube.png",
-               "technic_mv_alloy_furnace_side_tube.png", "technic_mv_alloy_furnace_side.png", "technic_mv_alloy_furnace_front_active.png"},
-       paramtype2 = "facedir",
-       light_source = 8,
-       drop = "technic:mv_alloy_furnace",
-       groups = {cracky=2, tubedevice=1,tubedevice_receiver=1,not_in_creative_inventory=1},
-       tube={insert_object=function(pos,node,stack,direction)
-                       local meta=minetest.env:get_meta(pos)
-                       local inv=meta:get_inventory()
-                               return inv:add_item("src",stack)
-               end,
-               can_insert=function(pos,node,stack,direction)
+minetest.register_node(
+   "technic:mv_alloy_furnace_active",
+   {description = "MV Alloy Furnace",
+    tiles = {"technic_mv_alloy_furnace_top.png", "technic_mv_alloy_furnace_bottom.png", "technic_mv_alloy_furnace_side_tube.png",
+            "technic_mv_alloy_furnace_side_tube.png", "technic_mv_alloy_furnace_side.png", "technic_mv_alloy_furnace_front_active.png"},
+    paramtype2 = "facedir",
+    light_source = 8,
+    drop = "technic:mv_alloy_furnace",
+    groups = {cracky=2, tubedevice=1,tubedevice_receiver=1,not_in_creative_inventory=1},
+    tube={insert_object=function(pos,node,stack,direction)
+                          local meta=minetest.env:get_meta(pos)
+                          local inv=meta:get_inventory()
+                          return inv:add_item("src",stack)
+                       end,
+         can_insert=function(pos,node,stack,direction)
                        local meta=minetest.env:get_meta(pos)
                        local inv=meta:get_inventory()
                        return inv:room_for_item("src",stack)
-               end,
-               },
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_stone_defaults(),
-       internal_EU_buffer=0;
-       interal_EU_buffer_size=2000;
-       technic_power_machine=1,
-       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 end
-               if not inv:is_empty("src") then
-                       return false end
-               if not inv:is_empty("upgrade1") then
-                       return false end
-               if not inv:is_empty("upgrade2") then
-                       return false end
-               return true
-       end,
+                    end,
+       },
+    legacy_facedir_simple = true,
+    sounds = default.node_sound_stone_defaults(),
+    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") or not inv:is_empty("upgrade1") or not inv:is_empty("upgrade2") then
+                   minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                   return false
+                else
+                   return true
+                end
+             end,
+    -- These three makes sure upgrades are not moved in or out while the furnace is active.
+    allow_metadata_inventory_put = function(pos, listname, index, stack, player)
+                                      if listname == "src" or listname == "dst" then
+                                         return 99
+                                      else
+                                         return 0 -- Disallow the move
+                                      end
+                                  end,
+    allow_metadata_inventory_take = function(pos, listname, index, stack, player)
+                                      if listname == "src" or listname == "dst" then
+                                         return 99
+                                      else
+                                         return 0 -- Disallow the move
+                                      end
+                                   end,
+    allow_metadata_inventory_move = function(pos, from_list, to_list, to_list, to_index, count, player)
+                                   return 0
+                                end,
 })
 
-minetest.register_abm({
-       nodenames = {"technic:mv_alloy_furnace","technic:mv_alloy_furnace_active"},
-       interval = 1,
-       chance = 1,
-
-       action = function(pos, node, active_object_count, active_object_count_wider)
-               local pos1={}
-               pos1.x=pos.x
-               pos1.y=pos.y
-               pos1.z=pos.z
-               local x_velocity=0
-               local z_velocity=0
-
-               -- output is on the left side of the furnace
-               if node.param2==3 then pos1.z=pos1.z-1 z_velocity =-1 end
-               if node.param2==2 then pos1.x=pos1.x-1 x_velocity =-1 end
-               if node.param2==1 then pos1.z=pos1.z+1 z_velocity = 1 end
-               if node.param2==0 then pos1.x=pos1.x+1 x_velocity = 1 end
-
-               local output_tube_connected = false
-               local meta=minetest.env:get_meta(pos1) 
-               if meta:get_int("tubelike")==1 then output_tube_connected=true end
-               meta = minetest.env:get_meta(pos)
-               local inv = meta:get_inventory()
-               local upg_item1
-               local upg_item1_name=""
-               local upg_item2
-               local upg_item2_name=""
-               local srcstack = inv:get_stack("upgrade1", 1)
-               if srcstack then upg_item1=srcstack:to_table() end
-               srcstack = inv:get_stack("upgrade2", 1)
-               if srcstack then upg_item2=srcstack:to_table() end
-               if upg_item1 then upg_item1_name=upg_item1.name end
-               if upg_item2 then upg_item2_name=upg_item2.name end
-
-               local speed=0
-               if upg_item1_name=="technic:control_logic_unit" then speed=speed+1 end
-               if upg_item2_name=="technic:control_logic_unit" then speed=speed+1 end
-               tube_time=meta:get_float("tube_time")
-               tube_time=tube_time+speed
-               if tube_time>3 then 
-                       tube_time=0
-                       if output_tube_connected then send_cooked_alloys(pos,x_velocity,z_velocity) end
-               end
-               meta:set_float("tube_time", tube_time)
+local send_cooked_items = function(pos,x_velocity,z_velocity)
+                            -- Send items on their way in the pipe system.
+                            local meta=minetest.env:get_meta(pos) 
+                            local inv = meta:get_inventory()
+                            local i=0
+                            for _,stack in ipairs(inv:get_list("dst")) do
+                               i=i+1
+                               if stack then
+                                  local item0=stack:to_table()
+                               if item0 then 
+                                  item0["count"]="1"
+                                  local item1=tube_item({x=pos.x,y=pos.y,z=pos.z},item0)
+                                  item1:get_luaentity().start_pos = {x=pos.x,y=pos.y,z=pos.z}
+                                  item1:setvelocity({x=x_velocity, y=0, z=z_velocity})
+                                  item1:setacceleration({x=0, y=0, z=0})
+                                  stack:take_item(1);
+                                  inv:set_stack("dst", i, stack)
+                                  return
+                               end
+                            end
+                         end
+                      end
 
-               local extra_buffer_size = 0
-               if upg_item1_name=="technic:battery" then extra_buffer_size =extra_buffer_size + 10000 end
-               if upg_item2_name=="technic:battery" then extra_buffer_size =extra_buffer_size + 10000 end
-               local internal_EU_buffer_size=2000+extra_buffer_size
-               meta:set_float("internal_EU_buffer_size",internal_EU_buffer_size)
+local smelt_item = function(pos)
+                     local meta=minetest.env:get_meta(pos) 
+                     local inv = meta:get_inventory()
+                     meta:set_int("src_time", meta:get_int("src_time") + 3) -- Cooking time 3x faster
+                     local result = minetest.get_craft_result({method = "cooking", width = 1, items = inv:get_list("src")})
+                     dst_stack={}
+                     dst_stack["name"]=alloy_recipes[dst_index].dst_name
+                     dst_stack["count"]=alloy_recipes[dst_index].dst_count
 
-               internal_EU_buffer=meta:get_float("internal_EU_buffer")
-               if internal_EU_buffer > internal_EU_buffer_size then internal_EU_buffer = internal_EU_buffer_size end
-               local meta = minetest.env:get_meta(pos)
-               local load = math.floor(internal_EU_buffer/internal_EU_buffer_size * 100)
-               meta:set_string("formspec",
-                               MV_alloy_furnace_formspec..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                               (load)..":technic_power_meter_fg.png]")
+                     if result and result.item and meta:get_int("src_time") >= result.time then
+                        meta:set_int("src_time", 0)
+                        -- check if there's room for output in "dst" list
+                        if inv:room_for_item("dst",result) then
+                           -- take stuff from "src" list
+                           srcstack = inv:get_stack("src", 1)
+                           srcstack:take_item()
+                           inv:set_stack("src", 1, srcstack)
+                           -- Put result in "dst" list
+                           inv:add_item("dst", result.item)
+                           return 1
+                        else
+                           return 0 -- done
+                        end
+                     end
+                     return 0 -- done
+                  end
 
-               local inv = meta:get_inventory()
+minetest.register_abm(
+   {nodenames = {"technic:mv_alloy_furnace","technic:mv_alloy_furnace_active"},
+    interval = 1,
+    chance = 1,
 
-               local furnace_is_cookin = meta:get_int("furnace_is_cookin")
+    action = function(pos, node, active_object_count, active_object_count_wider)
+               local meta         = minetest.env:get_meta(pos)
+               local eu_input     = meta:get_int("MV_EU_input")
+               local state        = meta:get_int("state")
+               local next_state   = state
 
-               local srclist = inv:get_list("src")
-               local srclist2 = inv:get_list("src2")
+               -- Machine information
+               local machine_name         = "MV Alloy Furnace"
+               local machine_node         = "technic:mv_alloy_furnace"
+               local machine_state_demand = { 50, 2000, 1500, 1000 }
                
-               srcstack = inv:get_stack("src", 1)
-               if srcstack then src_item1=srcstack:to_table() end
-               srcstack = inv:get_stack("src", 2)
-               if srcstack then src_item2=srcstack:to_table() end
-               dst_index=nil
-
-               if src_item1 and src_item2 then 
-                               dst_index=get_cook_result(src_item1,src_item2) 
-                               end
+               -- Setup meta data if it does not exist. state is used as an indicator of this
+               if state == 0 then
+                  meta:set_int("state", 1)
+                  meta:set_int("MV_EU_demand", machine_state_demand[1])
+                  meta:set_int("MV_EU_input", 0)
+                  return
+               end
+               
+               -- Power off automatically if no longer connected to a switching station
+               technic.switching_station_timeout_count(pos, "MV")
+               
+               -- Execute always logic
+               -- CODE HERE --
 
+               -- State machine
+               if eu_input == 0 then
+                  -- Unpowered - go idle
+                  hacky_swap_node(pos, machine_node)
+                  meta:set_string("infotext", machine_name.." Unpowered")
+                  next_state = 1
+               elseif eu_input == machine_state_demand[state] then
+                  -- Powered - do the state specific actions
+                  
+                  -- Execute always if powered logic
+                  local meta=minetest.env:get_meta(pos) 
+                  
+                  -- Get the names of the upgrades
+                  local meta=minetest.env:get_meta(pos) 
+                  local inv = meta:get_inventory()
+                  local upg_item1
+                  local upg_item1_name=""
+                  local upg_item2
+                  local upg_item2_name=""
+                  local srcstack = inv:get_stack("upgrade1", 1)
+                  if  srcstack then upg_item1=srcstack:to_table() end
+                  srcstack = inv:get_stack("upgrade2", 1)
+                  if  srcstack then upg_item2=srcstack:to_table() end
+                  if upg_item1 then upg_item1_name=upg_item1.name end
+                  if upg_item2 then upg_item2_name=upg_item2.name end
+                  
+                  -- Save some power by installing battery upgrades. Fully upgraded makes this
+                  -- furnace use the same amount of power as the LV version
+                  local EU_saving_upgrade = 0
+                  if upg_item1_name=="technic:battery" then EU_saving_upgrade = EU_saving_upgrade + 1 end
+                  if upg_item2_name=="technic:battery" then EU_saving_upgrade = EU_saving_upgrade + 1 end
+                  
+                  -- Tube loading speed can be upgraded using control logic units
+                  local tube_speed_upgrade = 0
+                  if upg_item1_name=="technic:control_logic_unit" then tube_speed_upgrade = tube_speed_upgrade + 1 end
+                  if upg_item2_name=="technic:control_logic_unit" then tube_speed_upgrade = tube_speed_upgrade + 1 end
+                  
+                  -- Handle pipeworks (consumes tube_speed_upgrade)
+                  local pos1={x=pos.x, y=pos.y, z=pos.z}
+                  local x_velocity=0
+                  local z_velocity=0
+                  
+                  -- Output is on the left side of the furnace
+                  if node.param2==3 then pos1.z=pos1.z-1 z_velocity =-1 end
+                  if node.param2==2 then pos1.x=pos1.x-1 x_velocity =-1 end
+                  if node.param2==1 then pos1.z=pos1.z+1 z_velocity = 1 end
+                  if node.param2==0 then pos1.x=pos1.x+1 x_velocity = 1 end
+                  
+                  local output_tube_connected = false
+                  local meta1 = minetest.env:get_meta(pos1) 
+                  if meta1:get_int("tubelike") == 1 then
+                     output_tube_connected=true
+                  end
+                  tube_time = meta:get_int("tube_time")
+                  tube_time = tube_time + tube_speed_upgrade
+                  if tube_time > 3 then
+                     tube_time = 0
+                     if output_tube_connected then
+                        send_cooked_items(pos,x_velocity,z_velocity)
+                     end
+                  end
+                  meta:set_int("tube_time", tube_time)
 
-               if (furnace_is_cookin == 1) then
-                       if internal_EU_buffer>=150 then
-                       internal_EU_buffer=internal_EU_buffer-150;
-                       meta:set_float("internal_EU_buffer",internal_EU_buffer)
-                       meta:set_float("src_time", meta:get_float("src_time") + 1)
-                       if dst_index and meta:get_float("src_time") >= 4 then
-                               -- check if there's room for output in "dst" list
-                               dst_stack={}
-                               dst_stack["name"]=alloy_recipes[dst_index].dst_name
-                               dst_stack["count"]=alloy_recipes[dst_index].dst_count
-                               if inv:room_for_item("dst",dst_stack) then
-                                       -- Put result in "dst" list
-                                       inv:add_item("dst",dst_stack)
-                                       -- take stuff from "src" list
-                                       for i=1,alloy_recipes[dst_index].src1_count,1 do
-                                               srcstack = inv:get_stack("src", 1)
-                                               srcstack:take_item()
-                                               inv:set_stack("src", 1, srcstack)
-                                               end
-                                       for i=1,alloy_recipes[dst_index].src2_count,1 do
-                                               srcstack = inv:get_stack("src", 2)
-                                               srcstack:take_item()
-                                               inv:set_stack("src", 2, srcstack)
-                                               end
+                  -- The machine shuts down if we have nothing to smelt and no tube is connected
+                  -- or if we have nothing to send with a tube connected.
+                  if    (not output_tube_connected and inv:is_empty("src"))
+                     or (    output_tube_connected and inv:is_empty("dst")) then
+                     next_state = 1
+                  end
+                  ----------------------
+                  local empty  = 1
+                  local recipe = nil
+                  local result = nil
 
-                               else
-                                       print("Furnace inventory full!")
-                               end
-                               meta:set_string("src_time", 0)
-                       end
-                       end
+                  -- Get what to cook if anything
+                  local srcstack  = inv:get_stack("src", 1)
+                  local src2stack = inv:get_stack("src", 2)
+                  local src_item1 = nil
+                  local src_item2 = nil
+                  if srcstack and src2stack then
+                     src_item1 = srcstack:to_table()
+                     src_item2 = src2stack:to_table()
+                     empty     = 0
+                  end
+                  
+                  if src_item1 and src_item2 then
+                     recipe = technic.get_alloy_recipe(src_item1,src_item2)
+                  end
+                  if recipe then
+                     result = { name=recipe.dst_name, count=recipe.dst_count}
+                  end
+                  
+                  if state == 1 then
+                     hacky_swap_node(pos, machine_node)
+                     meta:set_string("infotext", machine_name.." Idle")
+                     
+                     local meta=minetest.env:get_meta(pos) 
+                     local inv = meta:get_inventory()
+                     if not inv:is_empty("src") then
+                        if empty == 0 and recipe and inv:room_for_item("dst", result) then
+                           meta:set_string("infotext", machine_name.." Active")
+                           meta:set_int("src_time",     0)
+                           next_state = 2+EU_saving_upgrade -- Next state is decided by the battery upgrade (state 2= 0 batteries, state 3 = 1 battery, 4 = 2 batteries)
+                        end
+                     end
+                     
+                  elseif state == 2 or state == 3 or state == 4 then
+                     hacky_swap_node(pos, machine_node.."_active")
+                     meta:set_int("src_time", meta:get_int("src_time") + 1)
+                     if meta:get_int("src_time") == 4 then -- 4 ticks per output
+                        meta:set_string("src_time", 0)
+                        -- check if there's room for output in "dst" list and that we have the materials
+                        if recipe and inv:room_for_item("dst", result) then
+                           -- Take stuff from "src" list
+                           srcstack:take_item(recipe.src1_count)
+                           inv:set_stack("src", 1, srcstack)
+                           src2stack:take_item(recipe.src2_count)
+                           inv:set_stack("src2", 1, src2stack)
+                           -- Put result in "dst" list
+                           inv:add_item("dst",result)
+                        else
+                           next_state = 1
+                        end
+                     end
+                  end
+               end
+               -- Change state?
+               if next_state ~= state then
+                  meta:set_int("MV_EU_demand", machine_state_demand[next_state])
+                  meta:set_int("state", next_state)
                end
 
-               if dst_index and meta:get_int("furnace_is_cookin")==0 then
-                       hacky_swap_node(pos,"technic:mv_alloy_furnace_active")
-                       meta:set_string("infotext","MV Alloy Furnace active")
-                       meta:set_int("furnace_is_cookin",1)
-                       meta:set_string("src_time", 0)
-                       return
-                       end
 
-               if meta:get_int("furnace_is_cookin")==0 or dst_index==nil then
-                       hacky_swap_node(pos,"technic:mv_alloy_furnace")
-                       meta:set_string("infotext","MV Alloy Furnace inactive")
-                       meta:set_int("furnace_is_cookin",0)
-                       meta:set_string("src_time", 0)
-               end
 
-end,
-})
+            ------------------------------------
 
-function send_cooked_alloys (pos,x_velocity,z_velocity)
-               local meta=minetest.env:get_meta(pos) 
-               local inv = meta:get_inventory()
-               local i=0
-               for _,stack in ipairs(inv:get_list("dst")) do
-               i=i+1
-                       if stack then
-                       local item0=stack:to_table()
-                       if item0 then 
-                               item0["count"]="1"
-                               local item1=tube_item({x=pos.x,y=pos.y,z=pos.z},item0)
-                               item1:get_luaentity().start_pos = {x=pos.x,y=pos.y,z=pos.z}
-                               item1:setvelocity({x=x_velocity, y=0, z=z_velocity})
-                               item1:setacceleration({x=0, y=0, z=0})
-                               stack:take_item(1);
-                               inv:set_stack("dst", i, stack)
-                               return
-                               end
-                       end
-               end
-end
+--          local pos1={}
+--          pos1.x=pos.x
+--          pos1.y=pos.y
+--          pos1.z=pos.z
+--          local x_velocity=0
+--          local z_velocity=0
+--
+--          -- output is on the left side of the furnace
+--          if node.param2==3 then pos1.z=pos1.z-1 z_velocity =-1 end
+--          if node.param2==2 then pos1.x=pos1.x-1 x_velocity =-1 end
+--          if node.param2==1 then pos1.z=pos1.z+1 z_velocity = 1 end
+--          if node.param2==0 then pos1.x=pos1.x+1 x_velocity = 1 end
+--
+--          local output_tube_connected = false
+--          local meta=minetest.env:get_meta(pos1) 
+--          if meta:get_int("tubelike")==1 then output_tube_connected=true end
+--          meta = minetest.env:get_meta(pos)
+--          local inv = meta:get_inventory()
+--          local upg_item1
+--          local upg_item1_name=""
+--          local upg_item2
+--          local upg_item2_name=""
+--          local srcstack = inv:get_stack("upgrade1", 1)
+--          if srcstack then upg_item1=srcstack:to_table() end
+--          srcstack = inv:get_stack("upgrade2", 1)
+--          if srcstack then upg_item2=srcstack:to_table() end
+--          if upg_item1 then upg_item1_name=upg_item1.name end
+--          if upg_item2 then upg_item2_name=upg_item2.name end
+--
+--          local speed=0
+--          if upg_item1_name=="technic:control_logic_unit" then speed=speed+1 end
+--          if upg_item2_name=="technic:control_logic_unit" then speed=speed+1 end
+--          tube_time=meta:get_float("tube_time")
+--          tube_time=tube_time+speed
+--          if tube_time>3 then 
+--             tube_time=0
+--             if output_tube_connected then send_cooked_items(pos,x_velocity,z_velocity) end
+--          end
+--          meta:set_float("tube_time", tube_time)
+--
+--          local extra_buffer_size = 0
+--          if upg_item1_name=="technic:battery" then extra_buffer_size =extra_buffer_size + 10000 end
+--          if upg_item2_name=="technic:battery" then extra_buffer_size =extra_buffer_size + 10000 end
+--          local internal_EU_buffer_size=2000+extra_buffer_size
+--          meta:set_float("internal_EU_buffer_size",internal_EU_buffer_size)
+--
+--          internal_EU_buffer=meta:get_float("internal_EU_buffer")
+--          if internal_EU_buffer > internal_EU_buffer_size then internal_EU_buffer = internal_EU_buffer_size end
+--          local meta = minetest.env:get_meta(pos)
+--          local load = math.floor(internal_EU_buffer/internal_EU_buffer_size * 100)
+--          meta:set_string("formspec",
+--                          MV_alloy_furnace_formspec..
+--                             "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
+--                             (load)..":technic_power_meter_fg.png]")
+--
+--          local inv = meta:get_inventory()
+--
+--          local furnace_is_cookin = meta:get_int("furnace_is_cookin")
+--
+--          local srclist = inv:get_list("src")
+--          local srclist2 = inv:get_list("src2")
+--          
+--          srcstack = inv:get_stack("src", 1)
+--          if srcstack then src_item1=srcstack:to_table() end
+--          srcstack = inv:get_stack("src", 2)
+--          if srcstack then src_item2=srcstack:to_table() end
+--          dst_index=nil
+--
+--          if src_item1 and src_item2 then 
+--             dst_index=get_cook_result(src_item1,src_item2) 
+--          end
+--
+--
+--          if (furnace_is_cookin == 1) then
+--             if internal_EU_buffer>=150 then
+--                internal_EU_buffer=internal_EU_buffer-150;
+--                meta:set_float("internal_EU_buffer",internal_EU_buffer)
+--                meta:set_float("src_time", meta:get_float("src_time") + 1)
+--                if dst_index and meta:get_float("src_time") >= 4 then
+--                   -- check if there's room for output in "dst" list
+--                   dst_stack={}
+--                   dst_stack["name"]=alloy_recipes[dst_index].dst_name
+--                   dst_stack["count"]=alloy_recipes[dst_index].dst_count
+--                   if inv:room_for_item("dst",dst_stack) then
+--                      -- Put result in "dst" list
+--                      inv:add_item("dst",dst_stack)
+--                      -- take stuff from "src" list
+--                      for i=1,alloy_recipes[dst_index].src1_count,1 do
+--                         srcstack = inv:get_stack("src", 1)
+--                         srcstack:take_item()
+--                         inv:set_stack("src", 1, srcstack)
+--                      end
+--                      for i=1,alloy_recipes[dst_index].src2_count,1 do
+--                         srcstack = inv:get_stack("src", 2)
+--                         srcstack:take_item()
+--                         inv:set_stack("src", 2, srcstack)
+--                      end
+--
+--                   else
+--                      print("Furnace inventory full!")
+--                   end
+--                   meta:set_string("src_time", 0)
+--                end
+--             end
+--          end
+--
+--          if dst_index and meta:get_int("furnace_is_cookin")==0 then
+--             hacky_swap_node(pos,"technic:mv_alloy_furnace_active")
+--             meta:set_string("infotext","MV Alloy Furnace active")
+--             meta:set_int("furnace_is_cookin",1)
+--             meta:set_string("src_time", 0)
+--             return
+--          end
+--
+--          if meta:get_int("furnace_is_cookin")==0 or dst_index==nil then
+--             hacky_swap_node(pos,"technic:mv_alloy_furnace")
+--             meta:set_string("infotext","MV Alloy Furnace inactive")
+--             meta:set_int("furnace_is_cookin",0)
+--             meta:set_string("src_time", 0)
+--          end
+--
+         end,
+ })
 
-register_MV_machine ("technic:mv_alloy_furnace","RE")
-register_MV_machine ("technic:mv_alloy_furnace_active","RE")
+technic.register_MV_machine ("technic:mv_alloy_furnace","RE")
+technic.register_MV_machine ("technic:mv_alloy_furnace_active","RE")
index 9c9c42a97cfd90f35c24222a9b101834d4c006cc..5a6e65b4234273e878f29b603c4a0b1b7592e747 100644 (file)
@@ -1,32 +1,77 @@
-alloy_recipes ={}
+-- Register alloy recipes
+technic.alloy_recipes = {}
 
-registered_recipes_count=1
+-- Register recipe in a table
+technic.register_alloy_recipe = function(metal1, count1, metal2, count2, result, count3)
+                                  technic.alloy_recipes[metal1..metal2] = { src1_count = count1, src2_count = count2, dst_name = result, dst_count = count3 }
+                                  if unified_inventory then
+                                     unified_inventory.register_craft(
+                                        {
+                                           type = "alloy",
+                                           output = result.." "..count3,
+                                           items = {metal1.." "..count1,metal2.." "..count2},
+                                           width = 2,
+                                        })
+                                  end
+                               end
+
+-- Retrieve a recipe given the input metals.
+-- Input parameters are a table from a StackItem
+technic.get_alloy_recipe = function(metal1, metal2)
+                             -- Check for both combinations of metals and for the right amount in both
+                             if technic.alloy_recipes[metal1.name..metal2.name]
+                                and metal1.count >= technic.alloy_recipes[metal1.name..metal2.name].src1_count
+                                and metal2.count >= technic.alloy_recipes[metal1.name..metal2.name].src2_count then
+                                return technic.alloy_recipes[metal1.name..metal2.name]
+                             elseif technic.alloy_recipes[metal2.name..metal1.name]
+                                and metal2.count >= technic.alloy_recipes[metal2.name..metal1.name].src1_count
+                                and metal1.count >= technic.alloy_recipes[metal2.name..metal1.name].src2_count then
+                                return technic.alloy_recipes[metal2.name..metal1.name]
+                             else
+                                return nil
+                             end
+                          end
+
+technic.register_alloy_recipe("technic:copper_dust",  3, "technic:tin_dust",      1, "technic:bronze_dust",          4)
+technic.register_alloy_recipe("moreores:copper_ingot",3, "moreores:tin_ingot",    1, "moreores:bronze_ingot",        4)
+technic.register_alloy_recipe("technic:iron_dust",    3, "technic:chromium_dust", 1, "technic:stainless_steel_dust", 4)
+technic.register_alloy_recipe("default:steel_ingot",  3, "technic:chromium_ingot",1, "technic:stainless_steel_ingot",4)
+technic.register_alloy_recipe("technic:copper_dust",  2, "technic:zinc_dust",     1, "technic:brass_dust",           3)
+technic.register_alloy_recipe("moreores:copper_ingot",2, "technic:zinc_ingot",    1, "technic:brass_ingot",          3)
+technic.register_alloy_recipe("default:sand",         2, "technic:coal_dust",     2, "technic:silicon_wafer",        1)
+technic.register_alloy_recipe("technic:silicon_wafer",1, "technic:gold_dust",     1, "technic:doped_silicon_wafer",  1)
+
+--------------------------------------
+-- LEGACY CODE - some other mods might depend on this - Register the same recipes as above...
+--------------------------------------
+alloy_recipes = {}
+registered_recipes_count = 1
 
 function register_alloy_recipe (string1,count1, string2,count2, string3,count3)
-alloy_recipes[registered_recipes_count]={}
-alloy_recipes[registered_recipes_count].src1_name=string1
-alloy_recipes[registered_recipes_count].src1_count=count1
-alloy_recipes[registered_recipes_count].src2_name=string2
-alloy_recipes[registered_recipes_count].src2_count=count2
-alloy_recipes[registered_recipes_count].dst_name=string3
-alloy_recipes[registered_recipes_count].dst_count=count3
-registered_recipes_count=registered_recipes_count+1
-alloy_recipes[registered_recipes_count]={}
-alloy_recipes[registered_recipes_count].src1_name=string2
-alloy_recipes[registered_recipes_count].src1_count=count2
-alloy_recipes[registered_recipes_count].src2_name=string1
-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 unified_inventory then
-       unified_inventory.register_craft({
-       type = "alloy",
-       output = string3.." "..count3,
-       items = {string1.." "..count1,string2.." "..count2},
-       width = 2,
-       })
-       end
+   alloy_recipes[registered_recipes_count]={}
+   alloy_recipes[registered_recipes_count].src1_name=string1
+   alloy_recipes[registered_recipes_count].src1_count=count1
+   alloy_recipes[registered_recipes_count].src2_name=string2
+   alloy_recipes[registered_recipes_count].src2_count=count2
+   alloy_recipes[registered_recipes_count].dst_name=string3
+   alloy_recipes[registered_recipes_count].dst_count=count3
+   registered_recipes_count=registered_recipes_count+1
+   alloy_recipes[registered_recipes_count]={}
+   alloy_recipes[registered_recipes_count].src1_name=string2
+   alloy_recipes[registered_recipes_count].src1_count=count2
+   alloy_recipes[registered_recipes_count].src2_name=string1
+   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 unified_inventory then
+      unified_inventory.register_craft({
+                                         type = "alloy",
+                                         output = string3.." "..count3,
+                                         items = {string1.." "..count1,string2.." "..count2},
+                                         width = 2,
+                                      })
+   end
 end
 
 register_alloy_recipe ("technic:copper_dust",3, "technic:tin_dust",1, "technic:bronze_dust",4)
index 572605336f3d55db20c95d938d2e81e48f86c8e3..1f0740d847b67772755b613d5f232e6e488aa351 100644 (file)
@@ -1,23 +1,8 @@
--- 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
-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)
+-- LV Battery box and some other nodes...
+technic.register_LV_power_tool("technic:battery",10000)
+technic.register_MV_power_tool("technic:red_energy_crystal",100000)
+technic.register_HV_power_tool("technic:green_energy_crystal",250000)
+technic.register_HV_power_tool("technic:blue_energy_crystal",500000)
 
 minetest.register_craft({
                           output = 'technic:battery 1',
@@ -28,29 +13,32 @@ minetest.register_craft({
                           }
                        })
 
-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'},
-                          }
-                       })
-
-
 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}}}})
 
-minetest.register_craftitem("technic:battery_box", {
-                              description = "Battery box",
-                              stack_max = 99,
-                           })
-
+--------------------------------------------
+-- The Battery box
+--------------------------------------------
+minetest.register_craftitem(
+   "technic:battery_box",
+   {
+      description = "Battery box",
+      stack_max = 99,
+   })
 
+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'},
+      }
+   })
 
-battery_box_formspec =
+local battery_box_formspec =
    "invsize[8,9;]"..
    "image[1,1;1,2;technic_power_meter_bg.png]"..
    "list[current_name;src;3,1;1,1;]"..
@@ -71,28 +59,28 @@ minetest.register_node(
       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)
+                            meta:set_int("LV_EU_demand", 0) -- How much can this node charge
+                            meta:set_int("LV_EU_supply", 0) -- How much can this node discharge
+                            meta:set_int("LV_EU_input",  0) -- How much power is this machine getting.
+                            meta:set_float("internal_EU_charge", 0)
                             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,
+                  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(), "Machine cannot be removed because it is not empty");
+                     return false
+                  else
+                     return true
+                  end
+               end,
    })
 
 
@@ -105,51 +93,101 @@ for i=1,8,1 do
         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,
+                     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(), "Machine cannot be removed because it is not empty");
+                        return false
+                     else
+                        return true
+                     end
+                  end,
       })
 end
 
-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)
-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)
-end
+local power_tools = technic.LV_power_tools
+
+local charge_LV_tools = function(meta, charge)
+                    --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 toolname = src_item["name"]
+                       if power_tools[toolname] ~= nil then
+                          -- Set meta data for the tool if it didn't do it itself :-(
+                          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[toolname]
+                          local load            = src_meta["charge"]
+                          local load_step       = 1000 -- how much to charge per tick
+                          if load<item_max_charge and charge>0 then
+                             if charge-load_step<0 then load_step=charge end
+                             if load+load_step>item_max_charge then load_step=item_max_charge-load end
+                             load=load+load_step
+                             charge=charge-load_step
+                             technic.set_RE_wear(src_item,load,item_max_charge)
+                             src_meta["charge"]   = load
+                             src_item["metadata"] = set_item_meta(src_meta)
+                             inv:set_stack("src", 1, src_item)
+                          end
+                       end
+                    end
+                    return charge -- return the remaining charge in the battery
+                 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
-end
+local discharge_LV_tools = function(meta, charge, max_charge)
+                       -- discharging registered power tools
+                       local inv = meta:get_inventory()
+                       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 toolname = src_item["name"]
+                          if power_tools[toolname] ~= nil then
+                             -- Set meta data for the tool if it didn't do it itself :-(
+                             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 discharging
+                             local item_max_charge = power_tools[toolname]
+                             local load            = src_meta["charge"]
+                             local load_step       = 4000 -- how much to discharge per tick
+                             if load>0 and charge<max_charge then
+                                if charge+load_step>max_charge then load_step=max_charge-charge end
+                                if load-load_step<0 then load_step=load end
+                                load=load-load_step
+                                charge=charge+load_step
+                                technic.set_RE_wear(src_item,load,item_max_charge)
+                                src_meta["charge"]=load
+                                src_item["metadata"]=set_item_meta(src_meta)
+                                inv:set_stack("dst", 1, src_item)
+                             end
+                          end
+                       end
+                       return charge -- return the remaining charge in the battery
+                    end
 
 minetest.register_abm(
    {nodenames = {"technic:battery_box","technic:battery_box1","technic:battery_box2","technic:battery_box3","technic:battery_box4",
@@ -157,12 +195,39 @@ minetest.register_abm(
     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")
+               local meta               = minetest.env:get_meta(pos)
+               local max_charge         = 60000 -- Set maximum charge for the device here
+               local max_charge_rate    = 1000  -- Set maximum rate of charging
+               local max_discharge_rate = 2000  -- Set maximum rate of discharging
+               local eu_input           = meta:get_int("LV_EU_input")
+               local current_charge     = meta:get_int("internal_EU_charge") -- Battery charge right now
+
+               -- Power off automatically if no longer connected to a switching station
+               technic.switching_station_timeout_count(pos, "LV")
+
+               -- Charge/discharge the battery with the input EUs
+               if eu_input >=0 then
+                  current_charge = math.min(current_charge+eu_input, max_charge)
+               else
+                  current_charge = math.max(current_charge+eu_input, 0)
+               end
+
+               -- Charging/discharging tools here
+               current_charge = charge_LV_tools(meta, current_charge)
+               current_charge = discharge_LV_tools(meta, current_charge, max_charge)
+
+               -- Set a demand (we allow batteries to charge on less than the demand though)
+               meta:set_int("LV_EU_demand", math.min(max_charge_rate, max_charge-current_charge))
+               --print("BA:"..max_charge_rate.."|"..max_charge-current_charge.."|"..math.min(max_charge_rate, max_charge-current_charge))
+
+               -- Set how much we can supply
+               meta:set_int("LV_EU_supply", math.min(max_discharge_rate, current_charge))
+
+               meta:set_int("internal_EU_charge", current_charge)
+               --dprint("BA: input:"..eu_input.." supply="..meta:get_int("LV_EU_supply").." demand="..meta:get_int("LV_EU_demand").." current:"..current_charge)
 
                -- Select node textures
-               local i=math.ceil((charge/max_charge)*8)
+               local i=math.ceil((current_charge/max_charge)*8)
                if i > 8 then i = 8 end
                local j = meta:get_float("last_side_shown")
                if i~=j then
@@ -170,224 +235,26 @@ minetest.register_abm(
                   elseif i==0 then hacky_swap_node(pos,"technic: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"])
-                  
-                  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 load1<item_max_charge and charge>0 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 charge<max_charge then
-                           if charge+load_step>max_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)
+               local load = math.floor(current_charge/max_charge * 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]"
                             )
 
-               -- 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 charge<max_charge then
-                     if internal_EU_buffer-charge_to_take<=0 then
-                        charge_to_take=internal_EU_buffer
-                     end
-                     if charge_to_take>0 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
+               if eu_input == 0 then
+                  meta:set_string("infotext", "LV Battery box: "..current_charge.."/"..max_charge.." (idle)")
+               else
+                  meta:set_string("infotext", "LV Battery box: "..current_charge.."/"..max_charge)
                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")
+technic.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)
-   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,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,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
+   technic.register_LV_machine("technic:battery_box"..i,"BA")
 end
index 16aead992b243abbd2c38cc4e454e41eed5a6c4e..8cd0e2f8d0b05dddfc25ba058cbbdade14bff069 100644 (file)
@@ -1,10 +1,4 @@
--- 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
-
+-- HV battery box
 minetest.register_craft({
                           output = 'technic:hv_battery_box 1',
                           recipe = {
@@ -14,7 +8,7 @@ minetest.register_craft({
                           }
                        })
 
-hv_battery_box_formspec =
+local battery_box_formspec =
    "invsize[8,9;]"..
    "image[1,1;1,2;technic_power_meter_bg.png]"..
    "list[current_name;src;3,1;1,1;]"..
@@ -35,74 +29,176 @@ minetest.register_node(
       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)
+                       meta:set_int("HV_EU_demand", 0) -- How much can this node charge
+                       meta:set_int("HV_EU_supply", 0) -- How much can this node discharge
+                       meta:set_int("HV_EU_input",  0) -- How much power is this machine getting.
+                       meta:set_float("internal_EU_charge", 0)
                        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
+                  if not inv:is_empty("src") or not inv:is_empty("dst") then
+                     minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
                      return false
+                  else
+                     return true
                   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,
-      })
+      "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",
+       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(), "Machine cannot be removed because it is not empty");
+                      return false
+                   else
+                      return true
+                   end
+                end,
+    })
 end
 
+local power_tools = technic.HV_power_tools
+
+local charge_HV_tools = function(meta, charge)
+                    --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 toolname = src_item["name"]
+                       if power_tools[toolname] ~= nil then
+                          -- Set meta data for the tool if it didn't do it itself :-(
+                          src_meta=get_item_meta(src_item["metadata"])
+                          if src_meta==nil then
+                             src_meta={}
+                             src_meta["technic_hv_power_tool"]=true
+                             src_meta["charge"]=0
+                          else
+                             if src_meta["technic_hv_power_tool"]==nil then
+                                src_meta["technic_hv_power_tool"]=true
+                                src_meta["charge"]=0
+                             end
+                          end
+                          -- Do the charging
+                          local item_max_charge = power_tools[toolname]
+                          local load            = src_meta["charge"]
+                          local load_step       = 1000 -- how much to charge per tick
+                          if load<item_max_charge and charge>0 then
+                             if charge-load_step<0 then load_step=charge end
+                             if load+load_step>item_max_charge then load_step=item_max_charge-load end
+                             load=load+load_step
+                             charge=charge-load_step
+                             technic.set_RE_wear(src_item,load,item_max_charge)
+                             src_meta["charge"]   = load
+                             src_item["metadata"] = set_item_meta(src_meta)
+                             inv:set_stack("src", 1, src_item)
+                          end
+                       end
+                    end
+                    return charge -- return the remaining charge in the battery
+                 end
+
+local discharge_HV_tools = function(meta, charge, max_charge)
+                       -- discharging registered power tools
+                       local inv = meta:get_inventory()
+                       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 toolname = src_item["name"]
+                          if power_tools[toolname] ~= nil then
+                             -- Set meta data for the tool if it didn't do it itself :-(
+                             src_meta=get_item_meta(src_item["metadata"])
+                             if src_meta==nil then
+                                src_meta={}
+                                src_meta["technic_hv_power_tool"]=true
+                                src_meta["charge"]=0
+                             else
+                                if src_meta["technic_hv_power_tool"]==nil then
+                                   src_meta["technic_hv_power_tool"]=true
+                                   src_meta["charge"]=0
+                                end
+                             end
+                             -- Do the discharging
+                             local item_max_charge = power_tools[toolname]
+                             local load            = src_meta["charge"]
+                             local load_step       = 4000 -- how much to discharge per tick
+                             if load>0 and charge<max_charge then
+                                if charge+load_step>max_charge then load_step=max_charge-charge end
+                                if load-load_step<0 then load_step=load end
+                                load=load-load_step
+                                charge=charge+load_step
+                                technic.set_RE_wear(src_item,load,item_max_charge)
+                                src_meta["charge"]=load
+                                src_item["metadata"]=set_item_meta(src_meta)
+                                inv:set_stack("dst", 1, src_item)
+                             end
+                          end
+                       end
+                       return charge -- return the remaining charge in the battery
+                    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,
+    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")
+               local meta               = minetest.env:get_meta(pos)
+               local max_charge         = 1500000 -- Set maximum charge for the device here
+               local max_charge_rate    = 3000    -- Set maximum rate of charging
+               local max_discharge_rate = 5000    -- Set maximum rate of discharging (16000)
+               local eu_input           = meta:get_int("HV_EU_input")
+               local current_charge     = meta:get_int("internal_EU_charge") -- Battery charge right now
+
+               -- Power off automatically if no longer connected to a switching station
+               technic.switching_station_timeout_count(pos, "HV")
+
+               -- Charge/discharge the battery with the input EUs
+               if eu_input >=0 then
+                  current_charge = math.min(current_charge+eu_input, max_charge)
+               else
+                  current_charge = math.max(current_charge+eu_input, 0)
+               end
+
+               -- Charging/discharging tools here
+               current_charge = charge_HV_tools(meta, current_charge)
+               current_charge = discharge_HV_tools(meta, current_charge, max_charge)
+
+               -- Set a demand (we allow batteries to charge on less than the demand though)
+               meta:set_int("HV_EU_demand", math.min(max_charge_rate, max_charge-current_charge))
+
+               -- Set how much we can supply
+               meta:set_int("HV_EU_supply", math.min(max_discharge_rate, current_charge))
+
+               meta:set_int("internal_EU_charge", current_charge)
+               --dprint("BA: input:"..eu_input.." supply="..meta:get_int("HV_EU_supply").." demand="..meta:get_int("HV_EU_demand").." current:"..current_charge)
 
                -- Select node textures
-               local i = math.ceil((charge/max_charge)*8)
+               local i=math.ceil((current_charge/max_charge)*8)
                if i > 8 then i = 8 end
                local j = meta:get_float("last_side_shown")
                if i~=j then
@@ -111,221 +207,24 @@ minetest.register_abm(
                   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 load1<item_max_charge and charge>0 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 charge<max_charge then
-                           if charge+load_step>max_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)
+               local load = math.floor(current_charge/max_charge * 100)
                meta:set_string("formspec",
-                               hv_battery_box_formspec..
+                               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 charge<max_charge then
-                     if internal_EU_buffer-charge_to_take<=0 then
-                        charge_to_take=internal_EU_buffer
-                     end
-                     if charge_to_take>0 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;
+               if eu_input == 0 then
+                  meta:set_string("infotext", "HV Battery box: "..current_charge.."/"..max_charge.." (idle)")
+               else
+                  meta:set_string("infotext", "HV Battery box: "..current_charge.."/"..max_charge)
                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")
+technic.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
+   technic.register_HV_machine("technic:hv_battery_box"..i,"BA")
 end
index 86c445c79fc26a748654a1962f9de3864d3e20da..dfedc05c65ca240b64d84a6f625978cbb7ee3c10 100644 (file)
@@ -1,11 +1,4 @@
--- 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
-
+-- MV Battery box
 minetest.register_craft(
    {
       output = 'technic:mv_battery_box 1',
@@ -16,7 +9,7 @@ minetest.register_craft(
       }
    })
 
-mv_battery_box_formspec =
+local battery_box_formspec =
    "invsize[8,9;]"..
    "image[1,1;1,2;technic_power_meter_bg.png]"..
    "list[current_name;src;3,1;1,1;]"..
@@ -43,73 +36,172 @@ minetest.register_node(
                        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)
+                       meta:set_int("MV_EU_demand", 0) -- How much can this node charge
+                       meta:set_int("MV_EU_supply", 0) -- How much can this node discharge
+                       meta:set_int("MV_EU_input",  0) -- How much power is this machine getting.
+                       meta:set_float("internal_EU_charge", 0)
                        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
+                  if not inv:is_empty("src") or not inv:is_empty("dst") then
+                     minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
                      return false
+                  else
+                     return true
                   end
-                  return true
-               end
+               end,
    })
 
 
 for i=1,8,1 do
    minetest.register_node(
-      "technic:mv_battery_box"..i, {
+      "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
+                     if not inv:is_empty("src") or not inv:is_empty("dst") then
+                        minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
                         return false
+                     else
+                        return true
                      end
-                     return true
-                  end
+                  end,
       })
 end
 
+local power_tools = technic.MV_power_tools
+
+local charge_MV_tools = function(meta, charge)
+                    --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 toolname = src_item["name"]
+                       if power_tools[toolname] ~= nil then
+                          -- Set meta data for the tool if it didn't do it itself :-(
+                          src_meta=get_item_meta(src_item["metadata"])
+                          if src_meta==nil then
+                             src_meta={}
+                             src_meta["technic_mv_power_tool"]=true
+                             src_meta["charge"]=0
+                          else
+                             if src_meta["technic_mv_power_tool"]==nil then
+                                src_meta["technic_mv_power_tool"]=true
+                                src_meta["charge"]=0
+                             end
+                          end
+                          -- Do the charging
+                          local item_max_charge = power_tools[toolname]
+                          local load            = src_meta["charge"]
+                          local load_step       = 1000 -- how much to charge per tick
+                          if load<item_max_charge and charge>0 then
+                             if charge-load_step<0 then load_step=charge end
+                             if load+load_step>item_max_charge then load_step=item_max_charge-load end
+                             load=load+load_step
+                             charge=charge-load_step
+                             technic.set_RE_wear(src_item,load,item_max_charge)
+                             src_meta["charge"]   = load
+                             src_item["metadata"] = set_item_meta(src_meta)
+                             inv:set_stack("src", 1, src_item)
+                          end
+                       end
+                    end
+                    return charge -- return the remaining charge in the battery
+                 end
+
+local discharge_MV_tools = function(meta, charge, max_charge)
+                       -- discharging registered power tools
+                       local inv = meta:get_inventory()
+                       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 toolname = src_item["name"]
+                          if power_tools[toolname] ~= nil then
+                             -- Set meta data for the tool if it didn't do it itself :-(
+                             src_meta=get_item_meta(src_item["metadata"])
+                             if src_meta==nil then
+                                src_meta={}
+                                src_meta["technic_mv_power_tool"]=true
+                                src_meta["charge"]=0
+                             else
+                                if src_meta["technic_mv_power_tool"]==nil then
+                                   src_meta["technic_mv_power_tool"]=true
+                                   src_meta["charge"]=0
+                                end
+                             end
+                             -- Do the discharging
+                             local item_max_charge = power_tools[toolname]
+                             local load            = src_meta["charge"]
+                             local load_step       = 4000 -- how much to discharge per tick
+                             if load>0 and charge<max_charge then
+                                if charge+load_step>max_charge then load_step=max_charge-charge end
+                                if load-load_step<0 then load_step=load end
+                                load=load-load_step
+                                charge=charge+load_step
+                                technic.set_RE_wear(src_item,load,item_max_charge)
+                                src_meta["charge"]=load
+                                src_item["metadata"]=set_item_meta(src_meta)
+                                inv:set_stack("dst", 1, src_item)
+                             end
+                          end
+                       end
+                       return charge -- return the remaining charge in the battery
+                    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")
+   {
+      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 max_charge_rate    = 2000   -- Set maximum rate of charging (4000)
+               local max_discharge_rate = 3000   -- Set maximum rate of discharging
+               local eu_input           = meta:get_int("MV_EU_input")
+               local current_charge     = meta:get_int("internal_EU_charge") -- Battery charge right now
+
+               -- Power off automatically if no longer connected to a switching station
+               technic.switching_station_timeout_count(pos, "MV")
+
+               -- Charge/discharge the battery with the input EUs
+               if eu_input >=0 then
+                  current_charge = math.min(current_charge+eu_input, max_charge)
+               else
+                  current_charge = math.max(current_charge+eu_input, 0)
+               end
+
+               -- Charging/discharging tools here
+               current_charge = charge_MV_tools(meta, current_charge)
+               current_charge = discharge_MV_tools(meta, current_charge, max_charge)
+
+               -- Set a demand (we allow batteries to charge on less than the demand though)
+               meta:set_int("MV_EU_demand", math.min(max_charge_rate, max_charge-current_charge))
+
+               -- Set how much we can supply
+               meta:set_int("MV_EU_supply", math.min(max_discharge_rate, current_charge))
+
+               meta:set_int("internal_EU_charge", current_charge)
+               --dprint("BA: input:"..eu_input.." supply="..meta:get_int("MV_EU_supply").." demand="..meta:get_int("MV_EU_demand").." current:"..current_charge)
 
                -- Select node textures
-               local i = math.ceil((charge/max_charge)*8)
+               local i=math.ceil((current_charge/max_charge)*8)
                if i > 8 then i = 8 end
                local j = meta:get_float("last_side_shown")
                if i~=j then
@@ -118,221 +210,24 @@ minetest.register_abm(
                   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"])
-
-                  -- 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 load1<item_max_charge and charge>0 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 charge<max_charge then
-                           if charge+load_step>max_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/300000) * 100)
+               local load = math.floor(current_charge/max_charge * 100)
                meta:set_string("formspec",
-                               mv_battery_box_formspec..
+                               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 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
-
-               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 charge<max_charge then
-                     if internal_EU_buffer-charge_to_take<=0 then
-                        charge_to_take=internal_EU_buffer
-                     end
-                     if charge_to_take>0 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(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;
+               if eu_input == 0 then
+                  meta:set_string("infotext", "MV Battery box: "..current_charge.."/"..max_charge.." (idle)")
+               else
+                  meta:set_string("infotext", "MV Battery box: "..current_charge.."/"..max_charge)
                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")
+technic.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)
-   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,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,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
+   technic.register_MV_machine("technic:mv_battery_box"..i,"BA")
 end
index 78ff41348476919bba8df35f8d3380e23b52219d..6a98ce9fc3d838313d48f107ad1c611989c5de0f 100644 (file)
@@ -1,5 +1,5 @@
-water_can_max_load = 16
-lava_can_max_load = 8
+local water_can_max_load = 16
+local lava_can_max_load = 8
 
 minetest.register_craft({
        output = 'technic:water_can 1',
@@ -42,7 +42,7 @@ minetest.register_tool("technic:water_can", {
                        minetest.env:add_node(pointed_thing.under, {name="air"})
                         load=load+1;   
                        item["metadata"]=tostring(load)
-                       set_RE_wear(item,load,water_can_max_load)
+                       technic.set_RE_wear(item,load,water_can_max_load)
                        itemstack:replace(item)
                        end
                        return itemstack
@@ -54,7 +54,7 @@ minetest.register_tool("technic:water_can", {
                        minetest.env:add_node(pointed_thing.under, {name="default:water_source"})
                        load=load-1;    
                        item["metadata"]=tostring(load)
-                       set_RE_wear(item,load,water_can_max_load)
+                       technic.set_RE_wear(item,load,water_can_max_load)
                        itemstack:replace(item)
                        return itemstack
                        end
@@ -64,7 +64,7 @@ minetest.register_tool("technic:water_can", {
                        minetest.env:add_node(pointed_thing.above, {name="default:water_source"})
                        load=load-1;    
                        item["metadata"]=tostring(load)
-                       set_RE_wear(item,load,water_can_max_load)
+                       technic.set_RE_wear(item,load,water_can_max_load)
                        itemstack:replace(item)
                        return itemstack
                        end             
@@ -90,7 +90,7 @@ minetest.register_tool("technic:lava_can", {
                        minetest.env:add_node(pointed_thing.under, {name="air"})
                         load=load+1;
                        item["metadata"]=tostring(load)
-                       set_RE_wear(item,load,lava_can_max_load)
+                       technic.set_RE_wear(item,load,lava_can_max_load)
                        itemstack:replace(item)
                        end
                        return itemstack
@@ -102,7 +102,7 @@ minetest.register_tool("technic:lava_can", {
                        minetest.env:add_node(pointed_thing.under, {name="default:lava_source"})
                        load=load-1;    
                        item["metadata"]=tostring(load)
-                       set_RE_wear(item,load,lava_can_max_load)
+                       technic.set_RE_wear(item,load,lava_can_max_load)
                        itemstack:replace(item)
                        return itemstack
                        end
@@ -112,7 +112,7 @@ minetest.register_tool("technic:lava_can", {
                        minetest.env:add_node(pointed_thing.above, {name="default:lava_source"})
                        load=load-1;    
                        item["metadata"]=tostring(load)
-                       set_RE_wear(item,load,lava_can_max_load)
+                       technic.set_RE_wear(item,load,lava_can_max_load)
                        itemstack:replace(item)
                        return itemstack
                        end     
index 5b3b05b83ffc07fcc56041248aa3c6aabf79e713..5c5de4ce7c6796d33f29ff0abeea160e7fb534c5 100644 (file)
@@ -3,7 +3,7 @@ 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)
+technic.register_LV_power_tool ("technic:chainsaw",chainsaw_max_charge)
 
 minetest.register_tool("technic:chainsaw", {
         description = "Chainsaw",
@@ -20,7 +20,7 @@ minetest.register_tool("technic:chainsaw", {
                         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)
+                        technic.set_RE_wear(item,charge,chainsaw_max_charge)
                         meta["charge"]=charge
                         item["metadata"]=set_item_meta(meta)
                         itemstack:replace(item)
index 49765026eaeabd0a3eddd5eb7137601b1303fb9b..ad3dc6792571438aa0593204f1903bd01fff9ea7 100644 (file)
@@ -1,8 +1,8 @@
--- Technic CNC v1.0 by kpo
+-- Technic CNC v1.0 by kpoppel
 -- 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
+--   Somehow 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.
@@ -32,24 +32,6 @@ local twosize_products = {
    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:]"..
@@ -88,215 +70,212 @@ local cnc_formspec =
    
    "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
+                       -- 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,
-     })
+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,
+      on_construct = function(pos)
+                       local meta = minetest.env:get_meta(pos)
+                       meta:set_string("infotext", "CNC Machine")
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_string("formspec", cnc_formspec)
+                       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(), "Machine cannot be removed because it is not empty");
+                     return false
+                  else
+                     return true
+                  end
+               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,
-})
+                         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
+   { 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 eu_input     = meta:get_int("LV_EU_input")
+                local state        = meta:get_int("state")
+                local next_state   = state
 
-                 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
-   }) 
+                -- Machine information
+                local machine_name         = "CNC"
+                local machine_node         = "technic:cnc"
+                local machine_state_demand = { 50, 450 }
+                        
+                -- Setup meta data if it does not exist. state is used as an indicator of this
+                if state == 0 then
+                   meta:set_int("state", 1)
+                   meta:set_int("LV_EU_demand", machine_state_demand[1])
+                   meta:set_int("LV_EU_input", 0)
+                   return
+                end
+                        
+                -- Power off automatically if no longer connected to a switching station
+                technic.switching_station_timeout_count(pos, "LV")
+                        
+                -- State machine
+                if eu_input == 0 then
+                   -- Unpowered - go idle
+                   hacky_swap_node(pos, machine_node)
+                   meta:set_string("infotext", machine_name.." Unpowered")
+                   next_state = 1
+                elseif eu_input == machine_state_demand[state] then
+                   -- Powered - do the state specific actions
+                           
+                   local inv   = meta:get_inventory()
+                   local empty = inv:is_empty("src")
+
+                   if state == 1 then
+                      hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Idle")
+
+                      local result = meta:get_string("cnc_product")
+                      if not empty and minetest.registered_nodes[result] ~= nil and inv:room_for_item("dst",result) then
+                         next_state = 2
+                      else
+                         meta:set_string("cnc_product", "") -- Reset the program
+                      end
+                      --minetest.chat_send_player(meta:get_string("cnc_user"), "CNC machine does not know how to handle this material. Please remove it.");
+
+                   elseif state == 2 then
+                      hacky_swap_node(pos, machine_node.."_active")
+                      meta:set_string("infotext", machine_name.." Active")
+
+                      if empty then
+                         next_state = 1
+                      else
+                         meta:set_int("src_time", meta:get_int("src_time") + 1)
+                         if meta:get_int("src_time") >= 3 then -- 3 ticks per output
+                            local result = meta:get_string("cnc_product")
+                            -- check if there's room for output in "dst" list
+                            if inv:room_for_item("dst",result) then
+                               -- CNC does the transformation
+                               ------------------------------
+                               meta:set_int("src_time", 0)
+                               -- take stuff from "src" list
+                               srcstack = inv:get_stack("src", 1)
+                               srcstack:take_item()
+                               inv:set_stack("src", 1, srcstack)
+                               -- Put result in "dst" list
+                               inv:add_item("dst",result .. " " .. meta:get_int("cnc_multiplier"))
+                            else
+                               next_state = 1
+                            end
+                         end
+                      end
+                   end
+                end
+                -- Change state?
+                if next_state ~= state then
+                   meta:set_int("LV_EU_demand", machine_state_demand[next_state])
+                   meta:set_int("state", next_state)
+                end
+             end
+  }) 
 
-register_LV_machine ("technic:cnc","RE")
-register_LV_machine ("technic:cnc_active","RE")
+technic.register_LV_machine ("technic:cnc","RE")
+technic.register_LV_machine ("technic:cnc_active","RE")
 -------------------------
 
 -- CNC Machine Recipe
index e9d3236236da943abc02170862886bd8ed4d479d..4f2f11cc6bd0af2907a5310a36c0f4e5977f2071 100644 (file)
-minetest.register_craft({
-       output = 'technic:electric_furnace',
-       recipe = {
-               {'default:cobble', 'default:cobble', 'default:cobble'},
-               {'default:cobble', '', 'default:cobble'},
-               {'default:steel_ingot', 'moreores:copper_ingot', 'default:steel_ingot'},
-       }
-})
+-- LV Electric Furnace
+-- This is a faster version of the stone furnace which runs on EUs
 
+-- FIXME: kpoppel I'd like to introduce an induction heating element here also
+minetest.register_craft(
+   {output = 'technic:electric_furnace',
+    recipe = {
+       {'default:cobble',      'default:cobble',        'default:cobble'},
+       {'default:cobble',      '',                      'default:cobble'},
+       {'default:steel_ingot', 'moreores:copper_ingot', 'default:steel_ingot'},
+    }
+ })
 
-electric_furnace_formspec =
-       "invsize[8,9;]"..
-       "image[1,1;1,2;technic_power_meter_bg.png]"..
-       "list[current_name;src;3,1;1,1;]"..
-       "list[current_name;dst;5,1;2,2;]"..
-       "list[current_player;main;0,5;8,4;]"..
-       "label[0,0;Electric Furnace]"..
-       "label[1,3;Power level]"
-       
-minetest.register_node("technic:electric_furnace", {
-       description = "Electric furnace",
-       tiles = {"technic_electric_furnace_top.png", "technic_electric_furnace_bottom.png", "technic_electric_furnace_side.png",
-               "technic_electric_furnace_side.png", "technic_electric_furnace_side.png", "technic_electric_furnace_front.png"},
-       paramtype2 = "facedir",
-       groups = {cracky=2},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_stone_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       interal_EU_buffer_size=2000;
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_float("technic_power_machine", 1)
-               meta:set_string("formspec", electric_furnace_formspec)
-               meta:set_string("infotext", "Electric furnace")
-               local inv = meta:get_inventory()
-               inv:set_size("src", 1)
-               inv:set_size("dst", 4)
-               local EU_used  = 0
-               local furnace_is_cookin = 0
-               local cooked = nil
-               meta:set_float("internal_EU_buffer",0)
-               meta:set_float("internal_EU_buffer_size",2000)
+local electric_furnace_formspec =
+   "invsize[8,9;]"..
+   "list[current_name;src;3,1;1,1;]"..
+   "list[current_name;dst;5,1;2,2;]"..
+   "list[current_player;main;0,5;8,4;]"..
+   "label[0,0;Electric Furnace]"..
+   "label[1,3;Power level]"
 
-       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:electric_furnace",
+   {description = "Electric furnace",
+    tiles = {"technic_electric_furnace_top.png", "technic_electric_furnace_bottom.png", "technic_electric_furnace_side.png",
+            "technic_electric_furnace_side.png", "technic_electric_furnace_side.png", "technic_electric_furnace_front.png"},
+    paramtype2 = "facedir",
+    groups = {cracky=2},
+    legacy_facedir_simple = true,
+    sounds = default.node_sound_stone_defaults(),
+    on_construct = function(pos)
+                     local meta = minetest.env:get_meta(pos)
+                     meta:set_string("infotext", "Electric Furnace")
+                     meta:set_float("technic_power_machine", 1)
+                     meta:set_string("formspec", electric_furnace_formspec)
+                     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(), "Machine cannot be removed because it is not empty");
+                   return false
+                else
+                   return true
+                end
+             end,
+ })
 
-minetest.register_node("technic:electric_furnace_active", {
-       description = "Electric Furnace",
-       tiles = {"technic_electric_furnace_top.png", "technic_electric_furnace_bottom.png", "technic_electric_furnace_side.png",
-               "technic_electric_furnace_side.png", "technic_electric_furnace_side.png", "technic_electric_furnace_front_active.png"},
-       paramtype2 = "facedir",
-       light_source = 8,
-       drop = "technic:electric_furnace",
-       groups = {cracky=2, not_in_creative_inventory=1},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_stone_defaults(),
-       internal_EU_buffer=0;
-       interal_EU_buffer_size=2000;
-       technic_power_machine=1,
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_float("technic_power_machine", 1)
-               meta:set_string("formspec", electric_furnace_formspec)
-               meta:set_string("infotext", "Electric furnace");
-               local inv = meta:get_inventory()
-               inv:set_size("src", 1)
-               inv:set_size("dst", 4)
-               local EU_used  = 0
-               local furnace_is_cookin = 0
-               local cooked = nil
-       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:electric_furnace_active",
+   {description = "Electric Furnace",
+    tiles = {"technic_electric_furnace_top.png", "technic_electric_furnace_bottom.png", "technic_electric_furnace_side.png",
+            "technic_electric_furnace_side.png", "technic_electric_furnace_side.png", "technic_electric_furnace_front_active.png"},
+    paramtype2 = "facedir",
+    light_source = 8,
+    drop = "technic:electric_furnace",
+    groups = {cracky=2, not_in_creative_inventory=1},
+    legacy_facedir_simple = true,
+    sounds = default.node_sound_stone_defaults(),
+    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(), "Machine cannot be removed because it is not empty");
+                   return false
+                else
+                   return true
+                end
+             end,
+ })
 
-minetest.register_abm({
-       nodenames = {"technic:electric_furnace","technic:electric_furnace_active"},
-       interval = 1,
-       chance = 1,
-       
-       action = function(pos, node, active_object_count, active_object_count_wider)
+minetest.register_abm(
+   { nodenames = {"technic:electric_furnace","technic:electric_furnace_active"},
+     interval = 1,
+     chance   = 1,
+     action = function(pos, node, active_object_count, active_object_count_wider)
+                local meta         = minetest.env:get_meta(pos)
+                local eu_input     = meta:get_int("LV_EU_input")
+                local state        = meta:get_int("state")
+                local next_state   = state
 
-               local meta = minetest.env:get_meta(pos)
-               internal_EU_buffer=meta:get_float("internal_EU_buffer")
-               internal_EU_buffer_size=meta:get_float("internal_EU_buffer_size")
-               local load = math.floor(internal_EU_buffer/internal_EU_buffer_size * 100)
-               meta:set_string("formspec",
-                               "invsize[8,9;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                       (load)..":technic_power_meter_fg.png]"..
-                               "list[current_name;src;3,1;1,1;]"..
-                               "list[current_name;dst;5,1;2,2;]"..
-                               "list[current_player;main;0,5;8,4;]"..
-                               "label[0,0;Electric Furnace]"..
-                               "label[1,3;Power level]")
+                -- Machine information
+                local machine_name         = "Electric furnace"
+                local machine_node         = "technic:electric_furnace"
+                local machine_state_demand = { 50, 1000 }
+                        
+                -- Setup meta data if it does not exist. state is used as an indicator of this
+                if state == 0 then
+                   meta:set_int("state", 1)
+                   meta:set_int("LV_EU_demand", machine_state_demand[1])
+                   meta:set_int("LV_EU_input", 0)
+                   return
+                end
+                        
+                -- Power off automatically if no longer connected to a switching station
+                technic.switching_station_timeout_count(pos, "LV")
+                        
+                -- State machine
+                if eu_input == 0 then
+                   -- Unpowered - go idle
+                   hacky_swap_node(pos, machine_node)
+                   meta:set_string("infotext", machine_name.." Unpowered")
+                   next_state = 1
+                elseif eu_input == machine_state_demand[state] then
+                   -- Powered - do the state specific actions
+                           
+                   -- Execute always if powered logic
+                   local inv    = meta:get_inventory()
+                   local empty  = inv:is_empty("src")
 
-               local inv = meta:get_inventory()
-               
-               local furnace_is_cookin = meta:get_float("furnace_is_cookin")
-               
-               
-               local srclist = inv:get_list("src")
-               local cooked=nil 
+                   if state == 1 then
+                      hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Idle")
 
-               if srclist then
-                cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
-               end
-               
-               
-               if (furnace_is_cookin == 1) then
-                       if internal_EU_buffer>=150 then
-                       internal_EU_buffer=internal_EU_buffer-150;
-                       meta:set_float("internal_EU_buffer",internal_EU_buffer)
-                       meta:set_float("src_time", meta:get_float("src_time") + 3)
-                       if cooked and cooked.item and meta:get_float("src_time") >= cooked.time then
-                               -- check if there's room for output in "dst" list
-                               if inv:room_for_item("dst",cooked.item) then
-                                       -- Put result in "dst" list
-                                       inv:add_item("dst", cooked.item)
-                                       -- take stuff from "src" list
-                                       srcstack = inv:get_stack("src", 1)
-                                       srcstack:take_item()
-                                       inv:set_stack("src", 1, srcstack)
-                               else
-                                       print("Furnace inventory full!")
-                               end
-                               meta:set_string("src_time", 0)
-                       end
-                       end
-               end
+                      local result = minetest.get_craft_result({method = "cooking", width = 1, items = inv:get_list("src")})
+                      if not empty and result and inv:room_for_item("dst",result) then
+                         next_state = 2
+                      end
 
+                   elseif state == 2 then
+                      hacky_swap_node(pos, machine_node.."_active")
+                      meta:set_string("infotext", machine_name.." Active")
 
-               if srclist then
-                       cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
-                       if cooked.time>0 then 
-                       hacky_swap_node(pos,"technic:electric_furnace_active")
-                       meta:set_string("infotext","Furnace active")
-                       meta:set_string("furnace_is_cookin",1)
-                       meta:set_string("src_time", 0)
-                       return
-                       end
+                      if empty then
+                         next_state = 1
+                      else
+                         meta:set_int("src_time", meta:get_int("src_time") + 3) -- Cooking time 3x
+                         local result = minetest.get_craft_result({method = "cooking", width = 1, items = inv:get_list("src")})
+                         if result and result.item and meta:get_int("src_time") >= result.time then
+                            -- check if there's room for output in "dst" list
+                            meta:set_int("src_time", 0)
+                            if inv:room_for_item("dst",result.item) then
+                               -- take stuff from "src" list
+                               srcstack = inv:get_stack("src", 1)
+                               srcstack:take_item()
+                               inv:set_stack("src", 1, srcstack)
+                               -- Put result in "dst" list
+                               inv:add_item("dst", result.item)
+                            else
+                               -- all full: go idle
+                               next_state = 1
+                            end
+                         end
+                      end
+                   end
+                end
+                -- Change state?
+                if next_state ~= state then
+                   meta:set_int("LV_EU_demand", machine_state_demand[next_state])
+                   meta:set_int("state", next_state)
+                end
+             end,
+  })
 
-               end
-
-                               hacky_swap_node(pos,"technic:electric_furnace")
-                               meta:set_string("infotext","Furnace inactive")
-                               meta:set_string("furnace_is_cookin",0)
-                               meta:set_string("src_time", 0)
-
-end,
-})
-
-register_LV_machine ("technic:electric_furnace","RE")
-register_LV_machine ("technic:electric_furnace_active","RE")
+technic.register_LV_machine ("technic:electric_furnace","RE")
+technic.register_LV_machine ("technic:electric_furnace_active","RE")
index fd90b14332f6d4b52788b256bf902b812bd521f3..7f205b5e56d7827029248e968720c70c34b52f54 100644 (file)
-minetest.register_craft({
-       output = 'technic:mv_electric_furnace',
-       recipe = {
-               {'technic:stainless_steel_ingot', 'technic:electric_furnace', 'technic:stainless_steel_ingot'},
-               {'pipeworks:tube_000000', 'technic:mv_transformer', 'pipeworks:tube_000000'},
-               {'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
-       }
-})
+-- MV Electric Furnace
+-- This is a faster version of the stone furnace which runs on EUs
+-- In addition to this it can be upgraded with microcontrollers and batteries
+-- This new version uses the batteries to lower the power consumption of the machine
+-- Also in addition this furnace can be attached to the pipe system from the pipeworks mod.
 
+-- FIXME: kpoppel I'd like to introduce an induction heating element here also
+minetest.register_craft(
+   {output = 'technic:mv_electric_furnace',
+    recipe = {
+       {'technic:stainless_steel_ingot', 'technic:electric_furnace', 'technic:stainless_steel_ingot'},
+       {'pipeworks:tube_000000', 'technic:mv_transformer', 'pipeworks:tube_000000'},
+       {'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
+    }
+ })
 
-mv_electric_furnace_formspec =
-       "invsize[8,10;]"..
-       "image[1,1;1,2;technic_power_meter_bg.png]"..
-       "list[current_name;src;3,1;1,1;]"..
-       "list[current_name;dst;5,1;2,2;]"..
-       "list[current_player;main;0,6;8,4;]"..
-       "label[0,0;MV Electric Furnace]"..
-       "label[1,2.8;Power level]"..
-       "list[current_name;upgrade1;1,4;1,1;]"..
-       "list[current_name;upgrade2;2,4;1,1;]"..
-       "label[1,5;Upgrade Slots]"
+local mv_electric_furnace_formspec =
+   "invsize[8,10;]"..
+   "list[current_name;src;3,1;1,1;]"..
+   "list[current_name;dst;5,1;2,2;]"..
+   "list[current_player;main;0,6;8,4;]"..
+   "label[0,0;MV Electric Furnace]"..
+   "list[current_name;upgrade1;1,4;1,1;]"..
+   "list[current_name;upgrade2;2,4;1,1;]"..
+   "label[1,5;Upgrade Slots]"
 
-minetest.register_node("technic:mv_electric_furnace", {
-       description = "MV Electric furnace",
-       tiles = {"technic_mv_electric_furnace_top.png", "technic_mv_electric_furnace_bottom.png", "technic_mv_electric_furnace_side_tube.png",
-               "technic_mv_electric_furnace_side_tube.png", "technic_mv_electric_furnace_side.png", "technic_mv_electric_furnace_front.png"},
-       paramtype2 = "facedir",
-       groups = {cracky=2, tubedevice=1,tubedevice_receiver=1,},
-               tube={insert_object=function(pos,node,stack,direction)
-                       local meta=minetest.env:get_meta(pos)
-                       local inv=meta:get_inventory()
-                               return inv:add_item("src",stack)
-               end,
-               can_insert=function(pos,node,stack,direction)
+minetest.register_node(
+   "technic:mv_electric_furnace",
+   {description = "MV Electric furnace",
+    tiles = {"technic_mv_electric_furnace_top.png", "technic_mv_electric_furnace_bottom.png", "technic_mv_electric_furnace_side_tube.png",
+            "technic_mv_electric_furnace_side_tube.png", "technic_mv_electric_furnace_side.png", "technic_mv_electric_furnace_front.png"},
+    paramtype2 = "facedir",
+    groups = {cracky=2, tubedevice=1,tubedevice_receiver=1,},
+    tube={insert_object=function(pos,node,stack,direction)
+                          local meta=minetest.env:get_meta(pos)
+                          local inv=meta:get_inventory()
+                          return inv:add_item("src",stack)
+                       end,
+         can_insert=function(pos,node,stack,direction)
                        local meta=minetest.env:get_meta(pos)
                        local inv=meta:get_inventory()
                        return inv:room_for_item("src",stack)
-               end,
-               },
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_stone_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       interal_EU_buffer_size=2000;
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_float("technic_mv_power_machine", 1)
-               meta:set_string("formspec", mv_electric_furnace_formspec)
-               meta:set_string("infotext", "Electric furnace")
-               local inv = meta:get_inventory()
-               inv:set_size("src", 1)
-               inv:set_size("dst", 4)
-               inv:set_size("upgrade1", 1)
-               inv:set_size("upgrade2", 1)
-               local EU_used  = 0
-               local furnace_is_cookin = 0
-               local cooked = nil
-               meta:set_float("internal_EU_buffer",0)
-               meta:set_float("internal_EU_buffer_size",2000)
-               meta:set_float("tube_time", 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
-               elseif not inv:is_empty("upgrade1") then
-                       return false
-               elseif not inv:is_empty("upgrade2") then
-                       return false
-               end
-               return true
-       end,
-})
+                    end,
+       },
+    legacy_facedir_simple = true,
+    sounds = default.node_sound_stone_defaults(),
+    on_construct = function(pos)
+                     local meta = minetest.env:get_meta(pos)
+                     meta:set_string("infotext", "MV Electric furnace")
+                     meta:set_float("technic_mv_power_machine", 1)
+                     meta:set_int("tube_time",  0)
+                     meta:set_string("formspec", mv_electric_furnace_formspec)
+                     local inv = meta:get_inventory()
+                     inv:set_size("src", 1)
+                     inv:set_size("dst", 4)
+                     inv:set_size("upgrade1", 1)
+                     inv:set_size("upgrade2", 1)
+                  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") or not inv:is_empty("upgrade1") or not inv:is_empty("upgrade2") then
+                   minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                   return false
+                else
+                   return true
+                end
+             end,
+ })
 
-minetest.register_node("technic:mv_electric_furnace_active", {
-       description = "MV Electric Furnace",
-       tiles = {"technic_mv_electric_furnace_top.png", "technic_mv_electric_furnace_bottom.png", "technic_mv_electric_furnace_side_tube.png",
-               "technic_mv_electric_furnace_side_tube.png", "technic_mv_electric_furnace_side.png", "technic_mv_electric_furnace_front_active.png"},
-       paramtype2 = "facedir",
-       light_source = 8,
-       drop = "technic:mv_electric_furnace",
-       groups = {cracky=2, tubedevice=1,tubedevice_receiver=1,not_in_creative_inventory=1},
-       tube={insert_object=function(pos,node,stack,direction)
-                       local meta=minetest.env:get_meta(pos)
-                       local inv=meta:get_inventory()
-                               return inv:add_item("src",stack)
-               end,
-               can_insert=function(pos,node,stack,direction)
+minetest.register_node(
+   "technic:mv_electric_furnace_active",
+   {description = "MV Electric Furnace",
+    tiles = {"technic_mv_electric_furnace_top.png", "technic_mv_electric_furnace_bottom.png", "technic_mv_electric_furnace_side_tube.png",
+            "technic_mv_electric_furnace_side_tube.png", "technic_mv_electric_furnace_side.png", "technic_mv_electric_furnace_front_active.png"},
+    paramtype2 = "facedir",
+    light_source = 8,
+    drop = "technic:mv_electric_furnace",
+    groups = {cracky=2, tubedevice=1,tubedevice_receiver=1,not_in_creative_inventory=1},
+    tube={insert_object=function(pos,node,stack,direction)
+                          local meta=minetest.env:get_meta(pos)
+                          local inv=meta:get_inventory()
+                          return inv:add_item("src",stack)
+                       end,
+         can_insert=function(pos,node,stack,direction)
                        local meta=minetest.env:get_meta(pos)
                        local inv=meta:get_inventory()
                        return inv:room_for_item("src",stack)
-               end,
-               },
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_stone_defaults(),
-       internal_EU_buffer=0;
-       interal_EU_buffer_size=2000;
-       technic_power_machine=1,
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_float("technic_mv_power_machine", 1)
-               meta:set_string("formspec", mv_electric_furnace_formspec)
-               meta:set_string("infotext", "Electric furnace");
-               local inv = meta:get_inventory()
-               inv:set_size("src", 1)
-               inv:set_size("dst", 4)
-               inv:set_size("upgrade1", 1)
-               inv:set_size("upgrade2", 1)
-               local EU_used  = 0
-               local furnace_is_cookin = 0
-               local cooked = nil
-       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
-               elseif not inv:is_empty("upgrade1") then
-                       return false
-               elseif not inv:is_empty("upgrade2") then
-                       return false
-               end
-               return true
-       end,
-})
-
-minetest.register_abm({
-       nodenames = {"technic:mv_electric_furnace","technic:mv_electric_furnace_active"},
-       interval = 1,
-       chance = 1,
+                    end,
+       },
+    legacy_facedir_simple = true,
+    sounds = default.node_sound_stone_defaults(),
+    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") or not inv:is_empty("upgrade1") or not inv:is_empty("upgrade2") then
+                   minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                   return false
+                else
+                   return true
+                end
+             end,
+    -- These three makes sure upgrades are not moved in or out while the furnace is active.
+    allow_metadata_inventory_put = function(pos, listname, index, stack, player)
+                                      if listname == "src" or listname == "dst" then
+                                         return 99
+                                      else
+                                         return 0 -- Disallow the move
+                                      end
+                                  end,
+    allow_metadata_inventory_take = function(pos, listname, index, stack, player)
+                                      if listname == "src" or listname == "dst" then
+                                         return 99
+                                      else
+                                         return 0 -- Disallow the move
+                                      end
+                                   end,
+    allow_metadata_inventory_move = function(pos, from_list, to_list, to_list, to_index, count, player)
+                                   return 0
+                                end,
+ })
 
-       action = function(pos, node, active_object_count, active_object_count_wider)
+local send_cooked_items = function(pos,x_velocity,z_velocity)
+                            -- Send items on their way in the pipe system.
+                            local meta=minetest.env:get_meta(pos) 
+                            local inv = meta:get_inventory()
+                            local i=0
+                            for _,stack in ipairs(inv:get_list("dst")) do
+                               i=i+1
+                               if stack then
+                                  local item0=stack:to_table()
+                               if item0 then 
+                                  item0["count"]="1"
+                                  local item1=tube_item({x=pos.x,y=pos.y,z=pos.z},item0)
+                                  item1:get_luaentity().start_pos = {x=pos.x,y=pos.y,z=pos.z}
+                                  item1:setvelocity({x=x_velocity, y=0, z=z_velocity})
+                                  item1:setacceleration({x=0, y=0, z=0})
+                                  stack:take_item(1);
+                                  inv:set_stack("dst", i, stack)
+                                  return
+                               end
+                            end
+                         end
+                      end
 
-               local pos1={}
-               pos1.x=pos.x
-               pos1.y=pos.y
-               pos1.z=pos.z
-               local x_velocity=0
-               local z_velocity=0
-               
-               -- output is on the left side of the furnace
-               if node.param2==3 then pos1.z=pos1.z-1 z_velocity =-1 end
-               if node.param2==2 then pos1.x=pos1.x-1 x_velocity =-1 end
-               if node.param2==1 then pos1.z=pos1.z+1 z_velocity = 1 end
-               if node.param2==0 then pos1.x=pos1.x+1 x_velocity = 1 end
-               
-               local output_tube_connected = false
-               local meta=minetest.env:get_meta(pos1) 
-               if meta:get_int("tubelike")==1 then output_tube_connected=true end
-               meta = minetest.env:get_meta(pos)
-               local inv = meta:get_inventory()
-               local upg_item1
-               local upg_item1_name=""
-               local upg_item2
-               local upg_item2_name=""
-               local srcstack = inv:get_stack("upgrade1", 1)
-               if srcstack then upg_item1=srcstack:to_table() end
-               srcstack = inv:get_stack("upgrade2", 1)
-               if srcstack then upg_item2=srcstack:to_table() end
-               if upg_item1 then upg_item1_name=upg_item1.name end
-               if upg_item2 then upg_item2_name=upg_item2.name end
-               
-               local speed=0
-               if upg_item1_name=="technic:control_logic_unit" then speed=speed+1 end
-               if upg_item2_name=="technic:control_logic_unit" then speed=speed+1 end
-               tube_time=meta:get_float("tube_time")
-               tube_time=tube_time+speed
-               if tube_time>3 then 
-                       tube_time=0
-                       if output_tube_connected then send_cooked_items(pos,x_velocity,z_velocity) end
-               end
-               meta:set_float("tube_time", tube_time)
-                       
-               local extra_buffer_size = 0
-               if upg_item1_name=="technic:battery" then extra_buffer_size =extra_buffer_size + 10000 end
-               if upg_item2_name=="technic:battery" then extra_buffer_size =extra_buffer_size + 10000 end
-               local internal_EU_buffer_size=2000+extra_buffer_size
-               meta:set_float("internal_EU_buffer_size",internal_EU_buffer_size)
-               
-               internal_EU_buffer=meta:get_float("internal_EU_buffer")
-               if internal_EU_buffer > internal_EU_buffer_size then internal_EU_buffer = internal_EU_buffer_size end
-               local load = math.floor(internal_EU_buffer/(internal_EU_buffer_size) * 100)
-               meta:set_string("formspec",
-                               "invsize[8,10;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                       (load)..":technic_power_meter_fg.png]"..
-                               "list[current_name;src;3,1;1,1;]"..
-                               "list[current_name;dst;5,1;2,2;]"..
-                               "list[current_player;main;0,6;8,4;]"..
-                               "label[0,0;MV Electric Furnace]"..
-                               "label[1,2.8;Power level]"..
-                               "list[current_name;upgrade1;1,4;1,1;]"..
-                               "list[current_name;upgrade2;2,4;1,1;]"..
-                               "label[1,5;Upgrade Slots]")
+local smelt_item = function(pos)
+                     local meta=minetest.env:get_meta(pos) 
+                     local inv = meta:get_inventory()
+                     meta:set_int("src_time", meta:get_int("src_time") + 3) -- Cooking time 3x faster
+                     local result = minetest.get_craft_result({method = "cooking", width = 1, items = inv:get_list("src")})
+                     if result and result.item and meta:get_int("src_time") >= result.time then
+                        meta:set_int("src_time", 0)
+                        -- check if there's room for output in "dst" list
+                        if inv:room_for_item("dst",result) then
+                           -- take stuff from "src" list
+                           srcstack = inv:get_stack("src", 1)
+                           srcstack:take_item()
+                           inv:set_stack("src", 1, srcstack)
+                           -- Put result in "dst" list
+                           inv:add_item("dst", result.item)
+                           return 1
+                        else
+                           return 0 -- done
+                        end
+                     end
+                     return 0 -- done
+                  end
 
-               local furnace_is_cookin = meta:get_float("furnace_is_cookin")
-               
-               
-               local srclist = inv:get_list("src")
-               local cooked=nil 
+minetest.register_abm(
+   {nodenames = {"technic:mv_electric_furnace","technic:mv_electric_furnace_active"},
+    interval = 1,
+    chance   = 1,
+    action = function(pos, node, active_object_count, active_object_count_wider)
+               local meta         = minetest.env:get_meta(pos)
+               local eu_input     = meta:get_int("MV_EU_input")
+               local state        = meta:get_int("state")
+               local next_state   = state
 
-               if srclist then
-                cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
+               -- Machine information
+               local machine_name         = "MV Electric Furnace"
+               local machine_node         = "technic:mv_electric_furnace"
+               local machine_state_demand = { 50, 2000, 1500, 1000 }
+                        
+               -- Setup meta data if it does not exist. state is used as an indicator of this
+               if state == 0 then
+                  meta:set_int("state", 1)
+                  meta:set_int("MV_EU_demand", machine_state_demand[1])
+                  meta:set_int("MV_EU_input", 0)
+                  return
                end
+                        
+               -- Power off automatically if no longer connected to a switching station
+               technic.switching_station_timeout_count(pos, "MV")
                
+               -- Execute always logic
+               -- CODE HERE --
                
-               if (furnace_is_cookin == 1) then
-                       if internal_EU_buffer>=150 then
-                       internal_EU_buffer=internal_EU_buffer-150;
-                       meta:set_float("internal_EU_buffer",internal_EU_buffer)
-                       meta:set_float("src_time", meta:get_float("src_time") + 3)
-                       if cooked and cooked.item and meta:get_float("src_time") >= cooked.time then
-                               -- check if there's room for output in "dst" list
-                               if inv:room_for_item("dst",cooked.item) then
-                                       -- Put result in "dst" list
-                                       inv:add_item("dst", cooked.item)
-                                       -- take stuff from "src" list
-                                       srcstack = inv:get_stack("src", 1)
-                                       srcstack:take_item()
-                                       inv:set_stack("src", 1, srcstack)
-                               else
-                                       print("Furnace inventory full!")
-                               end
-                               meta:set_string("src_time", 0)
-                       end
-                       end             
+               -- State machine
+               if eu_input == 0 then
+                  -- Unpowered - go idle
+                  hacky_swap_node(pos, machine_node)
+                  meta:set_string("infotext", machine_name.." Unpowered")
+                  next_state = 1
+               elseif eu_input == machine_state_demand[state] then
+                  -- Powered - do the state specific actions
+                           
+                  -- Execute always if powered logic
+                  local meta=minetest.env:get_meta(pos) 
+                         
+                  -- Get the names of the upgrades
+                  local meta=minetest.env:get_meta(pos) 
+                  local inv = meta:get_inventory()
+                  local upg_item1
+                  local upg_item1_name=""
+                  local upg_item2
+                  local upg_item2_name=""
+                  local srcstack = inv:get_stack("upgrade1", 1)
+                  if  srcstack then upg_item1=srcstack:to_table() end
+                  srcstack = inv:get_stack("upgrade2", 1)
+                  if  srcstack then upg_item2=srcstack:to_table() end
+                  if upg_item1 then upg_item1_name=upg_item1.name end
+                  if upg_item2 then upg_item2_name=upg_item2.name end
+                  
+                  -- Save some power by installing battery upgrades. Fully upgraded makes this
+                  -- furnace use the same amount of power as the LV version
+                  local EU_saving_upgrade = 0
+                  if upg_item1_name=="technic:battery" then EU_saving_upgrade = EU_saving_upgrade + 1 end
+                  if upg_item2_name=="technic:battery" then EU_saving_upgrade = EU_saving_upgrade + 1 end
+                  
+                  -- Tube loading speed can be upgraded using control logic units
+                  local tube_speed_upgrade = 0
+                  if upg_item1_name=="technic:control_logic_unit" then tube_speed_upgrade = tube_speed_upgrade + 1 end
+                  if upg_item2_name=="technic:control_logic_unit" then tube_speed_upgrade = tube_speed_upgrade + 1 end
+                  
+                  -- Handle pipeworks (consumes tube_speed_upgrade)
+                  local pos1={x=pos.x, y=pos.y, z=pos.z}
+                  local x_velocity=0
+                  local z_velocity=0
+                  
+                  -- Output is on the left side of the furnace
+                  if node.param2==3 then pos1.z=pos1.z-1 z_velocity =-1 end
+                  if node.param2==2 then pos1.x=pos1.x-1 x_velocity =-1 end
+                  if node.param2==1 then pos1.z=pos1.z+1 z_velocity = 1 end
+                  if node.param2==0 then pos1.x=pos1.x+1 x_velocity = 1 end
+                  
+                  local output_tube_connected = false
+                  local meta1 = minetest.env:get_meta(pos1) 
+                  if meta1:get_int("tubelike") == 1 then
+                     output_tube_connected=true
+                  end
+                  tube_time = meta:get_int("tube_time")
+                  tube_time = tube_time + tube_speed_upgrade
+                  if tube_time > 3 then
+                     tube_time = 0
+                     if output_tube_connected then
+                        send_cooked_items(pos,x_velocity,z_velocity)
+                     end
+                  end
+                  meta:set_int("tube_time", tube_time)
+                  
+                  -- The machine shuts down if we have nothing to smelt and no tube is connected
+                  -- or if we have nothing to send with a tube connected.
+                  if    (not output_tube_connected and inv:is_empty("src"))
+                  or (    output_tube_connected and inv:is_empty("dst")) then
+                  next_state = 1
                end
-
-
-
-               if srclist then
-                       cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
-                       if cooked.time>0 then 
-                       hacky_swap_node(pos,"technic:mv_electric_furnace_active")
-                       meta:set_string("infotext","Furnace active")
-                       meta:set_string("furnace_is_cookin",1)
-                       meta:set_string("src_time", 0)
-                       return
-                       end
-
-               end
-
-                               hacky_swap_node(pos,"technic:mv_electric_furnace")
-                               meta:set_string("infotext","Furnace inactive")
-                               meta:set_string("furnace_is_cookin",0)
-                               meta:set_string("src_time", 0)
-
-end,
-})
-
-function send_cooked_items (pos,x_velocity,z_velocity)
-               local meta=minetest.env:get_meta(pos) 
-               local inv = meta:get_inventory()
-               local i=0
-               for _,stack in ipairs(inv:get_list("dst")) do
-               i=i+1
-                       if stack then
-                       local item0=stack:to_table()
-                       if item0 then 
-                               item0["count"]="1"
-                               local item1=tube_item({x=pos.x,y=pos.y,z=pos.z},item0)
-                               item1:get_luaentity().start_pos = {x=pos.x,y=pos.y,z=pos.z}
-                               item1:setvelocity({x=x_velocity, y=0, z=z_velocity})
-                               item1:setacceleration({x=0, y=0, z=0})
-                               stack:take_item(1);
-                               inv:set_stack("dst", i, stack)
-                               return
-                               end
-                       end
+               ----------------------
+               
+               if state == 1 then
+                  hacky_swap_node(pos, machine_node)
+                  meta:set_string("infotext", machine_name.." Idle")
+                  
+                  local meta=minetest.env:get_meta(pos) 
+                  local inv = meta:get_inventory()
+                  if not inv:is_empty("src") then
+                     local result = minetest.get_craft_result({method = "cooking", width = 1, items = inv:get_list("src")})
+                     if result then
+                        meta:set_string("infotext", machine_name.." Active")
+                        meta:set_int("src_time",     0)
+                        next_state = 2+EU_saving_upgrade -- Next state is decided by the battery upgrade (state 2= 0 batteries, state 3 = 1 battery, 4 = 2 batteries)
+                     end
+                  else
+                     meta:set_string("infotext", "Electric Furnace Idle")
+                  end
+                  
+               elseif state == 2 or state == 3 or state == 4 then
+                  hacky_swap_node(pos, machine_node.."_active")
+                  meta:set_string("infotext", machine_name.." Active")
+                  result = smelt_item(pos, data)
+                  if result == 0 then
+                     next_state = 1
+                  end
                end
-end
+            end
+            -- Change state?
+            if next_state ~= state then
+               meta:set_int("MV_EU_demand", machine_state_demand[next_state])
+               meta:set_int("state", next_state)
+            end
+         end,
+ })
 
-register_MV_machine ("technic:mv_electric_furnace","RE")
-register_MV_machine ("technic:mv_electric_furnace_active","RE")
+technic.register_MV_machine ("technic:mv_electric_furnace","RE")
+technic.register_MV_machine ("technic:mv_electric_furnace_active","RE")
index f6e4dc2cd1ffea155af0a1779d34bd8788900009..dd36c3131aa0a0aad14e3d854cb273433ad7c042 100644 (file)
@@ -1,7 +1,7 @@
 -- original code comes from walkin_light mod by Echo http://minetest.net/forum/viewtopic.php?id=2621
 
-flashlight_max_charge=30000
-register_power_tool ("technic:flashlight",flashlight_max_charge)
+local flashlight_max_charge=30000
+technic.register_LV_power_tool ("technic:flashlight",flashlight_max_charge)
       
 minetest.register_tool("technic:flashlight", {
        description = "Flashlight",
index dbcae018a01a57d28bc2918040a9d0e81098128d..8af98f4e26cef5eaf2935ce101ba934c1bc80953 100644 (file)
@@ -66,7 +66,7 @@ local function remove_forcefield(p, range)
        end
 end
 
-forcefield_receive_fields = function(pos, formname, fields, sender)
+local forcefield_receive_fields = function(pos, formname, fields, sender)
        local meta = minetest.env:get_meta(pos)
        local range = meta:get_int("range")
        if fields.add then range = range + 1 end
@@ -88,7 +88,7 @@ forcefield_receive_fields = function(pos, formname, fields, sender)
        end
 end
 
-function get_forcefield_formspec(range, load)
+local get_forcefield_formspec = function(range, load)
        if not load then load = 0 end
        return "invsize[8,9;]"..
        "label[0,0;Forcefield emitter]"..
@@ -103,7 +103,7 @@ function get_forcefield_formspec(range, load)
        "list[current_player;main;0,5;8,4;]"
 end
 
-local function forcefield_check(pos)
+local forcefield_check = function(pos)
        local meta = minetest.env:get_meta(pos)
        local node = minetest.env:get_node(pos)
        local internal_EU_buffer=meta:get_float("internal_EU_buffer")
@@ -145,7 +145,6 @@ minetest.register_node("technic:forcefield_emitter_off", {
        tiles = {"technic_forcefield_emitter_off.png"},
        is_ground_content = true,
        groups = {cracky = 1},
-       technic_power_machine=1,
        on_timer = forcefield_check,
        on_receive_fields = forcefield_receive_fields,
        on_construct = function(pos)
@@ -206,9 +205,5 @@ minetest.register_node("technic:forcefield", {
        },
 })
 
-register_MV_machine ("technic:forcefield_emitter_on","RE")
-register_MV_machine ("technic:forcefield_emitter_off","RE")
-
-
-
-
+technic.register_MV_machine("technic:forcefield_emitter_on","RE")
+technic.register_MV_machine("technic:forcefield_emitter_off","RE")
index ae899a659f9bc99d51322d5b6a15c1ef0cef8b07..48f3b03773d70f9e10a593559b073a25133e45ee 100644 (file)
@@ -1,3 +1,7 @@
+-- Th coal driven EU generator.
+-- A simple device to get started on the electric machines.
+-- Inefficient and expensive in coal (200EU 16 ticks)
+-- Also only allows for LV machinery to run.
 minetest.register_alias("generator", "technic:generator")
 minetest.register_alias("generator", "technic:generator_active")
 
@@ -15,7 +19,7 @@ minetest.register_craftitem("technic:generator", {
        stack_max = 99,
 }) 
 
-generator_formspec =
+local generator_formspec =
        "invsize[8,9;]"..
        "image[0,0;5,5;technic_generator_menu.png]"..
        "image[1,1;1,2;technic_power_meter_bg.png]"..
@@ -26,124 +30,118 @@ generator_formspec =
        "list[current_player;main;0,5;8,4;]"
        
 
-minetest.register_node("technic:generator", {
-       description = "Coal Driven Generator",
-       tiles = {"technic_generator_top.png", "technic_machine_bottom.png", "technic_generator_side.png",
-               "technic_generator_side.png", "technic_generator_side.png", "technic_generator_front.png"},
-       paramtype2 = "facedir",
-       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_wood_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=5000;
-       burn_time=0;
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_string("infotext", "Generator")
-               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", generator_formspec)
-               meta:set_float("burn_time", 0)
-               
-               local inv = meta:get_inventory()
-               inv:set_size("src", 1)
-               
+minetest.register_node(
+   "technic:generator",
+   {
+      description = "Coal Driven Generator",
+      tiles = {"technic_generator_top.png", "technic_machine_bottom.png", "technic_generator_side.png",
+              "technic_generator_side.png", "technic_generator_side.png", "technic_generator_front.png"},
+      paramtype2 = "facedir",
+      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_wood_defaults(),
+      on_construct = function(pos)
+                       local meta = minetest.env:get_meta(pos)
+                       meta:set_string("infotext", "Coal Electric Generator")
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_int("LV_EU_supply", 0)
+                       meta:set_int("LV_EU_from_fuel", 1) -- Signal to the switching station that this device burns some sort of fuel and needs special handling
+                       meta:set_int("burn_time", 0)
+                       meta:set_string("formspec", generator_formspec)
+                       local inv = meta:get_inventory()
+                       inv:set_size("src", 1)
                end,    
-       can_dig = function(pos,player)
-               local meta = minetest.env:get_meta(pos);
-               local inv = meta:get_inventory()
-               if not inv:is_empty("src") then
-                       return false
-               end
-               return true
+      can_dig = function(pos,player)
+                  local meta = minetest.env:get_meta(pos);
+                  local inv = meta:get_inventory()
+                  if not inv:is_empty("src") then
+                     minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                     return false
+                  else
+                     return true
+                  end
                end,
+   })
 
-})
-
-minetest.register_node("technic:generator_active", {
-       description = "Coal Driven Generator",
-       tiles = {"technic_generator_top.png", "technic_machine_bottom.png", "technic_generator_side.png",
-               "technic_generator_side.png", "technic_generator_side.png", "technic_generator_front_active.png"},
-       paramtype2 = "facedir",
-       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_wood_defaults(),
-       drop="technic:generator",
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=0;
-       burn_time=0;
-       can_dig = function(pos,player)
-               local meta = minetest.env:get_meta(pos);
-               local inv = meta:get_inventory()
-               if not inv:is_empty("src") then
-                       return false
-               end
-               return true
+minetest.register_node(
+   "technic:generator_active",
+   {
+      description = "Coal Driven Generator",
+      tiles = {"technic_generator_top.png", "technic_machine_bottom.png", "technic_generator_side.png",
+              "technic_generator_side.png", "technic_generator_side.png", "technic_generator_front_active.png"},
+      paramtype2 = "facedir",
+      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_wood_defaults(),
+      drop="technic:generator",
+      can_dig = function(pos,player)
+                  local meta = minetest.env:get_meta(pos);
+                  local inv = meta:get_inventory()
+                  if not inv:is_empty("src") then
+                     minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                     return false
+                  else
+                     return true
+                  end
                end,
+   })
 
-})
-minetest.register_abm({
-       nodenames = {"technic:generator","technic:generator_active"},
-       interval = 1,
-       chance = 1,
-       action = function(pos, node, active_object_count, active_object_count_wider)
-
-       local meta = minetest.env:get_meta(pos)
-       local burn_time= meta:get_float("burn_time")
-       local charge= meta:get_float("internal_EU_buffer")
-       local max_charge= meta:get_float("internal_EU_buffer_size")
-       local burn_charge=200
+minetest.register_abm(
+   {
+      nodenames = {"technic:generator","technic:generator_active"},
+      interval = 1,
+      chance   = 1,
+      action = function(pos, node, active_object_count, active_object_count_wider)
+                 local meta = minetest.env:get_meta(pos)
+                 local burn_time= meta:get_int("burn_time")
 
-       if burn_time>0 then
-               if charge+burn_charge>max_charge then
-               burn_charge=max_charge-charge
-               end
-               if burn_charge>0 then 
-               burn_time=burn_time-1
-               meta:set_float("burn_time",burn_time)
-               charge=charge+burn_charge
-               meta:set_float("internal_EU_buffer",charge)
-               end
-               
-       end
-       if burn_time==0 then
-               local inv = meta:get_inventory()
-               if inv:is_empty("src")==false  then 
-               local srcstack = inv:get_stack("src", 1)
-               src_item=srcstack:to_table()
-               if src_item["name"]== "default:coal_lump" then
-               srcstack:take_item()
-               inv:set_stack("src", 1, srcstack)
-               burn_time=16
-               meta:set_float("burn_time",burn_time)
-               hacky_swap_node (pos,"technic:generator_active") 
-               end
-               end
-       end
+                 -- If more to burn and the energy produced was used: produce some more
+                 if burn_time>0 then
+                    if meta:get_int("LV_EU_supply") == 0 then
+                       -- We did not use the power
+                       meta:set_int("LV_EU_supply", 200) -- Give 200EUs
+                    else
+                       burn_time = burn_time - 1
+                       meta:set_int("burn_time",burn_time)
+                    end
+                 end
 
-       local load = math.floor((charge/max_charge)*100)
-       local percent = math.floor((burn_time/16)*100)
-       meta:set_string("formspec",
-                               "invsize[8,9;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                               (load)..":technic_power_meter_fg.png]"..
-                               "label[0,0;Generator]"..
-                               "label[1,3;Power level]"..
-                               "list[current_name;src;3,1;1,1;]"..
-                               "image[4,1;1,1;default_furnace_fire_bg.png^[lowpart:"..
-                                               (percent)..":default_furnace_fire_fg.png]"..
-                               "list[current_player;main;0,5;8,4;]"
-                               )
+                 -- Burn another piece of coal
+                 if burn_time==0 then
+                    local inv = meta:get_inventory()
+                    if inv:is_empty("src") == false  then 
+                       local srcstack = inv:get_stack("src", 1)
+                       src_item=srcstack:to_table()
+                       if src_item["name"] == "default:coal_lump" then
+                          srcstack:take_item()
+                          inv:set_stack("src", 1, srcstack)
+                          burn_time=16
+                          meta:set_int("burn_time",burn_time)
+                          hacky_swap_node (pos,"technic:generator_active") 
+                          meta:set_int("LV_EU_supply", 200) -- Give 200EUs
+                       end
+                    end
+                 end
 
-       if burn_time==0 then
-               hacky_swap_node (pos,"technic:generator")
-       end
+                 local load = 8 -- math.floor((charge/max_charge)*100)
+                 local percent = math.floor((burn_time/16)*100)
+                 meta:set_string("formspec",
+                                 "invsize[8,9;]"..
+                                    "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
+                                    (load)..":technic_power_meter_fg.png]"..
+                                 "label[0,0;Generator]"..
+                                 "label[1,3;Power level]"..
+                                 "list[current_name;src;3,1;1,1;]"..
+                                 "image[4,1;1,1;default_furnace_fire_bg.png^[lowpart:"..
+                                 (percent)..":default_furnace_fire_fg.png]"..
+                              "list[current_player;main;0,5;8,4;]"
+                        )
 
-       end
-}) 
+                 if burn_time==0 then
+                    hacky_swap_node (pos,"technic:generator")
+                 end
+              end
+   })
 
-register_LV_machine ("technic:generator","PR")
-register_LV_machine ("technic:generator_active","PR")
+technic.register_LV_machine ("technic:generator","PR")
+technic.register_LV_machine ("technic:generator_active","PR")
index dccabf4f287c90fb19cdee41755b72ef47cb4582..5ba7a2369dea31fb85b9cebd06d6f110e473b4d0 100644 (file)
@@ -1,3 +1,7 @@
+-- A geothermal EU generator
+-- Using hot lava and water this device can create energy from steam
+-- The machine is only producing LV EUs and can thus not drive more advanced equipment
+-- The output is a little more than the coal burning generator (max 300EUs)
 minetest.register_alias("geothermal", "technic:geothermal")
 
 minetest.register_craft({
@@ -14,7 +18,7 @@ minetest.register_craftitem("technic:geothermal", {
        stack_max = 99,
 }) 
 
-geothermal_formspec =
+local geothermal_formspec =
        "invsize[8,4;]"..
        "image[1,1;1,2;technic_power_meter_bg.png]"..
        "label[0,0;Geothermal Generator]"..
@@ -22,117 +26,131 @@ geothermal_formspec =
        "list[current_player;main;0,5;8,4;]"
        
 
-minetest.register_node("technic:geothermal", {
-       description = "Geothermal Generator",
-       tiles = {"technic_geothermal_top.png", "technic_machine_bottom.png", "technic_geothermal_side.png",
-               "technic_geothermal_side.png", "technic_geothermal_side.png", "technic_geothermal_side.png"},
-       paramtype2 = "facedir",
-       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_wood_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=5000;
-       burn_time=0;
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_string("infotext", "Geothermal Generator")
-               meta:set_float("technic_power_machine", 1)
-               meta:set_float("internal_EU_buffer", 0)
-               meta:set_float("internal_EU_buffer_size", 2000)
-               meta:set_string("formspec", geothermal_formspec)        
-               end,    
+minetest.register_node(
+   "technic:geothermal",
+   {
+      description = "Geothermal Generator",
+      tiles = {"technic_geothermal_top.png", "technic_machine_bottom.png", "technic_geothermal_side.png",
+              "technic_geothermal_side.png", "technic_geothermal_side.png", "technic_geothermal_side.png"},
+      paramtype2 = "facedir",
+      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_wood_defaults(),
+      on_construct = function(pos)
+                       local meta = minetest.env:get_meta(pos)
+                       meta:set_string("infotext", "Geothermal Generator")
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_int("LV_EU_supply", 0)
+                       meta:set_string("formspec", geothermal_formspec)        
+                    end,       
+   })
 
-})
+minetest.register_node(
+   "technic:geothermal_active",
+   {
+      description = "Geothermal Generator",
+      tiles = {"technic_geothermal_top_active.png", "technic_machine_bottom.png", "technic_geothermal_side.png",
+              "technic_geothermal_side.png", "technic_geothermal_side.png", "technic_geothermal_side.png"},
+      paramtype2 = "facedir",
+      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_wood_defaults(),
+      drop="technic:geothermal",
+   })
 
-minetest.register_node("technic:geothermal_active", {
-       description = "Geothermal Generator",
-       tiles = {"technic_geothermal_top_active.png", "technic_machine_bottom.png", "technic_geothermal_side.png",
-               "technic_geothermal_side.png", "technic_geothermal_side.png", "technic_geothermal_side.png"},
-       paramtype2 = "facedir",
-       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_wood_defaults(),
-       drop="technic:geothermal",
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=0;
-})
+local check_node_around = function(pos)
+                            local node=minetest.env:get_node(pos)
+                            if node.name=="default:water_source" or node.name=="default:water_flowing" then return 1 end
+                            if node.name=="default:lava_source" or node.name=="default:lava_flowing" then return 2 end 
+                            return 0
+                         end
+
+minetest.register_abm(
+   {
+      nodenames = {"technic:geothermal","technic:geothermal_active"},
+      interval = 1,
+      chance   = 1,
+      action = function(pos, node, active_object_count, active_object_count_wider)
+                 local meta             = minetest.env:get_meta(pos)
+                 local water_nodes      = 0
+                 local lava_nodes       = 0
+                 local production_level = 0
+                 local eu_supply        = 0
 
-minetest.register_abm({
-       nodenames = {"technic:geothermal","technic:geothermal_active"},
-       interval = 1,
-       chance = 1,
-       action = function(pos, node, active_object_count, active_object_count_wider)
+                 -- Correct positioning is water on one side and lava on the other.
+                 -- The two cannot be adjacent because the lava the turns into obsidian or rock.
+                 -- To get to 100% production stack the water and lava one extra block down as well:
+                 --    WGL (W=Water, L=Lava, G=the generator, |=an LV cable)
+                  --    W|L
+                 pos.x=pos.x+1
+                 local check=check_node_around(pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 if check==2 then lava_nodes=lava_nodes+1 end
+                 pos.y=pos.y-1
+                 local check=check_node_around(pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 if check==2 then lava_nodes=lava_nodes+1 end
 
-       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 water_nodes = 0
-       local lava_nodes = 0
-       local production_level=0
-       local load_step=0
+                 pos.x=pos.x-2
+                 check=check_node_around(pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 if check==2 then lava_nodes=lava_nodes+1 end
+                 pos.y=pos.y+1
+                 check=check_node_around(pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 if check==2 then lava_nodes=lava_nodes+1 end
 
-       pos.x=pos.x+1
-       local check=check_node_around (pos)
-       if check==1 then water_nodes=water_nodes+1 end
-       if check==2 then lava_nodes=lava_nodes+1 end
-       pos.x=pos.x-2
-       check=check_node_around (pos)
-       if check==1 then water_nodes=water_nodes+1 end
-       if check==2 then lava_nodes=lava_nodes+1 end
-       pos.x=pos.x+1
-       pos.z=pos.z+1
-       check=check_node_around (pos)
-       if check==1 then water_nodes=water_nodes+1 end
-       if check==2 then lava_nodes=lava_nodes+1 end
-       pos.z=pos.z-2
-       check=check_node_around (pos)
-       if check==1 then water_nodes=water_nodes+1 end
-       if check==2 then lava_nodes=lava_nodes+1 end
-       pos.z=pos.z+1
+                 pos.x=pos.x+1
+                 pos.z=pos.z+1
+                 check=check_node_around(pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 if check==2 then lava_nodes=lava_nodes+1 end
+                 pos.y=pos.y-1
+                 check=check_node_around(pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 if check==2 then lava_nodes=lava_nodes+1 end
+
+                 pos.z=pos.z-2
+                 check=check_node_around(pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 if check==2 then lava_nodes=lava_nodes+1 end
+                 pos.y=pos.y+1
+                 check=check_node_around(pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 if check==2 then lava_nodes=lava_nodes+1 end
+
+                 -- Back to (0,0,0)
+                 pos.z=pos.z+1
        
-       if water_nodes==1 and lava_nodes==1 then production_level=50 load_step=30 end
-       if water_nodes==2 and lava_nodes==1 then production_level=75 load_step=45 end
-       if water_nodes==1 and lava_nodes==2 then production_level=75 load_step=45 end
-       if water_nodes==2 and lava_nodes==2 then production_level=100 load_step=60 end
-       if water_nodes==3 and lava_nodes==1 then production_level=25 load_step=15 end
-       if water_nodes==1 and lava_nodes==3 then production_level=25 load_step=15 end
+                 if water_nodes==1 and lava_nodes==1 then production_level =  25; eu_supply = 50 end
+                 if water_nodes==2 and lava_nodes==1 then production_level =  50; eu_supply = 100 end
+                 if water_nodes==1 and lava_nodes==2 then production_level =  75; eu_supply = 200 end
+                 if water_nodes==2 and lava_nodes==2 then production_level = 100; eu_supply = 300 end
 
-        if production_level>0 then
-               if charge+load_step>max_charge then
-               load_step=max_charge-charge
-               end
-               if load_step>0 then 
-               charge=charge+load_step
-               meta:set_float("internal_EU_buffer",charge)
-               end
-       end
+                 if production_level>0 then
+                    meta:set_int("LV_EU_supply", eu_supply)
+                 end
 
-       local load = math.floor((charge/max_charge)*100)
-       meta:set_string("formspec",
-                               "invsize[8,4;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                               (load)..":technic_power_meter_fg.png]"..
-                               "label[0,0;Geothermal Generator]"..
-                               "label[1,3;Power level]"..
-                               "label[4,0;Production at "..tostring(production_level).."%]"
-                               )
+                 local load = 1 -- math.floor((charge/max_charge)*100)
+                 meta:set_string("formspec",
+                                 "invsize[8,4;]"..
+                                    "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
+                                    (load)..":technic_power_meter_fg.png]"..
+                                 "label[0,0;Geothermal Generator]"..
+                                 "label[1,3;Power level]"..
+                                 "label[4,0;Production at "..tostring(production_level).."%]"
+                           )
                                
-       if production_level>0 and minetest.env:get_node(pos).name=="technic:geothermal" then
-               hacky_swap_node (pos,"technic:geothermal_active")
-               return
-       end
-       if production_level==0 then hacky_swap_node (pos,"technic:geothermal") end
-end
-}) 
-
-function check_node_around (pos)
-local node=minetest.env:get_node(pos)
-if node.name=="default:water_source" or node.name=="default:water_flowing"  then return 1 end
-if node.name=="default:lava_source" or node.name=="default:lava_flowing"  then return 2 end    
-return 0
-end
+                 if production_level>0 and minetest.env:get_node(pos).name=="technic:geothermal" then
+                    hacky_swap_node (pos,"technic:geothermal_active")
+                    return
+                 end
+                 if production_level==0 then
+                    hacky_swap_node (pos,"technic:geothermal")
+                    meta:set_int("LV_EU_supply", 0)
+                 end
+              end
+   }) 
 
-register_LV_machine ("technic:geothermal","PR")
-register_LV_machine ("technic:geothermal_active","PR")
+technic.register_LV_machine ("technic:geothermal","PR")
+technic.register_LV_machine ("technic:geothermal_active","PR")
index 07baa05e228e11dec5107414e85fd1e6bd5f63d4..8b41184028628338ce80bf275e37f8e61addd9bc 100644 (file)
-grinder_recipes ={}
-
-registered_grinder_recipes_count=1
-
-function register_grinder_recipe (string1,string2)
-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 unified_inventory then
-       unified_inventory.register_craft({
-       type = "grinding",
-       output = string2,
-       items = {string1},
-       width = 0,
-       })
-       end
-end
-
-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: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("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: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")
+technic.grinder_recipes ={}
+
+technic.register_grinder_recipe = function(src, dst)
+                                  technic.grinder_recipes[src] = dst
+                                  if unified_inventory then
+                                     unified_inventory.register_craft(
+                                        {
+                                           type = "grinding",
+                                           output = dst,
+                                           items = {src},
+                                           width = 0,
+                                        })
+                                  end
+                               end
+
+-- Receive an ItemStack of result by an ItemStack input
+technic.get_grinder_recipe = function(itemstack)
+                               local src_item  = itemstack:to_table()
+                               if src_item == nil then
+                                  return nil
+                               end
+                               local item_name = src_item["name"]
+                               if technic.grinder_recipes[item_name] then
+                                  return ItemStack(technic.grinder_recipes[item_name])
+                               else
+                                  return nil
+                               end
+                            end
+
+
+technic.register_grinder_recipe("default:stone","default:sand")
+technic.register_grinder_recipe("default:cobble","default:gravel")
+technic.register_grinder_recipe("default:gravel","default:dirt")
+technic.register_grinder_recipe("default:desert_stone","default:desert_sand")
+technic.register_grinder_recipe("default:iron_lump","technic:iron_dust 2")
+technic.register_grinder_recipe("default:steel_ingot","technic:iron_dust 1")
+technic.register_grinder_recipe("default:coal_lump","technic:coal_dust 2")
+technic.register_grinder_recipe("default:copper_lump","technic:copper_dust 2")
+technic.register_grinder_recipe("default:copper_ingot","technic:copper_dust 1")
+technic.register_grinder_recipe("default:gold_lump","technic:gold_dust 2")
+technic.register_grinder_recipe("default:gold_ingot","technic:gold_dust 1")
+--technic.register_grinder_recipe("default:bronze_ingot","technic:bronze_dust 1")  -- Dust does not exist yet
+--technic.register_grinder_recipe("home_decor:brass_ingot","technic:brass_dust 1") -- needs check for the mod
+technic.register_grinder_recipe("moreores:tin_lump","technic:tin_dust 2")
+technic.register_grinder_recipe("moreores:tin_ingot","technic:tin_dust 1")
+technic.register_grinder_recipe("moreores:silver_lump","technic:silver_dust 2")
+technic.register_grinder_recipe("moreores:silver_ingot","technic:silver_dust 1")
+technic.register_grinder_recipe("moreores:mithril_lump","technic:mithril_dust 2")
+technic.register_grinder_recipe("moreores:mithril_ingot","technic:mithril_dust 1")
+technic.register_grinder_recipe("technic:chromium_lump","technic:chromium_dust 2")
+technic.register_grinder_recipe("technic:chromium_ingot","technic:chromium_dust 1")
+technic.register_grinder_recipe("technic:stainless_steel_ingot","stainless_steel_dust 1")
+technic.register_grinder_recipe("technic:brass_ingot","technic:brass_dust 1")
+technic.register_grinder_recipe("technic:zinc_lump","technic:zinc_dust 2")
+technic.register_grinder_recipe("technic:zinc_ingot","technic:zinc_dust 1")
+technic.register_grinder_recipe("technic:coal_dust","dye:black 2")
+technic.register_grinder_recipe("default:cactus","dye:green 2")
+technic.register_grinder_recipe("default:dry_shrub","dye:brown 2")
+technic.register_grinder_recipe("flowers:flower_geranium","dye:blue 2")
+technic.register_grinder_recipe("flowers:flower_dandelion_white","dye:white 2")
+technic.register_grinder_recipe("flowers:flower_dandelion_yellow","dye:yellow 2")
+technic.register_grinder_recipe("flowers:flower_tulip","dye:orange 2")
+technic.register_grinder_recipe("flowers:flower_rose","dye:red 2")
+technic.register_grinder_recipe("flowers:flower_viola","dye:violet 2")
 
 minetest.register_craftitem( "technic:coal_dust", {
-       description = "Coal Dust",
-       inventory_image = "technic_coal_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Coal Dust",
+                               inventory_image = "technic_coal_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 
 minetest.register_craftitem( "technic:iron_dust", {
-       description = "Iron Dust",
-       inventory_image = "technic_iron_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Iron Dust",
+                               inventory_image = "technic_iron_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 
 minetest.register_craft({
-    type = "cooking",
-    output = "default:steel_ingot",
-    recipe = "technic:iron_dust",
-})
+                          type = "cooking",
+                          output = "default:steel_ingot",
+                          recipe = "technic:iron_dust",
+                       })
 
 minetest.register_craftitem( "technic:copper_dust", {
-       description = "Copper Dust",
-       inventory_image = "technic_copper_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Copper Dust",
+                               inventory_image = "technic_copper_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 minetest.register_craft({
-    type = "cooking",
-    output = "moreores:copper_ingot",
-    recipe = "technic:copper_dust",
-})
+                          type = "cooking",
+                          output = "moreores:copper_ingot",
+                          recipe = "technic:copper_dust",
+                       })
 
 minetest.register_craftitem( "technic:tin_dust", {
-       description = "Tin Dust",
-       inventory_image = "technic_tin_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Tin Dust",
+                               inventory_image = "technic_tin_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 minetest.register_craft({
-    type = "cooking",
-    output = "moreores:tin_ingot",
-    recipe = "technic:tin_dust",
-})
+                          type = "cooking",
+                          output = "moreores:tin_ingot",
+                          recipe = "technic:tin_dust",
+                       })
 
 minetest.register_craftitem( "technic:silver_dust", {
-       description = "Silver Dust",
-       inventory_image = "technic_silver_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Silver Dust",
+                               inventory_image = "technic_silver_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 minetest.register_craft({
-    type = "cooking",
-    output = "moreores:silver_ingot",
-    recipe = "technic:silver_dust",
-})
+                          type = "cooking",
+                          output = "moreores:silver_ingot",
+                          recipe = "technic:silver_dust",
+                       })
 
 minetest.register_craftitem( "technic:gold_dust", {
-       description = "Gold Dust",
-       inventory_image = "technic_gold_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Gold Dust",
+                               inventory_image = "technic_gold_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 minetest.register_craft({
-    type = "cooking",
-    output = "moreores:gold_ingot",
-    recipe = "technic:gold_dust",
-})
+                          type = "cooking",
+                          output = "moreores:gold_ingot",
+                          recipe = "technic:gold_dust",
+                       })
 
 minetest.register_craftitem( "technic:mithril_dust", {
-       description = "Mithril Dust",
-       inventory_image = "technic_mithril_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Mithril Dust",
+                               inventory_image = "technic_mithril_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 minetest.register_craft({
-    type = "cooking",
-    output = "moreores:mithril_ingot",
-    recipe = "technic:mithril_dust",
-})
+                          type = "cooking",
+                          output = "moreores:mithril_ingot",
+                          recipe = "technic:mithril_dust",
+                       })
 
 minetest.register_craftitem( "technic:chromium_dust", {
-       description = "Chromium Dust",
-       inventory_image = "technic_chromium_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Chromium Dust",
+                               inventory_image = "technic_chromium_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 minetest.register_craft({
-    type = "cooking",
-    output = "technic:chromium_ingot",
-    recipe = "technic:chromium_dust",
-})
+                          type = "cooking",
+                          output = "technic:chromium_ingot",
+                          recipe = "technic:chromium_dust",
+                       })
 
 minetest.register_craftitem( "technic:bronze_dust", {
-       description = "Bronze Dust",
-       inventory_image = "technic_bronze_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Bronze Dust",
+                               inventory_image = "technic_bronze_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 minetest.register_craft({
-    type = "cooking",
-    output = "moreores:bronze_ingot",
-    recipe = "technic:bronze_dust",
-})
+                          type = "cooking",
+                          output = "moreores:bronze_ingot",
+                          recipe = "technic:bronze_dust",
+                       })
 
 minetest.register_craftitem( "technic:brass_dust", {
-       description = "Brass Dust",
-       inventory_image = "technic_brass_dust.png",
-       on_place_on_ground = minetest.craftitem_place_item,
-       })
+                               description = "Brass Dust",
+                               inventory_image = "technic_brass_dust.png",
+                               on_place_on_ground = minetest.craftitem_place_item,
+                            })
 minetest.register_craft({
-    type = "cooking",
-    output = "technic:brass_ingot",
-    recipe = "technic:brass_dust",
-})
+                          type = "cooking",
+                          output = "technic:brass_ingot",
+                          recipe = "technic:brass_dust",
+                       })
 
 minetest.register_craftitem( "technic:stainless_steel_dust", {
-       description = "Stainless Steel Dust",
-       inventory_image = "technic_stainless_steel_dust.png",
-       })
+                               description = "Stainless Steel Dust",
+                               inventory_image = "technic_stainless_steel_dust.png",
+                            })
 
 minetest.register_craft({
-    type = "cooking",
-    output = "technic:stainless_steel_ingot",
-    recipe = "technic:stainless_steel_dust",
-})
+                          type = "cooking",
+                          output = "technic:stainless_steel_ingot",
+                          recipe = "technic:stainless_steel_dust",
+                       })
 
 minetest.register_craftitem( "technic:zinc_dust", {
-       description = "Zinc Dust",
-       inventory_image = "technic_zinc_dust.png",
-       })
+                               description = "Zinc Dust",
+                               inventory_image = "technic_zinc_dust.png",
+                            })
 
 minetest.register_craft({
-    type = "cooking",
-    output = "technic:zinc_ingot",
-    recipe = "technic:zinc_dust",
-})
+                          type = "cooking",
+                          output = "technic:zinc_ingot",
+                          recipe = "technic:zinc_dust",
+                       })
 
 minetest.register_alias("grinder", "technic:grinder")
 minetest.register_craft({
-       output = 'technic:grinder',
-       recipe = {
-               {'default:desert_stone', 'default:desert_stone', 'default:desert_stone'},
-               {'default:desert_stone', 'default:diamond', 'default:desert_stone'},
-               {'default:stone', 'moreores:copper_ingot', 'default:stone'},
-       }
-})
+                          output = 'technic:grinder',
+                          recipe = {
+                             {'default:desert_stone', 'default:desert_stone', 'default:desert_stone'},
+                             {'default:desert_stone', 'default:diamond', 'default:desert_stone'},
+                             {'default:stone', 'moreores:copper_ingot', 'default:stone'},
+                          }
+                       })
 
 minetest.register_craftitem("technic:grinder", {
-       description = "Grinder",
-       stack_max = 99,
-})
-
-grinder_formspec =
-       "invsize[8,9;]"..
-       "image[1,1;1,2;technic_power_meter_bg.png]"..
-       "label[0,0;Grinder]"..
-       "label[1,3;Power level]"..
-       "list[current_name;src;3,1;1,1;]"..
-       "list[current_name;dst;5,1;2,2;]"..
-       "list[current_player;main;0,5;8,4;]"
-
-
-minetest.register_node("technic:grinder", {
-       description = "Grinder",
-       tiles = {"technic_lv_grinder_top.png", "technic_lv_grinder_bottom.png", "technic_lv_grinder_side.png",
-               "technic_lv_grinder_side.png", "technic_lv_grinder_side.png", "technic_lv_grinder_front.png"},
-       paramtype2 = "facedir",
-       groups = {cracky=2},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_wood_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=5000;
-       grind_time=0;
-       grinded = nil;
-       src_time = 0;
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_string("infotext", "Grinder")
-               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", grinder_formspec)
-               meta:set_float("grind_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") then
-                       return false
-               end
-               if not inv:is_empty("dst") then
-                       return false
-               end
-               return true
+                              description = "Grinder",
+                              stack_max = 99,
+                           })
+
+local grinder_formspec =
+   "invsize[8,9;]"..
+   "label[0,0;Grinder]"..
+   "list[current_name;src;3,1;1,1;]"..
+   "list[current_name;dst;5,1;2,2;]"..
+   "list[current_player;main;0,5;8,4;]"
+
+minetest.register_node(
+   "technic:grinder",
+   {
+      description = "Grinder",
+      tiles = {"technic_lv_grinder_top.png", "technic_lv_grinder_bottom.png", "technic_lv_grinder_side.png",
+              "technic_lv_grinder_side.png", "technic_lv_grinder_side.png", "technic_lv_grinder_front.png"},
+      paramtype2 = "facedir",
+      groups = {cracky=2},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_wood_defaults(),
+      on_construct = function(pos)
+                       local meta = minetest.env:get_meta(pos)
+                       meta:set_string("infotext", "Grinder")
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_string("formspec", grinder_formspec)
+                       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(), "Machine cannot be removed because it is not empty");
+                     return false
+                  else
+                     return true
+                  end
                end,
-})
-
-minetest.register_node("technic:grinder_active", {
-       description = "Grinder",
-       tiles = {"technic_lv_grinder_top.png", "technic_lv_grinder_bottom.png", "technic_lv_grinder_side.png",
-               "technic_lv_grinder_side.png", "technic_lv_grinder_side.png", "technic_lv_grinder_front_active.png"},
-       paramtype2 = "facedir",
-       groups = {cracky=2,not_in_creative_inventory=1},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_wood_defaults(),
-       can_dig = function(pos,player)
-               local meta = minetest.env:get_meta(pos);
-               local inv = meta:get_inventory()
-               if not inv:is_empty("src") then
-                       return false
-               end
-               if not inv:is_empty("dst") then
-                       return false
-               end
-               return true
+   })
+
+minetest.register_node(
+   "technic:grinder_active",
+   {
+      description = "Grinder",
+      tiles = {"technic_lv_grinder_top.png", "technic_lv_grinder_bottom.png", "technic_lv_grinder_side.png",
+              "technic_lv_grinder_side.png", "technic_lv_grinder_side.png", "technic_lv_grinder_front_active.png"},
+      paramtype2 = "facedir",
+      groups = {cracky=2,not_in_creative_inventory=1},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_wood_defaults(),
+      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(), "Machine cannot be removed because it is not empty");
+                     return false
+                  else
+                     return true
+                  end
                end,
-})
-
-minetest.register_abm({
-       nodenames = {"technic:grinder","technic:grinder_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 grind_cost=200
-
-       local load = math.floor((charge/max_charge)*100)
-       meta:set_string("formspec",
-                               "invsize[8,9;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                               (load)..":technic_power_meter_fg.png]"..
-                               "label[0,0;Grinder]"..
-                               "label[1,3;Power level]"..
-                               "list[current_name;src;3,1;1,1;]"..
-                               "list[current_name;dst;5,1;2,2;]"..
-                               "list[current_player;main;0,5;8,4;]"
-                               )
-
-               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 (meta:get_float("grinder_on") == 1) then
-                       if charge>=grind_cost then
-                       charge=charge-grind_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("grind_time") then
-                               -- check if there's room for output in "dst" list
-                               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)
-                                       -- take stuff from "src" list
-                                       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
-                               else
-                                       print("Grinder inventory full!")
-                               end
-                               meta:set_float("src_time", 0)
-                       end
-                       end
-               end
-               if (meta:get_float("grinder_on")==0) then
-               local grinded=nil
-               if not inv:is_empty("src") then
-                       grinded = get_grinded_item (inv:get_stack("src", 1))
-                       if grinded then
-                               meta:set_float("grinder_on",1)
-                               hacky_swap_node(pos,"technic:grinder_active")
-                               meta:set_string("infotext", "Grinder Active")
-                               grind_time=4
-                               meta:set_float("grind_time",grind_time)
-                               meta:set_float("src_time", 0)
-                               return
-                       end
-                       else
-                               hacky_swap_node(pos,"technic:grinder")
-                               meta:set_string("infotext", "Grinder Inactive")
-               end
-               end
-       end
-})
-
-function get_grinded_item (items)
-new_item =nil
-src_item=items:to_table()
-item_name=src_item["name"]
-
-local counter=registered_grinder_recipes_count-1
-for i=1, counter,1 do
-       if      grinder_recipes[i].src_name==item_name then return ItemStack(grinder_recipes[i].dst_name) end
-end
-return nil
-end
-
-register_LV_machine ("technic:grinder","RE")
-register_LV_machine ("technic:grinder_active","RE")
+   })
+
+minetest.register_abm(
+   { nodenames = {"technic:grinder","technic:grinder_active"},
+     interval = 1,
+     chance   = 1,
+     action = function(pos, node, active_object_count, active_object_count_wider)
+                -- Run a machine through its states. Takes the same arguments as the ABM action
+                -- and adds the machine's states and any extra data which is needed by the machine.
+                -- A machine is characterized by running through a set number of states (usually 2:
+                -- Idle and active) in some order. A state decides when to move to the next one
+                -- and the machine only changes state if it is powered correctly.
+                -- The machine will automatically shut down if disconnected from power in some fashion.
+                local meta         = minetest.env:get_meta(pos)
+                local eu_input     = meta:get_int("LV_EU_input")
+                local state        = meta:get_int("state")
+                local next_state   = state
+
+                -- Machine information
+                local machine_name         = "Grinder"
+                local machine_node         = "technic:grinder"
+                local machine_state_demand = { 50, 300 }
+                        
+                -- Setup meta data if it does not exist. state is used as an indicator of this
+                if state == 0 then
+                   meta:set_int("state", 1)
+                   meta:set_int("LV_EU_demand", machine_state_demand[1])
+                   meta:set_int("LV_EU_input", 0)
+                   return
+                end
+                        
+                -- Power off automatically if no longer connected to a switching station
+                technic.switching_station_timeout_count(pos, "LV")
+                        
+                -- State machine
+                if eu_input == 0 then
+                   -- unpowered - go idle
+                   hacky_swap_node(pos, machine_node)
+                   meta:set_string("infotext", machine_name.." Unpowered")
+                   next_state = 1
+                elseif eu_input == machine_state_demand[state] then
+                   -- Powered - do the state specific actions
+                           
+                   local inv    = meta:get_inventory()
+                   local empty  = inv:is_empty("src")
+
+                   if state == 1 then
+                      hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Idle")
+
+                      local result = technic.get_grinder_recipe(inv:get_stack("src", 1))
+                      if not empty and result and inv:room_for_item("dst",result) then
+                         meta:set_int("src_time", 0)
+                         next_state = 2
+                      end
+
+                   elseif state == 2 then
+                      hacky_swap_node(pos, machine_node.."_active")
+                      meta:set_string("infotext", machine_name.." Active")
+
+                      if empty then
+                         next_state = 1
+                      else
+                         meta:set_int("src_time", meta:get_int("src_time") + 1)
+                         if meta:get_int("src_time") == 4 then -- 4 ticks per output
+                            -- check if there's room for output in "dst" list
+                            local result = technic.get_grinder_recipe(inv:get_stack("src", 1))
+
+                            meta:set_int("src_time", 0)
+                            if inv:room_for_item("dst",result) then
+                               -- take stuff from "src" list
+                               srcstack = inv:get_stack("src", 1)
+                               srcstack:take_item()
+                               inv:set_stack("src", 1, srcstack)
+                               -- Put result in "dst" list
+                               inv:add_item("dst", result)
+                            else
+                               -- all full: go idle
+                               next_state = 1
+                            end
+                         end
+                      end
+                   end
+                end
+                -- Change state?
+                if next_state ~= state then
+                   meta:set_int("LV_EU_demand", machine_state_demand[next_state])
+                   meta:set_int("state", next_state)
+                end
+             end
+  })
+
+technic.register_LV_machine ("technic:grinder","RE")
+technic.register_LV_machine ("technic:grinder_active","RE")
index 0c58c98732e5f93eb051459c8bfc6cff2c1c35cf..6f603b38ae239dc66d113e633ca19d76c49564a2 100644 (file)
@@ -1,8 +1,8 @@
-register_grinder_recipe("gloopores:alatro_lump","technic:alatro_dust 2")
-register_grinder_recipe("gloopores:kalite_lump","technic:kalite_dust 2")
-register_grinder_recipe("gloopores:arol_lump","technic:arol_dust 2")
-register_grinder_recipe("gloopores:talinite_lump","technic:talinite_dust 2")
-register_grinder_recipe("gloopores:akalin_lump","technic:akalin_dust 2")
+technic.register_grinder_recipe("gloopores:alatro_lump","technic:alatro_dust 2")
+technic.register_grinder_recipe("gloopores:kalite_lump","technic:kalite_dust 2")
+technic.register_grinder_recipe("gloopores:arol_lump","technic:arol_dust 2")
+technic.register_grinder_recipe("gloopores:talinite_lump","technic:talinite_dust 2")
+technic.register_grinder_recipe("gloopores:akalin_lump","technic:akalin_dust 2")
 Â 
 minetest.register_craftitem("technic:alatro_dust", {
 Â  Â  Â  Â  description = "Alatro Dust",
index 6dd7eac598228b238e0aa244fe6223b03a6a5026..abe0439241d932130e5ec9fc60246f357a4f1c62 100644 (file)
@@ -4,7 +4,13 @@
 
 technic = {}
 
-modpath=minetest.get_modpath("technic")
+technic.dprint = function(string)
+                   if technic.DBG == 1 then
+                      print(string)
+                   end
+                end
+
+local modpath=minetest.get_modpath("technic")
 
 --Read technic config file
 dofile(modpath.."/config.lua")
@@ -14,19 +20,26 @@ dofile(modpath.."/helpers.lua")
 --items 
 dofile(modpath.."/items.lua")
 
+-- Register functions
+dofile(modpath.."/register_machine_and_tool.lua")
+dofile(modpath.."/alloy_furnaces_commons.lua") -- Idea: Let the LV, MV, HV version of the furnace support different alloys
+
+-- Switching station LV,MV,HV
+dofile(modpath.."/switching_station.lua")
+dofile(modpath.."/supply_converter.lua")
+
 --LV machines
 dofile(modpath.."/wires.lua")
 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.."/generator.lua")
 dofile(modpath.."/electric_furnace.lua")
 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")
@@ -36,20 +49,18 @@ dofile(modpath.."/cnc_nodes.lua")
 dofile(modpath.."/wires_mv.lua")
 dofile(modpath.."/battery_box_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")
--- These two are a concept study: Supplying appliances with inductive coupled power:
--- lighting and associated textures is taken directly from VanessaE's homedecor and made electric.
+--dofile(modpath.."/forcefield.lua")
+---- The power radiator supplies appliances with inductive coupled power:
+---- lighting and associated textures is taken directly from VanessaE's homedecor and made electric.
 dofile(modpath.."/power_radiator.lua")
 dofile(modpath.."/lighting.lua")
-
---HV machines
+--
+----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 technic.config:getBool("enable_mining_drill") then dofile(modpath.."/mining_drill.lua") end
@@ -59,8 +70,8 @@ dofile(modpath.."/cans.lua")
 dofile(modpath.."/chainsaw.lua")
 dofile(modpath.."/tree_tap.lua")
 dofile(modpath.."/sonic_screwdriver.lua")
-
--- mesecons and tubes related
+--
+---- mesecons and tubes related
 dofile(modpath.."/injector.lua")
 dofile(modpath.."/node_breaker.lua")
 dofile(modpath.."/deployer.lua")
@@ -68,24 +79,23 @@ dofile(modpath.."/constructor.lua")
 dofile(modpath.."/frames.lua")
 
 function has_locked_chest_privilege(meta, player)
-       if player:get_player_name() ~= meta:get_string("owner") then
-               return false
-       end
-       return true
+   if player:get_player_name() ~= meta:get_string("owner") then
+      return false
+   end
+   return true
 end
 
 
+-- Swap nodes out. Return the node name.
 function hacky_swap_node(pos,name)
-       local node = minetest.env:get_node(pos)
-       local meta = minetest.env:get_meta(pos)
-       local meta0 = meta:to_table()
-       if node.name == name then
-               return nil
-       end
-       node.name = name
-       local meta0 = meta:to_table()
-       minetest.env:set_node(pos,node)
-       meta = minetest.env:get_meta(pos)
-       meta:from_table(meta0)
-       return 1
+   local node = minetest.env:get_node(pos)
+   if node.name ~= name then
+      local meta = minetest.env:get_meta(pos)
+      local meta0 = meta:to_table()
+      node.name = name
+      minetest.env:set_node(pos,node)
+      meta = minetest.env:get_meta(pos)
+      meta:from_table(meta0)
+   end
+   return node.name
 end
index 5aab4c39ad280b49968c6dfe474c79260be0cf7a..1d4b45f8008ae1dbb177a94cfaf43fc0457718e4 100644 (file)
@@ -48,7 +48,7 @@ end
 local dirs1 = { 20, 23, 22, 21 }
 local dirs2 = { 9, 18, 7, 12 }
 
-function technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
+local technic_homedecor_rotate_and_place = function(itemstack, placer, pointed_thing)
        if not technic_homedecor_node_is_owned(pointed_thing.under, placer) 
           and not technic_homedecor_node_is_owned(pointed_thing.above, placer) then
                local node = minetest.env:get_node(pointed_thing.under)
@@ -128,14 +128,10 @@ minetest.register_node('technic:homedecor_glowlight_half_yellow', {
                return itemstack
             end,
        on_construct = function(pos)
-                         print("Hello")
-                         technic_inductive_on_construct(pos, 100, "Yellow Glowlight (thick)")
-                         print("Hello2")
+                         technic.inductive_on_construct(pos, 100, "Yellow Glowlight (thick)")
                       end,
        on_punch = function(pos, node, puncher)
-                     print("Punch")
-                     technic_inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_half_yellow_active")
-                     print("Punch2")
+                     technic.inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_half_yellow_active")
                   end
 })
 
@@ -173,10 +169,10 @@ minetest.register_node('technic:homedecor_glowlight_half_yellow_active', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 100, "Yellow Glowlight (thick)")
+                         technic.inductive_on_construct(pos, 100, "Yellow Glowlight (thick)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_half_yellow")
+                     technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_half_yellow")
                   end
 })
 
@@ -213,10 +209,10 @@ minetest.register_node('technic:homedecor_glowlight_quarter_yellow', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 100, "Yellow Glowlight (thin)")
+                         technic.inductive_on_construct(pos, 100, "Yellow Glowlight (thin)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_quarter_yellow_active")
+                     technic.inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_quarter_yellow_active")
                   end
 })
 
@@ -254,10 +250,10 @@ minetest.register_node('technic:homedecor_glowlight_quarter_yellow_active', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 100, "Yellow Glowlight (thin)")
+                         technic.inductive_on_construct(pos, 100, "Yellow Glowlight (thin)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_quarter_yellow")
+                     technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_quarter_yellow")
                   end
 })
 
@@ -295,10 +291,10 @@ minetest.register_node('technic:homedecor_glowlight_half_white', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 100, "White Glowlight (thick)")
+                         technic.inductive_on_construct(pos, 100, "White Glowlight (thick)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_half_white_active")
+                     technic.inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_half_white_active")
                   end
 })
 
@@ -336,10 +332,10 @@ minetest.register_node('technic:homedecor_glowlight_half_white_active', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 100, "White Glowlight (thick)")
+                         technic.inductive_on_construct(pos, 100, "White Glowlight (thick)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_half_white")
+                     technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_half_white")
                   end
 })
 
@@ -376,10 +372,10 @@ minetest.register_node('technic:homedecor_glowlight_quarter_white', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 100, "White Glowlight (thin)")
+                         technic.inductive_on_construct(pos, 100, "White Glowlight (thin)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_quarter_white_active")
+                     technic.inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_quarter_white_active")
                   end
 })
 
@@ -417,10 +413,10 @@ minetest.register_node('technic:homedecor_glowlight_quarter_white_active', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 100, "White Glowlight (thin)")
+                         technic.inductive_on_construct(pos, 100, "White Glowlight (thin)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_quarter_white")
+                     technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_quarter_white")
                   end
 })
 
@@ -457,10 +453,10 @@ minetest.register_node('technic:homedecor_glowlight_small_cube_yellow', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 50, "Yellow Glowlight (small cube)")
+                         technic.inductive_on_construct(pos, 50, "Yellow Glowlight (small cube)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_off(pos, 50, "technic:homedecor_glowlight_small_cube_yellow_active")
+                     technic.inductive_on_punch_off(pos, 50, "technic:homedecor_glowlight_small_cube_yellow_active")
                   end
 })
 
@@ -498,10 +494,10 @@ minetest.register_node('technic:homedecor_glowlight_small_cube_yellow_active', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 50, "Yellow Glowlight (small cube)")
+                         technic.inductive_on_construct(pos, 50, "Yellow Glowlight (small cube)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_small_cube_yellow")
+                     technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_small_cube_yellow")
                   end
 })
 
@@ -538,10 +534,10 @@ minetest.register_node('technic:homedecor_glowlight_small_cube_white', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 50, "White Glowlight (small cube)")
+                         technic.inductive_on_construct(pos, 50, "White Glowlight (small cube)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_off(pos, 50, "technic:homedecor_glowlight_small_cube_white_active")
+                     technic.inductive_on_punch_off(pos, 50, "technic:homedecor_glowlight_small_cube_white_active")
                   end
 })
 
@@ -579,16 +575,16 @@ minetest.register_node('technic:homedecor_glowlight_small_cube_white_active', {
                return itemstack
             end,
        on_construct = function(pos)
-                         technic_inductive_on_construct(pos, 50, "White Glowlight (small cube)")
+                         technic.inductive_on_construct(pos, 50, "White Glowlight (small cube)")
                       end,
        on_punch = function(pos, node, puncher)
-                     technic_inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_small_cube_white")
+                     technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_small_cube_white")
                   end
 })
 
-register_inductive_machine("technic:homedecor_glowlight_half_yellow")
-register_inductive_machine("technic:homedecor_glowlight_half_white")
-register_inductive_machine("technic:homedecor_glowlight_quarter_yellow")
-register_inductive_machine("technic:homedecor_glowlight_quarter_white")
-register_inductive_machine("technic:homedecor_glowlight_small_cube_yellow")
-register_inductive_machine("technic:homedecor_glowlight_small_cube_white")
+technic.register_inductive_machine("technic:homedecor_glowlight_half_yellow")
+technic.register_inductive_machine("technic:homedecor_glowlight_half_white")
+technic.register_inductive_machine("technic:homedecor_glowlight_quarter_yellow")
+technic.register_inductive_machine("technic:homedecor_glowlight_quarter_white")
+technic.register_inductive_machine("technic:homedecor_glowlight_small_cube_yellow")
+technic.register_inductive_machine("technic:homedecor_glowlight_small_cube_white")
index 33a8e5a70590055594a49d15910c1ef7182def9d..4a50f2f407532543a85d472ee7cd5b3c6e6d3f91 100644 (file)
@@ -1,9 +1,9 @@
-mining_drill_max_charge=60000
-mining_drill_mk2_max_charge=240000
-mining_drill_mk3_max_charge=960000
-mining_drill_power_usage=200
-mining_drill_mk2_power_usage=600
-mining_drill_mk3_power_usage=1800
+local mining_drill_max_charge=60000
+local mining_drill_mk2_max_charge=240000
+local mining_drill_mk3_max_charge=960000
+local mining_drill_power_usage=200
+local mining_drill_mk2_power_usage=600
+local mining_drill_mk3_power_usage=1800
 
 minetest.register_craft({
        output = 'technic:mining_drill',
@@ -210,7 +210,7 @@ function drill_dig_it4 (pos,player)
        drill_dig_it0 (pos,player)
 end
 
-register_power_tool ("technic:mining_drill",mining_drill_max_charge)
+technic.register_MV_power_tool ("technic:mining_drill",mining_drill_max_charge)
 minetest.register_tool("technic:mining_drill", {
        description = "Mining Drill Mk1",
        inventory_image = "technic_mining_drill.png",
@@ -227,7 +227,7 @@ minetest.register_tool("technic:mining_drill", {
                        charge =charge-mining_drill_power_usage;
                        meta["charge"]=charge
                        item["metadata"]=set_item_meta(meta)
-                       set_RE_wear(item,charge,mining_drill_max_charge)
+                       technic.set_RE_wear(item,charge,mining_drill_max_charge)
                        itemstack:replace(item)
                        end
                return itemstack
@@ -243,10 +243,10 @@ minetest.register_tool("technic:mining_drill_mk2", {
        return itemstack
        end,
 })
-register_power_tool ("technic:mining_drill_mk2",mining_drill_mk2_max_charge)
+technic.register_HV_power_tool ("technic:mining_drill_mk2",mining_drill_mk2_max_charge)
 
 for i=1,4,1 do
-register_power_tool ("technic:mining_drill_mk2_"..i,mining_drill_mk2_max_charge)
+technic.register_HV_power_tool ("technic:mining_drill_mk2_"..i,mining_drill_mk2_max_charge)
 minetest.register_tool("technic:mining_drill_mk2_"..i, {
        description = "Mining Drill Mk2 in Mode "..i,
        inventory_image = "technic_mining_drill_mk2.png^technic_tool_mode"..i..".png",
@@ -267,10 +267,10 @@ minetest.register_tool("technic:mining_drill_mk3", {
        return itemstack
        end,
 })
-register_power_tool ("technic:mining_drill_mk3",mining_drill_mk3_max_charge)
+technic.register_HV_power_tool ("technic:mining_drill_mk3",mining_drill_mk3_max_charge)
 
 for i=1,5,1 do
-register_power_tool ("technic:mining_drill_mk3_"..i,mining_drill_mk3_max_charge)
+technic.register_HV_power_tool ("technic:mining_drill_mk3_"..i,mining_drill_mk3_max_charge)
 minetest.register_tool("technic:mining_drill_mk3_"..i, {
        description = "Mining Drill Mk3 in Mode "..i,
        inventory_image = "technic_mining_drill_mk3.png^technic_tool_mode"..i..".png",
@@ -299,7 +299,7 @@ function mining_drill_mk2_handler (itemstack,user,pointed_thing)
                if charge<0 then charge=0 end
                meta["charge"]=charge
                item["metadata"]=set_item_meta(meta)
-               set_RE_wear(item,charge,mining_drill_mk2_max_charge)
+               technic.set_RE_wear(item,charge,mining_drill_mk2_max_charge)
                itemstack:replace(item)
        end
        return itemstack
@@ -321,7 +321,7 @@ function mining_drill_mk3_handler (itemstack,user,pointed_thing)
                if charge<0 then charge=0 end
                meta["charge"]=charge
                item["metadata"]=set_item_meta(meta)
-               set_RE_wear(item,charge,mining_drill_mk3_max_charge)
+               technic.set_RE_wear(item,charge,mining_drill_mk3_max_charge)
                itemstack:replace(item)
        end
        return itemstack
index 5bafb6cb04b960a5165e4c11eb53cff6fec52f22..4dc76f827d52ccf0cb23ee6de5e371bebca0d1f8 100644 (file)
@@ -1,5 +1,5 @@
-laser_mk1_max_charge=40000
-register_power_tool ("technic:laser_mk1",laser_mk1_max_charge)
+local laser_mk1_max_charge=40000
+technic.register_LV_power_tool ("technic:laser_mk1",laser_mk1_max_charge)
 
 local laser_shoot = function(itemstack, player, pointed_thing)
                                local laser_straight_mode=0
@@ -62,8 +62,8 @@ minetest.register_tool("technic:laser_mk1", {
                charge=meta["charge"]
                if charge-400>0 then
                 laser_shoot(item, user, pointed_thing)
-                charge =charge-400;
-               set_RE_wear(item,charge,laser_mk1_max_charge)
+                charge = charge-400;
+               technic.set_RE_wear(item,charge,laser_mk1_max_charge)
                meta["charge"]=charge
                item["metadata"]=set_item_meta(meta)
                itemstack:replace(item)
index 81b9a656fd88ddc29e451bd31ea4064620913fb0..e0520ffa42dbd76fdb170cfb8ef8c40af3269825 100644 (file)
@@ -1,3 +1,5 @@
+-- LV Music player.
+-- The playe can play music. But it is high ampage!
 minetest.register_alias("music_player", "technic:music_player")
 minetest.register_craft({
        output = 'technic:music_player',
@@ -11,112 +13,144 @@ minetest.register_craft({
 minetest.register_craftitem("technic:music_player", {
        description = "Music Player",
        stack_max = 99,
-}) 
+})
 
-music_player_formspec =
-       "invsize[8,9;]"..
-       "image[1,1;1,2;technic_power_meter_bg.png]"..
-       "label[0,0;Music Player]"..
-       "label[1,3;Power level]"..
-       "button[5,2;1,1;track1;1]"..
-       "button[6,2;1,1;track2;2]"
-       
+local music_player_formspec =
+   "invsize[8,9;]"..
+   "label[0,0;Music Player]"..
+   "button[4,1;1,1;track1;1]"..
+   "button[5,1;1,1;track2;2]"..
+   "button[6,1;1,1;track3;3]"..
+   "button[4,2;1,1;track4;4]"..
+   "button[5,2;1,1;track5;5]"..
+   "button[6,2;1,1;track6;6]"..
+   "button[4,3;1,1;track7;7]"..
+   "button[5,3;1,1;track8;8]"..
+   "button[6,3;1,1;track9;9]"..
+   "button[4,4;1,2;play;Play]"..
+   "button[6,4;1,2;stop;Stop]"..
+   "label[4,0;Current track --]"
 
-minetest.register_node("technic:music_player", {
-       description = "Music Player",
-       tiles = {"technic_music_player_top.png", "technic_machine_bottom.png", "technic_music_player_side.png",
-               "technic_music_player_side.png", "technic_music_player_side.png", "technic_music_player_side.png"},
-       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
-       sounds = default.node_sound_wood_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0,
-       internal_EU_buffer_size=5000,
-       music_player_on=0,
-       music_playing =0,
-       music_handle = 0,
-       music_player_current_track =1,
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_string("infotext", "Music Player")
-               meta:set_float("technic_power_machine", 1)
-               meta:set_float("internal_EU_buffer", 1)
-               meta:set_float("internal_EU_buffer_size", 5000)
-               meta:set_string("formspec", music_player_formspec)
-               meta:set_float("music_player_on", 0)
-               meta:set_float("music_player_current_track", 1)
-               end,    
+minetest.register_node(
+   "technic:music_player",
+   {
+      description = "Music Player",
+      tiles = {"technic_music_player_top.png", "technic_machine_bottom.png", "technic_music_player_side.png",
+              "technic_music_player_side.png", "technic_music_player_side.png", "technic_music_player_side.png"},
+      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
+      sounds = default.node_sound_wood_defaults(),
+      on_construct = function(pos)
+                       local meta = minetest.env:get_meta(pos)
+                       meta:set_string("infotext", "Music Player")
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_int("active",     0) -- Is the device on?
+                       meta:set_int("music_player_current_track", 1)
+                       meta:set_string("formspec", music_player_formspec)
+                    end,
+      on_receive_fields = function(pos, formanme, fields, sender)
+                            local meta                 = minetest.env:get_meta(pos)
+                            music_handle               = meta:get_int("music_handle")
+                            music_player_current_track = meta:get_int("music_player_current_track")
+                            if fields.track1 then music_player_current_track = 1 end
+                            if fields.track2 then music_player_current_track = 2 end
+                            if fields.track3 then music_player_current_track = 3 end
+                            if fields.track4 then music_player_current_track = 4 end
+                            if fields.track5 then music_player_current_track = 5 end
+                            if fields.track6 then music_player_current_track = 6 end
+                            if fields.track7 then music_player_current_track = 7 end
+                            if fields.track8 then music_player_current_track = 8 end
+                            if fields.track9 then music_player_current_track = 9 end
+                            meta:set_int("music_player_current_track",music_player_current_track)
+                            if fields.play and meta:get_int("active") == 0 then
+                               if music_handle then minetest.sound_stop(music_handle) end
+                               music_handle = minetest.sound_play("technic_track"..music_player_current_track, {pos = pos, gain = 1.0,loop = true, max_hear_distance = 72,})
+                               meta:set_int("active",1)
+                            end
+                            if fields.stop then
+                               meta:set_int("active",0)
+                               if music_handle then minetest.sound_stop(music_handle) end
+                            end
+                            meta:set_int("music_handle",music_handle)
+                         end,
+   })
 
-       on_receive_fields = function(pos, formanme, fields, sender)
-       
-       local meta = minetest.env:get_meta(pos)
-       player_on=meta:get_float("music_player_on")
-       music_handle=meta:get_float("music_handle")
-       music_player_current_track=meta:get_float("music_player_current_track")
-       if fields.track1 then music_player_current_track=1 end
-       if fields.track2 then music_player_current_track=2 end
-       if fields.track3 then music_player_current_track=3 end
-       if fields.track4 then music_player_current_track=4 end
-       if fields.track5 then music_player_current_track=5 end
-       if fields.track6 then music_player_current_track=6 end
-       if fields.track7 then music_player_current_track=7 end
-       if fields.track8 then music_player_current_track=8 end
-       if fields.track9 then music_player_current_track=9 end
-       meta:set_float("music_player_current_track",music_player_current_track)
-       if fields.play and player_on==1 then  
-       if music_handle then minetest.sound_stop(music_handle) end
-       music_handle=minetest.sound_play("technic_track"..music_player_current_track, {pos = pos, gain = 1.0,loop = true, max_hear_distance = 72,})     
-       meta:set_float("music_playing",1)
-       end
-       if fields.stop then  
-       meta:set_float("music_playing",0)
-       if music_handle then minetest.sound_stop(music_handle) end
-       end
-       meta:set_float("music_handle",music_handle)
-       end,
-})
+minetest.register_abm(
+   { nodenames = {"technic:music_player"},
+     interval = 1,
+     chance   = 1,
+     action = function(pos, node, active_object_count, active_object_count_wider)
+                local meta         = minetest.env:get_meta(pos)
+                local eu_input     = meta:get_int("LV_EU_input")
+                local state        = meta:get_int("state")
+                local next_state   = state
+
+                -- Machine information
+                local machine_name         = "Music Player"
+                local machine_node         = "technic:music_player"
+                local machine_state_demand = { 10, 150 }
+                        
+                local music_handle         = meta:get_int("music_handle")
+
+                -- Setup meta data if it does not exist. state is used as an indicator of this
+                if state == 0 then
+                   meta:set_int("state", 1)
+                   meta:set_int("LV_EU_demand", machine_state_demand[1])
+                   meta:set_int("LV_EU_input", 0)
+                   return
+                end
+                        
+                -- Power off automatically if no longer connected to a switching station
+                technic.switching_station_timeout_count(pos, "LV")
+                        
+                -- State machine
+                if eu_input == 0 then
+                   -- unpowered - go idle
+                   -- hacky_swap_node(pos, machine_node) -- if someday two nodes for this
+                   meta:set_string("infotext", machine_name.." Unpowered")
+                   next_state = 1
+                elseif eu_input == machine_state_demand[state] then
+                   -- Powered - do the state specific actions
+                   if state == 1 then
+                      -- hacky_swap_node(pos, machine_node) -- if someday two nodes for this
+                      meta:set_string("infotext", machine_name.." Idle")
+
+                      if meta:get_int("active") == 1 then
+                         next_state = 2
+                      end
+
+                   elseif state == 2 then
+                      -- hacky_swap_node(pos, machine_node.."_active") -- if someday two nodes for this
+                      meta:set_string("infotext", machine_name.." Active")
 
-minetest.register_abm({
-       nodenames = {"technic:music_player"},
-       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")
-       player_on=meta:get_float("music_player_on")
-       music_player_current_track=meta:get_float("music_player_current_track")
-       local play_cost=80
-       
-       if charge>play_cost then 
-               if meta:get_float("music_playing")==1 then charge=charge-play_cost end
-                       meta:set_float("internal_EU_buffer",charge)
-               meta:set_float("music_player_on",1)
-       else 
-               meta:set_float("music_playing",0)
-               meta:set_float("music_player_on",0)
-               if music_handle then minetest.sound_stop(music_handle) end
-       end
-       local load = math.floor((charge/max_charge)*100)
-       meta:set_string("formspec",
-                               "invsize[8,9;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                               (load)..":technic_power_meter_fg.png]"..
-                               "label[0,0;Music Player]"..
-                               "label[1,3;Power level]"..
-                               "button[4,1;1,1;track1;1]"..
-                               "button[5,1;1,1;track2;2]"..
-                               "button[6,1;1,1;track3;3]"..
-                               "button[4,2;1,1;track4;4]"..
-                               "button[5,2;1,1;track5;5]"..
-                               "button[6,2;1,1;track6;6]"..    
-                               "button[4,3;1,1;track7;7]"..
-                               "button[5,3;1,1;track8;8]"..
-                               "button[6,3;1,1;track9;9]"..
-                               "button[4,4;1,2;play;Play]"..
-                               "button[6,4;1,2;stop;Stop]"..
-                               "label[4,0;Current track "..tostring(music_player_current_track).."]"
-                               )
-       end
-}) 
+                      music_player_current_track=meta:get_int("music_player_current_track")
+                      meta:set_string("formspec",
+                                      "invsize[8,9;]"..
+                                         "label[0,0;Music Player]"..
+                                         "button[4,1;1,1;track1;1]"..
+                                         "button[5,1;1,1;track2;2]"..
+                                         "button[6,1;1,1;track3;3]"..
+                                         "button[4,2;1,1;track4;4]"..
+                                         "button[5,2;1,1;track5;5]"..
+                                         "button[6,2;1,1;track6;6]"..
+                                         "button[4,3;1,1;track7;7]"..
+                                         "button[5,3;1,1;track8;8]"..
+                                         "button[6,3;1,1;track9;9]"..
+                                         "button[4,4;1,2;play;Play]"..
+                                         "button[6,4;1,2;stop;Stop]"..
+                                         "label[4,0;Current track "..tostring(music_player_current_track).."]"
+                                   )
+                      if meta:get_int("active") == 0 then
+                         if music_handle then minetest.sound_stop(music_handle) end
+                         next_state = 1
+                      end
+                   end
+                end
+                -- Change state?
+                if next_state ~= state then
+                   meta:set_int("LV_EU_demand", machine_state_demand[next_state])
+                   meta:set_int("state", next_state)
+                end
+             end
+   })
 
-register_LV_machine ("technic:music_player","RE")
+technic.register_LV_machine ("technic:music_player","RE")
index 3383d18920aed123d5a7f866a3207e60b3fa9ac1..383bf87bdb9917fb2f00cd9ed8eff67cd92b2e87 100644 (file)
@@ -8,38 +8,34 @@
 -- Using inductive power transfer is very inefficient so this is
 -- set to the factor 0.6.
 
+------------------------------------------------------------------
 -- API for inductive powered nodes:
 -- Use the functions below to set the corresponding callbacks
 -- Also two nodes are needed: The inactive and the active one. The active must be called <name>_active .
-
+------------------------------------------------------------------
 -- Register a new appliance using this function
-technic_inductive_nodes = {}
-registered_inductive_count=0
-
-register_inductive_machine = function(name)
-                               registered_inductive_count=registered_inductive_count+1
-                               technic_inductive_nodes[registered_inductive_count]=name
-                               registered_inductive_count=registered_inductive_count+1
-                               technic_inductive_nodes[registered_inductive_count]=name.."_active"
-                            end
-
+technic.inductive_nodes = {}
+technic.register_inductive_machine = function(name)
+                                       table.insert(technic.inductive_nodes, name)
+                                       table.insert(technic.inductive_nodes, name.."_active")
+                                    end
 
 -- Appliances:
 --  has_supply: pos of supply node if the appliance has a power radiator near with sufficient power for the demand else ""
 --  EU_demand: The power demand of the device.
 --  EU_charge: Actual use. set to EU_demand if active==1
 --  active: set to 1 if the device is on
-technic_inductive_on_construct = function(pos, eu_demand, infotext)
+technic.inductive_on_construct = function(pos, eu_demand, infotext)
                                    local meta = minetest.env:get_meta(pos)
                                    meta:set_string("infotext", infotext)
                                    meta:set_int("technic_inductive_power_machine", 1)
-                                   meta:set_int("EU_demand",eu_demand)     -- The power demand of this appliance
+                                   meta:set_int("MV_EU_demand",eu_demand)     -- The power demand of this appliance
                                    meta:set_int("EU_charge",0)       -- The actual power draw of this appliance
                                    meta:set_string("has_supply","") -- Register whether we are powered or not. For use with several radiators.
                                    meta:set_int("active", 0)    -- If the appliance can be turned on and off by using it use this.
                                 end
 
-technic_inductive_on_punch_off = function(pos, eu_charge, swapnode)
+technic.inductive_on_punch_off = function(pos, eu_charge, swapnode)
                    local meta = minetest.env:get_meta(pos)
                    if meta:get_string("has_supply") ~= "" then
                       hacky_swap_node(pos, swapnode)
@@ -53,7 +49,7 @@ technic_inductive_on_punch_off = function(pos, eu_charge, swapnode)
                    end
                 end
 
-technic_inductive_on_punch_on = function(pos, eu_charge, swapnode)
+technic.inductive_on_punch_on = function(pos, eu_charge, swapnode)
                    local meta = minetest.env:get_meta(pos)
                    hacky_swap_node(pos, swapnode)
                    meta:set_int("active", 0)
@@ -65,121 +61,12 @@ technic_inductive_on_punch_on = function(pos, eu_charge, swapnode)
                    --print("<---------->")
                 end
 
---minetest.register_node(
---   "technic:test_induc", {
---      description = "Test radiator node",
---      drawtype = "nodebox",
---      tiles = {
---      'homedecor_glowlight_yellow_tb.png',
---      'homedecor_glowlight_yellow_tb.png',
---      'homedecor_glowlight_thick_yellow_sides.png',
---      'homedecor_glowlight_thick_yellow_sides.png',
---      'homedecor_glowlight_thick_yellow_sides.png',
---      'homedecor_glowlight_thick_yellow_sides.png'
---      },
---
-----      tiles  = {"technic_hv_down_converter_top.png", "technic_hv_down_converter_top.png", "technic_hv_down_converter_top.png",
-----           "technic_hv_down_converter_top.png", "technic_hv_down_converter_top.png", "technic_hv_down_converter_top.png"},
---      selection_box = {
---      type = "fixed",
---      fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
---      },
---      node_box = {
---      type = "fixed",
---      fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
---      },
---      sunlight_propagates = false,
---      paramtype = "light",
---      paramtype2 = "facedir",
---      walkable = true,
---      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
---      on_place = function(itemstack, placer, pointed_thing)
---                 homedecor_rotate_and_place(itemstack, placer, pointed_thing)
---                 return itemstack
---              end,
---      on_construct = function(pos)
---                     local meta = minetest.env:get_meta(pos)
---                     meta:set_string("infotext", "Power Radiator Appliance")
---                     meta:set_int("technic_inductive_power_machine", 1)
---                     meta:set_int("EU_demand",200)     -- The power demand of this appliance
---                     meta:set_int("EU_charge",0)       -- The actual power draw of this appliance
---                     meta:set_string("has_supply","") -- Register whether we are powered or not. For use with several radiators.
---                     meta:set_int("active", 0)    -- If the appliance can be turned on and off by using it use this.
---                  end,
---      on_punch = function(pos,node,puncher)
---                 local meta = minetest.env:get_meta(pos)
---                 if meta:get_string("has_supply") ~= "" then
---                    hacky_swap_node(pos, "technic:test_induc_active")
---                    meta:set_int("active", 1)
---                    meta:set_int("EU_charge",200)
---                    print("-----------")
---                    print("Turn on:")
---                    print("EUcha:"..meta:get_int("EU_charge"))
---                    print("<----------->")
---                 end
---              end,
---   })
---
---minetest.register_node(
---   "technic:test_induc_active", {
---      description = "Test radiator node",
---      drawtype = "nodebox",
---      tiles = {
---      'homedecor_glowlight_yellow_tb.png',
---      'homedecor_glowlight_yellow_tb.png',
---      'homedecor_glowlight_thick_yellow_sides.png',
---      'homedecor_glowlight_thick_yellow_sides.png',
---      'homedecor_glowlight_thick_yellow_sides.png',
---      'homedecor_glowlight_thick_yellow_sides.png'
---      },
---
-----      tiles  = {"technic_hv_down_converter_side.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", "technic_hv_down_converter_side.png"},
---      selection_box = {
---      type = "fixed",
---      fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
---      },
---      node_box = {
---      type = "fixed",
---      fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
---      },
---      sunlight_propagates = false,
---      paramtype = "light",
---      paramtype2 = "facedir",
---      walkable = true,
---      light_source=14,
---      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1},
---      drop="technic:test_induc",
---      on_place = function(itemstack, placer, pointed_thing)
---                 homedecor_rotate_and_place(itemstack, placer, pointed_thing)
---                 return itemstack
---              end,
---      on_construct = function(pos)
---                     local meta = minetest.env:get_meta(pos)
---                     meta:set_string("infotext", "Power Radiator Appliance Active")
---                     meta:set_int("technic_inductive_power_machine", 1)
---                     meta:set_int("EU_demand",200)     -- The power demand of this appliance
---                     meta:set_int("EU_charge",0)       -- The actual power draw of this appliance
---                     meta:set_string("has_supply","") -- Register whether we are powered or not. For use with several radiators.
---                  end,
---      on_punch = function(pos,node,puncher)
---                 local meta = minetest.env:get_meta(pos)
---                 hacky_swap_node(pos, "technic:test_induc")
---                 meta:set_int("active", 0)
---                 meta:set_int("EU_charge",0)
---                 print("-----------")
---                 print("Turn off:")
---                 print("EUcha:"..meta:get_int("EU_charge"))
---                 print("<---------->")
---              end,
---   })
-
 local shutdown_inductive_appliances = function(pos)
                                         -- The supply radius
                                         local rad = 4
                                         -- If the radiator is removed. turn off all appliances in region
                                         -- If another radiator is near it will turn on the appliances again
-                                        local positions = minetest.env:find_nodes_in_area({x=pos.x-rad,y=pos.y-rad,z=pos.z-rad},{x=pos.x+rad,y=pos.y+rad,z=pos.z+rad}, technic_inductive_nodes)
+                                        local positions = minetest.env:find_nodes_in_area({x=pos.x-rad,y=pos.y-rad,z=pos.z-rad},{x=pos.x+rad,y=pos.y+rad,z=pos.z+rad}, technic.inductive_nodes)
                                         for _,pos1 in ipairs(positions) do
                                            local meta1 = minetest.env:get_meta(pos1)
                                            -- If the appliance is belonging to this node
@@ -218,8 +105,7 @@ minetest.register_node(
       on_construct = function(pos)
                        local meta = minetest.env:get_meta(pos)
                        meta:set_int("technic_mv_power_machine", 1)  -- MV machine
-                       meta:set_int("internal_EU_buffer",0)         -- internal buffer value
-                       meta:set_int("internal_EU_buffer_size",1000) -- Size of buffer
+                       meta:set_int("MV_EU_demand",1)               -- Demand on the primary side when idle
                        meta:set_int("connected_EU_demand",0)        -- Potential demand of connected appliances
                        meta:set_string("infotext", "Power Radiator")
 --                     meta:set_int("active", 0)
@@ -246,34 +132,45 @@ minetest.register_abm(
     chance     = 1,
     action = function(pos, node, active_object_count, active_object_count_wider)
                local meta             = minetest.env:get_meta(pos)
-               local my_supply        = meta:get_int("internal_EU_buffer")
-               -- The maximum EU sourcing a single radiator can provide.
-               local max_charge = 1000 -- == the max EU demand of the radiator
-               local connected_EU_demand = meta:get_int("connected_EU_demand")
-               --print("--------------------")
-               --print("My Supply:"..my_supply)
-               --print("Connected Demand:"..connected_EU_demand)
-               if my_supply > 0 then
+               local eu_input  = meta:get_int("MV_EU_input")
+               local eu_demand = meta:get_int("MV_EU_demand")
+
+               -- Power off automatically if no longer connected to a switching station
+               technic.switching_station_timeout_count(pos, "MV")
+
+               if eu_input == 0 then
+                  -- No power
+                  meta:set_string("infotext", "Power Radiator is unpowered");
+--                   meta:set_int("active",1) -- used for setting textures someday maybe
+                  shutdown_inductive_appliances(pos)
+                  connected_EU_demand = 0
+               elseif eu_input == eu_demand then
+                  -- Powered and ready
+
+                  -- The maximum EU sourcing a single radiator can provide.
+                  local max_charge          = 3000 -- == the max EU demand of the radiator
+                  local connected_EU_demand = meta:get_int("connected_EU_demand")
+
                   -- Efficiency factor
                   local eff_factor = 0.6
                   -- The supply radius
-                  local rad = 4
+                  local rad = 6
                   
                   local meta1            = nil
                   local pos1             = {}
                   local used_charge      = 0
                   
                   -- Index all nodes within supply range
-                  local positions = minetest.env:find_nodes_in_area({x=pos.x-rad,y=pos.y-rad,z=pos.z-rad},{x=pos.x+rad,y=pos.y+rad,z=pos.z+rad}, technic_inductive_nodes)
+                  local positions = minetest.env:find_nodes_in_area({x=pos.x-rad,y=pos.y-rad,z=pos.z-rad},{x=pos.x+rad,y=pos.y+rad,z=pos.z+rad}, technic.inductive_nodes)
                   for _,pos1 in ipairs(positions) do
                      local meta1 = minetest.env:get_meta(pos1)
                      -- If not supplied see if this node can handle it.
                      if meta1:get_string("has_supply") == "" then
                         -- if demand surpasses the capacity of this node, don't bother adding it.
-                        local eu_demand = meta1:get_int("EU_demand")/eff_factor
-                        if connected_EU_demand+eu_demand <= max_charge and connected_EU_demand+eu_demand <= my_supply then
+                        local app_eu_demand = meta1:get_int("EU_demand")/eff_factor
+                        if connected_EU_demand + app_eu_demand <= max_charge then
                            -- We can power the appliance. Register, and spend power if it is on.
-                           connected_EU_demand = connected_EU_demand+eu_demand
+                           connected_EU_demand = connected_EU_demand + app_eu_demand
 
                            meta1:set_string("has_supply", pos.x..pos.y..pos.z)
                            used_charge = math.floor(used_charge+meta1:get_int("EU_charge")/eff_factor)
@@ -281,28 +178,28 @@ minetest.register_abm(
                      elseif meta1:get_string("has_supply") == pos.x..pos.y..pos.z then
                         -- The appliance has power from this node. Spend power if it is on.
                         used_charge = math.floor(used_charge+meta1:get_int("EU_charge")/eff_factor)
+                        print("My Lamp ("..pos.x..","..pos.y..","..pos.z..") Used:"..used_charge)
+                     end
+                     meta:set_string("infotext", "Power Radiator is powered ("..math.floor(used_charge/max_charge*100).."% of maximum power)");
+                     if used_charge == 0 then
+                        meta:set_int("MV_EU_demand", 1) -- Still idle
+                     else
+                        meta:set_int("MV_EU_demand", used_charge)
                      end
-                  end
-                  --If demand surpasses actual supply turn off everything - we are out of power
-                  if used_charge>my_supply then
-                     meta:set_string("infotext", "Power Radiator is overloaded ("..math.floor(used_charge/my_supply*100).."% of available power)");
---                   meta:set_int("active",1) -- used for setting textures someday maybe
-                     shutdown_inductive_appliances(pos)
-                     connected_EU_demand = 0
-                  else
-                     meta:set_string("infotext", "Power Radiator is powered ("..math.floor(used_charge/my_supply*100).."% of available power)");
-                     meta:set_int("internal_EU_buffer",my_supply-used_charge)
 --                   meta:set_int("active",1) -- used for setting textures someday maybe
                   end
+                  -- Save state
+                  meta:set_int("connected_EU_demand",connected_EU_demand)
                else
-                  meta:set_string("infotext", "Power Radiator is unpowered");
---                meta:set_int("active",0) -- used for setting textures someday maybe
+                  -- This is the case where input ~= demand. Overloaded or underpowered!
+--                --If demand surpasses actual supply turn off everything - we are out of power
+--                if used_charge>eu_input then
+--                   meta:set_string("infotext", "Power Radiator is overloaded ("..math.floor(used_charge/eu_input*100).."% of available power)");
+----                 meta:set_int("active",1) -- used for setting textures someday maybe
+--                   shutdown_inductive_appliances(pos)
+--                   connected_EU_demand = 0
                end
-               
-               -- Save state
-               meta:set_int("connected_EU_demand",connected_EU_demand)
-               return
             end,
  })
 
-register_MV_machine ("technic:power_radiator","RE")
+technic.register_MV_machine ("technic:power_radiator","RE")
diff --git a/technic/register_machine_and_tool.lua b/technic/register_machine_and_tool.lua
new file mode 100644 (file)
index 0000000..2178224
--- /dev/null
@@ -0,0 +1,70 @@
+-- This file includes the functions and data structures for registering machines and tools for LV, MV, HV types.
+-- We use the technioc namespace for these functions and data to avoid eventual conflict.
+
+-- register LV machines here
+technic.LV_machines    = {}
+technic.LV_power_tools = {}
+technic.register_LV_machine = function(nodename,type)
+                                technic.LV_machines[nodename] = type
+                             end
+
+technic.unregister_LV_machine = function(nodename,type)
+                                  technic.LV_machines[nodename] = nil
+                               end
+
+technic.register_LV_power_tool = function(craftitem,max_charge)
+                                   technic.LV_power_tools[craftitem] = max_charge
+                                end
+
+-- register MV machines here
+technic.MV_machines    = {}
+technic.MV_power_tools = {}
+technic.register_MV_machine = function(nodename,type)
+                                technic.MV_machines[nodename] = type
+                             end
+
+technic.unregister_MV_machine = function(nodename)
+                                  technic.MV_machines[nodename] = nil
+                               end
+
+technic.register_MV_power_tool = function(craftitem,max_charge)
+                                   technic.MV_power_tools[craftitem] = max_charge
+                                end
+
+-- register HV machines here
+technic.HV_machines    = {}
+technic.HV_power_tools = {}
+technic.register_HV_machine = function(nodename,type)
+                                technic.HV_machines[nodename] = type
+                             end
+
+technic.unregister_HV_machine = function(nodename)
+                                  technic.HV_machines[nodename] = nil
+                               end
+
+technic.register_HV_power_tool = function(craftitem,max_charge)
+                                   technic.HV_power_tools[craftitem] = max_charge
+                                end
+
+
+-- Utility functions. Not sure exactly what they do.. water.lua uses the two first.
+function technic.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)
+end
+
+function technic.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)
+end
+
+-- Wear down a tool depending on the remaining charge.
+function technic.set_RE_wear (item_stack,load,max_load)
+   local temp=65536-math.floor(load/max_load*65535)
+   item_stack["wear"]=tostring(temp)
+   return item_stack
+end
index e1592481064ae028886f27799ebdfd9202d06d60..a2fb516f3c7c4cbf9782a21655e2ea0bceffa44a 100644 (file)
@@ -10,9 +10,6 @@ minetest.register_node("technic:solar_array_hv", {
        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,       
@@ -27,29 +24,25 @@ minetest.register_node("technic:solar_array_hv", {
        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_int("HV_EU_supply", 0)
                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_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)
+   {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.
@@ -62,7 +55,7 @@ minetest.register_abm(
                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)
@@ -70,24 +63,16 @@ minetest.register_abm(
                -- 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)
-                       
+                  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>160 then charge_to_give=160 end
+                  meta:set_string("infotext", "Solar Array is active ("..charge_to_give.."EU)")
+                  meta:set_int("HV_EU_supply", charge_to_give)
                else
-                       meta:set_string("infotext", "Solar Array is inactive");
-                       meta:set_float("active",0)
+                  meta:set_string("infotext", "Solar Array is inactive");
+                  meta:set_int("HV_EU_supply", 0)
                end
-       end,
-}) 
+            end,
+ }) 
 
-register_HV_machine ("technic:solar_array_hv","PR")
+technic.register_HV_machine ("technic:solar_array_hv","PR")
index f6578143ebc001d072ce808ab308ce77c9ccc369..ecc55d9f74e087920b4bbc959443f1df8c6db5b8 100644 (file)
@@ -10,10 +10,6 @@ minetest.register_node("technic:solar_array_lv", {
        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,       
@@ -27,68 +23,56 @@ minetest.register_node("technic:solar_array_lv", {
                },
        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_int("technic_power_machine", 1)
+               meta:set_int("LV_EU_supply", 0)
                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_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)
+   {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
+               -- 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.
+               -- 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)
-                       
+                  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
+                  meta:set_string("infotext", "Solar Array is active ("..charge_to_give.."EU)")
+                  meta:set_int("LV_EU_supply", charge_to_give)
                else
-                       meta:set_string("infotext", "Solar Array is inactive");
-                       meta:set_float("active",0)
+                  meta:set_string("infotext", "Solar Array is inactive");
+                  meta:set_int("LV_EU_supply", 0)
                end
-       end,
-}) 
+            end,
+ })
 
-register_LV_machine ("technic:solar_array_lv","PR")
+technic.register_LV_machine ("technic:solar_array_lv","PR")
index abcc027f418b6d75c39d2ed622bb19240f334571..3eba790a73ea14e80a20556a984662d8b0e3e9b6 100644 (file)
@@ -11,9 +11,6 @@ minetest.register_node("technic:solar_array_mv", {
        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,       
@@ -28,68 +25,57 @@ minetest.register_node("technic:solar_array_mv", {
        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_int("MV_EU_supply", 0)
                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_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)
+   {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
+               -- 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.
+               -- 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.                    
+                  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>160 then charge_to_give=160 end
+                  meta:set_string("infotext", "Solar Array is active ("..charge_to_give.."EU)")
+                  --                   meta:set_float("active",1)
+                  meta:set_int("MV_EU_supply", charge_to_give)
                else
-                       meta:set_string("infotext", "Solar Array is inactive");
-                       meta:set_float("active",0)
+                  meta:set_string("infotext", "Solar Array is inactive");
+                  meta:set_int("MV_EU_supply", 0)
                end
-       end,
-}) 
+            end,
+ }) 
 
-register_MV_machine ("technic:solar_array_mv","PR")
+technic.register_MV_machine ("technic:solar_array_mv","PR")
index 5b53f5fbee3e24aa4f2c852d6195f324e2dfbb14..96ee74495ffda7bbf416e2fa1a200133cb752804 100644 (file)
@@ -8,9 +8,6 @@ minetest.register_node("technic:solar_panel", {
        sounds = default.node_sound_wood_defaults(),
        description="Solar Panel",
        active = false,
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=160;
        drawtype = "nodebox",
        paramtype = "light",
        is_ground_content = true,       
@@ -24,12 +21,9 @@ minetest.register_node("technic:solar_panel", {
                },
        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", 160)
-
-               meta:set_string("infotext", "Solar Panel")
-               meta:set_float("active", false)
+               meta:set_int("technic_power_machine", 1)
+               meta:set_int("LV_EU_supply", 0)
+               meta:set_string("infotext", "LV Solar Panel")
        end,
 })
 
@@ -68,24 +62,16 @@ minetest.register_abm(
                -- 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=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>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
-                       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)
-                       
+                       meta:set_int("LV_EU_supply", charge_to_give)
                else
                        meta:set_string("infotext", "Solar Panel is inactive");
-                       meta:set_float("active",0)
+                       meta:set_int("LV_EU_supply", 0)
                end
        end,
 }) 
 
-register_LV_machine ("technic:solar_panel","PR")
+technic.register_LV_machine ("technic:solar_panel","PR")
index 97ec4460a7cb2e29238ab8bf72e76453b2163e72..14538622f0688f5032b6beecdf2bca152b9a3b05 100644 (file)
@@ -1,5 +1,5 @@
-sonic_screwdriver_max_charge=15000
-register_power_tool ("technic:sonic_screwdriver",sonic_screwdriver_max_charge)
+local sonic_screwdriver_max_charge=15000
+technic.register_HV_power_tool ("technic:sonic_screwdriver",sonic_screwdriver_max_charge)
 
 minetest.register_tool("technic:sonic_screwdriver", {
                        description = "Sonic Screwdriver",
diff --git a/technic/supply_converter.lua b/technic/supply_converter.lua
new file mode 100644 (file)
index 0000000..5e04d42
--- /dev/null
@@ -0,0 +1,223 @@
+-- The supply converter is a generic device which can convert from
+-- LV to MV and back, and HV to MV and back.
+-- The machine will not convert from HV directly to LV.
+-- The machine is configured by the wiring below and above it.
+-- It is prepared for an upgrade slot if this is to be implemented later.
+--
+-- The conversion factor is a constant and the conversion is a lossy operation.
+--
+-- It works like this:
+--   The top side is setup as the "RE" side, the bottom as the "PR" side.
+--   Once the RE side is powered it will deliver power to the other side.
+--   Unused power is wasted just like any other producer!
+--   
+minetest.register_node(
+   "technic:supply_converter", {
+      description = "Supply 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_hv_power_machine", 1)
+                       meta:set_float("technic_mv_power_machine", 1)
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_string("infotext", "Supply Converter")
+                         meta:set_float("active", false)
+                      end,
+   })
+
+minetest.register_craft({
+       output = 'technic:supply_converter 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:supply_converter"},
+     interval   = 1,
+     chance     = 1,
+     action = function(pos, node, active_object_count, active_object_count_wider)
+                -- Conversion factors (a picture of V*A - loss) Asymmetric.
+                local lv_mv_factor  = 5 -- division (higher is less efficient)
+                local mv_lv_factor  = 4 -- multiplication (higher is more efficient)
+                local mv_hv_factor  = 5 -- division
+                local hv_mv_factor  = 4 -- multiplication
+                local max_lv_demand = 2000 -- The increment size pwer supply tier. Determines how many are needed
+                local max_mv_demand = 2000 -- -""-
+                local max_hv_demand = 2000 -- -""-
+
+                -- Machine information
+                local machine_name  = "Supply Converter"
+                local meta          = minetest.env:get_meta(pos)
+                local upgrade       = "" -- Replace with expansion slot later??
+                
+                -- High voltage on top, low at bottom regardless of converter direction
+                local pos_up        = {x=pos.x, y=pos.y+1, z=pos.z}
+                local pos_down      = {x=pos.x, y=pos.y-1, z=pos.z}
+                local meta_up       = minetest.env:get_meta(pos_up)
+                local meta_down     = minetest.env:get_meta(pos_down)
+                local convert_MV_LV = 0
+                local convert_LV_MV = 0
+                local convert_MV_HV = 0
+                local convert_HV_MV = 0
+                -- check cabling
+                if meta_up:get_float("mv_cablelike") == 1 and meta_down:get_float("cablelike") == 1 then
+                   convert_MV_LV = 1
+                   upgrade = "MV-LV step down"
+                end
+                if meta_up:get_float("cablelike") == 1 and meta_down:get_float("mv_cablelike") == 1 then
+                   convert_LV_MV = 1
+                   upgrade = "LV-MV step up"
+                end
+                if meta_up:get_float("mv_cablelike") == 1 and meta_down:get_float("hv_cablelike") == 1 then
+                   convert_MV_HV = 1
+                   upgrade = "MV-HV step up"
+                end
+                if meta_up:get_float("hv_cablelike") == 1 and meta_down:get_float("mv_cablelike") == 1 then
+                   convert_HV_MV = 1
+                   upgrade = "HV-MV step down"
+                end
+                --print("Cabling:"..convert_MV_LV.."|"..convert_LV_MV.."|"..convert_HV_MV.."|"..convert_MV_HV)
+
+                if convert_MV_LV == 0 and convert_LV_MV == 0 and convert_HV_MV == 0 and convert_MV_HV == 0 then
+                   meta:set_string("infotext", machine_name.." has bad cabling")
+                   return
+                end
+
+                -- The node is programmed with an upgrade slot
+                -- containing a MV-LV step down, LV-MV step up, HV-MV step down or MV-HV step up unit
+
+                if upgrade == "" then
+                   meta:set_string("infotext", machine_name.." has an empty converter slot");
+                   technic.unregister_LV_machine("technic:supply_converter")
+                   technic.unregister_MV_machine("technic:supply_converter")
+                   technic.unregister_HV_machine("technic:supply_converter")
+                   meta:set_int("LV_EU_demand", 0)
+                   meta:set_int("LV_EU_supply", 0)
+                   meta:set_int("LV_EU_input",  0)
+                   meta:set_int("MV_EU_demand", 0)
+                   meta:set_int("MV_EU_supply", 0)
+                   meta:set_int("MV_EU_input",  0)
+                   meta:set_int("HV_EU_demand", 0)
+                   meta:set_int("HV_EU_supply", 0)
+                   meta:set_int("HV_EU_input",  0)
+                   return
+                end
+
+                -- State machine
+                if upgrade == "MV-LV step down" and convert_MV_LV then
+                   -- Register machine type
+                   technic.register_LV_machine("technic:supply_converter","PR")
+                   technic.register_MV_machine("technic:supply_converter","RE")
+
+                   -- Power off automatically if no longer connected to a switching station
+                   technic.switching_station_timeout_count(pos, "MV")
+
+                   local eu_input  = meta:get_int("MV_EU_input")
+                   if eu_input == 0 then
+                      -- Unpowered - go idle
+                      --hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Unpowered")
+                      meta:set_int("LV_EU_supply", 0)
+                      meta:set_int("MV_EU_supply", 0)
+
+                      meta:set_int("LV_EU_demand", 0)
+                      meta:set_int("MV_EU_demand", max_mv_demand)
+                   else
+                      -- MV side has got power to spare
+                      meta:set_string("infotext", machine_name.." is active (MV:"..max_mv_demand.."->LV:"..eu_input*mv_lv_factor..")");
+                      meta:set_int("LV_EU_supply", eu_input*mv_lv_factor)
+                   end
+                   ---------------------------------------------------
+                elseif upgrade == "LV-MV step up"   and convert_LV_MV then
+                   -- Register machine type
+                   technic.register_LV_machine("technic:supply_converter","RE")
+                   technic.register_MV_machine("technic:supply_converter","PR")
+
+                   -- Power off automatically if no longer connected to a switching station
+                   technic.switching_station_timeout_count(pos, "LV")
+
+                   local eu_input  = meta:get_int("LV_EU_input")
+                   if eu_input == 0 then
+                      -- Unpowered - go idle
+                      --hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Unpowered")
+                      meta:set_int("LV_EU_supply", 0)
+                      meta:set_int("MV_EU_supply", 0)
+
+                      meta:set_int("LV_EU_demand", max_lv_demand)
+                      meta:set_int("MV_EU_demand", 0)
+                   else
+                      -- LV side has got power to spare
+                      meta:set_string("infotext", machine_name.." is active (LV:"..max_lv_demand.."->MV:"..eu_input/lv_mv_factor..")");
+                      meta:set_int("MV_EU_supply", eu_input/lv_mv_factor)
+                   end
+                   ---------------------------------------------------
+
+                elseif upgrade == "HV-MV step down" and convert_HV_MV then
+                   -- Register machine type
+                   technic.register_MV_machine("technic:supply_converter","PR")
+                   technic.register_HV_machine("technic:supply_converter","RE")
+
+                   -- Power off automatically if no longer connected to a switching station
+                   technic.switching_station_timeout_count(pos, "HV")
+
+                   local eu_input  = meta:get_int("HV_EU_input")
+                   if eu_input == 0 then
+                      -- Unpowered - go idle
+                      --hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Unpowered")
+                      meta:set_int("MV_EU_supply", 0)
+                      meta:set_int("HV_EU_supply", 0)
+
+                      meta:set_int("MV_EU_demand", 0)
+                      meta:set_int("HV_EU_demand", max_hv_demand)
+                   else
+                      -- HV side has got power to spare
+                      meta:set_string("infotext", machine_name.." is active (HV:"..max_hv_demand.."->MV:"..eu_input*hv_mv_factor..")");
+                      meta:set_int("MV_EU_supply", eu_input*hv_mv_factor)
+                   end
+                   ---------------------------------------------------
+                elseif upgrade == "MV-HV step up"   and convert_MV_HV then
+                   -- Register machine type
+                   technic.register_MV_machine("technic:supply_converter","RE")
+                   technic.register_HV_machine("technic:supply_converter","PR")
+
+                   -- Power off automatically if no longer connected to a switching station
+                   technic.switching_station_timeout_count(pos, "MV")
+
+                   local eu_input  = meta:get_int("MV_EU_input")
+                   if eu_input == 0 then
+                      -- Unpowered - go idle
+                      --hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Unpowered")
+                      meta:set_int("MV_EU_supply", 0)
+                      meta:set_int("HV_EU_supply", 0)
+
+                      meta:set_int("MV_EU_demand", max_mv_demand)
+                      meta:set_int("HV_EU_demand", 0)
+                   else
+                      -- MV side has got power to spare
+                      meta:set_string("infotext", machine_name.." is active (MV:"..max_mv_demand.."->HV:"..eu_input/mv_hv_factor..")");
+                      meta:set_int("HV_EU_supply", eu_input/mv_hv_factor)
+                   end
+                   ---------------------------------------------------
+                end
+       end,
+})
diff --git a/technic/switching_station.lua b/technic/switching_station.lua
new file mode 100644 (file)
index 0000000..7919d5e
--- /dev/null
@@ -0,0 +1,352 @@
+-- SWITCHING STATION
+-- The switching station is the center of all power distribution on an electric network.
+-- The station will collect all produced power from producers (PR) and batteries (BA)
+-- and distribute it to receivers (RE) and depleted batteries (BA).
+--
+-- It works like this:
+--  All PR,BA,RE nodes are indexed and tagged with the switching station.
+-- The tagging is to allow more stations to be built without allowing a cheat
+-- with duplicating power.
+--  All the RE nodes are queried for their current EU demand. Those which are off
+-- would require no or a small standby EU demand, while those which are on would
+-- require more.
+-- If the total demand is less than the available power they are all updated with the
+-- demand number.
+-- If any surplus exists from the PR nodes the batteries will be charged evenly with this.
+-- If the total demand requires draw on the batteries they will be discharged evenly.
+--
+-- If the total demand is more than the available power all RE nodes will be shut down.
+-- We have a brown-out situation.
+--
+-- Hence all the power distribution logic resides in this single node.
+--
+--  Nodes connected to the network will have one or more of these parameters as meta data:
+--   <LV|MV|HV>_EU_supply : Exists for PR and BA node types. This is the EU value supplied by the node. Output
+--   <LV|MV|HV>_EU_demand : Exists for RE and BA node types. This is the EU value the node requires to run. Output
+--   <LV|MV|HV>_EU_input  : Exists for RE and BA node types. This is the actual EU value the network can give the node. Input
+--
+--  The reason the LV|MV|HV type is prepended toe meta data is because some machine could require several supplies to work.
+--  This way the supplies are separated per network.
+technic.DBG = 1
+local dprint = technic.dprint
+
+minetest.register_craft(
+   {
+      output = 'technic:switching_station 1',
+      recipe = {
+        {'technic:lv_transformer', 'technic:mv_transformer', 'technic:hv_transformer'},
+        {'technic:lv_transformer', 'technic:mv_transformer', 'technic:hv_transformer'},
+        {'technic:lv_cable',       'technic:mv_cable',       'technic:hv_cable'},
+      }
+   })
+
+minetest.register_node(
+   "technic:switching_station",
+   {description = "Switching Station",
+    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_string("infotext", "Switching Station")
+--                     minetest.chat_send_player(puncher:get_player_name(), "Switching station constructed. Punch the station to shut down the network.");
+--                     meta:set_int("active", 1)
+                  end,
+--      on_punch = function(pos, node, puncher)
+--                 local meta   = minetest.env:get_meta(pos)
+--                 local active = meta:get_int("active")
+--                 if active == 1 then
+--                    meta:set_int("active", 0)
+--                    minetest.chat_send_player(puncher:get_player_name(), "Electrical network shut down. Punch again to turn it on.");
+--                 else
+--                    meta:set_int("active", 1)
+--                    minetest.chat_send_player(puncher:get_player_name(), "Electrical network turned on. Punch again to shut it down.");
+--                 end
+--              end
+ })
+
+--------------------------------------------------
+-- Functions to help the machines on the electrical network
+--------------------------------------------------
+-- This one provides a timeout for a node in case it was disconnected from the network
+-- A node must be touched by the station continuously in order to function
+technic.switching_station_timeout_count = function(pos, machine_tier)
+                                            local meta = minetest.env:get_meta(pos)
+                                            timeout =  meta:get_int(machine_tier.."_EU_timeout")
+                                            --print("Counting timeout "..timeout)
+                                            if timeout == 0 then
+                                               --print("OFF")
+                                               meta:set_int(machine_tier.."_EU_input", 0)
+                                            else
+                                               --print("ON")
+                                               meta:set_int(machine_tier.."_EU_timeout", timeout-1)
+                                            end
+                                         end
+
+--------------------------------------------------
+-- Functions to traverse the electrical network
+--------------------------------------------------
+
+-- Add a wire node to the LV/MV/HV network
+local add_new_cable_node = function(nodes,pos)
+                             local i = 1
+                             repeat
+                                if nodes[i]==nil then break end
+                                if pos.x==nodes[i].x and pos.y==nodes[i].y and pos.z==nodes[i].z then return false end
+                                i=i+1
+                             until false
+                             nodes[i] = {x=pos.x, y=pos.y, z=pos.z, visited=1} -- copy position
+                             return true
+                          end
+
+-- Generic function to add found connected nodes to the right classification array
+local check_node_subp = function(PR_nodes,RE_nodes,BA_nodes,all_nodes,pos,machines,cablename)
+                          local meta = minetest.env:get_meta(pos)
+                          local name = minetest.env:get_node(pos).name
+                          if meta:get_float(cablename)==1 then
+                             add_new_cable_node(all_nodes,pos)
+                          elseif machines[name] then
+                             --dprint(name.." is a "..machines[name])
+                             if     machines[name] == "PR" then
+                                add_new_cable_node(PR_nodes,pos)
+                             elseif machines[name] == "RE" then
+                                add_new_cable_node(RE_nodes,pos)
+                             elseif machines[name] == "BA" then
+                                add_new_cable_node(BA_nodes,pos)
+                             end
+                             if cablename == "cablelike" then
+                                meta:set_int("LV_EU_timeout", 2) -- Touch node
+                             elseif cablename == "mv_cablelike" then
+                                meta:set_int("MV_EU_timeout", 2) -- Touch node
+                             elseif cablename == "hv_cablelike" then
+                                meta:set_int("HV_EU_timeout", 2) -- Touch node
+                             end
+                          end
+                       end
+
+-- Traverse a network given a list of machines and a cable type name
+local traverse_network = function(PR_nodes,RE_nodes,BA_nodes,all_nodes, i, machines, cablename)
+                           local pos = {x=all_nodes[i].x, y=all_nodes[i].y, z=all_nodes[i].z} -- copy position
+                           pos.x=pos.x+1
+                           check_node_subp(PR_nodes,RE_nodes,BA_nodes,all_nodes,pos, machines, cablename)
+                           pos.x=pos.x-2
+                           check_node_subp(PR_nodes,RE_nodes,BA_nodes,all_nodes,pos, machines, cablename)
+                           pos.x=pos.x+1
+                           
+                           pos.y=pos.y+1
+                           check_node_subp(PR_nodes,RE_nodes,BA_nodes,all_nodes,pos, machines, cablename)
+                           pos.y=pos.y-2
+                           check_node_subp(PR_nodes,RE_nodes,BA_nodes,all_nodes,pos, machines, cablename)
+                           pos.y=pos.y+1
+                           
+                           pos.z=pos.z+1
+                           check_node_subp(PR_nodes,RE_nodes,BA_nodes,all_nodes,pos, machines, cablename)
+                           pos.z=pos.z-2
+                           check_node_subp(PR_nodes,RE_nodes,BA_nodes,all_nodes,pos, machines, cablename)
+                           pos.z=pos.z+1
+                     end
+
+----------------------------------------------
+-- The action code for the switching station
+----------------------------------------------
+minetest.register_abm(
+       {nodenames = {"technic:switching_station"},
+       interval   = 1,
+       chance     = 1,
+       action = function(pos, node, active_object_count, active_object_count_wider)
+                   local meta             = minetest.env:get_meta(pos)
+                   local meta1            = nil
+                   local pos1             = {}
+                   local PR_EU            = 0 -- EUs from PR nodes
+                   local BA_PR_EU         = 0 -- EUs from BA nodes (discharching)
+                   local BA_RE_EU         = 0 -- EUs to BA nodes (charging)
+                   local RE_EU            = 0 -- EUs to RE nodes
+
+                   local network   = ""
+                   local all_nodes = {}
+                   local PR_nodes  = {}
+                   local BA_nodes  = {} 
+                   local RE_nodes  = {}
+
+--                 -- Possible to turn off the entire network
+--                 if meta:get_int("active") == 0 then
+--                    for _,pos1 in pairs(RE_nodes) do
+--                       meta1  = minetest.env:get_meta(pos1)
+--                       meta1:set_int("EU_input", 0)
+--                    end
+--                    for _,pos1 in pairs(BA_nodes) do
+--                       meta1  = minetest.env:get_meta(pos1)
+--                       meta1:set_int("EU_input", 0)
+--                    end
+--                    return
+--                 end
+
+                   -- Which kind of network are we on:
+                   pos1 = {x=pos.x, y=pos.y-1, z=pos.z}
+                   all_nodes[1] = pos1
+
+                   meta1  = minetest.env:get_meta(pos1)
+                   if meta1:get_float("cablelike") ==1 then
+                      -- LV type
+                      --dprint("LV type")
+                      network = "LV"
+                      local table_index = 1
+                      repeat
+                         traverse_network(PR_nodes,RE_nodes,BA_nodes,all_nodes,table_index, technic.LV_machines, "cablelike")
+                         table_index = table_index + 1
+                         if all_nodes[table_index] == nil then break end
+                      until false
+                   elseif meta1:get_float("mv_cablelike") ==1 then
+                      -- MV type
+                      --dprint("MV type")
+                      network = "MV"
+                      local table_index = 1
+                      repeat
+                         traverse_network(PR_nodes,RE_nodes,BA_nodes,all_nodes,table_index, technic.MV_machines, "mv_cablelike")
+                         table_index = table_index + 1
+                         if all_nodes[table_index] == nil then break end
+                      until false
+                   elseif meta1:get_float("hv_cablelike") ==1 then
+                      -- HV type
+                      --dprint("HV type")
+                      network = "HV"
+                      local table_index = 1
+                      repeat
+                         traverse_network(PR_nodes,RE_nodes,BA_nodes,all_nodes,table_index, technic.HV_machines, "hv_cablelike")
+                         table_index = table_index + 1
+                         if all_nodes[table_index] == nil then break end
+                      until false
+                   else
+                      -- No type :-)
+                      --dprint("Not connected to a network")
+                      meta:set_string("infotext", "Switching Station - no network")
+                      return
+                   end
+                   --dprint("nodes="..table.getn(all_nodes).." PR="..table.getn(PR_nodes).." BA="..table.getn(BA_nodes).." RE="..table.getn(RE_nodes))
+
+                   -- Strings for the meta data
+                   local eu_demand_str    = network.."_EU_demand"
+                   local eu_input_str     = network.."_EU_input"
+                   local eu_supply_str    = network.."_EU_supply"
+                   local eu_from_fuel_str = network.."_EU_from_fuel"
+
+                   -- Get all the power from the PR nodes
+                   local PR_eu_supply = 0 -- Total power
+                   for _,pos1 in pairs(PR_nodes) do
+                      meta1  = minetest.env:get_meta(pos1)
+                      PR_eu_supply = PR_eu_supply + meta1:get_int(eu_supply_str)
+                   end
+                   --dprint("Total PR supply:"..PR_eu_supply)
+
+                   -- Get all the demand from the RE nodes
+                   local RE_eu_demand = 0
+                   for _,pos1 in pairs(RE_nodes) do
+                      meta1  = minetest.env:get_meta(pos1)
+                      RE_eu_demand = RE_eu_demand + meta1:get_int(eu_demand_str)
+                   end
+                   --dprint("Total RE demand:"..RE_eu_demand)
+
+                   -- Get all the power from the BA nodes
+                   local BA_eu_supply = 0
+                   for _,pos1 in pairs(BA_nodes) do
+                      meta1  = minetest.env:get_meta(pos1)
+                      BA_eu_supply = BA_eu_supply + meta1:get_int(eu_supply_str)
+                   end
+                   --dprint("Total BA supply:"..BA_eu_supply)
+
+                   -- Get all the demand from the BA nodes
+                   local BA_eu_demand = 0
+                   for _,pos1 in pairs(BA_nodes) do
+                      meta1  = minetest.env:get_meta(pos1)
+                      BA_eu_demand = BA_eu_demand + meta1:get_int(eu_demand_str)
+                   end
+                   --dprint("Total BA demand:"..BA_eu_demand)
+
+                   meta:set_string("infotext", "Switching Station. PR("..(PR_eu_supply+BA_eu_supply)..") RE("..(RE_eu_demand+BA_eu_demand)..")")
+
+                   -- If the PR supply is enough for the RE demand supply them all
+                   if PR_eu_supply >= RE_eu_demand then
+                      --dprint("PR_eu_supply"..PR_eu_supply.." >= RE_eu_demand"..RE_eu_demand)
+                      for _,pos1 in pairs(RE_nodes) do
+                         meta1  = minetest.env:get_meta(pos1)
+                         local eu_demand = meta1:get_int(eu_demand_str)
+                         meta1:set_int(eu_input_str, eu_demand)
+                      end
+                      -- We have a surplus, so distribute the rest equally to the BA nodes
+                      -- Let's calculate the factor of the demand
+                      PR_eu_supply = PR_eu_supply - RE_eu_demand
+                      local charge_factor = 0 -- Assume all batteries fully charged
+                      if BA_eu_demand > 0 then
+                         charge_factor = PR_eu_supply / BA_eu_demand
+                      end
+                      for n,pos1 in pairs(BA_nodes) do
+                         meta1  = minetest.env:get_meta(pos1)
+                         local eu_demand = meta1:get_int(eu_demand_str)
+                         meta1:set_int(eu_input_str, math.floor(eu_demand*charge_factor))
+                         --dprint("Charging battery:"..math.floor(eu_demand*charge_factor))
+                      end
+                      -- If still a surplus we can start giving back to the fuel burning generators
+                      -- Only full EU packages are given back. The rest is wasted.
+                      if BA_eu_demand == 0 then
+                         for _,pos1 in pairs(PR_nodes) do
+                            meta1  = minetest.env:get_meta(pos1)
+                            if meta1:get_int(eu_from_fuel_str) == 1 then
+                               local eu_supply = meta1:get_int(eu_supply_str)
+                               if PR_eu_supply < eu_supply then
+                                  break
+                               else
+                                  -- Set the supply to 0 if we did not require it.
+                                  meta1:set_int(eu_supply_str, 0)
+                                  PR_eu_supply = PR_eu_supply - eu_supply
+                               end
+                            end
+                         end
+                      end
+                      return
+                   end
+
+                   -- If the PR supply is not enough for the RE demand we will discharge the batteries too
+                   if PR_eu_supply+BA_eu_supply >= RE_eu_demand then
+                      --dprint("PR_eu_supply "..PR_eu_supply.."+BA_eu_supply "..BA_eu_supply.." >= RE_eu_demand"..RE_eu_demand)
+                      for _,pos1 in pairs(RE_nodes) do
+                         meta1  = minetest.env:get_meta(pos1)
+                         local eu_demand = meta1:get_int(eu_demand_str)
+                         meta1:set_int(eu_input_str, eu_demand)
+                      end
+                      -- We have a deficit, so distribute to the BA nodes
+                      -- Let's calculate the factor of the supply
+                      local charge_factor = 0 -- Assume all batteries depleted
+                      if BA_eu_supply > 0 then
+                         charge_factor = (PR_eu_supply - RE_eu_demand) / BA_eu_supply
+                      end
+                      for n,pos1 in pairs(BA_nodes) do
+                         meta1  = minetest.env:get_meta(pos1)
+                         local eu_supply = meta1:get_int(eu_supply_str)
+                         meta1:set_int(eu_input_str, math.floor(eu_supply*charge_factor))
+                         --dprint("Discharging battery:"..math.floor(eu_supply*charge_factor))
+                      end
+                      return
+                   end
+
+                   -- If the PR+BA supply is not enough for the RE demand: Shut everything down!
+                   -- Note: another behaviour could also be imagined: provide the average power for all and let the node decide what happens.
+                   -- This is much simpler though: Not enough power for all==no power for all
+                   --print("NO POWER")
+                   for _,pos1 in pairs(RE_nodes) do
+                      meta1  = minetest.env:get_meta(pos1)
+                      meta1:set_int(eu_input_str, 0)
+                   end
+       end,
+})
index 11746334c56134a8be489ab56df0ad8f864b8f04..9351c0e2759a36c9a192ccfcd6f5177bfccce5c9 100644 (file)
@@ -1,3 +1,5 @@
+-- LV Tool workshop
+-- This machine repairs tools.
 minetest.register_alias("tool_workshop", "technic:tool_workshop")
 minetest.register_craft({
        output = 'technic:tool_workshop',
@@ -13,88 +15,108 @@ minetest.register_craftitem("technic:tool_workshop", {
        stack_max = 99,
 }) 
 
-workshop_formspec =
-       "invsize[8,9;]"..
-       "image[1,1;1,2;technic_power_meter_bg.png]"..
-       "list[current_name;src;3,1;1,1;]"..
-       "label[0,0;Tool Workshop]"..
-       "label[1,3;Power level]"..
-       "list[current_player;main;0,5;8,4;]"
+local workshop_formspec =
+   "invsize[8,9;]"..
+   "list[current_name;src;3,1;1,1;]"..
+   "label[0,0;Tool Workshop]"..
+   "list[current_player;main;0,5;8,4;]"
 
-minetest.register_node("technic:tool_workshop", {
-       description = "Tool Workshop",
-       tiles = {"technic_workshop_top.png", "technic_machine_bottom.png", "technic_workshop_side.png",
-               "technic_workshop_side.png", "technic_workshop_side.png", "technic_workshop_side.png"},
-       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
-       sounds = default.node_sound_wood_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=2000;
+minetest.register_node(
+   "technic:tool_workshop",
+   {
+      description = "Tool Workshop",
+      tiles = {"technic_workshop_top.png", "technic_machine_bottom.png", "technic_workshop_side.png",
+              "technic_workshop_side.png", "technic_workshop_side.png", "technic_workshop_side.png"},
+      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
+      sounds = default.node_sound_wood_defaults(),
+      on_construct = function(pos)
+                       local meta = minetest.env:get_meta(pos)
+                       meta:set_string("infotext", "Tool Workshop")
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_string("formspec", workshop_formspec)
+                       local inv = meta:get_inventory()
+                       inv:set_size("src", 1)
+                    end,       
+      can_dig = function(pos,player)
+                  local meta = minetest.env:get_meta(pos);
+                  local inv = meta:get_inventory()
+                  if not inv:is_empty("src") then
+                     minetest.chat_send_player(player:get_player_name(), "Machine cannot be removed because it is not empty");
+                     return false
+                  end
+                  return true
+               end,
+   })
 
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_string("infotext", "Tool Workshop")
-               meta:set_float("technic_power_machine", 1)
-               meta:set_float("internal_EU_buffer", 1)
-               meta:set_float("internal_EU_buffer_size", 2000)
-               meta:set_string("formspec", workshop_formspec)
-               local inv = meta:get_inventory()
-               inv:set_size("src", 1)
-               end,    
-       can_dig = function(pos,player)
-               local meta = minetest.env:get_meta(pos);
-               local inv = meta:get_inventory()
-               if not inv:is_empty("src") then
-                       return false
-               end
-               return true
-       end,
-})
+minetest.register_abm(
+   { nodenames = {"technic:tool_workshop"},
+     interval = 1,
+     chance   = 1,
+     action = function(pos, node, active_object_count, active_object_count_wider)
+                local meta         = minetest.env:get_meta(pos)
+                local eu_input     = meta:get_int("LV_EU_input")
+                local state        = meta:get_int("state")
+                local next_state   = state
 
-minetest.register_abm({
-       nodenames = {"technic:tool_workshop"},
-       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 load_step=2000
-       local load_cost=200
-               local inv = meta:get_inventory()
-               if inv:is_empty("src")==false  then 
-                       srcstack = inv:get_stack("src", 1)
-                       src_item=srcstack:to_table()
-                       if (src_item["name"]=="technic:water_can" or src_item["name"]=="technic:lava_can") then
-                               load_step=0
-                               load_cost=0
-                               end
-                       local load1=tonumber((src_item["wear"])) 
-                       if charge>load_cost then
-                               if load1>1 then 
-                                       if load1-load_step<0 then load_step=load1 load1=1
-                                       else load1=load1-load_step end
-                                       charge=charge-load_cost
-                                       src_item["wear"]=tostring(load1)
-                                       inv:set_stack("src", 1, src_item)
-                               end
-                       end
-               end
-       
-       meta:set_float("internal_EU_buffer",charge)
-       
-       
-       local load = math.floor((charge/max_charge)*100)
-       meta:set_string("formspec",
-                               "invsize[8,9;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                               (load)..":technic_power_meter_fg.png]"..
-                               "list[current_name;src;3,1;1,1;]"..
-                               "label[0,0;Tool Workshop]"..
-                               "label[1,3;Power level]"..
-                               "list[current_player;main;0,5;8,4;]")
-       end
-}) 
+                -- Machine information
+                local machine_name         = "Tool Workshop"
+                local machine_node         = "technic:tool_workshop"
+                local machine_state_demand = { 50, 150 }
+                        
+                -- Setup meta data if it does not exist. state is used as an indicator of this
+                if state == 0 then
+                   meta:set_int("state", 1)
+                   meta:set_int("LV_EU_demand", machine_state_demand[1])
+                   meta:set_int("LV_EU_input", 0)
+                   return
+                end
+                        
+                -- Power off automatically if no longer connected to a switching station
+                technic.switching_station_timeout_count(pos, "LV")
+                        
+                -- State machine
+                if eu_input == 0 then
+                   -- Unpowered - go idle
+                   --hacky_swap_node(pos, machine_node)
+                   meta:set_string("infotext", machine_name.." Unpowered")
+                   next_state = 1
+                elseif eu_input == machine_state_demand[state] then
+                   -- Powered - do the state specific actions
+                   local inv = meta:get_inventory()
+                           
+                   if state == 1 then
+                      --hacky_swap_node(pos, machine_node)
+                      meta:set_string("infotext", machine_name.." Idle")
+                      if not inv:is_empty("src") then
+                         next_state = 2
+                      end
+                   elseif state == 2 then
+                      --hacky_swap_node(pos, machine_node.."_active")
+                      meta:set_string("infotext", machine_name.." Active")
+
+                      if inv:is_empty("src") then
+                         next_state = 1
+                      else
+                         srcstack = inv:get_stack("src", 1)
+                         src_item=srcstack:to_table()
+                         -- Cannot charge cans
+                         if (src_item["name"]=="technic:water_can" or src_item["name"]=="technic:lava_can") then
+                            return
+                         end
+                         local wear=tonumber(src_item["wear"])
+                         wear = math.max(1, wear-2000) -- Improve the tool this much every tick
+                         src_item["wear"]=tostring(wear)
+                         inv:set_stack("src", 1, src_item)
+                      end
+                   end
+                end
+                -- Change state?
+                if next_state ~= state then
+                   meta:set_int("LV_EU_demand", machine_state_demand[next_state])
+                   meta:set_int("state", next_state)
+                end
+             end
+   }) 
 
-register_LV_machine ("technic:tool_workshop","RE")
+technic.register_LV_machine ("technic:tool_workshop","RE")
 
index 52966edf87013748623ed854b7a5a65536cd8724..e6314f079beef0818570deb4e4526c06f68e3710 100644 (file)
@@ -1,3 +1,6 @@
+-- A water mill produces LV EUs by exploiting flowing water across it
+-- It is a LV EU supplyer and fairly low yield (max 120EUs)
+-- It is a little under half as good as the thermal generator.
 minetest.register_alias("water_mill", "technic:water_mill")
 
 minetest.register_craft({
@@ -14,7 +17,7 @@ minetest.register_craftitem("technic:water_mill", {
        stack_max = 99,
 }) 
 
-water_mill_formspec =
+local water_mill_formspec =
        "invsize[8,4;]"..
        "image[1,1;1,2;technic_power_meter_bg.png]"..
        "label[0,0;Water Mill]"..
@@ -22,110 +25,98 @@ water_mill_formspec =
        "list[current_player;main;0,5;8,4;]"
        
 
-minetest.register_node("technic:water_mill", {
-       description = "Water Mill",
-       tiles = {"technic_water_mill_top.png", "technic_machine_bottom.png", "technic_water_mill_side.png",
-               "technic_water_mill_side.png", "technic_water_mill_side.png", "technic_water_mill_side.png"},
-       paramtype2 = "facedir",
-       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_wood_defaults(),
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=5000;
-       burn_time=0;
-       on_construct = function(pos)
-               local meta = minetest.env:get_meta(pos)
-               meta:set_string("infotext", "Water Mill")
-               meta:set_float("technic_power_machine", 1)
-               meta:set_float("internal_EU_buffer", 0)
-               meta:set_float("internal_EU_buffer_size", 3000)
-               meta:set_string("formspec", water_mill_formspec)        
-               end,    
-
-})
+minetest.register_node(
+   "technic:water_mill",
+   {
+      description = "Water Mill",
+      tiles = {"technic_water_mill_top.png", "technic_machine_bottom.png", "technic_water_mill_side.png",
+              "technic_water_mill_side.png", "technic_water_mill_side.png", "technic_water_mill_side.png"},
+      paramtype2 = "facedir",
+      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_wood_defaults(),
+      on_construct = function(pos)
+                       local meta = minetest.env:get_meta(pos)
+                       meta:set_string("infotext", "Water Mill")
+                       meta:set_float("technic_power_machine", 1)
+                       meta:set_int("LV_EU_supply", 0)
+                       meta:set_string("formspec", water_mill_formspec)        
+                    end,       
+   })
 
-minetest.register_node("technic:water_mill_active", {
-       description = "Water Mill",
-       tiles = {"technic_water_mill_top_active.png", "technic_machine_bottom.png", "technic_water_mill_side.png",
-               "technic_water_mill_side.png", "technic_water_mill_side.png", "technic_water_mill_side.png"},
-       paramtype2 = "facedir",
-       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1},
-       legacy_facedir_simple = true,
-       sounds = default.node_sound_wood_defaults(),
-       drop="technic:water_mill",
-       technic_power_machine=1,
-       internal_EU_buffer=0;
-       internal_EU_buffer_size=0;
+minetest.register_node(
+   "technic:water_mill_active",
+   {
+      description = "Water Mill",
+      tiles = {"technic_water_mill_top_active.png", "technic_machine_bottom.png", "technic_water_mill_side.png",
+              "technic_water_mill_side.png", "technic_water_mill_side.png", "technic_water_mill_side.png"},
+      paramtype2 = "facedir",
+      groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1},
+      legacy_facedir_simple = true,
+      sounds = default.node_sound_wood_defaults(),
+      drop="technic:water_mill",
 })
 
-minetest.register_abm({
-       nodenames = {"technic:water_mill","technic:water_mill_active"},
-       interval = 1,
-       chance = 1,
-       action = function(pos, node, active_object_count, active_object_count_wider)
+local check_node_around_mill = function(pos)
+                                 local node=minetest.env:get_node(pos)
+                                 if node.name=="default:water_flowing" then return 1 end
+                                 return 0
+                              end
 
-       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 water_nodes = 0
-       local lava_nodes = 0
-       local production_level=0
-       local load_step=0
+minetest.register_abm(
+   {
+      nodenames = {"technic:water_mill","technic:water_mill_active"},
+      interval = 1,
+      chance   = 1,
+      action = function(pos, node, active_object_count, active_object_count_wider)
+                 local meta             = minetest.env:get_meta(pos)
+                 local water_nodes      = 0
+                 local lava_nodes       = 0
+                 local production_level = 0
+                 local eu_supply        = 0
 
-       pos.x=pos.x+1
-       local check=check_node_around_mill (pos)
-       if check==1 then water_nodes=water_nodes+1 end
-       pos.x=pos.x-2
-       check=check_node_around_mill (pos)
-       if check==1 then water_nodes=water_nodes+1 end
-       pos.x=pos.x+1
-       pos.z=pos.z+1
-       check=check_node_around_mill (pos)
-       if check==1 then water_nodes=water_nodes+1 end
-       pos.z=pos.z-2
-       check=check_node_around_mill (pos)
-       if check==1 then water_nodes=water_nodes+1 end
-       pos.z=pos.z+1
+                 pos.x=pos.x+1
+                 local check=check_node_around_mill (pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 pos.x=pos.x-2
+                 check=check_node_around_mill (pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 pos.x=pos.x+1
+                 pos.z=pos.z+1
+                 check=check_node_around_mill (pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 pos.z=pos.z-2
+                 check=check_node_around_mill (pos)
+                 if check==1 then water_nodes=water_nodes+1 end
+                 pos.z=pos.z+1
        
-       if water_nodes==1 then production_level=25 load_step=30 end
-       if water_nodes==2 then production_level=50 load_step=60 end
-       if water_nodes==3 then production_level=75 load_step=90 end
-       if water_nodes==4 then production_level=100 load_step=120 end
+                 if water_nodes==1 then production_level =  25; eu_supply =  30 end
+                 if water_nodes==2 then production_level =  50; eu_supply =  60 end
+                 if water_nodes==3 then production_level =  75; eu_supply =  90 end
+                 if water_nodes==4 then production_level = 100; eu_supply = 120 end
 
-        if production_level>0 then
-               if charge+load_step>max_charge then
-               load_step=max_charge-charge
-               end
-               if load_step>0 then 
-               charge=charge+load_step
-               meta:set_float("internal_EU_buffer",charge)
-               end
-       end
+                 if production_level>0 then
+                    meta:set_int("LV_EU_supply", eu_supply)
+                 end
 
-       local load = math.floor((charge/max_charge)*100)
-       meta:set_string("formspec",
-                               "invsize[8,4;]"..
-                               "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
-                                               (load)..":technic_power_meter_fg.png]"..
-                               "label[0,0;Water Mill]"..
-                               "label[1,3;Power level]"..
-                               "label[4,0;Production at "..tostring(production_level).."%]"
-                               )
+                 local load = 1 -- math.floor((charge/max_charge)*100)
+                 meta:set_string("formspec",
+                                 "invsize[8,4;]"..
+                                    "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:"..
+                                    (load)..":technic_power_meter_fg.png]"..
+                                 "label[0,0;Water Mill]"..
+                                 "label[1,3;Power level]"..
+                                 "label[4,0;Production at "..tostring(production_level).."%]"
+                           )
                                
-       if production_level>0 and minetest.env:get_node(pos).name=="technic:water_mill" then
-               hacky_swap_node (pos,"technic:water_mill_active")
-               return
-       end
-       if production_level==0 then hacky_swap_node (pos,"technic:water_mill") end
-end
-}) 
-
-function check_node_around_mill (pos)
-local node=minetest.env:get_node(pos)
-if node.name=="default:water_flowing"  then return 1 end
-return 0
-end
+                 if production_level>0 and minetest.env:get_node(pos).name=="technic:water_mill" then
+                    hacky_swap_node (pos,"technic:water_mill_active")
+                    meta:set_int("LV_EU_supply", 0)
+                    return
+                 end
+                 if production_level==0 then hacky_swap_node (pos,"technic:water_mill") end
+              end
+   }) 
 
-register_LV_machine ("technic:water_mill","PR")
-register_LV_machine ("technic:water_mill_active","PR")
+technic.register_LV_machine ("technic:water_mill","PR")
+technic.register_LV_machine ("technic:water_mill_active","PR")