mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
182 lines
6.6 KiB
Lua
182 lines
6.6 KiB
Lua
--[[-- Commands - Inventory Search
|
|
Adds commands that will search all players inventories for an item
|
|
]]
|
|
|
|
local ExpUtil = require("modules/exp_util")
|
|
|
|
local Commands = require("modules/exp_commands")
|
|
local format_player_name = Commands.format_player_name_locale
|
|
|
|
local format_number = require("util").format_number
|
|
|
|
--- A player who is of a lower role than the executing player
|
|
--- @type Commands.InputParser
|
|
local function parse_item(input, player)
|
|
-- First Case - internal name is given
|
|
-- Second Case - rich text is given
|
|
local item_name = input:lower():gsub(" ", "-")
|
|
local item = prototypes.item[item_name] or prototypes.item[input:match("%[item=([0-9a-z-]+)%]")]
|
|
if item then
|
|
return Commands.status.success(item)
|
|
end
|
|
|
|
-- No item found, we do not attempt to search all prototypes as this will be expensive
|
|
return Commands.status.invalid_input{ "exp-commands_search.invalid-item", item_name }
|
|
end
|
|
|
|
--- @class SearchResult: { player: LuaPlayer, count: number, online_time: number }
|
|
|
|
--- Search all players for this item
|
|
--- @param players LuaPlayer[] Players to search
|
|
--- @param item LuaItemPrototype Item to find
|
|
--- @return SearchResult[]
|
|
local function search_players(players, item)
|
|
local found = {} --- @type SearchResult[]
|
|
local head = 1
|
|
|
|
-- 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
|
|
|
|
--- @alias SortFunction fun(result: SearchResult): number
|
|
|
|
--- Custom sort function which only retains 5 greatest values
|
|
--- @param results SearchResult[] Players to sort
|
|
--- @param func SortFunction Function to calculate value, higher better
|
|
--- @return SearchResult[] # Top 5 results
|
|
local function sort_results(results, func)
|
|
local sorted = {}
|
|
local values = {}
|
|
local threshold = 0
|
|
|
|
-- Loop over all provided players
|
|
for index, result in ipairs(results) do
|
|
local value = func(result)
|
|
-- Check if the item will make the top 5 elements
|
|
if index <= 5 or value > threshold then
|
|
local inserted = false
|
|
values[result] = value
|
|
|
|
-- Find where in the top 5 to insert the element
|
|
for next_index, next_result in ipairs(sorted) do
|
|
if value > values[next_result] then
|
|
table.insert(sorted, next_index, result)
|
|
inserted = true
|
|
break
|
|
end
|
|
end
|
|
|
|
-- Update the threshold, clean up the tables, and insert if needed
|
|
if sorted[6] then
|
|
threshold = values[sorted[5]]
|
|
values[sorted[6]] = nil
|
|
sorted[6] = nil
|
|
elseif not inserted then
|
|
-- index <= 5 so insert at the end
|
|
sorted[#sorted + 1] = result
|
|
threshold = value
|
|
end
|
|
end
|
|
end
|
|
|
|
return sorted
|
|
end
|
|
|
|
local display_players_time_format = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
|
|
|
|
--- Display to the player the top players which were found
|
|
--- @param results SearchResult[]
|
|
--- @param item LuaItemPrototype
|
|
--- @return LocalisedString
|
|
local function format_response(results, item)
|
|
if #results == 0 then
|
|
return { "exp-commands_search.no-results", item.name }
|
|
end
|
|
|
|
local response = { "", { "exp-commands_search.title", item.name } } --- @type LocalisedString
|
|
for index, data in ipairs(results) do
|
|
response[index + 2] = {
|
|
"exp-commands_search.result",
|
|
index,
|
|
format_player_name(data.player),
|
|
format_number(data.count, false),
|
|
display_players_time_format(data.online_time),
|
|
}
|
|
end
|
|
|
|
return response
|
|
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
|
|
Commands.new("search", { "exp-commands_search.description-search" })
|
|
:argument("item", { "exp-commands_search.arg-item" }, parse_item)
|
|
:enable_auto_concatenation()
|
|
:add_aliases{ "s" }
|
|
:register(function(player, item)
|
|
--- @cast item LuaItemPrototype
|
|
local results = search_players(game.players, item)
|
|
local sorted = sort_results(results, combined_sort)
|
|
return Commands.status.success(format_response(sorted, item))
|
|
end)
|
|
|
|
--- Get a list of online players sorted by quantity held and play time
|
|
Commands.new("search-online", { "exp-commands_search.description-online" })
|
|
:argument("item", { "exp-commands_search.arg-item" }, parse_item)
|
|
:enable_auto_concatenation()
|
|
:add_aliases{ "so" }
|
|
:register(function(player, item)
|
|
--- @cast item LuaItemPrototype
|
|
local results = search_players(game.connected_players, item)
|
|
local sorted = sort_results(results, combined_sort)
|
|
return Commands.status.success(format_response(sorted, item))
|
|
end)
|
|
|
|
--- Return the amount of an item a player has
|
|
--- @type SortFunction
|
|
local function sort_by_count(data)
|
|
return data.count
|
|
end
|
|
|
|
--- Get a list of players sorted by the quantity of an item in their inventory
|
|
Commands.new("search-amount", { "exp-commands_search.description-amount" })
|
|
:argument("item", { "exp-commands_search.arg-item" }, parse_item)
|
|
:enable_auto_concatenation()
|
|
:add_aliases{ "sa" } -- cant use /sc
|
|
:register(function(player, item)
|
|
--- @cast item LuaItemPrototype
|
|
local results = search_players(game.players, item)
|
|
local sorted = sort_results(results, sort_by_count)
|
|
return Commands.status.success(format_response(sorted, item))
|
|
end)
|
|
|
|
--- Return the index of the player, higher means they joined more recently
|
|
local function sort_by_recent(data)
|
|
return data.player.index
|
|
end
|
|
|
|
--- Get a list of players who have the given item, sorted by how recently they joined
|
|
Commands.new("search-recent", { "exp-commands_search.description-recent" })
|
|
:argument("item", { "exp-commands_search.arg-item" }, parse_item)
|
|
:enable_auto_concatenation()
|
|
:add_aliases{ "sr" } -- cant use /sc
|
|
:register(function(player, item)
|
|
--- @cast item LuaItemPrototype
|
|
local results = search_players(game.players, item)
|
|
local sorted = sort_results(results, sort_by_recent)
|
|
return Commands.status.success(format_response(sorted, item))
|
|
end)
|