mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-06 00:23:49 +02:00
429 lines
16 KiB
Lua
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 = 'heading-3'
|
|
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 = 'heading-3'
|
|
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 = 'heading-3'
|
|
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
|