Added renderer and selection events

This commit is contained in:
Cooldude2606
2021-04-24 21:05:34 +01:00
parent d83f1e3aea
commit 43d5ff7741
3 changed files with 160 additions and 8 deletions

View File

@@ -3,13 +3,24 @@
@commands Protection @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 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 EntityProtection = require 'modules.control.protection' --- @dep modules.control.protection
local Selection = require 'modules.control.selection' --- @dep modules.control.selection local Selection = require 'modules.control.selection' --- @dep modules.control.selection
local SelectionProtectEntity = 'ProtectEntity' local SelectionProtectEntity = 'ProtectEntity'
local SelectionProtectArea = 'ProtectArea' 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 --- Test if a point is inside an aabb
local function aabb_point_enclosed(point, aabb) local function aabb_point_enclosed(point, aabb)
return point.x >= aabb.left_top.x and point.y >= aabb.left_top.y 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 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 --- Toggles entity protection selection
-- @command protect-entity -- @command protect-entity
Commands.new_command('protect-entity', 'Toggles entity protection selection, hold shift to remove protection') 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 --- When an area is selected to add protection to entities
Selection.on_selection(SelectionProtectEntity, function(event) Selection.on_selection(SelectionProtectEntity, function(event)
local player = game.get_player(event.player_index)
for _, entity in ipairs(event.entities) do for _, entity in ipairs(event.entities) do
EntityProtection.add_entity(entity) EntityProtection.add_entity(entity)
show_protected_entity(player, entity)
end end
return Commands.success{'expcom-protection.protected-entities', #event.entities} return Commands.success{'expcom-protection.protected-entities', #event.entities}
end) end)
--- When an area is selected to remove protection from entities --- When an area is selected to remove protection from entities
Selection.on_alt_selection(SelectionProtectEntity, function(event) Selection.on_alt_selection(SelectionProtectEntity, function(event)
local player = game.get_player(event.player_index)
for _, entity in ipairs(event.entities) do for _, entity in ipairs(event.entities) do
EntityProtection.remove_entity(entity) EntityProtection.remove_entity(entity)
remove_render(player, get_entity_key(entity))
end end
return Commands.success{'expcom-protection.unprotected-entities', #event.entities} return Commands.success{'expcom-protection.unprotected-entities', #event.entities}
end) end)
@@ -81,7 +148,9 @@ Selection.on_selection(SelectionProtectArea, function(event)
return Commands.error{'expcom-protection.already-protected'} return Commands.error{'expcom-protection.already-protected'}
end end
end end
local player = game.get_player(event.player_index)
EntityProtection.add_area(event.surface, area) EntityProtection.add_area(event.surface, area)
show_protected_area(player, event.surface, area)
return Commands.success{'expcom-protection.protected-area'} return Commands.success{'expcom-protection.protected-area'}
end) end)
@@ -89,14 +158,55 @@ end)
Selection.on_alt_selection(SelectionProtectArea, function(event) Selection.on_alt_selection(SelectionProtectArea, function(event)
local area = aabb_align_expand(event.area) local area = aabb_align_expand(event.area)
local areas = EntityProtection.get_areas(event.surface) local areas = EntityProtection.get_areas(event.surface)
local player = game.get_player(event.player_index)
for _, next_area in pairs(areas) do for _, next_area in pairs(areas) do
if aabb_area_enclosed(next_area, area) then if aabb_area_enclosed(next_area, area) then
EntityProtection.remove_area(event.surface, next_area) EntityProtection.remove_area(event.surface, next_area)
Commands.print{'expcom-protection.unprotected-area'} Commands.print{'expcom-protection.unprotected-area'}
remove_render(player, get_area_key(next_area))
end end
end 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 --- When there is a repeat offence print it in chat
Event.add(EntityProtection.events.on_repeat_violation, function(event) Event.add(EntityProtection.events.on_repeat_violation, function(event)
local player_name = format_chat_player_name(event.player_index) local player_name = format_chat_player_name(event.player_index)

View File

@@ -8,6 +8,8 @@ local Global = require 'utils.global' --- @dep utils.global
local Event = require 'utils.event' --- @dep utils.event local Event = require 'utils.event' --- @dep utils.event
local config = require 'config.protection' --- @dep config.protection local config = require 'config.protection' --- @dep config.protection
local EntityProtection = { local EntityProtection = {
protected_entity_names = table.deep_copy(config.always_protected_names),
protected_entity_types = table.deep_copy(config.always_protected_types),
events = { events = {
--- When a player mines a protected entity --- When a player mines a protected entity
-- @event on_player_mined_protected -- @event on_player_mined_protected
@@ -59,12 +61,12 @@ end)
--- Get the key used in protected_entities --- Get the key used in protected_entities
local function get_entity_key(entity) 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 end
--- Get the key used in protected_areas --- Get the key used in protected_areas
local function get_area_key(area) 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 end
--- Check if an entity is always protected --- Check if an entity is always protected
@@ -99,7 +101,7 @@ end
--- Get all protected entities on a surface --- Get all protected entities on a surface
function EntityProtection.get_entities(surface) function EntityProtection.get_entities(surface)
return protected_entities[surface.index] return protected_entities[surface.index] or {}
end end
--- Check if an entity is protected --- Check if an entity is protected
@@ -129,7 +131,7 @@ end
--- Get all protected areas on a surface --- Get all protected areas on a surface
function EntityProtection.get_areas(surface) function EntityProtection.get_areas(surface)
return protected_areas[surface.index] return protected_areas[surface.index] or {}
end end
--- Check if an entity is protected --- Check if an entity is protected

View File

@@ -6,7 +6,20 @@
local Event = require 'utils.event' --- @dep utils.event local Event = require 'utils.event' --- @dep utils.event
local Global = require 'utils.global' --- @dep utils.global 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' } 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 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 -- @tparam[opt=false] boolean single_use When true the selection will stop after first use
function Selection.start(player, selection_name, single_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 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] = { selections[player.index] = {
name = selection_name, name = selection_name,
arguments = { ... }, arguments = { ... },
@@ -31,6 +54,14 @@ function Selection.start(player, selection_name, single_use, ...)
character = player.character 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 -- Give a selection tool if one is not in use
if player.cursor_stack.is_selection_tool then return end if player.cursor_stack.is_selection_tool then return end
player.clear_cursor() -- Clear the current item player.clear_cursor() -- Clear the current item
@@ -47,8 +78,17 @@ end
function Selection.stop(player) function Selection.stop(player)
if not selections[player.index] then return end if not selections[player.index] then return end
local character = selections[player.index].character local character = selections[player.index].character
local selection = selections[player.index].name
selections[player.index] = nil 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 -- Remove the selection tool
if player.cursor_stack.is_selection_tool then if player.cursor_stack.is_selection_tool then
player.cursor_stack.clear() player.cursor_stack.clear()
@@ -78,8 +118,8 @@ function Selection.is_selecting(player, selection_name)
if not selections[player.index] then return false end if not selections[player.index] then return false end
return selections[player.index].name == selection_name return selections[player.index].name == selection_name
else else
return player.cursor_stack.is_selection_tool return player.cursor_stack.is_selection_tool
end end
end end
--- Filter on_player_selected_area to this custom selection, appends the selection arguments --- Filter on_player_selected_area to this custom selection, appends the selection arguments