From 8c19d674505e64f182839c1c95d69adfbf99e667 Mon Sep 17 00:00:00 2001 From: PHIDIAS Date: Sun, 29 Dec 2024 02:29:51 +0900 Subject: [PATCH] Add Tool Gui (#20) * Update _file_loader.lua * Create tool.lua * Update trains.lua * Update research.lua * Fix use of created_entity in events * Update trains.lua * Update tool.lua * Update research.lua * Update research.lua * Update tool.lua * Update research.lua * Update trains.lua * Fix waterfill locale * Fix bug with selection tools and remote view * Fix tool GUI * Update tool.lua --------- Co-authored-by: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> --- exp_legacy/module/config/_file_loader.lua | 1 + exp_legacy/module/config/expcore/roles.lua | 1 + .../module/modules/control/selection.lua | 26 +- exp_legacy/module/modules/gui/tool.lua | 262 ++++++++++++++++++ exp_scenario/module/commands/research.lua | 24 +- exp_scenario/module/commands/trains.lua | 34 ++- exp_scenario/module/commands/waterfill.lua | 10 +- 7 files changed, 328 insertions(+), 30 deletions(-) create mode 100644 exp_legacy/module/modules/gui/tool.lua diff --git a/exp_legacy/module/config/_file_loader.lua b/exp_legacy/module/config/_file_loader.lua index e7c3f98d..9e72d522 100644 --- a/exp_legacy/module/config/_file_loader.lua +++ b/exp_legacy/module/config/_file_loader.lua @@ -56,6 +56,7 @@ return { "modules.gui.research", "modules.gui.module", "modules.gui.landfill", + "modules.gui.tool", "modules.gui.production", "modules.gui.playerdata", "modules.gui.surveillance", diff --git a/exp_legacy/module/config/expcore/roles.lua b/exp_legacy/module/config/expcore/roles.lua index abd745a4..14fd9695 100644 --- a/exp_legacy/module/config/expcore/roles.lua +++ b/exp_legacy/module/config/expcore/roles.lua @@ -233,6 +233,7 @@ Roles.new_role("Member", "Mem") "gui/warp-list/edit", "gui/surveillance", "gui/vlayer-edit", + "gui/tool", "command/save-quickbar", "command/vlayer-info", "command/personal-logistic", diff --git a/exp_legacy/module/modules/control/selection.lua b/exp_legacy/module/modules/control/selection.lua index 20c709b2..5f746e36 100644 --- a/exp_legacy/module/modules/control/selection.lua +++ b/exp_legacy/module/modules/control/selection.lua @@ -31,9 +31,10 @@ Storage.register({ end) --- Let a player select an area by providing a selection planner --- @tparam LuaPlayer player The player to place into selection mode --- @tparam string selection_name The name of the selection to start, used with on_selection --- @tparam[opt=false] boolean single_use When true the selection will stop after first use +--- @param player LuaPlayer The player to place into selection mode +--- @param selection_name string The name of the selection to start, used with on_selection +--- @param single_use boolean? When true the selection will stop after first use +--- @param ... any Arguments to pass to the selection handler function Selection.start(player, selection_name, single_use, ...) if not player or not player.valid then return end if selections[player.index] then @@ -67,10 +68,15 @@ function Selection.start(player, selection_name, single_use, ...) player.clear_cursor() -- Clear the current item player.cursor_stack.set_stack(selection_tool) + -- This does not work for selection planners, will make a feature request for it + --player.cursor_stack_temporary = true + -- Make a slot to place the selection tool even if inventory is full - if not player.character then return end player.character_inventory_slots_bonus = player.character_inventory_slots_bonus + 1 - player.hand_location = { inventory = defines.inventory.character_main, slot = #player.get_main_inventory() } + local inventory = player.get_main_inventory() + if inventory then + player.hand_location = { inventory = inventory.index, slot = #inventory } + end end --- Stop a player selection by removing the selection planner @@ -150,6 +156,16 @@ Event.add(defines.events.on_player_cursor_stack_changed, function(event) if player.cursor_stack.is_selection_tool then return end Selection.stop(player) end) + +--- Make sure the hand location exists when the player returns from remote view +Event.add(defines.events.on_player_controller_changed, function(event) + local player = game.players[event.player_index] --- @cast player -nil + local inventory = player.get_main_inventory() + if player.cursor_stack.is_selection_tool and inventory then + player.hand_location = { inventory = inventory.index, slot = #inventory } + end +end) + --- Stop selection after an event such as death or leaving the game local function stop_after_event(event) local player = game.players[event.player_index] diff --git a/exp_legacy/module/modules/gui/tool.lua b/exp_legacy/module/modules/gui/tool.lua new file mode 100644 index 00000000..be36d435 --- /dev/null +++ b/exp_legacy/module/modules/gui/tool.lua @@ -0,0 +1,262 @@ +--[[-- Gui Module - Tool + @gui Tool + @alias tool_container +]] + +local ExpUtil = require("modules/exp_util") +local Gui = require("modules/exp_legacy/expcore/gui") --- @dep expcore.gui +local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles +local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event +local Selection = require("modules/exp_legacy/modules/control/selection") --- @dep modules.control.selection +local addon_train = require("modules/exp_scenario/commands/trains") +local addon_research = require("modules/exp_scenario/commands/research") + +local tool_container + +local SelectionArtyArea = "ExpCommand_Artillery" +local SelectionWaterfillArea = "ExpCommand_Waterfill" + +local style = { + label = { + width = 160 + }, + button = { + width = 80 + } +} + +--- Arty label +-- @element tool_gui_arty_l +local tool_gui_arty_l = + Gui.element{ + type = "label", + name = "tool_arty_l", + caption = { "tool.artillery" }, + tooltip = { "tool.artillery-tooltip" }, + style = "heading_2_label" + }:style( + style.label + ) + +--- Arty button +-- @element tool_gui_arty_b +local tool_gui_arty_b = + Gui.element{ + type = "button", + name = "tool_arty_b", + caption = { "tool.apply" } + }:style( + style.button + ):on_click(function(player, _, _) + if Selection.is_selecting(player, SelectionArtyArea) then + Selection.stop(player) + + else + Selection.start(player, SelectionArtyArea) + player.print{ "tool.entered-area-selection" } + end + end) + +--- Waterfill label +-- @element tool_gui_waterfill_l +local tool_gui_waterfill_l = + Gui.element{ + type = "label", + name = "tool_waterfill_l", + caption = { "tool.waterfill" }, + tooltip = { "tool.waterfill-tooltip" }, + style = "heading_2_label" + }:style( + style.label + ) + +--- Waterfill button +-- @element tool_gui_waterfill_b +local tool_gui_waterfill_b = + Gui.element{ + type = "button", + name = "tool_waterfill_b", + caption = { "tool.apply" } + }:style( + style.button + ):on_click(function(player, _, _) + if Selection.is_selecting(player, SelectionWaterfillArea) then + Selection.stop(player) + return player.print{ "exp-commands_waterfill.exit" } + elseif player.get_item_count("cliff-explosives") == 0 then + return player.print{ "exp-commands_waterfill.requires-explosives" } + else + Selection.start(player, SelectionWaterfillArea) + return player.print{ "exp-commands_waterfill.enter" } + end + end) + +--- Train label +-- @element tool_gui_train_l +local tool_gui_train_l = + Gui.element{ + type = "label", + name = "tool_train_l", + caption = { "tool.train" }, + tooltip = { "tool.train-tooltip" }, + style = "heading_2_label" + }:style( + style.label + ) + +--- Train button +-- @element tool_gui_train_b +local tool_gui_train_b = + Gui.element{ + type = "button", + name = "tool_train_b", + caption = { "tool.apply" } + }:style( + style.button + ):on_click(function(player, _, _) + addon_train.manual(player) + end) + +--- Research label +-- @element tool_gui_research_l +local tool_gui_research_l = + Gui.element{ + type = "label", + name = "tool_research_l", + caption = { "tool.research" }, + tooltip = { "tool.research-tooltip" }, + style = "heading_2_label" + }:style( + style.label + ) + +--- Research button +-- @element tool_gui_research_b +local tool_gui_research_b = + Gui.element{ + type = "button", + name = "tool_research_b", + caption = { "tool.apply" } + }:style( + style.button + ):on_click(function(player, _, _) + local enabled = addon_research.set_auto_research() + + if enabled then + addon_research.res_queue(player.force, true) + end + + local player_name = ExpUtil.format_player_name_locale(player) + game.print{ "exp-commands_research.auto-research", player_name, enabled } + end) + +--- Spawn label +-- @element tool_gui_spawn_l +local tool_gui_spawn_l = + Gui.element{ + type = "label", + name = "tool_spawn_l", + caption = { "tool.spawn" }, + tooltip = { "tool.spawn-tooltip" }, + style = "heading_2_label" + }:style( + style.label + ) + +--- Spawn button +-- @element tool_gui_spawn_b +local tool_gui_spawn_b = + Gui.element{ + type = "button", + name = "tool_spawn_b", + caption = { "tool.apply" } + }:style( + style.button + ):on_click(function(player, _, _) + if not player.character + or player.character.health <= 0 + or not ExpUtil.teleport_player(player, game.surfaces.nauvis, { 0, 0 }, "dismount") then + return player.print{ "exp-commands_teleport.unavailable" } + end + end) + +local function tool_perm(player) + local frame = Gui.get_left_element(player, tool_container) + local disp = frame.container["tool_st"].disp.table + local allowed + + allowed = Roles.player_allowed(player, "command/artillery") + disp[tool_gui_arty_l.name].visible = allowed + disp[tool_gui_arty_b.name].visible = allowed + + allowed = Roles.player_allowed(player, "command/waterfill") + disp[tool_gui_waterfill_l.name].visible = allowed + disp[tool_gui_waterfill_b.name].visible = allowed + + allowed = Roles.player_allowed(player, "command/set-trains-to-automatic") + disp[tool_gui_train_l.name].visible = allowed + disp[tool_gui_train_b.name].visible = allowed + + allowed = Roles.player_allowed(player, "command/set-auto-research") + disp[tool_gui_research_l.name].visible = allowed + disp[tool_gui_research_b.name].visible = allowed + + allowed = Roles.player_allowed(player, "command/spawn") + disp[tool_gui_spawn_l.name].visible = allowed + disp[tool_gui_spawn_b.name].visible = allowed +end + +--- A vertical flow containing all the tool +-- @element tool_set +local tool_set = + Gui.element(function(_, parent, name) + local tool_set = parent.add{ type = "flow", direction = "vertical", name = name } + local disp = Gui.scroll_table(tool_set, 240, 2, "disp") + + tool_gui_arty_l(disp) + tool_gui_arty_b(disp) + + tool_gui_waterfill_l(disp) + tool_gui_waterfill_b(disp) + + tool_gui_train_l(disp) + tool_gui_train_b(disp) + + tool_gui_research_l(disp) + tool_gui_research_b(disp) + + tool_gui_spawn_l(disp) + tool_gui_spawn_b(disp) + + return tool_set + end) + +--- The main container for the tool gui +-- @element tool_container +tool_container = + Gui.element(function(definition, parent) + local player = Gui.get_player_from_element(parent) + local container = Gui.container(parent, definition.name, 240) + + tool_set(container, "tool_st") + + tool_perm(player) + + return container.parent + end) + :static_name(Gui.unique_static_name) + :add_to_left_flow() + +--- Button on the top flow used to toggle the tool container +-- @element toggle_left_element +Gui.left_toolbar_button("item/repair-pack", { "tool.main-tooltip" }, tool_container, function(player) + return Roles.player_allowed(player, "gui/tool") +end) + +Event.add(Roles.events.on_role_assigned, function(event) + tool_perm(game.players[event.player_index]) +end) + +Event.add(Roles.events.on_role_unassigned, function(event) + tool_perm(game.players[event.player_index]) +end) diff --git a/exp_scenario/module/commands/research.lua b/exp_scenario/module/commands/research.lua index 4a8a0e40..d6673193 100644 --- a/exp_scenario/module/commands/research.lua +++ b/exp_scenario/module/commands/research.lua @@ -36,24 +36,34 @@ function module.res_queue(force, silent) end end +--- @param state boolean? use nil to toggle current state +--- @return boolean # New auto research state +function module.set_auto_research(state) + local new_state + if state == nil then + new_state = not research.res_queue_enable + else + new_state = state ~= false + end + + research.res_queue_enable = new_state + return new_state +end + --- Sets the auto research state Commands.new("set-auto-research", { "exp-commands_research.description" }) :optional("state", { "exp-commands_research.arg-state" }, Commands.types.boolean) :add_aliases{ "auto-research" } :register(function(player, state) --- @cast state boolean? - if state == nil then - research.res_queue_enable = not research.res_queue_enable - else - research.res_queue_enable = state - end + local enabled = module.set_auto_research(state) - if research.res_queue_enable then + if enabled then module.res_queue(player.force --[[@as LuaForce]], true) end local player_name = format_player_name(player) - game.print{ "exp-commands_research.auto-research", player_name, research.res_queue_enable } + game.print{ "exp-commands_research.auto-research", player_name, enabled } end) --- @param event EventData.on_research_finished diff --git a/exp_scenario/module/commands/trains.lua b/exp_scenario/module/commands/trains.lua index a0f76430..0df7b2c7 100644 --- a/exp_scenario/module/commands/trains.lua +++ b/exp_scenario/module/commands/trains.lua @@ -4,9 +4,26 @@ Adds a command that set all train back to automatic local Commands = require("modules/exp_commands") local format_player_name = Commands.format_player_name_locale - local format_number = require("util").format_number +--- @class Command.Trains +local module = {} + +function module.manual(player, surface, force) + local trains = game.train_manager.get_trains{ + has_passenger = false, + is_manual = true, + surface = surface, + force = force, + } + + for _, train in ipairs(trains) do + train.manual_mode = false + end + + game.print{ "exp-commands_trains.response", format_player_name(player), format_number(#trains, false) } +end + --- Set all trains to automatic Commands.new("set-trains-to-automatic", { "exp-commands_trains.description" }) :optional("surface", { "exp-commands_trains.arg-surface" }, Commands.types.surface) @@ -14,16 +31,7 @@ Commands.new("set-trains-to-automatic", { "exp-commands_trains.description" }) :register(function(player, surface, force) --- @cast surface LuaSurface? --- @cast force LuaForce? - local trains = game.train_manager.get_trains{ - has_passenger = false, - is_manual = true, - surface = surface, - force = force, - } - - for _, train in ipairs(trains) do - train.manual_mode = false - end - - game.print{ "exp-commands_trains.response", format_player_name(player), format_number(#trains, false) } + module.manual(player, surface, force) end) + +return module diff --git a/exp_scenario/module/commands/waterfill.lua b/exp_scenario/module/commands/waterfill.lua index 4fe3cb8f..d748356f 100644 --- a/exp_scenario/module/commands/waterfill.lua +++ b/exp_scenario/module/commands/waterfill.lua @@ -29,19 +29,19 @@ Selection.on_selection(SelectionName, function(event) local surface = event.surface if surface.planet and surface.planet ~= game.planets.nauvis then - player.print({ "exp-cods_waterfill.nauvis-only" }, Commands.print_settings.error) + player.print({ "exp-commands_waterfill.nauvis-only" }, Commands.print_settings.error) return end local area_size = (area.right_bottom.x - area.left_top.x) * (area.right_bottom.y - area.left_top.y) if area_size > 1000 then - player.print({ "exp-cods_waterfill.area-too-large", 1000, area_size }, Commands.print_settings.error) + player.print({ "exp-commands_waterfill.area-too-large", 1000, area_size }, Commands.print_settings.error) return end local item_count = player.get_item_count("cliff-explosives") if item_count < area_size then - player.print({ "exp-cods_waterfill.too-few-explosives", area_size, item_count }, Commands.print_settings.error) + player.print({ "exp-commands_waterfill.too-few-explosives", area_size, item_count }, Commands.print_settings.error) return end @@ -62,8 +62,8 @@ Selection.on_selection(SelectionName, function(event) player.remove_item{ name = "cliff-explosives", count = tile_count - remaining_tiles } if remaining_tiles > 0 then - player.print({ "exp-cods_waterfill.part-complete", tile_count, remaining_tiles }, Commands.print_settings.default) + player.print({ "exp-commands_waterfill.part-complete", tile_count, remaining_tiles }, Commands.print_settings.default) else - player.print({ "exp-cods_waterfill.complete", tile_count }, Commands.print_settings.default) + player.print({ "exp-commands_waterfill.complete", tile_count }, Commands.print_settings.default) end end)