1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-06 00:23:49 +02:00
ComfyFactorio/utils/gui/group.lua
Gerkiz e91b6a352f 2.0 changes
Change global -> storage
Rework how rendering works
Game prototypes are now stored inside 'prototypes.#'
Renamed entity names
2024-10-22 21:47:11 +02:00

429 lines
16 KiB
Lua

-- this script adds a group button to create groups for your players --
local Gui = require 'utils.gui'
local Global = require 'utils.global'
local SpamProtection = require 'utils.spam_protection'
local Event = require 'utils.event'
local Token = require 'utils.token'
local Color = require 'utils.color_presets'
local module_name = Gui.uid_name()
local this = {
player_group = {},
join_spam_protection = {},
tag_groups = {
['Miner'] = { name = 'Miner', founder = 'script', description = '[img=item/electric-mining-drill]', static = true },
['Smeltery'] = { name = 'Smeltery', founder = 'script', description = '[img=item/stone-furnace]', static = true },
['Power'] = { name = 'Power', founder = 'script', description = '[img=item/big-electric-pole]', static = true },
['Production'] = { name = 'Production', founder = 'script', description = '[img=item/assembling-machine-1]', static = true },
['Science'] = { name = 'Science', founder = 'script', description = '[img=item/chemical-science-pack]', static = true },
['Trainman'] = { name = 'Trainman', founder = 'script', description = '[img=item/locomotive]', static = true },
['Oil processing'] = { name = 'Oil Processing', founder = 'script', description = '[img=fluid/crude-oil]', static = true },
['Trooper'] = { name = 'Trooper', founder = 'script', description = '[img=item/submachine-gun]', static = true },
['Fortifications'] = { name = 'Fortifications', founder = 'script', description = '[img=item/stone-wall]', static = true },
['Support'] = { name = 'Support', founder = 'script', description = '[img=item/repair-pack]', static = true }
},
alphanumeric = true
}
Global.register(
this,
function (t)
this = t
end
)
local Public = {}
local function build_group_gui(data)
local player = data.player
local frame = data.frame
local group_name_width = 150
local description_width = 240
local members_width = 90
local member_columns = 2
local actions_width = 130
local total_height = (frame.style.minimal_height or 500) - 60
frame.clear()
local t = frame.add({ type = 'table', column_count = 5 })
local headings = {
{ { 'gui.title' }, group_name_width },
{ { 'gui.description' }, description_width },
{ { 'gui.members' }, members_width * member_columns },
{ '', actions_width }
}
for _, h in pairs(headings) do
local l = t.add({ type = 'label', caption = h[1] })
l.style.font_color = { r = 0.98, g = 0.66, b = 0.22 }
l.style.font = 'heading-2'
l.style.top_padding = 6
l.style.minimal_height = 40
l.style.minimal_width = h[2]
l.style.maximal_width = h[2]
l.style.horizontal_align = 'center'
end
local scroll_pane =
frame.add(
{
type = 'scroll-pane',
name = 'scroll_pane',
direction = 'vertical',
horizontal_scroll_policy = 'never',
vertical_scroll_policy = 'auto'
}
)
scroll_pane.style.maximal_height = total_height - 50
scroll_pane.style.minimal_height = total_height - 50
t = scroll_pane.add({ type = 'table', name = 'groups_table', column_count = 4 })
for _, h in pairs(headings) do
local l = t.add({ type = 'label', caption = '' })
l.style.minimal_width = h[2]
l.style.maximal_width = h[2]
end
for _, group in pairs(this.tag_groups) do
if (group.name and group.founder and group.description) then
local l = t.add({ type = 'label', caption = group.name })
l.style.top_padding = 16
l.style.bottom_padding = 16
l.style.minimal_width = group_name_width
l.style.maximal_width = group_name_width
l.style.font = 'default-semibold'
l.style.horizontal_align = 'center'
local color
if game.players[group.founder] and game.players[group.founder].color then
color = game.players[group.founder].color
else
color = { r = 0.90, g = 0.90, b = 0.90 }
end
color = { r = color.r * 0.6 + 0.4, g = color.g * 0.6 + 0.4, b = color.b * 0.6 + 0.4, a = 1 }
l.style.font_color = color
l.style.single_line = false
l = t.add({ type = 'label', caption = group.description })
l.style.top_padding = 16
l.style.bottom_padding = 16
l.style.minimal_width = description_width
l.style.maximal_width = description_width
l.style.font_color = { r = 0.90, g = 0.90, b = 0.90 }
l.style.single_line = false
l.style.font = 'default-semibold'
l.style.horizontal_align = 'center'
local tt = t.add({ type = 'table', column_count = 2 })
local flow = tt.add({ type = 'flow' })
flow.style.left_padding = 65
local ttt = tt.add({ type = 'table', column_count = member_columns })
ttt.style.minimal_width = members_width * 2 - 25
for _, p in pairs(game.connected_players) do
if group.name == this.player_group[p.name] then
l = ttt.add({ type = 'label', caption = p.name })
color = {
r = p.color.r * 0.6 + 0.4,
g = p.color.g * 0.6 + 0.4,
b = p.color.b * 0.6 + 0.4,
a = 1
}
l.style.font_color = color
l.style.maximal_width = members_width * 2 - 60
l.style.single_line = false
l.style.font = 'default-semibold'
l.style.horizontal_align = 'center'
end
end
tt = t.add({ type = 'table', name = group.name, column_count = 1 })
if group.name ~= this.player_group[player.name] then
local b = tt.add({ type = 'button', caption = { 'gui.join' } })
b.style.font = 'default-bold'
b.style.minimal_width = actions_width
b.style.maximal_width = actions_width
else
local b = tt.add({ type = 'button', caption = { 'gui.leave' } })
b.style.font = 'default-bold'
b.style.minimal_width = actions_width
b.style.maximal_width = actions_width
end
if (player.admin == true or group.founder == player.name) and not group.static then
local b = tt.add({ type = 'button', caption = { 'gui.delete' } })
b.style.font = 'default-bold'
b.style.minimal_width = actions_width
b.style.maximal_width = actions_width
else
local b = tt.add({ type = 'button', caption = { 'gui.delete' } })
b.enabled = false
b.style.font = 'default-bold'
b.style.minimal_width = actions_width
b.style.maximal_width = actions_width
end
tt.add { type = 'line' }
end
end
local frame2 = frame.add({ type = 'frame', name = 'frame2' })
t = frame2.add({ type = 'table', name = 'group_table', column_count = 4 })
local textfield = t.add({ type = 'textfield', name = 'new_group_name', text = 'Name' })
textfield.style.minimal_width = 200
textfield = t.add({ type = 'textfield', name = 'new_group_description', text = 'Description' })
textfield.style.minimal_width = 400
local b = t.add({ type = 'button', name = 'create_new_group', caption = { 'gui.create' } })
b.style.minimal_width = 150
b.style.font = 'default-bold'
end
local build_group_gui_token = Token.register(build_group_gui)
local function refresh_gui()
local players = game.connected_players
for i = 1, #players do
local player = players[i]
local frame = Gui.get_player_active_frame(player)
if frame then
if frame.frame2 and frame.frame2.valid then
local new_group_name = frame.frame2.group_table.new_group_name.text
local new_group_description = frame.frame2.group_table.new_group_description.text
if new_group_name:len() > 30 then
new_group_name = ''
end
if new_group_description:len() > 60 then
new_group_description = ''
end
local data = { player = player, frame = frame }
build_group_gui(data)
frame = Gui.get_player_active_frame(player)
frame.frame2.group_table.new_group_name.text = new_group_name
frame.frame2.group_table.new_group_description.text = new_group_description
end
end
end
end
local function on_player_joined_game(event)
local player = game.players[event.player_index]
if not this.player_group[player.name] then
this.player_group[player.name] = '[Group]'
end
if not this.join_spam_protection[player.name] then
this.join_spam_protection[player.name] = game.tick
end
end
local function on_gui_text_changed(event)
local element = event.element
if not element or not element.valid then
return
end
local player = game.get_player(event.player_index)
local name = element.name
local text = element.text
if name == 'new_group_name' then
local is_spamming = SpamProtection.is_spamming(player, nil, 'Groups new_group_name')
if is_spamming then
return
end
if text:len() > 30 then
element.text = ''
end
end
if name == 'new_group_description' then
local is_spamming = SpamProtection.is_spamming(player, nil, 'Groups new_group_desc')
if is_spamming then
return
end
if text:len() > 60 then
element.text = ''
end
end
end
local function alphanumeric(str)
return (string.match(str, '[^%w%s%p]') ~= nil)
end
local function on_gui_click(event)
local element = event.element
if not element or not element.valid then
return
end
local player = game.get_player(event.player_index)
local name = element.name
local frame = Gui.get_player_active_frame(player)
if not frame then
return
end
if frame.name ~= 'Groups' then
return
end
if name == 'create_new_group' then
local is_spamming = SpamProtection.is_spamming(player, nil, 'Group Click')
if is_spamming then
return
end
local new_group_name = frame.frame2.group_table.new_group_name.text
local new_group_description = frame.frame2.group_table.new_group_description.text
if new_group_name ~= '' and new_group_name ~= 'Name' and new_group_description ~= 'Description' then
if this.alphanumeric then
if alphanumeric(new_group_name) then
player.print('Group name is not valid.', { r = 0.90, g = 0.0, b = 0.0 })
return
end
if alphanumeric(new_group_description) then
player.print('Group description is not valid.', { r = 0.90, g = 0.0, b = 0.0 })
return
end
end
if string.len(new_group_name) > 64 then
player.print('Group name is too long. 64 characters maximum.', { r = 0.90, g = 0.0, b = 0.0 })
return
end
if string.len(new_group_description) > 128 then
player.print('Description is too long. 128 characters maximum.', { r = 0.90, g = 0.0, b = 0.0 })
return
end
this.tag_groups[new_group_name] = {
name = new_group_name,
description = new_group_description,
founder = player.name
}
local color = {
r = player.color.r * 0.7 + 0.3,
g = player.color.g * 0.7 + 0.3,
b = player.color.b * 0.7 + 0.3,
a = 1
}
game.print(player.name .. ' has founded a new group!', color)
game.print('>> ' .. new_group_name, { r = 0.98, g = 0.66, b = 0.22 })
game.print(new_group_description, { r = 0.85, g = 0.85, b = 0.85 })
frame.frame2.group_table.new_group_name.text = 'Name'
frame.frame2.group_table.new_group_description.text = 'Description'
refresh_gui()
return
end
end
local p = element.parent
if p then
p = p.parent
end
if p then
if p.name == 'groups_table' then
local is_spamming = SpamProtection.is_spamming(player, nil, 'Group Click')
if is_spamming then
return
end
local caption = element.caption and element.caption[1]
if element.type == 'button' and caption == 'gui.join' then
this.player_group[player.name] = element.parent.name
local str = '[' .. element.parent.name
str = str .. ']'
player.tag = str
if game.tick - this.join_spam_protection[player.name] > 600 then
local color = {
r = player.color.r * 0.7 + 0.3,
g = player.color.g * 0.7 + 0.3,
b = player.color.b * 0.7 + 0.3,
a = 1
}
game.print(player.name .. ' has joined group "' .. element.parent.name .. '"', color)
this.join_spam_protection[player.name] = game.tick
end
refresh_gui()
return
end
if element.type == 'button' and caption == 'gui.delete' then
if this.tag_groups[element.parent.name] and this.tag_groups[element.parent.name].static then
player.print('Static groups cannot be deleted.', Color.warning)
return
end
for _, players in pairs(game.players) do
if this.player_group[players.name] then
if this.player_group[players.name] == element.parent.name then
this.player_group[players.name] = '[Group]'
players.tag = ''
end
end
end
game.print(player.name .. ' deleted group "' .. element.parent.name .. '"')
this.tag_groups[element.parent.name] = nil
refresh_gui()
return
end
if element.type == 'button' and caption == 'gui.leave' then
this.player_group[player.name] = '[Group]'
player.tag = ''
refresh_gui()
return
end
end
end
end
function Public.alphanumeric_only(value)
if value then
this.alphanumeric = value
else
this.alphanumeric = false
end
end
function Public.reset_groups()
local players = game.connected_players
for i = 1, #players do
local player = players[i]
this.player_group[player.name] = '[Group]'
this.join_spam_protection[player.name] = game.tick
end
if this.tag_groups and next(this.tag_groups) then
for name, data in pairs(this.tag_groups) do
if not data.static then
this.tag_groups[name] = nil
end
end
end
end
Gui.add_tab_to_gui({ name = module_name, caption = 'Groups', id = build_group_gui_token, admin = false })
Gui.on_click(
module_name,
function (event)
local player = event.player
Gui.reload_active_tab(player)
end
)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_gui_text_changed, on_gui_text_changed)
return Public