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

302 lines
9.7 KiB
Lua

-- Custom Extensions to the God-Controller
local God = {}
God.onBuiltEntityFilters = {
{ filter = "type", type = "tile-ghost" },
{ filter = "type", type = "entity-ghost" },
{ filter = "type", type = "item-request-proxy" },
}
for realEntityName, illusionName in pairs(Illusion.realToIllusionMap) do
table.insert(
God.onBuiltEntityFilters,
{ filter = "name", name = realEntityName }
)
end
-- TODO: Perhaps this can be determined by flags?
God.skipHandlingEntities = {
["logistic-train-stop-input"] = true,
["logistic-train-stop-output"] = true,
["tl-dummy-entity"] = true,
["si-in-world-drop-entity"] = true,
["si-in-world-pickup-entity"] = true,
}
-- Immediately destroy an Entity (and perhaps related Entities)
function God.Destroy(entity)
if entity.valid
and entity.can_be_destroyed()
and entity.to_be_deconstructed()
then
-- If the Entity has Transport Lines, also delete any Items on it
if entity.prototype.belt_speed ~= nil then
for i = 1, entity.get_max_transport_line_index() do
entity.get_transport_line(i).clear()
end
end
-- If the Entity represents a Hidden Tile underneath
if entity.type == "deconstructible-tile-proxy" then
local hiddenTile = entity.surface.get_hidden_tile(entity.position)
entity.surface.set_tiles {
{
name = hiddenTile,
position = entity.position,
}
}
end
entity.destroy({ raise_destroy = true })
end
end
-- Immediately Insert an Entity's Requests
function God.InsertRequests(entity)
if entity.valid
and entity.type == "item-request-proxy"
and entity.proxy_target then
-- Insert any Requested Items (like Modules, Fuel)
for name, count in pairs(entity.item_requests) do
entity.proxy_target.insert({
name = name,
count = count,
})
end
entity.destroy()
end
end
-- Immediately Revive a Ghost Entity
function God.Create(entity)
Illusion.ReplaceIfNecessary(entity)
if entity.valid then
if entity.type == "tile-ghost" then
-- Tiles are simple Revives
entity.silent_revive({ raise_revive = true })
elseif entity.type == "item-request-proxy" then
-- Requests are simple
God.InsertRequests(entity)
elseif entity.type == "entity-ghost" then
-- Entities might also want Items after Reviving
local _, revived, request = entity.silent_revive({
return_item_request_proxy = true,
raise_revive = true
})
if revived and request then
God.InsertRequests(request)
end
end
end
end
-- Immediately turn one Entity into another
function God.Upgrade(entity)
if entity.valid
and entity.to_be_upgraded()
then
local target = entity.get_upgrade_target()
local direction = entity.get_upgrade_direction()
if Illusion.IsIllusion(entity.name) and
Illusion.GetActualName(entity.name) == target.name
then
log("Cancelling an Upgrade from an Illusion to its Real Entity: " .. entity.name)
entity.cancel_upgrade(entity.force)
return
end
local options = {
name = target.name,
position = entity.position,
direction = direction or entity.direction,
force = entity.force,
fast_replace = true,
spill = false,
raise_built = true,
}
-- Otherwise it fails to place "output" sides (it defaults to "input")
if entity.type == "underground-belt" then
options.type = entity.belt_to_ground_type
end
local result = entity.surface.create_entity(options)
if result == nil and entity.valid then
log("Upgrade Failed, Cancelling: " .. entity.name)
entity.cancel_upgrade(entity.force)
else
log("Upgrade Failed, Old Entity Gone too!")
end
end
end
-- Ensure the God's Inventory is kept in-sync
function God.OnInventoryChanged(event)
local player = game.players[event.player_index]
local playerData = global.players[event.player_index]
if Sandbox.IsPlayerInsideSandbox(player) then
Inventory.Prune(player)
playerData.sandboxInventory = Inventory.Persist(
player.get_main_inventory(),
playerData.sandboxInventory
)
end
end
-- Ensure newly-crafted Items are put into the Cursor for use
function God.OnPlayerCraftedItem(event)
local player = game.players[event.player_index]
if Sandbox.IsPlayerInsideSandbox(player)
and player.cursor_stack
and player.cursor_stack.valid
and event.item_stack.valid
and event.item_stack.valid_for_read
and event.recipe.valid
and (
#event.recipe.products == 1
or (
event.recipe.prototype.main_product
and event.recipe.prototype.main_product.name == event.item_stack.name
)
)
and player.mod_settings[Settings.craftToCursor].value
then
event.item_stack.count = event.item_stack.prototype.stack_size
player.cursor_stack.clear()
player.cursor_stack.transfer_stack(event.item_stack)
end
end
function God.AsyncWrapper(setting, queue, handler, entity)
if settings.global[setting].value == 0 then
handler(entity)
else
Queue.Push(queue, entity)
end
end
function God.ShouldHandleEntity(entity)
if entity.force.name ~= "neutral"
and not Sandbox.IsSandboxForce(entity.force) then
return false
end
local name = Illusion.GhostOrRealName(entity)
if God.skipHandlingEntities[name] then
return false
end
return Lab.IsLab(entity.surface)
or SpaceExploration.IsSandbox(entity.surface)
or (Factorissimo.IsFactory(entity.surface)
and Factorissimo.IsFactoryInsideSandbox(entity.surface, entity.position))
end
-- Ensure new Orders are handled
function God.OnMarkedForDeconstruct(event)
-- log("Entity Deconstructing: " .. event.entity.unit_number .. " " .. event.entity.type)
if God.ShouldHandleEntity(event.entity) then
God.AsyncWrapper(
Settings.godAsyncDeleteRequestsPerTick,
global.asyncDestroyQueue,
God.Destroy,
event.entity
)
end
end
-- Ensure new Orders are handled
function God.OnMarkedForUpgrade(event)
-- log("Entity Upgrading: " .. event.entity.unit_number .. " " .. event.entity.type)
if God.ShouldHandleEntity(event.entity) then
God.AsyncWrapper(
Settings.godAsyncUpgradeRequestsPerTick,
global.asyncUpgradeQueue,
God.Upgrade,
event.entity
)
end
end
-- Ensure new Ghosts are handled
function God.OnBuiltEntity(entity)
-- log("Entity Creating: " .. entity.unit_number .. " " .. entity.type)
if God.ShouldHandleEntity(entity) then
God.AsyncWrapper(
Settings.godAsyncCreateRequestsPerTick,
global.asyncCreateQueue,
God.Create,
entity
)
end
end
-- For each known Sandbox Surface, handle any async God functionality
function God.HandleAllSandboxRequests(event)
local createRequestsPerTick = settings.global[Settings.godAsyncCreateRequestsPerTick].value
local upgradeRequestsPerTick = settings.global[Settings.godAsyncUpgradeRequestsPerTick].value
local deleteRequestsPerTick = settings.global[Settings.godAsyncDeleteRequestsPerTick].value
local destroyRequestsHandled = 0
while Queue.Size(global.asyncDestroyQueue) > 0
and deleteRequestsPerTick > 0
do
God.Destroy(Queue.Pop(global.asyncDestroyQueue))
destroyRequestsHandled = destroyRequestsHandled + 1
deleteRequestsPerTick = deleteRequestsPerTick - 1
end
if Queue.Size(global.asyncDestroyQueue) == 0
and destroyRequestsHandled > 0
then
global.asyncDestroyQueue = Queue.New()
end
local upgradeRequestsHandled = 0
while Queue.Size(global.asyncUpgradeQueue) > 0
and upgradeRequestsPerTick > 0
do
God.Upgrade(Queue.Pop(global.asyncUpgradeQueue))
upgradeRequestsHandled = upgradeRequestsHandled + 1
upgradeRequestsPerTick = upgradeRequestsPerTick - 1
end
if Queue.Size(global.asyncUpgradeQueue) == 0
and upgradeRequestsHandled > 0
then
global.asyncUpgradeQueue = Queue.New()
end
local createRequestsHandled = 0
while Queue.Size(global.asyncCreateQueue) > 0
and createRequestsPerTick > 0
do
God.Create(Queue.Pop(global.asyncCreateQueue))
createRequestsHandled = createRequestsHandled + 1
createRequestsPerTick = createRequestsPerTick - 1
end
if Queue.Size(global.asyncCreateQueue) == 0
and createRequestsHandled > 0
then
global.asyncCreateQueue = Queue.New()
end
end
-- Charts each Sandbox that a Player is currently inside of
function God.ChartAllOccupiedSandboxes()
if settings.global[Settings.scanSandboxes].value then
local charted = {}
for _, player in pairs(game.players) do
local hash = player.force.name .. player.surface.name
if Sandbox.IsSandbox(player.surface) and not charted[hash] then
player.force.chart_all(player.surface)
charted[hash] = true
end
end
end
end
return God