mirror of
https://github.com/Refactorio/RedMew.git
synced 2024-12-12 10:04:40 +02:00
commit
df6342cdd7
@ -56,7 +56,7 @@ local STD_BASE_CONTROL = 'lua52c+factorio+factorio_control+factorio_defines+fact
|
||||
--[Assume Factorio Control stage as default]--
|
||||
-------------------------------------------------------------------------------
|
||||
std = STD_CONTROL
|
||||
globals = {'math', 'table', '_DEBUG', '_CHEATS', 'MARKET_ITEM'} -- RedMew-specific globals
|
||||
globals = {'print', 'math', 'table', '_DEBUG', '_CHEATS', 'MARKET_ITEM', 'ServerCommands'} -- RedMew-specific globals
|
||||
max_line_length = LINE_LENGTH
|
||||
|
||||
not_globals = NOT_GLOBALS
|
||||
@ -625,7 +625,7 @@ stds.factorio_defines = {
|
||||
"on_gui_closed", "on_gui_value_changed", "on_player_muted", "on_player_unmuted", "on_player_cheat_mode_enabled", "on_player_cheat_mode_disabled",
|
||||
"on_character_corpse_expired", "on_pre_ghost_deconstructed", "on_player_pipette", "on_player_display_resolution_changed", "on_player_display_scale_changed",
|
||||
"on_pre_player_crafted_item", "on_player_cancelled_crafting", "on_chunk_charted", "on_technology_effects_reset", "on_land_mine_armed", "on_forces_merged",
|
||||
"on_player_trash_inventory_changed",
|
||||
"on_player_trash_inventory_changed", "on_server_started"
|
||||
},
|
||||
},
|
||||
alert_type = {
|
||||
|
@ -7,6 +7,10 @@ require 'utils.math'
|
||||
require 'map_gen.shared.perlin_noise'
|
||||
require 'map_layout'
|
||||
|
||||
-- Specific to RedMew hosts, can be disabled safely if not hosting on RedMew servers
|
||||
require 'features.server'
|
||||
require 'features.server_commands'
|
||||
|
||||
-- Library modules which, if missing, will cause other feature modules to fail
|
||||
require 'features.base_data'
|
||||
--require 'features.follow' -- Nothing currently uses anything inside follow
|
||||
|
@ -1,6 +1,6 @@
|
||||
local Game = require 'utils.game'
|
||||
local Event = require 'utils.event'
|
||||
local Donators = require 'resources.donators'
|
||||
local UserGroups = require 'features.user_groups'
|
||||
|
||||
local function player_joined(event)
|
||||
local player = Game.get_player_by_index(event.player_index)
|
||||
@ -8,7 +8,7 @@ local function player_joined(event)
|
||||
return
|
||||
end
|
||||
|
||||
local message = Donators.welcome_messages[player.name]
|
||||
local message = UserGroups.get_donator_welcome_message(player.name)
|
||||
if not message then
|
||||
return
|
||||
end
|
||||
|
@ -5,6 +5,7 @@ local UserGroups = require 'features.user_groups'
|
||||
local Game = require 'utils.game'
|
||||
local math = require 'utils.math'
|
||||
local Utils = require 'utils.utils'
|
||||
local Server = require 'features.server'
|
||||
|
||||
local default_poll_duration = 300 * 60 -- in ticks
|
||||
local duration_max = 3600 -- in seconds
|
||||
@ -108,6 +109,48 @@ local function do_remaining_time(poll, remaining_time_label)
|
||||
end
|
||||
end
|
||||
|
||||
local function send_poll_result_to_discord(poll)
|
||||
local result = {'Poll #', poll.id}
|
||||
|
||||
local created_by_player = poll.created_by
|
||||
if created_by_player and created_by_player.valid then
|
||||
table.insert(result, ' Created by ')
|
||||
table.insert(result, created_by_player.name)
|
||||
end
|
||||
|
||||
local edited_by_players = poll.edited_by
|
||||
if next(edited_by_players) then
|
||||
table.insert(result, ' Edited by ')
|
||||
for pi, _ in pairs(edited_by_players) do
|
||||
local p = game.players[pi]
|
||||
if p and p.valid then
|
||||
table.insert(result, p.name)
|
||||
table.insert(result, ', ')
|
||||
end
|
||||
end
|
||||
table.remove(result)
|
||||
end
|
||||
|
||||
table.insert(result, '\\n**Question: ')
|
||||
table.insert(result, poll.question)
|
||||
table.insert(result, '**\\n')
|
||||
|
||||
local answers = poll.answers
|
||||
local answers_count = #answers
|
||||
for i, a in ipairs(answers) do
|
||||
table.insert(result, '[')
|
||||
table.insert(result, a.voted_count)
|
||||
table.insert(result, '] - ')
|
||||
table.insert(result, a.text)
|
||||
if i ~= answers_count then
|
||||
table.insert(result, '\\n')
|
||||
end
|
||||
end
|
||||
|
||||
local message = table.concat(result)
|
||||
Server.to_discord_embed(message)
|
||||
end
|
||||
|
||||
local function redraw_poll_viewer_content(data)
|
||||
local poll_viewer_content = data.poll_viewer_content
|
||||
local remaining_time_label = data.remaining_time_label
|
||||
@ -657,6 +700,7 @@ local function create_poll(event)
|
||||
table.insert(polls, poll_data)
|
||||
|
||||
show_new_poll(poll_data)
|
||||
send_poll_result_to_discord(poll_data)
|
||||
|
||||
Gui.remove_data_recursivly(frame)
|
||||
frame.destroy()
|
||||
@ -1199,6 +1243,7 @@ function Class.poll(data)
|
||||
table.insert(polls, poll_data)
|
||||
|
||||
show_new_poll(poll_data)
|
||||
send_poll_result_to_discord(poll_data)
|
||||
|
||||
return true, id
|
||||
end
|
||||
@ -1273,6 +1318,23 @@ local function poll_result_command(cmd)
|
||||
Game.player_print(result)
|
||||
end
|
||||
|
||||
function Class.send_poll_result_to_discord(id)
|
||||
if type(id) ~= 'number' then
|
||||
Server.to_discord_embed('poll-id must be a number')
|
||||
return
|
||||
end
|
||||
|
||||
for _, poll_data in ipairs(polls) do
|
||||
if poll_data.id == id then
|
||||
send_poll_result_to_discord(poll_data)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local message = table.concat {'poll #', id, ' not found'}
|
||||
Server.to_discord_embed(message)
|
||||
end
|
||||
|
||||
commands.add_command(
|
||||
'poll',
|
||||
'<{question = "question", answers = {"answer 1", "answer 2"}, duration = 300 | nil}> - Creates a new poll (Admin and regulars only).',
|
||||
|
349
features/server.lua
Normal file
349
features/server.lua
Normal file
@ -0,0 +1,349 @@
|
||||
--- See documentation at https://github.com/Refactorio/RedMew/pull/469
|
||||
|
||||
local Token = require 'utils.global_token'
|
||||
|
||||
local Public = {}
|
||||
|
||||
local raw_print = print
|
||||
function print(str)
|
||||
raw_print('[PRINT] ' .. str)
|
||||
end
|
||||
|
||||
local discord_tag = '[DISCORD]'
|
||||
local discord_raw_tag = '[DISCORD-RAW]'
|
||||
local discord_bold_tag = '[DISCORD-BOLD]'
|
||||
local discord_admin_tag = '[DISCORD-ADMIN]'
|
||||
local discord_admin_raw_tag = '[DISCORD-ADMIN-RAW]'
|
||||
local discord_embed_tag = '[DISCORD-EMBED]'
|
||||
local discord_embed_raw_tag = '[DISCORD-EMBED-RAW]'
|
||||
local discord_admin_embed_tag = '[DISCORD-ADMIN-EMBED]'
|
||||
local discord_admin_embed_raw_tag = '[DISCORD-ADMIN-EMBED-RAW]'
|
||||
local start_scenario_tag = '[START-SCENARIO]'
|
||||
local ping_tag = '[PING]'
|
||||
local data_set_tag = '[DATA-SET]'
|
||||
local data_get_tag = '[DATA-GET]'
|
||||
local data_get_all_tag = '[DATA-GET-ALL]'
|
||||
local data_tracked_tag = '[DATA-TRACKED]'
|
||||
|
||||
Public.raw_print = raw_print
|
||||
|
||||
local data_set_handlers = {}
|
||||
|
||||
--- The event id for the on_server_started event.
|
||||
-- The event is raised whenever the server goes from the starting state to the running state.
|
||||
-- It provides a good opportunity to request data from the web server.
|
||||
-- Note that if the server is stopped then started again, this event will be raised again.
|
||||
-- @usage
|
||||
-- Event.add(Server.events.on_server_started,
|
||||
-- function()
|
||||
-- Server.try_get_all_data('regulars', callback)
|
||||
-- end)
|
||||
Public.events = {on_server_started = script.generate_event_name()}
|
||||
|
||||
--- Sends a message to the linked discord channel. The message is sanitized of markdown server side.
|
||||
-- @param message<string> message to send.
|
||||
-- @usage
|
||||
-- local Server = require 'server'
|
||||
-- Server.to_discord('Hello from scenario script!')
|
||||
function Public.to_discord(message)
|
||||
raw_print(discord_tag .. message)
|
||||
end
|
||||
|
||||
--- Sends a message to the linked discord channel. The message is not sanitized of markdown.
|
||||
-- @param message<string> message to send.
|
||||
function Public.to_discord_raw(message)
|
||||
raw_print(discord_raw_tag .. message)
|
||||
end
|
||||
|
||||
--- Sends a message to the linked discord channel. The message is sanitized of markdown server side, then made bold.
|
||||
-- @param message<string> message to send.
|
||||
function Public.to_discord_bold(message)
|
||||
raw_print(discord_bold_tag .. message)
|
||||
end
|
||||
|
||||
--- Sends a message to the linked admin discord channel. The message is sanitized of markdown server side.
|
||||
-- @param message<string> message to send.
|
||||
function Public.to_admin(message)
|
||||
raw_print(discord_admin_tag .. message)
|
||||
end
|
||||
|
||||
--- Sends a message to the linked admin discord channel. The message is not sanitized of markdown.
|
||||
-- @param message<string> message to send.
|
||||
function Public.to_admin_raw(message)
|
||||
raw_print(discord_admin_raw_tag .. message)
|
||||
end
|
||||
|
||||
--- Sends a embed message to the linked discord channel. The message is sanitized of markdown server side.
|
||||
-- @param message<string> the content of the embed.
|
||||
function Public.to_discord_embed(message)
|
||||
raw_print(discord_embed_tag .. message)
|
||||
end
|
||||
|
||||
--- Sends a embed message to the linked discord channel. The message is not sanitized of markdown.
|
||||
-- @param message<string> the content of the embed.
|
||||
function Public.to_discord_embed_raw(message)
|
||||
raw_print(discord_embed_raw_tag .. message)
|
||||
end
|
||||
|
||||
--- Sends a embed message to the linked admin discord channel. The message is sanitized of markdown server side.
|
||||
-- @param message<string> the content of the embed.
|
||||
function Public.to_admin_embed(message)
|
||||
raw_print(discord_admin_embed_tag .. message)
|
||||
end
|
||||
|
||||
--- Sends a embed message to the linked admin discord channel. The message is not sanitized of markdown.
|
||||
-- @param message<string> the content of the embed.
|
||||
function Public.to_admin_embed_raw(message)
|
||||
raw_print(discord_admin_embed_raw_tag .. message)
|
||||
end
|
||||
|
||||
--- Stops and saves the factorio server and starts the named scenario.
|
||||
-- @param scenario_name<string> The name of the scenario as appears in the scenario table on http://redmew.com/admin
|
||||
-- @usage
|
||||
-- local Server = require 'server'
|
||||
-- Server.start_scenario('my_scenario_name')
|
||||
function Public.start_scenario(scenario_name)
|
||||
if type(scenario_name) ~= 'string' then
|
||||
game.print('start_scenario - scenario_name ' .. tostring(scenario_name) .. ' must be a string.')
|
||||
return
|
||||
end
|
||||
|
||||
local message = start_scenario_tag .. scenario_name
|
||||
|
||||
raw_print(message)
|
||||
end
|
||||
|
||||
local default_ping_token =
|
||||
Token.register(
|
||||
function(sent_tick)
|
||||
local now = game.tick
|
||||
local diff = now - sent_tick
|
||||
|
||||
local message = table.concat({'Pong in ', diff, ' tick(s) ', 'sent tick: ', sent_tick, ' received tick: ', now})
|
||||
game.print(message)
|
||||
end
|
||||
)
|
||||
|
||||
--- Pings the web server.
|
||||
-- @param func_token<token> The function that is called when the web server replies.
|
||||
-- The function is passed the tick that the ping was sent.
|
||||
function Public.ping(func_token)
|
||||
local message = table.concat({ping_tag, func_token or default_ping_token, ' ', game.tick})
|
||||
raw_print(message)
|
||||
end
|
||||
|
||||
--- Sets the web server's persistent data storage. If you pass nil for the value removes the data.
|
||||
-- Data set this will by synced in with other server if they choose to.
|
||||
-- There can only be one key for each data_set.
|
||||
-- @param data_set<string>
|
||||
-- @param key<string>
|
||||
-- @param value<nil|boolean|number|string|table> Any type that is not a function. set to nil to remove the data.
|
||||
-- @usage
|
||||
-- local Server = require 'server'
|
||||
-- Server.set_data('my data set', 'key 1', 123)
|
||||
-- Server.set_data('my data set', 'key 2', 'abc')
|
||||
-- Server.set_data('my data set', 'key 3', {'some', 'data', ['is_set'] = true})
|
||||
--
|
||||
-- Server.set_data('my data set', 'key 1', nil) -- this will remove 'key 1'
|
||||
-- Server.set_data('my data set', 'key 2', 'def') -- this will change the value for 'key 2' to 'def'
|
||||
function Public.set_data(data_set, key, value)
|
||||
if type(data_set) ~= 'string' then
|
||||
error('data_set must be a string')
|
||||
end
|
||||
if type(key) ~= 'string' then
|
||||
error('key must be a string')
|
||||
end
|
||||
|
||||
-- Excessive escaping because the data is serialized twice.
|
||||
data_set = data_set:gsub('\\', '\\\\\\\\'):gsub('"', '\\\\\\"')
|
||||
key = key:gsub('\\', '\\\\\\\\'):gsub('"', '\\\\\\"')
|
||||
|
||||
local message
|
||||
local vt = type(value)
|
||||
if vt == 'nil' then
|
||||
message = table.concat({data_set_tag, '{data_set:"', data_set, '",key:"', key, '"}'})
|
||||
elseif vt == 'string' then
|
||||
-- Excessive escaping because the data is serialized twice.
|
||||
value = value:gsub('\\', '\\\\\\\\'):gsub('"', '\\\\\\"')
|
||||
|
||||
message = table.concat({data_set_tag, '{data_set:"', data_set, '",key:"', key, '",value:"\\"', value, '\\""}'})
|
||||
elseif vt == 'number' then
|
||||
message = table.concat({data_set_tag, '{data_set:"', data_set, '",key:"', key, '",value:"', value, '"}'})
|
||||
elseif vt == 'boolean' then
|
||||
message =
|
||||
table.concat({data_set_tag, '{data_set:"', data_set, '",key:"', key, '",value:"', tostring(value), '"}'})
|
||||
elseif vt == 'function' then
|
||||
error('value cannot be a function')
|
||||
else -- table
|
||||
value = serpent.line(value)
|
||||
|
||||
-- Less escaping than the string case as serpent provides one level of escaping.
|
||||
-- Need to escape single quotes as serpent uses double quotes for strings.
|
||||
value = value:gsub('\\', '\\\\'):gsub("'", "\\'")
|
||||
|
||||
message = table.concat({data_set_tag, '{data_set:"', data_set, '",key:"', key, "\",value:'", value, "'}"})
|
||||
end
|
||||
|
||||
raw_print(message)
|
||||
end
|
||||
|
||||
--- Gets data from the web server's persistent data storage.
|
||||
-- The callback is passed a table {data_set: string, key: string, value: any}.
|
||||
-- If the value is nil, it means there is no stored data for that data_set key pair.
|
||||
-- @param data_set<string>
|
||||
-- @param key<string>
|
||||
-- @param callback_token<token>
|
||||
-- @usage
|
||||
-- local Server = require 'server'
|
||||
-- local Token = require 'utils.global_token'
|
||||
--
|
||||
-- local callback =
|
||||
-- Token.register(
|
||||
-- function(data)
|
||||
-- local data_set = data.data_set
|
||||
-- local key = data.key
|
||||
-- local value = data.value -- will be nil if no data
|
||||
--
|
||||
-- game.print(data_set .. ':' .. key .. ':' .. tostring(value))
|
||||
-- end
|
||||
-- )
|
||||
--
|
||||
-- Server.try_get_data('my data set', 'key 1', callback)
|
||||
function Public.try_get_data(data_set, key, callback_token)
|
||||
if type(data_set) ~= 'string' then
|
||||
error('data_set must be a string')
|
||||
end
|
||||
if type(key) ~= 'string' then
|
||||
error('key must be a string')
|
||||
end
|
||||
if type(callback_token) ~= 'number' then
|
||||
error('callback_token must be a number')
|
||||
end
|
||||
|
||||
-- Excessive escaping because the data is serialized twice.
|
||||
data_set = data_set:gsub('\\', '\\\\\\\\'):gsub('"', '\\\\\\"')
|
||||
key = key:gsub('\\', '\\\\\\\\'):gsub('"', '\\\\\\"')
|
||||
|
||||
local message = table.concat {data_get_tag, callback_token, ' {', 'data_set:"', data_set, '",key:"', key, '"}'}
|
||||
raw_print(message)
|
||||
end
|
||||
|
||||
--- Gets all the data for the data_set from the web server's persistent data storage.
|
||||
-- The callback is passed a table {data_set: string, entries: {dictionary key -> value}}.
|
||||
-- If there is no data stored for the data_set entries will be nil.
|
||||
-- @param data_set<string>
|
||||
-- @param callback_token<token>
|
||||
-- @usage
|
||||
-- local Server = require 'server'
|
||||
-- local Token = require 'utils.global_token'
|
||||
--
|
||||
-- local callback =
|
||||
-- Token.register(
|
||||
-- function(data)
|
||||
-- local data_set = data.data_set
|
||||
-- local entries = data.entries -- will be nil if no data
|
||||
-- local value2 = entries['key 2']
|
||||
-- local value3 = entries['key 3']
|
||||
-- end
|
||||
-- )
|
||||
--
|
||||
-- Server.try_get_all_data('my data set', callback)
|
||||
function Public.try_get_all_data(data_set, callback_token)
|
||||
if type(data_set) ~= 'string' then
|
||||
error('data_set must be a string')
|
||||
end
|
||||
if type(callback_token) ~= 'number' then
|
||||
error('callback_token must be a number')
|
||||
end
|
||||
|
||||
-- Excessive escaping because the data is serialized twice.
|
||||
data_set = data_set:gsub('\\', '\\\\\\\\'):gsub('"', '\\\\\\"')
|
||||
|
||||
local message = table.concat {data_get_all_tag, callback_token, ' {', 'data_set:"', data_set, '"}'}
|
||||
raw_print(message)
|
||||
end
|
||||
|
||||
local function data_set_changed(data)
|
||||
local handlers = data_set_handlers[data.data_set]
|
||||
if handlers == nil then
|
||||
return
|
||||
end
|
||||
|
||||
if _DEBUG then
|
||||
for _, handler in ipairs(handlers) do
|
||||
local success, err = pcall(handler, data)
|
||||
if not success then
|
||||
log(err)
|
||||
error(err)
|
||||
end
|
||||
end
|
||||
else
|
||||
for _, handler in ipairs(handlers) do
|
||||
local success, err = pcall(handler, data)
|
||||
if not success then
|
||||
log(err)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Register a handler to be called when the data_set changes.
|
||||
-- The handler is passed a table {data_set:string, key:string, value:any}
|
||||
-- If value is nil that means the key was removed.
|
||||
-- The handler may be called even if the value hasn't changed. It's up to the implementer
|
||||
-- to determine if the value has changed, or not care.
|
||||
-- To prevent desyncs the same handlers must be registered for all clients. The easiest way to do this
|
||||
-- is in the control stage, i.e before on_init or on_load would be called.
|
||||
-- @param data_set<string>
|
||||
-- @param handler<function>
|
||||
-- @usage
|
||||
-- local Server = require 'server'
|
||||
-- Server.on_data_set_changed(
|
||||
-- 'my data set',
|
||||
-- function(data)
|
||||
-- local data_set = data.data_set
|
||||
-- local key = data.key
|
||||
-- local value = data.value -- will be nil if data was removed.
|
||||
-- end
|
||||
-- )
|
||||
function Public.on_data_set_changed(data_set, handler)
|
||||
if type(data_set) ~= 'string' then
|
||||
error('data_set must be a string')
|
||||
end
|
||||
|
||||
local handlers = data_set_handlers[data_set]
|
||||
if handlers == nil then
|
||||
handlers = {handler}
|
||||
data_set_handlers[data_set] = handlers
|
||||
else
|
||||
table.insert(handlers, handler)
|
||||
end
|
||||
end
|
||||
|
||||
Public.raise_data_set = data_set_changed
|
||||
|
||||
--- Called by the web server to determine which data_sets are being tracked.
|
||||
function Public.get_tracked_data_sets()
|
||||
local message = {data_tracked_tag, '['}
|
||||
|
||||
for k, _ in pairs(data_set_handlers) do
|
||||
-- Excessive escaping because the data is serialized twice.
|
||||
k = k:gsub('\\', '\\\\\\\\'):gsub('"', '\\\\\\"')
|
||||
|
||||
table.insert(message, '"')
|
||||
table.insert(message, k)
|
||||
table.insert(message, '"')
|
||||
table.insert(message, ',')
|
||||
end
|
||||
|
||||
if message[#message] == ',' then
|
||||
table.remove(message)
|
||||
end
|
||||
|
||||
table.insert(message, ']')
|
||||
|
||||
message = table.concat(message)
|
||||
raw_print(message)
|
||||
end
|
||||
|
||||
return Public
|
28
features/server_commands.lua
Normal file
28
features/server_commands.lua
Normal file
@ -0,0 +1,28 @@
|
||||
local Poll = require 'features.gui.poll'
|
||||
local UserGroups = require 'features.user_groups'
|
||||
local Token = require 'utils.global_token'
|
||||
local Server = require 'features.server'
|
||||
|
||||
--- This module is for the web server to call functions and raise events.
|
||||
-- Not intended to be called by scripts.
|
||||
-- Needs to be in the _G table so it can be accessed by the web server.
|
||||
ServerCommands = {}
|
||||
|
||||
ServerCommands.get_poll_result = Poll.send_poll_result_to_discord
|
||||
|
||||
ServerCommands.regular_sync = UserGroups.sync_regulars
|
||||
ServerCommands.donator_sync = UserGroups.sync_donators
|
||||
|
||||
function ServerCommands.raise_callback(func_token, data)
|
||||
local func = Token.get(func_token)
|
||||
func(data)
|
||||
end
|
||||
|
||||
ServerCommands.raise_data_set = Server.raise_data_set
|
||||
ServerCommands.get_tracked_data_sets = Server.get_tracked_data_sets
|
||||
|
||||
function ServerCommands.server_started()
|
||||
script.raise_event(Server.events.on_server_started, {})
|
||||
end
|
||||
|
||||
return ServerCommands
|
@ -1,62 +1,63 @@
|
||||
global.regulars = require 'resources.regulars'
|
||||
local Donators = require 'resources.donators'
|
||||
global.donators = Donators.donators
|
||||
local Event = require 'utils.event'
|
||||
local Utils = require 'utils.utils'
|
||||
local Server = require 'features.server'
|
||||
local Donators = require 'resources.donators'
|
||||
local Game = require 'utils.game'
|
||||
local Token = require 'utils.global_token'
|
||||
|
||||
global.regulars = {}
|
||||
global.donators = Donators.donators
|
||||
|
||||
local Module = {}
|
||||
|
||||
local function update_file()
|
||||
local data = {'{\n'}
|
||||
for player_name, _ in pairs(global.regulars) do
|
||||
table.insert(data, "['")
|
||||
table.insert(data, player_name)
|
||||
table.insert(data, "''] = true,\n")
|
||||
end
|
||||
table.insert(data, '}')
|
||||
|
||||
game.write_file('regulars.lua', table.concat(data), false, 0)
|
||||
end
|
||||
|
||||
Module.is_regular =
|
||||
function(player_name)
|
||||
return Utils.cast_bool(global.regulars[player_name] or global.regulars[player_name:lower()]) --to make it backwards compatible
|
||||
end
|
||||
|
||||
Module.add_regular = function(player_name)
|
||||
local actor = Utils.get_actor()
|
||||
if Module.is_regular(player_name) then
|
||||
|
||||
if (Module.is_regular(player_name)) then
|
||||
Game.player_print(player_name .. ' is already a regular.')
|
||||
else
|
||||
if game.players[player_name] then
|
||||
player_name = game.players[player_name].name
|
||||
game.print(actor .. ' promoted ' .. player_name .. ' to regular.')
|
||||
global.regulars[player_name] = true
|
||||
update_file()
|
||||
else
|
||||
Game.player_print(player_name .. ' does not exist.')
|
||||
end
|
||||
global.regulars[player_name] = true
|
||||
Server.set_data('regulars', player_name, true)
|
||||
game.print(actor .. ' promoted ' .. player_name .. ' to regular.')
|
||||
end
|
||||
end
|
||||
|
||||
Module.remove_regular =
|
||||
function(player_name)
|
||||
Module.remove_regular = function(player_name)
|
||||
local actor = Utils.get_actor()
|
||||
if game.players[player_name] then
|
||||
player_name = game.players[player_name].name
|
||||
if Module.is_regular(player_name) then
|
||||
game.print(player_name .. ' was demoted from regular by ' .. actor .. '.')
|
||||
end
|
||||
|
||||
if (Module.is_regular(player_name)) then
|
||||
global.regulars[player_name] = nil
|
||||
global.regulars[player_name:lower()] = nil --backwards compatible
|
||||
update_file()
|
||||
Server.set_data('regulars', player_name, nil)
|
||||
game.print(player_name .. ' was demoted from regular by ' .. actor .. '.')
|
||||
else
|
||||
Game.player_print(player_name .. ' is not a regular.')
|
||||
end
|
||||
end
|
||||
|
||||
local sync_regulars_callback =
|
||||
Token.register(
|
||||
function(data)
|
||||
global.regulars = data.entries or {}
|
||||
end
|
||||
)
|
||||
|
||||
function Module.sync_regulars()
|
||||
Server.try_get_all_data('regulars', sync_regulars_callback)
|
||||
end
|
||||
|
||||
Module.print_regulars = function()
|
||||
local result = {}
|
||||
for k, _ in pairs(global.regulars) do
|
||||
Game.player_print(k)
|
||||
table.insert(result, k)
|
||||
end
|
||||
|
||||
result = table.concat(result, ', ')
|
||||
game.print(result)
|
||||
end
|
||||
|
||||
function Module.get_rank(player)
|
||||
@ -70,7 +71,7 @@ function Module.get_rank(player)
|
||||
end
|
||||
|
||||
function Module.is_donator(player_name)
|
||||
return global.donators[player_name]
|
||||
return global.donators[player_name] ~= nil
|
||||
end
|
||||
|
||||
function Module.player_has_donator_perk(player_name, perk_flag)
|
||||
@ -79,19 +80,84 @@ function Module.player_has_donator_perk(player_name, perk_flag)
|
||||
return false
|
||||
end
|
||||
|
||||
return bit32.band(d, perk_flag) == perk_flag
|
||||
local flags = d.perk_flags
|
||||
if not flags then
|
||||
return false
|
||||
end
|
||||
|
||||
return bit32.band(flags, perk_flag) == perk_flag
|
||||
end
|
||||
|
||||
function Module.get_donator_welcome_message(player_name)
|
||||
local d = global.donators[player_name]
|
||||
if not d then
|
||||
return nil
|
||||
end
|
||||
|
||||
return d.welcome_messages
|
||||
end
|
||||
|
||||
function Module.set_donator(player_name, data)
|
||||
global.donators[player_name] = data
|
||||
Server.set_data('donators', player_name, data)
|
||||
end
|
||||
|
||||
local sync_donators_callback =
|
||||
Token.register(
|
||||
function(data)
|
||||
global.donators = data.entries or {}
|
||||
end
|
||||
)
|
||||
|
||||
function Module.sync_donators()
|
||||
Server.try_get_all_data('donators', sync_donators_callback)
|
||||
end
|
||||
|
||||
function Module.print_donators()
|
||||
local result = {}
|
||||
|
||||
for k, _ in pairs(global.donators) do
|
||||
table.insert(result, k)
|
||||
end
|
||||
|
||||
result = table.concat(result, ', ')
|
||||
game.print(result)
|
||||
end
|
||||
|
||||
Event.add(
|
||||
defines.events.on_player_joined_game,
|
||||
function(event)
|
||||
local correctCaseName = Game.get_player_by_index(event.player_index).name
|
||||
if global.regulars[correctCaseName:lower()] and not global.regulars[correctCaseName] then
|
||||
global.regulars[correctCaseName:lower()] = nil
|
||||
local lowerCaseName = correctCaseName:lower()
|
||||
if correctCaseName ~= lowerCaseName and global.regulars[lowerCaseName] then
|
||||
global.regulars[lowerCaseName] = nil
|
||||
global.regulars[correctCaseName] = true
|
||||
update_file()
|
||||
Server.set_data('regulars', lowerCaseName, nil)
|
||||
Server.set_data('regulars', correctCaseName, true)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
Event.add(
|
||||
Server.events.on_server_started,
|
||||
function()
|
||||
Module.sync_regulars()
|
||||
Module.sync_donators()
|
||||
end
|
||||
)
|
||||
|
||||
Server.on_data_set_changed(
|
||||
'regulars',
|
||||
function(data)
|
||||
global.regulars[data.key] = data.value
|
||||
end
|
||||
)
|
||||
|
||||
Server.on_data_set_changed(
|
||||
'donators',
|
||||
function(data)
|
||||
global.donators[data.key] = data.value
|
||||
end
|
||||
)
|
||||
|
||||
return Module
|
||||
|
@ -5,35 +5,6 @@ Module.donator_perk_flags = {
|
||||
train = 0x2
|
||||
}
|
||||
|
||||
local d = Module.donator_perk_flags
|
||||
|
||||
Module.donators = {
|
||||
['aldldl'] = d.rank,
|
||||
['Geostyx'] = d.rank,
|
||||
['Linaori'] = d.rank,
|
||||
['Xertez'] = d.rank,
|
||||
['Chevalier1200'] = d.rank + d.train,
|
||||
['DraugTheWhopper'] = d.rank + d.train,
|
||||
['der-dave.com'] = d.rank + d.train,
|
||||
['Jayefuu'] = d.rank,
|
||||
['Valansch'] = d.rank,
|
||||
['plague006'] = d.rank,
|
||||
['chromaddict'] = d.rank,
|
||||
['InphinitePhractals'] = d.rank + d.train,
|
||||
['shoghicp'] = d.rank + d.train,
|
||||
['DuelleuD'] = d.rank + d.train,
|
||||
['henrycn1997'] = d.rank + d.train,
|
||||
['Raiguard'] = d.rank + d.train,
|
||||
}
|
||||
|
||||
Module.welcome_messages = {
|
||||
['Linaori'] = 'I present to you Linaori of house Refactorio, Lady of the Void, Remover of Spaghetti, Queen of the Endless Nauvis, Breaker of Biters and Mother of Code!',
|
||||
['Valansch'] = 'Welcome Valansch, <insert custom welcome message here>.',
|
||||
['der-dave.com'] = "Dave doesn't want a welcome message.",
|
||||
['plague006'] = 'plague wrote this dumb message you have to read. If you want your own dumb on-join message be sure to donate on Patreon!',
|
||||
['shoghicp'] = 'Need more servers!',
|
||||
['aldldl'] = "ALo's Here",
|
||||
['Raiguard'] = "I am... was... God. The one you call 'The Almighty'. The creator of Factories. But now, I am dead. The Biters killed me. I am sorry.",
|
||||
}
|
||||
Module.donators = {}
|
||||
|
||||
return Module
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user