421 lines
16 KiB
Lua
421 lines
16 KiB
Lua
Gui = {}
|
|
|
|
---Toggles mod GUI on or off
|
|
---@param player_index uint Player index
|
|
---@param state boolean true -> on, false -> off
|
|
function Gui.toggle(player_index, state)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
state = state or not playerdata.is_active
|
|
|
|
if state then
|
|
playerdata.is_active = true
|
|
|
|
-- Create mod gui and register event handler
|
|
Gui.make_gui(player_index)
|
|
register_inventory_monitoring(true)
|
|
register_logistics_monitoring(true)
|
|
else
|
|
playerdata.is_active = false
|
|
playerdata.job = {
|
|
area={},
|
|
ghosts={},
|
|
requests={},
|
|
requests_sorted={}
|
|
}
|
|
-- Destroy mod GUI and remove references to it
|
|
if playerdata.gui.root and playerdata.gui.root.valid then
|
|
local last_location = playerdata.gui.root.location --[[@as GuiLocation.0]]
|
|
playerdata.gui.root.destroy()
|
|
playerdata.gui = {last_location=last_location}
|
|
end
|
|
|
|
-- Unbind event hooks if no no longer needed
|
|
if not is_inventory_monitoring_needed() then register_inventory_monitoring(false) end
|
|
if not is_logistics_monitoring_needed() then register_logistics_monitoring(false) end
|
|
end
|
|
end
|
|
|
|
---Make mod GUI
|
|
---@param player_index uint Player index
|
|
function Gui.make_gui(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local screen = playerdata.luaplayer.gui.screen
|
|
local window_loc_x, window_loc_y
|
|
|
|
-- Restore previous saved location, if any
|
|
if playerdata.gui.last_location then
|
|
local location = playerdata.gui.last_location
|
|
local resolution = playerdata.luaplayer.display_resolution
|
|
|
|
window_loc_x = location.x < resolution.width and location.x or nil
|
|
window_loc_y = location.y < resolution.height and location.y or nil
|
|
end
|
|
|
|
-- Destory existing mod GUI if one exists
|
|
if screen[NAME.gui.root_frame] then
|
|
local location = screen[NAME.gui.root_frame].location
|
|
window_loc_x, window_loc_y = location.x, location.y
|
|
screen[NAME.gui.root_frame].destroy()
|
|
end
|
|
|
|
playerdata.gui.root = screen.add{
|
|
type="frame",
|
|
name=NAME.gui.root_frame,
|
|
direction="vertical",
|
|
style=NAME.style.root_frame
|
|
}
|
|
|
|
do
|
|
local resolution = playerdata.luaplayer.display_resolution
|
|
local x = window_loc_x or 50
|
|
local y = window_loc_y or (resolution.height / 2) - 300
|
|
playerdata.gui.root.location = {x, y}
|
|
end
|
|
|
|
-- Create title bar
|
|
local titlebar_flow = playerdata.gui.root.add{
|
|
type="flow",
|
|
direction="horizontal",
|
|
style=NAME.style.titlebar_flow
|
|
}
|
|
titlebar_flow.drag_target = playerdata.gui.root
|
|
titlebar_flow.add{
|
|
type="label",
|
|
caption="Ghost Counter",
|
|
ignored_by_interaction=true,
|
|
style="frame_title"
|
|
}
|
|
titlebar_flow.add{
|
|
type="empty-widget",
|
|
ignored_by_interaction=true,
|
|
style=NAME.style.titlebar_space_header
|
|
}
|
|
|
|
local hide_empty = playerdata.options.hide_empty_requests
|
|
titlebar_flow.add{
|
|
type="sprite-button",
|
|
name=NAME.gui.hide_empty_button,
|
|
tooltip={"ghost-counter-gui.hide-empty-requests-tooltip"},
|
|
sprite=hide_empty and NAME.sprite.hide_empty_black or NAME.sprite.hide_empty_white,
|
|
hovered_sprite=NAME.sprite.hide_empty_black,
|
|
clicked_sprite=hide_empty and NAME.sprite.hide_empty_white or NAME.sprite.hide_empty_black,
|
|
style=hide_empty and NAME.style.titlebar_button_active or NAME.style.titlebar_button
|
|
}
|
|
titlebar_flow.add{
|
|
type="sprite-button",
|
|
name=NAME.gui.close_button,
|
|
sprite="utility/close_white",
|
|
hovered_sprite="utility/close_black",
|
|
clicked_sprite="utility/close_black",
|
|
tooltip={"ghost-counter-gui.close-button-tooltip"},
|
|
style="close_button"
|
|
}
|
|
|
|
local deep_frame = playerdata.gui.root.add{
|
|
type="frame",
|
|
direction="vertical",
|
|
style=NAME.style.inside_deep_frame
|
|
}
|
|
|
|
local toolbar = deep_frame.add{
|
|
type="frame",
|
|
direction="horizontal",
|
|
style=NAME.style.topbar_frame
|
|
}
|
|
toolbar.add{
|
|
type="sprite-button",
|
|
name=NAME.gui.get_signals_button,
|
|
sprite=NAME.sprite.get_signals_white,
|
|
hovered_sprite=NAME.sprite.get_signals_black,
|
|
clicked_sprite=NAME.sprite.get_signals_black,
|
|
tooltip={"ghost-counter-gui.get-signals-tooltip"},
|
|
style=NAME.style.get_signals_button
|
|
}
|
|
toolbar.add{
|
|
type="empty-widget",
|
|
style=NAME.style.topbar_space
|
|
}
|
|
toolbar.add{
|
|
type="sprite-button",
|
|
name=NAME.gui.craft_all_button,
|
|
sprite=NAME.sprite.craft_all_white,
|
|
hovered_sprite=NAME.sprite.craft_all_black,
|
|
clicked_sprite=NAME.sprite.craft_all_black,
|
|
tooltip={"ghost-counter-gui.craft-all-tooltip"},
|
|
style=NAME.style.get_signals_button
|
|
}
|
|
toolbar.add{
|
|
type="button",
|
|
name=NAME.gui.request_all_button,
|
|
caption={"ghost-counter-gui.request-all-caption"},
|
|
tooltip={"ghost-counter-gui.request-all-tooltip"},
|
|
style=NAME.style.ghost_request_all_button
|
|
}
|
|
toolbar.add{
|
|
type="sprite-button",
|
|
name=NAME.gui.cancel_all_button,
|
|
sprite=NAME.sprite.cancel_white,
|
|
hovered_sprite=NAME.sprite.cancel_black,
|
|
clicked_sprite=NAME.sprite.cancel_black,
|
|
tooltip={"ghost-counter-gui.cancel-all-tooltip"},
|
|
style=NAME.style.ghost_cancel_all_button
|
|
}
|
|
|
|
playerdata.gui.requests_container = deep_frame.add{
|
|
type="scroll-pane",
|
|
name=NAME.gui.scroll_pane,
|
|
style=NAME.style.scroll_pane
|
|
}
|
|
|
|
Gui.make_list(player_index)
|
|
end
|
|
|
|
---Creates the list of request frames in the GUI
|
|
---@param player_index uint Player index
|
|
function Gui.make_list(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
|
|
-- Create a new row frame for each request
|
|
playerdata.gui.requests = {}
|
|
for _, request in pairs(playerdata.job.requests_sorted) do
|
|
Gui.make_row(player_index, request)
|
|
end
|
|
end
|
|
|
|
---Returns request button properties based on request fulfillment and other criteria
|
|
---@param request table `request` table
|
|
---@param one_time_request table `playerdata.logistic_requests[request.name]`
|
|
---@return boolean enabled Whehter button should be enabled
|
|
---@return string style Style that should be applied to the button
|
|
---@return LocalisedString tooltip Tooltip shown for button
|
|
function make_request_button_properties(request, one_time_request)
|
|
local logistic_request = request.logistic_request or {}
|
|
|
|
local enabled = ((logistic_request.min or 0) < request.count) or one_time_request and true or
|
|
false
|
|
local style =
|
|
((logistic_request.min or 0) < request.count) and NAME.style.ghost_request_button or
|
|
NAME.style.ghost_request_active_button
|
|
|
|
local str = "[item=" .. request.name .. "] "
|
|
|
|
local tooltip
|
|
if enabled then
|
|
tooltip = ((logistic_request.min or 0) < request.count) and
|
|
{"ghost-counter-gui.set-temporary-request-tooltip", request.count, str} or
|
|
{"ghost-counter-gui.unset-temporary-request-tooltip"}
|
|
else
|
|
tooltip = {"ghost-counter-gui.existing-logistic-request-tooltip"}
|
|
end
|
|
|
|
return enabled, style, tooltip
|
|
end
|
|
|
|
---Updates the list of request frames in the GUI
|
|
---@param player_index uint Player index
|
|
function Gui.update_list(player_index)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
if not playerdata.is_active or not playerdata.gui.requests then return end
|
|
|
|
local indices = {count=1, sprite=2, label=3, inventory=4, request=5}
|
|
|
|
-- Update gui elements with new values
|
|
for name, frame in pairs(playerdata.gui.requests) do
|
|
local request = playerdata.job.requests[name]
|
|
|
|
if request.count > 0 or not playerdata.options.hide_empty_requests then
|
|
frame.visible = true
|
|
-- Update ghost count
|
|
frame.children[indices.count].caption = request.count
|
|
|
|
-- Update amont in inventory
|
|
frame.children[indices.inventory].caption = request.inventory
|
|
|
|
-- Calculate amount missing
|
|
local diff = request.count - request.inventory
|
|
|
|
-- If amount needed exceeds amount in inventory, show request button
|
|
local request_element = frame.children[indices.request]
|
|
if diff > 0 then
|
|
local enabled, style, tooltip = make_request_button_properties(request,
|
|
playerdata.logistic_requests[request.name])
|
|
|
|
if request_element.type == "button" then
|
|
request_element.enabled = enabled
|
|
request_element.style = style
|
|
request_element.caption = diff
|
|
request_element.tooltip = tooltip
|
|
else
|
|
frame.children[indices.request].destroy()
|
|
frame.add{
|
|
type="button",
|
|
caption=diff,
|
|
enabled=enabled,
|
|
style=style,
|
|
tooltip=tooltip,
|
|
tags={ghost_counter_request=request.name}
|
|
}
|
|
end
|
|
-- Otherwise create request-fulfilled checkmark previous element was a request button
|
|
elseif request_element.type == "button" then
|
|
request_element.destroy()
|
|
|
|
local sprite_container = frame.add{
|
|
type="flow",
|
|
direction="horizontal",
|
|
style=NAME.style.ghost_request_fulfilled_flow
|
|
}
|
|
sprite_container.add{
|
|
type="sprite",
|
|
sprite="utility/check_mark_white",
|
|
resize_to_sprite=false,
|
|
style=NAME.style.ghost_request_fulfilled_sprite
|
|
}
|
|
end
|
|
else
|
|
frame.visible = false
|
|
end
|
|
end
|
|
end
|
|
|
|
---Generates the row frame for a given request table
|
|
---@param player_index uint Player index
|
|
---@param request table `request` table, containing name, count, inventory, etc.
|
|
function Gui.make_row(player_index, request)
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local parent = playerdata.gui.requests_container
|
|
|
|
local localized_name = game.item_prototypes[request.name].localised_name
|
|
|
|
-- Row frame
|
|
local frame = parent.add{type="frame", direction="horizontal", style=NAME.style.row_frame}
|
|
playerdata.gui.requests[request.name] = frame
|
|
|
|
-- Ghost (item) count
|
|
frame.add{type="label", caption=request.count, style=NAME.style.ghost_number_label}
|
|
|
|
-- Item sprite
|
|
frame.add{
|
|
type="sprite",
|
|
sprite="item/" .. request.name,
|
|
resize_to_sprite=false,
|
|
style=NAME.style.ghost_sprite
|
|
}
|
|
|
|
-- Item or tile localized name
|
|
frame.add{type="label", caption=localized_name, style=NAME.style.ghost_name_label}
|
|
|
|
-- Amount in inventory
|
|
frame.add{type="label", caption=request.inventory, style=NAME.style.inventory_number_label}
|
|
|
|
-- Calculate amount missing
|
|
local diff = request.count - request.inventory
|
|
|
|
-- Show one-time request logistic button
|
|
if diff > 0 then
|
|
local enabled, style, tooltip = make_request_button_properties(request,
|
|
playerdata.logistic_requests[request.name])
|
|
|
|
frame.add{
|
|
type="button",
|
|
caption=diff,
|
|
enabled=enabled,
|
|
style=style,
|
|
tooltip=tooltip,
|
|
tags={ghost_counter_request=request.name}
|
|
}
|
|
else -- Show request fulfilled sprite
|
|
local sprite_container = frame.add{
|
|
type="flow",
|
|
direction="horizontal",
|
|
style=NAME.style.ghost_request_fulfilled_flow
|
|
}
|
|
sprite_container.add{
|
|
type="sprite",
|
|
sprite="utility/check_mark_white",
|
|
resize_to_sprite=false,
|
|
style=NAME.style.ghost_request_fulfilled_sprite
|
|
}
|
|
end
|
|
|
|
-- Hide frame if ghost count is 0 and player toggled hide empty requests
|
|
frame.visible = request.count > 0 or not playerdata.options.hide_empty_requests and true or
|
|
false
|
|
end
|
|
|
|
---Event handler for GUI button clicks
|
|
---@param event EventData.on_gui_click Event table
|
|
function Gui.on_gui_click(event)
|
|
local player_index = event.player_index
|
|
local element = event.element
|
|
local element_name = element.name
|
|
|
|
if element.name == NAME.gui.close_button then
|
|
-- Close button
|
|
Gui.toggle(player_index, false)
|
|
elseif element.tags and element.tags.ghost_counter_request then
|
|
-- One-time logistic request/craft button
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local request_name = element.tags.ghost_counter_request --[[@as string]]
|
|
if event.shift == true then
|
|
local request = playerdata.job.requests[request_name]
|
|
if request then
|
|
local result, crafted = craft_request(event.player_index, request)
|
|
local player = game.get_player(player_index) --[[@as LuaPlayer]]
|
|
if result == "no-crafts-needed" then
|
|
player.create_local_flying_text{
|
|
text={"ghost-counter-message.crafts-not-needed"},
|
|
create_at_cursor=true
|
|
}
|
|
elseif result == "attempted" and crafted == 0 then
|
|
player.create_local_flying_text{
|
|
text={"ghost-counter-message.crafts-attempted-none"},
|
|
create_at_cursor=true
|
|
}
|
|
end
|
|
end
|
|
else
|
|
if not playerdata.logistic_requests[request_name] then
|
|
make_one_time_logistic_request(player_index, request_name)
|
|
Gui.update_list(player_index)
|
|
else
|
|
restore_prior_logistic_request(player_index, request_name)
|
|
Gui.update_list(player_index)
|
|
end
|
|
end
|
|
elseif element_name == NAME.gui.hide_empty_button then
|
|
local playerdata = get_make_playerdata(player_index)
|
|
local new_state = not playerdata.options.hide_empty_requests
|
|
playerdata.options.hide_empty_requests = new_state
|
|
|
|
element.style = new_state and NAME.style.titlebar_button_active or
|
|
NAME.style.titlebar_button
|
|
element.sprite = new_state and NAME.sprite.hide_empty_black or NAME.sprite.hide_empty_white
|
|
element.clicked_sprite = new_state and NAME.sprite.hide_empty_white or
|
|
NAME.sprite.hide_empty_black
|
|
|
|
Gui.update_list(player_index)
|
|
elseif element_name == NAME.gui.get_signals_button then
|
|
make_combinators_blueprint(event.player_index)
|
|
elseif element_name == NAME.gui.craft_all_button then
|
|
local playerdata = get_make_playerdata(player_index)
|
|
for _, request in pairs(playerdata.job.requests) do
|
|
craft_request(player_index, request)
|
|
end
|
|
elseif element_name == NAME.gui.request_all_button then
|
|
local playerdata = get_make_playerdata(player_index)
|
|
for _, request in pairs(playerdata.job.requests) do
|
|
if request.count > 0 and not playerdata.logistic_requests[request.name] then
|
|
make_one_time_logistic_request(player_index, request.name)
|
|
end
|
|
end
|
|
|
|
Gui.update_list(player_index)
|
|
elseif element_name == NAME.gui.cancel_all_button then
|
|
cancel_all_one_time_requests(player_index)
|
|
|
|
Gui.update_list(player_index)
|
|
end
|
|
end
|
|
script.on_event(defines.events.on_gui_click, Gui.on_gui_click)
|