Tim
2015-03-16 137695ea67cf7096311c893de7cf139e6307b26b
commit | author | age
ee0765 1
be2f30 2 local S = technic.getter
S 3
ee0765 4 minetest.register_craft({
S 5     recipe = {
5e4a87 6         {"technic:carbon_plate",       "pipeworks:filter",       "technic:composite_plate"},
68ea0a 7         {"technic:motor",              "technic:machine_casing", "technic:diamond_drill_head"},
Z 8         {"technic:carbon_steel_block", "technic:hv_cable0",      "technic:carbon_steel_block"}},
ee0765 9     output = "technic:quarry",
S 10 })
11
12 local quarry_dig_above_nodes = 3 -- How far above the quarry we will dig nodes
13 local quarry_max_depth       = 100
d0efa1 14 local quarry_demand = 10000
ee0765 15
b74c2d 16 local function set_quarry_formspec(meta)
d0efa1 17     local radius = meta:get_int("size")
86dd58 18     local formspec = "size[6,4.3]"..
E 19         "list[context;cache;0,1;4,3;]"..
20         "item_image[4.8,0;1,1;technic:quarry]"..
21         "label[0,0.2;"..S("%s Quarry"):format("HV").."]"..
22         "field[4.3,3.5;2,1;size;"..S("Radius:")..";"..radius.."]"
b74c2d 23     if meta:get_int("enabled") == 0 then
86dd58 24         formspec = formspec.."button[4,1;2,1;enable;"..S("Disabled").."]"
b74c2d 25     else
86dd58 26         formspec = formspec.."button[4,1;2,1;disable;"..S("Enabled").."]"
b74c2d 27     end
d0efa1 28     local diameter = radius*2 + 1
Z 29     local nd = meta:get_int("dug")
30     local rel_y = quarry_dig_above_nodes - math.floor(nd / (diameter*diameter))
86dd58 31     formspec = formspec.."label[0,4;"..minetest.formspec_escape(
d0efa1 32             nd == 0 and S("Digging not started") or
Z 33             (rel_y < -quarry_max_depth and S("Digging finished") or
86dd58 34                 (meta:get_int("purge_on") == 1 and S("Purging cache") or
d0efa1 35                 S("Digging %d m "..(rel_y > 0 and "above" or "below").." machine")
86dd58 36                     :format(math.abs(rel_y))))
d0efa1 37             ).."]"
Z 38     formspec = formspec.."button[4,2;2,1;restart;"..S("Restart").."]"
b74c2d 39     meta:set_string("formspec", formspec)
d0efa1 40 end
Z 41
42 local function set_quarry_demand(meta)
43     local radius = meta:get_int("size")
44     local diameter = radius*2 + 1
45     local machine_name = S("%s Quarry"):format("HV")
86dd58 46     if meta:get_int("enabled") == 0 or meta:get_int("purge_on") == 1 then
E 47         meta:set_string("infotext", S(meta:get_int("purge_on") == 1 and "%s purging cache" or "%s Disabled"):format(machine_name))
d0efa1 48         meta:set_int("HV_EU_demand", 0)
Z 49     elseif meta:get_int("dug") == diameter*diameter * (quarry_dig_above_nodes+1+quarry_max_depth) then
50         meta:set_string("infotext", S("%s Finished"):format(machine_name))
51         meta:set_int("HV_EU_demand", 0)
52     else
53         meta:set_string("infotext", S(meta:get_int("HV_EU_input") >= quarry_demand and "%s Active" or "%s Unpowered"):format(machine_name))
54         meta:set_int("HV_EU_demand", quarry_demand)
55     end
ee0765 56 end
S 57
58 local function quarry_receive_fields(pos, formname, fields, sender)
59     local meta = minetest.get_meta(pos)
d0efa1 60     if fields.size and string.find(fields.size, "^[0-9]+$") then
Z 61         local size = tonumber(fields.size)
62         if size >= 2 and size <= 8 and size ~= meta:get_int("size") then
63             meta:set_int("size", size)
64             meta:set_int("dug", 0)
65         end
ee0765 66     end
b74c2d 67     if fields.enable then meta:set_int("enabled", 1) end
Z 68     if fields.disable then meta:set_int("enabled", 0) end
86dd58 69     if fields.restart then
E 70         meta:set_int("dug", 0)
71         meta:set_int("purge_on", 1)
72     end
b74c2d 73     set_quarry_formspec(meta)
d0efa1 74     set_quarry_demand(meta)
ee0765 75 end
S 76
86dd58 77 local function quarry_handle_purge(pos)
E 78     local meta = minetest.get_meta(pos)
79     local inv = meta:get_inventory()
80     local i = 0
81     for _,stack in ipairs(inv:get_list("cache")) do
82         i = i + 1
83         if stack then
84             local item = stack:to_table()
85             if item then
86                 technic.tube_inject_item(pos, pos, vector.new(0, 1, 0), item)
87                 stack:clear()
88                 inv:set_stack("cache", i, stack)
89                 break
90             end
91         end
92     end
93     if inv:is_empty("cache") then
94         meta:set_int("purge_on", 0)
95     end
96 end
97
d0efa1 98 local function quarry_run(pos, node)
ee0765 99     local meta = minetest.get_meta(pos)
86dd58 100     local inv = meta:get_inventory()
E 101     -- initialize cache for the case we load an older world
102     inv:set_size("cache", 12)
103     -- toss a coin whether we do an automatic purge. Chance 1:200
104     local purge_rand = math.random()
105     if purge_rand <= 0.005 then
106         meta:set_int("purge_on", 1)
107     end
108
109     if meta:get_int("enabled") and meta:get_int("HV_EU_input") >= quarry_demand and meta:get_int("purge_on") == 0 then
d0efa1 110         local pdir = minetest.facedir_to_dir(node.param2)
Z 111         local qdir = pdir.x == 1 and vector.new(0,0,-1) or
112             (pdir.z == -1 and vector.new(-1,0,0) or
113             (pdir.x == -1 and vector.new(0,0,1) or
114             vector.new(1,0,0)))
115         local radius = meta:get_int("size")
116         local diameter = radius*2 + 1
117         local startpos = vector.add(vector.add(vector.add(pos,
118             vector.new(0, quarry_dig_above_nodes, 0)),
119             pdir),
120             vector.multiply(qdir, -radius))
121         local endpos = vector.add(vector.add(vector.add(startpos,
122             vector.new(0, -quarry_dig_above_nodes-quarry_max_depth, 0)),
123             vector.multiply(pdir, diameter-1)),
124             vector.multiply(qdir, diameter-1))
125         local vm = VoxelManip()
126         local minpos, maxpos = vm:read_from_map(startpos, endpos)
127         local area = VoxelArea:new({MinEdge=minpos, MaxEdge=maxpos})
128         local data = vm:get_data()
129         local c_air = minetest.get_content_id("air")
130         local owner = meta:get_string("owner")
131         local nd = meta:get_int("dug")
132         while nd ~= diameter*diameter * (quarry_dig_above_nodes+1+quarry_max_depth) do
133             local ry = math.floor(nd / (diameter*diameter))
134             local ndl = nd % (diameter*diameter)
135             if ry % 2 == 1 then
136                 ndl = diameter*diameter - 1 - ndl
137             end
138             local rq = math.floor(ndl / diameter)
139             local rp = ndl % diameter
140             if rq % 2 == 1 then rp = diameter - 1 - rp end
141             local digpos = vector.add(vector.add(vector.add(startpos,
142                 vector.new(0, -ry, 0)),
143                 vector.multiply(pdir, rp)),
144                 vector.multiply(qdir, rq))
145             local can_dig = true
146             if can_dig and minetest.is_protected and minetest.is_protected(digpos, owner) then
147                 can_dig = false
148             end
149             local dignode
150             if can_dig then
c38da0 151                 dignode = technic.get_or_load_node(digpos) or minetest.get_node(digpos)
d0efa1 152                 local dignodedef = minetest.registered_nodes[dignode.name] or {diggable=false}
Z 153                 if not dignodedef.diggable or (dignodedef.can_dig and not dignodedef.can_dig(digpos, nil)) then
154                     can_dig = false
155                 end
156             end
c38da0 157
E 158             if can_dig then
159                 for ay = startpos.y, digpos.y+1, -1 do
160                     local checkpos = {x=digpos.x, y=ay, z=digpos.z}
161                     local checknode = technic.get_or_load_node(checkpos) or minetest.get_node(checkpos)
162                     if checknode.name ~= "air" then
163                         can_dig = false
164                         break
165                     end
166                 end
167             end
d0efa1 168             nd = nd + 1
Z 169             if can_dig then
170                 minetest.remove_node(digpos)
86dd58 171                 local drops = minetest.get_node_drops(dignode.name, "")
E 172                 for _, dropped_item in ipairs(drops) do
173                     local left = inv:add_item("cache", dropped_item)
174                     while not left:is_empty() do
175                         meta:set_int("purge_on", 1)
176                         quarry_handle_purge(pos)
177                         left = inv:add_item("cache", left)
178                     end
d0efa1 179                 end
Z 180                 break
181             end
ee0765 182         end
86dd58 183         if nd == diameter*diameter * (quarry_dig_above_nodes+1+quarry_max_depth) then
E 184             -- if a quarry is finished, we enable purge mode
185             meta:set_int("purge_on", 1)
186         end
d0efa1 187         meta:set_int("dug", nd)
86dd58 188     else
E 189         -- if a quarry is disabled or has no power, we enable purge mode
190         meta:set_int("purge_on", 1)
191     end
192     -- if something triggered a purge, we handle it
193     if meta:get_int("purge_on") == 1 then
194         quarry_handle_purge(pos)
ee0765 195     end
d0efa1 196     set_quarry_formspec(meta)
Z 197     set_quarry_demand(meta)
86dd58 198 end
E 199
200 local function send_move_error(player)
201     minetest.chat_send_player(player:get_player_name(),
202         S("Manually taking/removing from cache by hand is not possible. "..
203         "If you can't wait, restart or disable the quarry to start automatic purge."))
204     return 0
563a4c 205 end
N 206
ee0765 207 minetest.register_node("technic:quarry", {
7c4b70 208     description = S("%s Quarry"):format("HV"),
68b7bc 209     tiles = {"technic_carbon_steel_block.png", "technic_carbon_steel_block.png",
Z 210              "technic_carbon_steel_block.png", "technic_carbon_steel_block.png",
211              "technic_carbon_steel_block.png^default_tool_mesepick.png", "technic_carbon_steel_block.png"},
f250e1 212     inventory_image = minetest.inventorycube("technic_carbon_steel_block.png",
E 213              "technic_carbon_steel_block.png^default_tool_mesepick.png",
214              "technic_carbon_steel_block.png"),
ee0765 215     paramtype2 = "facedir",
563a4c 216     groups = {cracky=2, tubedevice=1, technic_machine = 1},
ee0765 217     tube = {
S 218         connect_sides = {top = 1},
219     },
220     on_construct = function(pos)
221         local meta = minetest.get_meta(pos)
7c4b70 222         meta:set_string("infotext", S("%s Quarry"):format("HV"))
b74c2d 223         meta:set_int("size", 4)
Z 224         set_quarry_formspec(meta)
d0efa1 225         set_quarry_demand(meta)
ee0765 226     end,
S 227     after_place_node = function(pos, placer, itemstack)
228         local meta = minetest.get_meta(pos)
229         meta:set_string("owner", placer:get_player_name())
ae235e 230         pipeworks.scan_for_tube_objects(pos)
ee0765 231     end,
86dd58 232     can_dig = function(pos,player)
E 233         local meta = minetest.get_meta(pos);
234         local inv = meta:get_inventory()
235         return inv:is_empty("cache")
236     end,
ae235e 237     after_dig_node = pipeworks.scan_for_tube_objects,
ee0765 238     on_receive_fields = quarry_receive_fields,
d0efa1 239     technic_run = quarry_run,
86dd58 240     allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
E 241         return send_move_error(player)
242     end,
243     allow_metadata_inventory_put = function(pos, listname, index, stack, player)
244         return send_move_error(player)
245     end,
246     allow_metadata_inventory_take = function(pos, listname, index, stack, player)
247         return send_move_error(player)
248     end
ee0765 249 })
S 250
251 technic.register_machine("HV", "technic:quarry", technic.receiver)