Aleksei-bird 46d69f3a45 Исправлен мод heroturrets
Добавлен мод blueprint-sandboxes
Добавляет метку версии в zzzparanoidal (#72)
2024-08-16 10:59:17 +03:00

144 lines
4.7 KiB
Lua

-- Equipment-related methods
local Equipment = {}
-- Initializes an Inventory for the default equipment Blueprint(s)
function Equipment.Init(default)
local equipment = game.create_inventory(1)
Equipment.Set(equipment, default)
return equipment
end
-- Updates the default equipment Blueprint(s)
function Equipment.Set(equipment, default)
equipment[1].import_stack(default)
end
--[[
Before 1.1.87, there was a bug that did not correctly forcefully generate
chunks for surfaces with the Lab Tiles setting, which required us to
fix those tiles after generation but before placing the Blueprint.
This but was fixed in 1.1.87, however, it introduced another bug where
building a blueprint then did not immediately work on those tiles,
but building entities seemed to. So, the workaround is to delay the blueprint
building, so we do some work when the surface is generated, then the rest
as soon as possible (aligning to generated chunks seems faster (in ticks)
than waiting any number of specific ticks).
]]
function Equipment.Place(stack, surface, forceName)
if stack.is_blueprint then
log("Beginning Equipment Placement")
Equipment.Prepare(stack, surface)
global.equipmentInProgress[surface.name] = {
stack = stack,
surface = surface,
forceName = forceName,
retries = 100,
}
Equipment.BuildBlueprint(stack, surface, forceName)
else
global.equipmentInProgress[surface.name] = nil
end
return true
end
-- Prepares a Surface for an Equipment Blueprint
function Equipment.Prepare(stack, surface)
-- We need to know how many Chunks must be generated to fit this Blueprint
local radius = 0
local function updateRadius(thing)
local x = math.abs(thing.position.x)
local y = math.abs(thing.position.y)
radius = math.max(radius, x, y)
end
local entities = stack.get_blueprint_entities()
local tiles = stack.get_blueprint_tiles()
if entities then
for _, thing in pairs(entities) do
updateRadius(thing)
end
end
if tiles then
for _, thing in pairs(tiles) do
updateRadius(thing)
end
end
-- Then, we can forcefully generate the necessary Chunks
local chunkRadius = 1 + math.ceil(radius / 32)
log("Requesting Chunks for Blueprint Placement: " .. chunkRadius)
surface.request_to_generate_chunks({ x = 0, y = 0 }, chunkRadius)
surface.force_generate_chunk_requests()
log("Chunks allegedly generated")
end
-- Applies an Equipment Blueprint to a Surface
function Equipment.IsReadyForBlueprint(stack, surface)
local entities = stack.get_blueprint_entities()
local tiles = stack.get_blueprint_tiles()
local function is_chunk_generated(thing)
return surface.is_chunk_generated({
thing.position.x / 32,
thing.position.y / 32,
})
end
if entities then
for _, thing in pairs(entities) do
if not is_chunk_generated(thing) then
return false
end
end
end
if tiles then
for _, thing in pairs(tiles) do
if not is_chunk_generated(thing) then
return false
end
end
end
return true
end
-- Applies an Equipment Blueprint to a Surface
function Equipment.BuildBlueprint(stack, surface, forceName)
local equipmentData = global.equipmentInProgress[surface.name]
-- First, let's check if the Chunks are ready for us
if not Equipment.IsReadyForBlueprint(stack, surface) then
equipmentData.retries = equipmentData.retries - 1
return false
end
-- Then, place the Tiles ourselves since it might prevent placing the Blueprint
local tiles = stack.get_blueprint_tiles()
if tiles then
surface.set_tiles(tiles, true, true, true, true)
end
-- Finally, we can place the Blueprint
local ghosts = stack.build_blueprint({
surface = surface.name,
force = forceName,
position = { 0, 0 },
skip_fog_of_war = true,
raise_built = true,
})
-- But that may have not been successful, despite our attempts to ensure it!
if #ghosts > 0 then
log("Some ghosts created, ending repeated attempts; assuming Blueprint is placed")
global.equipmentInProgress[surface.name] = nil
return true
elseif equipmentData.retries <= 0 then
log("No ghosts created, but we've exceeded retry limit, ending repeated attempts")
surface.print("Failed to place Equipment Blueprint after too many retries")
global.equipmentInProgress[surface.name] = nil
return false
else
equipmentData.retries = equipmentData.retries - 1
return false
end
end
return Equipment