From effdb97387a9894293c0c68ea68f3332c81042f0 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 00:26:24 +0100 Subject: [PATCH 01/14] Added selection control --- modules/control/protection.lua | 62 ++++++++++++++++++++ modules/control/selection.lua | 101 +++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 modules/control/protection.lua create mode 100644 modules/control/selection.lua diff --git a/modules/control/protection.lua b/modules/control/protection.lua new file mode 100644 index 00000000..5fce23db --- /dev/null +++ b/modules/control/protection.lua @@ -0,0 +1,62 @@ +--[[-- Control Module - Protection + - Controls protected entities + @control Protection + @alias Protection +]] + +local Global = require 'utils.global' --- @dep utils.global +local Event = require 'utils.event' --- @dep utils.event +local EntityProtection = {} + +----- Global Variables ----- +--- Variables stored in the global table + +local protected_entities = {} -- All entities which are protected +local protected_areas = {} -- All areas which are protected +local repeats = {} -- Stores repeat removals by players + +Global.register({ + protected_entities = protected_entities, + protected_areas = protected_areas, + repeats = repeats +}, function(tbl) + protected_entities = tbl.protected_entities + protected_areas = tbl.protected_areas + repeats = tbl.repeats +end) + +----- Local Functions ----- +--- Functions used internally to search and add to the protected array + + +----- Public Functions ----- +--- Functions used to add and remove protected entities + +--- Add an entity to the protected list +function EntityProtection.add_entity(entity) + +end + +--- Remove an entity from the protected list +function EntityProtection.remove_entity(entity) + +end + +--- Add an area to the protected list +function EntityProtection.add_area(area) + +end + +--- Remove an area from the protected list +function EntityProtection.remove_area(area) + +end + +----- Events ----- +--- All events registered by this module + +Event.add(defines.events.on_player_mined_item, function(event) + +end) + +return EntityProtection \ No newline at end of file diff --git a/modules/control/selection.lua b/modules/control/selection.lua new file mode 100644 index 00000000..4b966332 --- /dev/null +++ b/modules/control/selection.lua @@ -0,0 +1,101 @@ +--[[-- Control Module - Selection + - Controls players who have a selection planner, mostly event handlers + @control Selection + @alias Selection +]] + +local Event = require 'utils.event' --- @dep utils.event +local Global = require 'utils.global' --- @dep utils.global +local Selection = {} + +local selection_tool = { name='selection-tool' } + +local selections = {} +Global.register({ + selections = selections +}, function(tbl) + selections = tbl.selections +end) + +--- Let a player select an area by providing a selection planner +function Selection.start(player, single_use, ...) + game.print('Start selection') + -- Assign the arguments if the player is valid + if not player or not player.valid then return end + game.print('Valid Player') + selections[player.index] = { + arguments = { ... }, + single_use = single_use == true, + character = player.character + } + + -- Give a selection tool if one is not in use + if player.cursor_stack.is_selection_tool then return end + game.print('Give item') + player.clear_cursor() -- Clear the current item + player.cursor_stack.set_stack(selection_tool) + + -- Make a slot to place the selection tool even if inventory is full + if not player.character then return end + game.print('Give slot') + player.character_inventory_slots_bonus = player.character_inventory_slots_bonus + 1 + player.hand_location = { inventory = defines.inventory.character_main, slot = #player.get_main_inventory() } +end + +--- Stop a player selection by removing the selection planner +function Selection.stop(player) + if not selections[player.index] then return end + local character = selections[player.index].character + selections[player.index] = nil + + -- Remove the selection tool + if player.cursor_stack.is_selection_tool then + player.cursor_stack.clear() + else + player.remove_item(selection_tool) + end + + -- Remove the extra slot + if character and character == player.character then + player.character_inventory_slots_bonus = player.character_inventory_slots_bonus - 1 + player.hand_location = nil + end +end + +--- Alias to Event.add(defines.events.on_player_selected_area) +function Selection.on_selection(handler) + return Event.add(defines.events.on_player_selected_area, handler) +end + +--- Alias to Event.add(defines.events.on_player_alt_selected_area) +function Selection.on_alt_selection(handler) + return Event.add(defines.events.on_player_alt_selected_area, handler) +end + +--- Stop selection after an event such as death or leaving the game +local function stop_after_event(event) + local player = game.get_player(event.player_index) + Selection.stop(player) +end + +Event.add(defines.events.on_pre_player_left_game, stop_after_event) +Event.add(defines.events.on_pre_player_died, stop_after_event) + +--- Stop selection if the selection tool is removed from the cursor +Event.add(defines.events.on_player_cursor_stack_changed, function(event) + local player = game.get_player(event.player_index) + if player.cursor_stack.is_selection_tool then return end + Selection.stop(player) +end) + +--- Stop selection after a single use if the option was used +local function stop_after_use(event) + if not selections[event.player_index] then return end + if not selections[event.player_index].single_use then return end + stop_after_event(event) +end + +Event.add(defines.events.on_player_selected_area, stop_after_use) +Event.add(defines.events.on_player_alt_selected_area, stop_after_use) + +return Selection \ No newline at end of file From e9ec57225b204ca0cdbaa2bdce9ca3e86d56a418 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 00:28:19 +0100 Subject: [PATCH 02/14] Added Selection.get_arguments --- modules/control/selection.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/control/selection.lua b/modules/control/selection.lua index 4b966332..cc9b44d3 100644 --- a/modules/control/selection.lua +++ b/modules/control/selection.lua @@ -62,6 +62,12 @@ function Selection.stop(player) end end +--- Get the selection arguments for a player +function Selection.get_arguments(player) + if not selections[player.index] then return end + return selections[player.index].arguments +end + --- Alias to Event.add(defines.events.on_player_selected_area) function Selection.on_selection(handler) return Event.add(defines.events.on_player_selected_area, handler) From f195635dc3cb7cdc08f2638ea32a2a6b4c4da760 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 00:38:26 +0100 Subject: [PATCH 03/14] Added selection name filtering --- modules/control/selection.lua | 39 +++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/modules/control/selection.lua b/modules/control/selection.lua index cc9b44d3..7ccb4e8f 100644 --- a/modules/control/selection.lua +++ b/modules/control/selection.lua @@ -18,12 +18,13 @@ Global.register({ end) --- Let a player select an area by providing a selection planner -function Selection.start(player, single_use, ...) +function Selection.start(player, selection_name, single_use, ...) game.print('Start selection') -- Assign the arguments if the player is valid if not player or not player.valid then return end game.print('Valid Player') selections[player.index] = { + name = selection_name, arguments = { ... }, single_use = single_use == true, character = player.character @@ -68,16 +69,32 @@ function Selection.get_arguments(player) return selections[player.index].arguments end ---- Alias to Event.add(defines.events.on_player_selected_area) -function Selection.on_selection(handler) - return Event.add(defines.events.on_player_selected_area, handler) +--- Filter on_player_selected_area to this custom selection, pretends with player and appends with selection arguments +function Selection.on_selection(selection_name, handler) + return Event.add(defines.events.on_player_selected_area, function(event) + local selection = selections[event.player_index] + if not selection or selection.name ~= selection_name then return end + local player = game.get_player(event.player_index) + handler(player, event, unpack(selection.arguments)) + end) end ---- Alias to Event.add(defines.events.on_player_alt_selected_area) -function Selection.on_alt_selection(handler) - return Event.add(defines.events.on_player_alt_selected_area, handler) +--- Filter on_player_alt_selected_area to this custom selection, pretends with player and appends with selection arguments +function Selection.on_alt_selection(selection_name, handler) + return Event.add(defines.events.on_player_alt_selected_area, function(event) + local selection = selections[event.player_index] + if not selection or selection.name ~= selection_name then return end + local player = game.get_player(event.player_index) + handler(player, event, unpack(selection.arguments)) + end) end +--- Stop selection if the selection tool is removed from the cursor +Event.add(defines.events.on_player_cursor_stack_changed, function(event) + local player = game.get_player(event.player_index) + if player.cursor_stack.is_selection_tool then return end + Selection.stop(player) +end) --- Stop selection after an event such as death or leaving the game local function stop_after_event(event) local player = game.get_player(event.player_index) @@ -86,14 +103,6 @@ end Event.add(defines.events.on_pre_player_left_game, stop_after_event) Event.add(defines.events.on_pre_player_died, stop_after_event) - ---- Stop selection if the selection tool is removed from the cursor -Event.add(defines.events.on_player_cursor_stack_changed, function(event) - local player = game.get_player(event.player_index) - if player.cursor_stack.is_selection_tool then return end - Selection.stop(player) -end) - --- Stop selection after a single use if the option was used local function stop_after_use(event) if not selections[event.player_index] then return end From 43cb24f39654a8bb62304adf4cfc0693a2bf6f28 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 01:43:58 +0100 Subject: [PATCH 04/14] Added protection control --- config/protection.lua | 19 +++++ modules/control/protection.lua | 146 +++++++++++++++++++++++++++++++-- 2 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 config/protection.lua diff --git a/config/protection.lua b/config/protection.lua new file mode 100644 index 00000000..74281985 --- /dev/null +++ b/config/protection.lua @@ -0,0 +1,19 @@ +return { + ignore_admins = true, --- @setting ignore_admins If admins are ignored by the protection filter + ignore_role = 'Regular', --- @setting ignore_role This role will be ignored by the protection filter, leave nil if expcore.roles is not used + repeat_count = 5, --- @setting repeat_count Number of protected entities to be removed to count as repeated + repeat_lifetime = 3600*20, --- @setting repeat_lifetime How old repeats must be before being removed + refresh_rate = 3600*5, --- @setting refresh_rate How often old repeats will be removed + always_protected_names = { --- @setting always_protected_names Names of entities which are always protected + + }, + always_protected_types = { --- @setting always_protected_types Types of entities which are always protected + 'boiler', 'generator', 'offshore-pump', 'power-switch', 'reactor', 'rocket-silo' + }, + skip_repeat_names = { --- @setting skip_repeat_names Names of entities which always trigger protection repeated + + }, + skip_repeat_types = { --- @setting skip_repeat_types Types of entities which trigger protection repeated + 'reactor', 'rocket-silo' + } +} \ No newline at end of file diff --git a/modules/control/protection.lua b/modules/control/protection.lua index 5fce23db..dbb22b21 100644 --- a/modules/control/protection.lua +++ b/modules/control/protection.lua @@ -6,7 +6,39 @@ local Global = require 'utils.global' --- @dep utils.global local Event = require 'utils.event' --- @dep utils.event -local EntityProtection = {} +local config = require 'config.protection' --- @dep config.protection +local EntityProtection = { + events = { + --- When a player mines a protected entity + -- @event on_player_mined_protected + -- @tparam number player_index the player index of the player who got mined the entity + -- @tparam LuaEntity entity the entity which was mined + on_player_mined_protected = script.generate_event_name(), + --- When a player mines a many protected entities + -- @event on_repeat_violation + -- @tparam number player_index the player index of the player who got mined the entities + -- @tparam LuaEntity entity the last entity which was mined + on_repeat_violation = script.generate_event_name(), + } +} + +-- convert config tables into lookup tables +for _, config_key in ipairs{'always_protected_names', 'always_protected_types', 'skip_repeat_names', 'skip_repeat_types'} do + local tbl = config[config_key] + for key, value in ipairs(tbl) do + tbl[key] = nil + tbl[value] = true + end +end + +-- convert ignore role if present +if config.ignore_role then + local Roles = require 'expcore.roles' + local role = Roles.get_role_by_name(config.ignore_role) + config.ignore_role = function(player) + return Roles.player_has_role(player, role) + end +end ----- Global Variables ----- --- Variables stored in the global table @@ -28,35 +60,135 @@ end) ----- Local Functions ----- --- Functions used internally to search and add to the protected array +--- Get the key used in protected_entities +local function get_entity_key(entity) + return string.format('%i,%i', entity.position.x, entity.position.y) +end + +--- Get the key used in protected_areas +local function get_area_key(area) + return string.format('%i,%i', area.left_top.x, area.left_top.y) +end + +--- Check if an entity is always protected +local function check_always_protected(entity) + return config.always_protected_names[entity.name] or config.always_protected_types[entity.type] or false +end + +--- Check if an entity skips repeated +local function check_skip_repeat(entity) + return config.skip_repeat_names[entity.name] or config.skip_repeat_types[entity.type] or false +end ----- Public Functions ----- --- Functions used to add and remove protected entities --- Add an entity to the protected list function EntityProtection.add_entity(entity) - + local entities = protected_entities[entity.surface.index] + if not entities then + entities = {} + protected_entities[entity.surface.index] = entities + end + entities[get_entity_key(entity)] = entity end --- Remove an entity from the protected list function EntityProtection.remove_entity(entity) + local entities = protected_entities[entity.surface.index] + if not entities then return end + entities[get_entity_key(entity)] = nil +end +--- Get all protected entities on a surface +function EntityProtection.get_entities(surface) + return protected_entities[surface.index] +end + +--- Check if an entity is protected +function EntityProtection.is_entity_protected(entity) + local entities = protected_entities[entity.surface.index] + if not entities then return false end + return entities[get_entity_key(entity)] == entity end --- Add an area to the protected list -function EntityProtection.add_area(area) - +function EntityProtection.add_area(surface, area) + local areas = protected_areas[surface.index] + if not areas then + areas = {} + protected_areas[surface.index] = areas + end + areas[get_area_key(area)] = area end --- Remove an area from the protected list -function EntityProtection.remove_area(area) +function EntityProtection.remove_area(surface, area) + local areas = protected_areas[surface.index] + if not areas then return end + areas[get_area_key(area)] = nil +end +--- Get all protected areas on a surface +function EntityProtection.get_areas(surface) + return protected_areas[surface.index] +end + +--- Check if an entity is protected +function EntityProtection.is_position_protected(surface, position) + local areas = protected_areas[surface.index] + if not areas then return false end + for _, area in pairs(areas) do + if area.left_top.x <= position.x and area.left_top.y <= position.y + and area.right_bottom.x >= position.x and area.right_bottom.y >= position.y + then + return true + end + end + return false end ----- Events ----- --- All events registered by this module -Event.add(defines.events.on_player_mined_item, function(event) - +--- Raise events for protected entities +Event.add(defines.events.on_pre_player_mined_item, function(event) + local entity = event.entity + local player = game.get_player(event.player_index) + -- Check if the player should be ignored + if config.ignore_admins and player.admin then return end + if config.ignore_role and config.ignore_role(player) then return end + + -- Check if the entity is protected + if check_always_protected(entity) or EntityProtection.is_entity_protected(entity) + or EntityProtection.is_position_protected(entity.surface, entity.position) + then + -- Update repeats + local player_repeats = repeats[player.name] + if not player_repeats then + player_repeats = { last = game.tick, count = 0 } + repeats[player.name] = player_repeats + end + player_repeats.last = game.tick + player_repeats.count = player_repeats.count + 1 + -- Send events + event.name = EntityProtection.events.on_player_mined_protected + script.raise_event(EntityProtection.events.on_player_mined_protected, event) + if check_skip_repeat(entity) or player_repeats.count >= config.repeat_count then + event.name = EntityProtection.events.on_repeat_violation + script.raise_event(EntityProtection.events.on_repeat_violation, event) + end + end +end) + +--- Remove old repeats +Event.on_nth_tick(config.refresh_rate, function() + local old = game.tick - config.repeat_lifetime + for player_name, player_repeats in pairs(repeats) do + if player_repeats.last <= old then + repeats[player_name] = nil + end + end end) return EntityProtection \ No newline at end of file From cdded68ffb760d29d8c671100370b94c1cab7917 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 01:47:43 +0100 Subject: [PATCH 05/14] Added discord alert --- config/discord_alerts.lua | 1 + modules/addons/discord-alerts.lua | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/config/discord_alerts.lua b/config/discord_alerts.lua index 1890aa4b..be3bceca 100644 --- a/config/discord_alerts.lua +++ b/config/discord_alerts.lua @@ -2,6 +2,7 @@ -- @config Discord-Alerts return { + entity_protection=true, player_reports=true, player_warnings=true, player_bans=true, diff --git a/modules/addons/discord-alerts.lua b/modules/addons/discord-alerts.lua index fbeabf8a..fe13ec5c 100644 --- a/modules/addons/discord-alerts.lua +++ b/modules/addons/discord-alerts.lua @@ -76,6 +76,21 @@ local function emit_event(args) }) end +--- Repeat protected entity mining +if config.entity_protection then + local EntityProtection = require 'modules.control.protection' --- @dep modules.control.protection + Event.add(EntityProtection.events.on_repeat_violation, function(event) + local player_name = get_player_name(event) + emit_event{ + title='Entity Protection', + description='A player removed protected entities', + color=Colors.yellow, + ['Player']=''..player_name, + ['Entity']=''..event.entity.name + } + end) +end + --- Reports added and removed if config.player_reports then local Reports = require 'modules.control.reports' --- @dep modules.control.reports From 7fb1a14cb3935cabf99d86bb169944d8d8659da4 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 01:53:05 +0100 Subject: [PATCH 06/14] Changed ignore_role to ignore_permission --- config/expcore/roles.lua | 3 ++- config/protection.lua | 2 +- modules/control/protection.lua | 11 ++++------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/config/expcore/roles.lua b/config/expcore/roles.lua index 9b826202..46cd7072 100644 --- a/config/expcore/roles.lua +++ b/config/expcore/roles.lua @@ -210,7 +210,8 @@ Roles.new_role('Regular','Reg') 'command/rainbow', 'command/go-to-spawn', 'command/me', - 'standard-decon' + 'standard-decon', + 'bypass-entity-protection' } :set_auto_assign_condition(function(player) if player.online_time >= hours3 then diff --git a/config/protection.lua b/config/protection.lua index 74281985..fbba783d 100644 --- a/config/protection.lua +++ b/config/protection.lua @@ -1,6 +1,6 @@ return { ignore_admins = true, --- @setting ignore_admins If admins are ignored by the protection filter - ignore_role = 'Regular', --- @setting ignore_role This role will be ignored by the protection filter, leave nil if expcore.roles is not used + ignore_permission = 'bypass-entity-protection', --- @setting ignore_permission Players with this permission will be ignored by the protection filter, leave nil if expcore.roles is not used repeat_count = 5, --- @setting repeat_count Number of protected entities to be removed to count as repeated repeat_lifetime = 3600*20, --- @setting repeat_lifetime How old repeats must be before being removed refresh_rate = 3600*5, --- @setting refresh_rate How often old repeats will be removed diff --git a/modules/control/protection.lua b/modules/control/protection.lua index dbb22b21..e8320378 100644 --- a/modules/control/protection.lua +++ b/modules/control/protection.lua @@ -32,12 +32,9 @@ for _, config_key in ipairs{'always_protected_names', 'always_protected_types', end -- convert ignore role if present -if config.ignore_role then - local Roles = require 'expcore.roles' - local role = Roles.get_role_by_name(config.ignore_role) - config.ignore_role = function(player) - return Roles.player_has_role(player, role) - end +local Roles +if config.ignore_permission then + Roles = require 'expcore.roles' --- @dep expcore.roles end ----- Global Variables ----- @@ -157,7 +154,7 @@ Event.add(defines.events.on_pre_player_mined_item, function(event) local player = game.get_player(event.player_index) -- Check if the player should be ignored if config.ignore_admins and player.admin then return end - if config.ignore_role and config.ignore_role(player) then return end + if config.ignore_permission and Roles.player_allowed(player, config.ignore_permission) then return end -- Check if the entity is protected if check_always_protected(entity) or EntityProtection.is_entity_protected(entity) From f4afe8baeb5688fd271a16404dda6039d3433e2a Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 02:05:23 +0100 Subject: [PATCH 07/14] Ignore entity if player is last user --- modules/control/protection.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/control/protection.lua b/modules/control/protection.lua index e8320378..e7da4ec4 100644 --- a/modules/control/protection.lua +++ b/modules/control/protection.lua @@ -154,6 +154,7 @@ Event.add(defines.events.on_pre_player_mined_item, function(event) local player = game.get_player(event.player_index) -- Check if the player should be ignored if config.ignore_admins and player.admin then return end + if entity.last_user.index == player.index then return end if config.ignore_permission and Roles.player_allowed(player, config.ignore_permission) then return end -- Check if the entity is protected @@ -172,6 +173,7 @@ Event.add(defines.events.on_pre_player_mined_item, function(event) event.name = EntityProtection.events.on_player_mined_protected script.raise_event(EntityProtection.events.on_player_mined_protected, event) if check_skip_repeat(entity) or player_repeats.count >= config.repeat_count then + player_repeats.count = 0 -- Reset to avoid spamming of events event.name = EntityProtection.events.on_repeat_violation script.raise_event(EntityProtection.events.on_repeat_violation, event) end From fb51f06c84984990fa351f41913880c2370554a8 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 17:04:42 +0100 Subject: [PATCH 08/14] Added comments to selection --- modules/control/selection.lua | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/control/selection.lua b/modules/control/selection.lua index 7ccb4e8f..fb7bfe1e 100644 --- a/modules/control/selection.lua +++ b/modules/control/selection.lua @@ -18,11 +18,12 @@ Global.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 function Selection.start(player, selection_name, single_use, ...) - game.print('Start selection') -- Assign the arguments if the player is valid if not player or not player.valid then return end - game.print('Valid Player') selections[player.index] = { name = selection_name, arguments = { ... }, @@ -32,18 +33,17 @@ function Selection.start(player, selection_name, single_use, ...) -- Give a selection tool if one is not in use if player.cursor_stack.is_selection_tool then return end - game.print('Give item') player.clear_cursor() -- Clear the current item player.cursor_stack.set_stack(selection_tool) -- Make a slot to place the selection tool even if inventory is full if not player.character then return end - game.print('Give slot') player.character_inventory_slots_bonus = player.character_inventory_slots_bonus + 1 player.hand_location = { inventory = defines.inventory.character_main, slot = #player.get_main_inventory() } end --- Stop a player selection by removing the selection planner +-- @tparam LuaPlayer player The player to exit out of selection mode function Selection.stop(player) if not selections[player.index] then return end local character = selections[player.index].character @@ -64,14 +64,23 @@ function Selection.stop(player) end --- Get the selection arguments for a player +-- @tparam LuaPlayer player The player to get the selection arguments for function Selection.get_arguments(player) if not selections[player.index] then return end return selections[player.index].arguments end +--- Test if a player is selecting something +-- @tparam LuaPlayer player The player to test +function Selection.is_selecting(player) + return player.cursor_stack.is_selection_tool +end + --- Filter on_player_selected_area to this custom selection, pretends with player and appends with selection arguments +-- @tparam string selection_name The name of the selection to listen for +-- @tparam function handler The event handler function Selection.on_selection(selection_name, handler) - return Event.add(defines.events.on_player_selected_area, function(event) + Event.add(defines.events.on_player_selected_area, function(event) local selection = selections[event.player_index] if not selection or selection.name ~= selection_name then return end local player = game.get_player(event.player_index) @@ -80,8 +89,10 @@ function Selection.on_selection(selection_name, handler) end --- Filter on_player_alt_selected_area to this custom selection, pretends with player and appends with selection arguments +-- @param string selection_name The name of the selection to listen for +-- @param function handler The event handler function Selection.on_alt_selection(selection_name, handler) - return Event.add(defines.events.on_player_alt_selected_area, function(event) + Event.add(defines.events.on_player_alt_selected_area, function(event) local selection = selections[event.player_index] if not selection or selection.name ~= selection_name then return end local player = game.get_player(event.player_index) From 891663edb9719d01d6a041582a52407c56a913a0 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 18:04:33 +0100 Subject: [PATCH 09/14] Added protection commands --- modules/commands/protection.lua | 98 +++++++++++++++++++++++++++++++++ modules/control/selection.lua | 8 ++- 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 modules/commands/protection.lua diff --git a/modules/commands/protection.lua b/modules/commands/protection.lua new file mode 100644 index 00000000..753ec319 --- /dev/null +++ b/modules/commands/protection.lua @@ -0,0 +1,98 @@ +--[[-- Commands Module - Protection + - Adds a commands that can add and remove protection + @commands Protection +]] + +local Commands = require 'expcore.commands' --- @dep expcore.commands +local EntityProtection = require 'modules.control.protection' --- @dep modules.control.protection +local Selection = require 'modules.control.selection' --- @dep modules.control.selection + +local SelectionProtectEntity = 'ProtectEntity' +local SelectionProtectArea = 'ProtectArea' + +--- Test if a point is inside an aabb +local function aabb_point_enclosed(point, aabb) + return point.x >= aabb.left_top.x and point.y >= aabb.left_top.y + and point.x <= aabb.right_bottom.x and point.y <= aabb.right_bottom.y +end + +--- Test if an aabb is inside another aabb +local function aabb_area_enclosed(aabbOne, aabbTwo) + return aabb_point_enclosed(aabbOne.left_top, aabbTwo) + and aabb_point_enclosed(aabbOne.right_bottom, aabbTwo) +end + +--- Align an aabb to the grid by expanding it +local function aabb_align_expand(aabb) + return { + left_top = { x = math.floor(aabb.left_top.x), y = math.floor(aabb.left_top.y) }, + right_bottom = { x = math.ceil(aabb.right_bottom.x), y = math.ceil(aabb.right_bottom.y) } + } +end + +--- Toggles entity protection selection +-- @command protect-entity +Commands.new_command('protect-entity', 'Toggles entity protection selection, hold shift to remove protection') +:add_alias('pe') +:register(function(player) + if Selection.is_selecting(player, SelectionProtectEntity) then + Selection.stop(player) + else + Selection.start(player, SelectionProtectEntity) + return Commands.success{'expcom-protection.entered-entity-selection'} + end +end) + +--- Toggles area protection selection +-- @command protect-area +Commands.new_command('protect-area', 'Toggles area protection selection, hold shift to remove protection') +:add_alias('pa') +:register(function(player) + if Selection.is_selecting(player, SelectionProtectArea) then + Selection.stop(player) + else + Selection.start(player, SelectionProtectArea) + return Commands.success{'expcom-protection.entered-entity-selection'} + end +end) + +--- When an area is selected to add protection to entities +Selection.on_selection(SelectionProtectEntity, function(_, event) + for _, entity in ipairs(event.entities) do + EntityProtection.add_entity(entity) + end + return Commands.success{'expcom-protection.protected-entities', #event.entities} +end) + +--- When an area is selected to remove protection from entities +Selection.on_alt_selection(SelectionProtectEntity, function(_, event) + for _, entity in ipairs(event.entities) do + EntityProtection.remove_entity(entity) + end + return Commands.success{'expcom-protection.unprotected-entities', #event.entities} +end) + +--- When an area is selected to add protection to the area +Selection.on_selection(SelectionProtectEntity, function(_, event) + local area = aabb_align_expand(event.area) + local areas = EntityProtection.get_areas(event.surface) + for _, next_area in pairs(areas) do + if aabb_area_enclosed(area, next_area) then + return Commands.error{'expcom-protection.already-protected'} + end + end + EntityProtection.add_area(event.surface, area) + return Commands.success{'expcom-protection.protected-area'} +end) + +--- When an area is selected to remove protection from the area +Selection.on_alt_selection(SelectionProtectEntity, function(_, event) + local area = aabb_align_expand(event.area) + local areas = EntityProtection.get_areas(event.surface) + for _, next_area in pairs(areas) do + if aabb_area_enclosed(next_area, area) then + EntityProtection.remove_area(event.surface, area) + Commands.print{'expcom-protection.unprotected-area'} + end + end +end) \ No newline at end of file diff --git a/modules/control/selection.lua b/modules/control/selection.lua index fb7bfe1e..30df3e66 100644 --- a/modules/control/selection.lua +++ b/modules/control/selection.lua @@ -72,9 +72,15 @@ end --- Test if a player is selecting something -- @tparam LuaPlayer player The player to test -function Selection.is_selecting(player) +-- @tparam[opt] string selection_name If given will only return true if the selection is this selection +function Selection.is_selecting(player, selection_name) + if selection_name ~= nil then + if not selections[player.index] then return false end + return selections[player.index].name == selection_name + else return player.cursor_stack.is_selection_tool end +end --- Filter on_player_selected_area to this custom selection, pretends with player and appends with selection arguments -- @tparam string selection_name The name of the selection to listen for From d83f1e3aea355c1908fd46114de86c0c6c36a8c2 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 21:05:11 +0100 Subject: [PATCH 10/14] Fixed protection issues --- config/_file_loader.lua | 1 + config/expcore/roles.lua | 2 ++ locale/en/commands.cfg | 12 +++++++++++- modules/commands/protection.lua | 18 ++++++++++++------ modules/control/protection.lua | 13 ++++++++++++- modules/control/selection.lua | 10 ++++------ 6 files changed, 42 insertions(+), 14 deletions(-) diff --git a/config/_file_loader.lua b/config/_file_loader.lua index 16a135af..3b22a83d 100644 --- a/config/_file_loader.lua +++ b/config/_file_loader.lua @@ -29,6 +29,7 @@ return { 'modules.commands.home', 'modules.commands.connect', 'modules.commands.last-location', + 'modules.commands.protection', --- Addons 'modules.addons.chat-popups', diff --git a/config/expcore/roles.lua b/config/expcore/roles.lua index 46cd7072..e363dfc1 100644 --- a/config/expcore/roles.lua +++ b/config/expcore/roles.lua @@ -98,6 +98,8 @@ Roles.new_role('Trainee','TrMod') 'command/give-warning', 'command/get-warnings', 'command/get-reports', + 'command/protect-entity', + 'command/protect-area', 'command/jail', 'command/unjail', 'command/kick', diff --git a/locale/en/commands.cfg b/locale/en/commands.cfg index dea7b935..ef117971 100644 --- a/locale/en/commands.cfg +++ b/locale/en/commands.cfg @@ -82,4 +82,14 @@ offline=You cannot connect as the server is currently offline: __1__ none-matching=No servers were found with that name, if you used an address please append true to the end of your command. [expcom-lastlocation] -response=Last location of __1__ was [gps=__2__,__3__] \ No newline at end of file +response=Last location of __1__ was [gps=__2__,__3__] + +[expcom-protection] +entered-entity-selection=Entered entity selection, select entites to protect, hold shift to remove protection. +entered-area-selection=Entered area selection, select areas to protect, hold shift to remove protection. +protected-entities=__1__ entities have been protected. +unprotected-entities=__1__ entities have been unprotected. +already-protected=This area is already protected. +protected-area=This area is now protected. +unprotected-area=This area is now unprotected. +repeat-offence=__1__ has removed __2__ at [gps=__3__,__4__] \ No newline at end of file diff --git a/modules/commands/protection.lua b/modules/commands/protection.lua index 753ec319..e43a0989 100644 --- a/modules/commands/protection.lua +++ b/modules/commands/protection.lua @@ -52,12 +52,12 @@ Commands.new_command('protect-area', 'Toggles area protection selection, hold sh Selection.stop(player) else Selection.start(player, SelectionProtectArea) - return Commands.success{'expcom-protection.entered-entity-selection'} + return Commands.success{'expcom-protection.entered-area-selection'} end end) --- When an area is selected to add protection to entities -Selection.on_selection(SelectionProtectEntity, function(_, event) +Selection.on_selection(SelectionProtectEntity, function(event) for _, entity in ipairs(event.entities) do EntityProtection.add_entity(entity) end @@ -65,7 +65,7 @@ Selection.on_selection(SelectionProtectEntity, function(_, event) end) --- When an area is selected to remove protection from entities -Selection.on_alt_selection(SelectionProtectEntity, function(_, event) +Selection.on_alt_selection(SelectionProtectEntity, function(event) for _, entity in ipairs(event.entities) do EntityProtection.remove_entity(entity) end @@ -73,7 +73,7 @@ Selection.on_alt_selection(SelectionProtectEntity, function(_, event) end) --- When an area is selected to add protection to the area -Selection.on_selection(SelectionProtectEntity, function(_, event) +Selection.on_selection(SelectionProtectArea, function(event) local area = aabb_align_expand(event.area) local areas = EntityProtection.get_areas(event.surface) for _, next_area in pairs(areas) do @@ -86,13 +86,19 @@ Selection.on_selection(SelectionProtectEntity, function(_, event) end) --- When an area is selected to remove protection from the area -Selection.on_alt_selection(SelectionProtectEntity, function(_, event) +Selection.on_alt_selection(SelectionProtectArea, function(event) local area = aabb_align_expand(event.area) local areas = EntityProtection.get_areas(event.surface) for _, next_area in pairs(areas) do if aabb_area_enclosed(next_area, area) then - EntityProtection.remove_area(event.surface, area) + EntityProtection.remove_area(event.surface, next_area) Commands.print{'expcom-protection.unprotected-area'} end end +end) + +--- When there is a repeat offence print it in chat +Event.add(EntityProtection.events.on_repeat_violation, function(event) + local player_name = format_chat_player_name(event.player_index) + Roles.print_to_roles_higher('Regular', {'expcom-protection.repeat-offence', player_name, event.entity.localised_name, event.entity.position.x, event.entity.position.y}) end) \ No newline at end of file diff --git a/modules/control/protection.lua b/modules/control/protection.lua index e7da4ec4..490e0c7d 100644 --- a/modules/control/protection.lua +++ b/modules/control/protection.lua @@ -104,6 +104,7 @@ end --- Check if an entity is protected function EntityProtection.is_entity_protected(entity) + if check_always_protected(entity) then return true end local entities = protected_entities[entity.surface.index] if not entities then return false end return entities[get_entity_key(entity)] == entity @@ -158,7 +159,7 @@ Event.add(defines.events.on_pre_player_mined_item, function(event) if config.ignore_permission and Roles.player_allowed(player, config.ignore_permission) then return end -- Check if the entity is protected - if check_always_protected(entity) or EntityProtection.is_entity_protected(entity) + if EntityProtection.is_entity_protected(entity) or EntityProtection.is_position_protected(entity.surface, entity.position) then -- Update repeats @@ -190,4 +191,14 @@ Event.on_nth_tick(config.refresh_rate, function() end end) +--- When an entity is removed remove it from the protection list +local function event_remove_entity(event) + EntityProtection.remove_entity(event.entity) +end + +Event.add(defines.events.on_pre_player_mined_item, event_remove_entity) +Event.add(defines.events.on_robot_pre_mined, event_remove_entity) +Event.add(defines.events.on_entity_died, event_remove_entity) +Event.add(defines.events.script_raised_destroy, event_remove_entity) + return EntityProtection \ No newline at end of file diff --git a/modules/control/selection.lua b/modules/control/selection.lua index 30df3e66..00f76c6c 100644 --- a/modules/control/selection.lua +++ b/modules/control/selection.lua @@ -82,27 +82,25 @@ function Selection.is_selecting(player, selection_name) end end ---- Filter on_player_selected_area to this custom selection, pretends with player and appends with selection arguments +--- Filter on_player_selected_area to this custom selection, appends the selection arguments -- @tparam string selection_name The name of the selection to listen for -- @tparam function handler The event handler function Selection.on_selection(selection_name, handler) Event.add(defines.events.on_player_selected_area, function(event) local selection = selections[event.player_index] if not selection or selection.name ~= selection_name then return end - local player = game.get_player(event.player_index) - handler(player, event, unpack(selection.arguments)) + handler(event, unpack(selection.arguments)) end) end ---- Filter on_player_alt_selected_area to this custom selection, pretends with player and appends with selection arguments +--- Filter on_player_alt_selected_area to this custom selection, appends the selection arguments -- @param string selection_name The name of the selection to listen for -- @param function handler The event handler function Selection.on_alt_selection(selection_name, handler) Event.add(defines.events.on_player_alt_selected_area, function(event) local selection = selections[event.player_index] if not selection or selection.name ~= selection_name then return end - local player = game.get_player(event.player_index) - handler(player, event, unpack(selection.arguments)) + handler(event, unpack(selection.arguments)) end) end From 43d5ff774151e65e9b4f4113784a3002ecce9b49 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 21:05:34 +0100 Subject: [PATCH 11/14] Added renderer and selection events --- modules/commands/protection.lua | 110 ++++++++++++++++++++++++++++++++ modules/control/protection.lua | 10 +-- modules/control/selection.lua | 48 ++++++++++++-- 3 files changed, 160 insertions(+), 8 deletions(-) diff --git a/modules/commands/protection.lua b/modules/commands/protection.lua index e43a0989..bc79165f 100644 --- a/modules/commands/protection.lua +++ b/modules/commands/protection.lua @@ -3,13 +3,24 @@ @commands Protection ]] +local Event = require 'utils.event' --- @dep utils.event +local Global = require 'utils.global' --- @dep utils.global +local Roles = require 'expcore.roles' --- @dep expcore.roles local Commands = require 'expcore.commands' --- @dep expcore.commands +local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local EntityProtection = require 'modules.control.protection' --- @dep modules.control.protection local Selection = require 'modules.control.selection' --- @dep modules.control.selection local SelectionProtectEntity = 'ProtectEntity' local SelectionProtectArea = 'ProtectArea' +local renders = {} -- Stores all renders for a player +Global.register({ + renders = renders +}, function(tbl) + renders = tbl.renders +end) + --- Test if a point is inside an aabb local function aabb_point_enclosed(point, aabb) return point.x >= aabb.left_top.x and point.y >= aabb.left_top.y @@ -30,6 +41,58 @@ local function aabb_align_expand(aabb) } end +--- Get the key used in protected_entities +local function get_entity_key(entity) + return string.format('%i,%i', math.floor(entity.position.x), math.floor(entity.position.y)) +end + +--- Get the key used in protected_areas +local function get_area_key(area) + return string.format('%i,%i', math.floor(area.left_top.x), math.floor(area.left_top.y)) +end + + +--- Show a protected entity to a player +local function show_protected_entity(player, entity) + local key = get_entity_key(entity) + if renders[player.index][key] then return end + local rb = entity.selection_box.right_bottom + local render_id = rendering.draw_sprite{ + sprite = 'utility/notification', + target = entity, + target_offset = { + (rb.x-entity.position.x)*0.8, + (rb.y-entity.position.y)*0.8 + }, + surface = entity.surface, + players = { player } + } + renders[player.index][key] = render_id +end + +--- Show a protected are to a player +local function show_protected_area(player, surface, area) + local key = get_area_key(area) + if renders[player.index][key] then return end + local render_id = rendering.draw_rectangle{ + color = {1, 1, 0, 0.5}, + filled = false, + width = 3, + left_top = area.left_top, + right_bottom = area.right_bottom, + surface = surface, + players = { player } + } + renders[player.index][key] = render_id +end + +--- Remove a render object for a player +local function remove_render(player, key) + local render = renders[player.index][key] + if render and rendering.is_valid(render) then rendering.destroy(render) end + renders[player.index][key] = nil +end + --- Toggles entity protection selection -- @command protect-entity Commands.new_command('protect-entity', 'Toggles entity protection selection, hold shift to remove protection') @@ -58,16 +121,20 @@ end) --- When an area is selected to add protection to entities Selection.on_selection(SelectionProtectEntity, function(event) + local player = game.get_player(event.player_index) for _, entity in ipairs(event.entities) do EntityProtection.add_entity(entity) + show_protected_entity(player, entity) end return Commands.success{'expcom-protection.protected-entities', #event.entities} end) --- When an area is selected to remove protection from entities Selection.on_alt_selection(SelectionProtectEntity, function(event) + local player = game.get_player(event.player_index) for _, entity in ipairs(event.entities) do EntityProtection.remove_entity(entity) + remove_render(player, get_entity_key(entity)) end return Commands.success{'expcom-protection.unprotected-entities', #event.entities} end) @@ -81,7 +148,9 @@ Selection.on_selection(SelectionProtectArea, function(event) return Commands.error{'expcom-protection.already-protected'} end end + local player = game.get_player(event.player_index) EntityProtection.add_area(event.surface, area) + show_protected_area(player, event.surface, area) return Commands.success{'expcom-protection.protected-area'} end) @@ -89,14 +158,55 @@ end) Selection.on_alt_selection(SelectionProtectArea, function(event) local area = aabb_align_expand(event.area) local areas = EntityProtection.get_areas(event.surface) + local player = game.get_player(event.player_index) for _, next_area in pairs(areas) do if aabb_area_enclosed(next_area, area) then EntityProtection.remove_area(event.surface, next_area) Commands.print{'expcom-protection.unprotected-area'} + remove_render(player, get_area_key(next_area)) end end end) +--- When selection starts show all protected entities and protected areas +Event.add(Selection.events.on_player_selection_start, function(event) + if event.selection ~= SelectionProtectEntity and event.selection ~= SelectionProtectArea then return end + local player = game.get_player(event.player_index) + local surface = player.surface + renders[player.index] = {} + -- Show protected entities + local entities = EntityProtection.get_entities(surface) + for _, entity in pairs(entities) do + show_protected_entity(player, entity) + end + -- Show always protected entities by name + if #EntityProtection.protected_entity_names > 0 then + for _, entity in pairs(surface.find_entities_filtered{ name = EntityProtection.protected_entity_names, force = player.force }) do + show_protected_entity(player, entity) + end + end + -- Show always protected entities by type + if #EntityProtection.protected_entity_types > 0 then + for _, entity in pairs(surface.find_entities_filtered{ type = EntityProtection.protected_entity_types, force = player.force }) do + show_protected_entity(player, entity) + end + end + -- Show protected areas + local areas = EntityProtection.get_areas(surface) + for _, area in pairs(areas) do + show_protected_area(player, surface, area) + end +end) + +--- When selection ends show hide protected entities on screen and protected areas +Event.add(Selection.events.on_player_selection_end, function(event) + if event.selection ~= SelectionProtectEntity and event.selection ~= SelectionProtectArea then return end + for _, id in pairs(renders[event.player_index]) do + if rendering.is_valid(id) then rendering.destroy(id) end + end + renders[event.player_index] = nil +end) + --- When there is a repeat offence print it in chat Event.add(EntityProtection.events.on_repeat_violation, function(event) local player_name = format_chat_player_name(event.player_index) diff --git a/modules/control/protection.lua b/modules/control/protection.lua index 490e0c7d..e0d1c7cc 100644 --- a/modules/control/protection.lua +++ b/modules/control/protection.lua @@ -8,6 +8,8 @@ local Global = require 'utils.global' --- @dep utils.global local Event = require 'utils.event' --- @dep utils.event local config = require 'config.protection' --- @dep config.protection local EntityProtection = { + protected_entity_names = table.deep_copy(config.always_protected_names), + protected_entity_types = table.deep_copy(config.always_protected_types), events = { --- When a player mines a protected entity -- @event on_player_mined_protected @@ -59,12 +61,12 @@ end) --- Get the key used in protected_entities local function get_entity_key(entity) - return string.format('%i,%i', entity.position.x, entity.position.y) + return string.format('%i,%i', math.floor(entity.position.x), math.floor(entity.position.y)) end --- Get the key used in protected_areas local function get_area_key(area) - return string.format('%i,%i', area.left_top.x, area.left_top.y) + return string.format('%i,%i', math.floor(area.left_top.x), math.floor(area.left_top.y)) end --- Check if an entity is always protected @@ -99,7 +101,7 @@ end --- Get all protected entities on a surface function EntityProtection.get_entities(surface) - return protected_entities[surface.index] + return protected_entities[surface.index] or {} end --- Check if an entity is protected @@ -129,7 +131,7 @@ end --- Get all protected areas on a surface function EntityProtection.get_areas(surface) - return protected_areas[surface.index] + return protected_areas[surface.index] or {} end --- Check if an entity is protected diff --git a/modules/control/selection.lua b/modules/control/selection.lua index 00f76c6c..0b009b40 100644 --- a/modules/control/selection.lua +++ b/modules/control/selection.lua @@ -6,7 +6,20 @@ local Event = require 'utils.event' --- @dep utils.event local Global = require 'utils.global' --- @dep utils.global -local Selection = {} +local Selection = { + events = { + --- When a player enterers selection mode + -- @event on_player_selection_start + -- @tparam number player_index the player index of the player who entered selection mode + -- @tparam string selection the name of the selection being made + on_player_selection_start = script.generate_event_name(), + --- When a player leaves selection mode + -- @event on_player_selection_end + -- @tparam number player_index the player index of the player who left selection mode + -- @tparam string selection the name of the selection which ended + on_player_selection_end = script.generate_event_name(), + } +} local selection_tool = { name='selection-tool' } @@ -22,8 +35,18 @@ end) -- @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 function Selection.start(player, selection_name, single_use, ...) - -- Assign the arguments if the player is valid if not player or not player.valid then return end + if selections[player.index] then + -- Raise the end event if a selection was already in progress + script.raise_event(Selection.events.on_player_selection_end, { + name = Selection.events.on_player_selection_end, + tick = game.tick, + player_index = player.index, + selection = selections[player.index].name + }) + end + + -- Set the selection data selections[player.index] = { name = selection_name, arguments = { ... }, @@ -31,6 +54,14 @@ function Selection.start(player, selection_name, single_use, ...) character = player.character } + -- Raise the event + script.raise_event(Selection.events.on_player_selection_start, { + name = Selection.events.on_player_selection_start, + tick = game.tick, + player_index = player.index, + selection = selection_name + }) + -- Give a selection tool if one is not in use if player.cursor_stack.is_selection_tool then return end player.clear_cursor() -- Clear the current item @@ -47,8 +78,17 @@ end function Selection.stop(player) if not selections[player.index] then return end local character = selections[player.index].character + local selection = selections[player.index].name selections[player.index] = nil + -- Raise the event + script.raise_event(Selection.events.on_player_selection_end, { + name = Selection.events.on_player_selection_end, + tick = game.tick, + player_index = player.index, + selection = selection + }) + -- Remove the selection tool if player.cursor_stack.is_selection_tool then player.cursor_stack.clear() @@ -78,8 +118,8 @@ function Selection.is_selecting(player, selection_name) if not selections[player.index] then return false end return selections[player.index].name == selection_name else - return player.cursor_stack.is_selection_tool -end + return player.cursor_stack.is_selection_tool + end end --- Filter on_player_selected_area to this custom selection, appends the selection arguments From d6fd975771f6022f4244fbcce8c6392400b5e0e8 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 21:18:50 +0100 Subject: [PATCH 12/14] Adjusted icon size and offset --- modules/commands/protection.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/commands/protection.lua b/modules/commands/protection.lua index bc79165f..57841a43 100644 --- a/modules/commands/protection.lua +++ b/modules/commands/protection.lua @@ -61,9 +61,11 @@ local function show_protected_entity(player, entity) sprite = 'utility/notification', target = entity, target_offset = { - (rb.x-entity.position.x)*0.8, - (rb.y-entity.position.y)*0.8 + (rb.x-entity.position.x)*0.75, + (rb.y-entity.position.y)*0.75 }, + x_scale = 2, + y_scale = 2, surface = entity.surface, players = { player } } From e38eda007696da96e5da04d26efd538e22f57fb9 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 25 Apr 2021 03:45:51 +0100 Subject: [PATCH 13/14] Fixed missing output --- modules/commands/protection.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/commands/protection.lua b/modules/commands/protection.lua index 57841a43..c48454d1 100644 --- a/modules/commands/protection.lua +++ b/modules/commands/protection.lua @@ -128,7 +128,7 @@ Selection.on_selection(SelectionProtectEntity, function(event) EntityProtection.add_entity(entity) show_protected_entity(player, entity) end - return Commands.success{'expcom-protection.protected-entities', #event.entities} + player.print{'expcom-protection.protected-entities', #event.entities} end) --- When an area is selected to remove protection from entities @@ -138,22 +138,22 @@ Selection.on_alt_selection(SelectionProtectEntity, function(event) EntityProtection.remove_entity(entity) remove_render(player, get_entity_key(entity)) end - return Commands.success{'expcom-protection.unprotected-entities', #event.entities} + player.print{'expcom-protection.unprotected-entities', #event.entities} end) --- When an area is selected to add protection to the area Selection.on_selection(SelectionProtectArea, function(event) local area = aabb_align_expand(event.area) local areas = EntityProtection.get_areas(event.surface) + local player = game.get_player(event.player_index) for _, next_area in pairs(areas) do if aabb_area_enclosed(area, next_area) then - return Commands.error{'expcom-protection.already-protected'} + return player.print{'expcom-protection.already-protected'} end end - local player = game.get_player(event.player_index) EntityProtection.add_area(event.surface, area) show_protected_area(player, event.surface, area) - return Commands.success{'expcom-protection.protected-area'} + player.print{'expcom-protection.protected-area'} end) --- When an area is selected to remove protection from the area @@ -164,7 +164,7 @@ Selection.on_alt_selection(SelectionProtectArea, function(event) for _, next_area in pairs(areas) do if aabb_area_enclosed(next_area, area) then EntityProtection.remove_area(event.surface, next_area) - Commands.print{'expcom-protection.unprotected-area'} + player.print{'expcom-protection.unprotected-area'} remove_render(player, get_area_key(next_area)) end end From 2df7482a772d51e9cc47d83faf59f8204bfebdf3 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Mon, 26 Apr 2021 00:20:55 +0100 Subject: [PATCH 14/14] Implemented requested changes --- config/protection.lua | 10 +++++----- modules/addons/discord-alerts.lua | 2 +- modules/commands/protection.lua | 6 +++--- modules/control/protection.lua | 18 +++++++++--------- modules/control/selection.lua | 5 +++-- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/config/protection.lua b/config/protection.lua index fbba783d..6f051c37 100644 --- a/config/protection.lua +++ b/config/protection.lua @@ -1,19 +1,19 @@ return { ignore_admins = true, --- @setting ignore_admins If admins are ignored by the protection filter ignore_permission = 'bypass-entity-protection', --- @setting ignore_permission Players with this permission will be ignored by the protection filter, leave nil if expcore.roles is not used - repeat_count = 5, --- @setting repeat_count Number of protected entities to be removed to count as repeated - repeat_lifetime = 3600*20, --- @setting repeat_lifetime How old repeats must be before being removed - refresh_rate = 3600*5, --- @setting refresh_rate How often old repeats will be removed + repeat_count = 5, --- @setting repeat_count Number of protected entities that must be removed within repeat_lifetime in order to trigger repeated removal protection + repeat_lifetime = 3600*20, --- @setting repeat_lifetime The length of time, in ticks, that protected removals will be remembered for + refresh_rate = 3600*5, --- @setting refresh_rate How often the age of protected removals are checked against repeat_lifetime always_protected_names = { --- @setting always_protected_names Names of entities which are always protected }, always_protected_types = { --- @setting always_protected_types Types of entities which are always protected 'boiler', 'generator', 'offshore-pump', 'power-switch', 'reactor', 'rocket-silo' }, - skip_repeat_names = { --- @setting skip_repeat_names Names of entities which always trigger protection repeated + always_trigger_repeat_names = { --- @setting always_trigger_repeat_names Names of entities which always trigger repeated removal protection }, - skip_repeat_types = { --- @setting skip_repeat_types Types of entities which trigger protection repeated + always_trigger_repeat_types = { --- @setting always_trigger_repeat_types Types of entities which always trigger repeated removal protection 'reactor', 'rocket-silo' } } \ No newline at end of file diff --git a/modules/addons/discord-alerts.lua b/modules/addons/discord-alerts.lua index fe13ec5c..acab30e6 100644 --- a/modules/addons/discord-alerts.lua +++ b/modules/addons/discord-alerts.lua @@ -76,7 +76,7 @@ local function emit_event(args) }) end ---- Repeat protected entity mining +--- Repeated protected entity mining if config.entity_protection then local EntityProtection = require 'modules.control.protection' --- @dep modules.control.protection Event.add(EntityProtection.events.on_repeat_violation, function(event) diff --git a/modules/commands/protection.lua b/modules/commands/protection.lua index c48454d1..01066d35 100644 --- a/modules/commands/protection.lua +++ b/modules/commands/protection.lua @@ -1,5 +1,5 @@ --[[-- Commands Module - Protection - - Adds a commands that can add and remove protection + - Adds commands that can add and remove protection @commands Protection ]] @@ -72,7 +72,7 @@ local function show_protected_entity(player, entity) renders[player.index][key] = render_id end ---- Show a protected are to a player +--- Show a protected area to a player local function show_protected_area(player, surface, area) local key = get_area_key(area) if renders[player.index][key] then return end @@ -200,7 +200,7 @@ Event.add(Selection.events.on_player_selection_start, function(event) end end) ---- When selection ends show hide protected entities on screen and protected areas +--- When selection ends hide protected entities and protected areas Event.add(Selection.events.on_player_selection_end, function(event) if event.selection ~= SelectionProtectEntity and event.selection ~= SelectionProtectArea then return end for _, id in pairs(renders[event.player_index]) do diff --git a/modules/control/protection.lua b/modules/control/protection.lua index e0d1c7cc..61b5f5c6 100644 --- a/modules/control/protection.lua +++ b/modules/control/protection.lua @@ -16,7 +16,7 @@ local EntityProtection = { -- @tparam number player_index the player index of the player who got mined the entity -- @tparam LuaEntity entity the entity which was mined on_player_mined_protected = script.generate_event_name(), - --- When a player mines a many protected entities + --- When a player repeatedly mines protected entities -- @event on_repeat_violation -- @tparam number player_index the player index of the player who got mined the entities -- @tparam LuaEntity entity the last entity which was mined @@ -24,8 +24,8 @@ local EntityProtection = { } } --- convert config tables into lookup tables -for _, config_key in ipairs{'always_protected_names', 'always_protected_types', 'skip_repeat_names', 'skip_repeat_types'} do +-- Convert config tables into lookup tables +for _, config_key in ipairs{'always_protected_names', 'always_protected_types', 'always_trigger_repeat_names', 'always_trigger_repeat_types'} do local tbl = config[config_key] for key, value in ipairs(tbl) do tbl[key] = nil @@ -33,10 +33,10 @@ for _, config_key in ipairs{'always_protected_names', 'always_protected_types', end end --- convert ignore role if present +-- Require roles if a permission is assigned in the config local Roles if config.ignore_permission then - Roles = require 'expcore.roles' --- @dep expcore.roles + Roles = require 'expcore.roles' --- @dep expcore.roles end ----- Global Variables ----- @@ -74,9 +74,9 @@ local function check_always_protected(entity) return config.always_protected_names[entity.name] or config.always_protected_types[entity.type] or false end ---- Check if an entity skips repeated -local function check_skip_repeat(entity) - return config.skip_repeat_names[entity.name] or config.skip_repeat_types[entity.type] or false +--- Check if an entity always triggers repeat protection +local function check_always_trigger_repeat(entity) + return config.always_trigger_repeat_names[entity.name] or config.always_trigger_repeat_types[entity.type] or false end ----- Public Functions ----- @@ -175,7 +175,7 @@ Event.add(defines.events.on_pre_player_mined_item, function(event) -- Send events event.name = EntityProtection.events.on_player_mined_protected script.raise_event(EntityProtection.events.on_player_mined_protected, event) - if check_skip_repeat(entity) or player_repeats.count >= config.repeat_count then + if check_always_trigger_repeat(entity) or player_repeats.count >= config.repeat_count then player_repeats.count = 0 -- Reset to avoid spamming of events event.name = EntityProtection.events.on_repeat_violation script.raise_event(EntityProtection.events.on_repeat_violation, event) diff --git a/modules/control/selection.lua b/modules/control/selection.lua index 0b009b40..4939253b 100644 --- a/modules/control/selection.lua +++ b/modules/control/selection.lua @@ -8,7 +8,7 @@ local Event = require 'utils.event' --- @dep utils.event local Global = require 'utils.global' --- @dep utils.global local Selection = { events = { - --- When a player enterers selection mode + --- When a player enters selection mode -- @event on_player_selection_start -- @tparam number player_index the player index of the player who entered selection mode -- @tparam string selection the name of the selection being made @@ -158,7 +158,8 @@ end Event.add(defines.events.on_pre_player_left_game, stop_after_event) Event.add(defines.events.on_pre_player_died, stop_after_event) ---- Stop selection after a single use if the option was used + +--- Stop selection after a single use if single_use was true during Selection.start local function stop_after_use(event) if not selections[event.player_index] then return end if not selections[event.player_index].single_use then return end