mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
171 lines
6.7 KiB
Lua
171 lines
6.7 KiB
Lua
--[[-- Commands Module - Inventory Search
|
|
- Adds commands that will search all players inventories for an item
|
|
@commands InventorySearch
|
|
]]
|
|
|
|
local ExpUtil = require("modules/exp_util")
|
|
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
|
|
local format_number = require("util").format_number --- @dep util
|
|
local format_player_name = ExpUtil.format_player_name_locale
|
|
require("modules.exp_legacy.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 = prototypes.item[lower_input]
|
|
if item then return item end
|
|
|
|
-- Second Case - rich text is given
|
|
local item_name = input:match("%[item=([0-9a-z-]+)%]")
|
|
item = prototypes.item[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 index <= 5 or value > threshold 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
|
|
|
|
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
|
|
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_player_name(data.player)
|
|
local amount = format_number(data.count)
|
|
local time = display_players_time_format(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", { "expcom-inv-search.description-ia" }, "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", { "expcom-inv-search.description-ir" }, "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", { "expcom-inv-search.description-i" }, "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", { "expcom-inv-search.description-io" }, "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)
|