1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2024-12-12 10:04:40 +02:00
RedMew/features/landfill_remover.lua
RedRafe 26e1c28dc0
Factorio 2.0 update (#1436)
* Init Factorio 2.0 update

* add credits

* fix test module

* I know luackeck, I know

* Fixes

* Fix bad event.player_index handling

* Hotfixes

* Remove all filter inserters

* Migrate removed items

* Deprecating spidertron control and landfill features
2024-10-22 20:22:35 +01:00

205 lines
6.1 KiB
Lua

-- Module deprecated in 2.0, became a built-in feature
-- This feature allows players to remove landfill.
-- To use, create a deconstruction planner with the landfill tile filter and select tiles only mode.
-- Use the decon planner within range of the landfill to remove it
local Event = require 'utils.event'
local Rank = require 'features.rank_system'
local Ranks = require 'resources.ranks'
local table = require 'utils.table'
local math = require 'utils.math'
local config = storage.config.landfill_remover
local Public = {}
local rank_too_low_message = {'landfill_remover.rank_too_low'}
Public.rank_too_low_message =rank_too_low_message
local missing_research_message = {'landfill_remover.missing_research'}
Public.missing_research_message = missing_research_message
local floor = math.floor
local ceil = math.ceil
local fast_remove = table.fast_remove
local collision_mask = {'floor-layer', 'object-layer', 'resource-layer'}
local whitelist = defines.deconstruction_item.tile_filter_mode.whitelist
local entity_whitelist = defines.deconstruction_item.entity_filter_mode.whitelist
local normal = defines.deconstruction_item.tile_selection_mode.normal
local never = defines.deconstruction_item.tile_selection_mode.never
local function can_select_landfill_tiles(cursor, surface, area)
if not cursor or not cursor.valid or not cursor.valid_for_read or cursor.trees_and_rocks_only then
return false
end
local tile_selection_mode = cursor.tile_selection_mode
if tile_selection_mode == never then
return false
end
local tile_filters = cursor.tile_filters
local contains_landfill_filter = table.contains(tile_filters, 'landfill')
local tile_filter_mode = cursor.tile_filter_mode
if tile_filter_mode == whitelist then
if not contains_landfill_filter then
return false
end
else
if contains_landfill_filter then
return false
end
end
if tile_selection_mode ~= normal then
return true
end
local entity_filters = cursor.entity_filters
if #entity_filters == 0 then
if surface.count_entities_filtered({area = area, name = 'character', invert = true, limit = 1}) > 0 then
return false
end
return true
end
local invert = cursor.entity_filter_mode ~= entity_whitelist
if invert then
entity_filters[#entity_filters + 1] = 'character'
end
return surface.count_entities_filtered({area = area, name = entity_filters, invert = invert, limit = 1}) == 0
end
local function within_reach(tile_position, player_position, radius_squared)
local dx = tile_position.x - player_position.x
local dy = tile_position.y - player_position.y
return (dx * dx + dy * dy) < radius_squared
end
local function try_get_landfill_tiles(surface, area, player)
local build_distance = player.build_distance + 0.5
local radius_squared = build_distance * build_distance
local player_position = player.position
local find_tiles_filtered = surface.find_tiles_filtered
local landfill_tiles = find_tiles_filtered({area = area, name = 'landfill'})
local hidden_landfill_tiles = find_tiles_filtered({area = area, has_hidden_tile = true})
for i = #landfill_tiles, 1, -1 do
local tile = landfill_tiles[i]
if not within_reach(tile.position, player_position, radius_squared) then
fast_remove(landfill_tiles, i)
end
end
for i = #hidden_landfill_tiles, 1, -1 do
local tile = hidden_landfill_tiles[i]
if tile.hidden_tile ~= 'landfill' or not within_reach(tile.position, player_position, radius_squared) then
fast_remove(hidden_landfill_tiles, i)
end
end
if #landfill_tiles == 0 and #hidden_landfill_tiles == 0 then
return nil
end
local i = 0
local first = true
return function()
local tile
i = i + 1
if first then
tile = landfill_tiles[i]
if tile then
return tile
end
first = false
i = 1
end
return hidden_landfill_tiles[i]
end
end
Event.add(
defines.events.on_player_deconstructed_area,
function(event)
if event.item ~= 'deconstruction-planner' then
return
end
if event.alt then
return
end
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
local surface = event.surface
if not surface or not surface.valid then
return
end
local area = event.area
local lt, rb = area.left_top, area.right_bottom
lt.x, lt.y = floor(lt.x), floor(lt.y)
rb.x, rb.y = ceil(rb.x), ceil(rb.y)
local cursor = player.cursor_stack
if not can_select_landfill_tiles(cursor, surface, area) then
return
end
local tiles_iter = try_get_landfill_tiles(surface, area, player)
if not tiles_iter then
return
end
if not player.force.technologies['landfill'].researched then
player.print(missing_research_message)
return
end
if Rank.less_than(player.name, Ranks.auto_trusted) then
player.print(rank_too_low_message)
return
end
local count_entities_filtered = surface.count_entities_filtered
local tiles_to_add = {}
local revert_tile = config.revert_tile or 'water-mud'
while true do
local tile = tiles_iter()
if not tile then
break
end
local pos = tile.position
local tile_area = {pos, {pos.x + 1, pos.y + 1}}
if count_entities_filtered({area = tile_area, collision_mask = collision_mask}) == 0 then
tiles_to_add[#tiles_to_add + 1] = {name = revert_tile, position = tile.position}
end
end
surface.set_tiles(tiles_to_add)
local set_hidden_tile = surface.set_hidden_tile
for i = 1, #tiles_to_add do
local tile = tiles_to_add[i]
set_hidden_tile(tile.position, nil)
end
end
)
return Public