157 lines
6.7 KiB
Lua

-------------------------------------------------------------------------------
--[Planners]--
-------------------------------------------------------------------------------
-- TODO Remote API for registering/removing planners
local Event = require('__stdlib__/stdlib/event/event')
local Gui = require('__stdlib__/stdlib/event/gui')
local Player = require('__stdlib__/stdlib/event/player')
local lib = require('__PickerAtheneum__/utils/lib')
-------------------------------------------------------------------------------
--[Planner Menu]--
-------------------------------------------------------------------------------
local function is_creative(player, item)
return (item.name:find('creative%-mode') and (player.admin or player.cheat_mode) and remote.call('creative-mode', 'is_enabled'))
end
local function planner_enabled(player, item)
local recipe = player.force.recipes[item.name]
return not recipe or (recipe and recipe.enabled) or is_creative(player, item)
end
local function get_or_create_planner_flow(player, destroy)
local pdata = global.players[player.index]
local flow = player.gui.center['picker_planner_flow']
if flow and destroy then
return flow.destroy()
elseif not flow then
local planners = global.planners
pdata.planners = pdata.planners or {}
flow = player.gui.center.add {type = 'flow', name = 'picker_planner_flow', direction = 'vertical'}
local frame = flow.add {type = 'frame', name = 'picker_planner_frame', direction = 'vertical', caption = {'planner-menu.header'}}
local scroll = frame.add {type = 'scroll-pane', name = 'picker_planner_scroll'}
scroll.style.maximal_height = 110
local gui_table = scroll.add {type = 'table', name = 'picker_planner_table', column_count = 6}
for planner in pairs(planners) do
local proto = game.item_prototypes[planner]
if pdata.planners[planner] == false then
if not proto then
pdata.planners[planner] = nil
end
else
pdata.planners[planner] = true
end
gui_table.add {
type = 'sprite-button',
name = 'picker_planner_table_sprite_' .. planner,
sprite = 'item/' .. planner,
style = pdata.planners[planner] and 'picker_buttons_med' or 'picker_buttons_med_off',
tooltip = {'planner-menu.button', proto.localised_name, proto.localised_description}
}
end
flow.visible = false
end
return flow
end
local function planner_clicked(event)
local player, pdata = Player.get(event.player_index)
local item = game.item_prototypes[event.match]
if item then
if event.button == defines.mouse_button_type.left then
if planner_enabled(player, item) and player.clear_cursor() then
player.cursor_stack.set_stack(event.match)
event.element.parent.parent.parent.parent.visible = false
player.opened = nil
else
player.print({'planner-menu.not-enabled'})
end
elseif event.button == defines.mouse_button_type.right then
event.element.style = event.element.style.name == 'picker_buttons_med' and 'picker_buttons_med_off' or 'picker_buttons_med'
pdata.planners[item.name] = event.element.style.name == 'picker_buttons_med'
end
end
end
Gui.on_click('picker_planner_table_sprite_(.*)', planner_clicked)
local function close_planner_menu(event)
if event.element and event.element.name == 'picker_planner_flow' then
event.element.visible = false
end
end
Event.register(defines.events.on_gui_closed, close_planner_menu)
local function open_or_close_planner_menu(event)
local player = game.players[event.player_index]
local flow = get_or_create_planner_flow(player)
flow.visible = not flow.visible
player.opened = flow.visible and flow or nil
end
Event.register('picker-planner-menu', open_or_close_planner_menu)
-------------------------------------------------------------------------------
--[Next Planner]--
-------------------------------------------------------------------------------
local function get_next_planner(player, last_planner)
local stack = player.cursor_stack
local pdata = global.players[player.index]
local fail = 0
get_or_create_planner_flow(player).visible = false
if (not stack.valid_for_read) then
local planner
if player.mod_settings['picker-remember-planner'].value and pdata.planners[last_planner] then
planner = last_planner
else
repeat
planner = next(pdata.planners, planner)
fail = fail + 1
until pdata.planners[planner] and game.item_prototypes[planner] and planner_enabled(player, game.item_prototypes[planner]) or fail == 100
end
return planner and pdata.planners[planner] and player.clear_cursor() and lib.get_planner(player, planner)
elseif stack.valid_for_read then
local name = stack.name
local selected = player.selected
if pdata.planners[name] and not (name == 'deconstruction-planner' and selected) then
repeat
name = next(pdata.planners, name)
fail = fail + 1
until name and pdata.planners[name] and game.item_prototypes[name] and planner_enabled(player, game.item_prototypes[name]) or fail == 100
return name and pdata.planners[name] and player.clear_cursor() and lib.get_planner(player, name)
end
end
end
local function cycle_planners(event)
local player, pdata = Player.get(event.player_index)
if player.controller_type ~= defines.controllers.ghost then
if not pdata.new_simple or not player.cursor_stack.valid_for_read then
pdata.last_planner = get_next_planner(player, pdata.last_planner) and player.cursor_stack.name
end
pdata.new_simple = false
end
end
Event.register('picker-next-planner', cycle_planners)
local function planners_changed()
global.planners = {}
for _, item in pairs(game.item_prototypes) do
if item.type == 'blueprint-book' or item.type == 'blueprint' or item.type == 'deconstruction-item' or item.type == 'selection-tool' or item.type == 'upgrade-item' then
if not (item.name:find('^selection%-tool') or item.order:find('no%-picker')) then
global.planners[item.name] = true
end
end
end
for _, player in pairs(game.players) do
local gui = player.gui.center['picker_planner_flow']
if gui then
gui.destroy()
end
end
end
Event.register(Event.core_events.init_and_config, planners_changed)