mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-04 00:15:45 +02:00
705 lines
21 KiB
Lua
705 lines
21 KiB
Lua
--[[
|
|
Hello there!
|
|
|
|
This will add a player list with "ranks" to your server.
|
|
Oh.. and you can also "poke" a player.
|
|
pokemessages = 80% by redlabel
|
|
|
|
To install, add: require "player_list"
|
|
to your scenario control.lua.
|
|
|
|
---MewMew---
|
|
|
|
Minor changes by ~~~Gerkiz~~~
|
|
--]]
|
|
local Event = require 'utils.event'
|
|
local Session = require 'utils.session_data'
|
|
local Jailed = require 'utils.jail_data'
|
|
local Tabs = require 'comfy_panel.main'
|
|
local Global = require 'utils.global'
|
|
|
|
local Public = {}
|
|
|
|
local this = {
|
|
player_list = {
|
|
last_poke_tick = {},
|
|
pokes = {},
|
|
sorting_method = {}
|
|
},
|
|
show_roles_in_list = false
|
|
}
|
|
|
|
Global.register(
|
|
this,
|
|
function(t)
|
|
this = t
|
|
end
|
|
)
|
|
|
|
local symbol_asc = '▲'
|
|
local symbol_desc = '▼'
|
|
|
|
local pokemessages = {
|
|
'a stick',
|
|
'a leaf',
|
|
'a moldy carrot',
|
|
'a crispy slice of bacon',
|
|
'a french fry',
|
|
'a realistic toygun',
|
|
'a broomstick',
|
|
'a thirteen inch iron stick',
|
|
'a mechanical keyboard',
|
|
'a fly fishing cane',
|
|
'a selfie stick',
|
|
'an oversized fidget spinner',
|
|
'a thumb extender',
|
|
'a dirty straw',
|
|
'a green bean',
|
|
'a banana',
|
|
'an umbrella',
|
|
"grandpa's walking stick",
|
|
'live firework',
|
|
'a toilet brush',
|
|
'a fake hand',
|
|
'an undercooked hotdog',
|
|
"a slice of yesterday's microwaved pizza",
|
|
'bubblegum',
|
|
'a biter leg',
|
|
"grandma's toothbrush",
|
|
'charred octopus',
|
|
'a dollhouse bathtub',
|
|
'a length of copper wire',
|
|
'a decommissioned nuke',
|
|
'a smelly trout',
|
|
'an unopened can of deodorant',
|
|
'a stone brick',
|
|
'a half full barrel of lube',
|
|
'a half empty barrel of lube',
|
|
'an unexploded cannon shell',
|
|
'a blasting programmable speaker',
|
|
'a not so straight rail',
|
|
'a mismatched pipe to ground',
|
|
'a surplus box of landmines',
|
|
'decommissioned yellow rounds',
|
|
'an oily pumpjack shaft',
|
|
'a melted plastic bar in the shape of the virgin mary',
|
|
'a bottle of watermelon vitamin water',
|
|
'a slice of watermelon',
|
|
'a stegosaurus tibia',
|
|
"a basking musician's clarinet",
|
|
'a twig',
|
|
'an undisclosed pokey item',
|
|
'a childhood trophy everyone else got',
|
|
'a dead starfish',
|
|
'a titanium toothpick',
|
|
'a nail file',
|
|
'a stamp collection',
|
|
'a bucket of lego',
|
|
'a rolled up carpet',
|
|
'a rolled up WELCOME doormat',
|
|
"Bobby's favorite bone",
|
|
'an empty bottle of cheap vodka',
|
|
'a tattooing needle',
|
|
'a peeled cucumber',
|
|
'a stack of cotton candy',
|
|
'a signed baseball bat',
|
|
'that 5 dollar bill grandma sent for christmas',
|
|
'a stack of overdue phone bills',
|
|
"the 'relax' section of the white pages",
|
|
'a bag of gym clothes which never made it to the washing machine',
|
|
'a handful of peanut butter',
|
|
"a pheasant's feather",
|
|
'a rusty pickaxe',
|
|
'a diamond sword',
|
|
'the bill of rights of a banana republic',
|
|
"one of those giant airport Toblerone's",
|
|
'a long handed inserter',
|
|
'a wiimote',
|
|
'an easter chocolate rabbit',
|
|
'a ball of yarn the cat threw up',
|
|
'a slightly expired but perfectly edible cheese sandwich',
|
|
'conclusive proof of lizard people existence',
|
|
'a pen drive full of high res wallpapers',
|
|
'a pet hamster',
|
|
'an oversized goldfish',
|
|
'a one foot extension cord',
|
|
"a CD from Walmart's 1 dollar bucket",
|
|
'a magic wand',
|
|
'a list of disappointed people who believed in you',
|
|
'murder exhibit no. 3',
|
|
"a paperback copy of 'Great Expectations'",
|
|
'a baby biter',
|
|
'a little biter fang',
|
|
'the latest diet fad',
|
|
'a belt that no longer fits you',
|
|
'an abandoned pet rock',
|
|
'a lava lamp',
|
|
'some spirit herbs',
|
|
'a box of fish sticks found at the back of the freezer',
|
|
'a bowl of tofu rice',
|
|
'a bowl of ramen noodles',
|
|
'a live lobster!',
|
|
'a miniature golf cart',
|
|
'dunce cap',
|
|
'a fully furnished x-mas tree',
|
|
'an orphaned power pole',
|
|
'an horphaned power pole',
|
|
'an box of overpriced girl scout cookies',
|
|
'the cheapest item from the yard sale',
|
|
'a Sharpie',
|
|
'a glowstick',
|
|
'a thick unibrow hair',
|
|
'a very detailed map of Kazakhstan',
|
|
'the official Factorio installation DVD',
|
|
'a Liberal Arts degree',
|
|
'a pitcher of Kool-Aid',
|
|
'a 1/4 pound vegan burrito',
|
|
'a bottle of expensive wine',
|
|
'a hamster sized gravestone',
|
|
'a counterfeit Cuban cigar',
|
|
'an old Nokia phone',
|
|
'a huge inferiority complex',
|
|
'a dead real state agent',
|
|
'a deck of tarot cards',
|
|
'unreleased Wikileaks documents',
|
|
'a mean-looking garden dwarf',
|
|
'the actual mythological OBESE cat',
|
|
'a telescope used to spy on the MILF next door',
|
|
'a fancy candelabra',
|
|
'the comic version of the Kama Sutra',
|
|
"an inflatable 'Netflix & chill' doll",
|
|
'whatever it is redlabel gets high on',
|
|
"Obama's birth certificate",
|
|
'a deck of Cards Against Humanity',
|
|
'a copy of META MEME HUMOR for Dummies',
|
|
'an abandoned, not-so-young-anymore puppy',
|
|
'one of those useless items advertised on TV',
|
|
'a genetic blueprint of a Japanese teen idol'
|
|
}
|
|
|
|
local function get_formatted_playtime(x)
|
|
if x < 5184000 then
|
|
local y = x / 216000
|
|
y = tostring(y)
|
|
local h = ''
|
|
for i = 1, 10, 1 do
|
|
local z = string.sub(y, i, i)
|
|
|
|
if z == '.' then
|
|
break
|
|
else
|
|
h = h .. z
|
|
end
|
|
end
|
|
|
|
local m = x % 216000
|
|
m = m / 3600
|
|
m = math.floor(m)
|
|
m = tostring(m)
|
|
|
|
if h == '0' then
|
|
local str = m .. ' minutes'
|
|
return str
|
|
else
|
|
local str = h .. ' hours '
|
|
str = str .. m
|
|
str = str .. ' minutes'
|
|
return str
|
|
end
|
|
else
|
|
local y = x / 5184000
|
|
y = tostring(y)
|
|
local h = ''
|
|
for i = 1, 10, 1 do
|
|
local z = string.sub(y, i, i)
|
|
|
|
if z == '.' then
|
|
break
|
|
else
|
|
h = h .. z
|
|
end
|
|
end
|
|
|
|
local m = x % 5184000
|
|
m = m / 216000
|
|
m = math.floor(m)
|
|
m = tostring(m)
|
|
|
|
if h == '0' then
|
|
local str = m .. ' days'
|
|
return str
|
|
else
|
|
local str = h .. ' days '
|
|
str = str .. m
|
|
str = str .. ' hours'
|
|
return str
|
|
end
|
|
end
|
|
end
|
|
|
|
local function get_rank(player)
|
|
local play_table = Session.get_session_table()
|
|
local t = 0
|
|
if play_table then
|
|
if play_table[player.name] then
|
|
t = play_table[player.name]
|
|
end
|
|
end
|
|
|
|
local m = t / 3600
|
|
|
|
local ranks = {
|
|
'item/burner-mining-drill',
|
|
'item/burner-inserter',
|
|
'item/stone-furnace',
|
|
'item/light-armor',
|
|
'item/steam-engine',
|
|
'item/inserter',
|
|
'item/transport-belt',
|
|
'item/underground-belt',
|
|
'item/splitter',
|
|
'item/assembling-machine-1',
|
|
'item/long-handed-inserter',
|
|
'item/electronic-circuit',
|
|
'item/electric-mining-drill',
|
|
'item/dummy-steel-axe',
|
|
'item/heavy-armor',
|
|
'item/steel-furnace',
|
|
'item/gun-turret',
|
|
'item/fast-transport-belt',
|
|
'item/fast-underground-belt',
|
|
'item/fast-splitter',
|
|
'item/assembling-machine-2',
|
|
'item/fast-inserter',
|
|
'item/radar',
|
|
'item/filter-inserter',
|
|
'item/defender-capsule',
|
|
'item/pumpjack',
|
|
'item/chemical-plant',
|
|
'item/solar-panel',
|
|
'item/advanced-circuit',
|
|
'item/modular-armor',
|
|
'item/accumulator',
|
|
'item/construction-robot',
|
|
'item/distractor-capsule',
|
|
'item/stack-inserter',
|
|
'item/electric-furnace',
|
|
'item/express-transport-belt',
|
|
'item/express-underground-belt',
|
|
'item/express-splitter',
|
|
'item/assembling-machine-3',
|
|
'item/processing-unit',
|
|
'item/power-armor',
|
|
'item/logistic-robot',
|
|
'item/laser-turret',
|
|
'item/stack-filter-inserter',
|
|
'item/destroyer-capsule',
|
|
'item/power-armor-mk2',
|
|
'item/flamethrower-turret',
|
|
'item/beacon',
|
|
'item/steam-turbine',
|
|
'item/centrifuge',
|
|
'item/nuclear-reactor',
|
|
'item/cannon-shell',
|
|
'item/rocket',
|
|
'item/explosive-cannon-shell',
|
|
'item/explosive-rocket',
|
|
'item/uranium-cannon-shell',
|
|
'item/explosive-uranium-cannon-shell',
|
|
'item/atomic-bomb',
|
|
'achievement/so-long-and-thanks-for-all-the-fish',
|
|
'achievement/golem'
|
|
}
|
|
|
|
--60? ranks
|
|
|
|
local time_needed = 240 -- in minutes between rank upgrades
|
|
m = m / time_needed
|
|
m = math.floor(m)
|
|
m = m + 1
|
|
|
|
if m > #ranks then
|
|
m = #ranks
|
|
end
|
|
|
|
return ranks[m]
|
|
end
|
|
|
|
local comparators = {
|
|
['pokes_asc'] = function(a, b)
|
|
return a.pokes > b.pokes
|
|
end,
|
|
['pokes_desc'] = function(a, b)
|
|
return a.pokes < b.pokes
|
|
end,
|
|
['total_time_played_asc'] = function(a, b)
|
|
return a.total_played_ticks < b.total_played_ticks
|
|
end,
|
|
['total_time_played_desc'] = function(a, b)
|
|
return a.total_played_ticks > b.total_played_ticks
|
|
end,
|
|
['time_played_asc'] = function(a, b)
|
|
return a.played_ticks < b.played_ticks
|
|
end,
|
|
['time_played_desc'] = function(a, b)
|
|
return a.played_ticks > b.played_ticks
|
|
end,
|
|
['name_asc'] = function(a, b)
|
|
return a.name:lower() < b.name:lower()
|
|
end,
|
|
['name_desc'] = function(a, b)
|
|
return a.name:lower() > b.name:lower()
|
|
end
|
|
}
|
|
|
|
local function get_comparator(sort_by)
|
|
return comparators[sort_by]
|
|
end
|
|
|
|
local function get_sorted_list(sort_by)
|
|
local play_table = Session.get_session_table()
|
|
local player_list = {}
|
|
for i, player in pairs(game.connected_players) do
|
|
player_list[i] = {}
|
|
player_list[i].rank = get_rank(player)
|
|
player_list[i].name = player.name
|
|
|
|
local t = 0
|
|
if play_table[player.name] then
|
|
t = play_table[player.name]
|
|
end
|
|
|
|
player_list[i].total_played_time = get_formatted_playtime(t)
|
|
player_list[i].total_played_ticks = t
|
|
|
|
player_list[i].played_time = get_formatted_playtime(player.online_time)
|
|
player_list[i].played_ticks = player.online_time
|
|
|
|
player_list[i].pokes = this.player_list.pokes[player.index]
|
|
player_list[i].player_index = player.index
|
|
end
|
|
|
|
local comparator = get_comparator(sort_by)
|
|
table.sort(player_list, comparator)
|
|
|
|
return player_list
|
|
end
|
|
|
|
local function player_list_show(player, frame, sort_by)
|
|
-- Frame management
|
|
frame.clear()
|
|
frame.style.padding = 8
|
|
local play_table = Session.get_trusted_table()
|
|
local jailed = Jailed.get_jailed_table()
|
|
|
|
-- Header management
|
|
local t = frame.add {type = 'table', name = 'player_list_panel_header_table', column_count = 5}
|
|
local column_widths = {tonumber(40), tonumber(218), tonumber(220), tonumber(222), tonumber(50)}
|
|
local header_column_widths = {tonumber(40), tonumber(210), tonumber(220), tonumber(226), tonumber(50)}
|
|
for _, w in ipairs(header_column_widths) do
|
|
local label = t.add {type = 'label', caption = ''}
|
|
label.style.minimal_width = w
|
|
label.style.maximal_width = w
|
|
end
|
|
|
|
local headers = {
|
|
[1] = '[color=0.1,0.7,0.1]' .. -- green
|
|
tostring(#game.connected_players) .. '[/color]',
|
|
[2] = 'Online' ..
|
|
' / ' ..
|
|
'[color=0.7,0.1,0.1]' .. -- red
|
|
tostring(#game.players - #game.connected_players) .. '[/color]' .. ' Offline',
|
|
[3] = 'Total Time',
|
|
[4] = 'Current Time',
|
|
[5] = 'Poke'
|
|
}
|
|
local header_modifier = {
|
|
['name_asc'] = function(h)
|
|
h[2] = symbol_asc .. h[2]
|
|
end,
|
|
['name_desc'] = function(h)
|
|
h[2] = symbol_desc .. h[2]
|
|
end,
|
|
['total_time_played_asc'] = function(h)
|
|
h[3] = symbol_asc .. h[3]
|
|
end,
|
|
['total_time_played_desc'] = function(h)
|
|
h[3] = symbol_desc .. h[3]
|
|
end,
|
|
['time_played_asc'] = function(h)
|
|
h[4] = symbol_asc .. h[4]
|
|
end,
|
|
['time_played_desc'] = function(h)
|
|
h[4] = symbol_desc .. h[4]
|
|
end,
|
|
['pokes_asc'] = function(h)
|
|
h[5] = symbol_asc .. h[5]
|
|
end,
|
|
['pokes_desc'] = function(h)
|
|
h[5] = symbol_desc .. h[5]
|
|
end
|
|
}
|
|
|
|
if sort_by then
|
|
this.player_list.sorting_method[player.index] = sort_by
|
|
else
|
|
sort_by = this.player_list.sorting_method[player.index]
|
|
end
|
|
|
|
header_modifier[sort_by](headers)
|
|
|
|
for k, v in ipairs(headers) do
|
|
local header_label =
|
|
t.add {
|
|
type = 'label',
|
|
name = 'player_list_panel_header_' .. k,
|
|
caption = v
|
|
}
|
|
header_label.style.font = 'default-bold'
|
|
header_label.style.font_color = {r = 0.98, g = 0.66, b = 0.22}
|
|
end
|
|
|
|
-- special style on first header
|
|
local label = t['player_list_panel_header_1']
|
|
label.style.minimal_width = 36
|
|
label.style.maximal_width = 36
|
|
label.style.horizontal_align = 'right'
|
|
|
|
-- List management
|
|
local player_list_panel_table =
|
|
frame.add {
|
|
type = 'scroll-pane',
|
|
name = 'scroll_pane',
|
|
direction = 'vertical',
|
|
horizontal_scroll_policy = 'never',
|
|
vertical_scroll_policy = 'auto'
|
|
}
|
|
player_list_panel_table.style.maximal_height = 530
|
|
|
|
player_list_panel_table =
|
|
player_list_panel_table.add {type = 'table', name = 'player_list_panel_table', column_count = 5}
|
|
|
|
local player_list = get_sorted_list(sort_by)
|
|
for i = 1, #player_list, 1 do
|
|
-- Icon
|
|
local sprite =
|
|
player_list_panel_table.add {
|
|
type = 'sprite',
|
|
name = 'player_rank_sprite_' .. i,
|
|
sprite = player_list[i].rank
|
|
}
|
|
sprite.style.height = 32
|
|
sprite.style.width = 32
|
|
sprite.style.stretch_image_to_widget_size = true
|
|
|
|
local trusted
|
|
local tooltip
|
|
|
|
if game.players[player_list[i].name].admin then
|
|
trusted = '[color=red][A][/color]'
|
|
tooltip = 'This player is an admin of this server.'
|
|
elseif jailed[player_list[i].name] then
|
|
trusted = '[color=orange][J][/color]'
|
|
tooltip = 'This player is currently jailed.'
|
|
elseif play_table[player_list[i].name] then
|
|
trusted = '[color=green][T][/color]'
|
|
tooltip = 'This player is trusted.'
|
|
else
|
|
trusted = '[color=yellow][U][/color]'
|
|
tooltip = 'This player is not trusted.'
|
|
end
|
|
|
|
local caption
|
|
if this.show_roles_in_list or game.players[player_list[i].name].admin then
|
|
caption = player_list[i].name .. ' ' .. trusted
|
|
else
|
|
caption = player_list[i].name
|
|
end
|
|
|
|
-- Name
|
|
local name_label =
|
|
player_list_panel_table.add {
|
|
type = 'label',
|
|
name = 'player_list_panel_player_names_' .. i,
|
|
caption = caption,
|
|
tooltip = tooltip
|
|
}
|
|
|
|
local p_color = game.players[player_list[i].player_index]
|
|
name_label.style.font = 'default'
|
|
name_label.style.font_color = {
|
|
r = .4 + p_color.color.r * 0.6,
|
|
g = .4 + p_color.color.g * 0.6,
|
|
b = .4 + p_color.color.b * 0.6
|
|
}
|
|
name_label.style.minimal_width = column_widths[2]
|
|
name_label.style.maximal_width = column_widths[2]
|
|
|
|
-- Total time
|
|
local total_label =
|
|
player_list_panel_table.add {
|
|
type = 'label',
|
|
name = 'player_list_panel_player_total_time_played_' .. i,
|
|
caption = player_list[i].total_played_time
|
|
}
|
|
total_label.style.minimal_width = column_widths[3]
|
|
total_label.style.maximal_width = column_widths[3]
|
|
|
|
-- Current time
|
|
local current_label =
|
|
player_list_panel_table.add {
|
|
type = 'label',
|
|
name = 'player_list_panel_player_time_played_' .. i,
|
|
caption = player_list[i].played_time
|
|
}
|
|
current_label.style.minimal_width = column_widths[4]
|
|
current_label.style.maximal_width = column_widths[4]
|
|
|
|
-- Poke
|
|
local flow = player_list_panel_table.add {type = 'flow', name = 'button_flow_' .. i, direction = 'horizontal'}
|
|
flow.add {type = 'label', name = 'button_spacer_' .. i, caption = ''}
|
|
local button =
|
|
flow.add {type = 'button', name = 'poke_player_' .. player_list[i].name, caption = player_list[i].pokes}
|
|
button.style.font = 'default'
|
|
button.tooltip = 'Poke ' .. player_list[i].name .. ' with a random message!'
|
|
label.style.font_color = {r = 0.83, g = 0.83, b = 0.83}
|
|
button.style.minimal_height = 30
|
|
button.style.minimal_width = 30
|
|
button.style.maximal_height = 30
|
|
button.style.maximal_width = 30
|
|
button.style.top_padding = 0
|
|
button.style.left_padding = 0
|
|
button.style.right_padding = 0
|
|
button.style.bottom_padding = 0
|
|
end
|
|
end
|
|
|
|
local function on_gui_click(event)
|
|
if not event then
|
|
return
|
|
end
|
|
if not event.element then
|
|
return
|
|
end
|
|
if not event.element.valid then
|
|
return
|
|
end
|
|
if not event.element.name then
|
|
return
|
|
end
|
|
local player = game.players[event.element.player_index]
|
|
|
|
local frame = Tabs.comfy_panel_get_active_frame(player)
|
|
if not frame then
|
|
return
|
|
end
|
|
if frame.name ~= 'Players' then
|
|
return
|
|
end
|
|
|
|
local name = event.element.name
|
|
local actions = {
|
|
['player_list_panel_header_2'] = function()
|
|
if string.find(event.element.caption, symbol_desc) then
|
|
player_list_show(player, frame, 'name_asc')
|
|
else
|
|
player_list_show(player, frame, 'name_desc')
|
|
end
|
|
end,
|
|
['player_list_panel_header_3'] = function()
|
|
if string.find(event.element.caption, symbol_desc) then
|
|
player_list_show(player, frame, 'total_time_played_asc')
|
|
else
|
|
player_list_show(player, frame, 'total_time_played_desc')
|
|
end
|
|
end,
|
|
['player_list_panel_header_4'] = function()
|
|
if string.find(event.element.caption, symbol_desc) then
|
|
player_list_show(player, frame, 'time_played_asc')
|
|
else
|
|
player_list_show(player, frame, 'time_played_desc')
|
|
end
|
|
end,
|
|
['player_list_panel_header_5'] = function()
|
|
if string.find(event.element.caption, symbol_desc) then
|
|
player_list_show(player, frame, 'pokes_asc')
|
|
else
|
|
player_list_show(player, frame, 'pokes_desc')
|
|
end
|
|
end
|
|
}
|
|
|
|
if actions[name] then
|
|
actions[name]()
|
|
return
|
|
end
|
|
|
|
if not event.element.valid then
|
|
return
|
|
end
|
|
--Poke other players
|
|
if string.sub(event.element.name, 1, 11) == 'poke_player' then
|
|
local poked_player = string.sub(event.element.name, 13, string.len(event.element.name))
|
|
if player.name == poked_player then
|
|
return
|
|
end
|
|
if this.player_list.last_poke_tick[event.element.player_index] + 300 < game.tick then
|
|
local str = '>> '
|
|
str = str .. player.name
|
|
str = str .. ' has poked '
|
|
str = str .. poked_player
|
|
str = str .. ' with '
|
|
local z = math.random(1, #pokemessages)
|
|
str = str .. pokemessages[z]
|
|
str = str .. ' <<'
|
|
game.print(str)
|
|
this.player_list.last_poke_tick[event.element.player_index] = game.tick
|
|
local p = game.players[poked_player]
|
|
this.player_list.pokes[p.index] = this.player_list.pokes[p.index] + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local function refresh()
|
|
for _, player in pairs(game.connected_players) do
|
|
local frame = Tabs.comfy_panel_get_active_frame(player)
|
|
if frame then
|
|
if frame.name ~= 'Players' then
|
|
return
|
|
end
|
|
player_list_show(player, frame, this.player_list.sorting_method[player.index])
|
|
end
|
|
end
|
|
end
|
|
|
|
local function on_player_joined_game(event)
|
|
if not this.player_list.last_poke_tick[event.player_index] then
|
|
this.player_list.pokes[event.player_index] = 0
|
|
this.player_list.last_poke_tick[event.player_index] = 0
|
|
this.player_list.sorting_method[event.player_index] = 'total_time_played_desc'
|
|
end
|
|
refresh()
|
|
end
|
|
|
|
local function on_player_left_game()
|
|
refresh()
|
|
end
|
|
|
|
--- If the different roles should be shown in the player_list.
|
|
---@param value string
|
|
function Public.show_roles_in_list(value)
|
|
if value then
|
|
this.show_roles_in_list = value
|
|
end
|
|
|
|
return this.show_roles_in_list
|
|
end
|
|
|
|
comfy_panel_tabs['Players'] = {gui = player_list_show, admin = false}
|
|
|
|
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
|
Event.add(defines.events.on_player_left_game, on_player_left_game)
|
|
Event.add(defines.events.on_gui_click, on_gui_click)
|
|
|
|
return Public
|