Исправлен мод heroturrets
Добавлен мод blueprint-sandboxes Добавляет метку версии в zzzparanoidal (#72)
This commit is contained in:
209
blueprint-sandboxes/scripts/illusion.lua
Normal file
209
blueprint-sandboxes/scripts/illusion.lua
Normal file
@@ -0,0 +1,209 @@
|
||||
-- Illusion magic for swapping real/complex entities with fake/simple variants
|
||||
local Illusion = {}
|
||||
|
||||
Illusion.pfx = BPSB.pfx .. "ils-"
|
||||
local pfxLength = string.len(Illusion.pfx)
|
||||
|
||||
-- Full list of Entities that require Illusions
|
||||
Illusion.mappings = {
|
||||
-- { "type", "entity-name", "item-name" },
|
||||
{ "ammo-turret", "se-meteor-defence-container", "se-meteor-defence" },
|
||||
{ "ammo-turret", "se-meteor-point-defence-container", "se-meteor-point-defence" },
|
||||
{ "assembling-machine", "se-delivery-cannon", "se-delivery-cannon" },
|
||||
{ "assembling-machine", "se-delivery-cannon-weapon", "se-delivery-cannon-weapon" },
|
||||
{ "assembling-machine", "se-energy-transmitter-injector", "se-energy-transmitter-injector" },
|
||||
{ "assembling-machine", "se-energy-transmitter-emitter", "se-energy-transmitter-emitter" },
|
||||
{ "assembling-machine", "se-space-elevator", "se-space-elevator" },
|
||||
{ "boiler", "se-energy-transmitter-chamber", "se-energy-transmitter-chamber" },
|
||||
{ "container", "se-rocket-launch-pad", "se-rocket-launch-pad" },
|
||||
{ "container", "se-rocket-landing-pad", "se-rocket-landing-pad" },
|
||||
{ "electric-energy-interface", "se-energy-beam-defence", "se-energy-beam-defence" },
|
||||
{ "mining-drill", "se-core-miner-drill", "se-core-miner" },
|
||||
}
|
||||
|
||||
Illusion.realToIllusionMap = {}
|
||||
for _, mapping in ipairs(Illusion.mappings) do
|
||||
Illusion.realToIllusionMap[mapping[2]] = Illusion.pfx .. mapping[2]
|
||||
end
|
||||
|
||||
Illusion.realNameFilters = {}
|
||||
for realEntityName, illusionName in pairs(Illusion.realToIllusionMap) do
|
||||
table.insert(Illusion.realNameFilters, realEntityName)
|
||||
end
|
||||
|
||||
-- Whether the Thing is an Illusion
|
||||
function Illusion.IsIllusion(name)
|
||||
return string.sub(name, 1, pfxLength) == Illusion.pfx
|
||||
end
|
||||
|
||||
-- Extract the Name from an Illusion
|
||||
function Illusion.GetActualName(name)
|
||||
return string.sub(name, pfxLength + 1)
|
||||
end
|
||||
|
||||
-- Extract the Name from an Entity
|
||||
function Illusion.GhostOrRealName(entity)
|
||||
local realName = entity.name
|
||||
if entity.type == "entity-ghost" then
|
||||
realName = entity.ghost_name
|
||||
end
|
||||
return realName
|
||||
end
|
||||
|
||||
-- Convert a built Entity into an Illusion (if possible)
|
||||
function Illusion.ReplaceIfNecessary(entity)
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local realName = Illusion.GhostOrRealName(entity)
|
||||
local illusionName = Illusion.realToIllusionMap[realName]
|
||||
if illusionName == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local options = {
|
||||
name = illusionName,
|
||||
position = entity.position,
|
||||
direction = entity.direction,
|
||||
force = entity.force,
|
||||
fast_replace = true,
|
||||
spill = false,
|
||||
raise_built = true,
|
||||
}
|
||||
|
||||
local result = entity.surface.create_entity(options)
|
||||
|
||||
if result == nil then
|
||||
log("Could not replace " .. realName .. " with " .. illusionName)
|
||||
else
|
||||
log("Replaced " .. realName .. " with " .. illusionName)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Holy shit, this is perhaps __the__ most gross portion of the Modding API.
|
||||
on_player_setup_blueprint _should_ be the primary and only method for handling
|
||||
Blueprints, but it is not. It is only _correctly_ called when the Blueprint
|
||||
is first created. If a Blueprint has its contents reselected, then it is still
|
||||
called, but the event data is entirely useless. Allegedly, you'd have to find
|
||||
the Blueprint in the Player's inventory - but it might not always be there either!
|
||||
It seems most in the community went for on_gui_closed which _probably_ has the
|
||||
Blueprint, however it will occur after selection so I imagine there's potential
|
||||
for it to _appear_ wrong before saving. on_gui_opened would work the same,
|
||||
but of course it would not catch any updates, so it's useless in this case.
|
||||
Worse still, this _only_ works for Blueprints in your Inventory - not from
|
||||
the Library! For that situation, we'll warn the Player.
|
||||
|
||||
See:
|
||||
|
||||
[kovarex] [1.0.0] Updated blueprint has no entities during on_player_setup_blueprint
|
||||
https://forums.factorio.com/viewtopic.php?f=48&t=88100
|
||||
|
||||
[kovarex] [1.1.36] Blueprints missing entity list when reused
|
||||
https://forums.factorio.com/viewtopic.php?f=7&t=99323
|
||||
|
||||
[kovarex] [1.0.0] New contents for blueprint broken vs. new blueprint
|
||||
https://forums.factorio.com/viewtopic.php?f=29&t=88793
|
||||
|
||||
Copying (Ctrl+C):
|
||||
- on_blueprint_setup is called
|
||||
- blueprint_to_setup NOT valid_for_read
|
||||
- cursor_stack valid_for_read
|
||||
- cursor_stack is setup, has entity mapping, and entities
|
||||
|
||||
Copying into new Blueprint (Shift+Ctrl+C):
|
||||
Empty Blueprint in cursor, from Inventory or Book in Inventory, selecting new area (Alt+B):
|
||||
- on_blueprint_setup is called
|
||||
- blueprint_to_setup valid_for_read
|
||||
- blueprint_to_setup is setup, has entity mapping, and entities
|
||||
- cursor_stack NOT valid_for_read
|
||||
|
||||
Selecting new contents, from Inventory or Book in Inventory:
|
||||
Selecting new contents, from Library or Book in Library:
|
||||
- on_blueprint_setup is called
|
||||
- blueprint_to_setup NOT valid_for_read
|
||||
- cursor_stack valid_for_read
|
||||
- cursor_stack NOT setup, NO entity mapping, NO entities
|
||||
|
||||
Closing/Confirming Blueprint GUI, from Inventory or Book in Inventory:
|
||||
- on_gui_closed is called
|
||||
- item valid_for_read
|
||||
- item NOT setup, NO entity mapping, but has entities
|
||||
|
||||
Closing/Confirming Blueprint GUI, from Library or Book in Library:
|
||||
- on_gui_closed is called
|
||||
- item valid_for_read
|
||||
- item NOT setup, NO entity mapping, NO entities
|
||||
|
||||
]]
|
||||
|
||||
-- Convert an entire Blueprint's contents from Illusions (if possible)
|
||||
function Illusion.HandleBlueprintEvent(player, potentialItemStacks)
|
||||
if not Sandbox.IsPlayerInsideSandbox(player) then
|
||||
return
|
||||
end
|
||||
|
||||
local blueprint = nil
|
||||
for _, itemStack in pairs(potentialItemStacks) do
|
||||
if itemStack and itemStack.valid_for_read and itemStack.is_blueprint then
|
||||
blueprint = itemStack
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- We must catch more events than we need, so this is expected
|
||||
if not blueprint then
|
||||
return
|
||||
end
|
||||
|
||||
-- Some events won't have a functional Blueprint, so we're screwed!
|
||||
local entities = blueprint.get_blueprint_entities()
|
||||
if not entities then
|
||||
log("Cannot handle Blueprint update: no entities in Blueprint (caused by selecting new contents)")
|
||||
local playerData = global.players[player.index]
|
||||
local lastWarningForNewContents = playerData.lastWarningForNewContents or 0
|
||||
if game.tick - lastWarningForNewContents > (216000) then -- 1 hour
|
||||
player.print("WARNING: Known issues in Factorio prevent mods from seeing or updating Blueprints when using 'Select new contents'.")
|
||||
player.print("This mod requires that ability to swap the Fake Illusions for their Real Entities in your Blueprints.")
|
||||
player.print("If you are including any Fake Illusions in this Blueprint, they likely will NOT be replaced, especially if the source Blueprint is within the Library instead of your Inventory.")
|
||||
player.print("This message will only appear periodically. See the mod's page for more details.")
|
||||
playerData.lastWarningForNewContents = game.tick
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local replaced = 0
|
||||
for _, entity in pairs(entities) do
|
||||
if Illusion.IsIllusion(entity.name) then
|
||||
entity.name = Illusion.GetActualName(entity.name)
|
||||
replaced = replaced + 1
|
||||
end
|
||||
end
|
||||
if replaced > 0 then
|
||||
blueprint.set_blueprint_entities(entities)
|
||||
end
|
||||
log("Replaced " .. replaced .. " entities in Sandbox Blueprint")
|
||||
end
|
||||
|
||||
-- A Player is creating a new Blueprint from a selection
|
||||
function Illusion.OnBlueprintSetup(event)
|
||||
local player = game.players[event.player_index]
|
||||
Illusion.HandleBlueprintEvent(player, {
|
||||
player.blueprint_to_setup,
|
||||
player.cursor_stack,
|
||||
})
|
||||
end
|
||||
|
||||
-- A Player might be updating an existing Blueprint (only works in the Inventory!)
|
||||
function Illusion.OnBlueprintGUIClosed(event)
|
||||
if not event.item then
|
||||
return
|
||||
end
|
||||
Illusion.HandleBlueprintEvent(game.players[event.player_index], {
|
||||
event.item,
|
||||
})
|
||||
end
|
||||
|
||||
return Illusion
|
||||
Reference in New Issue
Block a user