RealBadAngel
2013-07-25 d8ec3f8bbee5c3c489e4c5740fc8c84449eb86c3
commit | author | age
37d9d9 1 -- The power radiator fuctions like an inductive charger
K 2 -- only better in the game setting.
3 -- The purpose is to allow small appliances to receive power
4 -- without the overhead of the wiring needed for larger machines.
5 --
6 -- The power radiator will consume power corresponding to the
7 -- sum(power rating of the attached appliances)/0.6
8 -- Using inductive power transfer is very inefficient so this is
9 -- set to the factor 0.6.
e64994 10 --
K 11 -- Punching the radiator will toggle the power state of all attached appliances.
12 --
13 local power_radius = 6
37d9d9 14
ee5c6c 15 ------------------------------------------------------------------
37d9d9 16 -- API for inductive powered nodes:
K 17 -- Use the functions below to set the corresponding callbacks
18 -- Also two nodes are needed: The inactive and the active one. The active must be called <name>_active .
ee5c6c 19 ------------------------------------------------------------------
37d9d9 20 -- Register a new appliance using this function
ee5c6c 21 technic.inductive_nodes = {}
K 22 technic.register_inductive_machine = function(name)
23                     table.insert(technic.inductive_nodes, name)
24                     table.insert(technic.inductive_nodes, name.."_active")
25                      end
37d9d9 26
K 27 -- Appliances:
28 --  has_supply: pos of supply node if the appliance has a power radiator near with sufficient power for the demand else ""
29 --  EU_demand: The power demand of the device.
30 --  EU_charge: Actual use. set to EU_demand if active==1
31 --  active: set to 1 if the device is on
ee5c6c 32 technic.inductive_on_construct = function(pos, eu_demand, infotext)
37d9d9 33                     local meta = minetest.env:get_meta(pos)
K 34                     meta:set_string("infotext", infotext)
35                     meta:set_int("technic_inductive_power_machine", 1)
e64994 36                     meta:set_int("EU_demand",eu_demand)     -- The power demand of this appliance
37d9d9 37                     meta:set_int("EU_charge",0)       -- The actual power draw of this appliance
K 38                     meta:set_string("has_supply","") -- Register whether we are powered or not. For use with several radiators.
39                     meta:set_int("active", 0)    -- If the appliance can be turned on and off by using it use this.
40                  end
41
ee5c6c 42 technic.inductive_on_punch_off = function(pos, eu_charge, swapnode)
37d9d9 43             local meta = minetest.env:get_meta(pos)
K 44             if meta:get_string("has_supply") ~= "" then
45                hacky_swap_node(pos, swapnode)
46                meta:set_int("active", 1)
47                meta:set_int("EU_charge",eu_charge)
48                --print("-----------")
49                --print("Turn on:")
50                --print("EUcha:"..meta:get_int("EU_charge"))
51                --print("has_supply:"..meta:get_string("has_supply"))
52                --print("<----------->")
53             end
54          end
55
ee5c6c 56 technic.inductive_on_punch_on = function(pos, eu_charge, swapnode)
37d9d9 57             local meta = minetest.env:get_meta(pos)
K 58             hacky_swap_node(pos, swapnode)
59             meta:set_int("active", 0)
60             meta:set_int("EU_charge",eu_charge)
61             --print("-----------")
62             --print("Turn off:")
63             --print("EUcha:"..meta:get_int("EU_charge"))
64             --print("has_supply:"..meta:get_string("has_supply"))
65             --print("<---------->")
66          end
67
68 local shutdown_inductive_appliances = function(pos)
69                      -- The supply radius
e64994 70                      local rad = power_radius
37d9d9 71                      -- If the radiator is removed. turn off all appliances in region
K 72                      -- If another radiator is near it will turn on the appliances again
ee5c6c 73                      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)
e64994 74                      for _,pos1 in pairs(positions) do
37d9d9 75                         local meta1 = minetest.env:get_meta(pos1)
K 76                         -- If the appliance is belonging to this node
77                         if meta1:get_string("has_supply") == pos.x..pos.y..pos.z then
78                            local nodename = minetest.env:get_node(pos1).name
79                            -- Swap the node and make sure it is off and unpowered
80                            if string.sub(nodename, -7) == "_active" then
81                           hacky_swap_node(pos1, string.sub(nodename, 1, -8))
82                           meta1:set_int("active", 0)
83                           meta1:set_int("EU_charge", 0)
84                            end
85                            meta1:set_string("has_supply", "")
86                        end
87                     end
88                      end
89
e64994 90 local toggle_on_off_inductive_appliances = function(pos, node, puncher)
K 91                           if pos == nil then return end
92                           -- The supply radius
93                           local rad = power_radius
94                           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)
95                           for _,pos1 in pairs(positions) do
96                          local meta1 = minetest.env:get_meta(pos1)
97                          if meta1:get_string("has_supply") == pos.x..pos.y..pos.z then
98                             minetest.env:punch_node(pos1)
99                          end
100                           end
101                        end
37d9d9 102
K 103 minetest.register_node(
104    "technic:power_radiator", {
105       description = "Power Radiator",
9770be 106       tiles  = {"technic_lv_cable.png", "technic_lv_cable.png", "technic_lv_cable.png",
K 107         "technic_lv_cable.png", "technic_lv_cable.png", "technic_lv_cable.png"},
37d9d9 108       groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
K 109       sounds = default.node_sound_wood_defaults(),
110       drawtype = "nodebox",
111       paramtype = "light",
112       is_ground_content = true,
113       node_box = {
114      type = "fixed",
115      fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
116       },
117       selection_box = {
118      type = "fixed",
119      fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
120       },
121       on_construct = function(pos)
122             local meta = minetest.env:get_meta(pos)
123             meta:set_int("technic_mv_power_machine", 1)  -- MV machine
ee5c6c 124             meta:set_int("MV_EU_demand",1)               -- Demand on the primary side when idle
37d9d9 125             meta:set_int("connected_EU_demand",0)        -- Potential demand of connected appliances
K 126             meta:set_string("infotext", "Power Radiator")
127 --            meta:set_int("active", 0)
128              end,
129       on_dig = function(pos, node, digger)
130           shutdown_inductive_appliances(pos)
131           return minetest.node_dig(pos, node, digger)
132            end,
e64994 133       on_punch = function(pos, node, puncher)
K 134             toggle_on_off_inductive_appliances(pos, node, puncher)
135          end
37d9d9 136    })
K 137
138 minetest.register_craft(
139    {
140       output = 'technic:power_radiator 1',
141       recipe = {
142      {'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot'},
143      {'technic:copper_coil',           'technic:mv_transformer',        'technic:copper_coil'},
144      {'technic:rubber',                'technic:mv_cable',              'technic:rubber'},
145       }
146    })
147
148 minetest.register_abm(
149    {nodenames = {"technic:power_radiator"},
150     interval   = 1,
151     chance     = 1,
152     action = function(pos, node, active_object_count, active_object_count_wider)
153         local meta             = minetest.env:get_meta(pos)
ee5c6c 154         local eu_input  = meta:get_int("MV_EU_input")
K 155         local eu_demand = meta:get_int("MV_EU_demand")
156
157         -- Power off automatically if no longer connected to a switching station
158         technic.switching_station_timeout_count(pos, "MV")
159
160         if eu_input == 0 then
161            -- No power
162            meta:set_string("infotext", "Power Radiator is unpowered");
163 --              meta:set_int("active",1) -- used for setting textures someday maybe
164            shutdown_inductive_appliances(pos)
e64994 165            meta:set_int("connected_EU_demand", 0)
4c6546 166            meta:set_int("MV_EU_demand",1)
ee5c6c 167         elseif eu_input == eu_demand then
K 168            -- Powered and ready
169
170            -- The maximum EU sourcing a single radiator can provide.
171            local max_charge          = 3000 -- == the max EU demand of the radiator
172            local connected_EU_demand = meta:get_int("connected_EU_demand")
173
37d9d9 174            -- Efficiency factor
K 175            local eff_factor = 0.6
176            -- The supply radius
e64994 177            local rad = power_radius
37d9d9 178            
K 179            local meta1            = nil
180            local pos1             = {}
181            local used_charge      = 0
182            
183            -- Index all nodes within supply range
ee5c6c 184            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)
e64994 185            for _,pos1 in pairs(positions) do
37d9d9 186               local meta1 = minetest.env:get_meta(pos1)
K 187               -- If not supplied see if this node can handle it.
188               if meta1:get_string("has_supply") == "" then
189              -- if demand surpasses the capacity of this node, don't bother adding it.
e64994 190              local app_eu_demand = math.floor(meta1:get_int("EU_demand")/eff_factor)
ee5c6c 191              if connected_EU_demand + app_eu_demand <= max_charge then
e64994 192                 --print("I can supply this:"..connected_EU_demand.."|"..app_eu_demand.."<="..max_charge.."|act:"..meta1:get_int("EU_charge"))
37d9d9 193                 -- We can power the appliance. Register, and spend power if it is on.
ee5c6c 194                 connected_EU_demand = connected_EU_demand + app_eu_demand
37d9d9 195
K 196                 meta1:set_string("has_supply", pos.x..pos.y..pos.z)
e64994 197                 --Always 0: used_charge = math.floor(used_charge+meta1:get_int("EU_charge")/eff_factor)
37d9d9 198              end
K 199               elseif meta1:get_string("has_supply") == pos.x..pos.y..pos.z then
200              -- The appliance has power from this node. Spend power if it is on.
e64994 201              used_charge = used_charge+math.floor(meta1:get_int("EU_charge")/eff_factor)
K 202              --print("My Lamp ("..pos.x..","..pos.y..","..pos.z..") Used:"..used_charge.."Max:"..max_charge)
37d9d9 203               end
ee5c6c 204               meta:set_string("infotext", "Power Radiator is powered ("..math.floor(used_charge/max_charge*100).."% of maximum power)");
K 205               if used_charge == 0 then
206              meta:set_int("MV_EU_demand", 1) -- Still idle
207               else
208              meta:set_int("MV_EU_demand", used_charge)
209               end
37d9d9 210 --              meta:set_int("active",1) -- used for setting textures someday maybe
K 211            end
ee5c6c 212            -- Save state
K 213            meta:set_int("connected_EU_demand",connected_EU_demand)
37d9d9 214         else
ee5c6c 215            -- This is the case where input ~= demand. Overloaded or underpowered!
K 216 --           --If demand surpasses actual supply turn off everything - we are out of power
217 --           if used_charge>eu_input then
218 --              meta:set_string("infotext", "Power Radiator is overloaded ("..math.floor(used_charge/eu_input*100).."% of available power)");
219 ----              meta:set_int("active",1) -- used for setting textures someday maybe
220 --              shutdown_inductive_appliances(pos)
221 --              connected_EU_demand = 0
37d9d9 222         end
K 223          end,
224  })
225
ee5c6c 226 technic.register_MV_machine ("technic:power_radiator","RE")