172 lines
6.1 KiB
Lua

--[[
"name": "BlueprintExtensions",
"title": "Blueprint Extensions",
"author": "Dewin",
"contact": "https://github.com/dewiniaid/BlueprintExtensions",
"homepage": "https://github.com/dewiniaid/BlueprintExensions",
"description": "Adds tools for updating and placing blueprints."
--]]
local Event = require('__stdlib__/stdlib/event/event')
local Player = require('__stdlib__/stdlib/event/player')
local Inventory = require('__stdlib__/stdlib/entity/inventory')
local lib = require('__PickerAtheneum__/utils/lib')
local evt = defines.events
local CLONED_BLUEPRINT = 'picker-bp-updater'
local VERSION_PATTERN = '(v[.]?)(%d)$' -- Matches version number at end of blueprints.
local DEFAULT_VERSION = ' v.2'
local AWAITING_GUI = 1
local AWAITING_BP = 2
local Updater = {}
local function increment_version(v, n)
return v .. (n + 1)
end
local function get_or_create_buffer(player, pdata)
if not (pdata.buffer_inventory and pdata.buffer_inventory.valid) then
pdata.buffer_inventory = lib.create_buffer_corpse(player, true).get_inventory(defines.inventory.character_corpse)
end
return pdata.buffer_inventory
end
local function load_stack(pdata)
if pdata.stored_bp and pdata.stored_bp.valid_for_read then
return pdata.stored_bp
end
end
local function save_stack(player, pdata, stack)
local inv = get_or_create_buffer(player, pdata)
pdata.stored_bp = inv[1]
pdata.stored_bp.set_stack(stack)
end
local rolling_stock = {
['locomotive'] = true,
['cargo-wagon'] = true,
['fluid-wagon'] = true,
['artillery-wagon'] = true
}
-- Capabilities related to updating blueprints.
function Updater.clone(event)
local player, pdata = Player.get(event.player_index)
local bp = Inventory.get_blueprint(player.cursor_stack, true)
if bp then
local updater = {
name = bp.name,
label = bp.label,
icons = bp.blueprint_icons,
status = nil
}
for _, ent in pairs(bp.get_blueprint_entities()) do
if rolling_stock[game.entity_prototypes[ent.name].type] then
updater.trains = true
updater.fuel = ent.items and true or false
elseif ent.station and ent.station ~= "" then
updater.stations = true
end
end
-- Create replacer tool, drop orignal back into inventory
if player.clear_cursor() then
pdata.updater = updater
player.cursor_stack.set_stack(CLONED_BLUEPRINT)
if updater.label then
player.cursor_stack.label = updater.label
end
end -- Warning about not being able to clean?
end
end
function Updater.on_selected_area(event)
if event.item == CLONED_BLUEPRINT then
local alt = (event.name == defines.events.on_player_alt_selected_area)
local player, pdata = Player.get(event.player_index)
local cursor = player.cursor_stack
-- Handle blueprint replacer.
if pdata.updater then
local area = event.area
cursor.set_stack(pdata.updater.name)
cursor.create_blueprint {
surface = player.surface,
force = player.force,
always_include_tiles = true,
include_station_names=pdata.updater.stations,
include_trains=pdata.updater.trains,
area = area
}
if not cursor.is_blueprint_setup() then
-- Empty blueprint area?
return cursor.set_stack(CLONED_BLUEPRINT)
end
local label = pdata.updater.label or 'v.1'
if label then
cursor.blueprint_icons = pdata.updater.icons
local versioning = player.mod_settings[alt and 'picker-bp-updater-alt-version-increment' or 'picker-bp-updater-version-increment'].value
if versioning ~= 'off' then
local found
label, found = label:gsub(VERSION_PATTERN, increment_version)
if found == 0 and versioning == 'on' then
label = label .. DEFAULT_VERSION
end
end
cursor.label = label
end
-- Move this blueprint to a temporary item
local stack = player.cursor_stack
stack.set_stack(save_stack(player, pdata.updater, stack)) -- returns nil, effectivly calling clear()
pdata.updater.status = AWAITING_GUI
player.opened = load_stack(pdata.updater)
else
cursor.clear()
end
end
end
function Updater.on_gui_opened(event)
-- If opening an item, this means our target blueprint was closed at some point and that any
-- on_player_configured_blueprint events we see are nonsense.
if event.gui_type == defines.gui_type.item then
local _, pdata = Player.get(event.player_index)
if pdata.updater then
pdata.updater.status = pdata.updater.status == AWAITING_GUI and AWAITING_BP or nil
end
end
end
function Updater.on_player_configured_blueprint(event)
local player, pdata = Player.get(event.player_index)
if pdata.updater and pdata.updater.status == AWAITING_BP then
if not player.clear_cursor() then
-- rarest of rare edge cases
player.print({'blueprint-updater.error_cannot_set_stack', {'item-name.'..pdata.updater.name}})
local ground = player.surface.create_entity{name = 'item-on-ground', position = player.position, stack = {name = pdata.updater.name, amount = 1}}
ground.stack.set_stack(load_stack(pdata))
else
player.cursor_stack.set_stack(load_stack(pdata.updater))
end
end
pdata.updater = nil -- Nuke this.
end
if settings.startup['picker-tool-bp-updater'].value then
Event.register({evt.on_player_selected_area, evt.on_player_alt_selected_area}, Updater.on_selected_area)
Event.register('picker-bp-update', Updater.clone)
Event.register(evt.on_gui_opened, Updater.on_gui_opened)
Event.register(evt.on_player_configured_blueprint, Updater.on_player_configured_blueprint)
end
return Updater