Pascal Abresch 13b78ff838 Added math.order
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
2019-10-04 04:38:18 +02:00

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" }
}
})