mirror of
https://github.com/Refactorio/RedMew.git
synced 2025-03-17 21:08:08 +02:00
Replaced settings commands with a GUI
This commit is contained in:
parent
421e78a2b1
commit
ac9c25ac6e
@ -361,7 +361,12 @@ global.config = {
|
||||
-- allows the saving and automatic loading of quickbars between maps
|
||||
player_quick_bars = {
|
||||
enabled = true
|
||||
}
|
||||
},
|
||||
-- enables the redmew settings GUI
|
||||
redmew_settings = {
|
||||
enabled = true,
|
||||
use_remote_server = true,
|
||||
},
|
||||
}
|
||||
|
||||
return global.config
|
||||
|
@ -133,6 +133,9 @@ end
|
||||
if config.rich_text_gui.enabled then
|
||||
require 'features.gui.rich_text'
|
||||
end
|
||||
if config.redmew_settings.enabled then
|
||||
require 'features.gui.redmew_settings'
|
||||
end
|
||||
|
||||
-- Debug-only modules
|
||||
if _DEBUG then
|
||||
|
241
features/gui/redmew_settings.lua
Normal file
241
features/gui/redmew_settings.lua
Normal file
@ -0,0 +1,241 @@
|
||||
local Gui = require 'utils.gui'
|
||||
local Token = require 'utils.token'
|
||||
local Event = require 'utils.event'
|
||||
local Game = require 'utils.game'
|
||||
local Server = require 'features.server'
|
||||
local Toast = require 'features.gui.toast'
|
||||
local Settings = require 'utils.redmew_settings'
|
||||
local Color = require 'resources.color_presets'
|
||||
|
||||
local pairs = pairs
|
||||
local table_size = table.size
|
||||
|
||||
local main_button_name = Gui.uid_name()
|
||||
local save_changes_button_name = Gui.uid_name()
|
||||
local main_frame_name = Gui.uid_name()
|
||||
|
||||
local Public = {}
|
||||
|
||||
local on_player_settings_get = Token.register(function (data)
|
||||
local player = game.players[data.key]
|
||||
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local settings = data.value
|
||||
|
||||
if settings ~= nil then
|
||||
local player_index = player.index
|
||||
for key, value in pairs(settings) do
|
||||
Settings.set(player_index, key, value)
|
||||
end
|
||||
end
|
||||
|
||||
local button = player.gui.top[main_button_name]
|
||||
button.enabled = true
|
||||
button.tooltip = {'redmew_settings.menu_item_tooltip'}
|
||||
end)
|
||||
|
||||
local function player_created(event)
|
||||
local player = Game.get_player_by_index(event.player_index)
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local button = player.gui.top.add({
|
||||
type = 'sprite-button',
|
||||
name = main_button_name,
|
||||
sprite = 'item/iron-gear-wheel',
|
||||
tooltip = {'redmew_settings.menu_item_tooltip'}
|
||||
})
|
||||
|
||||
-- disable the button if the remote server is used, won't be available until the settings are loaded
|
||||
if global.config.redmew_settings.use_remote_server then
|
||||
button.enabled = false
|
||||
button.tooltip = {'redmew_settings.menu_item_tooltip_loading'}
|
||||
end
|
||||
end
|
||||
|
||||
local function player_joined(event)
|
||||
if not global.config.redmew_settings.use_remote_server then
|
||||
return
|
||||
end
|
||||
|
||||
local player = Game.get_player_by_index(event.player_index)
|
||||
if not player or not player.valid then
|
||||
return
|
||||
end
|
||||
|
||||
Server.try_get_data('player_settings', player.name, on_player_settings_get);
|
||||
end
|
||||
|
||||
local function get_element_value(element)
|
||||
if element.type == 'text-box' then
|
||||
return element.text
|
||||
end
|
||||
if element.type == 'slider' then
|
||||
return element.slider_value
|
||||
end
|
||||
if element.type == 'checkbox' then
|
||||
return element.state
|
||||
end
|
||||
end
|
||||
|
||||
local function create_input_element(frame, type, value)
|
||||
if type == 'fraction' then
|
||||
return frame.add({type = 'slider', value = value, minimum_value = 0, maximum_value = 1})
|
||||
end
|
||||
if type == 'boolean' then
|
||||
return frame.add({type = 'checkbox', state = value})
|
||||
end
|
||||
|
||||
-- ensure something is always added to prevent errors
|
||||
return frame.add({type = 'text-box', text = value})
|
||||
end
|
||||
|
||||
local function draw_main_frame(center, player)
|
||||
local settings = Settings.get_setting_metadata()
|
||||
local settings_frame = center.add({
|
||||
type = 'frame',
|
||||
name = main_frame_name,
|
||||
direction = 'vertical',
|
||||
caption = {'redmew_settings.frame_title'},
|
||||
})
|
||||
|
||||
local settings_frame_style = settings_frame.style
|
||||
settings_frame_style.width = 400
|
||||
|
||||
local scroll_pane = settings_frame.add({type = 'scroll-pane'})
|
||||
local scroll_style = scroll_pane.style
|
||||
scroll_style.maximal_height = 800
|
||||
scroll_style.minimal_height = 35 * table_size(settings)
|
||||
scroll_style.bottom_padding = 5
|
||||
scroll_style.left_padding = 5
|
||||
scroll_style.right_padding = 5
|
||||
scroll_style.top_padding = 5
|
||||
|
||||
local setting_grid = scroll_pane.add({type = 'table', column_count = 2})
|
||||
local player_index = player.index
|
||||
|
||||
local data = {}
|
||||
|
||||
for name, setting in pairs(settings) do
|
||||
local caption = name
|
||||
|
||||
if setting.localisation_key then
|
||||
caption = {setting.localisation_key}
|
||||
end
|
||||
|
||||
local label = setting_grid.add({
|
||||
type = 'label',
|
||||
caption = caption,
|
||||
})
|
||||
label.style.horizontally_stretchable = true
|
||||
|
||||
local value = Settings.get(player_index, name)
|
||||
local input = create_input_element(setting_grid, setting.type, value)
|
||||
|
||||
data[name] = {
|
||||
label = label,
|
||||
input = input,
|
||||
previous_value = value,
|
||||
}
|
||||
end
|
||||
|
||||
local bottom_flow = settings_frame.add({type = 'flow', direction = 'horizontal'})
|
||||
|
||||
local left_flow = bottom_flow.add({type = 'flow'})
|
||||
left_flow.style.horizontal_align = 'left'
|
||||
left_flow.style.horizontally_stretchable = true
|
||||
|
||||
local close_button = left_flow.add({type = 'button', name = main_button_name, caption = {'redmew_settings.button_cancel'}})
|
||||
close_button.style = 'back_button'
|
||||
|
||||
local right_flow = bottom_flow.add({type = 'flow'})
|
||||
right_flow.style.horizontal_align = 'right'
|
||||
|
||||
local save_button = right_flow.add({type = 'button', name = save_changes_button_name, caption = {'redmew_settings.button_save_changes'}})
|
||||
save_button.style = 'confirm_button'
|
||||
|
||||
Gui.set_data(save_button, data)
|
||||
|
||||
player.opened = settings_frame
|
||||
end
|
||||
|
||||
local function toggle(event)
|
||||
local player = event.player
|
||||
local center = player.gui.center
|
||||
local main_frame = center[main_frame_name]
|
||||
|
||||
if main_frame then
|
||||
Gui.destroy(main_frame)
|
||||
else
|
||||
draw_main_frame(center, player)
|
||||
end
|
||||
end
|
||||
|
||||
local function save_changes(event)
|
||||
local data = Gui.get_data(event.element)
|
||||
local player_index = event.player_index
|
||||
local player = event.player
|
||||
|
||||
local errors_count = 0
|
||||
local values = {}
|
||||
|
||||
for name, element_data in pairs(data) do
|
||||
local input = element_data.input
|
||||
local label = element_data.label
|
||||
local value = get_element_value(input)
|
||||
local validated = Settings.validate(name, value)
|
||||
|
||||
if nil ~= validated then
|
||||
errors_count = errors_count + 1
|
||||
label.style.font_color = Color.red
|
||||
label.tooltip = validated
|
||||
label.parent.tooltip = validated
|
||||
input.tooltip = validated
|
||||
input.parent.tooltip = validated
|
||||
else
|
||||
label.style.font_color = Color.white
|
||||
label.tooltip = ''
|
||||
label.parent.tooltip = ''
|
||||
input.tooltip = ''
|
||||
input.parent.tooltip = ''
|
||||
end
|
||||
values[name] = value
|
||||
end
|
||||
|
||||
if errors_count > 0 then
|
||||
return
|
||||
end
|
||||
|
||||
for name, value in pairs (values) do
|
||||
Settings.set(player_index, name, value)
|
||||
end
|
||||
|
||||
Toast.toast_player(player, 5, {'redmew_settings.save_success_toast_message'})
|
||||
|
||||
if global.config.redmew_settings.use_remote_server then
|
||||
Server.set_data('player_settings', player.name, Settings.all(player_index));
|
||||
end
|
||||
|
||||
local main_frame = player.gui.center[main_frame_name]
|
||||
|
||||
if main_frame then
|
||||
Gui.destroy(main_frame)
|
||||
end
|
||||
end
|
||||
|
||||
Gui.on_custom_close(main_frame_name, function(event)
|
||||
Gui.destroy(event.element)
|
||||
end)
|
||||
|
||||
Gui.allow_player_to_toggle_top_element_visibility(main_button_name)
|
||||
|
||||
Gui.on_click(main_button_name, toggle)
|
||||
Gui.on_click(save_changes_button_name, save_changes)
|
||||
Event.add(defines.events.on_player_created, player_created)
|
||||
Event.add(defines.events.on_player_joined_game, player_joined)
|
||||
|
||||
return Public
|
@ -13,7 +13,7 @@ local pairs = pairs
|
||||
local next = next
|
||||
|
||||
local toast_volume_name = 'toast-volume'
|
||||
Settings.register(toast_volume_name, 'fraction', 1.0)
|
||||
Settings.register(toast_volume_name, Settings.types.fraction, 1.0, 'toast.toast_volume_setting_label')
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
0
locale/en/redmew.cfg
Normal file
0
locale/en/redmew.cfg
Normal file
@ -64,6 +64,15 @@ close_caption=Close
|
||||
poke_notify_caption=Notify me when pokes happen.
|
||||
poke_notify_tooltip=Receive a message when a player pokes another player.
|
||||
|
||||
[redmew_settings]
|
||||
menu_item_tooltip=Your RedMew settings
|
||||
menu_item_tooltip_loading=Loading your personal settings...
|
||||
save_success_toast_message=Your settings have been updated!
|
||||
frame_title=Redmew Settings
|
||||
|
||||
[toast]
|
||||
toast_volume_setting_label=Toast message volume
|
||||
|
||||
[evolution_progress]
|
||||
tooltip=Alien evolution progress
|
||||
|
||||
|
@ -28,3 +28,10 @@ print_admins=__1__(ADMIN) __2__: __3__
|
||||
|
||||
[gui_util]
|
||||
button_tooltip=Shows / hides the Redmew Gui buttons.
|
||||
|
||||
[redmew_settings]
|
||||
fraction_invalid_value=fraction setting type requires the input to be a valid number between 0 and 1.
|
||||
string_invalid_value=string setting type requires the input to be either a valid string or something that can be converted to a string.
|
||||
boolean_invalid_value=boolean setting type requires the input to be either a boolean, number or string that can be transformed to a boolean.
|
||||
button_cancel=Cancel
|
||||
button_save_changes=Save changes
|
||||
|
@ -12,7 +12,7 @@ local settings_type = {
|
||||
input = tonumber(input)
|
||||
|
||||
if input == nil then
|
||||
return false, 'fraction setting type requires the input to be a valid number between 0 and 1.'
|
||||
return false, {'redmew_settings.fraction_invalid_value'}
|
||||
end
|
||||
|
||||
if input < 0 then
|
||||
@ -39,7 +39,7 @@ local settings_type = {
|
||||
return true, tostring(input)
|
||||
end
|
||||
|
||||
return false, 'string setting type requires the input to be either a valid string or something that can be converted to a string.'
|
||||
return false, {'redmew_settings.string_invalid_value'}
|
||||
end,
|
||||
boolean = function (input)
|
||||
local input_type = type(input)
|
||||
@ -63,7 +63,7 @@ local settings_type = {
|
||||
return true, input ~= 0
|
||||
end
|
||||
|
||||
return false, 'boolean setting type requires the input to be either a boolean, number or string that can be transformed to a boolean.'
|
||||
return false, {'redmew_settings.boolean_invalid_value'}
|
||||
end,
|
||||
}
|
||||
|
||||
@ -87,8 +87,8 @@ Public.types = {fraction = 'fraction', string = 'string', boolean = 'boolean'}
|
||||
---
|
||||
---@param name string
|
||||
---@param setting_type string
|
||||
---@param default mixed
|
||||
function Public.register(name, setting_type, default)
|
||||
---@param default any
|
||||
function Public.register(name, setting_type, default, localisation_key)
|
||||
if _LIFECYCLE ~= _STAGE.control then
|
||||
error(format('You can only register setting names in the control stage, i.e. not inside events. Tried setting "%s" with type "%s".', name, setting_type), 2)
|
||||
end
|
||||
@ -103,8 +103,10 @@ function Public.register(name, setting_type, default)
|
||||
end
|
||||
|
||||
local setting = {
|
||||
type = setting_type,
|
||||
default = default,
|
||||
callback = callback,
|
||||
localisation_key = localisation_key,
|
||||
}
|
||||
|
||||
settings[name] = setting
|
||||
@ -112,17 +114,35 @@ function Public.register(name, setting_type, default)
|
||||
return setting
|
||||
end
|
||||
|
||||
---Validates whether a given value is valid for a given setting.
|
||||
---@param name string
|
||||
---@param value any
|
||||
function Public.validate(name, value)
|
||||
local setting = settings[name]
|
||||
if not setting then
|
||||
return format('Setting "%s" does not exist.', name)
|
||||
end
|
||||
|
||||
local success, sanitized_value = setting.callback(value)
|
||||
|
||||
if not success then
|
||||
return sanitized_value
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---Sets a setting to a specific value for a player.
|
||||
---
|
||||
---In order to get a setting value, it has to be registered via the "register" function.
|
||||
---
|
||||
---@param player_index number
|
||||
---@param name string
|
||||
---@param value mixed
|
||||
---@param value any
|
||||
function Public.set(player_index, name, value)
|
||||
local setting = settings[name]
|
||||
if not setting then
|
||||
return error(format('Setting "%s" does not exist.', name), 2)
|
||||
error(format('Setting "%s" does not exist.', name), 2)
|
||||
end
|
||||
|
||||
local success, sanitized_value = setting.callback(value)
|
||||
@ -175,4 +195,10 @@ function Public.all(player_index)
|
||||
return output
|
||||
end
|
||||
|
||||
---Returns the full settings data, note that this is a reference, do not modify
|
||||
---this data unless you know what you're doing!
|
||||
function Public.get_setting_metadata()
|
||||
return settings
|
||||
end
|
||||
|
||||
return Public
|
||||
|
Loading…
x
Reference in New Issue
Block a user