diff --git a/sparkmachine/lua/quarry.lua b/sparkmachine/lua/quarry.lua index 27aa94b..7a146f9 100644 --- a/sparkmachine/lua/quarry.lua +++ b/sparkmachine/lua/quarry.lua @@ -2,15 +2,40 @@ local NAME = minetest.get_current_modname() local ENERGYCOST = { static_struts = 20, dynamic_struct = 24, - hardness_mod = 1 + hardness_mod = 1, + mining_cost = 40, } local FORMSPEC = sparktech.add_inventory(32,8, - "list[current_name;quarry;0,0;32,4;]") + "list[current_name;quarry;0,0;16,6;]") +local MAX_SIZE = 64 -local function Position(x, y, z) +local function Position(x, y, z) --- + --- Returns a valid pos as used by the game return {x=x, y=y, z=z} end +local function order(x, y) --- + --- Returns (smaller, bigger) + if x <= y then + return x, y + else + return y,x + end +end + +local function try_drain_energy(target_pos, amount) --- + --- Returns true if drained, false otherwise + --- Removes amount energy from target_pos if energy >= amount + local target = minetest.get_meta(target_pos) + local current = target:get_int("energy") + if current >= amount then + target:set_int("energy", current - amount) + return true + else + return false + end +end + local function on_construct(pos, player) player:get_meta():set_string(NAME .. ":quarry_pos" , minetest.pos_to_string(pos)) @@ -21,19 +46,26 @@ local function on_construct(pos, player) end local function dig_node(pos, quarrypos) ---[[ local node = minetest.get_node(pos) - local quarryinv = minetest.get_meta(pos):get_inventory() - minetest.debug(ItemStack(node.name):get_name()) - local itemstack = ItemStack(nil) - itemstack:add_item(node.name) - minetest.debug(itemstack:to_string()) - if quarryinv:room_for_item("quarry", itemstack) then - quarryinv:add_item("quarry", itemstack) ]]-- - -- - -- Pretend this puts items in the quarry inventory, okay? - minetest.set_node(pos, {name = "air"}) - --end - + local node = minetest.get_node(pos) + + if node.name ~= "air" and try_drain_energy(quarrypos, ENERGYCOST.mining_cost) then + local quarry = minetest.get_meta(quarrypos) + local quarry_inv = quarry:get_inventory() + + local drops = minetest.get_node_drops(node.name); + local drops_added = 0 + for _, item in pairs(drops) do + if quarry_inv:add_item("quarry", item) then + drops_added = drops_added + 1 + end + end + if drops_added ~= 0 or #drops == 0 then + minetest.set_node(pos, {name = "air"}) + end + + end + + return node.name ~= "air" end local function on_marker_placed(pos, quarry_pos, player) @@ -46,12 +78,28 @@ local function on_marker_placed(pos, quarry_pos, player) -- TODO clear clipboard in quarry on_break end - -- TODO Possibly do a size check + + local minx, maxx = order(pos.x, quarry_pos.x) + local miny, maxy = order(pos.y, quarry_pos.y) + local minz, maxz = order(pos.z, quarry_pos.z) + + local diffx = maxx - minx + local diffy = maxy - miny + local diffz = maxz - minz + + if diffx < 2 or diffx >= MAX_SIZE or + diffy < 2 or diffy >= MAX_SIZE or + diffz < 2 or diffz >= MAX_SIZE + then + notify.hud.sendtext(player, "Invalid dimensions for quarry 3x3x3") +-- minetest.chat_send_player(player:get_player_name(), "Invalid dimensions for quarry") + return + end -- Set quarry metadata local meta = minetest.get_meta(quarry_pos) meta:set_string("marker", minetest.pos_to_string(pos)) - meta:set_int("current_frame", 13) + meta:set_int("current_frame", 1) minetest.get_node_timer(quarry_pos):start(1.0) end @@ -62,14 +110,6 @@ local function marker_construct(pos, player) on_marker_placed(pos, quarry_pos, player) end -local function order(x, y) - if x <= y then - return x, y - else - return y,x - end -end - local function clear_area(pos, pos2) local minx, maxx = order(pos.x, pos2.x) local miny, maxy = order(pos.y, pos2.y) @@ -79,19 +119,25 @@ local function clear_area(pos, pos2) for z=minz, maxz do -- dont remove quarry or marker if not ((x == pos.x and y == pos.y and z == pos.z) or - (x == pos2.x and y == pos2.y and z == pos2.z)) + (x == pos2.x and y == pos2.y and z == pos2.z)) then - dig_node(Position(x, y, z), pos) + if dig_node(Position(x, y, z), pos) then + return false + end end end end end + return true end local function place_strut(x, y, z) local position = Position(x, y, z) if minetest.get_node(position).name == "air" then minetest.set_node(position, { name = NAME .. ":static_strut"}) + return true + else + return false end end @@ -99,75 +145,85 @@ end local function strut_line_x(x, y, z, x2) local minx, maxx = order(x, x2) for x3=minx, maxx do - place_strut(x3, y, z) + if place_strut(x3, y, z) then + return false + end end + return true end local function strut_line_y(x, y, z, y2) local miny, maxy = order(y, y2) for y3=miny, maxy do - place_strut(x, y3, z) + if place_strut(x, y3, z) then + return false + end end + return true end local function strut_line_z(x, y, z, z2) local minz, maxz = order(z, z2) for z3=minz, maxz do - place_strut(x, y, z3) + if place_strut(x, y, z3) then + return false + end end + return true end local function timer_trigger(pos, elapsed) local meta = minetest.get_meta(pos) local framenum = meta:get_int("current_frame") local marker_pos = minetest.string_to_pos(meta:get_string("marker")) - if not framenum then - framenum = 13 - end - if framenum < 0 then - local start_pos = minetest.string_to_pos(meta:get_string("dig_area_start")) - local end_pos = minetest.string_to_pos(meta:get_string("dig_area_end")) - if not start_pos or not end_pos then return end - local height = start_pos.y + framenum - minetest.debug(start_pos.y .. ": " .. height) - for x=start_pos.x, end_pos.x do - for z=start_pos.z, end_pos.z do - minetest.debug(x, z) - dig_node(Position(x, height, z), pos) + + while true do -- Make this section breakable + if framenum < 0 then + minetest.debug("Mine layer") + -- Operation Phase + -- + local start_pos = minetest.string_to_pos(meta:get_string("dig_area_start")) + local end_pos = minetest.string_to_pos(meta:get_string("dig_area_end")) + if not start_pos or not end_pos then return end + local height = start_pos.y + framenum + + local exitloop = false + for x=start_pos.x, end_pos.x do + for z=start_pos.z, end_pos.z do + if dig_node(Position(x, height, z), pos) then + exitloop = true + end + if exitloop then break end + end + if exitloop then break end + end + if not exitloop then + -- Layer cleared, next layer + minetest.debug("Next layer") + framenum = framenum - 1 end - end - -- Operation Phase - -- - else - -- preparation phase - if framenum == 13 then -- stripmine area - clear_area(pos, marker_pos) - elseif framenum == 12 then - strut_line_x(pos.x, pos.y, pos.z, marker_pos.x) - elseif framenum == 11 then - strut_line_x(pos.x, marker_pos.y, pos.z, marker_pos.x) - elseif framenum == 10 then - strut_line_x(pos.x, pos.y, marker_pos.z, marker_pos.x) - elseif framenum == 9 then - strut_line_x(pos.x, marker_pos.y, marker_pos.z, marker_pos.x) - elseif framenum == 8 then - strut_line_z(pos.x, pos.y, pos.z, marker_pos.z) - elseif framenum == 7 then - strut_line_z(marker_pos.x, pos.y, pos.z, marker_pos.z) - elseif framenum == 6 then - strut_line_z(pos.x, marker_pos.y, pos.z, marker_pos.z) - elseif framenum == 5 then - strut_line_z(marker_pos.x, marker_pos.y, pos.z, marker_pos.z) - elseif framenum == 4 then - strut_line_y(marker_pos.x, pos.y, marker_pos.z, marker_pos.y) - elseif framenum == 3 then - strut_line_y(pos.x, pos.y, marker_pos.z, marker_pos.y) - elseif framenum == 2 then - strut_line_y(marker_pos.x, pos.y, pos.z, marker_pos.y) elseif framenum == 1 then - strut_line_y(pos.x, pos.y, pos.z, marker_pos.y) - elseif framenum == 0 then + minetest.debug("Clear area") + -- preparation phase + if clear_area(pos, marker_pos) then + framenum = 0 + end + else + minetest.debug("Build strats") + if not strut_line_x(pos.x, pos.y, pos.z, marker_pos.x) then break end + if not strut_line_x(pos.x, marker_pos.y, pos.z, marker_pos.x) then break end + if not strut_line_x(pos.x, pos.y, marker_pos.z, marker_pos.x) then break end + if not strut_line_x(pos.x, marker_pos.y, marker_pos.z, marker_pos.x) then break end + if not strut_line_z(pos.x, pos.y, pos.z, marker_pos.z) then break end + if not strut_line_z(marker_pos.x, pos.y, pos.z, marker_pos.z) then break end + if not strut_line_z(pos.x, marker_pos.y, pos.z, marker_pos.z) then break end + if not strut_line_z(marker_pos.x, marker_pos.y, pos.z, marker_pos.z) then break end + if not strut_line_y(marker_pos.x, pos.y, marker_pos.z, marker_pos.y) then break end + if not strut_line_y(pos.x, pos.y, marker_pos.z, marker_pos.y) then break end + if not strut_line_y(marker_pos.x, pos.y, pos.z, marker_pos.y) then break end + if not strut_line_y(pos.x, pos.y, pos.z, marker_pos.y) then break end --shrink the operational area here to a 2d space with one piece of border taken away to drill there + -- local posx, pos2x = order(pos.x, marker_pos.x) local posy, pos2y = order(pos.y, marker_pos.y) local posz, pos2z = order(pos.z, marker_pos.z) @@ -178,12 +234,15 @@ local function timer_trigger(pos, elapsed) meta:set_string("dig_area_start", minetest.pos_to_string(Position(posx, posy, posz))) meta:set_string("dig_area_end", minetest.pos_to_string(Position(pos2x, posy, pos2z))) -- can use this last z as counter, or ignore it minetest.debug("setup complete") - + framenum = -1 end - end - meta:set_int("current_frame", framenum -1) - minetest.get_node_timer(pos):start(1.0) + break + end + + meta:set_int("current_frame", framenum) + + if framenum > -MAX_SIZE then minetest.get_node_timer(pos):start(0.1) end end minetest.register_node( NAME .. ":quarry_marker", { @@ -251,6 +310,6 @@ minetest.register_node( NAME .. ":lv_quarry", { after_place_node = on_construct, --on_destruct = function(pos, player) player:get_meta():set_string(NAME .. ":quarry_pos" , "") end, - allow_metadata_inventory_put = function(_,_,_, stack) return stacK:get_count() end, + allow_metadata_inventory_put = function(_,_,_, stack) return stack:get_count() end, allow_metadata_inventory_take = function(_, _, _, stack) return stack:get_count() end })