1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-06 00:23:49 +02:00
ComfyFactorio/modules/collapse.lua

550 lines
15 KiB
Lua
Raw Normal View History

2022-05-14 19:15:51 +02:00
local Event = require 'utils.event'
2020-04-29 13:12:42 +02:00
local Global = require 'utils.global'
local Public = {}
local math_floor = math.floor
local table_shuffle_table = table.shuffle_table
2022-05-14 19:15:51 +02:00
local this = {
2023-08-10 14:29:05 +02:00
debug = false,
2024-05-31 22:47:33 +02:00
disabled = false,
reverse_disabled = false
2020-06-03 20:09:37 +02:00
}
2020-04-29 13:12:42 +02:00
Global.register(
2022-05-14 19:15:51 +02:00
this,
2024-10-25 21:56:34 +02:00
function (tbl)
2022-05-14 19:15:51 +02:00
this = tbl
2020-04-29 13:12:42 +02:00
end
)
2024-05-28 10:43:10 +02:00
local direction_reverse = {
['north'] = 'south',
['south'] = 'north',
['west'] = 'east',
['east'] = 'west'
}
2020-04-29 13:12:42 +02:00
local directions = {
2024-10-25 21:56:34 +02:00
['north'] = function (position, reverse)
2022-05-14 19:15:51 +02:00
local surface_index = this.surface_index
if not surface_index then
return
end
local surface = game.get_surface(surface_index)
2023-09-20 21:37:45 +02:00
if not surface or not surface.valid then
2022-05-14 19:15:51 +02:00
return
end
local width = surface.map_gen_settings.width
if width > this.max_line_size then
width = this.max_line_size
end
2024-03-27 09:01:53 +02:00
if this.max_line_size_force then
width = this.max_line_size
end
local a = width * 0.5 + 4
2024-05-28 10:43:10 +02:00
if not reverse then
2024-10-25 21:56:34 +02:00
this.vector = { 0, -1 }
this.area = { { position.x - a, position.y - 1 }, { position.x + a, position.y } }
2024-05-28 10:43:10 +02:00
else
2024-10-25 21:56:34 +02:00
this.reverse_vector = { 0, -1 }
this.reverse_area = { { position.x - a, position.y - 1 }, { position.x + a, position.y } }
2024-05-28 10:43:10 +02:00
end
end,
2024-10-25 21:56:34 +02:00
['south'] = function (position, reverse)
2022-05-14 19:15:51 +02:00
local surface_index = this.surface_index
if not surface_index then
return
end
local surface = game.get_surface(surface_index)
2023-09-20 21:37:45 +02:00
if not surface or not surface.valid then
2022-05-14 19:15:51 +02:00
return
end
local width = surface.map_gen_settings.width
if width > this.max_line_size then
width = this.max_line_size
end
2024-03-27 09:01:53 +02:00
if this.max_line_size_force then
width = this.max_line_size
end
local a = width * 0.5
2024-05-28 10:43:10 +02:00
if not reverse then
2024-10-25 21:56:34 +02:00
this.vector = { 0, 1 }
this.area = { { position.x - a, position.y }, { position.x + a, position.y + 1 } }
2024-05-28 10:43:10 +02:00
else
2024-10-25 21:56:34 +02:00
this.reverse_vector = { 0, 1 }
this.reverse_area = { { position.x - a, position.y }, { position.x + a, position.y + 1 } }
2024-05-28 10:43:10 +02:00
end
end,
2024-10-25 21:56:34 +02:00
['west'] = function (position, reverse)
2022-05-14 19:15:51 +02:00
local surface_index = this.surface_index
if not surface_index then
return
end
local surface = game.get_surface(surface_index)
2023-09-20 21:37:45 +02:00
if not surface or not surface.valid then
2022-05-14 19:15:51 +02:00
return
end
local width = surface.map_gen_settings.height
if width > this.max_line_size then
width = this.max_line_size
end
2024-03-27 09:01:53 +02:00
if this.max_line_size_force then
width = this.max_line_size
end
local a = width * 0.5 + 1
2024-05-28 10:43:10 +02:00
if not reverse then
2024-10-25 21:56:34 +02:00
this.vector = { -1, 0 }
this.area = { { position.x - 1, position.y - a }, { position.x, position.y + a } }
2024-05-28 10:43:10 +02:00
else
2024-10-25 21:56:34 +02:00
this.reverse_vector = { -1, 0 }
this.reverse_area = { { position.x - 1, position.y - a }, { position.x, position.y + a } }
2024-05-28 10:43:10 +02:00
end
end,
2024-10-25 21:56:34 +02:00
['east'] = function (position, reverse)
2022-05-14 19:15:51 +02:00
local surface_index = this.surface_index
if not surface_index then
return
end
local surface = game.get_surface(surface_index)
2023-09-20 21:37:45 +02:00
if not surface or not surface.valid then
2022-05-14 19:15:51 +02:00
return
end
local width = surface.map_gen_settings.height
if width > this.max_line_size then
width = this.max_line_size
end
2024-03-27 09:01:53 +02:00
if this.max_line_size_force then
width = this.max_line_size
end
local a = width * 0.5 + 1
2024-05-28 10:43:10 +02:00
if not reverse then
2024-10-25 21:56:34 +02:00
this.vector = { 1, 0 }
this.area = { { position.x, position.y - a }, { position.x + 1, position.y + a } }
2024-05-28 10:43:10 +02:00
else
2024-10-25 21:56:34 +02:00
this.reverse_vector = { 1, 0 }
this.reverse_area = { { position.x, position.y - a }, { position.x + 1, position.y + a } }
2024-05-28 10:43:10 +02:00
end
end
2020-04-29 13:12:42 +02:00
}
local function print_debug(a)
2022-05-14 19:15:51 +02:00
if not this.debug then
2020-06-03 20:09:37 +02:00
return
end
print('Collapse error #' .. a)
2020-04-29 13:12:42 +02:00
end
2020-04-29 15:56:57 +02:00
local function set_collapse_tiles(surface)
2020-06-03 20:09:37 +02:00
if not surface or surface.valid then
print_debug(45)
end
2022-05-14 19:15:51 +02:00
game.forces.player.chart(surface, this.area)
2024-10-25 21:56:34 +02:00
this.tiles = surface.find_tiles_filtered({ area = this.area, name = 'out-of-map', invert = true })
2024-11-04 20:58:40 +02:00
if not this.tiles then
return
end
2024-11-04 20:58:40 +02:00
2022-05-14 19:15:51 +02:00
this.size_of_tiles = #this.tiles
2024-11-04 20:58:40 +02:00
if this.size_of_tiles > 0 then
2022-05-14 19:15:51 +02:00
table_shuffle_table(this.tiles)
end
2024-10-25 21:56:34 +02:00
this.position = { x = this.position.x + this.vector[1], y = this.position.y + this.vector[2] }
2022-05-14 19:15:51 +02:00
local v = this.vector
2024-11-04 20:58:40 +02:00
if not v then
return
end
2022-05-14 19:15:51 +02:00
local area = this.area
2024-10-25 21:56:34 +02:00
this.area = { { area[1][1] + v[1], area[1][2] + v[2] }, { area[2][1] + v[1], area[2][2] + v[2] } }
local chart_area = { { area[1][1] + v[1] - 4, area[1][2] + v[2] - 4 }, { area[2][1] + v[1] + 4, area[2][2] + v[2] + 4 } }
game.forces.player.chart(surface, chart_area)
2020-04-29 13:12:42 +02:00
end
2024-05-28 10:43:10 +02:00
---@param surface LuaSurface
local function set_reverse_collapse_tiles(surface)
if not surface or surface.valid then
print_debug(45)
end
2024-10-25 21:56:34 +02:00
this.reverse_tiles = surface.find_tiles_filtered({ area = this.reverse_area, name = 'out-of-map', invert = true })
2024-05-28 10:43:10 +02:00
2024-11-04 20:58:40 +02:00
if not this.reverse_tiles then
2024-05-28 10:43:10 +02:00
return
end
2024-11-02 23:50:47 +02:00
2024-05-28 10:43:10 +02:00
this.reverse_size_of_tiles = #this.reverse_tiles
2024-11-04 20:58:40 +02:00
if this.reverse_size_of_tiles > 0 then
2024-05-28 10:43:10 +02:00
table_shuffle_table(this.reverse_tiles)
end
2024-10-25 21:56:34 +02:00
this.reverse_position = { x = this.reverse_position.x + this.reverse_vector[1], y = this.reverse_position.y + this.reverse_vector[2] }
2024-05-28 10:43:10 +02:00
local v = this.reverse_vector
2024-11-02 23:50:47 +02:00
if not v then return end
2024-05-28 10:43:10 +02:00
local area = this.reverse_area
2024-10-25 21:56:34 +02:00
this.reverse_area = { { area[1][1] + v[1], area[1][2] + v[2] }, { area[2][1] + v[1], area[2][2] + v[2] } }
local chart_area = { { area[1][1] + v[1] - 4, area[1][2] + v[2] - 10 }, { area[2][1] + v[1] + 4, area[2][2] + v[2] + 10 } }
2024-05-28 10:43:10 +02:00
local force = game.forces.player
2024-05-31 22:47:33 +02:00
force.chart(surface, chart_area)
2024-05-28 10:43:10 +02:00
end
2020-04-29 13:12:42 +02:00
local function progress()
2024-05-28 10:43:10 +02:00
if not this.start_now then
this.tiles = nil
return
end
2022-05-14 19:15:51 +02:00
local surface_index = this.surface_index
if not surface_index then
return
end
local surface = game.get_surface(surface_index)
2023-09-20 21:37:45 +02:00
if not surface or not surface.valid then
2022-05-14 19:15:51 +02:00
return
end
2022-05-14 19:15:51 +02:00
local tiles = this.tiles
if not tiles then
set_collapse_tiles(surface)
2022-05-14 19:15:51 +02:00
tiles = this.tiles
end
if not tiles then
return
end
2022-05-14 19:15:51 +02:00
for _ = 1, this.amount, 1 do
local tile = tiles[this.size_of_tiles]
if not tile then
2022-05-14 19:15:51 +02:00
this.tiles = nil
return
end
2022-05-14 19:15:51 +02:00
this.size_of_tiles = this.size_of_tiles - 1
if not tile.valid then
return
end
2022-05-14 19:15:51 +02:00
if this.specific_entities.enabled then
2024-10-25 21:56:34 +02:00
local position = { tile.position.x + 0.5, tile.position.y + 0.5 }
2022-05-14 19:15:51 +02:00
local entities = this.specific_entities.entities
2024-10-25 21:56:34 +02:00
for _, e in pairs(surface.find_entities_filtered({ area = { { position[1] - 4, position[2] - 2 }, { position[1] + 4, position[2] + 2 } } })) do
2020-09-02 08:33:13 +02:00
if entities[e.name] and e.valid and e.health then
e.die()
2020-08-31 20:37:27 +02:00
elseif e.valid then
e.destroy()
end
end
end
2022-05-14 19:15:51 +02:00
if this.kill then
2024-10-25 21:56:34 +02:00
local position = { tile.position.x + 0.5, tile.position.y + 0.5 }
for _, e in pairs(surface.find_entities_filtered({ area = { { position[1] - 4, position[2] - 2 }, { position[1] + 4, position[2] + 2 } } })) do
2020-09-02 08:33:13 +02:00
if e.valid and e.health then
e.die()
end
end
end
2024-10-25 21:56:34 +02:00
surface.set_tiles({ { name = 'out-of-map', position = tile.position } }, true)
end
2020-04-29 13:12:42 +02:00
end
2024-05-28 10:43:10 +02:00
local function progress_reverse()
if not this.reverse_start_now then
this.reverse_tiles = nil
return
end
local surface_index = this.surface_index
if not surface_index then
return
end
local surface = game.get_surface(surface_index)
if not surface or not surface.valid then
return
end
local tiles = this.reverse_tiles
if not tiles then
set_reverse_collapse_tiles(surface)
tiles = this.reverse_tiles
end
if not tiles then
return
end
2024-05-30 10:45:26 +02:00
for _ = 1, this.amount + 20, 1 do
2024-05-28 10:43:10 +02:00
local tile = tiles[this.reverse_size_of_tiles]
if not tile then
this.reverse_tiles = nil
return
end
this.reverse_size_of_tiles = this.reverse_size_of_tiles - 1
if not tile.valid then
return
end
if this.specific_entities.enabled then
2024-10-25 21:56:34 +02:00
local position = { tile.position.x + 0.5, tile.position.y + 0.5 }
2024-05-28 10:43:10 +02:00
local entities = this.specific_entities.entities
2024-10-25 21:56:34 +02:00
for _, e in pairs(surface.find_entities_filtered({ area = { { position[1] - 4, position[2] - 2 }, { position[1] + 4, position[2] + 2 } } })) do
2024-05-28 10:43:10 +02:00
if entities[e.name] and e.valid and e.health then
e.die()
elseif e.valid then
e.destroy()
end
end
end
if this.kill then
2024-10-25 21:56:34 +02:00
local position = { tile.position.x + 0.5, tile.position.y + 0.5 }
for _, e in pairs(surface.find_entities_filtered({ area = { { position[1] - 4, position[2] - 2 }, { position[1] + 4, position[2] + 2 } } })) do
2024-05-28 10:43:10 +02:00
if e.valid and e.health then
e.die()
end
end
end
2024-10-25 21:56:34 +02:00
surface.set_tiles({ { name = 'out-of-map', position = tile.position } }, true)
2024-05-28 10:43:10 +02:00
end
end
2022-05-14 19:15:51 +02:00
function Public.set_surface_index(surface_index)
if not surface_index then
print_debug(1)
return
end
2022-05-14 19:15:51 +02:00
local surface = game.get_surface(surface_index)
2023-09-20 21:37:45 +02:00
if not surface or not surface.valid then
print_debug(2)
return
end
2022-05-14 19:15:51 +02:00
this.surface_index = surface_index
2020-04-29 13:12:42 +02:00
end
function Public.set_direction(direction)
if not directions[direction] then
print_debug(11)
return
end
2022-05-14 19:15:51 +02:00
directions[direction](this.position)
2024-05-28 10:43:10 +02:00
this.direction = direction
end
function Public.set_reverse_position(position)
if not position then
print_debug(4)
return
end
if not position.x and not position[1] then
print_debug(5)
return
end
if not position.y and not position[2] then
print_debug(6)
return
end
local x = 0
local y = 0
if position[1] then
x = position[1]
end
if position[2] then
y = position[2]
end
if position.x then
x = position.x
end
if position.y then
y = position.y
end
2024-10-25 21:56:34 +02:00
this.reverse_position = { x = x, y = y }
2024-05-28 10:43:10 +02:00
end
function Public.set_reverse_direction()
if not directions[direction_reverse[this.direction]] then
print_debug(11)
return
end
if not this.reverse_position then
print_debug(13)
return
end
directions[direction_reverse[this.direction]](this.reverse_position, true)
this.direction = direction_reverse[this.direction]
2020-04-29 13:12:42 +02:00
end
function Public.set_speed(speed)
if not speed then
print_debug(8)
return
end
speed = math_floor(speed)
if speed < 1 then
speed = 1
end
2022-05-14 19:15:51 +02:00
this.speed = speed
2020-04-29 13:12:42 +02:00
end
function Public.set_amount(amount)
if not amount then
print_debug(9)
return
end
amount = math_floor(amount)
if amount < 0 then
amount = 0
end
2022-05-14 19:15:51 +02:00
this.amount = amount
2020-04-29 13:12:42 +02:00
end
2020-04-29 14:25:03 +02:00
function Public.set_position(position)
if not position then
print_debug(4)
return
end
if not position.x and not position[1] then
print_debug(5)
return
end
if not position.y and not position[2] then
print_debug(6)
return
end
local x = 0
local y = 0
if position[1] then
x = position[1]
end
if position[2] then
y = position[2]
end
if position.x then
x = position.x
end
if position.y then
y = position.y
end
2024-10-25 21:56:34 +02:00
this.position = { x = x, y = y }
2020-04-29 13:12:42 +02:00
end
2020-04-29 14:25:03 +02:00
function Public.get_position()
2022-05-14 19:15:51 +02:00
return this.position
end
2024-05-28 10:43:10 +02:00
function Public.get_reverse_position()
return this.reverse_position
end
2021-02-26 01:04:20 +02:00
function Public.get_amount()
2022-05-14 19:15:51 +02:00
return this.amount
2021-02-26 01:04:20 +02:00
end
2021-02-26 01:05:32 +02:00
function Public.get_speed()
2022-05-14 19:15:51 +02:00
return this.speed
2021-02-26 01:05:32 +02:00
end
2024-05-30 14:56:31 +02:00
--- Set the collapse to start or not, accepts a second argument to disable the collapse completely.
---@param state boolean
2024-05-31 22:47:33 +02:00
---@param disabled? boolean
2024-05-30 14:56:31 +02:00
---@return boolean
function Public.start_now(state, disabled)
2023-08-10 14:29:05 +02:00
this.start_now = state or false
2024-05-30 14:56:31 +02:00
this.disabled = disabled or false
2022-05-14 19:15:51 +02:00
return this.start_now
2020-04-29 14:25:03 +02:00
end
2024-05-31 22:47:33 +02:00
--- Set the reverse collapse to start or not, accepts a second argument to disable the collapse completely.
---@param state boolean
---@param disabled? boolean
---@return boolean
function Public.reverse_start_now(state, disabled)
2024-05-28 10:43:10 +02:00
this.reverse_start_now = state or false
2024-05-31 22:47:33 +02:00
this.reverse_disabled = disabled or false
2024-05-28 10:43:10 +02:00
return this.reverse_start_now
end
function Public.has_collapse_started()
2024-05-30 14:56:31 +02:00
if this.disabled then
return true
end
2023-09-05 00:03:55 +02:00
return this.start_now
end
2024-05-28 10:43:10 +02:00
function Public.has_reverse_collapse_started()
return this.reverse_start_now
end
2024-03-27 09:01:53 +02:00
function Public.set_max_line_size(size, force)
if not size then
print_debug(22)
return
end
size = math_floor(size)
if size <= 0 then
print_debug(21)
return
end
2022-05-14 19:15:51 +02:00
this.max_line_size = size
2024-03-27 09:01:53 +02:00
this.max_line_size_force = force or false
2020-04-29 13:12:42 +02:00
end
2020-04-29 14:25:03 +02:00
function Public.set_kill_entities(a)
2022-05-14 19:15:51 +02:00
this.kill = a
2020-04-29 13:12:42 +02:00
end
2020-09-02 08:33:13 +02:00
function Public.set_kill_specific_entities(tbl)
if tbl then
2022-05-14 19:15:51 +02:00
this.specific_entities = tbl
2020-09-02 08:33:13 +02:00
else
2022-05-14 19:15:51 +02:00
this.specific_entities = {
2020-09-02 08:33:13 +02:00
enabled = false
}
end
end
2020-04-29 13:12:42 +02:00
local function on_init()
2022-05-14 19:15:51 +02:00
Public.set_surface_index(game.surfaces.nauvis.index)
2024-10-25 21:56:34 +02:00
Public.set_position({ 0, 32 })
Public.set_max_line_size(256)
Public.set_direction('north')
Public.set_kill_entities(true)
2020-09-02 08:33:13 +02:00
Public.set_kill_specific_entities()
2022-05-14 19:15:51 +02:00
this.tiles = nil
2024-05-28 10:43:10 +02:00
this.reverse_tiles = nil
2022-05-14 19:15:51 +02:00
this.speed = 1
2024-05-30 14:56:31 +02:00
this.disabled = false
2024-05-31 22:47:33 +02:00
this.reverse_disabled = false
2024-05-28 10:43:10 +02:00
this.reverse_start_now = false
2022-05-14 19:15:51 +02:00
this.amount = 8
this.start_now = false
2020-04-29 13:12:42 +02:00
end
local function on_tick()
2022-05-14 19:15:51 +02:00
local tick = game.tick
if tick % this.speed ~= 0 then
return
end
2022-05-14 19:15:51 +02:00
2024-05-31 22:47:33 +02:00
if not this.reverse_disabled then
progress_reverse()
2024-05-30 14:56:31 +02:00
end
2024-05-31 22:47:33 +02:00
if not this.disabled then
progress()
end
2020-04-29 13:12:42 +02:00
end
2023-06-17 23:31:40 +02:00
if not Public.read_tables_only then
Event.on_init(on_init)
Event.add(defines.events.on_tick, on_tick)
end
2020-04-29 13:12:42 +02:00
return Public