apparently builtin already has the math. namespace, testing for it doesn't seam to work? but assigning an empty table over it makes it angry, so lets not do that
326 lines
8.9 KiB
Lua
326 lines
8.9 KiB
Lua
local NAME = minetest.get_current_modname()
|
|
local ENERGYCOST = {
|
|
static_strut = 20,
|
|
dynamic_struct = 24,
|
|
hardness_mod = 1,
|
|
mining_cost = 25,
|
|
}
|
|
local FORMSPEC = sparktech.add_inventory(19.8,8,
|
|
"list[current_name;quarry;0,0;16,6;]")
|
|
local MAX_SIZE = 64
|
|
|
|
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 try_drain_energy(target_pos, amount) ---
|
|
--- Returns true if drained, false otherwise
|
|
--- Removes amount energy from target_pos if energy >= amount
|
|
minetest.debug("try_drain")
|
|
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 try_remove_item(target_pos, listname, itemname, amount)
|
|
local inv = minetest.get_inventory({type="node", pos=target_pos})
|
|
local stack = ItemStack(itemname)
|
|
local amount = amount or 1
|
|
stack:set_count(amount)
|
|
|
|
local result = inv:remove_item(listname, stack)
|
|
|
|
if result:get_count() ~= amount then
|
|
inv:add_item(listname, result)
|
|
else
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
local function on_construct(pos, player)
|
|
player:get_meta():set_string(NAME .. ":quarry_pos" , minetest.pos_to_string(pos))
|
|
|
|
minetest.debug("on_construct")
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec", FORMSPEC)
|
|
local inventory = meta:get_inventory()
|
|
inventory:set_size('quarry', 96)
|
|
end
|
|
|
|
local function dig_node(pos, quarrypos)
|
|
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)
|
|
-- Validate position
|
|
if quarry_pos.x == pos.x and
|
|
quarry_pos.y == pos.y and
|
|
quarry_pos.z == pos.z then
|
|
-- Invalid position, marker replaced quarry somehow
|
|
return -- TODO Report failure?
|
|
-- TODO clear clipboard in quarry on_break
|
|
|
|
end
|
|
|
|
local minx, maxx = math.order(pos.x, quarry_pos.x)
|
|
local miny, maxy = math.order(pos.y, quarry_pos.y)
|
|
local minz, maxz = math.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")
|
|
return
|
|
end
|
|
|
|
-- Set quarry metadata
|
|
minetest.debug("on marker placed")
|
|
local meta = minetest.get_meta(quarry_pos)
|
|
meta:set_string("marker", minetest.pos_to_string(pos))
|
|
meta:set_int("current_frame", 1)
|
|
|
|
minetest.get_node_timer(quarry_pos):start(1.0)
|
|
end
|
|
|
|
local function marker_construct(pos, player)
|
|
local quarry_pos = minetest.string_to_pos(player:get_meta():get_string(NAME .. ":quarry_pos"))
|
|
local quarry = minetest.get_node(quarry_pos)
|
|
on_marker_placed(pos, quarry_pos, player)
|
|
end
|
|
|
|
local function place_strut(position, quarrypos)
|
|
if minetest.get_node(position).name == "air" then
|
|
local placed = false
|
|
if try_remove_item(quarrypos, "quarry", NAME .. ":static_strut") then
|
|
if try_drain_energy(quarrypos, ENERGYCOST.static_strut) then
|
|
minetest.set_node(position, { name = NAME .. ":static_strut"})
|
|
placed = true
|
|
else
|
|
-- TODO Restore items
|
|
end
|
|
end
|
|
return true, placed
|
|
end
|
|
return false, false
|
|
end
|
|
|
|
local function prepare_area(pos, pos2)
|
|
local placement_done = true
|
|
local minx, maxx = math.order(pos.x, pos2.x)
|
|
local miny, maxy = math.order(pos.y, pos2.y)
|
|
local minz, maxz = math.order(pos.z, pos2.z)
|
|
for x=minx , maxx do
|
|
for y=miny, maxy do
|
|
for z=minz, maxz do
|
|
-- dont remove quarry or marker
|
|
if not (x == pos.x and y == pos.y and z == pos.z) then
|
|
local count = 0
|
|
if x == pos.x then count = count +1 end
|
|
if x == pos2.x then count = count +1 end
|
|
if y == pos.y then count = count +1 end
|
|
if y == pos2.y then count = count +1 end
|
|
if z == pos.z then count = count +1 end
|
|
if z == pos2.z then count = count +1 end
|
|
if count >= 2 then
|
|
local node = minetest.get_node(Position(x, y, z))
|
|
if node.name ~= NAME .. ":static_strut" then
|
|
if node.name ~= "air" then
|
|
dig_node(Position(x, y, z), pos)
|
|
return false
|
|
end
|
|
local incomplete, placed = place_strut(Position(x, y, z), pos)
|
|
if placed then
|
|
return false
|
|
end
|
|
|
|
if incomplete then
|
|
placement_done = false
|
|
end
|
|
end
|
|
else
|
|
if dig_node(Position(x, y, z), pos) then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return placement_done --true: cleared
|
|
end
|
|
|
|
|
|
local function timer_trigger(pos, elapsed)
|
|
minetest.debug("timer elapsed")
|
|
local meta = minetest.get_meta(pos)
|
|
if not meta then assert("FUCK") end
|
|
local framenum = meta:get_int("current_frame")
|
|
local marker_pos = minetest.string_to_pos(meta:get_string("marker"))
|
|
|
|
while true do -- Make this section breakable
|
|
if framenum < 0 then
|
|
-- 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
|
|
framenum = framenum - 1
|
|
end
|
|
elseif framenum == 1 then
|
|
-- preparation phase
|
|
if prepare_area(pos, marker_pos) then
|
|
framenum = 0
|
|
end
|
|
else
|
|
--shrink the operational area here to a 2d space with one piece of border taken away to drill there
|
|
--
|
|
local posx, pos2x = math.order(pos.x, marker_pos.x)
|
|
local posy, pos2y = math.order(pos.y, marker_pos.y)
|
|
local posz, pos2z = math.order(pos.z, marker_pos.z)
|
|
posx = posx +1
|
|
pos2x = pos2x -1
|
|
posz = posz + 1
|
|
pos2z = pos2z -1
|
|
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
|
|
framenum = -1
|
|
end
|
|
|
|
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", {
|
|
descritption = "quarry marker",
|
|
tiles = {
|
|
NAME .. "marker.png"
|
|
},
|
|
groups = { sparktech_techy = 1 },
|
|
after_place_node = marker_construct,
|
|
})
|
|
|
|
minetest.register_node( NAME .. ":static_strut", {
|
|
description = "supporting strut",
|
|
drawtype = "nodebox",
|
|
paramtype = "light",
|
|
connects_to = {
|
|
NAME .. ":static_strut",
|
|
NAME .. ":quarry_marker",
|
|
NAME .. ":lv_quarry"
|
|
},
|
|
tiles = {
|
|
NAME .. "_strut.png"
|
|
},
|
|
node_box = {
|
|
type = "connected",
|
|
fixed = {-0.2, -0.2, -0.2, 0.2, 0.2, 0.2},
|
|
connect_top = {-0.2, 0.2, -0.2, 0.2, 0.5, 0.2},
|
|
connect_bottom = {-0.2, -0.5, -0.2, 0.2, -0.2, 0.2},
|
|
connect_back = {-0.2, -0.2, 0.2, 0.2, 0.2, 0.5},
|
|
connect_right = {0.2, -0.2, -0.2, 0.5, 0.2, 0.2},
|
|
connect_front = {-0.2, -0.2, -0.5, 0.2, 0.2, -0.2},
|
|
connect_left = {-0.5, -0.2, -0.2, -0.2, 0.2, 0.2},
|
|
},
|
|
groups = { sparktech_techy = 1 }
|
|
})
|
|
|
|
minetest.register_node( NAME .. ":lv_quarry", {
|
|
description = "Electric Quarry",
|
|
|
|
tiles = {
|
|
NAME .. "_steel_sideplate.png",
|
|
NAME .. "_steel_sideplate.png",
|
|
NAME .. "_steel_sideplate.png",
|
|
NAME .. "_steel_sideplate.png",
|
|
NAME .. "_steel_backplate.png",
|
|
NAME .. "_quarry_frontplate.png"
|
|
},
|
|
paramtype2 = "facedir",
|
|
|
|
groups = {
|
|
sparktech_techy = 1,
|
|
sparktech_struty = 1,
|
|
sparktech_energy_type = 4,
|
|
sparktech_net_trigger = 1,
|
|
sparktech_energy_max = 3000,
|
|
spark_energy_timer = 2
|
|
},
|
|
|
|
on_timer = timer_trigger,
|
|
|
|
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_take = function(_, _, _, stack) return stack:get_count() end
|
|
})
|
|
minetest.register_craft({
|
|
output = NAME .. ":lv_quarry",
|
|
recipe = {
|
|
{ NAME .. ":static_strut", "sparktool:handdrill", NAME .. ":static_strut" },
|
|
{ NAME .. ":static_strut", "group:steel_chasis", NAME .. ":static_strut" },
|
|
{ NAME .. ":static_strut", "sparkcore:cable", NAME .. ":static_strut" }
|
|
}
|
|
})
|
|
|
|
|
|
minetest.register_craft({
|
|
output = NAME .. ":static_strut 16",
|
|
recipe = {
|
|
{ "group:steel_plate", "group:steel_plate", "group:steel_plate" },
|
|
{ "", "", "" },
|
|
{ "group:steel_plate", "group:steel_plate", "group:steel_plate" }
|
|
}
|
|
})
|