mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-06 00:23:49 +02:00
272 lines
8.8 KiB
Lua
272 lines
8.8 KiB
Lua
local Server = require 'utils.server'
|
|
local Modifiers = require 'utils.player_modifiers'
|
|
local Global = require 'utils.global'
|
|
local Event = require 'utils.event'
|
|
|
|
local Public = {}
|
|
local this = {}
|
|
|
|
---------------------------global table-----------------------------------------
|
|
Global.register(
|
|
this,
|
|
function(tbl)
|
|
this = tbl
|
|
end
|
|
)
|
|
|
|
function Public.reset_table()
|
|
for k, _ in pairs(this) do
|
|
this[k] = nil
|
|
end
|
|
this.soft_reset_counter = 0
|
|
this.original_surface_name = nil
|
|
this.schedule_step = 0
|
|
this.schedule_max_step = 0
|
|
this.schedule = {}
|
|
this.initial_tick = 0
|
|
end
|
|
|
|
function Public.get_table()
|
|
return this
|
|
end
|
|
|
|
local on_init = function()
|
|
Public.reset_table()
|
|
end
|
|
|
|
Event.on_init(on_init)
|
|
|
|
-------------------------scheduled deletion-------------------------------------
|
|
local function add_step()
|
|
if this.schedule_step ~= this.schedule_max_step then
|
|
this.schedule_step = this.schedule_step + 1
|
|
end
|
|
end
|
|
|
|
local function scheduled_surface_clearing()
|
|
if this.initial_tick > game.tick then
|
|
return
|
|
end
|
|
local step = this.schedule_step
|
|
local schedule = this.schedule
|
|
if schedule[step] then
|
|
local surface = schedule[step].surface
|
|
if not surface.valid then
|
|
schedule[step] = nil
|
|
add_step()
|
|
return
|
|
end
|
|
if schedule[step].operation == 'biter_clearing' then
|
|
local biters = surface.find_entities_filtered {type = 'unit', limit = 10000}
|
|
for _, biter in pairs(biters) do
|
|
if biter.valid then
|
|
biter.destroy()
|
|
end
|
|
end
|
|
schedule[step] = nil
|
|
add_step()
|
|
elseif schedule[step].operation == 'nest_clearing' then
|
|
local nests = surface.find_entities_filtered {type = 'unit-spawner'}
|
|
for _, nest in pairs(nests) do
|
|
if nest.valid then
|
|
nest.destroy()
|
|
end
|
|
end
|
|
schedule[step] = nil
|
|
add_step()
|
|
elseif schedule[step].operation == 'scrap_clearing' then
|
|
local scrap = surface.find_entities_filtered {force = 'neutral', limit = 5000}
|
|
for _, e in pairs(scrap) do
|
|
if e.valid then
|
|
e.destroy()
|
|
end
|
|
end
|
|
schedule[step] = nil
|
|
add_step()
|
|
elseif schedule[step].operation == 'clear' then
|
|
surface.clear()
|
|
schedule[step] = nil
|
|
add_step()
|
|
elseif schedule[step].operation == 'delete' then
|
|
game.delete_surface(surface)
|
|
schedule[step] = nil
|
|
add_step()
|
|
end
|
|
end
|
|
end
|
|
|
|
function Public.add_schedule_to_delete_surface(surface)
|
|
local step = this.schedule_max_step
|
|
local add = 1
|
|
this.schedule[step + add] = {operation = 'nest_clearing', surface = surface}
|
|
add = add + 1
|
|
local count_biters = surface.count_entities_filtered {type = 'unit'}
|
|
for i = 1, count_biters, 10000 do
|
|
this.schedule[step + add] = {operation = 'biter_clearing', surface = surface}
|
|
add = add + 1
|
|
end
|
|
local count_scrap = surface.count_entities_filtered {force = 'neutral'}
|
|
for i = 1, count_scrap, 5000 do
|
|
this.schedule[step + add] = {operation = 'scrap_clearing', surface = surface}
|
|
add = add + 1
|
|
end
|
|
this.schedule[step + add] = {operation = 'clear', surface = surface}
|
|
add = add + 1
|
|
this.schedule[step + add] = {operation = 'delete', surface = surface}
|
|
this.schedule_max_step = this.schedule_max_step + add
|
|
if this.schedule_step == step then
|
|
this.schedule_step = this.schedule_step + 1
|
|
end
|
|
if this.initial_tick <= game.tick then
|
|
--add offset for starting of deletion, so new map can generate peacefully for a minute and tiny bit
|
|
this.initial_tick = game.tick + 4000
|
|
end
|
|
end
|
|
|
|
function Public.change_entities_to_neutral(surface, force, delete_pollution)
|
|
local entities = surface.find_entities_filtered {force = force or 'player'}
|
|
for _, entity in pairs(entities) do
|
|
if entity.valid then
|
|
entity.force = 'neutral'
|
|
entity.active = false
|
|
end
|
|
end
|
|
if delete_pollution then
|
|
local pollution = surface.get_total_pollution()
|
|
surface.clear_pollution()
|
|
game.pollution_statistics.on_flow('power-switch', -pollution)
|
|
end
|
|
end
|
|
|
|
Event.on_nth_tick(10, scheduled_surface_clearing)
|
|
|
|
---------------------------soft reset-------------------------------------------
|
|
|
|
local function reset_forces(new_surface, old_surface)
|
|
for _, f in pairs(game.forces) do
|
|
local spawn = {
|
|
x = game.forces.player.get_spawn_position(old_surface).x,
|
|
y = game.forces.player.get_spawn_position(old_surface).y
|
|
}
|
|
f.reset()
|
|
|
|
for _, tech in pairs(game.forces.player.technologies) do
|
|
tech.researched = false
|
|
game.forces.player.set_saved_technology_progress(tech, 0)
|
|
end
|
|
f.reset_evolution()
|
|
f.set_spawn_position(spawn, new_surface)
|
|
end
|
|
end
|
|
|
|
local function teleport_players(surface, small_force_chunk)
|
|
for _, player in pairs(game.connected_players) do
|
|
local spawn = player.force.get_spawn_position(surface)
|
|
local chunk = {math.floor(spawn.x / 32), math.floor(spawn.y / 32)}
|
|
if not surface.is_chunk_generated(chunk) then
|
|
if not small_force_chunk then
|
|
surface.request_to_generate_chunks(spawn, 1)
|
|
surface.force_generate_chunk_requests()
|
|
else
|
|
surface.request_to_generate_chunks({0, 0}, 0.1)
|
|
surface.force_generate_chunk_requests()
|
|
end
|
|
end
|
|
local pos = surface.find_non_colliding_position('character', spawn, 3, 0.5)
|
|
player.teleport(pos, surface)
|
|
end
|
|
end
|
|
|
|
local function equip_players(player_starting_items)
|
|
for k, player in pairs(game.connected_players) do
|
|
if player.character then
|
|
player.character.destroy()
|
|
end
|
|
player.character = nil
|
|
player.set_controller({type = defines.controllers.god})
|
|
player.create_character()
|
|
for item, amount in pairs(player_starting_items) do
|
|
player.insert({name = item, count = amount})
|
|
end
|
|
Modifiers.update_player_modifiers(player)
|
|
end
|
|
end
|
|
|
|
local function clear_robots(new_surface)
|
|
local radius = 512
|
|
local area = {{x = -radius, y = -radius}, {x = radius, y = radius}}
|
|
for _, entity in pairs(new_surface.find_entities_filtered {area = area, type = 'logistic-robot'}) do
|
|
entity.destroy()
|
|
end
|
|
|
|
for _, entity in pairs(new_surface.find_entities_filtered {area = area, type = 'construction-robot'}) do
|
|
entity.destroy()
|
|
end
|
|
end
|
|
|
|
function Public.soft_reset_map(old_surface, map_gen_settings, player_starting_items, small_force_chunk)
|
|
if not this.original_surface_name then
|
|
this.original_surface_name = old_surface.name
|
|
end
|
|
this.soft_reset_counter = this.soft_reset_counter + 1
|
|
|
|
local new_surface = game.create_surface(this.original_surface_name .. '_' .. tostring(this.soft_reset_counter), map_gen_settings)
|
|
if not small_force_chunk then
|
|
new_surface.request_to_generate_chunks({0, 0}, 1)
|
|
new_surface.force_generate_chunk_requests()
|
|
else
|
|
new_surface.request_to_generate_chunks({0, 0}, 0.1)
|
|
new_surface.force_generate_chunk_requests()
|
|
end
|
|
|
|
reset_forces(new_surface, old_surface)
|
|
teleport_players(new_surface)
|
|
equip_players(player_starting_items)
|
|
clear_robots(new_surface)
|
|
|
|
Public.change_entities_to_neutral(old_surface)
|
|
Public.add_schedule_to_delete_surface(old_surface)
|
|
|
|
local to_discord = {'modules.soft_reset_welcome', this.original_surface_name}
|
|
local restarting_to_discord = {'modules.soft_reset_reshape', this.original_surface_name, tostring(this.soft_reset_counter)}
|
|
|
|
local message
|
|
if this.enable_mapkeeper then
|
|
message = {'modules.soft_reset_welcome_mapkeeper', this.original_surface_name}
|
|
else
|
|
message = to_discord
|
|
end
|
|
|
|
if this.soft_reset_counter > 1 then
|
|
if this.enable_mapkeeper then
|
|
message = {
|
|
'modules.soft_reset_reshape_mapkeeper',
|
|
this.original_surface_name,
|
|
tostring(this.soft_reset_counter)
|
|
}
|
|
else
|
|
message = restarting_to_discord
|
|
end
|
|
end
|
|
|
|
game.print(message, {r = 0.98, g = 0.66, b = 0.22})
|
|
Server.to_discord_embed(message, true)
|
|
|
|
return new_surface
|
|
end
|
|
|
|
--- Returns the amount of times the server has soft restarted.
|
|
function Public.get_reset_counter()
|
|
return this.soft_reset_counter
|
|
end
|
|
|
|
--- Customizes the message with the mapkeeper param.
|
|
---@param boolean <true/false>
|
|
function Public.enable_mapkeeper(boolean)
|
|
if boolean and type(boolean) == 'boolean' then
|
|
this.enable_mapkeeper = boolean or false
|
|
end
|
|
end
|
|
|
|
return Public
|