mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-08 00:39:30 +02:00
248 lines
7.6 KiB
Lua
248 lines
7.6 KiB
Lua
--luacheck: ignore
|
|
local Public = {}
|
|
local simplex_noise = require 'utils.simplex_noise'.d2
|
|
local math_random = math.random
|
|
local math_abs = math.abs
|
|
local math_sqrt = math.sqrt
|
|
local math_floor = math.floor
|
|
local table_remove = table.remove
|
|
local table_insert = table.insert
|
|
local table_shuffle_table = table.shuffle_table
|
|
local chart_radius = 30
|
|
local start_chunk_y = 5
|
|
local tile_conversion = {
|
|
['concrete'] = 'stone-path',
|
|
['hazard-concrete-left'] = 'stone-path',
|
|
['hazard-concrete-right'] = 'stone-path',
|
|
['refined-concrete'] = 'concrete',
|
|
['refined-hazard-concrete-left'] = 'hazard-concrete-left',
|
|
['refined-hazard-concrete-right'] = 'hazard-concrete-right',
|
|
['stone-path'] = 'landfill'
|
|
}
|
|
|
|
local size_of_vector_list = 64
|
|
local function get_collapse_vectors(radius, seed)
|
|
local vectors = {}
|
|
local i = 1
|
|
local m = 1 / (radius * 2)
|
|
for x = radius * -1, radius, 1 do
|
|
for y = radius * -1, radius, 1 do
|
|
local noise = math_abs(simplex_noise(x * m, y * m, seed) * radius * 1.2)
|
|
local d = math_sqrt(x ^ 2 + y ^ 2)
|
|
if d + noise < radius then
|
|
vectors[i] = {x, y}
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local sorted_vectors = {}
|
|
for _, vector in pairs(vectors) do
|
|
local index = math_floor(math_sqrt(vector[1] ^ 2 + vector[2] ^ 2)) + 1
|
|
if not sorted_vectors[index] then
|
|
sorted_vectors[index] = {}
|
|
end
|
|
sorted_vectors[index][#sorted_vectors[index] + 1] = vector
|
|
end
|
|
|
|
local final_list = {}
|
|
for _, row in pairs(sorted_vectors) do
|
|
table_shuffle_table(row)
|
|
for _, tile in pairs(row) do
|
|
table_insert(final_list, tile)
|
|
end
|
|
end
|
|
|
|
return final_list
|
|
end
|
|
|
|
local function set_y(surface)
|
|
local level_width = surface.map_gen_settings.width
|
|
local map_collapse = global.map_collapse
|
|
local x_left = surface.map_gen_settings.width * -0.5
|
|
local x_right = surface.map_gen_settings.width * 0.5
|
|
for _ = 1, 16, 1 do
|
|
local area = {{x_left, map_collapse.last_position.y}, {x_right, map_collapse.last_position.y + 1}}
|
|
if surface.count_tiles_filtered({name = 'out-of-map', area = area}) < level_width then
|
|
return area
|
|
end
|
|
map_collapse.last_position.y = map_collapse.last_position.y - 1
|
|
end
|
|
end
|
|
|
|
local function set_positions(surface)
|
|
local area = set_y(surface)
|
|
if not area then
|
|
return
|
|
end
|
|
|
|
local map_collapse = global.map_collapse
|
|
map_collapse.positions = {}
|
|
|
|
local i = 1
|
|
for _, tile in pairs(surface.find_tiles_filtered({area = area})) do
|
|
if tile.valid then
|
|
if tile.name ~= 'out-of-map' then
|
|
map_collapse.positions[i] = tile
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
if i == 1 then
|
|
map_collapse.positions = nil
|
|
return
|
|
end
|
|
if i > 1 then
|
|
table_shuffle_table(map_collapse.positions)
|
|
end
|
|
end
|
|
|
|
local function set_collapse_tiles(surface, position, vectors)
|
|
local map_collapse = global.map_collapse
|
|
map_collapse.processing = {}
|
|
local i = 1
|
|
for _, vector in pairs(vectors) do
|
|
local shifted_position = {x = position[1] + vector[1], y = position[2] + vector[2] - 60}
|
|
local position = {x = position[1] + vector[1], y = position[2] + vector[2]}
|
|
local rocks = surface.find_entities_filtered {position = shifted_position, radius = 2, type = {'simple-entity', 'tree'}}
|
|
if #rocks > 0 then
|
|
for i = 1, #rocks, 1 do
|
|
if rocks[i].valid then
|
|
rocks[i].destroy()
|
|
end
|
|
end
|
|
end
|
|
local tile = surface.get_tile(position)
|
|
if tile.valid and tile.name ~= 'out-of-map' then
|
|
map_collapse.processing[i] = tile
|
|
i = i + 1
|
|
end
|
|
end
|
|
map_collapse.processing_index = 1
|
|
map_collapse.size_of_processing = #map_collapse.processing
|
|
end
|
|
|
|
local function clean_positions(tbl)
|
|
for k, tile in pairs(tbl) do
|
|
if not tile.valid then
|
|
table_remove(tbl, k)
|
|
else
|
|
if tile.name == 'out-of-map' then
|
|
table_remove(tbl, k)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function setup_next_collapse()
|
|
local surface = game.surfaces[global.active_surface_index]
|
|
local map_collapse = global.map_collapse
|
|
if not map_collapse.vector_list then
|
|
map_collapse.vector_list = {}
|
|
for _ = 1, size_of_vector_list, 1 do
|
|
table_insert(global.map_collapse.vector_list, get_collapse_vectors(math_random(24, 48), math_random(1, 9999999)))
|
|
end
|
|
end
|
|
|
|
if not map_collapse.positions then
|
|
--if math_random(1, 64) == 1 then map_collapse.last_position = {x = 0, y = 128} end
|
|
set_positions(surface)
|
|
return
|
|
end
|
|
|
|
local tile = map_collapse.positions[#map_collapse.positions]
|
|
if not tile then
|
|
map_collapse.positions = nil
|
|
return
|
|
end
|
|
if not tile.valid then
|
|
clean_positions(map_collapse.positions)
|
|
return
|
|
end
|
|
if tile.name == 'out-of-map' then
|
|
clean_positions(map_collapse.positions)
|
|
return
|
|
end
|
|
|
|
local position = {tile.position.x, tile.position.y}
|
|
|
|
local vectors = map_collapse.vector_list[math_random(1, size_of_vector_list)]
|
|
set_collapse_tiles(surface, position, vectors)
|
|
|
|
local last_position = global.map_collapse.last_position
|
|
game.forces.player.chart(surface, {{last_position.x - chart_radius, last_position.y - chart_radius}, {last_position.x + chart_radius, last_position.y + chart_radius}})
|
|
global.map_collapse.last_position = {x = position[1], y = position[2]}
|
|
game.forces.player.chart(surface, {{position[1] - chart_radius, position[2] - chart_radius}, {position[1] + chart_radius, position[2] + chart_radius}})
|
|
end
|
|
|
|
function Public.delete_out_of_map_chunks(surface)
|
|
local count = 0
|
|
for chunk in surface.get_chunks() do
|
|
if surface.count_tiles_filtered({name = 'out-of-map', area = chunk.area}) == 1024 then
|
|
surface.delete_chunk({chunk.x, chunk.y})
|
|
count = count + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local function process_tile(surface, tile, tiles_to_set)
|
|
if not tile then
|
|
return
|
|
end
|
|
if not tile.valid then
|
|
return
|
|
end
|
|
|
|
local conversion_tile = tile_conversion[tile.name]
|
|
if conversion_tile then
|
|
table_insert(tiles_to_set, {name = conversion_tile, position = tile.position})
|
|
surface.create_trivial_smoke({name = 'train-smoke', position = tile.position})
|
|
else
|
|
table_insert(tiles_to_set, {name = 'out-of-map', position = tile.position})
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function Public.process()
|
|
local surface = game.surfaces[global.active_surface_index]
|
|
local map_collapse = global.map_collapse
|
|
|
|
if map_collapse.processing_index >= map_collapse.size_of_processing then
|
|
setup_next_collapse()
|
|
return
|
|
end
|
|
|
|
local count = 0
|
|
local tiles_to_set = {}
|
|
for i = map_collapse.processing_index, map_collapse.size_of_processing, 1 do
|
|
if process_tile(surface, map_collapse.processing[i], tiles_to_set) then
|
|
count = count + 1
|
|
if count >= map_collapse.speed then
|
|
break
|
|
end
|
|
end
|
|
map_collapse.processing_index = map_collapse.processing_index + 1
|
|
end
|
|
|
|
if count > 1 then
|
|
surface.set_tiles(tiles_to_set, true)
|
|
end
|
|
end
|
|
|
|
function Public.init()
|
|
global.map_collapse = {
|
|
['processing_index'] = 0,
|
|
['size_of_processing'] = 0,
|
|
['processing'] = {},
|
|
['last_position'] = {x = 0, y = 128},
|
|
['speed'] = 3
|
|
}
|
|
end
|
|
|
|
local event = require 'utils.event'
|
|
event.on_init(Public.init())
|
|
|
|
return Public
|