mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
* Refactor custom start * Refactor afk kick * Fix use of assert get player * Refactor chat popup * Refactor chat auto reply * Refactor help bubbles * Refactor damage popups * Refactor death markers * Refactor deconstruction log * Remove FAGC logging * Refactor discord alerts * Refactor insert pickup * Refactor inventory clear * Refactor extra logging * Refactor nuke protection * Refactor pollution grading * Refactor protection jail * Refactor report jail * Refactor mine depletion * Refactor degrading tiles * Refactor station auto name * Refactor spawn area * Refactor fast deconstruction * Bug Fixes
405 lines
15 KiB
Lua
405 lines
15 KiB
Lua
--[[-- Gui - Autofill
|
|
Adds a config menu for setting autofill of placed entities
|
|
]]
|
|
|
|
local Gui = require("modules/exp_gui")
|
|
local Roles = require("modules.exp_legacy.expcore.roles")
|
|
local config = require("modules.exp_legacy.config.gui.autofill")
|
|
local FlyingText = require("modules/exp_util/flying_text")
|
|
|
|
local min = math.min
|
|
local string_format = string.format
|
|
|
|
--- @class ExpGui_Autofill.elements
|
|
local Elements = {}
|
|
|
|
--- Format a type and name to a rich text image
|
|
--- @param type string
|
|
--- @param name string
|
|
--- @return string
|
|
local function rich_img(type, name)
|
|
return string_format("[img=%s/%s]", type, name)
|
|
end
|
|
|
|
--- Toggle the visible state of a section
|
|
--- @class ExpGui_Autofill.elements.toggle_section_button: ExpElement
|
|
--- @field data table<LuaGuiElement, LuaGuiElement>
|
|
--- @overload fun(parent: LuaGuiElement, section: LuaGuiElement): LuaGuiElement
|
|
Elements.toggle_section_button = Gui.define("autofill/toggle_section_button")
|
|
:draw{
|
|
type = "sprite-button",
|
|
sprite = "utility/expand",
|
|
tooltip = { "exp-gui_autofill.tooltip-toggle-section-expand" },
|
|
style = "frame_action_button",
|
|
}
|
|
:style{
|
|
size = 20,
|
|
padding = -2,
|
|
}
|
|
:element_data(
|
|
Gui.from_argument(1)
|
|
)
|
|
:on_click(function(def, player, element)
|
|
--- @cast def ExpGui_Autofill.elements.toggle_section_button
|
|
local section = def.data[element]
|
|
if Gui.toggle_visible_state(section) then
|
|
element.sprite = "utility/collapse"
|
|
element.tooltip = { "exp-gui_autofill.tooltip-toggle-section-collapse" }
|
|
else
|
|
element.sprite = "utility/expand"
|
|
element.tooltip = { "exp-gui_autofill.tooltip-toggle-section-expand" }
|
|
end
|
|
end) --[[ @as any ]]
|
|
|
|
--- Toggle if an entity will be autofilled when played
|
|
--- @class ExpGui_Autofill.elements.toggle_entity_button: ExpElement
|
|
--- @field data table<LuaGuiElement, ExpGui_Autofill.entity_settings>
|
|
--- @overload fun(parent: LuaGuiElement, entity_settings: ExpGui_Autofill.entity_settings): LuaGuiElement
|
|
Elements.toggle_entity_button = Gui.define("autofill/toggle_entity_button")
|
|
:draw(function(_, parent, entity_settings)
|
|
--- @cast entity_settings ExpGui_Autofill.entity_settings
|
|
local enabled = entity_settings.enabled
|
|
return parent.add{
|
|
type = "sprite-button",
|
|
tooltip = { "exp-gui_autofill.tooltip-toggle-entity", rich_img("item", entity_settings.entity) },
|
|
sprite = enabled and "utility/confirm_slot" or "utility/close_black",
|
|
style = enabled and "shortcut_bar_button_green" or "shortcut_bar_button_red",
|
|
}
|
|
end)
|
|
:style{
|
|
size = 22,
|
|
padding = -2,
|
|
}
|
|
:element_data(
|
|
Gui.from_argument(1)
|
|
)
|
|
:on_click(function(def, player, element)
|
|
--- @cast def ExpGui_Autofill.elements.toggle_entity_button
|
|
local entity_settings = def.data[element]
|
|
local enabled = not entity_settings.enabled
|
|
entity_settings.enabled = enabled
|
|
|
|
-- Update the sprite and style
|
|
element.sprite = enabled and "utility/confirm_slot" or "utility/close_black"
|
|
element.style = enabled and "shortcut_bar_button_green" or "shortcut_bar_button_red"
|
|
|
|
-- Correct the button size
|
|
local style = element.style
|
|
style.padding = 0
|
|
style.height = 22
|
|
style.width = 22
|
|
end) --[[ @as any ]]
|
|
|
|
--- Toggle if an item will be inserted into an entity
|
|
--- @class ExpGui_Autofill.elements.toggle_item_button: ExpElement
|
|
--- @field data table<LuaGuiElement, ExpGui_Autofill.item_settings>
|
|
--- @overload fun(parent: LuaGuiElement, item_settings: ExpGui_Autofill.item_settings): LuaGuiElement
|
|
Elements.toggle_item_button = Gui.define("autofill/toggle_item_button")
|
|
:draw(function(_, parent, item_settings)
|
|
--- @cast item_settings ExpGui_Autofill.item_settings
|
|
return parent.add{
|
|
type = "sprite-button",
|
|
sprite = "item/" .. item_settings.name,
|
|
tooltip = { "exp-gui_autofill.tooltip-toggle-item", rich_img("item", item_settings.name), item_settings.category },
|
|
style = item_settings.enabled and "shortcut_bar_button_green" or "shortcut_bar_button_red",
|
|
}
|
|
end)
|
|
:style{
|
|
size = 32,
|
|
right_margin = -3,
|
|
padding = -1,
|
|
}
|
|
:element_data(
|
|
Gui.from_argument(1)
|
|
)
|
|
:on_click(function(def, player, element)
|
|
--- @cast def ExpGui_Autofill.elements.toggle_item_button
|
|
local item_settings = def.data[element]
|
|
local enabled = not item_settings.enabled
|
|
item_settings.enabled = enabled
|
|
|
|
-- Update the style
|
|
element.style = enabled and "shortcut_bar_button_green" or "shortcut_bar_button_red"
|
|
|
|
-- Correct the button size
|
|
local style = element.style
|
|
style.right_margin = -3
|
|
style.padding = -2
|
|
style.height = 32
|
|
style.width = 32
|
|
end) --[[ @as any ]]
|
|
|
|
--- The amount of an item to insert
|
|
--- @class ExpGui_Autofill.elements.amount_textfield: ExpElement
|
|
--- @field data table<LuaGuiElement, ExpGui_Autofill.item_settings>
|
|
--- @overload fun(parent: LuaGuiElement, item_settings: ExpGui_Autofill.item_settings): LuaGuiElement
|
|
Elements.amount_textfield = Gui.define("autofill/amount_textfield")
|
|
:draw(function(_, parent, item_settings)
|
|
--- @cast item_settings ExpGui_Autofill.item_settings
|
|
return parent.add{
|
|
type = "textfield",
|
|
tooltip = { "exp-gui_autofill.tooltip-amount", item_settings.category },
|
|
text = tostring(item_settings.amount) or "",
|
|
clear_and_focus_on_right_click = true,
|
|
numeric = true,
|
|
allow_decimal = false,
|
|
allow_negative = false,
|
|
}
|
|
end)
|
|
:style{
|
|
horizontally_stretchable = true,
|
|
minimal_width = 40,
|
|
height = 31,
|
|
padding = -2,
|
|
}
|
|
:element_data(
|
|
Gui.from_argument(1)
|
|
)
|
|
:on_text_changed(function(def, player, element, event)
|
|
--- @cast def ExpGui_Autofill.elements.amount_textfield
|
|
local value = tonumber(element.text) or 0
|
|
local clamped = math.clamp(value, 0, 999)
|
|
local item_settings = def.data[element]
|
|
item_settings.amount = clamped
|
|
if clamped ~= value then
|
|
element.text = tostring(clamped)
|
|
player.print{ "exp-gui_autofill.invalid", clamped, rich_img("item", item_settings.name), rich_img("entity", item_settings.entity) }
|
|
end
|
|
end) --[[ @as any ]]
|
|
|
|
--- A disabled version of the autofill settings used as a filler
|
|
Elements.disabled_autofill_setting = Gui.define("autofill/empty_autofill_setting")
|
|
:draw(function(_, parent)
|
|
local toggle_element_style = parent.add{
|
|
type = "sprite-button",
|
|
enabled = false,
|
|
}.style
|
|
toggle_element_style.right_margin = -3
|
|
toggle_element_style.width = 32
|
|
toggle_element_style.height = 32
|
|
|
|
local amount_element_style = parent.add{
|
|
type = "textfield",
|
|
enabled = false,
|
|
}.style
|
|
amount_element_style.horizontally_stretchable = true
|
|
amount_element_style.minimal_width = 40
|
|
amount_element_style.height = 31
|
|
amount_element_style.padding = -2
|
|
|
|
return Gui.no_return()
|
|
end)
|
|
|
|
--- Section representing an entity
|
|
--- @class ExpGui_Autofill.elements.section: ExpElement
|
|
--- @field data table<LuaGuiElement, LuaGuiElement|ExpGui_Autofill.entity_settings>
|
|
--- @overload fun(parent: LuaGuiElement, entity_settings: ExpGui_Autofill.entity_settings): LuaGuiElement
|
|
Elements.section = Gui.define("autofill/section")
|
|
:draw(function(def, parent, entity_settings)
|
|
--- @cast def ExpGui_Autofill.elements.section
|
|
--- @cast entity_settings ExpGui_Autofill.entity_settings
|
|
local header = Gui.elements.header(parent, {
|
|
caption = { "exp-gui_autofill.caption-section-header", rich_img("item", entity_settings.entity), { "entity-name." .. entity_settings.entity } },
|
|
tooltip = { "exp-gui_autofill.tooltip-toggle-section" },
|
|
})
|
|
|
|
local section_table = parent.add{
|
|
type = "table",
|
|
column_count = 3,
|
|
visible = false,
|
|
}
|
|
|
|
section_table.style.padding = 3
|
|
|
|
local header_label = header.label
|
|
Elements.toggle_entity_button(header, entity_settings)
|
|
def.data[header_label] = Elements.toggle_section_button(header, section_table)
|
|
def.data[section_table] = entity_settings
|
|
|
|
def:link_element(header_label)
|
|
return def:unlink_element(section_table)
|
|
end)
|
|
:on_click(function(def, player, element, event)
|
|
--- @cast def ExpGui_Autofill.elements.section
|
|
event.element = def.data[element] --[[ @as LuaGuiElement ]]
|
|
Elements.toggle_section_button:raise_event(event)
|
|
end) --[[ @as any ]]
|
|
|
|
--- Add an item category to a section, at most three can exist
|
|
--- @param section LuaGuiElement
|
|
--- @param category_name string
|
|
--- @return LuaGuiElement, number
|
|
function Elements.section.add_category(section, category_name)
|
|
local category = section.add{
|
|
type = "table",
|
|
column_count = 2,
|
|
}
|
|
|
|
category.style.vertical_spacing = 1
|
|
|
|
local ctn = 0
|
|
local entity_settings = Elements.section.data[section] --[[ @as ExpGui_Autofill.entity_settings ]]
|
|
for _, item_data in pairs(entity_settings.items) do
|
|
if item_data.category == category_name then
|
|
Elements.toggle_item_button(category, item_data)
|
|
Elements.amount_textfield(category, item_data)
|
|
ctn = ctn + 1
|
|
end
|
|
end
|
|
|
|
return category, ctn
|
|
end
|
|
|
|
--- @class ExpGui_Autofill.item_settings
|
|
--- @field entity string
|
|
--- @field category string
|
|
--- @field inv defines.inventory
|
|
--- @field name string
|
|
--- @field amount number
|
|
--- @field enabled boolean
|
|
|
|
--- @class ExpGui_Autofill.entity_settings
|
|
--- @field entity string
|
|
--- @field enabled boolean
|
|
--- @field items ExpGui_Autofill.item_settings[]
|
|
|
|
--- Container added to the left gui flow
|
|
--- @class ExpGui_Autofill.elements.container: ExpElement
|
|
--- @field data table<string, ExpGui_Autofill.entity_settings>
|
|
Elements.container = Gui.define("autofill/container")
|
|
:draw(function(def, parent)
|
|
--- @cast def ExpGui_Autofill.elements.container
|
|
local container = Gui.elements.container(parent)
|
|
local scroll_pane = Gui.elements.scroll_pane(container, 524)
|
|
scroll_pane.style.padding = 0
|
|
|
|
-- Cant modify vertical spacing on scroll pane style so need a sub flow
|
|
scroll_pane = scroll_pane.add{ type = "flow", direction = "vertical" }
|
|
scroll_pane.style.vertical_spacing = 0
|
|
scroll_pane.style.padding = 0
|
|
|
|
-- Add a header
|
|
Gui.elements.header(scroll_pane, {
|
|
caption = { "exp-gui_autofill.caption-main" },
|
|
})
|
|
|
|
-- Setup the player data, this is used by section and item category so needs to be done here
|
|
local player = Gui.get_player(parent)
|
|
--- @type table<string, ExpGui_Autofill.entity_settings>
|
|
local player_data = def.data[player] or table.deep_copy(config.default_entities)
|
|
def.data[player] = player_data
|
|
|
|
-- Add sections for each entity
|
|
for _, entity_settings in pairs(player_data) do
|
|
local section = Elements.section(scroll_pane, entity_settings)
|
|
|
|
-- Add the categories
|
|
local categories, largest = {}, 0
|
|
for _, category_name in pairs(config.categories) do
|
|
local category, size = Elements.section.add_category(section, category_name)
|
|
if largest < size then
|
|
largest = size
|
|
end
|
|
categories[category] = size
|
|
end
|
|
|
|
-- Fill in blanks for smaller categories
|
|
for category, size in pairs(categories) do
|
|
for i = size, largest - 1 do
|
|
Elements.disabled_autofill_setting(category)
|
|
end
|
|
end
|
|
end
|
|
|
|
return container.parent
|
|
end) --[[ @as any ]]
|
|
|
|
--- Get the autofill settings for a player
|
|
--- @param player LuaPlayer
|
|
--- @param entity_name string
|
|
--- @return ExpGui_Autofill.entity_settings
|
|
function Elements.container.get_autofill_settings(player, entity_name)
|
|
return Elements.container.data[player][entity_name]
|
|
end
|
|
|
|
--- Add the element to the left flow with a toolbar button
|
|
Gui.add_left_element(Elements.container, false)
|
|
Gui.toolbar.create_button{
|
|
name = "toggle_autofill",
|
|
left_element = Elements.container,
|
|
sprite = config.icon,
|
|
tooltip = { "exp-gui_autofill.tooltip-main" },
|
|
visible = function(player, element)
|
|
return Roles.player_allowed(player, "gui/autofill")
|
|
end
|
|
}
|
|
|
|
--- @param event EventData.on_built_entity
|
|
local function on_built_entity(event)
|
|
local player = Gui.get_player(event)
|
|
|
|
-- Check if the entity is in the config and enabled
|
|
local entity = event.entity
|
|
local entity_settings = Elements.container.get_autofill_settings(player, entity.name)
|
|
if not entity_settings or not entity_settings.enabled then
|
|
return
|
|
end
|
|
|
|
-- Get the inventory of the player
|
|
local player_inventory = player.get_main_inventory() --- @cast player_inventory -nil
|
|
local player_get_item_count = player_inventory.get_item_count
|
|
local player_remove = player_inventory.remove
|
|
|
|
-- Setup the tables being used
|
|
local offset = { x = 0, y = 0 }
|
|
local item = { name = "", count = 0 }
|
|
local color = { r = 0, g = 255, b = 0, a = 255 }
|
|
local flyingText = {
|
|
target_entity = entity,
|
|
text = "",
|
|
offset = offset,
|
|
player = player,
|
|
color = color,
|
|
}
|
|
|
|
for _, item_settings in pairs(entity_settings.items) do
|
|
-- Check if the item is enabled or goto next item
|
|
if not item_settings.enabled then goto continue end
|
|
|
|
-- Get the inventory of the entity or goto next item
|
|
local entity_inventory = entity.get_inventory(item_settings.inv)
|
|
if not entity_inventory then goto continue end
|
|
|
|
local preferred_amount = item_settings.amount
|
|
local item_amount = player_get_item_count(item_settings.name)
|
|
if item_amount ~= 0 then
|
|
item.name = item_settings.name
|
|
item.count = min(preferred_amount, item_amount)
|
|
if not entity_inventory.can_insert(item) then goto continue end
|
|
local inserted = entity_inventory.insert(item)
|
|
|
|
local ran_out = item_amount < preferred_amount
|
|
color.r = ran_out and 255 or 0
|
|
color.g = ran_out and 165 or 255
|
|
|
|
item.count = inserted
|
|
player_remove(item)
|
|
|
|
flyingText.text = { "exp-gui_autofill.inserted", inserted, rich_img("item", item_settings.name), rich_img("entity", entity.name) }
|
|
FlyingText.create_above_entity(flyingText)
|
|
offset.y = offset.y - 0.33
|
|
end
|
|
|
|
::continue::
|
|
end
|
|
end
|
|
|
|
local e = defines.events
|
|
|
|
return {
|
|
elements = Elements,
|
|
events = {
|
|
[e.on_built_entity] = on_built_entity,
|
|
}
|
|
}
|