Merge branch 'dev' into feature/entity-alert

This commit is contained in:
Cooldude2606
2021-04-26 00:21:48 +01:00
committed by GitHub
127 changed files with 4579 additions and 629 deletions

View File

@@ -0,0 +1,88 @@
--[[-- 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, 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 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
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 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
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)

View File

@@ -9,6 +9,15 @@ local Reports = require 'modules.control.reports' --- @dep modules.control.repor
local format_chat_player_name = _C.format_chat_player_name--- @dep expcore.common
require 'config.expcore.command_general_parse'
--- Print a message to all players who match the value of admin
local function print_to_players(admin, message)
for _, player in ipairs(game.connected_players) do
if player.admin == admin then
player.print(message)
end
end
end
--- Reports a player and notifies moderators
-- @command report
-- @tparam LuaPlayer player the player to report, some players are immune
@@ -19,6 +28,8 @@ Commands.new_command('report', 'Reports a player and notifies moderators')
if not input then return end
if Roles.player_has_flag(input, 'report-immune') then
return reject{'expcom-report.player-immune'}
elseif player == input then
return reject{'expcom-report.self-report'}
else
return input
end
@@ -30,8 +41,8 @@ end)
local action_player_name_color = format_chat_player_name(action_player)
local by_player_name_color = format_chat_player_name(player)
if Reports.report_player(action_player, player.name, reason) then
game.print{'expcom-report.non-admin', action_player_name_color, reason}
Roles.print_to_roles_higher('Trainee', {'expcom-report.admin', action_player_name_color, by_player_name_color, reason})
print_to_players(false, {'expcom-report.non-admin', action_player_name_color, reason})
print_to_players(true, {'expcom-report.admin', action_player_name_color, by_player_name_color, reason})
else
return Commands.error{'expcom-report.already-reported'}
end

167
modules/commands/search.lua Normal file
View File

@@ -0,0 +1,167 @@
--[[-- Commands Module - Inventory Search
- Adds commands that will search all players inventories for an item
@commands InventorySearch
]]
local Commands = require 'expcore.commands' --- @dep expcore.commands
local format_number = require('util').format_number --- @dep util
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common
local format_time = _C.format_time
require 'config.expcore.command_general_parse'
--- Input parse for items by name
local function item_parse(input, _, reject)
if input == nil then return end
local lower_input = input:lower():gsub(' ', '-')
-- Simple Case - internal name is given
local item = game.item_prototypes[lower_input]
if item then return item end
-- Second Case - rich text is given
local item_name = input:match('%[item=([0-9a-z-]+)%]')
item = game.item_prototypes[item_name]
if item then return item end
-- No item found, we do not attempt to search all prototypes as this will be expensive
return reject{'expcom-inv-search.reject-item', lower_input}
end
--- Search all players for this item
local function search_players(players, item)
local head = 1
local found = {}
-- Check the item count of all players
for _, player in pairs(players) do
local item_count = player.get_item_count(item.name)
if item_count > 0 then
-- Add the player to the array as they have the item
found[head] = { player=player, count=item_count, online_time=player.online_time }
head = head + 1
end
end
return found
end
--- Custom sort function which only retains 5 greatest values
local function sort_players(players, func)
local sorted = {}
local values = {}
local threshold = nil
-- Loop over all provided players
for index, player in ipairs(players) do
local value = func(player)
-- Check if the item will make the top 5 elements
if value > threshold or index <= 5 then
local inserted = false
values[player] = value
-- Find where in the top 5 to insert the element
for next_index, next_player in ipairs(sorted) do
if value > values[next_player] then
table.insert(sorted, next_index, player)
inserted = true
break
end
end
-- Insert the element, this can only be called when index <= 5
if not inserted then
sorted[#sorted+1] = player
end
-- Update the threshold
if sorted[6] then
threshold = values[sorted[5]]
values[sorted[6]] = nil
sorted[6] = nil
else
threshold = values[sorted[#sorted]]
end
end
end
return sorted
end
--- Display to the player the top players which were found
local function display_players(player, players, item)
player.print{'expcom-inv-search.results-heading', item.name}
for index, data in ipairs(players) do
local player_name_color = format_chat_player_name(data.player)
local amount = format_number(data.count)
local time = format_time(data.online_time)
player.print{'expcom-inv-search.results-item', index, player_name_color, amount, time}
end
end
--- Return the amount of an item a player has
local function amount_sort(data)
return data.count
end
--- Get a list of players sorted by the quantity of an item in their inventory
-- @command search-amount
-- @tparam LuaItemPrototype item The item to search for in players inventories
Commands.new_command('search-amount', 'Display players sorted by the quantity of an item held')
:add_alias('ia')
:add_param('item', false, item_parse)
:enable_auto_concat()
:register(function(player, item)
local players = search_players(game.players, item)
if #players == 0 then return {'expcom-inv-search.results-none', item.name} end
local top_players = sort_players(players, amount_sort)
display_players(player, top_players, item)
end)
--- Return the index of the player, higher means they joined more recently
local function recent_sort(data)
return data.player.index
end
--- Get a list of players who have the given item, sorted by how recently they joined
-- @command search-recent
-- @tparam LuaItemPrototype item The item to search for in players inventories
Commands.new_command('search-recent', 'Display players who hold an item sorted by join time')
:add_alias('ir')
:add_param('item', false, item_parse)
:enable_auto_concat()
:register(function(player, item)
local players = search_players(game.players, item)
if #players == 0 then return {'expcom-inv-search.results-none', item.name} end
local top_players = sort_players(players, recent_sort)
display_players(player, top_players, item)
end)
--- Return the the amount of an item a player has divided by their playtime
local function combined_sort(data)
return data.count/data.online_time
end
--- Get a list of players sorted by quantity held and play time
-- @command search
-- @tparam LuaItemPrototype item The item to search for in players inventories
Commands.new_command('search', 'Display players sorted by the quantity of an item held and playtime')
:add_alias('i')
:add_param('item', false, item_parse)
:enable_auto_concat()
:register(function(player, item)
local players = search_players(game.players, item)
if #players == 0 then return {'expcom-inv-search.results-none', item.name} end
local top_players = sort_players(players, combined_sort)
display_players(player, top_players, item)
end)
--- Get a list of online players sorted by quantity held and play time
-- @command search-online
-- @tparam LuaItemPrototype item The item to search for in players inventories
Commands.new_command('search-online', 'Display online players sorted by the quantity of an item held and playtime')
:add_alias('io')
:add_param('item', false, item_parse)
:enable_auto_concat()
:register(function(player, item)
local players = search_players(game.connected_players, item)
if #players == 0 then return {'expcom-inv-search.results-none', item.name} end
local top_players = sort_players(players, combined_sort)
display_players(player, top_players, item)
end)

View File

@@ -0,0 +1,33 @@
--[[-- Commands Module - Spectate
- Adds 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)