ShadowNinja
2013-10-30 be2f30a1a2f5b6c2aae7fd4cf8231aec2da0844d
commit | author | age
ee0765 1
be2f30 2 local S = technic.getter
S 3
ee0765 4 minetest.register_craft({
S 5     recipe = {
6         {"default:steelblock", "pipeworks:filter",           "default:steelblock"},
7         {"default:steelblock", "technic:motor",              "default:steelblock"},
8         {"default:steelblock", "technic:diamond_drill_head", "default:steelblock"}},
9     output = "technic:quarry",
10 })
11
12 local quarry_dig_above_nodes = 3 -- How far above the quarry we will dig nodes
13 local quarry_max_depth       = 100
14
15 local function get_quarry_formspec(size)
16     return "size[3,1.5]"..
17         "field[1,0.5;2,1;size;Radius;"..size.."]"..
be2f30 18         "button[0,1;3,1;toggle;"..S("Enable/Disable").."]"
ee0765 19 end
S 20
21 local function quarry_receive_fields(pos, formname, fields, sender)
22     local meta = minetest.get_meta(pos)
23     local size = tonumber(fields.size)
24
25     if fields.toggle then
26         if meta:get_int("enabled") == 0 then
27             meta:set_int("enabled", 1)
28         else
29             meta:set_int("enabled", 0)
30         end
31     end
32
33     -- Smallest size is 2. Anything less is asking for trouble.
34     -- Largest is 8. It is a matter of pratical node handling.
35     size = math.max(size, 2)
36     size = math.min(size, 8)
37
38     if meta:get_int("size") ~= size then
39         meta:set_int("size", size)
40         meta:set_string("formspec", get_quarry_formspec(size))
41     end
42 end
43
44 local function get_quarry_center(pos, size)
45     local node     = minetest.get_node(pos)
46     local back_dir = minetest.facedir_to_dir(node.param2)
47     local relative_center = vector.multiply(back_dir, size + 1)
48     local center = vector.add(pos, relative_center)
49     return center
50 end
51
52 local function gen_next_digpos(center, digpos, size)
53     digpos.x = digpos.x + 1
54     if digpos.x > center.x + size then
55         digpos.x = center.x - size
56         digpos.z = digpos.z + 1
57     end
58     if digpos.z > center.z + size then
59         digpos.x = center.x - size
60         digpos.z = center.z - size
61         digpos.y = digpos.y - 1
62     end
63 end
64
65 local function find_next_digpos(data, area, center, dig_y, size)
66     local c_air = minetest.get_content_id("air")
67
68     for y = center.y + quarry_dig_above_nodes, dig_y - 1, -1 do
69     for z = center.z - size, center.z + size do
70     for x = center.x - size, center.x + size do
71         if data[area:index(x, y, z)] ~= c_air then
72             return vector.new(x, y, z)
73         end
74     end
75     end
76     end
77 end
78
79 local function quarry_dig(pos, center, size)
80     local meta = minetest.get_meta(pos)
81     local drops = {}
82     local dig_y = meta:get_int("dig_y")
83     local owner = meta:get_int("owner")
84
85     local vm = VoxelManip()
86     local p1 = vector.new(
87             center.x - size,
88             center.y + quarry_dig_above_nodes,
89             center.z - size)
90     local p2 = vector.new(
91             center.x + size,
92             dig_y - 1, -- One node lower in case we have finished the current layer
93             center.z + size)
94     local e1, e2 = vm:read_from_map(p1, p2)
95     local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
96     local data = vm:get_data()
97
98     local digpos = find_next_digpos(data, area, center, dig_y, size)
99
100     if digpos then
101         if digpos.y < pos.y - quarry_max_depth then
102             meta:set_int("dig_y", digpos.y)
103             return drops
104         end
105         if minetest.is_protected and minetest.is_protected(digpos, owner) then
106             meta:set_int("enabled", 0)
107             return
108         end
109         dig_y = digpos.y
110         local node = minetest.get_node(digpos)
111         drops = minetest.get_node_drops(node.name, "")
112         minetest.dig_node(digpos)
113         if minetest.get_node(digpos).name == node.name then
114             -- We tried to dig something undigable like a
115             -- filled chest. Notice that we check for a node
116             -- change, not for air. This is so that we get drops
117             -- from things like concrete posts with platforms,
118             -- which turn into regular concrete posts when dug.
119             drops = {}
120         end
121     elseif not (dig_y < pos.y - quarry_max_depth) then
122         dig_y = dig_y - 16
123     end
124
125     meta:set_int("dig_y", dig_y)
126     return drops
127 end
128
129 local function send_items(items, pos, node)
130     for _, item in pairs(items) do
131         local tube_item = tube_item(vector.new(pos), item)
132         tube_item:get_luaentity().start_pos = vector.new(pos)
133         tube_item:setvelocity(vector.new(0, 1, 0))
134         tube_item:setacceleration({x=0, y=0, z=0})
135     end
136 end
137
138 minetest.register_node("technic:quarry", {
be2f30 139     description = S("Quarry"),
ee0765 140     tiles = {"default_steel_block.png", "default_steel_block.png",
S 141              "default_steel_block.png", "default_steel_block.png",
142              "default_steel_block.png^default_tool_mesepick.png", "default_steel_block.png"},
143     paramtype2 = "facedir",
144     groups = {cracky=2, tubedevice=1},
145     tube = {
146         connect_sides = {top = 1},
147     },
148     on_construct = function(pos)
149         local size = 4
150         local meta = minetest.get_meta(pos)
be2f30 151         meta:set_string("infotext", S("Quarry"))
ee0765 152         meta:set_string("formspec", get_quarry_formspec(4))
S 153         meta:set_int("size", size)
154         meta:set_int("dig_y", pos.y)
155     end,
156     after_place_node = function(pos, placer, itemstack)
157         local meta = minetest.get_meta(pos)
158         meta:set_string("owner", placer:get_player_name())
159         tube_scanforobjects(pos)
160     end,
161     after_dig_node = tube_scanforobjects,
162     on_receive_fields = quarry_receive_fields,
163 })
164
165 minetest.register_abm({
166     nodenames = {"technic:quarry"},
167     interval = 1,
168     chance = 1,
169     action = function(pos, node, active_object_count, active_object_count_wider)
170         local meta = minetest.get_meta(pos)
171         local size = meta:get_int("size")
172         local eu_input = meta:get_int("HV_EU_input")
173         local demand = 10000
174         local center = get_quarry_center(pos, size)
175         local dig_y = meta:get_int("dig_y")
be2f30 176         local machine_name = S("Quarry")
ee0765 177
S 178         technic.switching_station_timeout_count(pos, "HV")
179
180         if meta:get_int("enabled") == 0 then
be2f30 181             meta:set_string("infotext", S("%s Disabled"):format(machine_name))
ee0765 182             meta:set_int("HV_EU_demand", 0)
S 183             return
184         end
185
186         if eu_input < demand then
be2f30 187             meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
ee0765 188         elseif eu_input >= demand then
be2f30 189             meta:set_string("infotext", S("%s Active"):format(machine_name))
ee0765 190
S 191             local items = quarry_dig(pos, center, size)
192             send_items(items, pos, node)
193
194             if dig_y < pos.y - quarry_max_depth then
be2f30 195                 meta:set_string("infotext", S("%s Finished"):format(machine_name))
ee0765 196             end
S 197         end
198         meta:set_int("HV_EU_demand", demand)
199     end
200 })
201
202 technic.register_machine("HV", "technic:quarry", technic.receiver)
203