From b768b875467c7cb7f5a1f1b298cd01870ce8f73b Mon Sep 17 00:00:00 2001 From: grilledham Date: Wed, 19 Jun 2019 17:36:18 +0100 Subject: [PATCH] autofill --- config.lua | 4 + control.lua | 3 + features/autofill.lua | 146 +++++++++++++++++++++++++ features/gui/autofill.lua | 195 ++++++++++++++++++++++++++++++++++ locale/en/redmew_features.cfg | 11 ++ 5 files changed, 359 insertions(+) create mode 100644 features/autofill.lua create mode 100644 features/gui/autofill.lua diff --git a/config.lua b/config.lua index 466bca3c..2ab7d663 100644 --- a/config.lua +++ b/config.lua @@ -98,6 +98,10 @@ global.config = { paint = { enabled = true }, + -- autofill turrets with ammo + autofill = { + enabled = true + }, -- adds a market market = { enabled = true, diff --git a/control.lua b/control.lua index 2a207d52..dd0ca4b4 100644 --- a/control.lua +++ b/control.lua @@ -103,6 +103,9 @@ end if config.turret_active_delay.enabled then require 'features.turret_active_delay' end +if config.autofill then + require 'features.gui.autofill' +end -- GUIs -- The order determines the order they appear from left to right. diff --git a/features/autofill.lua b/features/autofill.lua new file mode 100644 index 00000000..04222a4b --- /dev/null +++ b/features/autofill.lua @@ -0,0 +1,146 @@ +local Event = require 'utils.event' +local Global = require 'utils.global' +local Settings = require 'utils.redmew_settings' +local pairs = pairs +local settings_get = Settings.get +local settings_set = Settings.set +local settings_validate = Settings.validate + +local enable_autofill_name = 'autofill.enabled' +local ammo_count_name = 'autofill.ammo_count' + +Settings.register(enable_autofill_name, Settings.types.boolean, true, 'autofill.enable') +Settings.register(ammo_count_name, Settings.types.positive_integer, 10, 'autofill.ammo_count') + +local Public = {} + +local ammo_locales = { + ['uranium-rounds-magazine'] = {'item-name.uranium-rounds-magazine'}, + ['piercing-rounds-magazine'] = {'item-name.piercing-rounds-magazine'}, + ['firearm-magazine'] = {'item-name.firearm-magazine'} +} +Public.ammo_locales = ammo_locales + +local player_ammos = {} -- player_index -> dict of name -> bool + +Global.register( + player_ammos, + function(tbl) + player_ammos = tbl + end +) + +local default_ammos = { + ['uranium-rounds-magazine'] = true, + ['piercing-rounds-magazine'] = true, + ['firearm-magazine'] = true +} + +local function copy(tbl) + local result = {} + + for k, v in pairs(tbl) do + result[k] = v + end + + return result +end + +function Public.get_player_ammos(player_index) + return player_ammos[player_index] or default_ammos +end +local get_player_ammos = Public.get_player_ammos + +function Public.set_player_ammo(player_index, name, value) + local pa = player_ammos[player_index] or copy(default_ammos) + + pa[name] = value + + player_ammos[player_index] = pa +end + +local function entity_built(event) + local entity = event.created_entity + + if not entity.valid then + return + end + + if entity.type ~= 'ammo-turret' then + return + end + + local player_index = event.player_index + local player = game.get_player(player_index) + if not player or not player.valid then + return + end + + local enabled = settings_get(player_index, enable_autofill_name) + if not enabled then + return + end + + local inventory = player.get_main_inventory() + if not inventory or not inventory.valid then + return + end + + local stack = {name = nil, count = settings_get(player_index, ammo_count_name)} + + for name, enabled in pairs(get_player_ammos(player_index)) do + if not enabled then + goto continue + end + + stack.name = name + local removed = inventory.remove(stack) + + if removed > 0 then + stack.count = removed + entity.insert(stack) + + local remaining_count = inventory.get_item_count(name) + + player.surface.create_entity( + { + name = 'flying-text', + position = entity.position, + text = {'autofill.insert_item', removed, ammo_locales[name], remaining_count} + } + ) + + break + end + + ::continue:: + end +end + +Event.add(defines.events.on_built_entity, entity_built) + +function Public.get_enabled(player_index) + return settings_get(player_index, enable_autofill_name) +end + +function Public.set_enabled(player_index, value) + Settings_set(player_index, enable_autofill_name, value) +end + +function Public.get_ammo_count(player_index) + return settings_get(player_index, ammo_count_name) +end + +function Public.set_ammo_count(player_index, value) + if settings_validate(ammo_count_name, value) == nil then + settings_set(player_index, ammo_count_name, value) + return true + else + return false + end +end + +Public.enable_autofill_name = enable_autofill_name +Public.ammo_count_name = ammo_count_name + +return Public diff --git a/features/gui/autofill.lua b/features/gui/autofill.lua new file mode 100644 index 00000000..3bae0794 --- /dev/null +++ b/features/gui/autofill.lua @@ -0,0 +1,195 @@ +local Autofill = require 'features.autofill' +local Gui = require 'utils.gui' +local Event = require 'utils.event' +local Settings = require 'utils.redmew_settings' +local Color = require 'resources.color_presets' + +local enabled_style = 'green_slot_button' +local disabled_style = 'red_slot_button' + +local style_map = {[true] = enabled_style, [false] = disabled_style} +local enabled_locale_map = {[true] = {'autofill.enabled'}, [false] = {'autofill.disabled'}} + +local main_button_name = Gui.uid_name() +local main_frame_name = Gui.uid_name() +local enabled_checkbox_name = Gui.uid_name() +local ammo_count_name = Gui.uid_name() +local enabled_ammo_button = Gui.uid_name() + +local function player_created(event) + local player = game.get_player(event.player_index) + + if not player or not player.valid then + return + end + + player.gui.top.add { + type = 'sprite-button', + name = main_button_name, + sprite = 'item/piercing-rounds-magazine', + tooltip = {'autofill.main_button_tooltip'} + } +end + +local function update_ammo_button(button, name, enabled) + local locale_name = Autofill.ammo_locales[name] + local style = style_map[enabled] + local tooltip = {'', locale_name, ' ', enabled_locale_map[enabled]} + + button.style = style + button.tooltip = tooltip +end + +local function toggle_main_frame(event) + local player = event.player + local player_index = player.index + local left = player.gui.left + + local frame = left[main_frame_name] + if frame then + Gui.destroy(frame) + else + frame = + left.add {type = 'frame', name = main_frame_name, caption = {'autofill.frame_name'}, direction = 'vertical'} + + local enabled_checkbox = + frame.add { + type = 'checkbox', + name = enabled_checkbox_name, + caption = {'autofill.enable'}, + state = Autofill.get_enabled(player_index) + } + + local ammo_count_flow = frame.add {type = 'flow', direction = 'horizontal'} + local ammo_count_label = ammo_count_flow.add {type = 'label', caption = {'autofill.ammo_count'}} + local ammo_count_textfield = + ammo_count_flow.add { + type = 'textfield', + name = ammo_count_name, + text = Autofill.get_ammo_count(player_index) + } + + local enabled_ammos_flow = frame.add {type = 'flow', direction = 'horizontal'} + enabled_ammos_flow.add {type = 'label', caption = {'autofill.enabled_ammos'}} + + for name, enabled in pairs(Autofill.get_player_ammos(player_index)) do + local button = + enabled_ammos_flow.add({type = 'flow'}).add( + { + type = 'sprite-button', + name = enabled_ammo_button, + sprite = 'item/' .. name + } + ) + update_ammo_button(button, name, enabled) + + Gui.set_data(button, name) + end + + local close_button = frame.add {type = 'button', name = main_button_name, caption = 'Close'} + + local data = { + enabled_checkbox = enabled_checkbox, + ammo_count_label = ammo_count_label, + ammo_count_textfield = ammo_count_textfield + } + + Gui.set_data(frame, data) + Gui.set_data(ammo_count_textfield, data) + end +end + +local function enabled_checkbox_changed(event) + Autofill.set_enabled(event.player_index, event.element.state) +end + +local function set_ammo_count_elements_validation(textfield, label, valid) + local color, label_color, tooltip + if valid then + color = Color.black + label_color = Color.white + tooltip = '' + else + color = Color.red + label_color = Color.red + tooltip = {'autofill.invalid_ammo_count'} + end + + textfield.style.font_color = color + label.style.font_color = label_color + textfield.tooltip = tooltip + label.tooltip = tooltip +end + +local function ammo_count_changed(event) + local element = event.element + local data = Gui.get_data(element) + local ammo_count_label = data.ammo_count_label + + local color, label_color, tooltip + + local valid = Autofill.set_ammo_count(event.player_index, element.text) + set_ammo_count_elements_validation(element, ammo_count_label, valid) +end + +local function enabled_ammos_changed(event) + local player_index = event.player_index + local element = event.element + local name = Gui.get_data(element) + + local ammos = Autofill.get_player_ammos(player_index) + local enabled = not ammos[name] + Autofill.set_player_ammo(player_index, name, enabled) + + update_ammo_button(element, name, enabled) +end + +local function settings_changed(event) + local settings_name = event.setting_name + + if setting_name == Autofill.enable_autofill_name then + local player_index = event.player_index + local player = game.get_player(player_index) + if not player or not player.valid then + return + end + + local frame = player.gui.left[main_frame_name] + if not frame then + return + end + + local data = Gui.get_data(frame) + local checkbox = data.enabled_checkbox + + checkbox.state = event.new_value + elseif settings_name == Autofill.ammo_count_name then + local player_index = event.player_index + local player = game.get_player(player_index) + if not player or not player.valid then + return + end + + local frame = player.gui.left[main_frame_name] + if not frame then + return + end + + local data = Gui.get_data(frame) + local ammo_count_label = data.ammo_count_label + local ammo_count_textfield = data.ammo_count_textfield + + ammo_count_textfield.text = event.new_value + set_ammo_count_elements_validation(ammo_count_textfield, ammo_count_label, true) + end +end + +Gui.allow_player_to_toggle_top_element_visibility(main_button_name) + +Gui.on_checked_state_changed(enabled_checkbox_name, enabled_checkbox_changed) +Gui.on_text_changed(ammo_count_name, ammo_count_changed) +Gui.on_click(enabled_ammo_button, enabled_ammos_changed) +Gui.on_click(main_button_name, toggle_main_frame) + +Event.add(Settings.events.on_setting_set, settings_changed) +Event.add(defines.events.on_player_created, player_created) diff --git a/locale/en/redmew_features.cfg b/locale/en/redmew_features.cfg index f674dcd4..21a6784c 100644 --- a/locale/en/redmew_features.cfg +++ b/locale/en/redmew_features.cfg @@ -146,3 +146,14 @@ player_items_crafted=Player items crafted player_distance_walked=Distance walked satellites_launched=Satellites launched unknown_death_cause=Unknown + +[autofill] +insert_item=-__1__ __2__ (__3__) +enable=enable autofill +enabled_ammos=enabled ammo types +enabled=enabled +disabled=disabled +ammo_count=autofill ammo count +invalid_ammo_count=ammo count must be a positive integer +main_button_tooltip=Autofill settings +frame_name=Autofill