mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
191 lines
6.4 KiB
Lua
191 lines
6.4 KiB
Lua
local Gui = require("modules/exp_gui")
|
|
local ExpElement = require("modules/exp_gui/prototype")
|
|
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
|
|
|
|
-- Used to store the state of the toolbar when a player leaves
|
|
local ToolbarState = PlayerData.Settings:combine("ToolbarState")
|
|
ToolbarState:set_metadata{
|
|
stringify = function(value)
|
|
local buttons, favourites = 0, 0
|
|
for _, state in ipairs(value) do
|
|
buttons = buttons + 1
|
|
if state.favourite then
|
|
favourites = favourites + 1
|
|
end
|
|
end
|
|
|
|
return string.format("Buttons: %d, Favourites: %d", buttons, favourites)
|
|
end,
|
|
}
|
|
|
|
--- Set the default value for the datastore
|
|
local datastore_id_map = {} --- @type table<string, ExpElement>
|
|
local toolbar_default_state = {}
|
|
ToolbarState:set_default(toolbar_default_state)
|
|
|
|
--- Get the datastore id for this element define, to best of ability it should be unique between versions
|
|
local function to_datastore_id(element_define)
|
|
-- First try to use the tooltip locale string
|
|
local tooltip = element_define.tooltip
|
|
if type(tooltip) == "table" then
|
|
return tooltip[1]:gsub("%.(.+)", "")
|
|
end
|
|
|
|
-- Then try to use the caption or sprite
|
|
return element_define.caption or element_define.sprite
|
|
end
|
|
|
|
--- For all top element, register an on click which will copy their style
|
|
for index, element_define in ipairs(Gui.top_elements) do
|
|
-- Insert the element into the id map
|
|
datastore_id_map[to_datastore_id(element_define)] = element_define -- Backwards Compatibility
|
|
datastore_id_map[element_define.name] = element_define
|
|
|
|
-- Add the element to the default state
|
|
table.insert(toolbar_default_state, {
|
|
element = element_define.uid,
|
|
favourite = true,
|
|
})
|
|
end
|
|
|
|
--- Get the top order based on the players settings
|
|
Gui.inject_top_flow_order(function(player)
|
|
local order = ToolbarState:get(player)
|
|
|
|
local elements = {}
|
|
for index, state in ipairs(order) do
|
|
elements[index] = Gui.defines[state.element]
|
|
end
|
|
|
|
return elements
|
|
end)
|
|
|
|
--- Get the left order based on the player settings, with toolbar menu first, and all remaining after
|
|
Gui.inject_left_flow_order(function(player)
|
|
local order = Gui.get_top_flow_order(player)
|
|
local elements, element_map = { toolbar_container }, { [toolbar_container] = true }
|
|
|
|
-- Add the flows that have a top element
|
|
for _, element_define in ipairs(order) do
|
|
if element_define.left_flow_element then
|
|
table.insert(elements, element_define.left_flow_element)
|
|
element_map[element_define.left_flow_element] = true
|
|
end
|
|
end
|
|
|
|
-- Add the flows that dont have a top element
|
|
for _, element_define in ipairs(Gui.left_elements) do
|
|
if not element_map[element_define] then
|
|
table.insert(elements, element_define)
|
|
end
|
|
end
|
|
|
|
return elements
|
|
end)
|
|
|
|
--- Overwrite the default update top flow
|
|
local _update_top_flow = Gui.update_top_flow
|
|
function Gui.update_top_flow(player)
|
|
_update_top_flow(player) -- Call the original
|
|
|
|
local order = ToolbarState:get(player)
|
|
for index, state in ipairs(order) do
|
|
local element_define = Gui.defines[state.element]
|
|
local top_element = Gui.get_top_element(player, element_define)
|
|
top_element.visible = top_element.visible and state.favourite or false
|
|
end
|
|
end
|
|
|
|
--- Uncompress the data to be more useable
|
|
ToolbarState:on_load(function(player_name, value)
|
|
-- If there is no value, do nothing
|
|
if value == nil then return end
|
|
--- @cast value [ string[], string[], string[], boolean ]
|
|
|
|
-- Create a hash map of the favourites
|
|
local favourites = {}
|
|
for _, id in ipairs(value[2]) do
|
|
favourites[id] = true
|
|
end
|
|
|
|
-- Read the order from the value
|
|
local elements = {}
|
|
local element_hash = {}
|
|
for index, id in ipairs(value[1]) do
|
|
local element = datastore_id_map[id]
|
|
if element and not element_hash[element.name] then
|
|
element_hash[element.name] = true
|
|
elements[index] = {
|
|
element = element,
|
|
favourite = favourites[id] or false,
|
|
}
|
|
end
|
|
end
|
|
|
|
-- Add any in the default state that are missing
|
|
for _, state in ipairs(toolbar_default_state) do
|
|
if not element_hash[state.element] then
|
|
table.insert(elements, table.deep_copy(state))
|
|
end
|
|
end
|
|
|
|
-- Create a hash map of the open left flows
|
|
local open_left_elements = {}
|
|
for _, id in ipairs(value[3]) do
|
|
local element = datastore_id_map[id]
|
|
local left_element = element.left_flow_element
|
|
if left_element then
|
|
open_left_elements[left_element] = true
|
|
end
|
|
end
|
|
|
|
-- Set the visible state of all left flows
|
|
local player = assert(game.get_player(player_name))
|
|
for left_element in pairs(Gui.left_elements) do
|
|
Gui.set_left_element_visible(left_element, player, open_left_elements[left_element] or false)
|
|
end
|
|
|
|
-- Set the toolbar visible state
|
|
Gui.set_top_flow_visible(player, value[4])
|
|
|
|
-- Set the data now and update now, ideally this would be on_update but that had too large of a latency
|
|
ToolbarState:raw_set(player_name, elements)
|
|
Gui.reorder_top_flow(player)
|
|
Gui.reorder_left_flow(player)
|
|
reorder_toolbar_menu(player)
|
|
|
|
return elements
|
|
end)
|
|
|
|
--- Save the current state of the players toolbar menu
|
|
ToolbarState:on_save(function(player_name, value)
|
|
if value == nil then return nil end -- Don't save default
|
|
local order, favourites, left_flows = {}, {}, {}
|
|
|
|
local player = assert(game.get_player(player_name))
|
|
local top_flow_open = Gui.get_top_flow(player).parent.visible
|
|
|
|
for index, state in ipairs(value) do
|
|
-- Add the element to the order array
|
|
--- @diagnostic disable-next-line invisible
|
|
local element_define = ExpElement._elements[state.element]
|
|
local id = to_datastore_id(element_define)
|
|
order[index] = id
|
|
|
|
-- If its a favourite then insert it
|
|
if state.favourite then
|
|
table.insert(favourites, id)
|
|
end
|
|
|
|
-- If it has a left flow and its open then insert it
|
|
if element_define.left_flow_element then
|
|
local left_element = Gui.get_left_element(element_define.left_flow_element, player)
|
|
if left_element.visible then
|
|
table.insert(left_flows, id)
|
|
end
|
|
end
|
|
end
|
|
|
|
return { order, favourites, left_flows, top_flow_open }
|
|
end)
|