From 3ab6326a5f352f6b1ceadac8553bf037cfa0bd25 Mon Sep 17 00:00:00 2001 From: bbassie Date: Sun, 24 Jan 2021 02:02:24 +0100 Subject: [PATCH 01/56] Tasklist refactor to match the new warp system * Removed the ability to pass `task_number` to `Task.add_task` * Unified button styles of the Gui * Made task-list code simular to the new warp-list --- modules/control/tasks.lua | 17 +- modules/gui/task-list.lua | 322 +++++++++++++++++++++----------------- 2 files changed, 181 insertions(+), 158 deletions(-) diff --git a/modules/control/tasks.lua b/modules/control/tasks.lua index ec0f8c38..0b319709 100644 --- a/modules/control/tasks.lua +++ b/modules/control/tasks.lua @@ -31,7 +31,6 @@ end) --[[-- Add a new task for a force, the task can be placed into a certain position for that force @tparam string force_name the name of the force to add the task for -@tparam[opt] number task_number the order place to add the task to, appends to end if omited @tparam[opt] string player_name the player who added this task, will cause them to be listed under editing @tparam[opt] string task_message the message that is used for this task, if not given default is used @treturn string the uid of the task which was created @@ -40,25 +39,21 @@ end) local task_id = Tasks.add_task(game.player.force.name, nil, game.player.name) ]] -function Tasks.add_task(force_name, task_number, player_name, task_message) +function Tasks.add_task(force_name, player_name, task_message) -- Get a new task id local task_id = tostring(force_tasks._uid) task_message = task_message or 'New Task' force_tasks._uid = force_tasks._uid + 1 -- Get the existing tasks for this force - local tasks = force_tasks[force_name] - if not tasks then - force_tasks[force_name] = {} - tasks = force_tasks[force_name] + local task_ids = force_tasks[force_name] + if not task_ids then + task_ids = {} + force_tasks[force_name] = task_ids end -- Insert the task id into the forces tasks - if task_number then - table.insert(tasks, task_number, task_id) - else - table.insert(tasks, task_id) - end + table.insert(task_ids, task_id) -- Create the editing table local editing = {} diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index a83b3aa5..335f2516 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -13,8 +13,7 @@ local format_time = _C.format_time --- @dep expcore.common -- Styles used for sprite buttons local Styles = { - sprite20 = Gui.sprite_style(20), - sprite22 = Gui.sprite_style(20, nil, { right_margin = -3 }) + sprite22 = { height = 22, width = 22, padding = -2 }, } --- If a player is allowed to use the edit buttons @@ -66,130 +65,29 @@ Gui.element{ tooltip = {'task-list.add-tooltip'}, style = 'tool_button' } -:style(Styles.sprite20) +:style(Styles.sprite22) :on_click(function(player, _,_) - Tasks.add_task(player.force.name, nil, player.name) -end) - ---- Button displayed next to tasks which the user is can edit, used to start editing a task --- @element edit_task -local edit_task = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/rename_icon_normal', - tooltip = {'task-list.edit-tooltip-none'}, - style = 'tool_button' -} -:style(Styles.sprite20) -:on_click(function(player, element, _) - local task_id = element.parent.name:sub(6) - Tasks.set_editing(task_id, player.name, true) -end) - ---- Button displayed next to tasks which the user is can edit, used to delete a task from the list --- @element discard_task -local discard_task = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/trash', - tooltip = {'task-list.discard-tooltip'}, - style = 'tool_button' -} -:style(Styles.sprite20) -:on_click(function(_, element, _) - local task_id = element.parent.name:sub(6) - Tasks.remove_task(task_id) -end) - ---- Set of three elements which make up each row of the task table --- @element add_task_base -local add_task_base = -Gui.element(function(_, parent, task_id) - -- Add the task number label - local task_number = parent.add{ - name = 'count-'..task_id, - type = 'label', - caption = '0)' - } - task_number.style.left_margin = 1 - - -- Add a flow which will contain the task message and edit buttons - local task_flow = parent.add{ name = task_id, type = 'flow', } - task_flow.style.padding = 0 - - -- Add the two edit buttons outside the task flow - local edit_flow = Gui.alignment(parent, 'edit-'..task_id) - edit_task(edit_flow) - discard_task(edit_flow) - - -- Return the task flow as the main element - return task_flow -end) - --- Removes the three elements that are added as part of the task base -local function remove_task_base(parent, task_id) - Gui.destroy_if_valid(parent['count-'..task_id]) - Gui.destroy_if_valid(parent['edit-'..task_id]) - Gui.destroy_if_valid(parent[task_id]) -end - ---- Button displayed next to tasks which the user is currently editing, used to save changes --- @element confirm_edit -local task_editing -local confirm_edit = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/confirm_slot', - tooltip = {'task-list.confirm-tooltip'}, - style = 'shortcut_bar_button_green' -} -:style(Styles.sprite22) -:on_click(function(player, element, _) - local task_id = element.parent.name - local new_message = element.parent[task_editing.name].text - Tasks.set_editing(task_id, player.name) - Tasks.update_task(task_id, new_message, player.name) -end) - ---- Button displayed next to tasks which the user is currently editing, used to discard changes --- @element cancel_edit -local cancel_edit = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/close_black', - tooltip = {'task-list.cancel-tooltip'}, - style = 'shortcut_bar_button_red' -} -:style(Styles.sprite22) -:on_click(function(player, element, _) - local task_id = element.parent.name - Tasks.set_editing(task_id, player.name) + Tasks.add_task(player.force.name, player.name) end) --- Editing state for a task, contrins a text field and the two edit buttons -- @element task_editing -task_editing = +local task_textfield = Gui.element(function(event_trigger, parent, task) - local message = task.message - -- Draw the element local element = parent.add{ name = event_trigger, type = 'textfield', - text = message, + text = task.message, clear_and_focus_on_right_click = true } - -- Add the edit buttons - cancel_edit(parent) - confirm_edit(parent) - -- Return the element return element end) :style{ - maximal_width = 110, + maximal_width = 131, height = 20 } :on_confirmed(function(player, element, _) @@ -202,23 +100,134 @@ end) --- Default state for a task, contains only a label with the task message -- @element task_label local task_label = -Gui.element(function(_, parent, task) - local message = task.message +Gui.element(function(event_trigger, parent, task) local last_edit_name = task.last_edit_name local last_edit_time = task.last_edit_time -- Draw the element return parent.add{ - name = task_editing.name, + name = event_trigger, type = 'label', - caption = message, + caption = task.message, tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)} } end) :style{ single_line = false, - maximal_width = 150 + maximal_width = 150, + horizontally_stretchable = true } +--- Button displayed next to tasks which the user is can edit, used to start editing a task +-- @element edit_task_button +local edit_task_button = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/rename_icon_normal', + tooltip = {'task-list.edit-tooltip-none'}, + style = 'shortcut_bar_button' +} +:style(Styles.sprite22) +:on_click(function(player, element, _) + local task_id = element.parent.caption + Tasks.set_editing(task_id, player.name, true) +end) + +--- Button displayed next to tasks which the user is can edit, used to remove a task from the list +-- @element remove_task_button +local remove_task_button = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/trash', + tooltip = {'task-list.discard-tooltip'}, + style = 'shortcut_bar_button_red' +} +:style(Styles.sprite22) +:on_click(function(_, element, _) + local task_id = element.parent.caption + Tasks.remove_task(task_id) +end) + +-- Removes the three elements that are added as part of the task base +local function remove_task_base(parent, task_id) + Gui.destroy_if_valid(parent['count-'..task_id]) + Gui.destroy_if_valid(parent['name-'..task_id]) + Gui.destroy_if_valid(parent['button-'..task_id]) +end + +--- Button displayed next to tasks which the user is currently editing, used to save changes +-- @element confirm_edit_button +local confirm_edit_button = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/confirm_slot', + tooltip = {'task-list.confirm-tooltip'}, + style = 'shortcut_bar_button_green' +} +:style(Styles.sprite22) +:on_click(function(player, element, _) + local task_id = element.parent.caption + local new_message = element.parent.parent['name-'..task_id][task_textfield.name].text + Tasks.set_editing(task_id, player.name) + Tasks.update_task(task_id, new_message, player.name) +end) + +--- Button displayed next to tasks which the user is currently editing, used to cancel changes +-- @element cancel_edit_button +local cancel_edit_button = +Gui.element{ + type = 'sprite-button', + sprite = 'utility/close_black', + tooltip = {'task-list.cancel-tooltip'}, + style = 'shortcut_bar_button_red' +} +:style(Styles.sprite22) +:on_click(function(player, element, _) + local task_id = element.parent.caption + Tasks.set_editing(task_id, player.name) +end) + +--- Set of three elements which make up each row of the task table +-- @element add_task_elements +local add_task_elements = +Gui.element(function(_, parent, task) + -- Add the task number label + local task_number = parent.add{ + name = 'count-'..task.task_id, + type = 'label', + caption = '#)' + } + task_number.style.left_margin = 1 + + -- Add name flow this will contain the task label and textbox + local task_flow = parent.add{ + name = 'name-'..task.task_id, + type = 'flow', + caption = task.task_id, + } + task_flow.style.padding = 0 + + -- Add the label and textfield of the task + task_label(task_flow, task) + task_textfield(task_flow, task) + + -- Add button flow this will contain buttons to manage this specific task + local button_flow = parent.add{ + name = 'button-'..task.task_id, + type = 'flow', + caption = task.task_id, + } + button_flow.style.padding = 0 + + -- Add both edit state buttons + cancel_edit_button(button_flow) + confirm_edit_button(button_flow) + edit_task_button(button_flow) + remove_task_button(button_flow) + + -- Return the task flow as the main element + return { task_flow, button_flow } +end) + --- Updates a task for a player local function update_task(player, task_table, task_id) local task = Tasks.get_task(task_id) @@ -233,19 +242,31 @@ local function update_task(player, task_table, task_id) end -- Get the task flow for this task - local task_flow = task_table[task_id] or add_task_base(task_table, task_id) + if not task_table['name-'..task_id] then + add_task_elements(task_table, task) + end + local count_flow = task_table['count-'..task_id] + local name_flow = task_table['name-'..task_id] + local button_flow = task_table['button-'..task_id] task_table.parent.no_tasks.visible = false - task_table['count-'..task_id].caption = task_number..')' + count_flow.caption = task_number..')' - -- Update the edit flow - local edit_flow = task_table['edit-'..task_id] + -- Create local references to the elements for this task + local label_element = name_flow[task_label.name] + local textfield_element = name_flow[task_textfield.name] + + local cancel_edit_element = button_flow[cancel_edit_button.name] + local confirm_edit_element = button_flow[confirm_edit_button.name] + + local edit_task_element = button_flow[edit_task_button.name] + local remove_task_element = button_flow[remove_task_button.name] + + -- Hide the edit button if the player is not allowed to edit the task local player_allowed_edit = check_player_permissions(player, task) local players_editing = table.get_keys(task.currently_editing) - local edit_task_element = edit_flow[edit_task.name] - local discard_task_element = edit_flow[discard_task.name] - edit_task_element.visible = player_allowed_edit - discard_task_element.visible = player_allowed_edit + remove_task_element.visible = player_allowed_edit + if #players_editing > 0 then edit_task_element.hovered_sprite = 'utility/warning_icon' edit_task_element.tooltip = {'task-list.edit-tooltip', table.concat(players_editing, ', ')} @@ -254,33 +275,39 @@ local function update_task(player, task_table, task_id) edit_task_element.tooltip = {'task-list.edit-tooltip-none'} end - -- Check if the player is was editing and/or currently editing - local task_entry = task_flow[task_editing.name] or task_label(task_flow, task) - local player_was_editing = task_entry.type == 'textfield' + -- Check if the player is editing the task local player_is_editing = task.currently_editing[player.name] - -- Update the task flow - if not player_was_editing and not player_is_editing then - -- Update the task message label - local message = task.message + if player_is_editing then + -- Set the name elements visibility + label_element.visible = false + textfield_element.visible = true + textfield_element.focus() + task_table.parent.scroll_to_element(textfield_element, 'top-third') + + -- Set the edit buttons + cancel_edit_element.visible = true + confirm_edit_element.visible = true + -- Set the task buttons + edit_task_element.visible = false + remove_task_element.visible = false + else + -- Set the name elements visibility + label_element.visible = true + label_element.caption = task.message local last_edit_name = task.last_edit_name local last_edit_time = task.last_edit_time - task_entry.caption = message - task_entry.tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)} - - elseif player_was_editing and not player_is_editing then - -- Player was editing but is no longer, remove text field and add label - edit_task_element.enabled = true - task_flow.clear() - task_label(task_flow, task) - - elseif not player_was_editing and player_is_editing then - -- Player was not editing but now is, remove label and add text field - edit_task_element.enabled = false - task_flow.clear() - task_editing(task_flow, task).focus() - task_table.parent.scroll_to_element(task_flow, 'top-third') + label_element.tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)} + textfield_element.visible = false + textfield_element.focus() + task_table.parent.scroll_to_element(textfield_element, 'top-third') + -- Set the edit buttons + cancel_edit_element.visible = false + confirm_edit_element.visible = false + -- Set the task buttons + edit_task_element.visible = true and player_allowed_edit + remove_task_element.visible = true and player_allowed_edit end end @@ -299,7 +326,7 @@ end local task_list_container = Gui.element(function(event_trigger, parent) -- Draw the internal container - local container = Gui.container(parent, event_trigger, 200) + local container = Gui.container(parent, event_trigger, 230) -- Draw the header local header = Gui.header( @@ -316,6 +343,7 @@ Gui.element(function(event_trigger, parent) -- Draw the scroll table for the tasks local scroll_table = Gui.scroll_table(container, 190, 3) + scroll_table.parent.vertical_scroll_policy = 'always' scroll_table.draw_horizontal_lines = true scroll_table.vertical_centering = false @@ -334,9 +362,9 @@ Gui.element(function(event_trigger, parent) -- Change the style of the no tasks label local no_tasks_style = no_tasks_label.style - no_tasks_style.padding = {2, 4} - no_tasks_style.single_line = false - no_tasks_style.width = 200 + no_tasks_style.padding = {4, 4} + no_tasks_style.single_line = true + no_tasks_style.horizontally_stretchable = true -- Add any existing tasks local task_ids = Tasks.get_force_task_ids(player.force.name) From 84159a743a14d25a3af5da5bb4f9d7b427a2155d Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 24 Jan 2021 02:39:20 +0000 Subject: [PATCH 02/56] Bumped lua action to v8 --- .github/workflows/dev-deploy.yml | 2 +- .github/workflows/pr-checker.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-deploy.yml b/.github/workflows/dev-deploy.yml index 418d1360..f1d49189 100644 --- a/.github/workflows/dev-deploy.yml +++ b/.github/workflows/dev-deploy.yml @@ -18,7 +18,7 @@ jobs: fetch-depth: 0 - name: Install Lua - uses: leafo/gh-actions-lua@v5 + uses: leafo/gh-actions-lua@v8.0.0 - name: Install LuaRocks uses: leafo/gh-actions-luarocks@v2 diff --git a/.github/workflows/pr-checker.yml b/.github/workflows/pr-checker.yml index 77e50408..f2277cd5 100644 --- a/.github/workflows/pr-checker.yml +++ b/.github/workflows/pr-checker.yml @@ -28,7 +28,7 @@ jobs: fetch-depth: 0 - name: Install Lua - uses: leafo/gh-actions-lua@v5 + uses: leafo/gh-actions-lua@v8.0.0 - name: Install LuaRocks uses: leafo/gh-actions-luarocks@v2 From 2bdc1ff8b0ea9065291aaf13553948996990c375 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 24 Jan 2021 02:56:49 +0000 Subject: [PATCH 03/56] Bumped luarocks action to v4 --- .github/workflows/dev-deploy.yml | 2 +- .github/workflows/pr-checker.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-deploy.yml b/.github/workflows/dev-deploy.yml index f1d49189..d1773da3 100644 --- a/.github/workflows/dev-deploy.yml +++ b/.github/workflows/dev-deploy.yml @@ -21,7 +21,7 @@ jobs: uses: leafo/gh-actions-lua@v8.0.0 - name: Install LuaRocks - uses: leafo/gh-actions-luarocks@v2 + uses: leafo/gh-actions-luarocks@v4 - name: Install LDoc run: luarocks install ldoc 1.4.4-1 diff --git a/.github/workflows/pr-checker.yml b/.github/workflows/pr-checker.yml index f2277cd5..aaf4242a 100644 --- a/.github/workflows/pr-checker.yml +++ b/.github/workflows/pr-checker.yml @@ -31,7 +31,7 @@ jobs: uses: leafo/gh-actions-lua@v8.0.0 - name: Install LuaRocks - uses: leafo/gh-actions-luarocks@v2 + uses: leafo/gh-actions-luarocks@v4 - name: Install LDoc run: luarocks install ldoc 1.4.4-1 From 8a652648406fe7b9f1fab9563f9036cc76aabd58 Mon Sep 17 00:00:00 2001 From: bbassie Date: Wed, 27 Jan 2021 01:11:33 +0100 Subject: [PATCH 04/56] Task list styling fixes: * Ported over textbox styles to make it strechable. * Fixed the label to allow multi line and not create weird empty areas below the table. * Fixed cell padding to be better spaced, may need more fine tuning. --- modules/gui/task-list.lua | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index 335f2516..d1438cbd 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -87,8 +87,16 @@ Gui.element(function(event_trigger, parent, task) return element end) :style{ - maximal_width = 131, - height = 20 + -- Needed fields to make it squashable and strechable. + minimal_width = 10, + maximal_width = 300, + horizontally_squashable = "on", + horizontally_stretchable = "on", + -- Other styling + height = 22, + padding = -2, + left_margin = 2, + right_margin = 2, } :on_confirmed(function(player, element, _) local task_id = element.parent.name @@ -113,7 +121,7 @@ Gui.element(function(event_trigger, parent, task) end) :style{ single_line = false, - maximal_width = 150, + vertically_stretchable = true, horizontally_stretchable = true } @@ -196,7 +204,7 @@ Gui.element(function(_, parent, task) type = 'label', caption = '#)' } - task_number.style.left_margin = 1 + task_number.style.padding = 0 -- Add name flow this will contain the task label and textbox local task_flow = parent.add{ @@ -326,7 +334,7 @@ end local task_list_container = Gui.element(function(event_trigger, parent) -- Draw the internal container - local container = Gui.container(parent, event_trigger, 230) + local container = Gui.container(parent, event_trigger, 268) -- Draw the header local header = Gui.header( @@ -343,14 +351,15 @@ Gui.element(function(event_trigger, parent) -- Draw the scroll table for the tasks local scroll_table = Gui.scroll_table(container, 190, 3) + -- Set the scroll panel to always show the scrollbar (not doing this will result in a changing gui size) scroll_table.parent.vertical_scroll_policy = 'always' scroll_table.draw_horizontal_lines = true scroll_table.vertical_centering = false -- Change the style of the scroll table local scroll_table_style = scroll_table.style - scroll_table_style.top_cell_padding = 3 - scroll_table_style.bottom_cell_padding = 3 + scroll_table_style.top_cell_padding = 2 + scroll_table_style.bottom_cell_padding = 4 -- Draw the no tasks label local no_tasks_label = From 1042fe637964ba96dda8351ebc527a43341f227f Mon Sep 17 00:00:00 2001 From: bbassie Date: Wed, 27 Jan 2021 22:13:03 +0100 Subject: [PATCH 05/56] Make number bold --- modules/gui/task-list.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index d1438cbd..7281f9ed 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -205,6 +205,7 @@ Gui.element(function(_, parent, task) caption = '#)' } task_number.style.padding = 0 + task_number.style.font = 'default-semibold' -- Add name flow this will contain the task label and textbox local task_flow = parent.add{ From 57434f4b68a8a092d96cf2991f9064d00ded3226 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Wed, 31 Mar 2021 00:43:57 +0100 Subject: [PATCH 06/56] Added spectate control --- modules/control/spectate.lua | 146 +++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 modules/control/spectate.lua diff --git a/modules/control/spectate.lua b/modules/control/spectate.lua new file mode 100644 index 00000000..25354854 --- /dev/null +++ b/modules/control/spectate.lua @@ -0,0 +1,146 @@ + +local Event = require 'utils.event' --- @dep utils.event +local Global = require 'utils.global' --- @dep utils.global +local Gui = require 'expcore.gui' --- @dep expcore.gui + +----- Locals ----- +local follow_label -- Gui constructor +local following = {} +local spectating = {} +local Public = {} + +----- Global data ----- +Global.register({ + following = following, + spectating = spectating +}, function(tbl) + following = tbl.following + spectating = tbl.spectating +end) + +----- Public Functions ----- + +--- Puts a player into spectator while maintaining an association to their character +-- @tparam LuaPlayer player The player that will be placed into spectator +-- @treturn boolean Returns false if the player was already in spectator +function Public.start_spectate(player) + assert(player and player.valid, 'Invalid player given to follower') + if spectating[player.index] or not player.character then return false end + local character = player.character + player.set_controller{ type = defines.controllers.spectator } + player.associate_character(character) + spectating[player.index] = character + return true +end + +--- Return a player from spectator back to their character, if the character was killed then respawn the character +-- @tparam LuaPlayer player The player that will leave spectator +function Public.stop_spectate(player) + assert(player and player.valid, 'Invalid player given to follower') + local character = spectating[player.index] + spectating[player.index] = nil + if character and character.valid then + player.teleport(character.position, character.surface) + player.set_controller{ type = defines.controllers.character, character = character } + else + player.ticks_to_respawn = 300 + end +end + +--- Puts a player into spectator and follows an entity as it moves +-- @tparam LuaPlayer player The player that will follow the entity +-- @tparam ?LuaPlayer|LuaEntity entity The player or entity that will be followed +function Public.start_follow(player, entity) + assert(player and player.valid, 'Invalid player given to follower') + assert(entity and entity.valid, 'Invalid entity given to follower') + local spectate = Public.start_spectate(player) + + player.close_map() + follow_label(player.gui.screen, entity) + player.teleport(entity.position, entity.surface) + following[player.index] = { player, entity, entity.position, spectate } +end + +--- Stops a player from following their current entity, can also return a player from spectate +-- @tparam LuaPlayer player The player that you want to stop following their entity +function Public.stop_follow(player) + assert(player and player.valid, 'Invalid player given to follower') + if following[player.index] and following[player.index][4] then Public.stop_spectate(player) end + + Gui.destroy_if_valid(player.gui.screen[follow_label.name]) + following[player.index] = nil +end + +--- Used to stop all players following an entity or player +function Public.stop_all() + for key, data in pairs(following) do + Public.stop_follow(data[1]) + end +end + +----- Gui ----- + +--- Label used to show that the player is following, also used to allow esc to stop following +-- @element follow_label +follow_label = +Gui.element(function(event_trigger, parent, target) + Gui.destroy_if_valid(parent[event_trigger]) + + local label = parent.add{ + name = event_trigger, + type = 'label', + style = 'heading_1_label', + caption = 'Following '..target.name..'.\nClick here or press esc to stop following.' + } + + local player = Gui.get_player_from_element(parent) + local res = player.display_resolution + label.location = {0, res.height-150} + label.style.width = res.width + label.style.horizontal_align = 'center' + player.opened = label + + return label +end) +:on_close(Public.stop_follow) +:on_click(Public.stop_follow) + +----- Events ----- + +--- Updates the location of the player as well as doing some sanity checks +-- @tparam LuaPlayer player The player to update the position of +-- @tparam ?LuaPlayer|LuaEntity entity The player or entity being followed +local function update_player_location(player, entity, old_position) + if player.character or not entity.valid then + Public.stop_follow(player) + elseif player.position.x ~= old_position.x or player.position.y ~= old_position.y then + Public.stop_follow(player) + else + player.teleport(entity.position, entity.surface) + end +end + +--- Updates the locations of all players currently following something +local function update_all() + for _, data in pairs(following) do + update_player_location(data[1], data[2], data[3]) + data[3] = data[1].position + end +end + +-- Update the location of all players each tick +Event.add(defines.events.on_tick, update_all) + +-- Check for player leaving +Event.add(defines.events.on_player_left_game, function(event) + local player = game.players[event.player_index] + Public.stop_follow(player) + for _, data in pairs(following) do + if data[2] == player then + Public.stop_follow(data[1]) + end + end +end) + +----- Module Return ----- +return Public \ No newline at end of file From f56eb4c145e73c07162165cfd16fb09d976a9b78 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Wed, 31 Mar 2021 01:06:57 +0100 Subject: [PATCH 07/56] Added spectate commands --- config/_file_loader.lua | 1 + config/expcore/roles.lua | 4 ++++ locale/en/commands.cfg | 5 ++++- modules/commands/spectate.lua | 33 +++++++++++++++++++++++++++++++++ modules/control/spectate.lua | 16 ++++++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 modules/commands/spectate.lua diff --git a/config/_file_loader.lua b/config/_file_loader.lua index 16a135af..f42a33d7 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.spectate', --- Addons 'modules.addons.chat-popups', diff --git a/config/expcore/roles.lua b/config/expcore/roles.lua index 9b826202..62932b07 100644 --- a/config/expcore/roles.lua +++ b/config/expcore/roles.lua @@ -102,6 +102,8 @@ Roles.new_role('Trainee','TrMod') 'command/unjail', 'command/kick', 'command/ban', + 'command/spectate', + 'command/follow', } --- Trusted Roles @@ -115,6 +117,8 @@ Roles.new_role('Board Member','Board') :allow{ 'command/goto', 'command/repair', + 'command/spectate', + 'command/follow', } Roles.new_role('Senior Backer','Backer') diff --git a/locale/en/commands.cfg b/locale/en/commands.cfg index dea7b935..c2f91450 100644 --- a/locale/en/commands.cfg +++ b/locale/en/commands.cfg @@ -82,4 +82,7 @@ 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-spectate] +follow-self=You can not follow your self \ No newline at end of file diff --git a/modules/commands/spectate.lua b/modules/commands/spectate.lua new file mode 100644 index 00000000..51f28bd3 --- /dev/null +++ b/modules/commands/spectate.lua @@ -0,0 +1,33 @@ +--[[-- Commands Module - Spectate + - Adds a commands relating to spectate and follow + @commands Spectate +]] + +local Spectate = require 'modules.control.spectate' --- @dep modules.control.spectate +local Commands = require 'expcore.commands' --- @dep expcore.commands +require 'config.expcore.command_general_parse' + +--- Toggles spectator mode for the caller +-- @command spectate +Commands.new_command('spectate', 'Toggles spectator mode') +:register(function(player) + if Spectate.is_spectating(player) then + Spectate.stop_spectate(player) + else + Spectate.start_spectate(player) + end +end) + +--- Enters follow mode for the caller, following the given player. +-- @command follow +-- @tparam LuaPlayer player The player that will be followed +Commands.new_command('follow', 'Start following a player in spectator') +:add_alias('f') +:add_param('player', false, 'player-online') +:register(function(player, action_player) + if player == action_player then + return Commands.error{'expcom-spectate.follow-self'} + else + Spectate.start_follow(player, action_player) + end +end) \ No newline at end of file diff --git a/modules/control/spectate.lua b/modules/control/spectate.lua index 25354854..d9320ae7 100644 --- a/modules/control/spectate.lua +++ b/modules/control/spectate.lua @@ -20,6 +20,14 @@ end) ----- Public Functions ----- +--- Test if a player is in spectator mode +-- @tparam LuaPlayer player The player to test the controller type of +-- @treturn boolean True if the player is in spectator mode +function Public.is_spectating(player) + assert(player and player.valid, 'Invalid player given to follower') + return player.controller_type == defines.controllers.spectator +end + --- Puts a player into spectator while maintaining an association to their character -- @tparam LuaPlayer player The player that will be placed into spectator -- @treturn boolean Returns false if the player was already in spectator @@ -47,6 +55,14 @@ function Public.stop_spectate(player) end end +--- Test if a player is in follow mode +-- @tparam LuaPlayer player The player to test the follow mode of +-- @treturn boolean True if the player is in follow mode +function Public.is_following(player) + assert(player and player.valid, 'Invalid player given to follower') + return following[player.index] ~= nil +end + --- Puts a player into spectator and follows an entity as it moves -- @tparam LuaPlayer player The player that will follow the entity -- @tparam ?LuaPlayer|LuaEntity entity The player or entity that will be followed From 3d9c7e3400b6ac775f5641003f65b48f625f6aad Mon Sep 17 00:00:00 2001 From: bbassie Date: Sat, 10 Apr 2021 21:30:29 +0200 Subject: [PATCH 08/56] Task list redesign - Redesigned the gui - Added / changed locales where needed --- locale/en/gui.cfg | 21 +- modules/gui/task-list.lua | 938 +++++++++++++++++++++++--------------- 2 files changed, 586 insertions(+), 373 deletions(-) diff --git a/locale/en/gui.cfg b/locale/en/gui.cfg index e4fa8611..41338c23 100644 --- a/locale/en/gui.cfg +++ b/locale/en/gui.cfg @@ -69,18 +69,25 @@ net-tooltip=Total net: __1__ no-packs=You have not made any science packs yet [task-list] -main-caption=Task List +main-caption=Task List [img=info] main-tooltip=Task List -sub-tooltip=Tasks that remain to be done -no-tasks=You have no tasks +sub-tooltip=Tasks that remain to be done\n- You can use richtext to include images [img=utility/not_enough_repair_packs_icon] or [color=blue]color[/color] your tasks. +no-tasks=No tasks found! +no-tasks-tooltip=Click on the plus button to the top right of this window to add a new task! last-edit=Last edited by __1__ at __2__ add-tooltip=Add new task -confirm-tooltip=Save changes -cancel-tooltip=Discard changes +confirm=Confirm +confirm-tooltip=Save task +discard=Discard +discard-tooltip=Discard task/changes +close=Close +close-tooltip=Close task details +edit=Edit task edit-tooltip=Currently being edited by: __1__ edit-tooltip-none=Currently being edited by: Nobody -discard-tooltip=Remove task - +create-footer-header=Create task +edit-footer-header=Edit task +view-footer-header=Task details [autofill] main-tooltip=Autofill settings toggle-section-caption=__1__ __2__ diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index 7281f9ed..21606601 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -3,17 +3,37 @@ @gui Task-List @alias task_list ]] - -local Gui = require 'expcore.gui' --- @dep expcore.gui -local Event = require 'utils.event' --- @dep utils.event -local Roles = require 'expcore.roles' --- @dep expcore.roles -local config = require 'config.gui.tasks' --- @dep config.gui.tasks -local Tasks = require 'modules.control.tasks' --- @dep modules.control.tasks +local Gui = require "expcore.gui" --- @dep expcore.gui +local Event = require "utils.event" --- @dep utils.event +local Roles = require "expcore.roles" --- @dep expcore.roles +local Datastore = require "expcore.datastore" --- @dep expcore.datastore +local config = require "config.gui.tasks" --- @dep config.gui.tasks +local Tasks = require "modules.control.tasks" --- @dep modules.control.tasks local format_time = _C.format_time --- @dep expcore.common +--- Stores all data for the task gui by player +local TaskGuiData = Datastore.connect("TaskGuiData") +TaskGuiData:set_serializer(Datastore.name_serializer) +local PlayerIsEditing = TaskGuiData:combine("PlayerIsEditing") +PlayerIsEditing:set_default(false) +local PlayerIsCreating = TaskGuiData:combine("PlayerIsCreating") +PlayerIsCreating:set_default(false) +local PlayerSelected = TaskGuiData:combine("PlayerSelected") +PlayerSelected:set_default(nil) + -- Styles used for sprite buttons local Styles = { - sprite22 = { height = 22, width = 22, padding = -2 }, + sprite22 = { + height = 22, + width = 22, + padding = -2 + }, + footer_button = { + height = 22, + maximal_width = 268, + horizontally_stretchable = true, + padding = -2 + } } --- If a player is allowed to use the edit buttons @@ -28,11 +48,11 @@ local function check_player_permissions(player, task) end -- Check player has permisison based on value in the config - if allow_edit_task == 'all' then + if allow_edit_task == "all" then return true - elseif allow_edit_task == 'admin' then + elseif allow_edit_task == "admin" then return player.admin - elseif allow_edit_task == 'expcore.roles' then + elseif allow_edit_task == "expcore.roles" then return Roles.player_allowed(player, config.expcore_roles_allow_edit_task) end @@ -43,11 +63,11 @@ local function check_player_permissions(player, task) local allow_add_task = config.allow_add_task -- Check player has permisison based on value in the config - if allow_add_task == 'all' then + if allow_add_task == "all" then return true - elseif allow_add_task == 'admin' then + elseif allow_add_task == "admin" then return player.admin - elseif allow_add_task == 'expcore.roles' then + elseif allow_add_task == "expcore.roles" then return Roles.player_allowed(player, config.expcore_roles_allow_add_task) end @@ -56,399 +76,585 @@ local function check_player_permissions(player, task) end end ---- Button displayed in the ehader bar, used to add a new task +--- Elements + +--- Button displayed in the header bar, used to add a new task -- @element add_new_task local add_new_task = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/add', - tooltip = {'task-list.add-tooltip'}, - style = 'tool_button' -} -:style(Styles.sprite22) -:on_click(function(player, _,_) - Tasks.add_task(player.force.name, player.name) -end) - ---- Editing state for a task, contrins a text field and the two edit buttons --- @element task_editing -local task_textfield = -Gui.element(function(event_trigger, parent, task) - -- Draw the element - local element = - parent.add{ - name = event_trigger, - type = 'textfield', - text = task.message, - clear_and_focus_on_right_click = true - } - - -- Return the element - return element -end) -:style{ - -- Needed fields to make it squashable and strechable. - minimal_width = 10, - maximal_width = 300, - horizontally_squashable = "on", - horizontally_stretchable = "on", - -- Other styling - height = 22, - padding = -2, - left_margin = 2, - right_margin = 2, -} -:on_confirmed(function(player, element, _) - local task_id = element.parent.name - local new_message = element.text - Tasks.set_editing(task_id, player.name) - Tasks.update_task(task_id, new_message, player.name) -end) - ---- Default state for a task, contains only a label with the task message --- @element task_label -local task_label = -Gui.element(function(event_trigger, parent, task) - local last_edit_name = task.last_edit_name - local last_edit_time = task.last_edit_time - -- Draw the element - return parent.add{ - name = event_trigger, - type = 'label', - caption = task.message, - tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)} - } -end) -:style{ - single_line = false, - vertically_stretchable = true, - horizontally_stretchable = true -} - ---- Button displayed next to tasks which the user is can edit, used to start editing a task --- @element edit_task_button -local edit_task_button = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/rename_icon_normal', - tooltip = {'task-list.edit-tooltip-none'}, - style = 'shortcut_bar_button' -} -:style(Styles.sprite22) -:on_click(function(player, element, _) - local task_id = element.parent.caption - Tasks.set_editing(task_id, player.name, true) -end) - ---- Button displayed next to tasks which the user is can edit, used to remove a task from the list --- @element remove_task_button -local remove_task_button = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/trash', - tooltip = {'task-list.discard-tooltip'}, - style = 'shortcut_bar_button_red' -} -:style(Styles.sprite22) -:on_click(function(_, element, _) - local task_id = element.parent.caption - Tasks.remove_task(task_id) -end) - --- Removes the three elements that are added as part of the task base -local function remove_task_base(parent, task_id) - Gui.destroy_if_valid(parent['count-'..task_id]) - Gui.destroy_if_valid(parent['name-'..task_id]) - Gui.destroy_if_valid(parent['button-'..task_id]) -end - ---- Button displayed next to tasks which the user is currently editing, used to save changes --- @element confirm_edit_button -local confirm_edit_button = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/confirm_slot', - tooltip = {'task-list.confirm-tooltip'}, - style = 'shortcut_bar_button_green' -} -:style(Styles.sprite22) -:on_click(function(player, element, _) - local task_id = element.parent.caption - local new_message = element.parent.parent['name-'..task_id][task_textfield.name].text - Tasks.set_editing(task_id, player.name) - Tasks.update_task(task_id, new_message, player.name) -end) - ---- Button displayed next to tasks which the user is currently editing, used to cancel changes --- @element cancel_edit_button -local cancel_edit_button = -Gui.element{ - type = 'sprite-button', - sprite = 'utility/close_black', - tooltip = {'task-list.cancel-tooltip'}, - style = 'shortcut_bar_button_red' -} -:style(Styles.sprite22) -:on_click(function(player, element, _) - local task_id = element.parent.caption - Tasks.set_editing(task_id, player.name) -end) - ---- Set of three elements which make up each row of the task table --- @element add_task_elements -local add_task_elements = -Gui.element(function(_, parent, task) - -- Add the task number label - local task_number = parent.add{ - name = 'count-'..task.task_id, - type = 'label', - caption = '#)' - } - task_number.style.padding = 0 - task_number.style.font = 'default-semibold' - - -- Add name flow this will contain the task label and textbox - local task_flow = parent.add{ - name = 'name-'..task.task_id, - type = 'flow', - caption = task.task_id, - } - task_flow.style.padding = 0 - - -- Add the label and textfield of the task - task_label(task_flow, task) - task_textfield(task_flow, task) - - -- Add button flow this will contain buttons to manage this specific task - local button_flow = parent.add{ - name = 'button-'..task.task_id, - type = 'flow', - caption = task.task_id, - } - button_flow.style.padding = 0 - - -- Add both edit state buttons - cancel_edit_button(button_flow) - confirm_edit_button(button_flow) - edit_task_button(button_flow) - remove_task_button(button_flow) - - -- Return the task flow as the main element - return { task_flow, button_flow } -end) - ---- Updates a task for a player -local function update_task(player, task_table, task_id) - local task = Tasks.get_task(task_id) - local task_ids = Tasks.get_force_task_ids(player.force.name) - local task_number = table.get_index(task_ids, task_id) - - -- Task no longer exists so should be removed from the list - if not task then - task_table.parent.no_tasks.visible = #task_ids == 0 - remove_task_base(task_table, task_id) - return + Gui.element { + type = "sprite-button", + sprite = "utility/add", + tooltip = {"task-list.add-tooltip"}, + style = "tool_button" +}:style(Styles.sprite22):on_click( + function(player, _, _) + -- Disable editing + PlayerIsEditing:set(player, false) + -- Clear selected + PlayerSelected:set(player, nil) + -- Open create task footer + PlayerIsCreating:set(player, true) end +) - -- Get the task flow for this task - if not task_table['name-'..task_id] then - add_task_elements(task_table, task) +--- Header displayed when no tasks are in the task list +-- @element no_tasks_found +local no_tasks_found = + Gui.element( + function(_, parent) + local header = + parent.add { + name = "no_tasks_found_element", + type = "frame", + style = "negative_subheader_frame" + } + header.style.horizontally_stretchable = true + -- Flow used for centering the content in the subheader + local center = + header.add { + type = "flow", + style = "centering_horizontal_flow" + } + center.style.horizontally_stretchable = true + center.add { + name = "header_label", + type = "label", + style = "bold_label", + caption = {"", "[img=utility/warning_white] ", {"task-list.no-tasks"}}, + tooltip = "Add task" + } + return header end - local count_flow = task_table['count-'..task_id] - local name_flow = task_table['name-'..task_id] - local button_flow = task_table['button-'..task_id] - task_table.parent.no_tasks.visible = false - count_flow.caption = task_number..')' +) - -- Create local references to the elements for this task - local label_element = name_flow[task_label.name] - local textfield_element = name_flow[task_textfield.name] - - local cancel_edit_element = button_flow[cancel_edit_button.name] - local confirm_edit_element = button_flow[confirm_edit_button.name] - - local edit_task_element = button_flow[edit_task_button.name] - local remove_task_element = button_flow[remove_task_button.name] - - -- Hide the edit button if the player is not allowed to edit the task - local player_allowed_edit = check_player_permissions(player, task) - local players_editing = table.get_keys(task.currently_editing) - edit_task_element.visible = player_allowed_edit - remove_task_element.visible = player_allowed_edit - - if #players_editing > 0 then - edit_task_element.hovered_sprite = 'utility/warning_icon' - edit_task_element.tooltip = {'task-list.edit-tooltip', table.concat(players_editing, ', ')} - else - edit_task_element.hovered_sprite = edit_task_element.sprite - edit_task_element.tooltip = {'task-list.edit-tooltip-none'} +local subfooter_frame = + Gui.element( + function(_, parent, name) + return parent.add { + type = "frame", + name = name, + direction = "vertical", + style = "subfooter_frame" + } end - - -- Check if the player is editing the task - local player_is_editing = task.currently_editing[player.name] - - if player_is_editing then - -- Set the name elements visibility - label_element.visible = false - textfield_element.visible = true - textfield_element.focus() - task_table.parent.scroll_to_element(textfield_element, 'top-third') - - -- Set the edit buttons - cancel_edit_element.visible = true - confirm_edit_element.visible = true - -- Set the task buttons - edit_task_element.visible = false - remove_task_element.visible = false - else - -- Set the name elements visibility - label_element.visible = true - label_element.caption = task.message - local last_edit_name = task.last_edit_name - local last_edit_time = task.last_edit_time - label_element.tooltip = {'task-list.last-edit', last_edit_name, format_time(last_edit_time)} - textfield_element.visible = false - textfield_element.focus() - task_table.parent.scroll_to_element(textfield_element, 'top-third') - - -- Set the edit buttons - cancel_edit_element.visible = false - confirm_edit_element.visible = false - -- Set the task buttons - edit_task_element.visible = true and player_allowed_edit - remove_task_element.visible = true and player_allowed_edit +):style( + { + padding = 5, + use_header_filler = false, + horizontally_stretchable = true + } +) +local subfooter_label = + Gui.element( + function(_, parent, caption) + return parent.add { + name = "footer_label", + type = "label", + style = "heading_1_label", + caption = caption + } end -end +) +local subfooter_actions = + Gui.element( + function(_, parent) + return parent.add { + type = "flow", + name = "actions" + } + end +) --- Update all the tasks for a player -local function update_all_tasks(player, scroll_table) - local task_ids = Tasks.get_force_task_ids(player.force.name) - if #task_ids > 0 then - for _, task_id in ipairs(task_ids) do - update_task(player, scroll_table, task_id) +local task_list_item +task_list_item = + Gui.element( + function(event_trigger, parent, task) + local flow = + parent.add { + type = "flow", + name = "task-" .. task.task_id, + caption = task.task_id + } + flow.style.horizontally_stretchable = true + local button = + flow.add { + name = event_trigger, + type = "button", + style = "list_box_item", + caption = task.message + } + button.style.horizontally_stretchable = true + button.style.horizontally_squashable = true + return flow + end +):on_click( + function(player, element, _) + local task_id = element.parent.caption + PlayerSelected:set(player, task_id) + end +) + +--- Scrollable list of all tasks +-- @element no_tasks_found +local task_list = + Gui.element( + function(_, parent) + local scroll_pane = + parent.add { + name = "scroll", + type = "scroll-pane", + direction = "vertical", + horizontal_scroll_policy = "never", + vertical_scroll_policy = "auto", + style = "scroll_pane_under_subheader" + } + scroll_pane.style.horizontally_stretchable = true + scroll_pane.style.padding = 0 + scroll_pane.style.maximal_height = 300 + + local flow = + scroll_pane.add { + name = "task_list", + type = "flow", + direction = "vertical" + } + flow.style.vertical_spacing = 0 + flow.style.horizontally_stretchable = true + + return flow + end +) + +local view_task_edit_button = + Gui.element { + type = "button", + caption = {"", "[img=utility/rename_icon_normal] ", {"task-list.edit"}}, + tooltip = {"task-list.edit-tooltip"}, + style = "shortcut_bar_button" +}:style(Styles.footer_button):on_click( + function(player, _, _) + local selected = PlayerSelected:get(player) + PlayerIsEditing:set(player, true) + + Tasks.set_editing(selected, player.name, true) + end +) +local view_task_close_button = + Gui.element { + type = "button", + caption = {"", "[img=utility/close_black] ", {"task-list.close"}}, + tooltip = {"task-list.close-tooltip"}, + style = "shortcut_bar_button" +}:style(Styles.footer_button):on_click( + function(player, _, _) + PlayerSelected:set(player, nil) + end +) + +local task_view_footer = + Gui.element( + function(_, parent) + local footer = subfooter_frame(parent, "view") + subfooter_label(footer, {"task-list.view-footer-header"}) + + local label = + footer.add { + type = "label", + name = "message", + caption = "New task" + } + label.style.padding = 4 + label.style.single_line = false + + local action_flow = subfooter_actions(footer) + + view_task_edit_button(action_flow) + view_task_close_button(action_flow) + return footer + end +) +local edit_task_confirm_button +local create_task_confirm_button +local task_message_textfield +task_message_textfield = + Gui.element { + type = "textfield", + text = "" +}:style( + { + maximal_width = 268, + horizontally_stretchable = true + } +):on_text_changed( + function(player, element, _) + local isEditing = PlayerIsEditing:get(player) + local isCreating = PlayerIsCreating:get(player) + + local valid = string.len(element.text) > 5 + + if isCreating then + element.parent.actions[create_task_confirm_button.name].enabled = valid + elseif isEditing then + element.parent.actions[edit_task_confirm_button.name].enabled = valid end end -end +):on_confirmed( + function(player, element, _) + local isEditing = PlayerIsEditing:get(player) + local isCreating = PlayerIsCreating:get(player) + + local message = element.text + local valid = string.len(element.text) > 5 + if not valid then + return + end + + if isCreating then + PlayerIsCreating:set(player, false) + + local task_id = Tasks.add_task(player.force.name, player.name, message) + PlayerSelected:set(player, task_id) + elseif isEditing then + local selected = PlayerSelected:get(player) + PlayerIsEditing:set(player, false) + Tasks.update_task(selected, message, player.name) + Tasks.set_editing(selected, player.name, nil) + end + end +) +edit_task_confirm_button = + Gui.element { + type = "button", + caption = {"", "[img=utility/check_mark] ", {"task-list.confirm"}}, + tooltip = {"task-list.confirm-tooltip"}, + style = "shortcut_bar_button_green" +}:style(Styles.footer_button):on_click( + function(player, element, _) + local selected = PlayerSelected:get(player) + PlayerIsEditing:set(player, false) + local new_message = element.parent.parent[task_message_textfield.name].text + Tasks.update_task(selected, new_message, player.name) + Tasks.set_editing(selected, player.name, nil) + end +) +local edit_task_discard_button = + Gui.element { + type = "button", + caption = {"", "[img=utility/close_black] ", {"task-list.discard"}}, + tooltip = {"task-list.discard-tooltip"}, + style = "shortcut_bar_button_red" +}:style(Styles.footer_button):on_click( + function(player, _, _) + local selected = PlayerSelected:get(player) + Tasks.set_editing(selected, player.name, nil) + PlayerIsEditing:set(player, false) + -- Redraw selected + PlayerSelected:set(player, selected) + end +) +local task_edit_footer = + Gui.element( + function(_, parent) + local footer = subfooter_frame(parent, "edit") + subfooter_label(footer, {"task-list.edit-footer-header"}) + + task_message_textfield(footer) + + local action_flow = subfooter_actions(footer) + + edit_task_discard_button(action_flow) + edit_task_confirm_button(action_flow) + + return footer + end +) + +create_task_confirm_button = + Gui.element { + type = "button", + caption = {"", "[img=utility/check_mark] ", {"task-list.confirm"}}, + tooltip = {"task-list.confirm-tooltip"}, + style = "shortcut_bar_button_green", + enabled = false +}:style(Styles.footer_button):on_click( + function(player, element, _) + local message = element.parent.parent[task_message_textfield.name].text + PlayerIsCreating:set(player, false) + + local task_id = Tasks.add_task(player.force.name, player.name, message) + PlayerSelected:set(player, task_id) + end +) +local create_task_discard_button = + Gui.element { + type = "button", + caption = {"", "[img=utility/close_black] ", {"task-list.discard"}}, + tooltip = {"task-list.discard-tooltip"}, + style = "shortcut_bar_button_red" +}:style(Styles.footer_button):on_click( + function(player, _, _) + PlayerIsCreating:set(player, false) + end +) +local task_create_footer = + Gui.element( + function(_, parent) + local footer = subfooter_frame(parent, "create") + subfooter_label(footer, {"task-list.create-footer-header"}) + + task_message_textfield(footer) + + local action_flow = subfooter_actions(footer) + + create_task_discard_button(action_flow) + create_task_confirm_button(action_flow) + + return footer + end +) --- Main task list container for the left flow -- @element task_list_container local task_list_container = -Gui.element(function(event_trigger, parent) - -- Draw the internal container - local container = Gui.container(parent, event_trigger, 268) + Gui.element( + function(event_trigger, parent) + -- Draw the internal container + local container = Gui.container(parent, event_trigger, 268) + container.style.maximal_width = 268 + container.style.minimal_width = 268 - -- Draw the header - local header = Gui.header( - container, - {'task-list.main-caption'}, - {'task-list.sub-tooltip'}, - true - ) + -- Draw the header + local header = Gui.header(container, {"task-list.main-caption"}, {"task-list.sub-tooltip"}, true) - -- Draw the new task button - local player = Gui.get_player_from_element(parent) - local add_new_task_element = add_new_task(header) - add_new_task_element.visible = check_player_permissions(player) + -- Draw the new task button + local player = Gui.get_player_from_element(parent) + local add_new_task_element = add_new_task(header) + add_new_task_element.visible = check_player_permissions(player) - -- Draw the scroll table for the tasks - local scroll_table = Gui.scroll_table(container, 190, 3) - -- Set the scroll panel to always show the scrollbar (not doing this will result in a changing gui size) - scroll_table.parent.vertical_scroll_policy = 'always' - scroll_table.draw_horizontal_lines = true - scroll_table.vertical_centering = false + -- Draw no task found element + no_tasks_found(container) - -- Change the style of the scroll table - local scroll_table_style = scroll_table.style - scroll_table_style.top_cell_padding = 2 - scroll_table_style.bottom_cell_padding = 4 + -- Draw task list element + task_list(container) - -- Draw the no tasks label - local no_tasks_label = - scroll_table.parent.add{ - name = 'no_tasks', - type = 'label', - caption = {'task-list.no-tasks'} - } - - -- Change the style of the no tasks label - local no_tasks_style = no_tasks_label.style - no_tasks_style.padding = {4, 4} - no_tasks_style.single_line = true - no_tasks_style.horizontally_stretchable = true - - -- Add any existing tasks - local task_ids = Tasks.get_force_task_ids(player.force.name) - if #task_ids > 0 then - no_tasks_label.visible = false - for _, task_id in ipairs(task_ids) do - update_task(player, scroll_table, task_id) - end + local task_view_footer_element = task_view_footer(container) + local task_edit_footer_element = task_edit_footer(container) + local task_create_footer_element = task_create_footer(container) + task_view_footer_element.visible = false + task_edit_footer_element.visible = false + task_create_footer_element.visible = false + -- Return the exteral container + return container.parent end - - -- Return the exteral container - return container.parent -end) -:add_to_left_flow(function(player) - local task_ids = Tasks.get_force_task_ids(player.force.name) - return #task_ids > 0 -end) +):add_to_left_flow( + function(player) + local task_ids = Tasks.get_force_task_ids(player.force.name) + return #task_ids > 0 + end +) --- Button on the top flow used to toggle the task list container -- @element toggle_left_element -Gui.left_toolbar_button('utility/not_enough_repair_packs_icon', {'task-list.main-tooltip'}, task_list_container, function(player) - return Roles.player_allowed(player, 'gui/task-list') -end) +Gui.left_toolbar_button( + "utility/not_enough_repair_packs_icon", + {"task-list.main-tooltip"}, + task_list_container, + function(player) + return Roles.player_allowed(player, "gui/task-list") + end +) + +local update_task = function(player, task_list_element, task_id) + local task = Tasks.get_task(task_id) + local task_ids = Tasks.get_force_task_ids(player.force.name) + + -- Task no longer exists so should be removed from the list + if not task then + task_list_element["task-" .. task_id] = nil + return + end + task_list_element.parent.parent.no_tasks_found_element.visible = #task_ids == 0 + + local element + -- If task does not exist yet add it to the list + if not task_list_element["task-" .. task_id] then + element = task_list_item(task_list_element, task) + else + -- If the task exists update the caption + element = task_list_element["task-" .. task_id] + element[task_list_item.name].caption = task.message + end + -- Set tooltip + local last_edit_name = task.last_edit_name + local last_edit_time = task.last_edit_time + element[task_list_item.name].tooltip = {"task-list.last-edit", last_edit_name, format_time(last_edit_time)} +end + +-- Update the footer task edit view +local update_task_edit_footer = function(player, task_id) + local task = Tasks.get_task(task_id) + local frame = Gui.get_left_element(player, task_list_container) + local edit_flow = frame.container.edit + + local message_element = edit_flow[task_message_textfield.name] + + message_element.focus() + message_element.text = task.message +end + +-- Update the footer task view +local update_task_view_footer = function(player, task_id) + local task = Tasks.get_task(task_id) + local frame = Gui.get_left_element(player, task_list_container) + local view_flow = frame.container.view + local has_permission = check_player_permissions(player, task) + + local message_element = view_flow.message + local edit_button_element = view_flow.actions[view_task_edit_button.name] + + edit_button_element.visible = has_permission + message_element.caption = task.message + + local players_editing = table.get_keys(task.currently_editing) + if #players_editing > 0 then + -- edit_task_element.hovered_sprite = 'utility/warning_icon' + edit_button_element.tooltip = {"task-list.edit-tooltip", table.concat(players_editing, ", ")} + else + -- edit_task_element.hovered_sprite = edit_task_element.sprite + edit_button_element.tooltip = {"task-list.edit-tooltip-none"} + end +end --- When a new task is added it will update the task list for everyone on that force -Tasks.on_update(function(task_id, task, old_task) - -- Get the force to update, task is nil when removed - local force - if task then - force = game.forces[task.force_name] - else - force = game.forces[old_task.force_name] - end +Tasks.on_update( + function(task_id, task, old_task) + -- Get the force to update, task is nil when removed + local force + if task then + force = game.forces[task.force_name] + else + force = game.forces[old_task.force_name] + end - -- Update the task for all the players on the force - local task_ids = Tasks.get_force_task_ids(force.name) - for _, player in pairs(force.connected_players) do - local frame = Gui.get_left_element(player, task_list_container) - local scroll_table = frame.container.scroll.table - - -- Update the task that was changed - update_task(player, scroll_table, task_id) - - -- Update the numbering of the other tasks if the task was removed - if not task then - for task_number, next_task_id in pairs(task_ids) do - scroll_table['count-'..next_task_id].caption = task_number..')' + -- Update the task for all the players on the force + for _, player in pairs(force.connected_players) do + -- Update the task view if the player has the changed task selected + local selected = PlayerSelected:get(player) + if selected == task_id then + update_task_view_footer(player, selected) end + + local frame = Gui.get_left_element(player, task_list_container) + local task_list_element = frame.container.scroll.task_list + + -- Update the task that was changed + update_task(player, task_list_element, task_id) end end +) -end) +PlayerIsCreating:on_update( + function(player_name, new_state, _) + local player = game.players[player_name] ---- Update the tasks when the player joins -Event.add(defines.events.on_player_joined_game, function(event) - local player = game.players[event.player_index] - local frame = Gui.get_left_element(player, task_list_container) - local scroll_table = frame.container.scroll.table - update_all_tasks(player, scroll_table) -end) + local frame = Gui.get_left_element(player, task_list_container) + local create = frame.container.create + + -- Clear the textfield + frame.container.create[task_message_textfield.name].text = "" + frame.container.create.actions[create_task_confirm_button.name].enabled = false + + if new_state then + create.visible = true + else + create.visible = false + end + end +) + +-- When a player selects a different warp from the list +PlayerSelected:on_update( + function(player_name, new_state, old_state) + local player = game.players[player_name] + + local frame = Gui.get_left_element(player, task_list_container) + local task_list_element = frame.container.scroll.task_list + local view_flow = frame.container.view + local edit_flow = frame.container.edit + local isEditing = PlayerIsEditing:get(player) + + if old_state then + task_list_element["task-" .. old_state][task_list_item.name].enabled = true + end + + if new_state then + task_list_element["task-" .. new_state][task_list_item.name].enabled = false + + update_task_view_footer(player, new_state) + + if isEditing then + update_task_edit_footer(player, new_state) + Tasks.set_editing(old_state, player.name, nil) + Tasks.set_editing(new_state, player.name, true) + view_flow.visible = false + edit_flow.visible = true + else + view_flow.visible = true + edit_flow.visible = false + end + else + -- If new state nil then hide footer elements and set editing to nil for old_state + if old_state then + Tasks.set_editing(old_state, player.name, nil) + end + view_flow.visible = false + edit_flow.visible = false + end + end +) + +-- When the edit view opens or closes +PlayerIsEditing:on_update( + function(player_name, new_state, _) + local player = game.players[player_name] + + local frame = Gui.get_left_element(player, task_list_container) + local view_flow = frame.container.view + local edit_flow = frame.container.edit + + local selected = PlayerSelected:get(player) + if new_state then + update_task_edit_footer(player, selected) + view_flow.visible = false + edit_flow.visible = true + else + view_flow.visible = true + edit_flow.visible = false + end + end +) --- Makes sure the right buttons are present when roles change local function role_update_event(event) local player = game.players[event.player_index] local container = Gui.get_left_element(player, task_list_container).container - - -- Update the tasks, incase the user can now edit them - local scroll_table = container.scroll.table - update_all_tasks(player, scroll_table) + -- Update the view task + local selected = PlayerSelected:get(player) + if selected then + update_task_view_footer(player, selected) + -- Set selected to the same value, this will make sure if player was in a editing state he will leave it if no permissions. + PlayerSelected:set(selected) + end -- Update the new task button incase the user can now add them + local has_permission = check_player_permissions(player) local add_new_task_element = container.header.alignment[add_new_task.name] - add_new_task_element.visible = check_player_permissions(player) + add_new_task_element.visible = has_permission + local isCreating = PlayerIsCreating:get(player) + if isCreating and not has_permission then + PlayerIsCreating:set(false) + end end Event.add(Roles.events.on_role_assigned, role_update_event) -Event.add(Roles.events.on_role_unassigned, role_update_event) \ No newline at end of file +Event.add(Roles.events.on_role_unassigned, role_update_event) From d853d1c9912b80a9cee18e9e9530a859e0b15ece Mon Sep 17 00:00:00 2001 From: bbassie Date: Sat, 10 Apr 2021 22:13:21 +0200 Subject: [PATCH 09/56] Delete button and some fixes - Add delete task button - Fix update task item - Fix no tasks found visibility and tooltip --- locale/en/gui.cfg | 2 ++ modules/gui/task-list.lua | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/locale/en/gui.cfg b/locale/en/gui.cfg index 41338c23..557253d2 100644 --- a/locale/en/gui.cfg +++ b/locale/en/gui.cfg @@ -80,6 +80,8 @@ confirm=Confirm confirm-tooltip=Save task discard=Discard discard-tooltip=Discard task/changes +delete=Delete +delete-tooltip=Delete task close=Close close-tooltip=Close task details edit=Edit task diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index 21606601..3d7e7ac0 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -121,7 +121,7 @@ local no_tasks_found = type = "label", style = "bold_label", caption = {"", "[img=utility/warning_white] ", {"task-list.no-tasks"}}, - tooltip = "Add task" + tooltip = {"task-list.no-tasks-tooltip"} } return header end @@ -250,6 +250,19 @@ local view_task_close_button = PlayerSelected:set(player, nil) end ) +local view_task_delete_button = + Gui.element { + type = "button", + caption = {"", "[img=utility/trash] ", {"task-list.delete"}}, + tooltip = {"task-list.delete-tooltip"}, + style = "shortcut_bar_button_red" +}:style(Styles.footer_button):on_click( + function(player, _, _) + local selected = PlayerSelected:get(player) + PlayerSelected:set(player, nil) + Tasks.remove_task(selected) + end +) local task_view_footer = Gui.element( @@ -267,7 +280,7 @@ local task_view_footer = label.style.single_line = false local action_flow = subfooter_actions(footer) - + view_task_delete_button(action_flow) view_task_edit_button(action_flow) view_task_close_button(action_flow) return footer @@ -467,13 +480,14 @@ Gui.left_toolbar_button( local update_task = function(player, task_list_element, task_id) local task = Tasks.get_task(task_id) local task_ids = Tasks.get_force_task_ids(player.force.name) + -- Set visibility of the no_tasks_found element + task_list_element.parent.parent.no_tasks_found_element.visible = #task_ids == 0 -- Task no longer exists so should be removed from the list if not task then - task_list_element["task-" .. task_id] = nil + task_list_element["task-" .. task_id].destroy() return end - task_list_element.parent.parent.no_tasks_found_element.visible = #task_ids == 0 local element -- If task does not exist yet add it to the list @@ -511,8 +525,10 @@ local update_task_view_footer = function(player, task_id) local message_element = view_flow.message local edit_button_element = view_flow.actions[view_task_edit_button.name] + local delete_button_element = view_flow.actions[view_task_delete_button.name] edit_button_element.visible = has_permission + delete_button_element.visible = has_permission message_element.caption = task.message local players_editing = table.get_keys(task.currently_editing) From 11296b3b367d6fdfe7b899c97de37b7c1db80470 Mon Sep 17 00:00:00 2001 From: bbassie Date: Sun, 11 Apr 2021 19:54:38 +0200 Subject: [PATCH 10/56] Small improvements - Removed extra redraw that doesn't seem to be needed - Fixed that it would not focus on the create new warp textbox --- modules/gui/task-list.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index 3d7e7ac0..f4c632bd 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -361,8 +361,6 @@ local edit_task_discard_button = local selected = PlayerSelected:get(player) Tasks.set_editing(selected, player.name, nil) PlayerIsEditing:set(player, false) - -- Redraw selected - PlayerSelected:set(player, selected) end ) local task_edit_footer = @@ -577,8 +575,11 @@ PlayerIsCreating:on_update( local create = frame.container.create -- Clear the textfield - frame.container.create[task_message_textfield.name].text = "" - frame.container.create.actions[create_task_confirm_button.name].enabled = false + local message_element = frame.container.create[task_message_textfield.name] + local confirm_button_element = frame.container.create.actions[create_task_confirm_button.name] + message_element.focus() + message_element.text = "" + confirm_button_element.enabled = false if new_state then create.visible = true From 745f10b10d032a35b9144e24f9bfc172b440c0b5 Mon Sep 17 00:00:00 2001 From: bbassie Date: Sun, 11 Apr 2021 20:09:35 +0200 Subject: [PATCH 11/56] Added file and logic comments --- modules/gui/task-list.lua | 58 +++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index f4c632bd..25ab7c86 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -127,6 +127,8 @@ local no_tasks_found = end ) +--- Frame element with the right styling +-- @element subfooter_frame local subfooter_frame = Gui.element( function(_, parent, name) @@ -144,6 +146,9 @@ local subfooter_frame = horizontally_stretchable = true } ) + +--- Label element preset +-- @element subfooter_label local subfooter_label = Gui.element( function(_, parent, caption) @@ -155,6 +160,9 @@ local subfooter_label = } end ) + +--- Action flow that contains action buttons +-- @element subfooter_actions local subfooter_actions = Gui.element( function(_, parent) @@ -165,8 +173,9 @@ local subfooter_actions = end ) -local task_list_item -task_list_item = +--- Button element with a flow around it to fix duplicate name inside of the scroll flow +-- @element task_list_item +local task_list_item = Gui.element( function(event_trigger, parent, task) local flow = @@ -225,6 +234,8 @@ local task_list = end ) +--- Button element inside the task view footer to start editing a task +-- @element view_task_edit_button local view_task_edit_button = Gui.element { type = "button", @@ -239,6 +250,9 @@ local view_task_edit_button = Tasks.set_editing(selected, player.name, true) end ) + +--- Button to close the view task footer +-- @element view_task_close_button local view_task_close_button = Gui.element { type = "button", @@ -250,6 +264,9 @@ local view_task_close_button = PlayerSelected:set(player, nil) end ) + +--- Button to delete the task +-- @element view_task_delete_button local view_task_delete_button = Gui.element { type = "button", @@ -264,6 +281,8 @@ local view_task_delete_button = end ) +--- Subfooter inside the tasklist container +-- @element task_view_footer local task_view_footer = Gui.element( function(_, parent) @@ -286,10 +305,14 @@ local task_view_footer = return footer end ) + +-- Button variable initialisation because it is used inside the textfield element events local edit_task_confirm_button local create_task_confirm_button -local task_message_textfield -task_message_textfield = + +--- Textfield element used in both the create and edit footers +-- @element task_message_textfield +local task_message_textfield = Gui.element { type = "textfield", text = "" @@ -335,6 +358,9 @@ task_message_textfield = end end ) + +--- Button to confirm the changes +-- @element edit_task_confirm_button edit_task_confirm_button = Gui.element { type = "button", @@ -350,6 +376,9 @@ edit_task_confirm_button = Tasks.set_editing(selected, player.name, nil) end ) + +--- Button to discard the changes +-- @element edit_task_discard_button local edit_task_discard_button = Gui.element { type = "button", @@ -363,6 +392,9 @@ local edit_task_discard_button = PlayerIsEditing:set(player, false) end ) + +--- Subfooter inside the tasklist container +-- @element task_edit_footer local task_edit_footer = Gui.element( function(_, parent) @@ -380,6 +412,8 @@ local task_edit_footer = end ) +--- Button to confirm the changes +-- @element create_task_confirm_button create_task_confirm_button = Gui.element { type = "button", @@ -396,6 +430,9 @@ create_task_confirm_button = PlayerSelected:set(player, task_id) end ) + +--- Button to discard the changes +-- @element create_task_discard_button local create_task_discard_button = Gui.element { type = "button", @@ -407,6 +444,9 @@ local create_task_discard_button = PlayerIsCreating:set(player, false) end ) + +--- Subfooter inside the tasklist container +-- @element task_create_footer local task_create_footer = Gui.element( function(_, parent) @@ -475,10 +515,11 @@ Gui.left_toolbar_button( end ) +-- Function to update a single task and some of the elements inside the container local update_task = function(player, task_list_element, task_id) local task = Tasks.get_task(task_id) local task_ids = Tasks.get_force_task_ids(player.force.name) - -- Set visibility of the no_tasks_found element + -- Set visibility of the no_tasks_found element depending on the amount of tasks still in the task manager task_list_element.parent.parent.no_tasks_found_element.visible = #task_ids == 0 -- Task no longer exists so should be removed from the list @@ -567,6 +608,7 @@ Tasks.on_update( end ) +-- When a player is creating a new task. PlayerIsCreating:on_update( function(player_name, new_state, _) local player = game.players[player_name] @@ -600,15 +642,19 @@ PlayerSelected:on_update( local edit_flow = frame.container.edit local isEditing = PlayerIsEditing:get(player) + -- If the selection has a old state re-enable the button list element if old_state then task_list_element["task-" .. old_state][task_list_item.name].enabled = true end if new_state then + -- Disable the selected element task_list_element["task-" .. new_state][task_list_item.name].enabled = false + -- Update the view footer update_task_view_footer(player, new_state) + -- Depending on if the player is currently editing change the current edit session to the new task if isEditing then update_task_edit_footer(player, new_state) Tasks.set_editing(old_state, player.name, nil) @@ -663,7 +709,7 @@ local function role_update_event(event) PlayerSelected:set(selected) end - -- Update the new task button incase the user can now add them + -- Update the new task button and create footer incase the user can now add them local has_permission = check_player_permissions(player) local add_new_task_element = container.header.alignment[add_new_task.name] add_new_task_element.visible = has_permission From 7bbefd67b445720090a4067840d3b49165a62cfc Mon Sep 17 00:00:00 2001 From: bbassie Date: Sun, 11 Apr 2021 23:03:16 +0200 Subject: [PATCH 12/56] Change button size - The icons were clipping --- modules/gui/task-list.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index 25ab7c86..656d5500 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -29,7 +29,7 @@ local Styles = { padding = -2 }, footer_button = { - height = 22, + height = 29, maximal_width = 268, horizontally_stretchable = true, padding = -2 From 465627535b561dbb01bfabf96ec0fa5c6af9c47b Mon Sep 17 00:00:00 2001 From: bbassie Date: Sun, 11 Apr 2021 23:07:07 +0200 Subject: [PATCH 13/56] Change tooltip of the confirm button - Tooltip didn't show usefull information on why you could not confirm --- locale/en/gui.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/en/gui.cfg b/locale/en/gui.cfg index 557253d2..260f1c2e 100644 --- a/locale/en/gui.cfg +++ b/locale/en/gui.cfg @@ -77,7 +77,7 @@ no-tasks-tooltip=Click on the plus button to the top right of this window to add last-edit=Last edited by __1__ at __2__ add-tooltip=Add new task confirm=Confirm -confirm-tooltip=Save task +confirm-tooltip=Save task (minimum of 5 characters long) discard=Discard discard-tooltip=Discard task/changes delete=Delete From eeb9f31b57bfae9fe7b5ff2641a26ba3a0c30055 Mon Sep 17 00:00:00 2001 From: bbassie Date: Wed, 14 Apr 2021 00:24:52 +0200 Subject: [PATCH 14/56] Basic task with title and body implementation - Parsing of the message is a bit low effort and will need to be improved. --- modules/control/tasks.lua | 19 +++++---- modules/gui/task-list.lua | 85 ++++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 43 deletions(-) diff --git a/modules/control/tasks.lua b/modules/control/tasks.lua index 0b319709..0e143725 100644 --- a/modules/control/tasks.lua +++ b/modules/control/tasks.lua @@ -32,17 +32,19 @@ end) --[[-- Add a new task for a force, the task can be placed into a certain position for that force @tparam string force_name the name of the force to add the task for @tparam[opt] string player_name the player who added this task, will cause them to be listed under editing -@tparam[opt] string task_message the message that is used for this task, if not given default is used +@tparam[opt] string task_title the message title that is used for this task, if not given default is used +@tparam[opt] string task_body the message body that is used for this task, if not given default is used @treturn string the uid of the task which was created @usage-- Adding a new task for your force local task_id = Tasks.add_task(game.player.force.name, nil, game.player.name) ]] -function Tasks.add_task(force_name, player_name, task_message) +function Tasks.add_task(force_name, player_name, message_title, message_body) -- Get a new task id local task_id = tostring(force_tasks._uid) - task_message = task_message or 'New Task' + message_title = message_title or 'New Task' + message_body = message_body or 'Do x or y' force_tasks._uid = force_tasks._uid + 1 -- Get the existing tasks for this force @@ -65,7 +67,8 @@ function Tasks.add_task(force_name, player_name, task_message) TaskData:set(task_id, { task_id = task_id, force_name = force_name, - message = task_message, + title = message_title, + body = message_body, last_edit_name = player_name or '', last_edit_time = game.tick, currently_editing = editing @@ -90,18 +93,20 @@ end --[[-- Update the message and last edited information for a task @tparam string task_id the uid of the task that you want to update -@tparam string new_message the message that you want to have for the task +@tparam string message_title the message title that you want to have for the task +@tparam string message_body the message body that you want to have for the task @tparam[opt='server'] string player_name the name of the player who made the edit @usage-- Updating the message for on a task Task.update_task(task_id, 'We need more iron!', game.player.name) ]] -function Tasks.update_task(task_id, new_message, player_name) +function Tasks.update_task(task_id, message_title, message_body, player_name) TaskData:update(task_id, function(_, task) task.last_edit_name = player_name or '' task.last_edit_time = game.tick - task.message = new_message + task.title = message_title + task.body = message_body end) end diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index 656d5500..ecfb7852 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -190,7 +190,7 @@ local task_list_item = name = event_trigger, type = "button", style = "list_box_item", - caption = task.message + caption = task.title } button.style.horizontally_stretchable = true button.style.horizontally_squashable = true @@ -289,14 +289,23 @@ local task_view_footer = local footer = subfooter_frame(parent, "view") subfooter_label(footer, {"task-list.view-footer-header"}) - local label = + local title_label = footer.add { type = "label", - name = "message", + name = "title", caption = "New task" } - label.style.padding = 4 - label.style.single_line = false + title_label.style.padding = 4 + title_label.style.font = "default-bold" + title_label.style.single_line = false + local body_label = + footer.add { + type = "label", + name = "body", + caption = "Do x or y" + } + body_label.style.padding = 4 + body_label.style.single_line = false local action_flow = subfooter_actions(footer) view_task_delete_button(action_flow) @@ -306,6 +315,29 @@ local task_view_footer = end ) +local message_pattern = "(.-)\n(.*)" + +--- Parce a string into a message object with title and body +-- @tparam string str message data +local function parse_message(str) + -- Trimm the spaces of the string + local trimmed = (string.gsub(str, "^%s*(.-)%s*$", "%1")) + local message = { title = "", body = "" } + -- If it doesn't match the patter return the str as a title + local match = string.match(trimmed, message_pattern) + if not match then + message.title = trimmed + return message + end + -- If message has multiple lines + for key, value in string.gmatch(trimmed, message_pattern) do + message.title = key + message.body = value + break + end + return message +end + -- Button variable initialisation because it is used inside the textfield element events local edit_task_confirm_button local create_task_confirm_button @@ -314,11 +346,12 @@ local create_task_confirm_button -- @element task_message_textfield local task_message_textfield = Gui.element { - type = "textfield", + type = "text-box", text = "" }:style( { maximal_width = 268, + minimal_height = 100, horizontally_stretchable = true } ):on_text_changed( @@ -334,29 +367,6 @@ local task_message_textfield = element.parent.actions[edit_task_confirm_button.name].enabled = valid end end -):on_confirmed( - function(player, element, _) - local isEditing = PlayerIsEditing:get(player) - local isCreating = PlayerIsCreating:get(player) - - local message = element.text - local valid = string.len(element.text) > 5 - if not valid then - return - end - - if isCreating then - PlayerIsCreating:set(player, false) - - local task_id = Tasks.add_task(player.force.name, player.name, message) - PlayerSelected:set(player, task_id) - elseif isEditing then - local selected = PlayerSelected:get(player) - PlayerIsEditing:set(player, false) - Tasks.update_task(selected, message, player.name) - Tasks.set_editing(selected, player.name, nil) - end - end ) --- Button to confirm the changes @@ -372,7 +382,8 @@ edit_task_confirm_button = local selected = PlayerSelected:get(player) PlayerIsEditing:set(player, false) local new_message = element.parent.parent[task_message_textfield.name].text - Tasks.update_task(selected, new_message, player.name) + local parsed = parse_message(new_message) + Tasks.update_task(selected, parsed.title, parsed.body, player.name) Tasks.set_editing(selected, player.name, nil) end ) @@ -425,8 +436,8 @@ create_task_confirm_button = function(player, element, _) local message = element.parent.parent[task_message_textfield.name].text PlayerIsCreating:set(player, false) - - local task_id = Tasks.add_task(player.force.name, player.name, message) + local parsed = parse_message(message) + local task_id = Tasks.add_task(player.force.name, player.name, parsed.title, parsed.body) PlayerSelected:set(player, task_id) end ) @@ -535,7 +546,7 @@ local update_task = function(player, task_list_element, task_id) else -- If the task exists update the caption element = task_list_element["task-" .. task_id] - element[task_list_item.name].caption = task.message + element[task_list_item.name].caption = task.title end -- Set tooltip local last_edit_name = task.last_edit_name @@ -552,7 +563,7 @@ local update_task_edit_footer = function(player, task_id) local message_element = edit_flow[task_message_textfield.name] message_element.focus() - message_element.text = task.message + message_element.text = task.title .. "\n" .. task.body end -- Update the footer task view @@ -562,13 +573,15 @@ local update_task_view_footer = function(player, task_id) local view_flow = frame.container.view local has_permission = check_player_permissions(player, task) - local message_element = view_flow.message + local title_element = view_flow.title + local body_element = view_flow.body local edit_button_element = view_flow.actions[view_task_edit_button.name] local delete_button_element = view_flow.actions[view_task_delete_button.name] edit_button_element.visible = has_permission delete_button_element.visible = has_permission - message_element.caption = task.message + title_element.caption = task.title + body_element.caption = task.body local players_editing = table.get_keys(task.currently_editing) if #players_editing > 0 then From 0866e9f9c31912b8204f3602a328f4ac559936b8 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Thu, 15 Apr 2021 21:55:41 +0100 Subject: [PATCH 15/56] Refactored spawn area --- config/spawn_area.lua | 311 ++++++++++++++++++---------------- modules/addons/spawn-area.lua | 199 ++++++++++++---------- 2 files changed, 280 insertions(+), 230 deletions(-) diff --git a/config/spawn_area.lua b/config/spawn_area.lua index 889fc20e..588f9d3c 100644 --- a/config/spawn_area.lua +++ b/config/spawn_area.lua @@ -2,156 +2,179 @@ -- @config Spawn-Area return { - infinite_ammo_turrets = { --- @setting infinite_ammo_turrets These turrets will have they ammo refilled automatically and can not be looted - enabled=true, --- @setting enabled weather the turrets will be created and refilled - ammo_type='uranium-rounds-magazine', --- @setting ammo_type the ammo type that will be used - locations={ --- @setting locations locations of all turrets, this is default it can be changed during runtime + spawn_area = { --- @setting spawn_area Settings relating to the whole spawn area + deconstruction_radius = 20, --- @setting deconstruction_radius All entities within this radius will be removed + deconstruction_tile = 'concrete', --- @setting deconstruction_tile Tile to be placed in the deconstruction radius, use nil for map gen + landfill_radius = 50, --- @setting pattern_radius All water within this radius will be land filled + }, + turrets = { --- @setting turrets Settings relating to adding turrets to spawn + enabled = true, --- @setting enabled Weather turrets will be added to spawn + ammo_type = 'uranium-rounds-magazine', --- @setting ammo_type The ammo type that will be used during refills + refill_time = 60*60*5, --- @setting refill_time The time in ticks between each refill of the turrets, only change if having lag issues + offset = { x=0, y=0 }, --- @setting offset The position offset to apply to turrets + locations = { --- @setting locations The locations of all turrets, this list can change during runtime {surface=1,position={x=-3,y=-3}}, - {surface=1,position={x=3 ,y=-3}}, - {surface=1,position={x=-3,y=3 }}, - {surface=1,position={x=3 ,y=3 }} + {surface=1,position={x= 3,y=-3}}, + {surface=1,position={x=-3,y= 3}}, + {surface=1,position={x= 3,y= 3}} } }, - afk_belts = { --- @setting afk_belts setting relating to afk belts round the spawn point - enabled=true, --- @setting enabled weather afk belts will be generated - locations={ --- @setting locations top left connors of any afk belt loops to be added - {x=-5,y=-5}, - {x=5, y=-5}, - {x=-5,y=5 }, - {x=5, y=5 } + afk_belts = { --- @setting afk_belts Settings relating to adding afk belts to spawn + enabled = true, --- @setting enabled Weather afk belts will be added to spawn + belt_type = 'transport-belt', --- @setting belt_type The belt to used used as afk belts + protected = true, --- @settins protected Weather belts will be protected from player interaction + offset = { x=0, y=0 }, --- @setting offset The position offset to apply to afk belts + locations={ --- @setting locations The locations to spawn afk belts at, given as the top left position + {-5, -5}, { 5, -5}, + {-5, 5}, { 5, 5} } }, - corrections = { --- @setting corrections Some settings that have no where else to go - protect_entities=true, --- @setting protect_entities if the spawn entites will be protected - offset = {x=0,y=-2}, --- @setting offset a global offset value to correct the x and y values of the tables below - deconstruction_radius=20, --- @setting deconstruction_radius when the spawn is made this area will have all entities removed first - deconstruction_tile='concrete', --- @setting deconstruction_tile this is the tile that will spawn in the deconstruction radius - pattern_radius = 50, --- @setting pattern_radius this is the radius of the pattern all water in this area will be filled - pattern_tile = 'stone-path' --- @setting pattern_tile the tile that is used for the pattern + water = { --- @setting water Settings relating to adding water to spawn + enabled = true, --- @setting enabled Weather water tiles will be added to spawn + water_tile = 'water-mud', --- @setting water_tile The tile to be used as the water tile + offset = { x=0, y=0 }, --- @setting offset The position offset to apply to water tiles + locations = { --- @setting locations The location of the water tiles {x,y} + -- Each is a 3x3 with the closest tile to 0,0 removed + { 7, 8}, { 7, 9 }, { 8, 7}, { 8, 8}, { 8, 9 }, { 9, 7}, { 9, 8}, { 9, 9 }, -- Bottom Right + { 7, -9}, { 7, -10}, { 8, -8}, { 8, -9}, { 8, -10}, { 9, -8}, { 9, -9}, { 9, -10}, -- Top Right + {-8, -9}, {-8, -10}, {-9, -8}, {-9, -9}, {-9, -10}, {-10, -8}, {-10, -9}, {-10, -10}, -- Top Left + {-8, 8}, {-8, 9 }, {-9, 7}, {-9, 8}, {-9, 9 }, {-10, 7}, {-10, 8}, {-10, 9 }, -- Bottom Left + } }, - entities = { --- @setting entities All entities that will be created as part of spawn {entity-name,x-pos,y-pos} - {"stone-wall",-10,-6},{"stone-wall",-10,-5},{"stone-wall",-10,-4},{"stone-wall",-10,-3},{"stone-wall",-10,-2},{"stone-wall",-10,-1},{"stone-wall",-10,0},{"stone-wall",-10,3},{"stone-wall",-10,4},{"stone-wall",-10,5}, - {"stone-wall",-10,6},{"stone-wall",-10,7},{"stone-wall",-10,8},{"stone-wall",-10,9},{"stone-wall",-8,-8},{"small-lamp",-8,-4},{"small-lamp",-8,-1},{"iron-chest",-8,0},{"iron-chest",-8,3},{"small-lamp",-8,4}, - {"small-lamp",-8,7},{"stone-wall",-8,11},{"stone-wall",-7,-8},{"small-electric-pole",-7,-2},{"iron-chest",-7,0},{"iron-chest",-7,3},{"small-electric-pole",-7,5},{"stone-wall",-7,11},{"stone-wall",-6,-8},{"small-lamp",-6,-6}, - {"iron-chest",-6,0},{"iron-chest",-6,3},{"small-lamp",-6,9},{"stone-wall",-6,11},{"stone-wall",-5,-8},{"small-lamp",-5,-1},{"iron-chest",-5,0},{"iron-chest",-5,3},{"small-lamp",-5,4},{"stone-wall",-5,11}, - {"stone-wall",-4,-8},{"small-electric-pole",-4,-5},{"iron-chest",-4,0},{"iron-chest",-4,3},{"small-electric-pole",-4,8},{"stone-wall",-4,11},{"stone-wall",-3,-8},{"small-lamp",-3,-6},{"small-lamp",-3,-3},{"small-lamp",-3,6}, - {"small-lamp",-3,9},{"stone-wall",-3,11},{"stone-wall",-2,-8},{"iron-chest",-2,-6},{"iron-chest",-2,-5},{"iron-chest",-2,-4},{"iron-chest",-2,-3},{"iron-chest",-2,-2},{"iron-chest",-2,5},{"iron-chest",-2,6}, - {"iron-chest",-2,7},{"iron-chest",-2,8},{"iron-chest",-2,9},{"stone-wall",-2,11},{"stone-wall",1,-8},{"iron-chest",1,-6}, - {"iron-chest",1,-5},{"iron-chest",1,-4},{"iron-chest",1,-3},{"iron-chest",1,-2},{"iron-chest",1,5},{"iron-chest",1,6},{"iron-chest",1,7},{"iron-chest",1,8},{"iron-chest",1,9},{"stone-wall",1,11}, - {"stone-wall",2,-8},{"small-lamp",2,-6},{"small-lamp",2,-3},{"small-lamp",2,6},{"small-lamp",2,9},{"stone-wall",2,11},{"stone-wall",3,-8},{"small-electric-pole",3,-5},{"iron-chest",3,0},{"iron-chest",3,3}, - {"small-electric-pole",3,8},{"stone-wall",3,11},{"stone-wall",4,-8},{"small-lamp",4,-1},{"iron-chest",4,0},{"iron-chest",4,3},{"small-lamp",4,4},{"stone-wall",4,11},{"stone-wall",5,-8},{"small-lamp",5,-6}, - {"iron-chest",5,0},{"iron-chest",5,3},{"small-lamp",5,9},{"stone-wall",5,11},{"stone-wall",6,-8},{"small-electric-pole",6,-2},{"iron-chest",6,0},{"iron-chest",6,3},{"small-electric-pole",6,5},{"stone-wall",6,11}, - {"stone-wall",7,-8},{"small-lamp",7,-4},{"small-lamp",7,-1},{"iron-chest",7,0},{"iron-chest",7,3},{"small-lamp",7,4},{"small-lamp",7,7},{"stone-wall",7,11},{"stone-wall",9,-6},{"stone-wall",9,-5}, - {"stone-wall",9,-4},{"stone-wall",9,-3},{"stone-wall",9,-2},{"stone-wall",9,-1},{"stone-wall",9,0},{"stone-wall",9,3},{"stone-wall",9,4},{"stone-wall",9,5},{"stone-wall",9,6},{"stone-wall",9,7}, - {"stone-wall",9,8},{"stone-wall",9,9} + entities = { --- @setting entities Settings relating to adding entities to spawn + enabled = true, --- @settings enabled Weather entities will be added to spawn + protected = true, --- @settins protected Weather entities will be protected from player interaction + operable = true, --- @settings operable Weather entities can be opened by players, must be true if chests are used + offset = { x=0, y=-2 }, --- @settings offset The position offset to apply to entities + locations = { --- @setting locations The location and names of entities {name,x,y} + {"stone-wall",-10,-5},{"stone-wall",-10,-4},{"stone-wall",-10,-3},{"stone-wall",-10,-2},{"stone-wall",-10,-1},{"stone-wall",-10,0},{"stone-wall",-10,3},{"stone-wall",-10,4},{"stone-wall",-10,5}, + {"stone-wall",-10,6},{"stone-wall",-10,7},{"stone-wall",-10,8},{"small-lamp",-8,-4},{"small-lamp",-8,-1},{"iron-chest",-8,0},{"iron-chest",-8,3},{"small-lamp",-8,4}, + {"small-lamp",-8,7},{"stone-wall",-7,-8},{"small-electric-pole",-7,-2},{"iron-chest",-7,0},{"iron-chest",-7,3},{"small-electric-pole",-7,5},{"stone-wall",-7,11},{"stone-wall",-6,-8},{"small-lamp",-6,-6}, + {"iron-chest",-6,0},{"iron-chest",-6,3},{"small-lamp",-6,9},{"stone-wall",-6,11},{"stone-wall",-5,-8},{"small-lamp",-5,-1},{"iron-chest",-5,0},{"iron-chest",-5,3},{"small-lamp",-5,4},{"stone-wall",-5,11}, + {"stone-wall",-4,-8},{"small-electric-pole",-4,-5},{"iron-chest",-4,0},{"iron-chest",-4,3},{"small-electric-pole",-4,8},{"stone-wall",-4,11},{"stone-wall",-3,-8},{"small-lamp",-3,-6},{"small-lamp",-3,-3},{"small-lamp",-3,6}, + {"small-lamp",-3,9},{"stone-wall",-3,11},{"stone-wall",-2,-8},{"iron-chest",-2,-6},{"iron-chest",-2,-5},{"iron-chest",-2,-4},{"iron-chest",-2,-3},{"iron-chest",-2,-2},{"iron-chest",-2,5},{"iron-chest",-2,6}, + {"iron-chest",-2,7},{"iron-chest",-2,8},{"iron-chest",-2,9},{"stone-wall",-2,11},{"stone-wall",1,-8},{"iron-chest",1,-6}, + {"iron-chest",1,-5},{"iron-chest",1,-4},{"iron-chest",1,-3},{"iron-chest",1,-2},{"iron-chest",1,5},{"iron-chest",1,6},{"iron-chest",1,7},{"iron-chest",1,8},{"iron-chest",1,9},{"stone-wall",1,11}, + {"stone-wall",2,-8},{"small-lamp",2,-6},{"small-lamp",2,-3},{"small-lamp",2,6},{"small-lamp",2,9},{"stone-wall",2,11},{"stone-wall",3,-8},{"small-electric-pole",3,-5},{"iron-chest",3,0},{"iron-chest",3,3}, + {"small-electric-pole",3,8},{"stone-wall",3,11},{"stone-wall",4,-8},{"small-lamp",4,-1},{"iron-chest",4,0},{"iron-chest",4,3},{"small-lamp",4,4},{"stone-wall",4,11},{"stone-wall",5,-8},{"small-lamp",5,-6}, + {"iron-chest",5,0},{"iron-chest",5,3},{"small-lamp",5,9},{"stone-wall",5,11},{"stone-wall",6,-8},{"small-electric-pole",6,-2},{"iron-chest",6,0},{"iron-chest",6,3},{"small-electric-pole",6,5},{"stone-wall",6,11}, + {"small-lamp",7,-4},{"small-lamp",7,-1},{"iron-chest",7,0},{"iron-chest",7,3},{"small-lamp",7,4},{"small-lamp",7,7},{"stone-wall",9,-5}, + {"stone-wall",9,-4},{"stone-wall",9,-3},{"stone-wall",9,-2},{"stone-wall",9,-1},{"stone-wall",9,0},{"stone-wall",9,3},{"stone-wall",9,4},{"stone-wall",9,5},{"stone-wall",9,6},{"stone-wall",9,7}, + {"stone-wall",9,8} + } }, - tiles = { --- @setting tiles The location of the "pattern" tiles {x-pos,y-pos} - {-49,-3},{-49,-2},{-49,1},{-49,2},{-49,5},{-49,6},{-48,-4},{-48,-3},{-48,-2},{-48,1},{-48,2},{-48,5},{-48,6},{-48,7},{-47,-7},{-47,-6},{-47,-5},{-47,-4},{-47,-3},{-47,-2},{-47,5},{-47,6},{-47,7},{-47,8},{-47,9},{-47,10},{-46,-8},{-46,-7},{-46,-6},{-46,-5}, - {-46,-4},{-46,-3},{-46,-2},{-46,-1},{-46,4},{-46,5},{-46,6},{-46,7},{-46,8},{-46,9},{-46,10},{-46,11},{-45,-17},{-45,-16},{-45,-15},{-45,-14},{-45,-13},{-45,-12},{-45,-9},{-45,-8},{-45,-7},{-45,-2},{-45,-1},{-45,0},{-45,1},{-45,2},{-45,3},{-45,4},{-45,5},{-45,10}, - {-45,11},{-45,12},{-45,15},{-45,16},{-45,17},{-45,18},{-45,19},{-45,20},{-44,-18},{-44,-17},{-44,-16},{-44,-15},{-44,-14},{-44,-13},{-44,-12},{-44,-9},{-44,-8},{-44,-1},{-44,0},{-44,1},{-44,2},{-44,3},{-44,4},{-44,11},{-44,12},{-44,15},{-44,16},{-44,17},{-44,18},{-44,19}, - {-44,20},{-44,21},{-43,-19},{-43,-18},{-43,-17},{-43,-1},{-43,0},{-43,1},{-43,2},{-43,3},{-43,4},{-43,20},{-43,21},{-43,22},{-42,-19},{-42,-18},{-42,-1},{-42,0},{-42,1},{-42,2},{-42,3},{-42,4},{-42,21},{-42,22},{-41,-25},{-41,-24},{-41,-19},{-41,-18},{-41,-13},{-41,-12}, - {-41,-11},{-41,-10},{-41,-5},{-41,-4},{-41,7},{-41,8},{-41,13},{-41,14},{-41,15},{-41,16},{-41,21},{-41,22},{-41,27},{-41,28},{-40,-26},{-40,-25},{-40,-24},{-40,-20},{-40,-19},{-40,-18},{-40,-13},{-40,-12},{-40,-11},{-40,-10},{-40,-5},{-40,-4},{-40,7},{-40,8},{-40,13},{-40,14}, - {-40,15},{-40,16},{-40,21},{-40,22},{-40,23},{-40,27},{-40,28},{-40,29},{-39,-27},{-39,-26},{-39,-25},{-39,-24},{-39,-21},{-39,-20},{-39,-19},{-39,-13},{-39,-12},{-39,-5},{-39,-4},{-39,-3},{-39,-2},{-39,-1},{-39,0},{-39,1},{-39,2},{-39,3},{-39,4},{-39,5},{-39,6},{-39,7}, - {-39,8},{-39,15},{-39,16},{-39,22},{-39,23},{-39,24},{-39,27},{-39,28},{-39,29},{-39,30},{-38,-27},{-38,-26},{-38,-25},{-38,-24},{-38,-21},{-38,-20},{-38,-13},{-38,-12},{-38,-5},{-38,-4},{-38,-3},{-38,-2},{-38,-1},{-38,0},{-38,1},{-38,2},{-38,3},{-38,4},{-38,5},{-38,6}, - {-38,7},{-38,8},{-38,15},{-38,16},{-38,23},{-38,24},{-38,27},{-38,28},{-38,29},{-38,30},{-37,-17},{-37,-16},{-37,-13},{-37,-12},{-37,-11},{-37,-10},{-37,-4},{-37,-3},{-37,-2},{-37,-1},{-37,0},{-37,3},{-37,4},{-37,5},{-37,6},{-37,7},{-37,13},{-37,14},{-37,15},{-37,16}, - {-37,19},{-37,20},{-36,-17},{-36,-16},{-36,-13},{-36,-12},{-36,-11},{-36,-10},{-36,-9},{-36,-3},{-36,-2},{-36,-1},{-36,0},{-36,3},{-36,4},{-36,5},{-36,6},{-36,12},{-36,13},{-36,14},{-36,15},{-36,16},{-36,19},{-36,20},{-35,-29},{-35,-28},{-35,-23},{-35,-22},{-35,-17},{-35,-16}, - {-35,-12},{-35,-11},{-35,-10},{-35,-9},{-35,-8},{-35,11},{-35,12},{-35,13},{-35,14},{-35,15},{-35,19},{-35,20},{-35,25},{-35,26},{-35,31},{-35,32},{-34,-30},{-34,-29},{-34,-28},{-34,-23},{-34,-22},{-34,-17},{-34,-16},{-34,-15},{-34,-11},{-34,-10},{-34,-9},{-34,-8},{-34,11},{-34,12}, - {-34,13},{-34,14},{-34,18},{-34,19},{-34,20},{-34,25},{-34,26},{-34,31},{-34,32},{-34,33},{-33,-31},{-33,-30},{-33,-29},{-33,-28},{-33,-23},{-33,-22},{-33,-16},{-33,-15},{-33,-14},{-33,-5},{-33,-4},{-33,-1},{-33,0},{-33,3},{-33,4},{-33,7},{-33,8},{-33,17},{-33,18},{-33,19}, - {-33,25},{-33,26},{-33,31},{-33,32},{-33,33},{-33,34},{-32,-32},{-32,-31},{-32,-30},{-32,-29},{-32,-28},{-32,-27},{-32,-23},{-32,-22},{-32,-21},{-32,-15},{-32,-14},{-32,-6},{-32,-5},{-32,-4},{-32,-1},{-32,0},{-32,3},{-32,4},{-32,7},{-32,8},{-32,9},{-32,17},{-32,18},{-32,24}, - {-32,25},{-32,26},{-32,30},{-32,31},{-32,32},{-32,33},{-32,34},{-32,35},{-31,-33},{-31,-32},{-31,-31},{-31,-30},{-31,-29},{-31,-28},{-31,-27},{-31,-26},{-31,-22},{-31,-21},{-31,-20},{-31,-19},{-31,-18},{-31,-11},{-31,-10},{-31,-9},{-31,-8},{-31,-7},{-31,-6},{-31,-5},{-31,-1},{-31,0}, - {-31,1},{-31,2},{-31,3},{-31,4},{-31,8},{-31,9},{-31,10},{-31,11},{-31,12},{-31,13},{-31,14},{-31,21},{-31,22},{-31,23},{-31,24},{-31,25},{-31,29},{-31,30},{-31,31},{-31,32},{-31,33},{-31,34},{-31,35},{-31,36},{-30,-33},{-30,-32},{-30,-31},{-30,-30},{-30,-29},{-30,-28}, - {-30,-27},{-30,-26},{-30,-21},{-30,-20},{-30,-19},{-30,-18},{-30,-11},{-30,-10},{-30,-9},{-30,-8},{-30,-7},{-30,-6},{-30,-1},{-30,0},{-30,1},{-30,2},{-30,3},{-30,4},{-30,9},{-30,10},{-30,11},{-30,12},{-30,13},{-30,14},{-30,21},{-30,22},{-30,23},{-30,24},{-30,29},{-30,30}, - {-30,31},{-30,32},{-30,33},{-30,34},{-30,35},{-30,36},{-29,-37},{-29,-36},{-29,-30},{-29,-29},{-29,-28},{-29,-27},{-29,-26},{-29,-15},{-29,-14},{-29,-10},{-29,-9},{-29,-8},{-29,-7},{-29,10},{-29,11},{-29,12},{-29,13},{-29,17},{-29,18},{-29,29},{-29,30},{-29,31},{-29,32},{-29,33}, - {-29,39},{-29,40},{-28,-38},{-28,-37},{-28,-36},{-28,-29},{-28,-28},{-28,-27},{-28,-26},{-28,-16},{-28,-15},{-28,-14},{-28,-9},{-28,-8},{-28,11},{-28,12},{-28,17},{-28,18},{-28,19},{-28,29},{-28,30},{-28,31},{-28,32},{-28,39},{-28,40},{-28,41},{-27,-39},{-27,-38},{-27,-37},{-27,-36}, - {-27,-23},{-27,-22},{-27,-19},{-27,-18},{-27,-17},{-27,-16},{-27,-15},{-27,-5},{-27,-4},{-27,-1},{-27,0},{-27,1},{-27,2},{-27,3},{-27,4},{-27,7},{-27,8},{-27,18},{-27,19},{-27,20},{-27,21},{-27,22},{-27,25},{-27,26},{-27,39},{-27,40},{-27,41},{-27,42},{-26,-39},{-26,-38}, - {-26,-37},{-26,-36},{-26,-24},{-26,-23},{-26,-22},{-26,-19},{-26,-18},{-26,-17},{-26,-16},{-26,-6},{-26,-5},{-26,-4},{-26,-1},{-26,0},{-26,1},{-26,2},{-26,3},{-26,4},{-26,7},{-26,8},{-26,9},{-26,19},{-26,20},{-26,21},{-26,22},{-26,25},{-26,26},{-26,27},{-26,39},{-26,40}, - {-26,41},{-26,42},{-25,-33},{-25,-32},{-25,-31},{-25,-30},{-25,-25},{-25,-24},{-25,-23},{-25,-22},{-25,-19},{-25,-18},{-25,-17},{-25,-9},{-25,-8},{-25,-7},{-25,-6},{-25,-5},{-25,-4},{-25,-1},{-25,0},{-25,1},{-25,2},{-25,3},{-25,4},{-25,7},{-25,8},{-25,9},{-25,10},{-25,11}, - {-25,12},{-25,20},{-25,21},{-25,22},{-25,25},{-25,26},{-25,27},{-25,28},{-25,33},{-25,34},{-25,35},{-25,36},{-24,-33},{-24,-32},{-24,-31},{-24,-30},{-24,-29},{-24,-25},{-24,-24},{-24,-23},{-24,-22},{-24,-19},{-24,-18},{-24,-9},{-24,-8},{-24,-7},{-24,-6},{-24,-5},{-24,-4},{-24,-1}, - {-24,0},{-24,1},{-24,2},{-24,3},{-24,4},{-24,7},{-24,8},{-24,9},{-24,10},{-24,11},{-24,12},{-24,21},{-24,22},{-24,25},{-24,26},{-24,27},{-24,28},{-24,32},{-24,33},{-24,34},{-24,35},{-24,36},{-23,-37},{-23,-36},{-23,-30},{-23,-29},{-23,-28},{-23,-19},{-23,-18},{-23,-15}, - {-23,-14},{-23,-9},{-23,-8},{-23,-7},{-23,-6},{-23,-5},{-23,0},{-23,1},{-23,2},{-23,3},{-23,8},{-23,9},{-23,10},{-23,11},{-23,12},{-23,17},{-23,18},{-23,21},{-23,22},{-23,31},{-23,32},{-23,33},{-23,39},{-23,40},{-22,-38},{-22,-37},{-22,-36},{-22,-29},{-22,-28},{-22,-19}, - {-22,-18},{-22,-15},{-22,-14},{-22,-13},{-22,-9},{-22,-8},{-22,-7},{-22,-6},{-22,1},{-22,2},{-22,9},{-22,10},{-22,11},{-22,12},{-22,16},{-22,17},{-22,18},{-22,21},{-22,22},{-22,31},{-22,32},{-22,39},{-22,40},{-22,41},{-21,-41},{-21,-40},{-21,-39},{-21,-38},{-21,-37},{-21,-29}, - {-21,-28},{-21,-25},{-21,-24},{-21,-23},{-21,-22},{-21,-21},{-21,-20},{-21,-19},{-21,-18},{-21,-15},{-21,-14},{-21,-13},{-21,-12},{-21,-3},{-21,-2},{-21,5},{-21,6},{-21,15},{-21,16},{-21,17},{-21,18},{-21,21},{-21,22},{-21,23},{-21,24},{-21,25},{-21,26},{-21,27},{-21,28},{-21,31}, - {-21,32},{-21,40},{-21,41},{-21,42},{-21,43},{-21,44},{-20,-42},{-20,-41},{-20,-40},{-20,-39},{-20,-38},{-20,-29},{-20,-28},{-20,-25},{-20,-24},{-20,-23},{-20,-22},{-20,-21},{-20,-20},{-20,-19},{-20,-18},{-20,-15},{-20,-14},{-20,-13},{-20,-12},{-20,-3},{-20,-2},{-20,-1},{-20,4},{-20,5}, - {-20,6},{-20,15},{-20,16},{-20,17},{-20,18},{-20,21},{-20,22},{-20,23},{-20,24},{-20,25},{-20,26},{-20,27},{-20,28},{-20,31},{-20,32},{-20,41},{-20,42},{-20,43},{-20,44},{-20,45},{-19,-43},{-19,-42},{-19,-41},{-19,-35},{-19,-34},{-19,-33},{-19,-32},{-19,-25},{-19,-24},{-19,-23}, - {-19,-15},{-19,-14},{-19,-13},{-19,-9},{-19,-8},{-19,-7},{-19,-6},{-19,-2},{-19,-1},{-19,0},{-19,1},{-19,2},{-19,3},{-19,4},{-19,5},{-19,9},{-19,10},{-19,11},{-19,12},{-19,16},{-19,17},{-19,18},{-19,26},{-19,27},{-19,28},{-19,35},{-19,36},{-19,37},{-19,38},{-19,44}, - {-19,45},{-19,46},{-18,-43},{-18,-42},{-18,-35},{-18,-34},{-18,-33},{-18,-32},{-18,-31},{-18,-26},{-18,-25},{-18,-24},{-18,-15},{-18,-14},{-18,-10},{-18,-9},{-18,-8},{-18,-7},{-18,-6},{-18,-1},{-18,0},{-18,1},{-18,2},{-18,3},{-18,4},{-18,9},{-18,10},{-18,11},{-18,12},{-18,13}, - {-18,17},{-18,18},{-18,27},{-18,28},{-18,29},{-18,34},{-18,35},{-18,36},{-18,37},{-18,38},{-18,45},{-18,46},{-17,-43},{-17,-42},{-17,-32},{-17,-31},{-17,-30},{-17,-27},{-17,-26},{-17,-25},{-17,-21},{-17,-20},{-17,-19},{-17,-18},{-17,-17},{-17,-16},{-17,-15},{-17,-14},{-17,-11},{-17,-10}, - {-17,-9},{-17,-8},{-17,-7},{-17,-6},{-17,0},{-17,1},{-17,2},{-17,3},{-17,9},{-17,10},{-17,11},{-17,12},{-17,13},{-17,14},{-17,17},{-17,18},{-17,19},{-17,20},{-17,21},{-17,22},{-17,23},{-17,24},{-17,28},{-17,29},{-17,30},{-17,33},{-17,34},{-17,35},{-17,45},{-17,46}, - {-16,-43},{-16,-42},{-16,-31},{-16,-30},{-16,-27},{-16,-26},{-16,-21},{-16,-20},{-16,-19},{-16,-18},{-16,-17},{-16,-16},{-16,-15},{-16,-14},{-16,-11},{-16,-10},{-16,-9},{-16,-8},{-16,-7},{-16,-6},{-16,1},{-16,2},{-16,9},{-16,10},{-16,11},{-16,12},{-16,13},{-16,14},{-16,17},{-16,18}, - {-16,19},{-16,20},{-16,21},{-16,22},{-16,23},{-16,24},{-16,29},{-16,30},{-16,33},{-16,34},{-16,45},{-16,46},{-15,-43},{-15,-42},{-15,-39},{-15,-38},{-15,-37},{-15,-36},{-15,-35},{-15,-34},{-15,-20},{-15,-19},{-15,-18},{-15,-17},{-15,-10},{-15,-9},{-15,-8},{-15,-7},{-15,-3},{-15,-2}, - {-15,1},{-15,2},{-15,5},{-15,6},{-15,10},{-15,11},{-15,12},{-15,13},{-15,20},{-15,21},{-15,22},{-15,23},{-15,37},{-15,38},{-15,39},{-15,40},{-15,41},{-15,42},{-15,45},{-15,46},{-14,-43},{-14,-42},{-14,-39},{-14,-38},{-14,-37},{-14,-36},{-14,-35},{-14,-34},{-14,-33},{-14,-19}, - {-14,-18},{-14,-9},{-14,-8},{-14,-4},{-14,-3},{-14,-2},{-14,1},{-14,2},{-14,5},{-14,6},{-14,7},{-14,11},{-14,12},{-14,21},{-14,22},{-14,36},{-14,37},{-14,38},{-14,39},{-14,40},{-14,41},{-14,42},{-14,45},{-14,46},{-13,-39},{-13,-38},{-13,-35},{-13,-34},{-13,-33},{-13,-32}, - {-13,-29},{-13,-28},{-13,-15},{-13,-14},{-13,-5},{-13,-4},{-13,-3},{-13,-2},{-13,5},{-13,6},{-13,7},{-13,8},{-13,17},{-13,18},{-13,31},{-13,32},{-13,35},{-13,36},{-13,37},{-13,38},{-13,41},{-13,42},{-12,-39},{-12,-38},{-12,-35},{-12,-34},{-12,-33},{-12,-32},{-12,-29},{-12,-28}, - {-12,-27},{-12,-16},{-12,-15},{-12,-14},{-12,-13},{-12,-5},{-12,-4},{-12,-3},{-12,-2},{-12,5},{-12,6},{-12,7},{-12,8},{-12,16},{-12,17},{-12,18},{-12,19},{-12,30},{-12,31},{-12,32},{-12,35},{-12,36},{-12,37},{-12,38},{-12,41},{-12,42},{-11,-43},{-11,-42},{-11,-34},{-11,-33}, - {-11,-32},{-11,-29},{-11,-28},{-11,-27},{-11,-26},{-11,-23},{-11,-22},{-11,-21},{-11,-20},{-11,-17},{-11,-16},{-11,-15},{-11,-14},{-11,-13},{-11,-12},{-11,-9},{-11,-8},{-11,1},{-11,2},{-11,11},{-11,12},{-11,15},{-11,16},{-11,17},{-11,18},{-11,19},{-11,20},{-11,23},{-11,24},{-11,25}, - {-11,26},{-11,29},{-11,30},{-11,31},{-11,32},{-11,35},{-11,36},{-11,37},{-11,45},{-11,46},{-10,-44},{-10,-43},{-10,-42},{-10,-33},{-10,-32},{-10,-29},{-10,-28},{-10,-27},{-10,-26},{-10,-23},{-10,-22},{-10,-21},{-10,-20},{-10,-17},{-10,-16},{-10,-15},{-10,-14},{-10,-13},{-10,-12},{-10,-9}, - {-10,-8},{-10,-7},{-10,0},{-10,1},{-10,2},{-10,3},{-10,10},{-10,11},{-10,12},{-10,15},{-10,16},{-10,17},{-10,18},{-10,19},{-10,20},{-10,23},{-10,24},{-10,25},{-10,26},{-10,29},{-10,30},{-10,31},{-10,32},{-10,35},{-10,36},{-10,45},{-10,46},{-10,47},{-9,-45},{-9,-44}, - {-9,-43},{-9,-29},{-9,-28},{-9,-27},{-9,-23},{-9,-22},{-9,-21},{-9,-20},{-9,-17},{-9,-16},{-9,-15},{-9,-14},{-9,-13},{-9,-8},{-9,-7},{-9,-6},{-9,-5},{-9,-1},{-9,0},{-9,1},{-9,2},{-9,3},{-9,4},{-9,8},{-9,9},{-9,10},{-9,11},{-9,16},{-9,17},{-9,18}, - {-9,19},{-9,20},{-9,23},{-9,24},{-9,25},{-9,26},{-9,30},{-9,31},{-9,32},{-9,46},{-9,47},{-9,48},{-8,-45},{-8,-44},{-8,-30},{-8,-29},{-8,-28},{-8,-24},{-8,-23},{-8,-22},{-8,-21},{-8,-20},{-8,-17},{-8,-16},{-8,-15},{-8,-14},{-8,-7},{-8,-6},{-8,-5},{-8,-4}, - {-8,-1},{-8,0},{-8,1},{-8,2},{-8,3},{-8,4},{-8,7},{-8,8},{-8,9},{-8,10},{-8,17},{-8,18},{-8,19},{-8,20},{-8,23},{-8,24},{-8,25},{-8,26},{-8,27},{-8,31},{-8,32},{-8,33},{-8,47},{-8,48},{-7,-45},{-7,-44},{-7,-39},{-7,-38},{-7,-37},{-7,-36}, - {-7,-31},{-7,-30},{-7,-29},{-7,-25},{-7,-24},{-7,-23},{-7,-22},{-7,-21},{-7,-11},{-7,-10},{-7,-7},{-7,-6},{-7,-5},{-7,-4},{-7,7},{-7,8},{-7,9},{-7,10},{-7,13},{-7,14},{-7,24},{-7,25},{-7,26},{-7,27},{-7,28},{-7,32},{-7,33},{-7,34},{-7,39},{-7,40}, - {-7,41},{-7,42},{-7,47},{-7,48},{-6,-46},{-6,-45},{-6,-44},{-6,-39},{-6,-38},{-6,-37},{-6,-36},{-6,-35},{-6,-31},{-6,-30},{-6,-25},{-6,-24},{-6,-23},{-6,-22},{-6,-12},{-6,-11},{-6,-10},{-6,-6},{-6,-5},{-6,8},{-6,9},{-6,13},{-6,14},{-6,15},{-6,25},{-6,26}, - {-6,27},{-6,28},{-6,33},{-6,34},{-6,38},{-6,39},{-6,40},{-6,41},{-6,42},{-6,47},{-6,48},{-6,49},{-5,-47},{-5,-46},{-5,-45},{-5,-44},{-5,-37},{-5,-36},{-5,-35},{-5,-34},{-5,-19},{-5,-18},{-5,-13},{-5,-12},{-5,-11},{-5,-10},{-5,-1},{-5,0},{-5,1},{-5,2}, - {-5,3},{-5,4},{-5,13},{-5,14},{-5,15},{-5,16},{-5,21},{-5,22},{-5,37},{-5,38},{-5,39},{-5,40},{-5,47},{-5,48},{-5,49},{-5,50},{-4,-47},{-4,-46},{-4,-45},{-4,-44},{-4,-43},{-4,-37},{-4,-36},{-4,-35},{-4,-34},{-4,-19},{-4,-18},{-4,-17},{-4,-13},{-4,-12}, - {-4,-11},{-4,-10},{-4,-2},{-4,-1},{-4,0},{-4,1},{-4,2},{-4,3},{-4,4},{-4,5},{-4,13},{-4,14},{-4,15},{-4,16},{-4,20},{-4,21},{-4,22},{-4,37},{-4,38},{-4,39},{-4,40},{-4,46},{-4,47},{-4,48},{-4,49},{-4,50},{-3,-44},{-3,-43},{-3,-42},{-3,-41}, - {-3,-40},{-3,-37},{-3,-36},{-3,-35},{-3,-34},{-3,-31},{-3,-30},{-3,-29},{-3,-28},{-3,-25},{-3,-24},{-3,-23},{-3,-22},{-3,-18},{-3,-17},{-3,-16},{-3,-7},{-3,-6},{-3,-3},{-3,-2},{-3,-1},{-3,0},{-3,3},{-3,4},{-3,5},{-3,6},{-3,9},{-3,10},{-3,19},{-3,20}, - {-3,21},{-3,25},{-3,26},{-3,27},{-3,28},{-3,31},{-3,32},{-3,33},{-3,34},{-3,37},{-3,38},{-3,39},{-3,40},{-3,43},{-3,44},{-3,45},{-3,46},{-3,47},{-2,-43},{-2,-42},{-2,-41},{-2,-40},{-2,-37},{-2,-36},{-2,-35},{-2,-34},{-2,-31},{-2,-30},{-2,-29},{-2,-28}, - {-2,-25},{-2,-24},{-2,-23},{-2,-22},{-2,-21},{-2,-17},{-2,-16},{-2,-15},{-2,-8},{-2,-7},{-2,-6},{-2,-3},{-2,-2},{-2,-1},{-2,0},{-2,3},{-2,4},{-2,5},{-2,6},{-2,9},{-2,10},{-2,11},{-2,18},{-2,19},{-2,20},{-2,24},{-2,25},{-2,26},{-2,27},{-2,28}, - {-2,31},{-2,32},{-2,33},{-2,34},{-2,37},{-2,38},{-2,39},{-2,40},{-2,43},{-2,44},{-2,45},{-2,46},{-1,-47},{-1,-46},{-1,-43},{-1,-42},{-1,-41},{-1,-40},{-1,-37},{-1,-36},{-1,-29},{-1,-28},{-1,-25},{-1,-24},{-1,-23},{-1,-22},{-1,-21},{-1,-20},{-1,-17},{-1,-16}, - {-1,-15},{-1,-14},{-1,-13},{-1,-12},{-1,-9},{-1,-8},{-1,-7},{-1,-6},{-1,-3},{-1,-2},{-1,5},{-1,6},{-1,9},{-1,10},{-1,11},{-1,12},{-1,15},{-1,16},{-1,17},{-1,18},{-1,19},{-1,20},{-1,23},{-1,24},{-1,25},{-1,26},{-1,27},{-1,28},{-1,31},{-1,32}, - {-1,39},{-1,40},{-1,43},{-1,44},{-1,45},{-1,46},{-1,49},{-1,50},{0,-47},{0,-46},{0,-43},{0,-42},{0,-41},{0,-40},{0,-37},{0,-36},{0,-29},{0,-28},{0,-25},{0,-24},{0,-23},{0,-22},{0,-21},{0,-20},{0,-17},{0,-16},{0,-15},{0,-14},{0,-13},{0,-12}, - {0,-9},{0,-8},{0,-7},{0,-6},{0,-3},{0,-2},{0,5},{0,6},{0,9},{0,10},{0,11},{0,12},{0,15},{0,16},{0,17},{0,18},{0,19},{0,20},{0,23},{0,24},{0,25},{0,26},{0,27},{0,28},{0,31},{0,32},{0,39},{0,40},{0,43},{0,44}, - {0,45},{0,46},{0,49},{0,50},{1,-43},{1,-42},{1,-41},{1,-40},{1,-37},{1,-36},{1,-35},{1,-34},{1,-31},{1,-30},{1,-29},{1,-28},{1,-25},{1,-24},{1,-23},{1,-22},{1,-21},{1,-17},{1,-16},{1,-15},{1,-8},{1,-7},{1,-6},{1,-3},{1,-2},{1,-1}, - {1,0},{1,3},{1,4},{1,5},{1,6},{1,9},{1,10},{1,11},{1,18},{1,19},{1,20},{1,24},{1,25},{1,26},{1,27},{1,28},{1,31},{1,32},{1,33},{1,34},{1,37},{1,38},{1,39},{1,40},{1,43},{1,44},{1,45},{1,46},{2,-44},{2,-43}, - {2,-42},{2,-41},{2,-40},{2,-37},{2,-36},{2,-35},{2,-34},{2,-31},{2,-30},{2,-29},{2,-28},{2,-25},{2,-24},{2,-23},{2,-22},{2,-18},{2,-17},{2,-16},{2,-7},{2,-6},{2,-3},{2,-2},{2,-1},{2,0},{2,3},{2,4},{2,5},{2,6},{2,9},{2,10}, - {2,19},{2,20},{2,21},{2,25},{2,26},{2,27},{2,28},{2,31},{2,32},{2,33},{2,34},{2,37},{2,38},{2,39},{2,40},{2,43},{2,44},{2,45},{2,46},{2,47},{3,-47},{3,-46},{3,-45},{3,-44},{3,-43},{3,-37},{3,-36},{3,-35},{3,-34},{3,-19}, - {3,-18},{3,-17},{3,-13},{3,-12},{3,-11},{3,-10},{3,-2},{3,-1},{3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,13},{3,14},{3,15},{3,16},{3,20},{3,21},{3,22},{3,37},{3,38},{3,39},{3,40},{3,46},{3,47},{3,48},{3,49},{3,50}, - {4,-47},{4,-46},{4,-45},{4,-44},{4,-37},{4,-36},{4,-35},{4,-34},{4,-19},{4,-18},{4,-13},{4,-12},{4,-11},{4,-10},{4,-1},{4,0},{4,1},{4,2},{4,3},{4,4},{4,13},{4,14},{4,15},{4,16},{4,21},{4,22},{4,37},{4,38},{4,39},{4,40}, - {4,47},{4,48},{4,49},{4,50},{5,-46},{5,-45},{5,-44},{5,-39},{5,-38},{5,-37},{5,-36},{5,-35},{5,-31},{5,-30},{5,-25},{5,-24},{5,-23},{5,-22},{5,-12},{5,-11},{5,-10},{5,-6},{5,-5},{5,8},{5,9},{5,13},{5,14},{5,15},{5,25},{5,26}, - {5,27},{5,28},{5,33},{5,34},{5,38},{5,39},{5,40},{5,41},{5,42},{5,47},{5,48},{5,49},{6,-45},{6,-44},{6,-39},{6,-38},{6,-37},{6,-36},{6,-31},{6,-30},{6,-29},{6,-25},{6,-24},{6,-23},{6,-22},{6,-21},{6,-11},{6,-10},{6,-7},{6,-6}, - {6,-5},{6,-4},{6,7},{6,8},{6,9},{6,10},{6,13},{6,14},{6,24},{6,25},{6,26},{6,27},{6,28},{6,32},{6,33},{6,34},{6,39},{6,40},{6,41},{6,42},{6,47},{6,48},{7,-45},{7,-44},{7,-30},{7,-29},{7,-28},{7,-24},{7,-23},{7,-22}, - {7,-21},{7,-20},{7,-17},{7,-16},{7,-15},{7,-14},{7,-7},{7,-6},{7,-5},{7,-4},{7,-1},{7,0},{7,1},{7,2},{7,3},{7,4},{7,7},{7,8},{7,9},{7,10},{7,17},{7,18},{7,19},{7,20},{7,23},{7,24},{7,25},{7,26},{7,27},{7,31}, - {7,32},{7,33},{7,47},{7,48},{8,-45},{8,-44},{8,-43},{8,-29},{8,-28},{8,-27},{8,-23},{8,-22},{8,-21},{8,-20},{8,-17},{8,-16},{8,-15},{8,-14},{8,-13},{8,-8},{8,-7},{8,-6},{8,-5},{8,-1},{8,0},{8,1},{8,2},{8,3},{8,4},{8,8}, - {8,9},{8,10},{8,11},{8,16},{8,17},{8,18},{8,19},{8,20},{8,23},{8,24},{8,25},{8,26},{8,30},{8,31},{8,32},{8,46},{8,47},{8,48},{9,-44},{9,-43},{9,-42},{9,-33},{9,-32},{9,-29},{9,-28},{9,-27},{9,-26},{9,-23},{9,-22},{9,-21}, - {9,-20},{9,-17},{9,-16},{9,-15},{9,-14},{9,-13},{9,-12},{9,-9},{9,-8},{9,-7},{9,0},{9,1},{9,2},{9,3},{9,10},{9,11},{9,12},{9,15},{9,16},{9,17},{9,18},{9,19},{9,20},{9,23},{9,24},{9,25},{9,26},{9,29},{9,30},{9,31}, - {9,32},{9,35},{9,36},{9,45},{9,46},{9,47},{10,-43},{10,-42},{10,-34},{10,-33},{10,-32},{10,-29},{10,-28},{10,-27},{10,-26},{10,-23},{10,-22},{10,-21},{10,-20},{10,-17},{10,-16},{10,-15},{10,-14},{10,-13},{10,-12},{10,-9},{10,-8},{10,1},{10,2},{10,11}, - {10,12},{10,15},{10,16},{10,17},{10,18},{10,19},{10,20},{10,23},{10,24},{10,25},{10,26},{10,29},{10,30},{10,31},{10,32},{10,35},{10,36},{10,37},{10,45},{10,46},{11,-39},{11,-38},{11,-35},{11,-34},{11,-33},{11,-32},{11,-29},{11,-28},{11,-27},{11,-16}, - {11,-15},{11,-14},{11,-13},{11,-5},{11,-4},{11,-3},{11,-2},{11,5},{11,6},{11,7},{11,8},{11,16},{11,17},{11,18},{11,19},{11,30},{11,31},{11,32},{11,35},{11,36},{11,37},{11,38},{11,41},{11,42},{12,-39},{12,-38},{12,-35},{12,-34},{12,-33},{12,-32}, - {12,-29},{12,-28},{12,-15},{12,-14},{12,-5},{12,-4},{12,-3},{12,-2},{12,5},{12,6},{12,7},{12,8},{12,17},{12,18},{12,31},{12,32},{12,35},{12,36},{12,37},{12,38},{12,41},{12,42},{13,-43},{13,-42},{13,-39},{13,-38},{13,-37},{13,-36},{13,-35},{13,-34}, - {13,-33},{13,-19},{13,-18},{13,-9},{13,-8},{13,-4},{13,-3},{13,-2},{13,1},{13,2},{13,5},{13,6},{13,7},{13,11},{13,12},{13,21},{13,22},{13,36},{13,37},{13,38},{13,39},{13,40},{13,41},{13,42},{13,45},{13,46},{14,-43},{14,-42},{14,-39},{14,-38}, - {14,-37},{14,-36},{14,-35},{14,-34},{14,-20},{14,-19},{14,-18},{14,-17},{14,-10},{14,-9},{14,-8},{14,-7},{14,-3},{14,-2},{14,1},{14,2},{14,5},{14,6},{14,10},{14,11},{14,12},{14,13},{14,20},{14,21},{14,22},{14,23},{14,37},{14,38},{14,39},{14,40}, - {14,41},{14,42},{14,45},{14,46},{15,-43},{15,-42},{15,-31},{15,-30},{15,-27},{15,-26},{15,-21},{15,-20},{15,-19},{15,-18},{15,-17},{15,-16},{15,-15},{15,-14},{15,-11},{15,-10},{15,-9},{15,-8},{15,-7},{15,-6},{15,1},{15,2},{15,9},{15,10},{15,11},{15,12}, - {15,13},{15,14},{15,17},{15,18},{15,19},{15,20},{15,21},{15,22},{15,23},{15,24},{15,29},{15,30},{15,33},{15,34},{15,45},{15,46},{16,-43},{16,-42},{16,-32},{16,-31},{16,-30},{16,-27},{16,-26},{16,-25},{16,-21},{16,-20},{16,-19},{16,-18},{16,-17},{16,-16}, - {16,-15},{16,-14},{16,-11},{16,-10},{16,-9},{16,-8},{16,-7},{16,-6},{16,0},{16,1},{16,2},{16,3},{16,9},{16,10},{16,11},{16,12},{16,13},{16,14},{16,17},{16,18},{16,19},{16,20},{16,21},{16,22},{16,23},{16,24},{16,28},{16,29},{16,30},{16,33}, - {16,34},{16,35},{16,45},{16,46},{17,-43},{17,-42},{17,-35},{17,-34},{17,-33},{17,-32},{17,-31},{17,-26},{17,-25},{17,-24},{17,-15},{17,-14},{17,-10},{17,-9},{17,-8},{17,-7},{17,-6},{17,-1},{17,0},{17,1},{17,2},{17,3},{17,4},{17,9},{17,10},{17,11}, - {17,12},{17,13},{17,17},{17,18},{17,27},{17,28},{17,29},{17,34},{17,35},{17,36},{17,37},{17,38},{17,45},{17,46},{18,-43},{18,-42},{18,-41},{18,-35},{18,-34},{18,-33},{18,-32},{18,-25},{18,-24},{18,-23},{18,-15},{18,-14},{18,-13},{18,-9},{18,-8},{18,-7}, - {18,-6},{18,-2},{18,-1},{18,0},{18,1},{18,2},{18,3},{18,4},{18,5},{18,9},{18,10},{18,11},{18,12},{18,16},{18,17},{18,18},{18,26},{18,27},{18,28},{18,35},{18,36},{18,37},{18,38},{18,44},{18,45},{18,46},{19,-42},{19,-41},{19,-40},{19,-39}, - {19,-38},{19,-29},{19,-28},{19,-25},{19,-24},{19,-23},{19,-22},{19,-21},{19,-20},{19,-19},{19,-18},{19,-15},{19,-14},{19,-13},{19,-12},{19,-3},{19,-2},{19,-1},{19,4},{19,5},{19,6},{19,15},{19,16},{19,17},{19,18},{19,21},{19,22},{19,23},{19,24},{19,25}, - {19,26},{19,27},{19,28},{19,31},{19,32},{19,41},{19,42},{19,43},{19,44},{19,45},{20,-41},{20,-40},{20,-39},{20,-38},{20,-37},{20,-29},{20,-28},{20,-25},{20,-24},{20,-23},{20,-22},{20,-21},{20,-20},{20,-19},{20,-18},{20,-15},{20,-14},{20,-13},{20,-12},{20,-3}, - {20,-2},{20,5},{20,6},{20,15},{20,16},{20,17},{20,18},{20,21},{20,22},{20,23},{20,24},{20,25},{20,26},{20,27},{20,28},{20,31},{20,32},{20,40},{20,41},{20,42},{20,43},{20,44},{21,-38},{21,-37},{21,-36},{21,-29},{21,-28},{21,-19},{21,-18},{21,-15}, - {21,-14},{21,-13},{21,-9},{21,-8},{21,-7},{21,-6},{21,1},{21,2},{21,9},{21,10},{21,11},{21,12},{21,16},{21,17},{21,18},{21,21},{21,22},{21,31},{21,32},{21,39},{21,40},{21,41},{22,-37},{22,-36},{22,-30},{22,-29},{22,-28},{22,-19},{22,-18},{22,-15}, - {22,-14},{22,-9},{22,-8},{22,-7},{22,-6},{22,-5},{22,0},{22,1},{22,2},{22,3},{22,8},{22,9},{22,10},{22,11},{22,12},{22,17},{22,18},{22,21},{22,22},{22,31},{22,32},{22,33},{22,39},{22,40},{23,-33},{23,-32},{23,-31},{23,-30},{23,-29},{23,-25}, - {23,-24},{23,-23},{23,-22},{23,-19},{23,-18},{23,-9},{23,-8},{23,-7},{23,-6},{23,-5},{23,-4},{23,-1},{23,0},{23,1},{23,2},{23,3},{23,4},{23,7},{23,8},{23,9},{23,10},{23,11},{23,12},{23,21},{23,22},{23,25},{23,26},{23,27},{23,28},{23,32}, - {23,33},{23,34},{23,35},{23,36},{24,-33},{24,-32},{24,-31},{24,-30},{24,-25},{24,-24},{24,-23},{24,-22},{24,-19},{24,-18},{24,-17},{24,-9},{24,-8},{24,-7},{24,-6},{24,-5},{24,-4},{24,-1},{24,0},{24,1},{24,2},{24,3},{24,4},{24,7},{24,8},{24,9}, - {24,10},{24,11},{24,12},{24,20},{24,21},{24,22},{24,25},{24,26},{24,27},{24,28},{24,33},{24,34},{24,35},{24,36},{25,-39},{25,-38},{25,-37},{25,-36},{25,-24},{25,-23},{25,-22},{25,-19},{25,-18},{25,-17},{25,-16},{25,-6},{25,-5},{25,-4},{25,-1},{25,0}, - {25,1},{25,2},{25,3},{25,4},{25,7},{25,8},{25,9},{25,19},{25,20},{25,21},{25,22},{25,25},{25,26},{25,27},{25,39},{25,40},{25,41},{25,42},{26,-39},{26,-38},{26,-37},{26,-36},{26,-23},{26,-22},{26,-19},{26,-18},{26,-17},{26,-16},{26,-15},{26,-5}, - {26,-4},{26,-1},{26,0},{26,1},{26,2},{26,3},{26,4},{26,7},{26,8},{26,18},{26,19},{26,20},{26,21},{26,22},{26,25},{26,26},{26,39},{26,40},{26,41},{26,42},{27,-38},{27,-37},{27,-36},{27,-29},{27,-28},{27,-27},{27,-26},{27,-16},{27,-15},{27,-14}, - {27,-9},{27,-8},{27,11},{27,12},{27,17},{27,18},{27,19},{27,29},{27,30},{27,31},{27,32},{27,39},{27,40},{27,41},{28,-37},{28,-36},{28,-30},{28,-29},{28,-28},{28,-27},{28,-26},{28,-15},{28,-14},{28,-10},{28,-9},{28,-8},{28,-7},{28,10},{28,11},{28,12}, - {28,13},{28,17},{28,18},{28,29},{28,30},{28,31},{28,32},{28,33},{28,39},{28,40},{29,-33},{29,-32},{29,-31},{29,-30},{29,-29},{29,-28},{29,-27},{29,-26},{29,-21},{29,-20},{29,-19},{29,-18},{29,-11},{29,-10},{29,-9},{29,-8},{29,-7},{29,-6},{29,-1},{29,0}, - {29,1},{29,2},{29,3},{29,4},{29,9},{29,10},{29,11},{29,12},{29,13},{29,14},{29,21},{29,22},{29,23},{29,24},{29,29},{29,30},{29,31},{29,32},{29,33},{29,34},{29,35},{29,36},{30,-33},{30,-32},{30,-31},{30,-30},{30,-29},{30,-28},{30,-27},{30,-26}, - {30,-22},{30,-21},{30,-20},{30,-19},{30,-18},{30,-11},{30,-10},{30,-9},{30,-8},{30,-7},{30,-6},{30,-5},{30,-1},{30,0},{30,1},{30,2},{30,3},{30,4},{30,8},{30,9},{30,10},{30,11},{30,12},{30,13},{30,14},{30,21},{30,22},{30,23},{30,24},{30,25}, - {30,29},{30,30},{30,31},{30,32},{30,33},{30,34},{30,35},{30,36},{31,-32},{31,-31},{31,-30},{31,-29},{31,-28},{31,-27},{31,-23},{31,-22},{31,-21},{31,-15},{31,-14},{31,-6},{31,-5},{31,-4},{31,-1},{31,0},{31,3},{31,4},{31,7},{31,8},{31,9},{31,17}, - {31,18},{31,24},{31,25},{31,26},{31,30},{31,31},{31,32},{31,33},{31,34},{31,35},{32,-31},{32,-30},{32,-29},{32,-28},{32,-23},{32,-22},{32,-16},{32,-15},{32,-14},{32,-5},{32,-4},{32,-1},{32,0},{32,3},{32,4},{32,7},{32,8},{32,17},{32,18},{32,19}, - {32,25},{32,26},{32,31},{32,32},{32,33},{32,34},{33,-30},{33,-29},{33,-28},{33,-23},{33,-22},{33,-17},{33,-16},{33,-15},{33,-11},{33,-10},{33,-9},{33,-8},{33,11},{33,12},{33,13},{33,14},{33,18},{33,19},{33,20},{33,25},{33,26},{33,31},{33,32},{33,33}, - {34,-29},{34,-28},{34,-23},{34,-22},{34,-17},{34,-16},{34,-12},{34,-11},{34,-10},{34,-9},{34,-8},{34,11},{34,12},{34,13},{34,14},{34,15},{34,19},{34,20},{34,25},{34,26},{34,31},{34,32},{35,-17},{35,-16},{35,-13},{35,-12},{35,-11},{35,-10},{35,-9},{35,-3}, - {35,-2},{35,-1},{35,0},{35,3},{35,4},{35,5},{35,6},{35,12},{35,13},{35,14},{35,15},{35,16},{35,19},{35,20},{36,-17},{36,-16},{36,-13},{36,-12},{36,-11},{36,-10},{36,-4},{36,-3},{36,-2},{36,-1},{36,0},{36,3},{36,4},{36,5},{36,6},{36,7}, - {36,13},{36,14},{36,15},{36,16},{36,19},{36,20},{37,-27},{37,-26},{37,-25},{37,-24},{37,-21},{37,-20},{37,-13},{37,-12},{37,-5},{37,-4},{37,-3},{37,-2},{37,-1},{37,0},{37,1},{37,2},{37,3},{37,4},{37,5},{37,6},{37,7},{37,8},{37,15},{37,16}, - {37,23},{37,24},{37,27},{37,28},{37,29},{37,30},{38,-27},{38,-26},{38,-25},{38,-24},{38,-21},{38,-20},{38,-19},{38,-13},{38,-12},{38,-5},{38,-4},{38,-3},{38,-2},{38,-1},{38,0},{38,1},{38,2},{38,3},{38,4},{38,5},{38,6},{38,7},{38,8},{38,15}, - {38,16},{38,22},{38,23},{38,24},{38,27},{38,28},{38,29},{38,30},{39,-26},{39,-25},{39,-24},{39,-20},{39,-19},{39,-18},{39,-13},{39,-12},{39,-11},{39,-10},{39,-5},{39,-4},{39,7},{39,8},{39,13},{39,14},{39,15},{39,16},{39,21},{39,22},{39,23},{39,27}, - {39,28},{39,29},{40,-25},{40,-24},{40,-19},{40,-18},{40,-13},{40,-12},{40,-11},{40,-10},{40,-5},{40,-4},{40,7},{40,8},{40,13},{40,14},{40,15},{40,16},{40,21},{40,22},{40,27},{40,28},{41,-19},{41,-18},{41,-1},{41,0},{41,1},{41,2},{41,3},{41,4}, - {41,21},{41,22},{42,-19},{42,-18},{42,-17},{42,-1},{42,0},{42,1},{42,2},{42,3},{42,4},{42,20},{42,21},{42,22},{43,-18},{43,-17},{43,-16},{43,-15},{43,-14},{43,-13},{43,-12},{43,-9},{43,-8},{43,-1},{43,0},{43,1},{43,2},{43,3},{43,4},{43,11}, - {43,12},{43,15},{43,16},{43,17},{43,18},{43,19},{43,20},{43,21},{44,-17},{44,-16},{44,-15},{44,-14},{44,-13},{44,-12},{44,-9},{44,-8},{44,-7},{44,-2},{44,-1},{44,0},{44,1},{44,2},{44,3},{44,4},{44,5},{44,10},{44,11},{44,12},{44,15},{44,16}, - {44,17},{44,18},{44,19},{44,20},{45,-8},{45,-7},{45,-6},{45,-5},{45,-4},{45,-3},{45,-2},{45,-1},{45,4},{45,5},{45,6},{45,7},{45,8},{45,9},{45,10},{45,11},{46,-7},{46,-6},{46,-5},{46,-4},{46,-3},{46,-2},{46,5},{46,6},{46,7},{46,8}, - {46,9},{46,10},{47,-4},{47,-3},{47,-2},{47,1},{47,2},{47,5},{47,6},{47,7},{48,-3},{48,-2},{48,1},{48,2},{48,5},{48,6} + pattern = { + enabled = true, --- @settings enabled Weather pattern tiles will be added to spawn + pattern_tile = 'stone-path', --- @setting pattern_tile The tile to be used for the pattern + offset = { x=0, y=-2 }, --- @settings offset The position offset to apply to pattern tiles + locations = { --- @setting locations The location of the pattern tiles {x,y} + {-49,-3},{-49,-2},{-49,1},{-49,2},{-49,5},{-49,6},{-48,-4},{-48,-3},{-48,-2},{-48,1},{-48,2},{-48,5},{-48,6},{-48,7},{-47,-7},{-47,-6},{-47,-5},{-47,-4},{-47,-3},{-47,-2},{-47,5},{-47,6},{-47,7},{-47,8},{-47,9},{-47,10},{-46,-8},{-46,-7},{-46,-6},{-46,-5}, + {-46,-4},{-46,-3},{-46,-2},{-46,-1},{-46,4},{-46,5},{-46,6},{-46,7},{-46,8},{-46,9},{-46,10},{-46,11},{-45,-17},{-45,-16},{-45,-15},{-45,-14},{-45,-13},{-45,-12},{-45,-9},{-45,-8},{-45,-7},{-45,-2},{-45,-1},{-45,0},{-45,1},{-45,2},{-45,3},{-45,4},{-45,5},{-45,10}, + {-45,11},{-45,12},{-45,15},{-45,16},{-45,17},{-45,18},{-45,19},{-45,20},{-44,-18},{-44,-17},{-44,-16},{-44,-15},{-44,-14},{-44,-13},{-44,-12},{-44,-9},{-44,-8},{-44,-1},{-44,0},{-44,1},{-44,2},{-44,3},{-44,4},{-44,11},{-44,12},{-44,15},{-44,16},{-44,17},{-44,18},{-44,19}, + {-44,20},{-44,21},{-43,-19},{-43,-18},{-43,-17},{-43,-1},{-43,0},{-43,1},{-43,2},{-43,3},{-43,4},{-43,20},{-43,21},{-43,22},{-42,-19},{-42,-18},{-42,-1},{-42,0},{-42,1},{-42,2},{-42,3},{-42,4},{-42,21},{-42,22},{-41,-25},{-41,-24},{-41,-19},{-41,-18},{-41,-13},{-41,-12}, + {-41,-11},{-41,-10},{-41,-5},{-41,-4},{-41,7},{-41,8},{-41,13},{-41,14},{-41,15},{-41,16},{-41,21},{-41,22},{-41,27},{-41,28},{-40,-26},{-40,-25},{-40,-24},{-40,-20},{-40,-19},{-40,-18},{-40,-13},{-40,-12},{-40,-11},{-40,-10},{-40,-5},{-40,-4},{-40,7},{-40,8},{-40,13},{-40,14}, + {-40,15},{-40,16},{-40,21},{-40,22},{-40,23},{-40,27},{-40,28},{-40,29},{-39,-27},{-39,-26},{-39,-25},{-39,-24},{-39,-21},{-39,-20},{-39,-19},{-39,-13},{-39,-12},{-39,-5},{-39,-4},{-39,-3},{-39,-2},{-39,-1},{-39,0},{-39,1},{-39,2},{-39,3},{-39,4},{-39,5},{-39,6},{-39,7}, + {-39,8},{-39,15},{-39,16},{-39,22},{-39,23},{-39,24},{-39,27},{-39,28},{-39,29},{-39,30},{-38,-27},{-38,-26},{-38,-25},{-38,-24},{-38,-21},{-38,-20},{-38,-13},{-38,-12},{-38,-5},{-38,-4},{-38,-3},{-38,-2},{-38,-1},{-38,0},{-38,1},{-38,2},{-38,3},{-38,4},{-38,5},{-38,6}, + {-38,7},{-38,8},{-38,15},{-38,16},{-38,23},{-38,24},{-38,27},{-38,28},{-38,29},{-38,30},{-37,-17},{-37,-16},{-37,-13},{-37,-12},{-37,-11},{-37,-10},{-37,-4},{-37,-3},{-37,-2},{-37,-1},{-37,0},{-37,3},{-37,4},{-37,5},{-37,6},{-37,7},{-37,13},{-37,14},{-37,15},{-37,16}, + {-37,19},{-37,20},{-36,-17},{-36,-16},{-36,-13},{-36,-12},{-36,-11},{-36,-10},{-36,-9},{-36,-3},{-36,-2},{-36,-1},{-36,0},{-36,3},{-36,4},{-36,5},{-36,6},{-36,12},{-36,13},{-36,14},{-36,15},{-36,16},{-36,19},{-36,20},{-35,-29},{-35,-28},{-35,-23},{-35,-22},{-35,-17},{-35,-16}, + {-35,-12},{-35,-11},{-35,-10},{-35,-9},{-35,-8},{-35,11},{-35,12},{-35,13},{-35,14},{-35,15},{-35,19},{-35,20},{-35,25},{-35,26},{-35,31},{-35,32},{-34,-30},{-34,-29},{-34,-28},{-34,-23},{-34,-22},{-34,-17},{-34,-16},{-34,-15},{-34,-11},{-34,-10},{-34,-9},{-34,-8},{-34,11},{-34,12}, + {-34,13},{-34,14},{-34,18},{-34,19},{-34,20},{-34,25},{-34,26},{-34,31},{-34,32},{-34,33},{-33,-31},{-33,-30},{-33,-29},{-33,-28},{-33,-23},{-33,-22},{-33,-16},{-33,-15},{-33,-14},{-33,-5},{-33,-4},{-33,-1},{-33,0},{-33,3},{-33,4},{-33,7},{-33,8},{-33,17},{-33,18},{-33,19}, + {-33,25},{-33,26},{-33,31},{-33,32},{-33,33},{-33,34},{-32,-32},{-32,-31},{-32,-30},{-32,-29},{-32,-28},{-32,-27},{-32,-23},{-32,-22},{-32,-21},{-32,-15},{-32,-14},{-32,-6},{-32,-5},{-32,-4},{-32,-1},{-32,0},{-32,3},{-32,4},{-32,7},{-32,8},{-32,9},{-32,17},{-32,18},{-32,24}, + {-32,25},{-32,26},{-32,30},{-32,31},{-32,32},{-32,33},{-32,34},{-32,35},{-31,-33},{-31,-32},{-31,-31},{-31,-30},{-31,-29},{-31,-28},{-31,-27},{-31,-26},{-31,-22},{-31,-21},{-31,-20},{-31,-19},{-31,-18},{-31,-11},{-31,-10},{-31,-9},{-31,-8},{-31,-7},{-31,-6},{-31,-5},{-31,-1},{-31,0}, + {-31,1},{-31,2},{-31,3},{-31,4},{-31,8},{-31,9},{-31,10},{-31,11},{-31,12},{-31,13},{-31,14},{-31,21},{-31,22},{-31,23},{-31,24},{-31,25},{-31,29},{-31,30},{-31,31},{-31,32},{-31,33},{-31,34},{-31,35},{-31,36},{-30,-33},{-30,-32},{-30,-31},{-30,-30},{-30,-29},{-30,-28}, + {-30,-27},{-30,-26},{-30,-21},{-30,-20},{-30,-19},{-30,-18},{-30,-11},{-30,-10},{-30,-9},{-30,-8},{-30,-7},{-30,-6},{-30,-1},{-30,0},{-30,1},{-30,2},{-30,3},{-30,4},{-30,9},{-30,10},{-30,11},{-30,12},{-30,13},{-30,14},{-30,21},{-30,22},{-30,23},{-30,24},{-30,29},{-30,30}, + {-30,31},{-30,32},{-30,33},{-30,34},{-30,35},{-30,36},{-29,-37},{-29,-36},{-29,-30},{-29,-29},{-29,-28},{-29,-27},{-29,-26},{-29,-15},{-29,-14},{-29,-10},{-29,-9},{-29,-8},{-29,-7},{-29,10},{-29,11},{-29,12},{-29,13},{-29,17},{-29,18},{-29,29},{-29,30},{-29,31},{-29,32},{-29,33}, + {-29,39},{-29,40},{-28,-38},{-28,-37},{-28,-36},{-28,-29},{-28,-28},{-28,-27},{-28,-26},{-28,-16},{-28,-15},{-28,-14},{-28,-9},{-28,-8},{-28,11},{-28,12},{-28,17},{-28,18},{-28,19},{-28,29},{-28,30},{-28,31},{-28,32},{-28,39},{-28,40},{-28,41},{-27,-39},{-27,-38},{-27,-37},{-27,-36}, + {-27,-23},{-27,-22},{-27,-19},{-27,-18},{-27,-17},{-27,-16},{-27,-15},{-27,-5},{-27,-4},{-27,-1},{-27,0},{-27,1},{-27,2},{-27,3},{-27,4},{-27,7},{-27,8},{-27,18},{-27,19},{-27,20},{-27,21},{-27,22},{-27,25},{-27,26},{-27,39},{-27,40},{-27,41},{-27,42},{-26,-39},{-26,-38}, + {-26,-37},{-26,-36},{-26,-24},{-26,-23},{-26,-22},{-26,-19},{-26,-18},{-26,-17},{-26,-16},{-26,-6},{-26,-5},{-26,-4},{-26,-1},{-26,0},{-26,1},{-26,2},{-26,3},{-26,4},{-26,7},{-26,8},{-26,9},{-26,19},{-26,20},{-26,21},{-26,22},{-26,25},{-26,26},{-26,27},{-26,39},{-26,40}, + {-26,41},{-26,42},{-25,-33},{-25,-32},{-25,-31},{-25,-30},{-25,-25},{-25,-24},{-25,-23},{-25,-22},{-25,-19},{-25,-18},{-25,-17},{-25,-9},{-25,-8},{-25,-7},{-25,-6},{-25,-5},{-25,-4},{-25,-1},{-25,0},{-25,1},{-25,2},{-25,3},{-25,4},{-25,7},{-25,8},{-25,9},{-25,10},{-25,11}, + {-25,12},{-25,20},{-25,21},{-25,22},{-25,25},{-25,26},{-25,27},{-25,28},{-25,33},{-25,34},{-25,35},{-25,36},{-24,-33},{-24,-32},{-24,-31},{-24,-30},{-24,-29},{-24,-25},{-24,-24},{-24,-23},{-24,-22},{-24,-19},{-24,-18},{-24,-9},{-24,-8},{-24,-7},{-24,-6},{-24,-5},{-24,-4},{-24,-1}, + {-24,0},{-24,1},{-24,2},{-24,3},{-24,4},{-24,7},{-24,8},{-24,9},{-24,10},{-24,11},{-24,12},{-24,21},{-24,22},{-24,25},{-24,26},{-24,27},{-24,28},{-24,32},{-24,33},{-24,34},{-24,35},{-24,36},{-23,-37},{-23,-36},{-23,-30},{-23,-29},{-23,-28},{-23,-19},{-23,-18},{-23,-15}, + {-23,-14},{-23,-9},{-23,-8},{-23,-7},{-23,-6},{-23,-5},{-23,0},{-23,1},{-23,2},{-23,3},{-23,8},{-23,9},{-23,10},{-23,11},{-23,12},{-23,17},{-23,18},{-23,21},{-23,22},{-23,31},{-23,32},{-23,33},{-23,39},{-23,40},{-22,-38},{-22,-37},{-22,-36},{-22,-29},{-22,-28},{-22,-19}, + {-22,-18},{-22,-15},{-22,-14},{-22,-13},{-22,-9},{-22,-8},{-22,-7},{-22,-6},{-22,1},{-22,2},{-22,9},{-22,10},{-22,11},{-22,12},{-22,16},{-22,17},{-22,18},{-22,21},{-22,22},{-22,31},{-22,32},{-22,39},{-22,40},{-22,41},{-21,-41},{-21,-40},{-21,-39},{-21,-38},{-21,-37},{-21,-29}, + {-21,-28},{-21,-25},{-21,-24},{-21,-23},{-21,-22},{-21,-21},{-21,-20},{-21,-19},{-21,-18},{-21,-15},{-21,-14},{-21,-13},{-21,-12},{-21,-3},{-21,-2},{-21,5},{-21,6},{-21,15},{-21,16},{-21,17},{-21,18},{-21,21},{-21,22},{-21,23},{-21,24},{-21,25},{-21,26},{-21,27},{-21,28},{-21,31}, + {-21,32},{-21,40},{-21,41},{-21,42},{-21,43},{-21,44},{-20,-42},{-20,-41},{-20,-40},{-20,-39},{-20,-38},{-20,-29},{-20,-28},{-20,-25},{-20,-24},{-20,-23},{-20,-22},{-20,-21},{-20,-20},{-20,-19},{-20,-18},{-20,-15},{-20,-14},{-20,-13},{-20,-12},{-20,-3},{-20,-2},{-20,-1},{-20,4},{-20,5}, + {-20,6},{-20,15},{-20,16},{-20,17},{-20,18},{-20,21},{-20,22},{-20,23},{-20,24},{-20,25},{-20,26},{-20,27},{-20,28},{-20,31},{-20,32},{-20,41},{-20,42},{-20,43},{-20,44},{-20,45},{-19,-43},{-19,-42},{-19,-41},{-19,-35},{-19,-34},{-19,-33},{-19,-32},{-19,-25},{-19,-24},{-19,-23}, + {-19,-15},{-19,-14},{-19,-13},{-19,-9},{-19,-8},{-19,-7},{-19,-6},{-19,-2},{-19,-1},{-19,0},{-19,1},{-19,2},{-19,3},{-19,4},{-19,5},{-19,9},{-19,10},{-19,11},{-19,12},{-19,16},{-19,17},{-19,18},{-19,26},{-19,27},{-19,28},{-19,35},{-19,36},{-19,37},{-19,38},{-19,44}, + {-19,45},{-19,46},{-18,-43},{-18,-42},{-18,-35},{-18,-34},{-18,-33},{-18,-32},{-18,-31},{-18,-26},{-18,-25},{-18,-24},{-18,-15},{-18,-14},{-18,-10},{-18,-9},{-18,-8},{-18,-7},{-18,-6},{-18,-1},{-18,0},{-18,1},{-18,2},{-18,3},{-18,4},{-18,9},{-18,10},{-18,11},{-18,12},{-18,13}, + {-18,17},{-18,18},{-18,27},{-18,28},{-18,29},{-18,34},{-18,35},{-18,36},{-18,37},{-18,38},{-18,45},{-18,46},{-17,-43},{-17,-42},{-17,-32},{-17,-31},{-17,-30},{-17,-27},{-17,-26},{-17,-25},{-17,-21},{-17,-20},{-17,-19},{-17,-18},{-17,-17},{-17,-16},{-17,-15},{-17,-14},{-17,-11},{-17,-10}, + {-17,-9},{-17,-8},{-17,-7},{-17,-6},{-17,0},{-17,1},{-17,2},{-17,3},{-17,9},{-17,10},{-17,11},{-17,12},{-17,13},{-17,14},{-17,17},{-17,18},{-17,19},{-17,20},{-17,21},{-17,22},{-17,23},{-17,24},{-17,28},{-17,29},{-17,30},{-17,33},{-17,34},{-17,35},{-17,45},{-17,46}, + {-16,-43},{-16,-42},{-16,-31},{-16,-30},{-16,-27},{-16,-26},{-16,-21},{-16,-20},{-16,-19},{-16,-18},{-16,-17},{-16,-16},{-16,-15},{-16,-14},{-16,-11},{-16,-10},{-16,-9},{-16,-8},{-16,-7},{-16,-6},{-16,1},{-16,2},{-16,9},{-16,10},{-16,11},{-16,12},{-16,13},{-16,14},{-16,17},{-16,18}, + {-16,19},{-16,20},{-16,21},{-16,22},{-16,23},{-16,24},{-16,29},{-16,30},{-16,33},{-16,34},{-16,45},{-16,46},{-15,-43},{-15,-42},{-15,-39},{-15,-38},{-15,-37},{-15,-36},{-15,-35},{-15,-34},{-15,-20},{-15,-19},{-15,-18},{-15,-17},{-15,-10},{-15,-9},{-15,-8},{-15,-7},{-15,-3},{-15,-2}, + {-15,1},{-15,2},{-15,5},{-15,6},{-15,10},{-15,11},{-15,12},{-15,13},{-15,20},{-15,21},{-15,22},{-15,23},{-15,37},{-15,38},{-15,39},{-15,40},{-15,41},{-15,42},{-15,45},{-15,46},{-14,-43},{-14,-42},{-14,-39},{-14,-38},{-14,-37},{-14,-36},{-14,-35},{-14,-34},{-14,-33},{-14,-19}, + {-14,-18},{-14,-9},{-14,-8},{-14,-4},{-14,-3},{-14,-2},{-14,1},{-14,2},{-14,5},{-14,6},{-14,7},{-14,11},{-14,12},{-14,21},{-14,22},{-14,36},{-14,37},{-14,38},{-14,39},{-14,40},{-14,41},{-14,42},{-14,45},{-14,46},{-13,-39},{-13,-38},{-13,-35},{-13,-34},{-13,-33},{-13,-32}, + {-13,-29},{-13,-28},{-13,-15},{-13,-14},{-13,-5},{-13,-4},{-13,-3},{-13,-2},{-13,5},{-13,6},{-13,7},{-13,8},{-13,17},{-13,18},{-13,31},{-13,32},{-13,35},{-13,36},{-13,37},{-13,38},{-13,41},{-13,42},{-12,-39},{-12,-38},{-12,-35},{-12,-34},{-12,-33},{-12,-32},{-12,-29},{-12,-28}, + {-12,-27},{-12,-16},{-12,-15},{-12,-14},{-12,-13},{-12,-5},{-12,-4},{-12,-3},{-12,-2},{-12,5},{-12,6},{-12,7},{-12,8},{-12,16},{-12,17},{-12,18},{-12,19},{-12,30},{-12,31},{-12,32},{-12,35},{-12,36},{-12,37},{-12,38},{-12,41},{-12,42},{-11,-43},{-11,-42},{-11,-34},{-11,-33}, + {-11,-32},{-11,-29},{-11,-28},{-11,-27},{-11,-26},{-11,-23},{-11,-22},{-11,-21},{-11,-20},{-11,-17},{-11,-16},{-11,-15},{-11,-14},{-11,-13},{-11,-12},{-11,-9},{-11,-8},{-11,1},{-11,2},{-11,11},{-11,12},{-11,15},{-11,16},{-11,17},{-11,18},{-11,19},{-11,20},{-11,23},{-11,24},{-11,25}, + {-11,26},{-11,29},{-11,30},{-11,31},{-11,32},{-11,35},{-11,36},{-11,37},{-11,45},{-11,46},{-10,-44},{-10,-43},{-10,-42},{-10,-33},{-10,-32},{-10,-29},{-10,-28},{-10,-27},{-10,-26},{-10,-23},{-10,-22},{-10,-21},{-10,-20},{-10,-17},{-10,-16},{-10,-15},{-10,-14},{-10,-13},{-10,-12},{-10,-9}, + {-10,-8},{-10,-7},{-10,0},{-10,1},{-10,2},{-10,3},{-10,10},{-10,11},{-10,12},{-10,15},{-10,16},{-10,17},{-10,18},{-10,19},{-10,20},{-10,23},{-10,24},{-10,25},{-10,26},{-10,29},{-10,30},{-10,31},{-10,32},{-10,35},{-10,36},{-10,45},{-10,46},{-10,47},{-9,-45},{-9,-44}, + {-9,-43},{-9,-29},{-9,-28},{-9,-27},{-9,-23},{-9,-22},{-9,-21},{-9,-20},{-9,-17},{-9,-16},{-9,-15},{-9,-14},{-9,-13},{-9,-8},{-9,-7},{-9,-6},{-9,-5},{-9,-1},{-9,0},{-9,1},{-9,2},{-9,3},{-9,4},{-9,8},{-9,9},{-9,10},{-9,11},{-9,16},{-9,17},{-9,18}, + {-9,19},{-9,20},{-9,23},{-9,24},{-9,25},{-9,26},{-9,30},{-9,31},{-9,32},{-9,46},{-9,47},{-9,48},{-8,-45},{-8,-44},{-8,-30},{-8,-29},{-8,-28},{-8,-24},{-8,-23},{-8,-22},{-8,-21},{-8,-20},{-8,-17},{-8,-16},{-8,-15},{-8,-14},{-8,-7},{-8,-6},{-8,-5},{-8,-4}, + {-8,-1},{-8,0},{-8,1},{-8,2},{-8,3},{-8,4},{-8,7},{-8,8},{-8,9},{-8,10},{-8,17},{-8,18},{-8,19},{-8,20},{-8,23},{-8,24},{-8,25},{-8,26},{-8,27},{-8,31},{-8,32},{-8,33},{-8,47},{-8,48},{-7,-45},{-7,-44},{-7,-39},{-7,-38},{-7,-37},{-7,-36}, + {-7,-31},{-7,-30},{-7,-29},{-7,-25},{-7,-24},{-7,-23},{-7,-22},{-7,-21},{-7,-11},{-7,-10},{-7,-7},{-7,-6},{-7,-5},{-7,-4},{-7,7},{-7,8},{-7,9},{-7,10},{-7,13},{-7,14},{-7,24},{-7,25},{-7,26},{-7,27},{-7,28},{-7,32},{-7,33},{-7,34},{-7,39},{-7,40}, + {-7,41},{-7,42},{-7,47},{-7,48},{-6,-46},{-6,-45},{-6,-44},{-6,-39},{-6,-38},{-6,-37},{-6,-36},{-6,-35},{-6,-31},{-6,-30},{-6,-25},{-6,-24},{-6,-23},{-6,-22},{-6,-12},{-6,-11},{-6,-10},{-6,-6},{-6,-5},{-6,8},{-6,9},{-6,13},{-6,14},{-6,15},{-6,25},{-6,26}, + {-6,27},{-6,28},{-6,33},{-6,34},{-6,38},{-6,39},{-6,40},{-6,41},{-6,42},{-6,47},{-6,48},{-6,49},{-5,-47},{-5,-46},{-5,-45},{-5,-44},{-5,-37},{-5,-36},{-5,-35},{-5,-34},{-5,-19},{-5,-18},{-5,-13},{-5,-12},{-5,-11},{-5,-10},{-5,-1},{-5,0},{-5,1},{-5,2}, + {-5,3},{-5,4},{-5,13},{-5,14},{-5,15},{-5,16},{-5,21},{-5,22},{-5,37},{-5,38},{-5,39},{-5,40},{-5,47},{-5,48},{-5,49},{-5,50},{-4,-47},{-4,-46},{-4,-45},{-4,-44},{-4,-43},{-4,-37},{-4,-36},{-4,-35},{-4,-34},{-4,-19},{-4,-18},{-4,-17},{-4,-13},{-4,-12}, + {-4,-11},{-4,-10},{-4,-2},{-4,-1},{-4,0},{-4,1},{-4,2},{-4,3},{-4,4},{-4,5},{-4,13},{-4,14},{-4,15},{-4,16},{-4,20},{-4,21},{-4,22},{-4,37},{-4,38},{-4,39},{-4,40},{-4,46},{-4,47},{-4,48},{-4,49},{-4,50},{-3,-44},{-3,-43},{-3,-42},{-3,-41}, + {-3,-40},{-3,-37},{-3,-36},{-3,-35},{-3,-34},{-3,-31},{-3,-30},{-3,-29},{-3,-28},{-3,-25},{-3,-24},{-3,-23},{-3,-22},{-3,-18},{-3,-17},{-3,-16},{-3,-7},{-3,-6},{-3,-3},{-3,-2},{-3,-1},{-3,0},{-3,3},{-3,4},{-3,5},{-3,6},{-3,9},{-3,10},{-3,19},{-3,20}, + {-3,21},{-3,25},{-3,26},{-3,27},{-3,28},{-3,31},{-3,32},{-3,33},{-3,34},{-3,37},{-3,38},{-3,39},{-3,40},{-3,43},{-3,44},{-3,45},{-3,46},{-3,47},{-2,-43},{-2,-42},{-2,-41},{-2,-40},{-2,-37},{-2,-36},{-2,-35},{-2,-34},{-2,-31},{-2,-30},{-2,-29},{-2,-28}, + {-2,-25},{-2,-24},{-2,-23},{-2,-22},{-2,-21},{-2,-17},{-2,-16},{-2,-15},{-2,-8},{-2,-7},{-2,-6},{-2,-3},{-2,-2},{-2,-1},{-2,0},{-2,3},{-2,4},{-2,5},{-2,6},{-2,9},{-2,10},{-2,11},{-2,18},{-2,19},{-2,20},{-2,24},{-2,25},{-2,26},{-2,27},{-2,28}, + {-2,31},{-2,32},{-2,33},{-2,34},{-2,37},{-2,38},{-2,39},{-2,40},{-2,43},{-2,44},{-2,45},{-2,46},{-1,-47},{-1,-46},{-1,-43},{-1,-42},{-1,-41},{-1,-40},{-1,-37},{-1,-36},{-1,-29},{-1,-28},{-1,-25},{-1,-24},{-1,-23},{-1,-22},{-1,-21},{-1,-20},{-1,-17},{-1,-16}, + {-1,-15},{-1,-14},{-1,-13},{-1,-12},{-1,-9},{-1,-8},{-1,-7},{-1,-6},{-1,-3},{-1,-2},{-1,5},{-1,6},{-1,9},{-1,10},{-1,11},{-1,12},{-1,15},{-1,16},{-1,17},{-1,18},{-1,19},{-1,20},{-1,23},{-1,24},{-1,25},{-1,26},{-1,27},{-1,28},{-1,31},{-1,32}, + {-1,39},{-1,40},{-1,43},{-1,44},{-1,45},{-1,46},{-1,49},{-1,50},{0,-47},{0,-46},{0,-43},{0,-42},{0,-41},{0,-40},{0,-37},{0,-36},{0,-29},{0,-28},{0,-25},{0,-24},{0,-23},{0,-22},{0,-21},{0,-20},{0,-17},{0,-16},{0,-15},{0,-14},{0,-13},{0,-12}, + {0,-9},{0,-8},{0,-7},{0,-6},{0,-3},{0,-2},{0,5},{0,6},{0,9},{0,10},{0,11},{0,12},{0,15},{0,16},{0,17},{0,18},{0,19},{0,20},{0,23},{0,24},{0,25},{0,26},{0,27},{0,28},{0,31},{0,32},{0,39},{0,40},{0,43},{0,44}, + {0,45},{0,46},{0,49},{0,50},{1,-43},{1,-42},{1,-41},{1,-40},{1,-37},{1,-36},{1,-35},{1,-34},{1,-31},{1,-30},{1,-29},{1,-28},{1,-25},{1,-24},{1,-23},{1,-22},{1,-21},{1,-17},{1,-16},{1,-15},{1,-8},{1,-7},{1,-6},{1,-3},{1,-2},{1,-1}, + {1,0},{1,3},{1,4},{1,5},{1,6},{1,9},{1,10},{1,11},{1,18},{1,19},{1,20},{1,24},{1,25},{1,26},{1,27},{1,28},{1,31},{1,32},{1,33},{1,34},{1,37},{1,38},{1,39},{1,40},{1,43},{1,44},{1,45},{1,46},{2,-44},{2,-43}, + {2,-42},{2,-41},{2,-40},{2,-37},{2,-36},{2,-35},{2,-34},{2,-31},{2,-30},{2,-29},{2,-28},{2,-25},{2,-24},{2,-23},{2,-22},{2,-18},{2,-17},{2,-16},{2,-7},{2,-6},{2,-3},{2,-2},{2,-1},{2,0},{2,3},{2,4},{2,5},{2,6},{2,9},{2,10}, + {2,19},{2,20},{2,21},{2,25},{2,26},{2,27},{2,28},{2,31},{2,32},{2,33},{2,34},{2,37},{2,38},{2,39},{2,40},{2,43},{2,44},{2,45},{2,46},{2,47},{3,-47},{3,-46},{3,-45},{3,-44},{3,-43},{3,-37},{3,-36},{3,-35},{3,-34},{3,-19}, + {3,-18},{3,-17},{3,-13},{3,-12},{3,-11},{3,-10},{3,-2},{3,-1},{3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,13},{3,14},{3,15},{3,16},{3,20},{3,21},{3,22},{3,37},{3,38},{3,39},{3,40},{3,46},{3,47},{3,48},{3,49},{3,50}, + {4,-47},{4,-46},{4,-45},{4,-44},{4,-37},{4,-36},{4,-35},{4,-34},{4,-19},{4,-18},{4,-13},{4,-12},{4,-11},{4,-10},{4,-1},{4,0},{4,1},{4,2},{4,3},{4,4},{4,13},{4,14},{4,15},{4,16},{4,21},{4,22},{4,37},{4,38},{4,39},{4,40}, + {4,47},{4,48},{4,49},{4,50},{5,-46},{5,-45},{5,-44},{5,-39},{5,-38},{5,-37},{5,-36},{5,-35},{5,-31},{5,-30},{5,-25},{5,-24},{5,-23},{5,-22},{5,-12},{5,-11},{5,-10},{5,-6},{5,-5},{5,8},{5,9},{5,13},{5,14},{5,15},{5,25},{5,26}, + {5,27},{5,28},{5,33},{5,34},{5,38},{5,39},{5,40},{5,41},{5,42},{5,47},{5,48},{5,49},{6,-45},{6,-44},{6,-39},{6,-38},{6,-37},{6,-36},{6,-31},{6,-30},{6,-29},{6,-25},{6,-24},{6,-23},{6,-22},{6,-21},{6,-11},{6,-10},{6,-7},{6,-6}, + {6,-5},{6,-4},{6,7},{6,8},{6,9},{6,10},{6,13},{6,14},{6,24},{6,25},{6,26},{6,27},{6,28},{6,32},{6,33},{6,34},{6,39},{6,40},{6,41},{6,42},{6,47},{6,48},{7,-45},{7,-44},{7,-30},{7,-29},{7,-28},{7,-24},{7,-23},{7,-22}, + {7,-21},{7,-20},{7,-17},{7,-16},{7,-15},{7,-14},{7,-7},{7,-6},{7,-5},{7,-4},{7,-1},{7,0},{7,1},{7,2},{7,3},{7,4},{7,7},{7,8},{7,9},{7,10},{7,17},{7,18},{7,19},{7,20},{7,23},{7,24},{7,25},{7,26},{7,27},{7,31}, + {7,32},{7,33},{7,47},{7,48},{8,-45},{8,-44},{8,-43},{8,-29},{8,-28},{8,-27},{8,-23},{8,-22},{8,-21},{8,-20},{8,-17},{8,-16},{8,-15},{8,-14},{8,-13},{8,-8},{8,-7},{8,-6},{8,-5},{8,-1},{8,0},{8,1},{8,2},{8,3},{8,4},{8,8}, + {8,9},{8,10},{8,11},{8,16},{8,17},{8,18},{8,19},{8,20},{8,23},{8,24},{8,25},{8,26},{8,30},{8,31},{8,32},{8,46},{8,47},{8,48},{9,-44},{9,-43},{9,-42},{9,-33},{9,-32},{9,-29},{9,-28},{9,-27},{9,-26},{9,-23},{9,-22},{9,-21}, + {9,-20},{9,-17},{9,-16},{9,-15},{9,-14},{9,-13},{9,-12},{9,-9},{9,-8},{9,-7},{9,0},{9,1},{9,2},{9,3},{9,10},{9,11},{9,12},{9,15},{9,16},{9,17},{9,18},{9,19},{9,20},{9,23},{9,24},{9,25},{9,26},{9,29},{9,30},{9,31}, + {9,32},{9,35},{9,36},{9,45},{9,46},{9,47},{10,-43},{10,-42},{10,-34},{10,-33},{10,-32},{10,-29},{10,-28},{10,-27},{10,-26},{10,-23},{10,-22},{10,-21},{10,-20},{10,-17},{10,-16},{10,-15},{10,-14},{10,-13},{10,-12},{10,-9},{10,-8},{10,1},{10,2},{10,11}, + {10,12},{10,15},{10,16},{10,17},{10,18},{10,19},{10,20},{10,23},{10,24},{10,25},{10,26},{10,29},{10,30},{10,31},{10,32},{10,35},{10,36},{10,37},{10,45},{10,46},{11,-39},{11,-38},{11,-35},{11,-34},{11,-33},{11,-32},{11,-29},{11,-28},{11,-27},{11,-16}, + {11,-15},{11,-14},{11,-13},{11,-5},{11,-4},{11,-3},{11,-2},{11,5},{11,6},{11,7},{11,8},{11,16},{11,17},{11,18},{11,19},{11,30},{11,31},{11,32},{11,35},{11,36},{11,37},{11,38},{11,41},{11,42},{12,-39},{12,-38},{12,-35},{12,-34},{12,-33},{12,-32}, + {12,-29},{12,-28},{12,-15},{12,-14},{12,-5},{12,-4},{12,-3},{12,-2},{12,5},{12,6},{12,7},{12,8},{12,17},{12,18},{12,31},{12,32},{12,35},{12,36},{12,37},{12,38},{12,41},{12,42},{13,-43},{13,-42},{13,-39},{13,-38},{13,-37},{13,-36},{13,-35},{13,-34}, + {13,-33},{13,-19},{13,-18},{13,-9},{13,-8},{13,-4},{13,-3},{13,-2},{13,1},{13,2},{13,5},{13,6},{13,7},{13,11},{13,12},{13,21},{13,22},{13,36},{13,37},{13,38},{13,39},{13,40},{13,41},{13,42},{13,45},{13,46},{14,-43},{14,-42},{14,-39},{14,-38}, + {14,-37},{14,-36},{14,-35},{14,-34},{14,-20},{14,-19},{14,-18},{14,-17},{14,-10},{14,-9},{14,-8},{14,-7},{14,-3},{14,-2},{14,1},{14,2},{14,5},{14,6},{14,10},{14,11},{14,12},{14,13},{14,20},{14,21},{14,22},{14,23},{14,37},{14,38},{14,39},{14,40}, + {14,41},{14,42},{14,45},{14,46},{15,-43},{15,-42},{15,-31},{15,-30},{15,-27},{15,-26},{15,-21},{15,-20},{15,-19},{15,-18},{15,-17},{15,-16},{15,-15},{15,-14},{15,-11},{15,-10},{15,-9},{15,-8},{15,-7},{15,-6},{15,1},{15,2},{15,9},{15,10},{15,11},{15,12}, + {15,13},{15,14},{15,17},{15,18},{15,19},{15,20},{15,21},{15,22},{15,23},{15,24},{15,29},{15,30},{15,33},{15,34},{15,45},{15,46},{16,-43},{16,-42},{16,-32},{16,-31},{16,-30},{16,-27},{16,-26},{16,-25},{16,-21},{16,-20},{16,-19},{16,-18},{16,-17},{16,-16}, + {16,-15},{16,-14},{16,-11},{16,-10},{16,-9},{16,-8},{16,-7},{16,-6},{16,0},{16,1},{16,2},{16,3},{16,9},{16,10},{16,11},{16,12},{16,13},{16,14},{16,17},{16,18},{16,19},{16,20},{16,21},{16,22},{16,23},{16,24},{16,28},{16,29},{16,30},{16,33}, + {16,34},{16,35},{16,45},{16,46},{17,-43},{17,-42},{17,-35},{17,-34},{17,-33},{17,-32},{17,-31},{17,-26},{17,-25},{17,-24},{17,-15},{17,-14},{17,-10},{17,-9},{17,-8},{17,-7},{17,-6},{17,-1},{17,0},{17,1},{17,2},{17,3},{17,4},{17,9},{17,10},{17,11}, + {17,12},{17,13},{17,17},{17,18},{17,27},{17,28},{17,29},{17,34},{17,35},{17,36},{17,37},{17,38},{17,45},{17,46},{18,-43},{18,-42},{18,-41},{18,-35},{18,-34},{18,-33},{18,-32},{18,-25},{18,-24},{18,-23},{18,-15},{18,-14},{18,-13},{18,-9},{18,-8},{18,-7}, + {18,-6},{18,-2},{18,-1},{18,0},{18,1},{18,2},{18,3},{18,4},{18,5},{18,9},{18,10},{18,11},{18,12},{18,16},{18,17},{18,18},{18,26},{18,27},{18,28},{18,35},{18,36},{18,37},{18,38},{18,44},{18,45},{18,46},{19,-42},{19,-41},{19,-40},{19,-39}, + {19,-38},{19,-29},{19,-28},{19,-25},{19,-24},{19,-23},{19,-22},{19,-21},{19,-20},{19,-19},{19,-18},{19,-15},{19,-14},{19,-13},{19,-12},{19,-3},{19,-2},{19,-1},{19,4},{19,5},{19,6},{19,15},{19,16},{19,17},{19,18},{19,21},{19,22},{19,23},{19,24},{19,25}, + {19,26},{19,27},{19,28},{19,31},{19,32},{19,41},{19,42},{19,43},{19,44},{19,45},{20,-41},{20,-40},{20,-39},{20,-38},{20,-37},{20,-29},{20,-28},{20,-25},{20,-24},{20,-23},{20,-22},{20,-21},{20,-20},{20,-19},{20,-18},{20,-15},{20,-14},{20,-13},{20,-12},{20,-3}, + {20,-2},{20,5},{20,6},{20,15},{20,16},{20,17},{20,18},{20,21},{20,22},{20,23},{20,24},{20,25},{20,26},{20,27},{20,28},{20,31},{20,32},{20,40},{20,41},{20,42},{20,43},{20,44},{21,-38},{21,-37},{21,-36},{21,-29},{21,-28},{21,-19},{21,-18},{21,-15}, + {21,-14},{21,-13},{21,-9},{21,-8},{21,-7},{21,-6},{21,1},{21,2},{21,9},{21,10},{21,11},{21,12},{21,16},{21,17},{21,18},{21,21},{21,22},{21,31},{21,32},{21,39},{21,40},{21,41},{22,-37},{22,-36},{22,-30},{22,-29},{22,-28},{22,-19},{22,-18},{22,-15}, + {22,-14},{22,-9},{22,-8},{22,-7},{22,-6},{22,-5},{22,0},{22,1},{22,2},{22,3},{22,8},{22,9},{22,10},{22,11},{22,12},{22,17},{22,18},{22,21},{22,22},{22,31},{22,32},{22,33},{22,39},{22,40},{23,-33},{23,-32},{23,-31},{23,-30},{23,-29},{23,-25}, + {23,-24},{23,-23},{23,-22},{23,-19},{23,-18},{23,-9},{23,-8},{23,-7},{23,-6},{23,-5},{23,-4},{23,-1},{23,0},{23,1},{23,2},{23,3},{23,4},{23,7},{23,8},{23,9},{23,10},{23,11},{23,12},{23,21},{23,22},{23,25},{23,26},{23,27},{23,28},{23,32}, + {23,33},{23,34},{23,35},{23,36},{24,-33},{24,-32},{24,-31},{24,-30},{24,-25},{24,-24},{24,-23},{24,-22},{24,-19},{24,-18},{24,-17},{24,-9},{24,-8},{24,-7},{24,-6},{24,-5},{24,-4},{24,-1},{24,0},{24,1},{24,2},{24,3},{24,4},{24,7},{24,8},{24,9}, + {24,10},{24,11},{24,12},{24,20},{24,21},{24,22},{24,25},{24,26},{24,27},{24,28},{24,33},{24,34},{24,35},{24,36},{25,-39},{25,-38},{25,-37},{25,-36},{25,-24},{25,-23},{25,-22},{25,-19},{25,-18},{25,-17},{25,-16},{25,-6},{25,-5},{25,-4},{25,-1},{25,0}, + {25,1},{25,2},{25,3},{25,4},{25,7},{25,8},{25,9},{25,19},{25,20},{25,21},{25,22},{25,25},{25,26},{25,27},{25,39},{25,40},{25,41},{25,42},{26,-39},{26,-38},{26,-37},{26,-36},{26,-23},{26,-22},{26,-19},{26,-18},{26,-17},{26,-16},{26,-15},{26,-5}, + {26,-4},{26,-1},{26,0},{26,1},{26,2},{26,3},{26,4},{26,7},{26,8},{26,18},{26,19},{26,20},{26,21},{26,22},{26,25},{26,26},{26,39},{26,40},{26,41},{26,42},{27,-38},{27,-37},{27,-36},{27,-29},{27,-28},{27,-27},{27,-26},{27,-16},{27,-15},{27,-14}, + {27,-9},{27,-8},{27,11},{27,12},{27,17},{27,18},{27,19},{27,29},{27,30},{27,31},{27,32},{27,39},{27,40},{27,41},{28,-37},{28,-36},{28,-30},{28,-29},{28,-28},{28,-27},{28,-26},{28,-15},{28,-14},{28,-10},{28,-9},{28,-8},{28,-7},{28,10},{28,11},{28,12}, + {28,13},{28,17},{28,18},{28,29},{28,30},{28,31},{28,32},{28,33},{28,39},{28,40},{29,-33},{29,-32},{29,-31},{29,-30},{29,-29},{29,-28},{29,-27},{29,-26},{29,-21},{29,-20},{29,-19},{29,-18},{29,-11},{29,-10},{29,-9},{29,-8},{29,-7},{29,-6},{29,-1},{29,0}, + {29,1},{29,2},{29,3},{29,4},{29,9},{29,10},{29,11},{29,12},{29,13},{29,14},{29,21},{29,22},{29,23},{29,24},{29,29},{29,30},{29,31},{29,32},{29,33},{29,34},{29,35},{29,36},{30,-33},{30,-32},{30,-31},{30,-30},{30,-29},{30,-28},{30,-27},{30,-26}, + {30,-22},{30,-21},{30,-20},{30,-19},{30,-18},{30,-11},{30,-10},{30,-9},{30,-8},{30,-7},{30,-6},{30,-5},{30,-1},{30,0},{30,1},{30,2},{30,3},{30,4},{30,8},{30,9},{30,10},{30,11},{30,12},{30,13},{30,14},{30,21},{30,22},{30,23},{30,24},{30,25}, + {30,29},{30,30},{30,31},{30,32},{30,33},{30,34},{30,35},{30,36},{31,-32},{31,-31},{31,-30},{31,-29},{31,-28},{31,-27},{31,-23},{31,-22},{31,-21},{31,-15},{31,-14},{31,-6},{31,-5},{31,-4},{31,-1},{31,0},{31,3},{31,4},{31,7},{31,8},{31,9},{31,17}, + {31,18},{31,24},{31,25},{31,26},{31,30},{31,31},{31,32},{31,33},{31,34},{31,35},{32,-31},{32,-30},{32,-29},{32,-28},{32,-23},{32,-22},{32,-16},{32,-15},{32,-14},{32,-5},{32,-4},{32,-1},{32,0},{32,3},{32,4},{32,7},{32,8},{32,17},{32,18},{32,19}, + {32,25},{32,26},{32,31},{32,32},{32,33},{32,34},{33,-30},{33,-29},{33,-28},{33,-23},{33,-22},{33,-17},{33,-16},{33,-15},{33,-11},{33,-10},{33,-9},{33,-8},{33,11},{33,12},{33,13},{33,14},{33,18},{33,19},{33,20},{33,25},{33,26},{33,31},{33,32},{33,33}, + {34,-29},{34,-28},{34,-23},{34,-22},{34,-17},{34,-16},{34,-12},{34,-11},{34,-10},{34,-9},{34,-8},{34,11},{34,12},{34,13},{34,14},{34,15},{34,19},{34,20},{34,25},{34,26},{34,31},{34,32},{35,-17},{35,-16},{35,-13},{35,-12},{35,-11},{35,-10},{35,-9},{35,-3}, + {35,-2},{35,-1},{35,0},{35,3},{35,4},{35,5},{35,6},{35,12},{35,13},{35,14},{35,15},{35,16},{35,19},{35,20},{36,-17},{36,-16},{36,-13},{36,-12},{36,-11},{36,-10},{36,-4},{36,-3},{36,-2},{36,-1},{36,0},{36,3},{36,4},{36,5},{36,6},{36,7}, + {36,13},{36,14},{36,15},{36,16},{36,19},{36,20},{37,-27},{37,-26},{37,-25},{37,-24},{37,-21},{37,-20},{37,-13},{37,-12},{37,-5},{37,-4},{37,-3},{37,-2},{37,-1},{37,0},{37,1},{37,2},{37,3},{37,4},{37,5},{37,6},{37,7},{37,8},{37,15},{37,16}, + {37,23},{37,24},{37,27},{37,28},{37,29},{37,30},{38,-27},{38,-26},{38,-25},{38,-24},{38,-21},{38,-20},{38,-19},{38,-13},{38,-12},{38,-5},{38,-4},{38,-3},{38,-2},{38,-1},{38,0},{38,1},{38,2},{38,3},{38,4},{38,5},{38,6},{38,7},{38,8},{38,15}, + {38,16},{38,22},{38,23},{38,24},{38,27},{38,28},{38,29},{38,30},{39,-26},{39,-25},{39,-24},{39,-20},{39,-19},{39,-18},{39,-13},{39,-12},{39,-11},{39,-10},{39,-5},{39,-4},{39,7},{39,8},{39,13},{39,14},{39,15},{39,16},{39,21},{39,22},{39,23},{39,27}, + {39,28},{39,29},{40,-25},{40,-24},{40,-19},{40,-18},{40,-13},{40,-12},{40,-11},{40,-10},{40,-5},{40,-4},{40,7},{40,8},{40,13},{40,14},{40,15},{40,16},{40,21},{40,22},{40,27},{40,28},{41,-19},{41,-18},{41,-1},{41,0},{41,1},{41,2},{41,3},{41,4}, + {41,21},{41,22},{42,-19},{42,-18},{42,-17},{42,-1},{42,0},{42,1},{42,2},{42,3},{42,4},{42,20},{42,21},{42,22},{43,-18},{43,-17},{43,-16},{43,-15},{43,-14},{43,-13},{43,-12},{43,-9},{43,-8},{43,-1},{43,0},{43,1},{43,2},{43,3},{43,4},{43,11}, + {43,12},{43,15},{43,16},{43,17},{43,18},{43,19},{43,20},{43,21},{44,-17},{44,-16},{44,-15},{44,-14},{44,-13},{44,-12},{44,-9},{44,-8},{44,-7},{44,-2},{44,-1},{44,0},{44,1},{44,2},{44,3},{44,4},{44,5},{44,10},{44,11},{44,12},{44,15},{44,16}, + {44,17},{44,18},{44,19},{44,20},{45,-8},{45,-7},{45,-6},{45,-5},{45,-4},{45,-3},{45,-2},{45,-1},{45,4},{45,5},{45,6},{45,7},{45,8},{45,9},{45,10},{45,11},{46,-7},{46,-6},{46,-5},{46,-4},{46,-3},{46,-2},{46,5},{46,6},{46,7},{46,8}, + {46,9},{46,10},{47,-4},{47,-3},{47,-2},{47,1},{47,2},{47,5},{47,6},{47,7},{48,-3},{48,-2},{48,1},{48,2},{48,5},{48,6} + } } } \ No newline at end of file diff --git a/modules/addons/spawn-area.lua b/modules/addons/spawn-area.lua index 4b9daf3b..61a73096 100644 --- a/modules/addons/spawn-area.lua +++ b/modules/addons/spawn-area.lua @@ -4,16 +4,23 @@ local Global = require 'utils.global' --- @dep utils.global local Event = require 'utils.event' --- @dep utils.event local config = require 'config.spawn_area' --- @dep config.spawn_area -local tiles = config.tiles -local entities = config.entities -local belts = config.afk_belts.locations -local turrets = config.infinite_ammo_turrets.locations +local turrets = config.turrets.locations Global.register(turrets, function(tbl) turrets = tbl end) --- returns the Spawn force or creates it +-- Apply an offset to a LuaPosition +local function apply_offset(position, offset) + return { x = position.x + (offset.x or offset[1]), y = position.y + (offset.y or offset[2]) } +end + +-- Apply the offset to the turrets default position +for _, turret in ipairs(turrets) do + turret.position = apply_offset(turret.position, config.turrets.offset) +end + +-- Get or create the force used for entities in spawn local function get_spawn_force() local force = game.forces['Spawn'] if force and force.valid then return force end @@ -23,7 +30,7 @@ local function get_spawn_force() return force end --- protects and entity so players cant do anything to it +-- Protects an entity and sets its force to the spawn force local function protect_entity(entity, set_force) if entity and entity.valid then entity.destructible = false @@ -35,113 +42,133 @@ local function protect_entity(entity, set_force) end end --- handles the infinite ammo turrets +-- Will spawn all infinite ammo turrets and keep them refilled local function spawn_turrets() - if config.infinite_ammo_turrets.enabled then - for _, turret_pos in pairs(turrets) do - local surface = game.surfaces[turret_pos.surface] - local pos = turret_pos.position - local turret = surface.find_entity('gun-turret', pos) - -- Makes a new turret if it is not found - if not turret or not turret.valid then - turret = surface.create_entity{name='gun-turret', position=pos, force='Spawn'} - protect_entity(turret, true) - end - -- adds ammo to the turret - local inv = turret.get_inventory(defines.inventory.turret_ammo) - if inv.can_insert{name=config.infinite_ammo_turrets.ammo_type, count=10} then - inv.insert{name=config.infinite_ammo_turrets.ammo_type, count=10} - end + for _, turret_pos in pairs(turrets) do + local surface = game.surfaces[turret_pos.surface] + local pos = turret_pos.position + local turret = surface.find_entity('gun-turret', pos) + + -- Makes a new turret if it is not found + if not turret or not turret.valid then + turret = surface.create_entity{name='gun-turret', position=pos, force='Spawn'} + protect_entity(turret, true) + end + + -- Adds ammo to the turret + local inv = turret.get_inventory(defines.inventory.turret_ammo) + if inv.can_insert{name=config.turrets.ammo_type, count=10} then + inv.insert{name=config.turrets.ammo_type, count=10} end end end --- makes a 2x2 afk belt where set in config +-- Makes a 2x2 afk belt at the locations in the config local function spawn_belts(surface, position) + position = apply_offset(position, config.afk_belts.offset) + local belt_type = config.afk_belts.belt_type local belt_details = {{-0.5, -0.5, 2}, {0.5, -0.5, 4}, {-0.5, 0.5, 0}, {0.5, 0.5, 6}} -- x, y,dir - for _, belt_set in pairs(belts) do - local o = position - local p = belt_set + for _, belt_set in pairs(config.afk_belts.locations) do + local set_position = apply_offset(position, belt_set) for _, belt in pairs(belt_details) do - local pos = {x=o.x+p.x+belt[1], y=o.y+p.y+belt[2]} - local belt_entity = surface.create_entity{name='transport-belt', position=pos, force='neutral', direction=belt[3]} - protect_entity(belt_entity) + local pos = apply_offset(set_position, belt) + local belt_entity = surface.create_entity{name=belt_type, position=pos, force='neutral', direction=belt[3]} + if config.afk_belts.protected then protect_entity(belt_entity) end end end end --- generates an area with no water and removes entities in the decon area -local function spawn_base(surface, position) - local dr = config.corrections.deconstruction_radius - local dr2 = dr^2 - local dtile = config.corrections.deconstruction_tile - local pr = config.corrections.pattern_radius - local pr2 = pr^2 - local ptile = surface.get_tile(position).name - if ptile == 'deepwater' or ptile == 'water' then ptile = 'grass-1' end +-- Generates extra tiles in a set pattern set out in the config +local function spawn_pattern(surface, position) + position = apply_offset(position, config.pattern.offset) local tiles_to_make = {} - for x = -pr, pr do -- loop over x - local x2 = x^2 - for y = -pr, pr do -- loop over y - local y2 = y^2 - local prod = x2+y2 - local p = {x=position.x+x, y=position.y+y} - if prod < dr2 then - -- if it is inside the decon radius - table.insert(tiles_to_make, {name=dtile, position=p}) - local entities_to_remove = surface.find_entities_filtered{area={{p.x-1, p.y-1}, {p.x, p.y}}} - for _, entity in pairs(entities_to_remove) do - if entity.name ~= 'character' then entity.destroy() end - end - elseif prod < pr2 then - -- if it is inside the pattern radius - table.insert(tiles_to_make, {name=ptile, position=p}) + local pattern_tile = config.pattern.pattern_tile + for _, tile in pairs(config.pattern.locations) do + table.insert(tiles_to_make, {name=pattern_tile, position=apply_offset(position, tile)}) + end + surface.set_tiles(tiles_to_make) +end + +-- Generates extra water as set out in the config +local function spawn_water(surface, position) + position = apply_offset(position, config.water.offset) + local tiles_to_make = {} + local water_tile = config.water.water_tile + for _, tile in pairs(config.water.locations) do + table.insert(tiles_to_make, {name=water_tile, position=apply_offset(position, tile)}) + end + surface.set_tiles(tiles_to_make) +end + +-- Generates the entities that are in the config +local function spawn_entities(surface, position) + position = apply_offset(position, config.entities.offset) + for _, entity in pairs(config.entities.locations) do + local pos = apply_offset(position, { x=entity[2], y=entity[3] }) + entity = surface.create_entity{name=entity[1], position=pos, force='neutral'} + if config.entities.protected then protect_entity(entity) end + entity.operable = config.entities.operable + end +end + +-- Generates an area with no water or entities, no water area is larger +local function spawn_area(surface, position) + local dr = config.spawn_area.deconstruction_radius + local dr2 = dr^2 + local decon_tile = config.spawn_area.deconstruction_tile + + local fr = config.spawn_area.landfill_radius + local fr2 = fr^2 + local fill_tile = surface.get_tile(position).name + + -- Make sure a non water tile is used for each tile + if surface.get_tile(position).collides_with('player-layer') then fill_tile = 'landfill' end + if decon_tile == nil then decon_tile = fill_tile end + + local tiles_to_make = {} + for x = -fr, fr do -- loop over x + local x2 = (x+0.5)^2 + for y = -fr, fr do -- loop over y + local y2 = (y+0.5)^2 + local dst = x2+y2 + local pos = {x=position.x+x, y=position.y+y} + if dst < dr2 then + -- If it is inside the decon radius always set the tile + table.insert(tiles_to_make, {name=decon_tile, position=pos}) + elseif dst < fr2 and surface.get_tile(pos).collides_with('player-layer') then + -- If it is inside the fill radius only set the tile if its water + table.insert(tiles_to_make, {name=fill_tile, position=pos}) end end end + + -- Remove entities then set the tiles + local entities_to_remove = surface.find_entities_filtered{position=position, radius=dr, name='character', invert=true} + for _, entity in pairs(entities_to_remove) do entity.destroy() end surface.set_tiles(tiles_to_make) end --- generates the pattern that is in the config -local function spawn_pattern(surface, position) - local tiles_to_make = {} - local ptile = config.corrections.pattern_tile - local o = config.corrections.offset - local p = {x=position.x+o.x, y=position.y+o.y} - for _, tile in pairs(tiles) do - table.insert(tiles_to_make, {name=ptile, position={tile[1]+p.x, tile[2]+p.y}}) - end - surface.set_tiles(tiles_to_make) +-- Only add a event handler if the turrets are enabled +if config.turrets.enabled then + Event.on_nth_tick(config.turrets.refill_time, function() + if game.tick < 10 then return end + spawn_turrets() + end) end --- generates the entities that are in the config -local function spawn_entities(surface, position) - local o = config.corrections.offset - local p = {x=position.x+o.x, y=position.y+o.y} - for _, entity in pairs(entities) do - entity = surface.create_entity{name=entity[1], position={entity[2]+p.x, entity[3]+p.y}, force='neutral'} - protect_entity(entity) - entity.operable = true - end -end - -local refill_time = 60*60*5 -- 5 minutes -Event.on_nth_tick(refill_time, function() - if game.tick < 10 then return end - spawn_turrets() -end) - +-- When the first player joins create the spawn area Event.add(defines.events.on_player_created, function(event) if event.player_index ~= 1 then return end local player = game.players[event.player_index] local p = {x=0, y=0} local s = player.surface - spawn_base(s, p) - spawn_pattern(s, p) get_spawn_force() - spawn_entities(s, p) - spawn_belts(s, p) - spawn_turrets() + spawn_area(s, p) + if config.pattern.enabled then spawn_pattern(s, p) end + if config.water.enabled then spawn_water(s, p) end + if config.afk_belts.enabled then spawn_belts(s, p) end + if config.turrets.enabled then spawn_turrets() end + if config.entities.enabled then spawn_entities(s, p) end player.teleport(p, s) end) From 49e056fee18f27fb2c6a038aafd363bd7b0ea65a Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Thu, 15 Apr 2021 22:03:32 +0100 Subject: [PATCH 16/56] Fixed doc comments --- config/spawn_area.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/config/spawn_area.lua b/config/spawn_area.lua index 588f9d3c..5092f514 100644 --- a/config/spawn_area.lua +++ b/config/spawn_area.lua @@ -22,7 +22,7 @@ return { afk_belts = { --- @setting afk_belts Settings relating to adding afk belts to spawn enabled = true, --- @setting enabled Weather afk belts will be added to spawn belt_type = 'transport-belt', --- @setting belt_type The belt to used used as afk belts - protected = true, --- @settins protected Weather belts will be protected from player interaction + protected = true, --- @setting protected Weather belts will be protected from player interaction offset = { x=0, y=0 }, --- @setting offset The position offset to apply to afk belts locations={ --- @setting locations The locations to spawn afk belts at, given as the top left position {-5, -5}, { 5, -5}, @@ -42,10 +42,10 @@ return { } }, entities = { --- @setting entities Settings relating to adding entities to spawn - enabled = true, --- @settings enabled Weather entities will be added to spawn - protected = true, --- @settins protected Weather entities will be protected from player interaction - operable = true, --- @settings operable Weather entities can be opened by players, must be true if chests are used - offset = { x=0, y=-2 }, --- @settings offset The position offset to apply to entities + enabled = true, --- @setting enabled Weather entities will be added to spawn + protected = true, --- @setting protected Weather entities will be protected from player interaction + operable = true, --- @setting operable Weather entities can be opened by players, must be true if chests are used + offset = { x=0, y=-2 }, --- @setting offset The position offset to apply to entities locations = { --- @setting locations The location and names of entities {name,x,y} {"stone-wall",-10,-5},{"stone-wall",-10,-4},{"stone-wall",-10,-3},{"stone-wall",-10,-2},{"stone-wall",-10,-1},{"stone-wall",-10,0},{"stone-wall",-10,3},{"stone-wall",-10,4},{"stone-wall",-10,5}, {"stone-wall",-10,6},{"stone-wall",-10,7},{"stone-wall",-10,8},{"small-lamp",-8,-4},{"small-lamp",-8,-1},{"iron-chest",-8,0},{"iron-chest",-8,3},{"small-lamp",-8,4}, @@ -64,9 +64,9 @@ return { } }, pattern = { - enabled = true, --- @settings enabled Weather pattern tiles will be added to spawn + enabled = true, --- @setting enabled Weather pattern tiles will be added to spawn pattern_tile = 'stone-path', --- @setting pattern_tile The tile to be used for the pattern - offset = { x=0, y=-2 }, --- @settings offset The position offset to apply to pattern tiles + offset = { x=0, y=-2 }, --- @setting offset The position offset to apply to pattern tiles locations = { --- @setting locations The location of the pattern tiles {x,y} {-49,-3},{-49,-2},{-49,1},{-49,2},{-49,5},{-49,6},{-48,-4},{-48,-3},{-48,-2},{-48,1},{-48,2},{-48,5},{-48,6},{-48,7},{-47,-7},{-47,-6},{-47,-5},{-47,-4},{-47,-3},{-47,-2},{-47,5},{-47,6},{-47,7},{-47,8},{-47,9},{-47,10},{-46,-8},{-46,-7},{-46,-6},{-46,-5}, {-46,-4},{-46,-3},{-46,-2},{-46,-1},{-46,4},{-46,5},{-46,6},{-46,7},{-46,8},{-46,9},{-46,10},{-46,11},{-45,-17},{-45,-16},{-45,-15},{-45,-14},{-45,-13},{-45,-12},{-45,-9},{-45,-8},{-45,-7},{-45,-2},{-45,-1},{-45,0},{-45,1},{-45,2},{-45,3},{-45,4},{-45,5},{-45,10}, From bb46d44ea3c51970e08a9d6cb65817e1f799da34 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Thu, 15 Apr 2021 23:24:27 +0100 Subject: [PATCH 17/56] Added admin markers --- config/_file_loader.lua | 1 + config/expcore/roles.lua | 1 + locale/en/commands.cfg | 8 ++- modules/commands/admin-markers.lua | 80 ++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 modules/commands/admin-markers.lua diff --git a/config/_file_loader.lua b/config/_file_loader.lua index 16a135af..376cb6d3 100644 --- a/config/_file_loader.lua +++ b/config/_file_loader.lua @@ -12,6 +12,7 @@ return { 'modules.commands.me', 'modules.commands.kill', 'modules.commands.admin-chat', + 'modules.commands.admin-markers', 'modules.commands.teleport', 'modules.commands.cheat-mode', 'modules.commands.ratio', diff --git a/config/expcore/roles.lua b/config/expcore/roles.lua index 9b826202..0a629063 100644 --- a/config/expcore/roles.lua +++ b/config/expcore/roles.lua @@ -92,6 +92,7 @@ Roles.new_role('Trainee','TrMod') :set_parent('Veteran') :allow{ 'command/admin-chat', + 'command/admin-marker', 'command/teleport', 'command/bring', 'command/goto', diff --git a/locale/en/commands.cfg b/locale/en/commands.cfg index dea7b935..4255195b 100644 --- a/locale/en/commands.cfg +++ b/locale/en/commands.cfg @@ -82,4 +82,10 @@ 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-admin-marker] +exit=You have left admin marker mode, all new makers will not be protected. +enter=You have entered admin marker mode, all new makers will be protected. +edit=You have edited an admin marker. +revert=You cannot edit admin markers. \ No newline at end of file diff --git a/modules/commands/admin-markers.lua b/modules/commands/admin-markers.lua new file mode 100644 index 00000000..cc43510b --- /dev/null +++ b/modules/commands/admin-markers.lua @@ -0,0 +1,80 @@ +--[[-- Commands Module - Admin Markers + - Adds a command that creates map markers which can only be edited by admins + @commands Admin-Markers +]] + +local Commands = require 'expcore.commands' --- @dep expcore.commands +local Global = require 'utils.global' --- @dep utils.global +local Event = require 'utils.event' --- @dep utils.event + +local admins = {} -- Stores all players in admin marker mode +local markers = {} -- Stores all admin markers + +--- Global variables +Global.register({ + admins = admins, + markers = markers +}, function(tbl) + admins = tbl.admins + markers = tbl.markers +end) + +--- Toggle admin marker mode, can only be applied to yourself +-- @command admin-marker +Commands.new_command('admin-marker', 'Toggles admin marker mode, new markers can only be edited by admins') +:set_flag('admin_only') +:add_alias('am', 'admin-markers') +:register(function(player) + if admins[player.name] then + -- Exit admin mode + admins[player.name] = nil + return Commands.success{'expcom-admin-marker.exit'} + else + -- Enter admin mode + admins[player.name] = true + return Commands.success{'expcom-admin-marker.enter'} + end +end) + +--- Listen for new map markers being added +Event.add(defines.events.on_chart_tag_added, function(event) + if not event.player_index then return end + local player = game.get_player(event.player_index) + if not admins[player.name] then return end + local tag = event.tag + markers[tag.force.name..tag.tag_number] = true +end) + +--- Listen for tags being removed or edited +local function maintain_tag(event) + local tag = event.tag + if not event.player_index then return end + if not markers[tag.force.name..tag.tag_number] then return end + local player = game.get_player(event.player_index) + if player.admin then + -- Player is added, tell them it was an admin marker + Commands.print({'expcom-admin-marker.edit'}, nil, player) + elseif event.name == defines.events.on_chart_tag_modified then + -- Tag was modified, revert the changes + tag.text = event.old_text + tag.last_user = event.old_player + if event.old_icon then tag.icon = event.old_icon end + player.play_sound{path='utility/wire_pickup'} + Commands.print({'expcom-admin-marker.revert'}, nil, player) + else + -- Tag was removed, remake the tag + player.play_sound{path='utility/wire_pickup'} + Commands.print({'expcom-admin-marker.revert'}, 'orange_red', player) + local new_tag = tag.force.add_chart_tag(tag.surface, { + last_user = tag.last_user, + position = tag.position, + icon = tag.icon, + text = tag.text, + }) + markers[tag.force.name..tag.tag_number] = nil + markers[new_tag.force.name..new_tag.tag_number] = true + end +end + +Event.add(defines.events.on_chart_tag_modified, maintain_tag) +Event.add(defines.events.on_chart_tag_removed, maintain_tag) \ No newline at end of file From 573dfd781bb50d0f4306a0440f8be7bb9c051b37 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Thu, 15 Apr 2021 23:28:30 +0100 Subject: [PATCH 18/56] Added tag placed message --- locale/en/commands.cfg | 1 + modules/commands/admin-markers.lua | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/locale/en/commands.cfg b/locale/en/commands.cfg index 4255195b..1cb2e86f 100644 --- a/locale/en/commands.cfg +++ b/locale/en/commands.cfg @@ -87,5 +87,6 @@ response=Last location of __1__ was [gps=__2__,__3__] [expcom-admin-marker] exit=You have left admin marker mode, all new makers will not be protected. enter=You have entered admin marker mode, all new makers will be protected. +place=You have placed an admin marker. edit=You have edited an admin marker. revert=You cannot edit admin markers. \ No newline at end of file diff --git a/modules/commands/admin-markers.lua b/modules/commands/admin-markers.lua index cc43510b..95062705 100644 --- a/modules/commands/admin-markers.lua +++ b/modules/commands/admin-markers.lua @@ -36,16 +36,24 @@ Commands.new_command('admin-marker', 'Toggles admin marker mode, new markers can end end) ---- Listen for new map markers being added +--- Listen for new map markers being added, add admin marker if done by player in admin mode Event.add(defines.events.on_chart_tag_added, function(event) if not event.player_index then return end local player = game.get_player(event.player_index) if not admins[player.name] then return end local tag = event.tag markers[tag.force.name..tag.tag_number] = true + Commands.print({'expcom-admin-marker.place'}, nil, player) end) ---- Listen for tags being removed or edited +--- Listen for players leaving the game, leave admin mode to avoid unexpected admin markers +Event.add(defines.events.on_player_left_game, function(event) + if not event.player_index then return end + local player = game.get_player(event.player_index) + admins[player.name] = nil +end) + +--- Listen for tags being removed or edited, maintain tags edited by non admins local function maintain_tag(event) local tag = event.tag if not event.player_index then return end From d485e2148061369278c040fc3dbb29a4d37ca73c Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Fri, 16 Apr 2021 18:13:41 +0100 Subject: [PATCH 19/56] Fixed calling set_controller during on_close --- modules/control/spectate.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/control/spectate.lua b/modules/control/spectate.lua index d9320ae7..5fec23af 100644 --- a/modules/control/spectate.lua +++ b/modules/control/spectate.lua @@ -48,8 +48,10 @@ function Public.stop_spectate(player) local character = spectating[player.index] spectating[player.index] = nil if character and character.valid then + local opened = player.opened player.teleport(character.position, character.surface) player.set_controller{ type = defines.controllers.character, character = character } + if opened then player.opened = opened end -- Maintain opened after controller change else player.ticks_to_respawn = 300 end @@ -118,8 +120,12 @@ Gui.element(function(event_trigger, parent, target) return label end) -:on_close(Public.stop_follow) :on_click(Public.stop_follow) +:on_close(function(player) + -- Dont call set_controller during on_close as it invalidates the controller + -- Setting an invalid position (as to not equal their current) will call stop_follow on the next tick + following[player.index][3] = {} +end) ----- Events ----- @@ -148,7 +154,7 @@ end Event.add(defines.events.on_tick, update_all) -- Check for player leaving -Event.add(defines.events.on_player_left_game, function(event) +Event.add(defines.events.on_pre_player_left_game, function(event) local player = game.players[event.player_index] Public.stop_follow(player) for _, data in pairs(following) do From b08e93e2455d6b1dcdfaf6883ab34e254d481a57 Mon Sep 17 00:00:00 2001 From: bbassie Date: Fri, 16 Apr 2021 22:45:58 +0200 Subject: [PATCH 20/56] Fix parse_message --- modules/gui/task-list.lua | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/modules/gui/task-list.lua b/modules/gui/task-list.lua index ecfb7852..d8173d36 100644 --- a/modules/gui/task-list.lua +++ b/modules/gui/task-list.lua @@ -323,17 +323,13 @@ local function parse_message(str) -- Trimm the spaces of the string local trimmed = (string.gsub(str, "^%s*(.-)%s*$", "%1")) local message = { title = "", body = "" } - -- If it doesn't match the patter return the str as a title - local match = string.match(trimmed, message_pattern) - if not match then + local title, body = string.match(trimmed, message_pattern) + if not title then + -- If it doesn't match the patter return the str as a title message.title = trimmed - return message - end - -- If message has multiple lines - for key, value in string.gmatch(trimmed, message_pattern) do - message.title = key - message.body = value - break + else + message.title = title + message.body = body end return message end From 8674704f15179819f0862aec38fed631c8dd0797 Mon Sep 17 00:00:00 2001 From: bbassie Date: Fri, 16 Apr 2021 22:50:16 +0200 Subject: [PATCH 21/56] Fix docs gen param argument name mismatch param and formal argument name mismatch: 'task_title' 'message_title' param and formal argument name mismatch: 'task_body' 'message_body' --- modules/control/tasks.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/control/tasks.lua b/modules/control/tasks.lua index 0e143725..1420a6b5 100644 --- a/modules/control/tasks.lua +++ b/modules/control/tasks.lua @@ -40,11 +40,11 @@ end) local task_id = Tasks.add_task(game.player.force.name, nil, game.player.name) ]] -function Tasks.add_task(force_name, player_name, message_title, message_body) +function Tasks.add_task(force_name, player_name, task_title, task_body) -- Get a new task id local task_id = tostring(force_tasks._uid) - message_title = message_title or 'New Task' - message_body = message_body or 'Do x or y' + task_title = task_title or 'New Task' + task_body = task_body or 'Do x or y' force_tasks._uid = force_tasks._uid + 1 -- Get the existing tasks for this force @@ -67,8 +67,8 @@ function Tasks.add_task(force_name, player_name, message_title, message_body) TaskData:set(task_id, { task_id = task_id, force_name = force_name, - title = message_title, - body = message_body, + title = task_title, + body = task_body, last_edit_name = player_name or '', last_edit_time = game.tick, currently_editing = editing From effdb97387a9894293c0c68ea68f3332c81042f0 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sat, 24 Apr 2021 00:26:24 +0100 Subject: [PATCH 22/56] 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 23/56] 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 24/56] 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 25/56] 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 26/56] 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 27/56] 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 28/56] 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 29/56] 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 30/56] 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 31/56] 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 32/56] 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 33/56] 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 34/56] 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 f8b22d7768ac22ca5f389fbd9316e153e1d404fc Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 25 Apr 2021 20:15:25 +0100 Subject: [PATCH 35/56] Implimented Changes --- config/spawn_area.lua | 18 +++++++++--------- modules/addons/spawn-area.lua | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/config/spawn_area.lua b/config/spawn_area.lua index 5092f514..e3d0fb53 100644 --- a/config/spawn_area.lua +++ b/config/spawn_area.lua @@ -8,7 +8,7 @@ return { landfill_radius = 50, --- @setting pattern_radius All water within this radius will be land filled }, turrets = { --- @setting turrets Settings relating to adding turrets to spawn - enabled = true, --- @setting enabled Weather turrets will be added to spawn + enabled = true, --- @setting enabled Whether turrets will be added to spawn ammo_type = 'uranium-rounds-magazine', --- @setting ammo_type The ammo type that will be used during refills refill_time = 60*60*5, --- @setting refill_time The time in ticks between each refill of the turrets, only change if having lag issues offset = { x=0, y=0 }, --- @setting offset The position offset to apply to turrets @@ -20,9 +20,9 @@ return { } }, afk_belts = { --- @setting afk_belts Settings relating to adding afk belts to spawn - enabled = true, --- @setting enabled Weather afk belts will be added to spawn - belt_type = 'transport-belt', --- @setting belt_type The belt to used used as afk belts - protected = true, --- @setting protected Weather belts will be protected from player interaction + enabled = true, --- @setting enabled Whether afk belts will be added to spawn + belt_type = 'transport-belt', --- @setting belt_type The belt to be used as afk belts + protected = true, --- @setting protected Whether belts will be protected from player interaction offset = { x=0, y=0 }, --- @setting offset The position offset to apply to afk belts locations={ --- @setting locations The locations to spawn afk belts at, given as the top left position {-5, -5}, { 5, -5}, @@ -30,7 +30,7 @@ return { } }, water = { --- @setting water Settings relating to adding water to spawn - enabled = true, --- @setting enabled Weather water tiles will be added to spawn + enabled = true, --- @setting enabled Whether water tiles will be added to spawn water_tile = 'water-mud', --- @setting water_tile The tile to be used as the water tile offset = { x=0, y=0 }, --- @setting offset The position offset to apply to water tiles locations = { --- @setting locations The location of the water tiles {x,y} @@ -42,9 +42,9 @@ return { } }, entities = { --- @setting entities Settings relating to adding entities to spawn - enabled = true, --- @setting enabled Weather entities will be added to spawn - protected = true, --- @setting protected Weather entities will be protected from player interaction - operable = true, --- @setting operable Weather entities can be opened by players, must be true if chests are used + enabled = true, --- @setting enabled Whether entities will be added to spawn + protected = true, --- @setting protected Whether entities will be protected from player interaction + operable = true, --- @setting operable Whether entities can be opened by players, must be true if chests are used offset = { x=0, y=-2 }, --- @setting offset The position offset to apply to entities locations = { --- @setting locations The location and names of entities {name,x,y} {"stone-wall",-10,-5},{"stone-wall",-10,-4},{"stone-wall",-10,-3},{"stone-wall",-10,-2},{"stone-wall",-10,-1},{"stone-wall",-10,0},{"stone-wall",-10,3},{"stone-wall",-10,4},{"stone-wall",-10,5}, @@ -64,7 +64,7 @@ return { } }, pattern = { - enabled = true, --- @setting enabled Weather pattern tiles will be added to spawn + enabled = true, --- @setting enabled Whether pattern tiles will be added to spawn pattern_tile = 'stone-path', --- @setting pattern_tile The tile to be used for the pattern offset = { x=0, y=-2 }, --- @setting offset The position offset to apply to pattern tiles locations = { --- @setting locations The location of the pattern tiles {x,y} diff --git a/modules/addons/spawn-area.lua b/modules/addons/spawn-area.lua index 61a73096..7b711033 100644 --- a/modules/addons/spawn-area.lua +++ b/modules/addons/spawn-area.lua @@ -78,7 +78,7 @@ local function spawn_belts(surface, position) end end --- Generates extra tiles in a set pattern set out in the config +-- Generates extra tiles in a set pattern as defined in the config local function spawn_pattern(surface, position) position = apply_offset(position, config.pattern.offset) local tiles_to_make = {} @@ -89,7 +89,7 @@ local function spawn_pattern(surface, position) surface.set_tiles(tiles_to_make) end --- Generates extra water as set out in the config +-- Generates extra water as defined in the config local function spawn_water(surface, position) position = apply_offset(position, config.water.offset) local tiles_to_make = {} @@ -136,7 +136,7 @@ local function spawn_area(surface, position) -- If it is inside the decon radius always set the tile table.insert(tiles_to_make, {name=decon_tile, position=pos}) elseif dst < fr2 and surface.get_tile(pos).collides_with('player-layer') then - -- If it is inside the fill radius only set the tile if its water + -- If it is inside the fill radius only set the tile if it is water table.insert(tiles_to_make, {name=fill_tile, position=pos}) end end From c899674ef65b0d0a2d3de2133eb49933ad5b1d89 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 25 Apr 2021 20:17:46 +0100 Subject: [PATCH 36/56] Implimented Changes --- locale/en/commands.cfg | 4 ++-- modules/commands/admin-markers.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/locale/en/commands.cfg b/locale/en/commands.cfg index 1cb2e86f..b2fcb456 100644 --- a/locale/en/commands.cfg +++ b/locale/en/commands.cfg @@ -85,8 +85,8 @@ none-matching=No servers were found with that name, if you used an address pleas response=Last location of __1__ was [gps=__2__,__3__] [expcom-admin-marker] -exit=You have left admin marker mode, all new makers will not be protected. -enter=You have entered admin marker mode, all new makers will be protected. +exit=You have left admin marker mode, all new markers will not be protected. +enter=You have entered admin marker mode, all new markers will be protected. place=You have placed an admin marker. edit=You have edited an admin marker. revert=You cannot edit admin markers. \ No newline at end of file diff --git a/modules/commands/admin-markers.lua b/modules/commands/admin-markers.lua index 95062705..91fab3ec 100644 --- a/modules/commands/admin-markers.lua +++ b/modules/commands/admin-markers.lua @@ -60,7 +60,7 @@ local function maintain_tag(event) if not markers[tag.force.name..tag.tag_number] then return end local player = game.get_player(event.player_index) if player.admin then - -- Player is added, tell them it was an admin marker + -- Player is admin, tell them it was an admin marker Commands.print({'expcom-admin-marker.edit'}, nil, player) elseif event.name == defines.events.on_chart_tag_modified then -- Tag was modified, revert the changes From 1660cf8ed8bd3afe4e152691db49ee2ea8d72926 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 25 Apr 2021 19:19:56 +0000 Subject: [PATCH 37/56] Automatic Doc Update --- docs/addons/Advanced-Start.html | 2 +- docs/addons/Chat-Popups.html | 2 +- docs/addons/Chat-Reply.html | 2 +- docs/addons/Compilatron.html | 2 +- docs/addons/Damage-Popups.html | 2 +- docs/addons/Death-Logger.html | 2 +- docs/addons/Discord-Alerts.html | 2 +- docs/addons/Inventory-Clear.html | 2 +- docs/addons/Pollution-Grading.html | 2 +- docs/addons/Scorched-Earth.html | 2 +- docs/addons/Spawn-Area.html | 2 +- docs/addons/Tree-Decon.html | 2 +- docs/addons/afk-kick.html | 2 +- docs/addons/report-jail.html | 2 +- docs/commands/Admin-Chat.html | 2 +- docs/commands/Cheat-Mode.html | 2 +- docs/commands/Clear-Inventory.html | 2 +- docs/commands/Connect.html | 2 +- docs/commands/Debug.html | 2 +- docs/commands/Find.html | 2 +- docs/commands/Help.html | 2 +- docs/commands/Home.html | 2 +- docs/commands/Interface.html | 2 +- docs/commands/InventorySearch.html | 2 +- docs/commands/Jail.html | 2 +- docs/commands/Kill.html | 2 +- docs/commands/LastLocation.html | 2 +- docs/commands/Me.html | 2 +- docs/commands/Rainbow.html | 2 +- docs/commands/Repair.html | 2 +- docs/commands/Reports.html | 2 +- docs/commands/Roles.html | 2 +- docs/commands/Spawn.html | 2 +- docs/commands/Teleport.html | 2 +- docs/commands/Warnings.html | 2 +- docs/configs/Advanced-Start.html | 2 +- docs/configs/Autofill.html | 2 +- docs/configs/Bonuses.html | 2 +- docs/configs/Chat-Reply.html | 2 +- docs/configs/Commands-Auth-Admin.html | 2 +- docs/configs/Commands-Auth-Roles.html | 2 +- .../Commands-Auth-Runtime-Disable.html | 2 +- docs/configs/Commands-Color-Parse.html | 2 +- docs/configs/Commands-Parse-Roles.html | 2 +- docs/configs/Commands-Parse.html | 2 +- docs/configs/Compilatron.html | 2 +- docs/configs/Death-Logger.html | 2 +- docs/configs/Discord-Alerts.html | 2 +- docs/configs/File-Loader.html | 2 +- docs/configs/Permission-Groups.html | 2 +- docs/configs/Player-List.html | 2 +- docs/configs/Pollution-Grading.html | 2 +- docs/configs/Popup-Messages.html | 2 +- docs/configs/Preset-Player-Colours.html | 2 +- docs/configs/Preset-Player-Quickbar.html | 2 +- docs/configs/Repair.html | 2 +- docs/configs/Rockets.html | 2 +- docs/configs/Roles.html | 2 +- docs/configs/Science.html | 2 +- docs/configs/Scorched-Earth.html | 2 +- docs/configs/Spawn-Area.html | 1025 ++++++++++++----- docs/configs/Statistics.html | 2 +- docs/configs/Tasks.html | 2 +- docs/configs/Warnings.html | 2 +- docs/configs/Warps.html | 2 +- docs/configs/inventory_clear.html | 2 +- docs/control/Jail.html | 2 +- docs/control/Production.html | 2 +- docs/control/Reports.html | 2 +- docs/control/Rockets.html | 2 +- docs/control/Tasks.html | 2 +- docs/control/Warnings.html | 2 +- docs/control/Warps.html | 2 +- docs/core/Async.html | 2 +- docs/core/Commands.html | 2 +- docs/core/Common.html | 2 +- docs/core/Datastore.html | 2 +- docs/core/External.html | 2 +- docs/core/Groups.html | 2 +- docs/core/Gui.html | 2 +- docs/core/PlayerData.html | 2 +- docs/core/Roles.html | 2 +- docs/data/Alt-View.html | 2 +- docs/data/Bonus.html | 2 +- docs/data/Greetings.html | 2 +- docs/data/Player-Colours.html | 2 +- docs/data/Quickbar.html | 2 +- docs/data/Tag.html | 2 +- docs/guis/Autofill.html | 2 +- docs/guis/Player-List.html | 2 +- docs/guis/Readme.html | 2 +- docs/guis/Rocket-Info.html | 2 +- docs/guis/Science-Info.html | 2 +- docs/guis/Task-List.html | 2 +- docs/guis/Warps-List.html | 2 +- docs/guis/server-ups.html | 2 +- docs/index.html | 2 +- docs/modules/control.html | 2 +- .../modules.addons.station-auto-name.html | 2 +- docs/modules/overrides.debug.html | 2 +- docs/modules/overrides.math.html | 2 +- docs/modules/overrides.table.html | 2 +- docs/modules/utils.event.html | 2 +- docs/modules/utils.event_core.html | 2 +- docs/modules/utils.task.html | 2 +- docs/topics/LICENSE.html | 2 +- docs/topics/README.md.html | 2 +- 107 files changed, 844 insertions(+), 393 deletions(-) diff --git a/docs/addons/Advanced-Start.html b/docs/addons/Advanced-Start.html index edd6c7a1..bfe54549 100644 --- a/docs/addons/Advanced-Start.html +++ b/docs/addons/Advanced-Start.html @@ -342,7 +342,7 @@ generated by LDoc diff --git a/docs/addons/Chat-Popups.html b/docs/addons/Chat-Popups.html index e78ea134..b0a72c24 100644 --- a/docs/addons/Chat-Popups.html +++ b/docs/addons/Chat-Popups.html @@ -371,7 +371,7 @@ generated by LDoc diff --git a/docs/addons/Chat-Reply.html b/docs/addons/Chat-Reply.html index 5c69eca3..46e8f203 100644 --- a/docs/addons/Chat-Reply.html +++ b/docs/addons/Chat-Reply.html @@ -370,7 +370,7 @@ generated by LDoc diff --git a/docs/addons/Compilatron.html b/docs/addons/Compilatron.html index 91f0f46d..5841e387 100644 --- a/docs/addons/Compilatron.html +++ b/docs/addons/Compilatron.html @@ -579,7 +579,7 @@ generated by LDoc diff --git a/docs/addons/Damage-Popups.html b/docs/addons/Damage-Popups.html index e57f7ba9..451936f7 100644 --- a/docs/addons/Damage-Popups.html +++ b/docs/addons/Damage-Popups.html @@ -371,7 +371,7 @@ generated by LDoc diff --git a/docs/addons/Death-Logger.html b/docs/addons/Death-Logger.html index a6faa3d6..5a191a2d 100644 --- a/docs/addons/Death-Logger.html +++ b/docs/addons/Death-Logger.html @@ -398,7 +398,7 @@ generated by LDoc diff --git a/docs/addons/Discord-Alerts.html b/docs/addons/Discord-Alerts.html index 4c703f6c..bdc34803 100644 --- a/docs/addons/Discord-Alerts.html +++ b/docs/addons/Discord-Alerts.html @@ -454,7 +454,7 @@ generated by LDoc diff --git a/docs/addons/Inventory-Clear.html b/docs/addons/Inventory-Clear.html index 22725ae2..cdcf2e34 100644 --- a/docs/addons/Inventory-Clear.html +++ b/docs/addons/Inventory-Clear.html @@ -370,7 +370,7 @@ generated by LDoc diff --git a/docs/addons/Pollution-Grading.html b/docs/addons/Pollution-Grading.html index cf2bb1c6..17962ea1 100644 --- a/docs/addons/Pollution-Grading.html +++ b/docs/addons/Pollution-Grading.html @@ -342,7 +342,7 @@ generated by LDoc diff --git a/docs/addons/Scorched-Earth.html b/docs/addons/Scorched-Earth.html index e6c6b551..2d38d8e3 100644 --- a/docs/addons/Scorched-Earth.html +++ b/docs/addons/Scorched-Earth.html @@ -398,7 +398,7 @@ generated by LDoc diff --git a/docs/addons/Spawn-Area.html b/docs/addons/Spawn-Area.html index f04f2c70..f0a8d8ca 100644 --- a/docs/addons/Spawn-Area.html +++ b/docs/addons/Spawn-Area.html @@ -370,7 +370,7 @@ generated by LDoc diff --git a/docs/addons/Tree-Decon.html b/docs/addons/Tree-Decon.html index 22b0e441..8e6e2572 100644 --- a/docs/addons/Tree-Decon.html +++ b/docs/addons/Tree-Decon.html @@ -370,7 +370,7 @@ generated by LDoc diff --git a/docs/addons/afk-kick.html b/docs/addons/afk-kick.html index f6021d26..370a29ac 100644 --- a/docs/addons/afk-kick.html +++ b/docs/addons/afk-kick.html @@ -398,7 +398,7 @@ generated by LDoc diff --git a/docs/addons/report-jail.html b/docs/addons/report-jail.html index bf4cf645..54abcefa 100644 --- a/docs/addons/report-jail.html +++ b/docs/addons/report-jail.html @@ -398,7 +398,7 @@ generated by LDoc diff --git a/docs/commands/Admin-Chat.html b/docs/commands/Admin-Chat.html index f16fa496..75bba2df 100644 --- a/docs/commands/Admin-Chat.html +++ b/docs/commands/Admin-Chat.html @@ -410,7 +410,7 @@ generated by LDoc diff --git a/docs/commands/Cheat-Mode.html b/docs/commands/Cheat-Mode.html index 37258c9c..e1576dbe 100644 --- a/docs/commands/Cheat-Mode.html +++ b/docs/commands/Cheat-Mode.html @@ -383,7 +383,7 @@ generated by LDoc diff --git a/docs/commands/Clear-Inventory.html b/docs/commands/Clear-Inventory.html index d2c63a2e..020eb960 100644 --- a/docs/commands/Clear-Inventory.html +++ b/docs/commands/Clear-Inventory.html @@ -410,7 +410,7 @@ generated by LDoc diff --git a/docs/commands/Connect.html b/docs/commands/Connect.html index ba9a7a98..37610c38 100644 --- a/docs/commands/Connect.html +++ b/docs/commands/Connect.html @@ -613,7 +613,7 @@ generated by LDoc diff --git a/docs/commands/Debug.html b/docs/commands/Debug.html index 0aa460ba..d5c8b520 100644 --- a/docs/commands/Debug.html +++ b/docs/commands/Debug.html @@ -387,7 +387,7 @@ generated by LDoc diff --git a/docs/commands/Find.html b/docs/commands/Find.html index 8ba085e1..99be20dd 100644 --- a/docs/commands/Find.html +++ b/docs/commands/Find.html @@ -382,7 +382,7 @@ generated by LDoc diff --git a/docs/commands/Help.html b/docs/commands/Help.html index 2f663feb..2a52b5a1 100644 --- a/docs/commands/Help.html +++ b/docs/commands/Help.html @@ -426,7 +426,7 @@ generated by LDoc diff --git a/docs/commands/Home.html b/docs/commands/Home.html index e0ed01c4..4b694b72 100644 --- a/docs/commands/Home.html +++ b/docs/commands/Home.html @@ -480,7 +480,7 @@ generated by LDoc diff --git a/docs/commands/Interface.html b/docs/commands/Interface.html index a04c634b..3e4c547e 100644 --- a/docs/commands/Interface.html +++ b/docs/commands/Interface.html @@ -410,7 +410,7 @@ generated by LDoc diff --git a/docs/commands/InventorySearch.html b/docs/commands/InventorySearch.html index d03c1d0d..a26213af 100644 --- a/docs/commands/InventorySearch.html +++ b/docs/commands/InventorySearch.html @@ -600,7 +600,7 @@ generated by LDoc diff --git a/docs/commands/Jail.html b/docs/commands/Jail.html index 8ed2e752..f3ccfde3 100644 --- a/docs/commands/Jail.html +++ b/docs/commands/Jail.html @@ -509,7 +509,7 @@ generated by LDoc diff --git a/docs/commands/Kill.html b/docs/commands/Kill.html index dca0f95e..a017e88c 100644 --- a/docs/commands/Kill.html +++ b/docs/commands/Kill.html @@ -411,7 +411,7 @@ generated by LDoc diff --git a/docs/commands/LastLocation.html b/docs/commands/LastLocation.html index a68dbdd4..ab784d75 100644 --- a/docs/commands/LastLocation.html +++ b/docs/commands/LastLocation.html @@ -410,7 +410,7 @@ generated by LDoc diff --git a/docs/commands/Me.html b/docs/commands/Me.html index f213de79..23742e96 100644 --- a/docs/commands/Me.html +++ b/docs/commands/Me.html @@ -382,7 +382,7 @@ generated by LDoc diff --git a/docs/commands/Rainbow.html b/docs/commands/Rainbow.html index 9c2922e4..5781828a 100644 --- a/docs/commands/Rainbow.html +++ b/docs/commands/Rainbow.html @@ -410,7 +410,7 @@ generated by LDoc diff --git a/docs/commands/Repair.html b/docs/commands/Repair.html index ec62f069..8fd32836 100644 --- a/docs/commands/Repair.html +++ b/docs/commands/Repair.html @@ -343,7 +343,7 @@ generated by LDoc diff --git a/docs/commands/Reports.html b/docs/commands/Reports.html index 4f1edec7..22fc2f06 100644 --- a/docs/commands/Reports.html +++ b/docs/commands/Reports.html @@ -607,7 +607,7 @@ generated by LDoc diff --git a/docs/commands/Roles.html b/docs/commands/Roles.html index c69fa4ec..01d43c3c 100644 --- a/docs/commands/Roles.html +++ b/docs/commands/Roles.html @@ -579,7 +579,7 @@ generated by LDoc diff --git a/docs/commands/Spawn.html b/docs/commands/Spawn.html index c833022c..1ef87905 100644 --- a/docs/commands/Spawn.html +++ b/docs/commands/Spawn.html @@ -411,7 +411,7 @@ generated by LDoc diff --git a/docs/commands/Teleport.html b/docs/commands/Teleport.html index 3c89af3f..4e5c50df 100644 --- a/docs/commands/Teleport.html +++ b/docs/commands/Teleport.html @@ -506,7 +506,7 @@ generated by LDoc diff --git a/docs/commands/Warnings.html b/docs/commands/Warnings.html index 6906cbca..ba38f71a 100644 --- a/docs/commands/Warnings.html +++ b/docs/commands/Warnings.html @@ -591,7 +591,7 @@ generated by LDoc diff --git a/docs/configs/Advanced-Start.html b/docs/configs/Advanced-Start.html index be69c242..4777a84c 100644 --- a/docs/configs/Advanced-Start.html +++ b/docs/configs/Advanced-Start.html @@ -528,7 +528,7 @@ generated by LDoc diff --git a/docs/configs/Autofill.html b/docs/configs/Autofill.html index cd81a662..0b0dc5d9 100644 --- a/docs/configs/Autofill.html +++ b/docs/configs/Autofill.html @@ -259,7 +259,7 @@ generated by LDoc diff --git a/docs/configs/Bonuses.html b/docs/configs/Bonuses.html index a4185dd8..77da0d4a 100644 --- a/docs/configs/Bonuses.html +++ b/docs/configs/Bonuses.html @@ -259,7 +259,7 @@ generated by LDoc diff --git a/docs/configs/Chat-Reply.html b/docs/configs/Chat-Reply.html index c423011a..3287d5ff 100644 --- a/docs/configs/Chat-Reply.html +++ b/docs/configs/Chat-Reply.html @@ -507,7 +507,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Admin.html b/docs/configs/Commands-Auth-Admin.html index 69ea2518..f96e4d66 100644 --- a/docs/configs/Commands-Auth-Admin.html +++ b/docs/configs/Commands-Auth-Admin.html @@ -316,7 +316,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Roles.html b/docs/configs/Commands-Auth-Roles.html index ee2560db..73a08902 100644 --- a/docs/configs/Commands-Auth-Roles.html +++ b/docs/configs/Commands-Auth-Roles.html @@ -342,7 +342,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Auth-Runtime-Disable.html b/docs/configs/Commands-Auth-Runtime-Disable.html index d49c5b0f..157cf4ce 100644 --- a/docs/configs/Commands-Auth-Runtime-Disable.html +++ b/docs/configs/Commands-Auth-Runtime-Disable.html @@ -464,7 +464,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Color-Parse.html b/docs/configs/Commands-Color-Parse.html index 1042227a..98d167ea 100644 --- a/docs/configs/Commands-Color-Parse.html +++ b/docs/configs/Commands-Color-Parse.html @@ -342,7 +342,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Parse-Roles.html b/docs/configs/Commands-Parse-Roles.html index 9cbbf6a7..df0b8cb4 100644 --- a/docs/configs/Commands-Parse-Roles.html +++ b/docs/configs/Commands-Parse-Roles.html @@ -376,7 +376,7 @@ generated by LDoc diff --git a/docs/configs/Commands-Parse.html b/docs/configs/Commands-Parse.html index ab37c9bc..03a3358b 100644 --- a/docs/configs/Commands-Parse.html +++ b/docs/configs/Commands-Parse.html @@ -332,7 +332,7 @@ see ./expcore/commands.lua for more details

generated by LDoc diff --git a/docs/configs/Compilatron.html b/docs/configs/Compilatron.html index 4ffe586f..ac9839fb 100644 --- a/docs/configs/Compilatron.html +++ b/docs/configs/Compilatron.html @@ -376,7 +376,7 @@ generated by LDoc diff --git a/docs/configs/Death-Logger.html b/docs/configs/Death-Logger.html index ab15e9bb..0426e9be 100644 --- a/docs/configs/Death-Logger.html +++ b/docs/configs/Death-Logger.html @@ -498,7 +498,7 @@ generated by LDoc diff --git a/docs/configs/Discord-Alerts.html b/docs/configs/Discord-Alerts.html index 54d364d6..d2fdcc51 100644 --- a/docs/configs/Discord-Alerts.html +++ b/docs/configs/Discord-Alerts.html @@ -259,7 +259,7 @@ generated by LDoc diff --git a/docs/configs/File-Loader.html b/docs/configs/File-Loader.html index a3909d3c..df6d41a3 100644 --- a/docs/configs/File-Loader.html +++ b/docs/configs/File-Loader.html @@ -262,7 +262,7 @@ generated by LDoc diff --git a/docs/configs/Permission-Groups.html b/docs/configs/Permission-Groups.html index 17b56988..113ec3ca 100644 --- a/docs/configs/Permission-Groups.html +++ b/docs/configs/Permission-Groups.html @@ -317,7 +317,7 @@ generated by LDoc diff --git a/docs/configs/Player-List.html b/docs/configs/Player-List.html index f447c497..d1f774fe 100644 --- a/docs/configs/Player-List.html +++ b/docs/configs/Player-List.html @@ -716,7 +716,7 @@ generated by LDoc diff --git a/docs/configs/Pollution-Grading.html b/docs/configs/Pollution-Grading.html index b714a8be..dc21bace 100644 --- a/docs/configs/Pollution-Grading.html +++ b/docs/configs/Pollution-Grading.html @@ -406,7 +406,7 @@ generated by LDoc diff --git a/docs/configs/Popup-Messages.html b/docs/configs/Popup-Messages.html index 92f6ed5b..cd075fd5 100644 --- a/docs/configs/Popup-Messages.html +++ b/docs/configs/Popup-Messages.html @@ -436,7 +436,7 @@ generated by LDoc diff --git a/docs/configs/Preset-Player-Colours.html b/docs/configs/Preset-Player-Colours.html index c2068453..9c7e6f11 100644 --- a/docs/configs/Preset-Player-Colours.html +++ b/docs/configs/Preset-Player-Colours.html @@ -346,7 +346,7 @@ generated by LDoc diff --git a/docs/configs/Preset-Player-Quickbar.html b/docs/configs/Preset-Player-Quickbar.html index 578a5a93..eb0ce20d 100644 --- a/docs/configs/Preset-Player-Quickbar.html +++ b/docs/configs/Preset-Player-Quickbar.html @@ -259,7 +259,7 @@ generated by LDoc diff --git a/docs/configs/Repair.html b/docs/configs/Repair.html index 4ff50110..9af9f938 100644 --- a/docs/configs/Repair.html +++ b/docs/configs/Repair.html @@ -436,7 +436,7 @@ generated by LDoc diff --git a/docs/configs/Rockets.html b/docs/configs/Rockets.html index 57da2800..fa735066 100644 --- a/docs/configs/Rockets.html +++ b/docs/configs/Rockets.html @@ -856,7 +856,7 @@ generated by LDoc diff --git a/docs/configs/Roles.html b/docs/configs/Roles.html index 7ea81e7d..a49c8259 100644 --- a/docs/configs/Roles.html +++ b/docs/configs/Roles.html @@ -342,7 +342,7 @@ generated by LDoc diff --git a/docs/configs/Science.html b/docs/configs/Science.html index adfbe697..14411a30 100644 --- a/docs/configs/Science.html +++ b/docs/configs/Science.html @@ -376,7 +376,7 @@ generated by LDoc diff --git a/docs/configs/Scorched-Earth.html b/docs/configs/Scorched-Earth.html index 4631fd77..d7b859fe 100644 --- a/docs/configs/Scorched-Earth.html +++ b/docs/configs/Scorched-Earth.html @@ -410,7 +410,7 @@ generated by LDoc diff --git a/docs/configs/Spawn-Area.html b/docs/configs/Spawn-Area.html index 8325f698..c3e12a5a 100644 --- a/docs/configs/Spawn-Area.html +++ b/docs/configs/Spawn-Area.html @@ -263,34 +263,7 @@ - infinite_ammo_turrets - - - enabled - - - ammo_type - - - locations - - - afk_belts - - - enabled - - - locations - - - corrections - - - protect_entities - - - offset + spawn_area deconstruction_radius @@ -302,13 +275,85 @@ pattern_radius - pattern_tile + turrets + + + enabled + + + ammo_type + + + refill_time + + + offset + + + locations + + + afk_belts + + + enabled + + + belt_type + + + protected + + + offset + + + locations + + + water + + + enabled + + + water_tile + + + offset + + + locations entities - tiles + enabled + + + protected + + + operable + + + offset + + + locations + + + enabled + + + pattern_tile + + + offset + + + locations @@ -322,258 +367,15 @@
- # - infinite_ammo_turrets + # + spawn_area

-

These turrets will have they ammo refilled automatically and can not be looted

- - - - - - - - - - - - - - -
-
-
-
- # - enabled -
-
-
-
- -

-

weather the turrets will be created and refilled

- - - - - - - - - - - - - - -
-
-
-
- # - ammo_type -
-
-
-
- -

-

the ammo type that will be used

- - - - - - - - - - - - - - -
-
-
-
- # - locations -
-
-
-
- -

-

locations of all turrets, this is default it can be changed during runtime

- - - - - - - - - - - - - - -
-
-
-
- # - afk_belts -
-
-
-
- -

-

setting relating to afk belts round the spawn point

- - - - - - - - - - - - - - -
-
-
-
- # - enabled -
-
-
-
- -

-

weather afk belts will be generated

- - - - - - - - - - - - - - -
-
-
-
- # - locations -
-
-
-
- -

-

top left connors of any afk belt loops to be added

- - - - - - - - - - - - - - -
-
-
-
- # - corrections -
-
-
-
- -

-

Some settings that have no where else to go

- - - - - - - - - - - - - - -
-
-
-
- # - protect_entities -
-
-
-
- -

-

if the spawn entites will be protected

- - - - - - - - - - - - - - -
-
-
-
- # - offset -
-
-
-
- -

-

a global offset value to correct the x and y values of the tables below

+

Settings relating to the whole spawn area

@@ -600,7 +402,7 @@

-

when the spawn is made this area will have all entities removed first

+

All entities within this radius will be removed

@@ -627,7 +429,7 @@

-

this is the tile that will spawn in the deconstruction radius

+

Tile to be placed in the deconstruction radius, use nil for map gen

@@ -654,7 +456,7 @@

-

this is the radius of the pattern all water in this area will be filled

+

All water within this radius will be land filled

@@ -673,15 +475,448 @@
- # - pattern_tile + # + turrets

-

the tile that is used for the pattern

+

Settings relating to adding turrets to spawn

+ + + + + + + + + + + + + + +
+
+
+
+ # + enabled +
+
+
+
+ +

+

Whether turrets will be added to spawn

+ + + + + + + + + + + + + + +
+
+
+
+ # + ammo_type +
+
+
+
+ +

+

The ammo type that will be used during refills

+ + + + + + + + + + + + + + +
+
+
+
+ # + refill_time +
+
+
+
+ +

+

The time in ticks between each refill of the turrets, only change if having lag issues

+ + + + + + + + + + + + + + +
+
+
+
+ # + offset +
+
+
+
+ +

+

The position offset to apply to turrets

+ + + + + + + + + + + + + + +
+
+
+
+ # + locations +
+
+
+
+ +

+

The locations of all turrets, this list can change during runtime

+ + + + + + + + + + + + + + +
+
+
+
+ # + afk_belts +
+
+
+
+ +

+

Settings relating to adding afk belts to spawn

+ + + + + + + + + + + + + + +
+
+
+
+ # + enabled +
+
+
+
+ +

+

Whether afk belts will be added to spawn

+ + + + + + + + + + + + + + +
+
+
+
+ # + belt_type +
+
+
+
+ +

+

The belt to be used as afk belts

+ + + + + + + + + + + + + + +
+
+
+
+ # + protected +
+
+
+
+ +

+

Whether belts will be protected from player interaction

+ + + + + + + + + + + + + + +
+
+
+
+ # + offset +
+
+
+
+ +

+

The position offset to apply to afk belts

+ + + + + + + + + + + + + + +
+
+
+
+ # + locations +
+
+
+
+ +

+

The locations to spawn afk belts at, given as the top left position

+ + + + + + + + + + + + + + +
+
+
+
+ # + water +
+
+
+
+ +

+

Settings relating to adding water to spawn

+ + + + + + + + + + + + + + +
+
+
+
+ # + enabled +
+
+
+
+ +

+

Whether water tiles will be added to spawn

+ + + + + + + + + + + + + + +
+
+
+
+ # + water_tile +
+
+
+
+ +

+

The tile to be used as the water tile

+ + + + + + + + + + + + + + +
+
+
+
+ # + offset +
+
+
+
+ +

+

The position offset to apply to water tiles

+ + + + + + + + + + + + + + +
+
+
+
+ # + locations +
+
+
+
+ +

+

The location of the water tiles {x,y} + Each is a 3x3 with the closest tile to 0,0 removed

@@ -708,7 +943,7 @@

-

All entities that will be created as part of spawn {entity-name,x-pos,y-pos}

+

Settings relating to adding entities to spawn

@@ -727,15 +962,231 @@
- # - tiles + # + enabled

-

The location of the "pattern" tiles {x-pos,y-pos}

+

Whether entities will be added to spawn

+ + + + + + + + + + + + + + +
+
+
+
+ # + protected +
+
+
+
+ +

+

Whether entities will be protected from player interaction

+ + + + + + + + + + + + + + +
+
+
+
+ # + operable +
+
+
+
+ +

+

Whether entities can be opened by players, must be true if chests are used

+ + + + + + + + + + + + + + +
+
+
+
+ # + offset +
+
+
+
+ +

+

The position offset to apply to entities

+ + + + + + + + + + + + + + +
+
+
+
+ # + locations +
+
+
+
+ +

+

The location and names of entities {name,x,y}

+ + + + + + + + + + + + + + +
+
+
+
+ # + enabled +
+
+
+
+ +

+

Whether pattern tiles will be added to spawn

+ + + + + + + + + + + + + + +
+
+
+
+ # + pattern_tile +
+
+
+
+ +

+

The tile to be used for the pattern

+ + + + + + + + + + + + + + +
+
+
+
+ # + offset +
+
+
+
+ +

+

The position offset to apply to pattern tiles

+ + + + + + + + + + + + + + +
+
+
+
+ # + locations +
+
+
+
+ +

+

The location of the pattern tiles {x,y}

@@ -766,7 +1217,7 @@ generated by LDoc
diff --git a/docs/configs/Statistics.html b/docs/configs/Statistics.html index fdf3b60b..5b16eef1 100644 --- a/docs/configs/Statistics.html +++ b/docs/configs/Statistics.html @@ -676,7 +676,7 @@ generated by LDoc diff --git a/docs/configs/Tasks.html b/docs/configs/Tasks.html index 78ab1601..9cf9cccf 100644 --- a/docs/configs/Tasks.html +++ b/docs/configs/Tasks.html @@ -406,7 +406,7 @@ generated by LDoc diff --git a/docs/configs/Warnings.html b/docs/configs/Warnings.html index 40b6a248..801c2716 100644 --- a/docs/configs/Warnings.html +++ b/docs/configs/Warnings.html @@ -377,7 +377,7 @@ generated by LDoc diff --git a/docs/configs/Warps.html b/docs/configs/Warps.html index 0a682886..3eb057cb 100644 --- a/docs/configs/Warps.html +++ b/docs/configs/Warps.html @@ -766,7 +766,7 @@ generated by LDoc diff --git a/docs/configs/inventory_clear.html b/docs/configs/inventory_clear.html index 87abbb5a..92e2c935 100644 --- a/docs/configs/inventory_clear.html +++ b/docs/configs/inventory_clear.html @@ -259,7 +259,7 @@ generated by LDoc diff --git a/docs/control/Jail.html b/docs/control/Jail.html index 17966b28..10688a82 100644 --- a/docs/control/Jail.html +++ b/docs/control/Jail.html @@ -797,7 +797,7 @@ generated by LDoc diff --git a/docs/control/Production.html b/docs/control/Production.html index 4ff20bc5..715501a9 100644 --- a/docs/control/Production.html +++ b/docs/control/Production.html @@ -1351,7 +1351,7 @@ generated by LDoc diff --git a/docs/control/Reports.html b/docs/control/Reports.html index 48af4f6c..7b53fec7 100644 --- a/docs/control/Reports.html +++ b/docs/control/Reports.html @@ -1164,7 +1164,7 @@ generated by LDoc diff --git a/docs/control/Rockets.html b/docs/control/Rockets.html index 09b0ebaa..ea156e5e 100644 --- a/docs/control/Rockets.html +++ b/docs/control/Rockets.html @@ -1006,7 +1006,7 @@ generated by LDoc diff --git a/docs/control/Tasks.html b/docs/control/Tasks.html index 32195da4..b4d26631 100644 --- a/docs/control/Tasks.html +++ b/docs/control/Tasks.html @@ -992,7 +992,7 @@ Tasks.update_task(task_id, 'We need more iron!', gam generated by LDoc diff --git a/docs/control/Warnings.html b/docs/control/Warnings.html index 3c63f2cf..d9da4490 100644 --- a/docs/control/Warnings.html +++ b/docs/control/Warnings.html @@ -1547,7 +1547,7 @@ generated by LDoc diff --git a/docs/control/Warps.html b/docs/control/Warps.html index da3c3a93..33542ca1 100644 --- a/docs/control/Warps.html +++ b/docs/control/Warps.html @@ -1529,7 +1529,7 @@ Warps.make_warp_tag(warp_id) generated by LDoc diff --git a/docs/core/Async.html b/docs/core/Async.html index 47c28614..1fa0aaba 100644 --- a/docs/core/Async.html +++ b/docs/core/Async.html @@ -620,7 +620,7 @@ Async.register(function(player, message) generated by LDoc diff --git a/docs/core/Commands.html b/docs/core/Commands.html index e9e9027b..d0f81c2e 100644 --- a/docs/core/Commands.html +++ b/docs/core/Commands.html @@ -2435,7 +2435,7 @@ nb: use error(error_message) within your callback to trigger do not trigger dire generated by LDoc diff --git a/docs/core/Common.html b/docs/core/Common.html index 9d8479d7..f278d160 100644 --- a/docs/core/Common.html +++ b/docs/core/Common.html @@ -2774,7 +2774,7 @@ https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4 generated by LDoc diff --git a/docs/core/Datastore.html b/docs/core/Datastore.html index bdae8365..71203f33 100644 --- a/docs/core/Datastore.html +++ b/docs/core/Datastore.html @@ -2971,7 +2971,7 @@ ExampleData:on_update(function(key, value) generated by LDoc diff --git a/docs/core/External.html b/docs/core/External.html index a43bfe85..a4bdbe7d 100644 --- a/docs/core/External.html +++ b/docs/core/External.html @@ -755,7 +755,7 @@ generated by LDoc diff --git a/docs/core/Groups.html b/docs/core/Groups.html index e5f2934a..4b011701 100644 --- a/docs/core/Groups.html +++ b/docs/core/Groups.html @@ -1450,7 +1450,7 @@ generated by LDoc diff --git a/docs/core/Gui.html b/docs/core/Gui.html index ca545e75..c02f5c6f 100644 --- a/docs/core/Gui.html +++ b/docs/core/Gui.html @@ -4428,7 +4428,7 @@ Gui.left_toolbar_button('entity/inserter', generated by LDoc diff --git a/docs/core/PlayerData.html b/docs/core/PlayerData.html index 69077e1e..c3b837d8 100644 --- a/docs/core/PlayerData.html +++ b/docs/core/PlayerData.html @@ -538,7 +538,7 @@ generated by LDoc diff --git a/docs/core/Roles.html b/docs/core/Roles.html index 0b010fe2..53225cd4 100644 --- a/docs/core/Roles.html +++ b/docs/core/Roles.html @@ -3398,7 +3398,7 @@ nb: this is one way, failing false after already gaining the role will not revok generated by LDoc diff --git a/docs/data/Alt-View.html b/docs/data/Alt-View.html index 1c48b0db..5dc3a0a8 100644 --- a/docs/data/Alt-View.html +++ b/docs/data/Alt-View.html @@ -342,7 +342,7 @@ generated by LDoc diff --git a/docs/data/Bonus.html b/docs/data/Bonus.html index daed46ca..b71f9fee 100644 --- a/docs/data/Bonus.html +++ b/docs/data/Bonus.html @@ -494,7 +494,7 @@ generated by LDoc diff --git a/docs/data/Greetings.html b/docs/data/Greetings.html index b7a6e7bf..41ea1832 100644 --- a/docs/data/Greetings.html +++ b/docs/data/Greetings.html @@ -437,7 +437,7 @@ generated by LDoc diff --git a/docs/data/Player-Colours.html b/docs/data/Player-Colours.html index ab0420c8..d8b5b485 100644 --- a/docs/data/Player-Colours.html +++ b/docs/data/Player-Colours.html @@ -398,7 +398,7 @@ generated by LDoc diff --git a/docs/data/Quickbar.html b/docs/data/Quickbar.html index f1f7b0a2..0f52db5f 100644 --- a/docs/data/Quickbar.html +++ b/docs/data/Quickbar.html @@ -415,7 +415,7 @@ generated by LDoc diff --git a/docs/data/Tag.html b/docs/data/Tag.html index ab205cb6..b5a3681d 100644 --- a/docs/data/Tag.html +++ b/docs/data/Tag.html @@ -547,7 +547,7 @@ generated by LDoc diff --git a/docs/guis/Autofill.html b/docs/guis/Autofill.html index d2dffb78..50df8856 100644 --- a/docs/guis/Autofill.html +++ b/docs/guis/Autofill.html @@ -599,7 +599,7 @@ generated by LDoc diff --git a/docs/guis/Player-List.html b/docs/guis/Player-List.html index 0462c27d..5db4f742 100644 --- a/docs/guis/Player-List.html +++ b/docs/guis/Player-List.html @@ -713,7 +713,7 @@ generated by LDoc diff --git a/docs/guis/Readme.html b/docs/guis/Readme.html index 9b818bf6..0c064be7 100644 --- a/docs/guis/Readme.html +++ b/docs/guis/Readme.html @@ -1005,7 +1005,7 @@ generated by LDoc diff --git a/docs/guis/Rocket-Info.html b/docs/guis/Rocket-Info.html index 3ca13c26..fca656a5 100644 --- a/docs/guis/Rocket-Info.html +++ b/docs/guis/Rocket-Info.html @@ -713,7 +713,7 @@ generated by LDoc diff --git a/docs/guis/Science-Info.html b/docs/guis/Science-Info.html index baae5a84..c2190442 100644 --- a/docs/guis/Science-Info.html +++ b/docs/guis/Science-Info.html @@ -592,7 +592,7 @@ generated by LDoc diff --git a/docs/guis/Task-List.html b/docs/guis/Task-List.html index 2bdb2a9f..816cd7a4 100644 --- a/docs/guis/Task-List.html +++ b/docs/guis/Task-List.html @@ -778,7 +778,7 @@ generated by LDoc diff --git a/docs/guis/Warps-List.html b/docs/guis/Warps-List.html index acf3c0d4..b66ea7ec 100644 --- a/docs/guis/Warps-List.html +++ b/docs/guis/Warps-List.html @@ -1082,7 +1082,7 @@ generated by LDoc diff --git a/docs/guis/server-ups.html b/docs/guis/server-ups.html index 17535746..2d34c668 100644 --- a/docs/guis/server-ups.html +++ b/docs/guis/server-ups.html @@ -515,7 +515,7 @@ generated by LDoc diff --git a/docs/index.html b/docs/index.html index 50153a2b..90889585 100644 --- a/docs/index.html +++ b/docs/index.html @@ -581,7 +581,7 @@ Events.set_event_filter(defines.events.on_built_entity, {{filter = "name", name generated by LDoc diff --git a/docs/modules/control.html b/docs/modules/control.html index b178bb30..07714b0f 100644 --- a/docs/modules/control.html +++ b/docs/modules/control.html @@ -317,7 +317,7 @@ generated by LDoc diff --git a/docs/modules/modules.addons.station-auto-name.html b/docs/modules/modules.addons.station-auto-name.html index 651e55c8..41dca16a 100644 --- a/docs/modules/modules.addons.station-auto-name.html +++ b/docs/modules/modules.addons.station-auto-name.html @@ -315,7 +315,7 @@ Events.set_event_filter(defines.events.on_built_entity, {{filter = "name", name generated by LDoc diff --git a/docs/modules/overrides.debug.html b/docs/modules/overrides.debug.html index 108bec39..21d796c5 100644 --- a/docs/modules/overrides.debug.html +++ b/docs/modules/overrides.debug.html @@ -676,7 +676,7 @@ generated by LDoc diff --git a/docs/modules/overrides.math.html b/docs/modules/overrides.math.html index 4ab48b47..eefee835 100644 --- a/docs/modules/overrides.math.html +++ b/docs/modules/overrides.math.html @@ -375,7 +375,7 @@ generated by LDoc diff --git a/docs/modules/overrides.table.html b/docs/modules/overrides.table.html index 24a20d10..e2c7b25d 100644 --- a/docs/modules/overrides.table.html +++ b/docs/modules/overrides.table.html @@ -2030,7 +2030,7 @@ generated by LDoc diff --git a/docs/modules/utils.event.html b/docs/modules/utils.event.html index f93d2810..c7d6bdd1 100644 --- a/docs/modules/utils.event.html +++ b/docs/modules/utils.event.html @@ -1314,7 +1314,7 @@ generated by LDoc diff --git a/docs/modules/utils.event_core.html b/docs/modules/utils.event_core.html index 76a814a7..824de660 100644 --- a/docs/modules/utils.event_core.html +++ b/docs/modules/utils.event_core.html @@ -456,7 +456,7 @@ generated by LDoc diff --git a/docs/modules/utils.task.html b/docs/modules/utils.task.html index ca72e2a7..021699e2 100644 --- a/docs/modules/utils.task.html +++ b/docs/modules/utils.task.html @@ -673,7 +673,7 @@ generated by LDoc diff --git a/docs/topics/LICENSE.html b/docs/topics/LICENSE.html index d0ef39ff..096939f1 100644 --- a/docs/topics/LICENSE.html +++ b/docs/topics/LICENSE.html @@ -811,7 +811,7 @@ Public License instead of this License. But first, please read generated by LDoc diff --git a/docs/topics/README.md.html b/docs/topics/README.md.html index 7021b8ef..2e877cbf 100644 --- a/docs/topics/README.md.html +++ b/docs/topics/README.md.html @@ -366,7 +366,7 @@ Please report these errors to [the issues page](issues). generated by LDoc From e5f3ce5966b3a8be2b46b0742ab8b88ce44f106e Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 25 Apr 2021 19:21:17 +0000 Subject: [PATCH 38/56] Automatic Doc Update --- docs/addons/Advanced-Start.html | 3 +- docs/addons/Chat-Popups.html | 3 +- docs/addons/Chat-Reply.html | 3 +- docs/addons/Compilatron.html | 3 +- docs/addons/Damage-Popups.html | 3 +- docs/addons/Death-Logger.html | 3 +- docs/addons/Discord-Alerts.html | 3 +- docs/addons/Inventory-Clear.html | 3 +- docs/addons/Pollution-Grading.html | 3 +- docs/addons/Scorched-Earth.html | 3 +- docs/addons/Spawn-Area.html | 3 +- docs/addons/Tree-Decon.html | 3 +- docs/addons/afk-kick.html | 3 +- docs/addons/report-jail.html | 3 +- docs/commands/Admin-Chat.html | 3 +- docs/commands/Admin-Markers.html | 424 ++++++++++++++++++ docs/commands/Cheat-Mode.html | 3 +- docs/commands/Clear-Inventory.html | 3 +- docs/commands/Connect.html | 3 +- docs/commands/Debug.html | 3 +- docs/commands/Find.html | 3 +- docs/commands/Help.html | 3 +- docs/commands/Home.html | 3 +- docs/commands/Interface.html | 3 +- docs/commands/InventorySearch.html | 3 +- docs/commands/Jail.html | 3 +- docs/commands/Kill.html | 3 +- docs/commands/LastLocation.html | 3 +- docs/commands/Me.html | 3 +- docs/commands/Rainbow.html | 3 +- docs/commands/Repair.html | 3 +- docs/commands/Reports.html | 3 +- docs/commands/Roles.html | 3 +- docs/commands/Spawn.html | 3 +- docs/commands/Teleport.html | 3 +- docs/commands/Warnings.html | 3 +- docs/configs/Advanced-Start.html | 3 +- docs/configs/Autofill.html | 3 +- docs/configs/Bonuses.html | 3 +- docs/configs/Chat-Reply.html | 3 +- docs/configs/Commands-Auth-Admin.html | 3 +- docs/configs/Commands-Auth-Roles.html | 3 +- .../Commands-Auth-Runtime-Disable.html | 3 +- docs/configs/Commands-Color-Parse.html | 3 +- docs/configs/Commands-Parse-Roles.html | 3 +- docs/configs/Commands-Parse.html | 3 +- docs/configs/Compilatron.html | 3 +- docs/configs/Death-Logger.html | 3 +- docs/configs/Discord-Alerts.html | 3 +- docs/configs/File-Loader.html | 3 +- docs/configs/Permission-Groups.html | 3 +- docs/configs/Player-List.html | 3 +- docs/configs/Pollution-Grading.html | 3 +- docs/configs/Popup-Messages.html | 3 +- docs/configs/Preset-Player-Colours.html | 3 +- docs/configs/Preset-Player-Quickbar.html | 3 +- docs/configs/Repair.html | 3 +- docs/configs/Rockets.html | 3 +- docs/configs/Roles.html | 3 +- docs/configs/Science.html | 3 +- docs/configs/Scorched-Earth.html | 3 +- docs/configs/Spawn-Area.html | 3 +- docs/configs/Statistics.html | 3 +- docs/configs/Tasks.html | 3 +- docs/configs/Warnings.html | 3 +- docs/configs/Warps.html | 3 +- docs/configs/inventory_clear.html | 3 +- docs/control/Jail.html | 3 +- docs/control/Production.html | 3 +- docs/control/Reports.html | 3 +- docs/control/Rockets.html | 3 +- docs/control/Tasks.html | 3 +- docs/control/Warnings.html | 3 +- docs/control/Warps.html | 3 +- docs/core/Async.html | 3 +- docs/core/Commands.html | 3 +- docs/core/Common.html | 3 +- docs/core/Datastore.html | 3 +- docs/core/External.html | 3 +- docs/core/Groups.html | 3 +- docs/core/Gui.html | 3 +- docs/core/PlayerData.html | 3 +- docs/core/Roles.html | 3 +- docs/data/Alt-View.html | 3 +- docs/data/Bonus.html | 3 +- docs/data/Greetings.html | 3 +- docs/data/Player-Colours.html | 3 +- docs/data/Quickbar.html | 3 +- docs/data/Tag.html | 3 +- docs/guis/Autofill.html | 3 +- docs/guis/Player-List.html | 3 +- docs/guis/Readme.html | 3 +- docs/guis/Rocket-Info.html | 3 +- docs/guis/Science-Info.html | 3 +- docs/guis/Task-List.html | 3 +- docs/guis/Warps-List.html | 3 +- docs/guis/server-ups.html | 3 +- docs/index.html | 7 +- docs/modules/control.html | 3 +- .../modules.addons.station-auto-name.html | 3 +- docs/modules/overrides.debug.html | 3 +- docs/modules/overrides.math.html | 3 +- docs/modules/overrides.table.html | 3 +- docs/modules/utils.event.html | 3 +- docs/modules/utils.event_core.html | 3 +- docs/modules/utils.task.html | 3 +- docs/topics/LICENSE.html | 3 +- docs/topics/README.md.html | 3 +- 108 files changed, 642 insertions(+), 107 deletions(-) create mode 100644 docs/commands/Admin-Markers.html diff --git a/docs/addons/Advanced-Start.html b/docs/addons/Advanced-Start.html index bfe54549..dd1acf48 100644 --- a/docs/addons/Advanced-Start.html +++ b/docs/addons/Advanced-Start.html @@ -129,6 +129,7 @@

Commands

@@ -812,7 +813,7 @@ Public License instead of this License. But first, please read generated by LDoc diff --git a/docs/topics/README.md.html b/docs/topics/README.md.html index 226215b1..1242c613 100644 --- a/docs/topics/README.md.html +++ b/docs/topics/README.md.html @@ -149,6 +149,7 @@ + @@ -367,7 +368,7 @@ Please report these errors to [the issues page](issues). generated by LDoc From 2df7482a772d51e9cc47d83faf59f8204bfebdf3 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Mon, 26 Apr 2021 00:20:55 +0100 Subject: [PATCH 42/56] 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 From 3229318debf6ecd0eadd62663c1ee1226ce9d8f6 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 25 Apr 2021 23:23:07 +0000 Subject: [PATCH 43/56] Automatic Doc Update --- docs/addons/Advanced-Start.html | 5 +- docs/addons/Chat-Popups.html | 5 +- docs/addons/Chat-Reply.html | 5 +- docs/addons/Compilatron.html | 5 +- docs/addons/Damage-Popups.html | 5 +- docs/addons/Death-Logger.html | 5 +- docs/addons/Discord-Alerts.html | 33 +- docs/addons/Inventory-Clear.html | 5 +- docs/addons/Pollution-Grading.html | 5 +- docs/addons/Scorched-Earth.html | 5 +- docs/addons/Spawn-Area.html | 5 +- docs/addons/Tree-Decon.html | 5 +- docs/addons/afk-kick.html | 5 +- docs/addons/report-jail.html | 5 +- docs/commands/Admin-Chat.html | 5 +- docs/commands/Admin-Markers.html | 5 +- docs/commands/Cheat-Mode.html | 5 +- docs/commands/Clear-Inventory.html | 5 +- docs/commands/Connect.html | 5 +- docs/commands/Debug.html | 5 +- docs/commands/Find.html | 5 +- docs/commands/Help.html | 5 +- docs/commands/Home.html | 5 +- docs/commands/Interface.html | 5 +- docs/commands/InventorySearch.html | 5 +- docs/commands/Jail.html | 5 +- docs/commands/Kill.html | 5 +- docs/commands/LastLocation.html | 5 +- docs/commands/Me.html | 5 +- docs/commands/Protection.html | 571 +++++++++ docs/commands/Rainbow.html | 5 +- docs/commands/Repair.html | 5 +- docs/commands/Reports.html | 5 +- docs/commands/Roles.html | 5 +- docs/commands/Spawn.html | 5 +- docs/commands/Spectate.html | 5 +- docs/commands/Teleport.html | 5 +- docs/commands/Warnings.html | 5 +- docs/configs/Advanced-Start.html | 5 +- docs/configs/Autofill.html | 5 +- docs/configs/Bonuses.html | 5 +- docs/configs/Chat-Reply.html | 5 +- docs/configs/Commands-Auth-Admin.html | 5 +- docs/configs/Commands-Auth-Roles.html | 5 +- .../Commands-Auth-Runtime-Disable.html | 5 +- docs/configs/Commands-Color-Parse.html | 5 +- docs/configs/Commands-Parse-Roles.html | 5 +- docs/configs/Commands-Parse.html | 5 +- docs/configs/Compilatron.html | 5 +- docs/configs/Death-Logger.html | 5 +- docs/configs/Discord-Alerts.html | 5 +- docs/configs/File-Loader.html | 5 +- docs/configs/Permission-Groups.html | 5 +- docs/configs/Player-List.html | 5 +- docs/configs/Pollution-Grading.html | 5 +- docs/configs/Popup-Messages.html | 5 +- docs/configs/Preset-Player-Colours.html | 5 +- docs/configs/Preset-Player-Quickbar.html | 5 +- docs/configs/Repair.html | 5 +- docs/configs/Rockets.html | 5 +- docs/configs/Roles.html | 5 +- docs/configs/Science.html | 5 +- docs/configs/Scorched-Earth.html | 5 +- docs/configs/Spawn-Area.html | 5 +- docs/configs/Statistics.html | 5 +- docs/configs/Tasks.html | 5 +- docs/configs/Warnings.html | 5 +- docs/configs/Warps.html | 5 +- docs/configs/inventory_clear.html | 5 +- docs/control/Jail.html | 5 +- docs/control/Production.html | 5 +- docs/control/Protection.html | 1036 +++++++++++++++++ docs/control/Reports.html | 5 +- docs/control/Rockets.html | 5 +- docs/control/Selection.html | 926 +++++++++++++++ docs/control/Tasks.html | 5 +- docs/control/Warnings.html | 5 +- docs/control/Warps.html | 5 +- docs/core/Async.html | 5 +- docs/core/Commands.html | 5 +- docs/core/Common.html | 5 +- docs/core/Datastore.html | 5 +- docs/core/External.html | 5 +- docs/core/Groups.html | 5 +- docs/core/Gui.html | 5 +- docs/core/PlayerData.html | 5 +- docs/core/Roles.html | 5 +- docs/data/Alt-View.html | 5 +- docs/data/Bonus.html | 5 +- docs/data/Greetings.html | 5 +- docs/data/Player-Colours.html | 5 +- docs/data/Quickbar.html | 5 +- docs/data/Tag.html | 5 +- docs/guis/Autofill.html | 5 +- docs/guis/Player-List.html | 5 +- docs/guis/Readme.html | 5 +- docs/guis/Rocket-Info.html | 5 +- docs/guis/Science-Info.html | 5 +- docs/guis/Task-List.html | 5 +- docs/guis/Warps-List.html | 5 +- docs/guis/server-ups.html | 5 +- docs/index.html | 17 +- docs/modules/control.html | 5 +- .../modules.addons.station-auto-name.html | 5 +- docs/modules/overrides.debug.html | 5 +- docs/modules/overrides.math.html | 5 +- docs/modules/overrides.table.html | 5 +- docs/modules/utils.event.html | 5 +- docs/modules/utils.event_core.html | 5 +- docs/modules/utils.task.html | 5 +- docs/topics/LICENSE.html | 5 +- docs/topics/README.md.html | 5 +- 112 files changed, 3009 insertions(+), 109 deletions(-) create mode 100644 docs/commands/Protection.html create mode 100644 docs/control/Protection.html create mode 100644 docs/control/Selection.html diff --git a/docs/addons/Advanced-Start.html b/docs/addons/Advanced-Start.html index 00f1d2f1..36d3090c 100644 --- a/docs/addons/Advanced-Start.html +++ b/docs/addons/Advanced-Start.html @@ -88,8 +88,10 @@
+
+
+
+ # + modules.control.protection +
+
+
+
+ + + + + + + + + @@ -456,7 +487,7 @@ generated by LDoc
diff --git a/docs/addons/Inventory-Clear.html b/docs/addons/Inventory-Clear.html index 2016e826..53fcb86e 100644 --- a/docs/addons/Inventory-Clear.html +++ b/docs/addons/Inventory-Clear.html @@ -88,8 +88,10 @@
+
+
+
+ # + expcore.datastore +
+
+
+
+ + + + + + + + + @@ -508,7 +576,7 @@
-

Button displayed in the ehader bar, used to add a new task

+

Button displayed in the header bar, used to add a new task

@@ -528,14 +596,14 @@
- # - edit_task + # + no_tasks_found
-

Button displayed next to tasks which the user is can edit, used to start editing a task

+

Header displayed when no tasks are in the task list

@@ -555,14 +623,14 @@
- # - discard_task + # + subfooter_frame
-

Button displayed next to tasks which the user is can edit, used to delete a task from the list

+

Frame element with the right styling

@@ -582,14 +650,14 @@
- # - add_task_base + # + subfooter_label
-

Set of three elements which make up each row of the task table

+

Label element preset

@@ -609,14 +677,14 @@
- # - confirm_edit + # + subfooter_actions
-

Button displayed next to tasks which the user is currently editing, used to save changes

+

Action flow that contains action buttons

@@ -636,14 +704,14 @@
- # - cancel_edit + # + task_list_item
-

Button displayed next to tasks which the user is currently editing, used to discard changes

+

Button element with a flow around it to fix duplicate name inside of the scroll flow

@@ -663,14 +731,14 @@
- # - task_editing + # + task_list
-

Editing state for a task, contrins a text field and the two edit buttons

+

Scrollable list of all tasks

@@ -690,14 +758,284 @@
- # - task_label + # + task_view_edit_button
-

Default state for a task, contains only a label with the task message

+

Button element inside the task view footer to start editing a task

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_view_close_button +
+
+
+
+ +

Button to close the task view footer

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_view_delete_button +
+
+
+
+ +

Button to delete the task inside the task view footer

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_view_footer +
+
+
+
+ +

Subfooter inside the tasklist container that holds all the elements for viewing a task

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_message_textfield +
+
+
+
+ +

Textfield element used in both the task create and edit footers

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_edit_confirm_button +
+
+
+
+ +

Button to confirm the changes inside the task edit footer

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + edit_task_discard_button +
+
+
+
+ +

Button to discard the changes inside the task edit footer

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_edit_footer +
+
+
+
+ +

Subfooter inside the tasklist container that holds all the elements for editing a task

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_create_confirm_button +
+
+
+
+ +

Button to confirm the changes inside the task create footer

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_create_discard_button +
+
+
+
+ +

Button to discard the changes inside the task create footer

+

+ + + + + + + + + + + + + + +
+
+
+
+ # + task_create_footer +
+
+
+
+ +

Subfooter inside the tasklist container that holds all the elements to create a new task

@@ -783,7 +1121,7 @@ generated by LDoc
diff --git a/docs/guis/Warps-List.html b/docs/guis/Warps-List.html index 65415686..e4da229c 100644 --- a/docs/guis/Warps-List.html +++ b/docs/guis/Warps-List.html @@ -1087,7 +1087,7 @@ generated by LDoc diff --git a/docs/guis/server-ups.html b/docs/guis/server-ups.html index add25ab2..9e77665d 100644 --- a/docs/guis/server-ups.html +++ b/docs/guis/server-ups.html @@ -520,7 +520,7 @@ generated by LDoc diff --git a/docs/index.html b/docs/index.html index 07441ba5..f8e152fe 100644 --- a/docs/index.html +++ b/docs/index.html @@ -606,7 +606,7 @@ Events.set_event_filter(defines.events.on_built_entity, {{filter = "name", name generated by LDoc diff --git a/docs/modules/control.html b/docs/modules/control.html index bfd9a46b..ef0384a9 100644 --- a/docs/modules/control.html +++ b/docs/modules/control.html @@ -322,7 +322,7 @@ generated by LDoc diff --git a/docs/modules/modules.addons.station-auto-name.html b/docs/modules/modules.addons.station-auto-name.html index 3b775d6f..f3cdfe1b 100644 --- a/docs/modules/modules.addons.station-auto-name.html +++ b/docs/modules/modules.addons.station-auto-name.html @@ -320,7 +320,7 @@ Events.set_event_filter(defines.events.on_built_entity, {{filter = "name", name generated by LDoc diff --git a/docs/modules/overrides.debug.html b/docs/modules/overrides.debug.html index 3f33469d..2ae34311 100644 --- a/docs/modules/overrides.debug.html +++ b/docs/modules/overrides.debug.html @@ -681,7 +681,7 @@ generated by LDoc diff --git a/docs/modules/overrides.math.html b/docs/modules/overrides.math.html index bd95adef..bdf50ac7 100644 --- a/docs/modules/overrides.math.html +++ b/docs/modules/overrides.math.html @@ -380,7 +380,7 @@ generated by LDoc diff --git a/docs/modules/overrides.table.html b/docs/modules/overrides.table.html index a8886808..42f65b31 100644 --- a/docs/modules/overrides.table.html +++ b/docs/modules/overrides.table.html @@ -2035,7 +2035,7 @@ generated by LDoc diff --git a/docs/modules/utils.event.html b/docs/modules/utils.event.html index 40f17fbb..f7ed5925 100644 --- a/docs/modules/utils.event.html +++ b/docs/modules/utils.event.html @@ -1319,7 +1319,7 @@ generated by LDoc diff --git a/docs/modules/utils.event_core.html b/docs/modules/utils.event_core.html index bc8f2442..afe81b19 100644 --- a/docs/modules/utils.event_core.html +++ b/docs/modules/utils.event_core.html @@ -461,7 +461,7 @@ generated by LDoc diff --git a/docs/modules/utils.task.html b/docs/modules/utils.task.html index 3388e824..24a3828d 100644 --- a/docs/modules/utils.task.html +++ b/docs/modules/utils.task.html @@ -678,7 +678,7 @@ generated by LDoc diff --git a/docs/topics/LICENSE.html b/docs/topics/LICENSE.html index fccd066f..1a567026 100644 --- a/docs/topics/LICENSE.html +++ b/docs/topics/LICENSE.html @@ -816,7 +816,7 @@ Public License instead of this License. But first, please read generated by LDoc diff --git a/docs/topics/README.md.html b/docs/topics/README.md.html index a0b15c4c..25a5a42d 100644 --- a/docs/topics/README.md.html +++ b/docs/topics/README.md.html @@ -371,7 +371,7 @@ Please report these errors to [the issues page](issues). generated by LDoc From b7d005fadc92b56b878f35806e69cb1ab1b12f2c Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Thu, 29 Apr 2021 23:53:35 +0100 Subject: [PATCH 56/56] Update expcore/datastore.lua Co-authored-by: mark9064 <30447455+mark9064@users.noreply.github.com> --- expcore/datastore.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/expcore/datastore.lua b/expcore/datastore.lua index e5d72bb9..241699cd 100644 --- a/expcore/datastore.lua +++ b/expcore/datastore.lua @@ -522,7 +522,7 @@ function Datastore:increment(key, delta) return self:set(key, value + (delta or 1)) end -local function update_error(err) log('An error ocurred in datastore update: '..trace(err)) end +local function update_error(err) log('An error occurred in datastore update: '..trace(err)) end --[[-- Use a function to update the value locally, will trigger on_update then on_save, save_to_disk and auto_save is required for on_save @tparam any key The key that you want to apply the update to, must be a string unless a serializer is set @tparam function callback The function that will be used to update the value at this key