diff --git a/technic/machines/HV/quarry.lua b/technic/machines/HV/quarry.lua index 0187a30..ee4f05a 100644 --- a/technic/machines/HV/quarry.lua +++ b/technic/machines/HV/quarry.lua @@ -13,6 +13,41 @@ local quarry_dig_above_nodes = 3 -- How far above the quarry we will dig nodes local quarry_max_depth = 100 local quarry_demand = 10000 +-- keeps the quarry and the full dig zone loaded +-- pos - the position of the quarry +-- pos1,pos2 - two opposite corner positions that mark the zone to force load +local function forceload_dig(pos, pos1, pos2) + if not technic.auto_forceloading_enabled then + return + end + local meta = minetest.get_meta(pos) + + minpos = vector.new(math.min(pos.x, pos1.x, pos2.x), math.min(pos.y, pos1.y, pos2.y), math.min(pos.z, pos1.z, pos2.z)) + maxpos = vector.new(math.max(pos.x, pos1.x, pos2.x), math.max(pos.y, pos1.y, pos2.y), math.max(pos.z, pos1.z, pos2.z)) + + flpos = technic.compute_forceload_positions_between_points(minpos, maxpos) + technic.forceload_on_flposes(flpos, meta) + print("DEBUG: forceload_dig(), currently forceloaded = " .. dump(technic.currently_forceloaded_positions(meta))) +end + +-- keeps only the quarry loaded +local function forceload_purge(pos) + if not technic.auto_forceloading_enabled then + return + end + local meta = minetest.get_meta(pos) + flpos = technic.compute_forceload_positions_between_points(pos, pos) + technic.forceload_on_flposes(flpos, meta) + print("DEBUG: forceload_dig(), currently forceloaded = " .. dump(technic.currently_forceloaded_positions(meta))) +end + +local function forceload_off(meta) + if not technic.auto_forceloading_enabled then + return + end + technic.forceload_off(meta) +end + local function set_quarry_formspec(meta) local radius = meta:get_int("size") local formspec = "size[6,4.3]".. @@ -78,6 +113,7 @@ local function quarry_handle_purge(pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local i = 0 + forceload_purge(pos) for _,stack in ipairs(inv:get_list("cache")) do i = i + 1 if stack then @@ -107,21 +143,43 @@ local function quarry_run(pos, node) end if meta:get_int("enabled") and meta:get_int("HV_EU_input") >= quarry_demand and meta:get_int("purge_on") == 0 then + -- the direction the quarry faces local pdir = minetest.facedir_to_dir(node.param2) + -- the direction to the right of where the quarry faces local qdir = pdir.x == 1 and vector.new(0,0,-1) or (pdir.z == -1 and vector.new(-1,0,0) or (pdir.x == -1 and vector.new(0,0,1) or vector.new(1,0,0))) local radius = meta:get_int("size") local diameter = radius*2 + 1 - local startpos = vector.add(vector.add(vector.add(pos, - vector.new(0, quarry_dig_above_nodes, 0)), - pdir), - vector.multiply(qdir, -radius)) - local endpos = vector.add(vector.add(vector.add(startpos, - vector.new(0, -quarry_dig_above_nodes-quarry_max_depth, 0)), - vector.multiply(pdir, diameter-1)), - vector.multiply(qdir, diameter-1)) + -- the back left top corner of the digging zone + local startpos = vector.add( + vector.add( + vector.add( + pos, + vector.new(0, quarry_dig_above_nodes, 0) + ), + pdir + ), + vector.multiply(qdir, -radius) + ) + -- the forward right bottom corner of the digging zone + local endpos = vector.add( + vector.add( + vector.add( + startpos, + vector.new(0, -quarry_dig_above_nodes-quarry_max_depth, 0) + ), + vector.multiply(pdir, diameter-1) + ), + vector.multiply(qdir, diameter-1) + ) + + --TEST +-- print("DEBUG: startpos = (" .. startpos.x .. "," .. startpos.y .. "," .. startpos.z .. ")") +-- print("DEBUG: endpos = (" .. endpos.x .. "," .. endpos.y .. "," .. endpos.z .. ")") + forceload_dig(pos, startpos, endpos) + local vm = VoxelManip() local minpos, maxpos = vm:read_from_map(startpos, endpos) local area = VoxelArea:new({MinEdge=minpos, MaxEdge=maxpos}) @@ -236,6 +294,10 @@ minetest.register_node("technic:quarry", { set_quarry_formspec(meta) set_quarry_demand(meta) end, + on_destruct = function (pos) + local meta = minetest.get_meta(pos) + forceload_off(meta) + end, after_place_node = function(pos, placer, itemstack) local meta = minetest.get_meta(pos) meta:set_string("owner", placer:get_player_name()) diff --git a/technic/machines/other/anchor.lua b/technic/machines/other/anchor.lua index df8d576..cdc906c 100644 --- a/technic/machines/other/anchor.lua +++ b/technic/machines/other/anchor.lua @@ -2,6 +2,9 @@ local S = technic.getter local desc = S("Administrative World Anchor") +-- set to false to disable autoforceloading in other files, such as the quarry force loading itself and dig area +technic.auto_forceloading_enabled = true + -- pos - position of the anchor node -- meta - contains "radius" -- return table of positions, one position per block @@ -9,6 +12,12 @@ local function compute_forceload_positions(pos, meta) local radius = meta:get_int("radius") local minpos = vector.subtract(pos, vector.new(radius, radius, radius)) local maxpos = vector.add(pos, vector.new(radius, radius, radius)) + return compute_forceload_positions_between_points(minpos, maxpos) +end + +-- minpos,maxpos - two opposite corner positions that mark the zone to force load; all coordinates in minpos have to be lower than the ones in maxpos +-- return table of positions, one position per block +local function compute_forceload_positions_between_points(minpos, maxpos) local minbpos = {} local maxbpos = {} for _, coord in ipairs({"x","y","z"}) do @@ -25,6 +34,7 @@ local function compute_forceload_positions(pos, meta) end return flposes end +technic.compute_forceload_positions_between_points = compute_forceload_positions_between_points -- meta - contains "forceloaded", which is a serialized table of positions that are currently forceloaded -- return table of positions that are currently forceloaded @@ -32,6 +42,7 @@ local function currently_forceloaded_positions(meta) local ser = meta:get_string("forceloaded") return ser == "" and {} or minetest.deserialize(ser) end +technic.currently_forceloaded_positions = currently_forceloaded_positions -- turns off forceloading for all positions in the table -- meta - contains "forceloaded" (used by currently_forceloaded_positions) @@ -42,12 +53,18 @@ local function forceload_off(meta) minetest.forceload_free_block(p) end end +technic.forceload_off = forceload_off --- computes the forceload positions (using compute_forceload_positions) and tries to force load all of them, and records them in meta "forcedloaded" +-- computes the forceload positions (using compute_forceload_positions) and tries to force load all of them, and records them in meta "forceloaded" -- pos - position of the anchor node -- meta - contains "radius" (to be read) and "forceloaded" (to be written) local function forceload_on(pos, meta) local want_flposes = compute_forceload_positions(pos, meta) + forceload_on_flposes(want_flposes, meta) + return +end + +local function forceload_on_flposes(want_flposes, meta) local have_flposes = {} for _, p in ipairs(want_flposes) do if minetest.forceload_block(p) then @@ -56,6 +73,7 @@ local function forceload_on(pos, meta) end meta:set_string("forceloaded", #have_flposes == 0 and "" or minetest.serialize(have_flposes)) end +technic.forceload_on_flposes = forceload_on_flposes local function set_display(pos, meta) meta:set_string("infotext", S(meta:get_int("enabled") ~= 0 and "%s Enabled" or "%s Disabled"):format(desc))