diff --git a/config/miner.lua b/config/miner.lua new file mode 100644 index 00000000..7ee2a3ab --- /dev/null +++ b/config/miner.lua @@ -0,0 +1,7 @@ +--- Settings for miner +-- @config miner + +return { + fluid = true, --- @setting fluid When true, checks for for fluid pipes when removing miners + chest = true --- @setting chest When true, checks for for chest when removing miners +} diff --git a/modules/addons/miner.lua b/modules/addons/miner.lua index 290577ad..64950a97 100644 --- a/modules/addons/miner.lua +++ b/modules/addons/miner.lua @@ -1,64 +1,183 @@ local Event = require 'utils.event_core' --- @dep utils.event_core +local Global = require 'utils.global' --- @dep utils.global +local config = require 'config.miner' --- @dep config.miner -local function miner_check(entity, event) - if ((math.abs(entity.position.x - event.entity.position.x) < entity.prototype.mining_drill_radius) and (math.abs(entity.position.y - event.entity.position.y) < entity.prototype.mining_drill_radius)) then - if entity.mining_target ~= nil and entity.mining_target.valid then - if entity.mining_target.amount > 0 then - return - end +local miner_data = {} - local resources = entity.surface.find_entities_filtered{area={{entity.position.x - entity.prototype.mining_drill_radius, entity.position.y - entity.prototype.mining_drill_radius}, {entity.position.x + entity.prototype.mining_drill_radius, entity.position.y + entity.prototype.mining_drill_radius}}, type='resource'} +Global.register(miner_data, function(tbl) + miner_data = tbl +end) - for _, resource in pairs(resources) do - if resource.amount > 0 then - -- if any tile in the radius have resources - return - end - end +miner_data.queue = {} - if entity.to_be_deconstructed(entity.force) then - -- if it is already waiting to be deconstruct - return - else - if entity.fluidbox and #entity.fluidbox > 0 then - -- if require fluid to mine - return - end +local function drop_target(entity) + if entity.drop_target then + return entity.drop_target - if next(entity.circuit_connected_entities.red) ~= nil or next(entity.circuit_connected_entities.green) ~= nil then - -- connected to circuit network - return - end + else + local entities = entity.surface.find_entities_filtered{position=entity.drop_position} - if not entity.minable then - -- if it is minable - return - end - - if not entity.prototype.selectable_in_game then - -- if it can select - return - end - - if entity.has_flag('not-deconstructable') then - -- if it can deconstruct - return - end - - entity.order_deconstruction(entity.force) - end + if #entities > 0 then + return entities[1] end end end +local function check_entity(entity) + if entity.to_be_deconstructed(entity.force) then + -- if it is already waiting to be deconstruct + return true + end + + if next(entity.circuit_connected_entities.red) ~= nil or next(entity.circuit_connected_entities.green) ~= nil then + -- connected to circuit network + return true + end + + if not entity.minable then + -- if it is minable + return true + end + + if not entity.prototype.selectable_in_game then + -- if it can select + return true + end + + if entity.has_flag('not-deconstructable') then + -- if it can deconstruct + return true + end + + return false +end + +local function chest_check(entity) + local target = drop_target(entity) + + if check_entity(entity) then + return + end + + if target.type ~= 'logistic-container' and target.type ~= 'container' then + -- not a chest + return + end + + local radius = 2 + local entities = target.surface.find_entities_filtered{area={{target.position.x - radius, target.position.y - radius}, {target.position.x + radius, target.position.y + radius}}, type={'mining-drill', 'inserter'}} + + for _, e in pairs(entities) do + if drop_target(e) == target then + if not e.to_be_deconstructed(entity.force) and e ~= entity then + return + end + end + end + + if check_entity(target) then + table.insert(miner_data.queue, {t=game.tick + 10, e=target}) + end +end + +local function miner_check(entity) + -- if any tile in the radius have resources + if entity.mining_target and entity.mining_target.valid then + if entity.mining_target.amount > 0 then + return + end + end + + local position = entity.position + local radius = entity.prototype.mining_drill_radius + local resources = entity.surface.find_entities_filtered{area={{position.x - radius, position.y - radius}, {position.x + radius, position.y + radius}}, type='resource'} + + for _, resource in pairs(resources) do + if resource.amount > 0 then + return + end + end + + if check_entity(entity) then + return + end + + local pipe_build = {} + + if config.fluid and entity.fluidbox and #entity.fluidbox > 0 then + -- if require fluid to mine + table.insert(pipe_build, {x=0, y=0}) + + local half = math.floor(entity.get_radius()) + radius = 1 + entity.prototype.mining_drill_radius + + local entities = entity.surface.find_entities_filtered{area={{entity.position.x - radius, entity.position.y - radius}, {entity.position.x + radius, entity.position.y + radius}}, type={'mining-drill', 'pipe', 'pipe-to-ground'}} + local entities_t = entity.surface.find_entities_filtered{area={{entity.position.x - radius, entity.position.y - radius}, {entity.position.x + radius, entity.position.y + radius}}, ghost_type={'pipe', 'pipe-to-ground'}} + + table.array_insert(entities, entities_t) + + for _, e in pairs(entities) do + if (e.position.x > entity.position.x) and (e.position.y == entity.position.y) then + for h=1, half do + table.insert(pipe_build, {x=h, y=0}) + end + + elseif (e.position.x < entity.position.x) and (e.position.y == entity.position.y) then + for h=1, half do + table.insert(pipe_build, {x=-h, y=0}) + end + + elseif (e.position.x == entity.position.x) and (e.position.y > entity.position.y) then + for h=1, half do + table.insert(pipe_build, {x=0, y=h}) + end + + elseif (e.position.x == entity.position.x) and (e.position.y < entity.position.y) then + for h=1, half do + table.insert(pipe_build, {x=0, y=-h}) + end + end + end + end + + table.insert(miner_data.queue, {t=game.tick + 5, e=entity}) + + if config.chest then + chest_check(entity) + end + + for _, pos in ipairs(pipe_build) do + entity.surface.create_entity{name='entity-ghost', position={x=entity.position.x + pos.x, y=entity.position.y + pos.y}, force=entity.force, inner_name='pipe', raise_built=true} + end +end + Event.add(defines.events.on_resource_depleted, function(event) - local entities = event.entity.surface.find_entities_filtered{area={{event.entity.position.x-1, event.entity.position.y-1}, {event.entity.position.x+1, event.entity.position.y+1}}, type='mining-drill'} + if event.entity.prototype.infinite_resource then + return + end + + local entities = event.entity.surface.find_entities_filtered{area={{event.entity.position.x - 1, event.entity.position.y - 1}, {event.entity.position.x + 1, event.entity.position.y + 1}}, type='mining-drill'} if #entities == 0 then return end for _, entity in pairs(entities) do - miner_check(entity, event) + if ((math.abs(entity.position.x - event.entity.position.x) < entity.prototype.mining_drill_radius) and (math.abs(entity.position.y - event.entity.position.y) < entity.prototype.mining_drill_radius)) then + miner_check(entity) + end + end +end) + +Event.on_nth_tick(10, function(event) + for k, q in pairs(miner_data.queue) do + if not q.e or not q.e.valid then + table.remove(miner_data.queue, k) + break + + elseif event.tick >= q.t then + q.e.order_deconstruction(q.e.force) + table.remove(miner_data.queue, k) + end end end)