mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-06 00:23:49 +02:00
513 lines
13 KiB
Lua
513 lines
13 KiB
Lua
-- created by Gerkiz
|
|
|
|
local Global = require 'utils.global'
|
|
local Color = require 'utils.color_presets'
|
|
local SpamProtection = require 'utils.spam_protection'
|
|
local Event = require 'utils.event'
|
|
local Gui = require 'utils.gui'
|
|
local Commands = require 'utils.commands'
|
|
|
|
local this = {
|
|
data = {},
|
|
module_disabled = false
|
|
}
|
|
local Public = {}
|
|
|
|
Global.register(
|
|
this,
|
|
function (tbl)
|
|
this = tbl
|
|
end
|
|
)
|
|
|
|
local main_frame_name = Gui.uid_name()
|
|
|
|
local space = {
|
|
minimal_height = 10,
|
|
top_padding = 0,
|
|
bottom_padding = 0
|
|
}
|
|
|
|
local function get_player_data(player, remove)
|
|
local data = this.data[player.index]
|
|
if remove and data then
|
|
if data and data.frame and data.frame.valid then
|
|
data.frame.destroy()
|
|
end
|
|
|
|
this.data[player.index] = nil
|
|
return
|
|
end
|
|
|
|
if not this.data[player.index] then
|
|
this.data[player.index] = {}
|
|
end
|
|
|
|
return this.data[player.index]
|
|
end
|
|
|
|
local function unpack_inventory(inventory)
|
|
if not inventory then
|
|
return
|
|
end
|
|
local unpacked = {}
|
|
for i = 1, #inventory do
|
|
unpacked[i] = inventory[i]
|
|
end
|
|
return unpacked
|
|
end
|
|
|
|
local function add_style(guiIn, styleIn)
|
|
for k, v in pairs(styleIn) do
|
|
guiIn.style[k] = v
|
|
end
|
|
end
|
|
|
|
local function adjust_space(guiIn)
|
|
add_style(guiIn.add { type = 'line', direction = 'horizontal' }, space)
|
|
end
|
|
|
|
local function is_valid(obj)
|
|
if not obj then
|
|
return false
|
|
end
|
|
if not obj.valid then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function get_target_player(index)
|
|
local viewingPlayer = game.get_player(index)
|
|
if not viewingPlayer or not viewingPlayer.valid then
|
|
return false
|
|
end
|
|
return viewingPlayer
|
|
end
|
|
|
|
local function watching_inventory(player)
|
|
for index, data in pairs(this.data) do
|
|
if data and data.player_opened == player.index then
|
|
local source_player = game.get_player(index)
|
|
if not source_player or not source_player.valid then
|
|
return false
|
|
else
|
|
return source_player, data
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function player_opened(player)
|
|
local data = get_player_data(player)
|
|
|
|
if not data then
|
|
return false
|
|
end
|
|
|
|
local opened = data.player_opened
|
|
|
|
if not opened then
|
|
return false
|
|
end
|
|
|
|
return true, opened
|
|
end
|
|
|
|
local function validate_player(player)
|
|
if not player then
|
|
return false
|
|
end
|
|
if not player.valid then
|
|
return false
|
|
end
|
|
if not player.character then
|
|
return false
|
|
end
|
|
if not player.connected then
|
|
return false
|
|
end
|
|
if not game.get_player(player.index) then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function close_player_inventory(player)
|
|
local data = get_player_data(player)
|
|
|
|
if not data then
|
|
return
|
|
end
|
|
|
|
local gui = player.gui.screen
|
|
|
|
if not is_valid(gui) then
|
|
return
|
|
end
|
|
|
|
local element = gui[main_frame_name]
|
|
|
|
if not is_valid(element) then
|
|
return
|
|
end
|
|
|
|
element.destroy()
|
|
get_player_data(player, true)
|
|
end
|
|
|
|
local function get_inventory_type(player, inventory_type)
|
|
local target_types = {
|
|
['Main'] = function ()
|
|
return unpack_inventory(player.get_main_inventory())
|
|
end,
|
|
['Armor'] = function ()
|
|
return unpack_inventory(player.get_inventory(defines.inventory.character_armor))
|
|
end,
|
|
['Guns'] = function ()
|
|
return unpack_inventory(player.get_inventory(defines.inventory.character_guns))
|
|
end,
|
|
['Ammo'] = function ()
|
|
return unpack_inventory(player.get_inventory(defines.inventory.character_ammo))
|
|
end,
|
|
['Trash'] = function ()
|
|
return unpack_inventory(player.get_inventory(defines.inventory.character_trash))
|
|
end
|
|
}
|
|
return target_types[inventory_type]()
|
|
end
|
|
|
|
local function redraw_inventory(gui, source, target, caption, panel_type)
|
|
gui.clear()
|
|
|
|
local items_table = gui.add({ type = 'table', column_count = 11 })
|
|
local types = prototypes.item
|
|
|
|
local screen = source.gui.screen
|
|
|
|
if not is_valid(screen) then
|
|
return
|
|
end
|
|
|
|
local inventory_gui = screen[main_frame_name]
|
|
inventory_gui.caption = 'Inventory of ' .. target.name
|
|
|
|
for i = 1, #panel_type do
|
|
if panel_type[i] and panel_type[i].valid_for_read then
|
|
local name = panel_type[i].name
|
|
local count = panel_type[i].count
|
|
local flow = items_table.add({ type = 'flow' })
|
|
flow.style.vertical_align = 'bottom'
|
|
|
|
local button =
|
|
flow.add(
|
|
{
|
|
type = 'sprite-button',
|
|
sprite = 'item/' .. name,
|
|
number = count,
|
|
name = name,
|
|
tooltip = types[name].localised_name,
|
|
style = 'slot_button'
|
|
}
|
|
)
|
|
button.enabled = false
|
|
|
|
if caption == 'Armor' then
|
|
if target.get_inventory(5)[1].grid then
|
|
local p_armor = target.get_inventory(5)[1].grid.get_contents()
|
|
for k, v in pairs(p_armor) do
|
|
local armor_gui =
|
|
flow.add(
|
|
{
|
|
type = 'sprite-button',
|
|
sprite = 'item/' .. k,
|
|
number = v,
|
|
name = k,
|
|
tooltip = types[name].localised_name,
|
|
style = 'slot_button'
|
|
}
|
|
)
|
|
armor_gui.enabled = false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function add_inventory(panel, source, target, caption, panel_type)
|
|
local data = get_player_data(source)
|
|
data.panel_type = data.panel_type or {}
|
|
local pane_name = panel.add({ type = 'tab', caption = caption, name = caption })
|
|
local scroll_pane =
|
|
panel.add {
|
|
type = 'scroll-pane',
|
|
name = caption .. 'tab',
|
|
direction = 'vertical',
|
|
vertical_scroll_policy = 'always',
|
|
horizontal_scroll_policy = 'never'
|
|
}
|
|
scroll_pane.style.maximal_height = 200
|
|
scroll_pane.style.horizontally_stretchable = true
|
|
scroll_pane.style.minimal_height = 200
|
|
scroll_pane.style.right_padding = 0
|
|
panel.add_tab(pane_name, scroll_pane)
|
|
|
|
data.panel_type[caption] = panel_type
|
|
|
|
redraw_inventory(scroll_pane, source, target, caption, panel_type)
|
|
end
|
|
|
|
local function open_inventory(source, target)
|
|
if not validate_player(source) then
|
|
return
|
|
end
|
|
source.opened = nil
|
|
|
|
if not validate_player(target) then
|
|
return
|
|
end
|
|
|
|
local screen = source.gui.screen
|
|
|
|
if not is_valid(screen) then
|
|
return
|
|
end
|
|
|
|
local inventory_gui = screen[main_frame_name]
|
|
if inventory_gui then
|
|
close_player_inventory(source)
|
|
end
|
|
|
|
local frame =
|
|
screen.add(
|
|
{
|
|
type = 'frame',
|
|
caption = 'Inventory',
|
|
direction = 'vertical',
|
|
name = main_frame_name
|
|
}
|
|
)
|
|
|
|
if not (frame and frame.valid) then
|
|
return
|
|
end
|
|
|
|
frame.auto_center = true
|
|
frame.style.minimal_width = 500
|
|
frame.style.minimal_height = 250
|
|
|
|
adjust_space(frame)
|
|
|
|
local panel = frame.add({ type = 'tabbed-pane', name = 'tabbed_pane' })
|
|
panel.selected_tab_index = 1
|
|
|
|
local data = get_player_data(source)
|
|
|
|
data.player_opened = target.index
|
|
data.last_tab = 'Main'
|
|
|
|
local main = unpack_inventory(target.get_main_inventory())
|
|
if not main then
|
|
return
|
|
end
|
|
|
|
local armor = unpack_inventory(target.get_inventory(defines.inventory.character_armor))
|
|
local guns = unpack_inventory(target.get_inventory(defines.inventory.character_guns))
|
|
local ammo = unpack_inventory(target.get_inventory(defines.inventory.character_ammo))
|
|
local trash = unpack_inventory(target.get_inventory(defines.inventory.character_trash))
|
|
|
|
local types = {
|
|
['Main'] = main,
|
|
['Armor'] = armor,
|
|
['Guns'] = guns,
|
|
['Ammo'] = ammo,
|
|
['Trash'] = trash
|
|
}
|
|
|
|
for frame_name, callback in pairs(types) do
|
|
if callback ~= nil then
|
|
add_inventory(panel, source, target, frame_name, callback)
|
|
end
|
|
end
|
|
source.opened = frame
|
|
end
|
|
|
|
local function on_gui_click(event)
|
|
local player = game.get_player(event.player_index)
|
|
if not this.data[player.index] then
|
|
return
|
|
end
|
|
|
|
local element = event.element
|
|
|
|
if not element or not element.valid then
|
|
return
|
|
end
|
|
|
|
local types = {
|
|
['Main'] = true,
|
|
['Armor'] = true,
|
|
['Guns'] = true,
|
|
['Ammo'] = true,
|
|
['Trash'] = true
|
|
}
|
|
|
|
local name = element.name
|
|
|
|
if not types[name] then
|
|
return
|
|
end
|
|
|
|
local is_spamming = SpamProtection.is_spamming(player, nil, 'Player Inventory')
|
|
if is_spamming then
|
|
return
|
|
end
|
|
|
|
local data = get_player_data(player)
|
|
if not data then
|
|
return
|
|
end
|
|
|
|
data.last_tab = name
|
|
|
|
local valid, target = player_opened(player)
|
|
if valid and target then
|
|
local viewingPlayer = get_target_player(target)
|
|
if not viewingPlayer then
|
|
return false
|
|
end
|
|
|
|
local frame = Public.get_active_frame(player)
|
|
|
|
if frame then
|
|
local callback = get_inventory_type(viewingPlayer, name)
|
|
redraw_inventory(frame, player, viewingPlayer, name, callback)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function on_pre_player_left_game(event)
|
|
local player = game.get_player(event.player_index)
|
|
if not this.data[player.index] then
|
|
return
|
|
end
|
|
|
|
close_player_inventory(player)
|
|
end
|
|
|
|
local function update_gui(event)
|
|
local player = game.get_player(event.player_index)
|
|
if not player or not player.valid then
|
|
return
|
|
end
|
|
|
|
local source_player, source_data = watching_inventory(player)
|
|
if not source_player then
|
|
return
|
|
end
|
|
|
|
local frame = Public.get_active_frame(source_player)
|
|
if frame and frame.valid then
|
|
local callback = get_inventory_type(player, source_data.last_tab)
|
|
if frame.name == source_data.last_tab .. 'tab' then
|
|
redraw_inventory(frame, source_player, player, source_data.last_tab, callback)
|
|
end
|
|
end
|
|
end
|
|
|
|
Commands.new('inventory', 'Open another players inventory')
|
|
:add_parameter('player', false, 'player-online')
|
|
:callback(
|
|
function (player, target)
|
|
if this.module_disabled then
|
|
return false
|
|
end
|
|
|
|
if target and target.valid then
|
|
local valid, opened = player_opened(player)
|
|
if valid then
|
|
if target.index == opened then
|
|
player.print('You are already viewing this players inventory.', Color.warning)
|
|
return false
|
|
end
|
|
end
|
|
|
|
open_inventory(player, target)
|
|
else
|
|
player.print('[Inventory] Please type a name of a player who is connected.', Color.warning)
|
|
end
|
|
end
|
|
)
|
|
|
|
function Public.show_inventory(player, target_player)
|
|
if not player or not player.valid then
|
|
return false
|
|
end
|
|
if not target_player or not target_player.valid then
|
|
return false
|
|
end
|
|
|
|
local valid, opened = player_opened(player)
|
|
if valid then
|
|
if target_player.index == opened then
|
|
player.print('You are already viewing this players inventory.', Color.warning)
|
|
return false
|
|
end
|
|
end
|
|
|
|
if validate_player(target_player) then
|
|
open_inventory(player, target_player)
|
|
return true
|
|
else
|
|
player.print('[Inventory] Please type a name of a player who is connected.', Color.warning)
|
|
return false
|
|
end
|
|
end
|
|
|
|
function Public.get_active_frame(player)
|
|
if not player.gui.screen[main_frame_name] then
|
|
return false
|
|
end
|
|
return player.gui.screen[main_frame_name].tabbed_pane.tabs[player.gui.screen[main_frame_name].tabbed_pane.selected_tab_index].content
|
|
end
|
|
|
|
function Public.get(key)
|
|
if key then
|
|
return this[key]
|
|
else
|
|
return this
|
|
end
|
|
end
|
|
|
|
--- Disables the module.
|
|
---@param state boolean
|
|
function Public.module_disabled(state)
|
|
this.module_disabled = state or false
|
|
end
|
|
|
|
Gui.on_custom_close(
|
|
main_frame_name,
|
|
function (event)
|
|
local player = game.get_player(event.player_index)
|
|
if not this.data[player.index] then
|
|
return
|
|
end
|
|
|
|
close_player_inventory(player)
|
|
end
|
|
)
|
|
|
|
Event.add(defines.events.on_player_main_inventory_changed, update_gui)
|
|
Event.add(defines.events.on_player_gun_inventory_changed, update_gui)
|
|
Event.add(defines.events.on_player_ammo_inventory_changed, update_gui)
|
|
Event.add(defines.events.on_player_armor_inventory_changed, update_gui)
|
|
Event.add(defines.events.on_player_trash_inventory_changed, update_gui)
|
|
Event.add(defines.events.on_gui_click, on_gui_click)
|
|
Event.add(defines.events.on_pre_player_left_game, on_pre_player_left_game)
|
|
|
|
Public.close_player_inventory = close_player_inventory
|
|
|
|
return Public
|