1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-01-05 22:53:39 +02:00

Overhaul rank system, command, donator, add probation rank

This commit is contained in:
Matthew Heguy 2019-01-29 22:52:43 -05:00
parent a48f6444cc
commit 28daf88f21
35 changed files with 543 additions and 333 deletions

View File

@ -231,10 +231,6 @@ global.config = {
admin_commands = {
enabled = true
},
-- enables donators' on-join messages
donator_messages = {
enabled = true
},
player_colors = {
enabled = true
},

View File

@ -21,7 +21,7 @@ require 'features.server_commands'
-- Library modules
-- If missing, will cause other feature modules to fail
require 'features.player_create'
require 'features.user_groups'
require 'features.rank_system'
-- Feature modules
-- Each can be disabled safely
@ -46,9 +46,6 @@ end
if config.redmew_commands.enabled then
require 'features.redmew_commands'
end
if config.donator_messages.enabled then
require 'features.donator_messages'
end
if config.market.enabled then
require 'features.market'
end

View File

@ -1,12 +1,13 @@
local Task = require 'utils.task'
local Token = require 'utils.token'
local Global = require 'utils.global'
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local Report = require 'features.report'
local Utils = require 'utils.core'
local Game = require 'utils.game'
local Event = require 'utils.event'
local Command = require 'utils.command'
local Ranks = require 'resources.ranks'
local format = string.format
local loadstring = loadstring
@ -76,9 +77,21 @@ local function regular(args)
local remove_target = args['name']
if remove_target and add_target == 'remove' then
UserGroups.remove_regular(remove_target)
Rank.set_rank(remove_target, Ranks.guest)
else
UserGroups.add_regular(add_target)
Rank.set_rank(add_target, Ranks.regular)
end
end
--- Add or remove someone from probation
local function probation(args)
local add_target = args['name|remove']
local remove_target = args['name']
if remove_target and add_target == 'remove' then
Rank.set_rank(remove_target, Ranks.guest)
else
Rank.set_rank(add_target, Ranks.probation)
end
end
@ -281,7 +294,7 @@ Command.add(
{
description = 'Admin chat. Messages all other admins.',
arguments = {'msg'},
admin_only = true,
required_rank = Ranks.admin,
capture_excess_arguments = true,
allowed_by_server = true
},
@ -293,7 +306,7 @@ Command.add(
{
description = 'silent-command',
arguments = {'str'},
admin_only = true,
required_rank = Ranks.admin,
capture_excess_arguments = true,
allowed_by_server = true
},
@ -304,7 +317,7 @@ Command.add(
'hax',
{
description = 'Toggles your hax (makes recipes cost nothing)',
admin_only = true
required_rank = Ranks.admin
},
toggle_cheat_mode
)
@ -313,7 +326,7 @@ Command.add(
'all-tech',
{
description = 'researches all technologies',
admin_only = true,
required_rank = Ranks.admin,
debug_only = true,
cheat_only = true
},
@ -326,18 +339,29 @@ Command.add(
description = 'Add/remove player from regualrs. Use /regular <name> to add or /regular remove <name> to remove.',
arguments = {'name|remove', 'name'},
default_values = {['name'] = false},
admin_only = true,
capture_excess_arguments = false,
allowed_by_server = false
required_rank = Ranks.admin,
allowed_by_server = true
},
regular
)
Command.add(
'probation',
{
description = 'Add/remove player from probation. Use /probation <name> to add or /probation remove <name> to remove.',
arguments = {'name|remove', 'name'},
default_values = {['name'] = false},
required_rank = Ranks.admin,
allowed_by_server = true
},
probation
)
Command.add(
'showreports',
{
description = 'Shows user reports',
admin_only = true
required_rank = Ranks.admin
},
show_reports
)
@ -347,7 +371,7 @@ Command.add(
{
description = 'Puts a player in jail',
arguments = {'player'},
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true
},
jail_player
@ -358,7 +382,7 @@ Command.add(
{
description = 'Removes a player from jail',
arguments = {'player'},
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true
},
unjail_player
@ -369,7 +393,7 @@ Command.add(
{
description = 'Temporarily bans a player',
arguments = {'player', 'minutes'},
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true
},
tempban
@ -379,7 +403,7 @@ Command.add(
'pool',
{
description = 'Spawns a pool of water',
admin_only = true
required_rank = Ranks.admin
},
pool
)
@ -389,7 +413,7 @@ Command.add(
{
description = 'Teleports the player to you.',
arguments = {'player'},
admin_only = true
required_rank = Ranks.admin
},
invoke
)
@ -400,7 +424,7 @@ Command.add(
description = 'if blank, teleport to selected entity. mode = toggle tp mode where you can teleport to a placed ghost. player = teleport to player.',
arguments = {'mode|player'},
default_values = {['mode|player'] = false},
admin_only = true,
required_rank = Ranks.admin,
custom_help_text = '<blank|mode|player> 3 different uses: "/tp" to tp to selected entity. "/tp mode" to toggle tp mode. "/tp Newcott" to tp to Newcott'
},
teleport_command

View File

@ -3,6 +3,7 @@ local Global = require 'utils.global'
local Token = require 'utils.token'
local Command = require 'utils.command'
local Event = require 'utils.event'
local Ranks = require 'utils.ranks'
local random = math.random
local ceil = math.ceil
local floor = math.floor
@ -55,7 +56,7 @@ Command.add('particle-scale', {
description = 'Provide a fraction between 0 and 1 to lower or increase the amount of (max) particles. Leave empty to view the current values.',
arguments = {'fraction'},
default_values = {fraction = false},
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true,
}, function (arguments, player)
local p = player and player.print or print

133
features/donator.lua Normal file
View File

@ -0,0 +1,133 @@
local Event = require 'utils.event'
local Server = require 'features.server'
local Game = require 'utils.game'
local Token = require 'utils.token'
local table = require 'utils.table'
local Global = require 'utils.global'
local Task = require 'utils.task'
local donators = {} -- global register
Global.register(
{
donators = donators
},
function(tbl)
donators = tbl.donators
end
)
local Public = {}
--- Prints the donator message with the color returned from the server
local print_after_timeout =
Token.register(
function(data)
local player = data.player
if not player.valid then
return
end
game.print(data.message, player.chat_color)
end
)
--- When a player joins, set a 1s timer to retrieve their color before printing their welcome message
local function player_joined(event)
local player = Game.get_player_by_index(event.player_index)
if not player or not player.valid then
return
end
local d = donators[player.name]
if not d then
return nil
end
local message = d.welcome_messages
if not message then
return
end
message = table.concat({'*** ', message, ' ***'})
Task.set_timeout_in_ticks(60, print_after_timeout, {player = player, message = message})
end
--- Checks if a player is a donator
-- @param player_name <string>
-- @return <boolean>
function Public.is_donator(player_name)
return donators[player_name] ~= nil
end
--- Checks if a player has a specific donator perk
-- @param player_name <string>
-- @param perf_flag <number>
-- @return <boolean>
function Public.player_has_donator_perk(player_name, perk_flag)
local d = donators[player_name]
if not d then
return false
end
local flags = d.perk_flags
if not flags then
return false
end
return bit32.band(flags, perk_flag) == perk_flag
end
--- Sets the data for a donator
-- @param player_name <string>
-- @param data <table> a table containing perk_flags and welcome_messages
-- @return <string|nil>
function Public.set_donator(player_name, data)
donators[player_name] = data
Server.set_data('donators', player_name, data)
end
--- Clears the player_ranks table and merges the entries into it
local sync_donators_callback =
Token.register(
function(data)
table.clear_table(donators)
table.merge({donators, data.entries})
end
)
--- Signals the server to retrieve the donators data set
function Public.sync_donators()
Server.try_get_all_data('donators', sync_donators_callback)
end
--- Prints a list of donators
function Public.print_donators()
local result = {}
for k, _ in pairs(global.donators) do
table.insert(result, k)
end
result = table.concat(result, ', ')
Game.player_print(result)
end
Event.add(
Server.events.on_server_started,
function()
Public.sync_donators()
end
)
Server.on_data_set_changed(
'donators',
function(data)
global.donators[data.key] = data.value
end
)
Event.add(defines.events.on_player_joined_game, player_joined)
return Public

View File

@ -1,33 +0,0 @@
local Game = require 'utils.game'
local Event = require 'utils.event'
local UserGroups = require 'features.user_groups'
local Task = require 'utils.task'
local Token = require 'utils.token'
local print_after_timeout =
Token.register(
function(data)
local player = data.player
if not player.valid then
return
end
game.print(data.message, player.chat_color)
end
)
local function player_joined(event)
local player = Game.get_player_by_index(event.player_index)
if not player or not player.valid then
return
end
local message = UserGroups.get_donator_welcome_message(player.name)
if not message then
return
end
message = table.concat({'*** ', message, ' ***'})
Task.set_timeout_in_ticks(60, print_after_timeout, {player = player, message = message})
end
Event.add(defines.events.on_player_joined_game, player_joined)

View File

@ -1,12 +1,13 @@
local Gui = require 'utils.gui'
local Global = require 'utils.global'
local Event = require 'utils.event'
local UserGroups = require 'features.user_groups'
local Donator = require 'features.donator'
local Rank = require 'features.rank_system'
local Game = require 'utils.game'
local PlayerRewards = require 'utils.player_rewards'
local Color = require 'resources.color_presets'
local Server = require 'features.server'
local Token = require 'utils.token'
local Color = require 'resources.color_presets'
local format = string.format
@ -16,12 +17,6 @@ local config_prewards = config.player_rewards
local normal_color = Color.white
local focus_color = Color.dark_orange
local rank_colors = {
Color.white, -- Guest
Color.regular, -- Regular
Color.donator, -- Donator
Color.admin -- Admin
}
local reward_amount = 2
local reward_plural_indicator = reward_amount > 1 and 's' or ''
@ -379,18 +374,14 @@ you're working on a project which requires it.]]
ranks_label_style.single_line = false
local player_rank_flow = ranks_flow.add {type = 'flow', direction = 'horizontal'}
player_rank_flow.add {type = 'label', caption = 'Your rank is:'}
if player.admin then
local label = player_rank_flow.add {type = 'label', caption = 'Admin'}
label.style.font_color = rank_colors[4]
elseif UserGroups.is_donator(player.name) then
local player_name = player.name
if Donator.is_donator(player_name) then
local label = player_rank_flow.add {type = 'label', caption = 'Donator'}
label.style.font_color = rank_colors[3]
elseif UserGroups.is_regular(player.name) then
local label = player_rank_flow.add {type = 'label', caption = 'Regular'}
label.style.font_color = rank_colors[2]
label.style.font_color = Color.donator
else
local label = player_rank_flow.add {type = 'label', caption = 'Guest'}
label.style.font_color = rank_colors[1]
local label = player_rank_flow.add {type = 'label', caption = Rank.get_player_rank_name(player_name)}
label.style.font_color = Rank.get_player_rank_color(player_name)
end
grid.add {type = 'sprite', sprite = 'entity/market'}

View File

@ -1,14 +1,16 @@
local Event = require 'utils.event'
local Global = require 'utils.global'
local Gui = require 'utils.gui'
local Donators = require 'resources.donators'
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local Donator = require 'features.Donator'
local PlayerStats = require 'features.player_stats'
local Utils = require 'utils.core'
local Report = require 'features.report'
local Game = require 'utils.game'
local Color = require 'resources.color_presets'
local table = require 'utils.table'
local Color = require 'resources.color_presets'
local DonatorPerks = require 'resources.donator_perks'
local Ranks = require 'resources.ranks'
local poke_messages = require 'resources.poke_messages'
local player_sprites = require 'resources.player_sprites'
@ -28,7 +30,7 @@ local rank_colors = {
}
local inv_sprite_time_step = 1 / sprite_time_step
local rank_perk_flag = Donators.donator_perk_flags.rank
local rank_perk_flag = DonatorPerks.rank
local rank_names = {
'Guest',
'Regular',
@ -97,9 +99,9 @@ local function get_rank_level(player)
end
local name = player.name
if UserGroups.player_has_donator_perk(name, rank_perk_flag) then
if Donator.player_has_donator_perk(name, rank_perk_flag) then
return 3
elseif UserGroups.is_regular(name) then
elseif Rank.equal(name, Ranks.regular) then
return 2
end

View File

@ -1,12 +1,13 @@
local Gui = require 'utils.gui'
local Global = require 'utils.global'
local Event = require 'utils.event'
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local Game = require 'utils.game'
local math = require 'utils.math'
local Server = require 'features.server'
local Command = require 'utils.command'
local Color = require 'resources.color_presets'
local Ranks = require 'resources.ranks'
local insert = table.insert
@ -222,7 +223,7 @@ local function redraw_poll_viewer_content(data)
local question_flow = poll_viewer_content.add {type = 'table', column_count = 2}
if player.admin or UserGroups.is_regular(player.name) then
if Rank.equal_or_greater_than(player.name, Ranks.regular) then
local edit_button =
question_flow.add {
type = 'sprite-button',
@ -372,7 +373,7 @@ local function draw_main_frame(left, player)
local right_flow = bottom_flow.add {type = 'flow'}
right_flow.style.align = 'right'
if player.admin or UserGroups.is_regular(player.name) then
if Rank.equal_or_greater_than(player.name, Ranks.regular) then
local create_poll_button =
right_flow.add {type = 'button', name = create_poll_button_name, caption = 'Create Poll'}
apply_button_style(create_poll_button)
@ -1326,7 +1327,7 @@ Command.add(
'poll',
{
arguments = {'poll'},
regular_only = true,
required_rank = Ranks.regular,
allowed_by_server = true,
custom_help_text = '<{question = "question", answers = {"answer 1", "answer 2"}, duration = 300}> - Creates a new poll (Regulars only).',
log_command = true,

View File

@ -2,6 +2,7 @@ local Gui = require 'utils.gui'
local Utils = require 'utils.core'
local Game = require 'utils.game'
local Command = require 'utils.command'
local Ranks = require 'resources.ranks'
local close_name = Gui.uid_name()
@ -144,7 +145,7 @@ Command.add(
{
description = 'Shows a popup to all connected players',
arguments = {'message'},
admin_only = true,
required_rank = Ranks.admin,
capture_excess_arguments = true,
allowed_by_server = true
},
@ -156,7 +157,7 @@ Command.add(
{
description = 'Shows an update popup to all connected players',
arguments = {'version'},
admin_only = true,
required_rank = Ranks.admin,
capture_excess_arguments = true,
allowed_by_server = true
},
@ -168,7 +169,7 @@ Command.add(
{
description = 'Shows a popup to the player.',
arguments = {'player', 'message'},
admin_only = true,
required_rank = Ranks.admin,
capture_excess_arguments = true,
allowed_by_server = true
},

View File

@ -1,9 +1,10 @@
local Event = require 'utils.event'
local Gui = require 'utils.gui'
local Global = require 'utils.global'
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local Game = require 'utils.game'
local Command = require 'utils.command'
local Ranks = require 'resources.ranks'
local deafult_verb = 'expanded'
@ -147,7 +148,7 @@ local function draw_main_frame_content(parent)
local row = grid.add {type = 'table', column_count = 4}
row.style.horizontal_spacing = 0
if player.admin or UserGroups.is_regular(player.name) then
if Rank.equal_or_greater_than(player.name, Ranks.regular) then
local edit_button =
row.add {
type = 'sprite-button',
@ -238,7 +239,7 @@ local function draw_main_frame(player)
right_flow.add {type = 'button', name = clear_button_name, caption = 'Clear Tag'}
if player.admin or UserGroups.is_regular(player.name) then
if Rank.equal_or_greater_than(player.name, Ranks.regular) then
right_flow.add {type = 'button', name = create_tag_button_name, caption = 'Create Tag'}
end
end
@ -688,7 +689,7 @@ Command.add(
{
description = "Sets a player's tag",
arguments = {'player', 'tag'},
admin_only = true,
required_rank = Ranks.admin,
capture_excess_arguments = true,
allowed_by_server = true
},

View File

@ -1,12 +1,13 @@
local Event = require 'utils.event'
local Gui = require 'utils.gui'
local Global = require 'utils.global'
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local Utils = require 'utils.core'
local Game = require 'utils.game'
local Color = require 'resources.color_presets'
local math = require 'utils.math'
local Command = require 'utils.command'
local Color = require 'resources.color_presets'
local Ranks = require 'resources.ranks'
local normal_color = Color.white
local focus_color = Color.dark_orange
@ -311,7 +312,7 @@ local function redraw_tasks(data, enabled)
end
local function draw_main_frame(left, player)
local enabled = player.admin or UserGroups.is_regular(player.name)
local enabled = Rank.equal_or_greater_than(player.name, Ranks.regular)
local data = {}
@ -537,7 +538,7 @@ local function create_new_tasks(task_name, player)
local frame_data = Gui.get_data(frame)
frame_data.tasks_updated_label.caption = update_message
local enabled = p.admin or UserGroups.is_regular(p.name)
local enabled = Rank.equal_or_greater_than(p.name, Ranks.regular)
redraw_tasks(frame_data, enabled)
elseif notify then
draw_main_frame(left, p)
@ -605,7 +606,7 @@ local function player_joined(event)
label.caption = last_edit_message
label.tooltip = last_edit_message
local enabled = player.admin or UserGroups.is_regular(player.name)
local enabled = Rank.equal_or_greater_than(player.name, Ranks.regular)
redraw_tasks(data, enabled)
end
@ -821,7 +822,7 @@ Gui.on_click(
local frame = left[main_frame_name]
if frame and frame.valid then
local data = Gui.get_data(frame)
local enabled = p.admin or UserGroups.is_regular(p.name)
local enabled = Rank.equal_or_greater_than(p.name, Ranks.regular)
redraw_tasks(data, enabled)
elseif notify then
draw_main_frame(left, p)
@ -876,7 +877,7 @@ local function do_direction(event, sign)
local frame = p.gui.left[main_frame_name]
if frame and frame.valid then
local data = Gui.get_data(frame)
local enabled = p.admin or UserGroups.is_regular(p.name)
local enabled = Rank.equal_or_greater_than(p.name, Ranks.regular)
redraw_tasks(data, enabled)
end
end
@ -1056,7 +1057,7 @@ Gui.on_click(
local main_frame_data = Gui.get_data(main_frame)
main_frame_data.tasks_updated_label.caption = update_message
local enabled = p.admin or UserGroups.is_regular(p.name)
local enabled = Rank.equal_or_greater_than(p.name, Ranks.regular)
redraw_tasks(main_frame_data, enabled)
elseif notify then
draw_main_frame(left, p)
@ -1076,7 +1077,7 @@ Command.add(
{
description = 'Creates a new task.',
arguments = {'task'},
regular_only = true,
required_rank = Ranks.regular,
allowed_by_server = true,
log_command = true,
capture_excess_arguments = true,

View File

@ -4,6 +4,8 @@ local Command = require 'utils.command'
local Task = require 'utils.task'
local Token = require 'utils.token'
local Retailer = require 'features.retailer'
local Ranks = require 'resources.ranks'
local round = math.round
local insert = table.insert
local remove = table.remove
@ -118,7 +120,7 @@ end)
Command.add('lazy-bastard-bootstrap', {
description = 'Puts down the minimum requirements to get started',
admin_only = true,
required_rank = Ranks.admin,
}, function(_, player)
local surface = player.surface
local force = player.force

View File

@ -6,6 +6,7 @@ local PlayerStats = require 'features.player_stats'
local Game = require 'utils.game'
local Command = require 'utils.command'
local Retailer = require 'features.retailer'
local Ranks = require 'resources.ranks'
local market_items = require 'resources.market_items'
local fish_market_bonus_message = require 'resources.fish_messages'
@ -244,7 +245,7 @@ Command.add(
'market',
{
description = 'Places a market near you.',
admin_only = true,
required_rank = Ranks.admin,
},
spawn_market
)

View File

@ -1,14 +1,15 @@
local Event = require 'utils.event'
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local Utils = require 'utils.core'
local Game = require 'utils.game'
local Server = require 'features.server'
local Ranks = require 'resources.ranks'
local format = string.format
local match = string.match
local function allowed_to_nuke(player)
return player.admin or UserGroups.is_regular(player.name) or ((player.online_time / 216000) > global.config.nuke_control.nuke_min_time_hours)
return Rank.equal_or_greater_than(player.name, Ranks.auto_trusted)
end
local function ammo_changed(event)

View File

@ -1,4 +1,6 @@
local Command = require 'utils.command'
local Ranks = require 'resources.ranks'
local format = string.format
local Performance = {}
@ -37,7 +39,7 @@ Command.add(
{
description = 'Sets the performance scale between 0.05 and 1. Will alter the game speed, manual mining speed, manual crafting speed and character running speed per force.',
arguments = {'scale'},
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true
},
function(arguments, player)

View File

@ -4,6 +4,7 @@ local Command = require 'utils.command'
local Server = require 'features.server'
local Token = require 'utils.token'
local Utils = require 'utils.core'
local Ranks = require 'resources.ranks'
local serialize = serpent.line
@ -44,8 +45,7 @@ Command.add(
{
description = 'Set will save your current color for future maps. Reset will erase your saved color. Random will give you a random color.',
arguments = {'set-reset-random'},
admin_only = false,
regular_only = true,
required_rank = Ranks.regular,
allowed_by_server = false,
allowed_by_player = true
},

View File

@ -3,7 +3,6 @@ local Game = require 'utils.game'
local Event = require 'utils.event'
local Global = require 'utils.global'
local Info = require 'features.gui.info'
local UserGroups = require 'features.user_groups'
local get_random_weighted = table.get_random_weighted

239
features/rank_system.lua Normal file
View File

@ -0,0 +1,239 @@
--[[
This rank system is meant to allow for easy addition or removal of ranks from the heirarchy.
Ranks can be freely modified in resources.ranks as all the relation of the ranks to one another is all that matters.
While all the public functions want rank as a number, modules should use references to resources.ranks and not have actual numbers.
To dissuade the use of numeric ranks, there is explicitly no get_rank function.
Ex: right way: Rank.equal(player_name, Rank.regular) wrong way: Rank.equal(player_name, 2)
]]
-- Dependencies
local Event = require 'utils.event'
local Game = require 'utils.game'
local Global = require 'utils.global'
local table = require 'utils.table'
local Token = require 'utils.token'
local Utils = require 'utils.core'
local Server = require 'features.server'
local Ranks = require 'resources.ranks'
local Colors = require 'resources.color_presets'
local Config = global.config.rank_system
local format = string.format
-- Localized functions
local index_of = table.index_of
-- Constants
local ranking_data_set = 'rankings'
local nth_tick = 215983 -- nearest prime to 1 hour in ticks
-- Local vars
local Public = {}
local player_ranks = {} -- global register
Global.register(
{
player_ranks = player_ranks
},
function(tbl)
player_ranks = tbl.player_ranks
end
)
-- Local functions
--- Check each online player and if their playtime
local function check_playtime()
local auto_trusted = Ranks.auto_trusted
local time_for_trust = Config.time_for_trust
local less_than = Public.less_than
local set_data = Server.set_data
for _, p in pairs(game.connected_players) do
local player_name = p.name
if (p.online_time > time_for_trust) and less_than(player_name, auto_trusted) then
player_ranks[player_name] = auto_trusted
set_data(ranking_data_set, player_name, auto_trusted)
end
end
end
--- Clears the player_ranks table and merges the entries into it
local sync_ranks_callback =
Token.register(
function(data)
table.clear_table(player_ranks)
table.merge({player_ranks, data.entries})
end
)
--- Fix for legacy name storage
local function on_player_joined(event)
local player = Game.get_player_by_index(event.player_index)
if not player then
return
end
local player_name = player.name
local lowerCaseName = player_name:lower()
if player_name ~= lowerCaseName and player_ranks[lowerCaseName] then
local player_rank = player_ranks[lowerCaseName]
player_ranks[lowerCaseName] = nil
player_ranks[player_name] = player_rank
Server.set_data(ranking_data_set, lowerCaseName, nil)
Server.set_data(ranking_data_set, player_name, player_rank)
end
end
-- Exposed functions
--- Returns the player's rank as a name.
-- @param player_name <string>
-- @return <string>
function Public.get_player_rank_name(player_name)
return index_of(Ranks, (player_ranks[player_name] or 0))
end
--- Returns the player's rank as a name.
-- @param player_name <string>
-- @return <table>
function Public.get_player_rank_color(player_name)
local rank_name = Public.get_player_rank_name(player_name)
return Colors[rank_name]
end
--- Returns the rank's name.
-- @param rank <number>
-- @return <string>
function Public.get_rank_name(rank)
return index_of(Ranks, rank)
end
--- Returns the rank's color.
-- @param rank <table>
function Public.get_rank_color(rank)
local rank_name = Public.get_rank_name(rank)
return Colors[rank_name]
end
--- Evaluates if a player's rank is equal to the rank provided
-- @param player_name <string>
-- @param rank <number>
-- @return <boolean>
function Public.equal(player_name, rank)
local p_rank = player_ranks[player_name] or 0
return p_rank == rank
end
--- Evaluates if a player's rank is not equal to the rank provided
-- @param player_name <string>
-- @param rank <number>
-- @return <boolean>
function Public.not_equal(player_name, rank)
local p_rank = player_ranks[player_name] or 0
return p_rank ~= rank
end
--- Evaluates if a player's rank is greater than the rank provided
-- @param player_name <string>
-- @param rank <number>
-- @return <boolean>
function Public.greater_than(player_name, rank)
local p_rank = player_ranks[player_name] or 0
return p_rank > rank
end
--- Evaluates if a player's rank is less than the rank provided
-- @param player_name <string>
-- @param rank <number>
-- @return <boolean>
function Public.less_than(player_name, rank)
local p_rank = player_ranks[player_name] or 0
return p_rank < rank
end
--- Evaluates if a player's rank is equal to or greater than the rank provided
-- @param player_name <string>
-- @param rank <number>
-- @return <boolean>
function Public.equal_or_greater_than(player_name, rank)
local p_rank = player_ranks[player_name] or 0
return p_rank >= rank
end
--- Evaluates if a player's rank is equal to or less than the rank provided
-- @param player_name <string>
-- @param rank <number>
-- @return <boolean>
function Public.equal_or_less_than(player_name, rank)
local p_rank = player_ranks[player_name] or 0
return p_rank <= rank
end
--- Sets a player's rank
-- @param player_name <string>
-- @param rank <number>
function Public.set_rank(player_name, rank)
local actor = Utils.get_actor()
if Public.equal(player_name, rank) then
Game.player_print(format('%s is %s rank already.', player_name, Public.get_rank_name(rank)))
else
player_ranks[player_name] = rank
Server.set_data(ranking_data_set, player_name, rank)
game.print(format("%s set %s's rank to %s.", actor, player_name, Public.get_rank_name(rank)))
end
end
--- Resets a player's rank
-- @param player_name <string>
function Public.reset_rank(player_name)
local actor = Utils.get_actor()
local guest_rank = Ranks.guest
local auto_trusted = Ranks.auto_trusted
if Public.equal(player_name, guest_rank) then
Game.player_print(format('%s is %s rank already.', player_name, Public.get_rank_name(guest_rank)))
else
local player = game.players[player_name]
local rank
if player and player.valid and (player.online_time > Config.time_for_trust) then
player_ranks[player_name] = auto_trusted
Server.set_data(ranking_data_set, player_name, auto_trusted)
rank = auto_trusted
else
player_ranks[player_name] = nil
Server.set_data(ranking_data_set, player_name, nil)
rank = guest_rank
end
game.print(format("%s set %s's rank to %s.", actor, player_name, Public.get_rank_name(rank)))
end
end
function Public.sync_ranks()
Server.try_get_all_data(ranking_data_set, sync_ranks_callback)
end
-- Events
Event.add(defines.events.on_player_joined_game, on_player_joined)
Server.on_data_set_changed(
ranking_data_set,
function(data)
player_ranks[data.key] = data.value
end
)
Event.add(
Server.events.on_server_started,
function()
Public.sync_rankings()
end
)
Event.on_nth_tick(nth_tick, check_playtime)
return Public

View File

@ -8,6 +8,8 @@ local Game = require 'utils.game'
local Command = require 'utils.command'
local Global = require 'utils.global'
local Ranks = require 'resources.ranks'
local primitives = {reactors_enabled = {global.config.reactor_meltdown.on_by_default}}
local wastelands = {}
local reactors = {}
@ -182,7 +184,7 @@ Command.add(
'meltdown',
{
description = 'Toggles if reactors blow up',
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true,
log_command = true
},

View File

@ -1,3 +1,4 @@
local Report = require 'features.report'
local Game = require 'utils.game'
local Timestamp = require 'utils.timestamp'
local Command = require 'utils.command'
@ -377,15 +378,7 @@ Command.add(
Report.report_command
)
Command.add(
'regulars',
{
description = 'Prints a list of game regulars.',
allowed_by_server = true
},
UserGroups.print_regulars
)
-- No man's land / free for all
Command.add('redmew-setting-set', {
description = 'Set a setting for yourself',
arguments = {'setting_name', 'new_value'},

View File

@ -2,9 +2,11 @@ local Poll = {send_poll_result_to_discord = function () end}
if global.config.poll.enabled then
Poll = require 'features.gui.poll'
end
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local Token = require 'utils.token'
local Server = require 'features.server'
local Donator = require 'features.donator'
--- This module is for the web server to call functions and raise events.
-- Not intended to be called by scripts.
@ -13,8 +15,8 @@ ServerCommands = {}
ServerCommands.get_poll_result = Poll.send_poll_result_to_discord
ServerCommands.regular_sync = UserGroups.sync_regulars
ServerCommands.donator_sync = UserGroups.sync_donators
ServerCommands.regular_sync = Rank.sync_ranks
ServerCommands.donator_sync = Donator.sync_donators
function ServerCommands.raise_callback(func_token, data)
local func = Token.get(func_token)

View File

@ -1,10 +1,10 @@
local Event = require 'utils.event'
local market_items = require 'resources.market_items'
local Global = require 'utils.global'
local Donators = require 'resources.donators'
local UserGroups = require 'features.user_groups'
local DonatorPerks = require 'resources.donator_perks'
local Donator = require 'features.donator'
local Game = require 'utils.game'
local train_perk_flag = Donators.donator_perk_flags.train
local train_perk_flag = DonatorPerks.train
local saviour_token_name = 'small-plane' -- item name for what saves players
local saviour_timeout = 180 -- number of ticks players are train immune after getting hit (roughly)
@ -66,7 +66,7 @@ local function on_pre_death(event)
local player_name = player.name
if UserGroups.player_has_donator_perk(player_name, train_perk_flag) then
if Donator.player_has_donator_perk(player_name, train_perk_flag) then
saved_players[player_index] = game_tick
save_player(player)

View File

@ -1,163 +0,0 @@
local Event = require 'utils.event'
local Utils = require 'utils.core'
local Server = require 'features.server'
local Donators = require 'resources.donators'
local Game = require 'utils.game'
local Token = require 'utils.token'
global.regulars = {}
global.donators = Donators.donators
local Module = {}
Module.is_regular =
function(player_name)
return Utils.cast_bool(global.regulars[player_name])
end
Module.add_regular = function(player_name)
local actor = Utils.get_actor()
if (Module.is_regular(player_name)) then
Game.player_print(player_name .. ' is already a regular.')
else
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)
local actor = Utils.get_actor()
if (Module.is_regular(player_name)) then
global.regulars[player_name] = nil
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
table.insert(result, k)
end
result = table.concat(result, ', ')
Game.player_print(result)
end
function Module.get_rank(player)
if player.admin then
return 'Admin'
elseif Module.is_regular(player.name) then
return 'Regular'
else
return 'Guest'
end
end
function Module.is_donator(player_name)
return global.donators[player_name] ~= nil
end
function Module.player_has_donator_perk(player_name, perk_flag)
local d = global.donators[player_name]
if not d then
return false
end
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.player_print(result)
end
Event.add(
defines.events.on_player_joined_game,
function(event)
local correctCaseName = Game.get_player_by_index(event.player_index).name
local lowerCaseName = correctCaseName:lower()
if correctCaseName ~= lowerCaseName and global.regulars[lowerCaseName] then
global.regulars[lowerCaseName] = nil
global.regulars[correctCaseName] = true
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

View File

@ -4,6 +4,7 @@ local Event = require 'utils.event'
local Token = require 'utils.token'
local Command = require 'utils.command'
local Global = require 'utils.global'
local Ranks = require 'resources.ranks'
local Public = {}
local return_player
@ -176,7 +177,7 @@ Command.add(
description = 'Send someone on a walk. Duration is in seconds.',
arguments = {'player', 'duration'},
default_values = {duration = 60},
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true
},
walkabout

View File

@ -1,4 +1,5 @@
local Command = require 'utils.command'
local Ranks = require 'resources.ranks'
local insert = table.insert
@ -210,7 +211,7 @@ Command.add(
{
arguments = {'size'},
default_values = {size = 6},
admin_only = true
required_rank = Ranks.admin
},
extract1
)
@ -219,7 +220,7 @@ Command.add(
{
arguments = {'size'},
default_values = {size = 6},
admin_only = true
required_rank = Ranks.admin
},
extract4
)

View File

@ -4,6 +4,7 @@ local Token = require 'utils.token'
local Server = require 'features.server'
local Popup = require 'features.gui.popup'
local Global = require 'utils.global'
local Ranks = require 'resources.ranks'
local server_player = {name = '<server>', print = print}
@ -51,7 +52,7 @@ Command.add(
description = 'Restarts the crashsite scenario.',
arguments = {'scenario_name'},
default_values = {scenario_name = 'crashsite'},
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true
},
function(args, player)
@ -83,7 +84,7 @@ Command.add(
'abort',
{
description = 'Aborts the restart of the crashsite scenario.',
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true
},
function(_, player)

View File

@ -10,6 +10,8 @@ local Template = require 'map_gen.maps.diggy.template'
local ScoreTable = require 'map_gen.maps.diggy.score_table'
local Command = require 'utils.command'
local CreateParticles = require 'features.create_particles'
local Ranks = require 'resources.ranks'
local random = math.random
local tonumber = tonumber
local pairs = pairs
@ -128,7 +130,7 @@ Command.add('diggy-clear-void', {
description = 'Clears the void in a given area but still triggers all events Diggy would when clearing void.',
arguments = {'left_top_x', 'left_top_y', 'width', 'height', 'surface_index'},
debug_only = true,
admin_only = true,
required_rank = Ranks.admin,
}, function(arguments)
local left_top_x = tonumber(arguments.left_top_x)
local left_top_y = tonumber(arguments.left_top_y)

View File

@ -4,9 +4,10 @@ local Event = require 'utils.event'
local naming_words = require 'resources.naming_words'
local Utils = require 'utils.core'
local Global = require 'utils.global'
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local ScenarioInfo = require 'features.gui.info'
local Command = require 'utils.command'
local Ranks = require 'resources.ranks'
local format = string.format
local random = math.random
@ -36,7 +37,7 @@ Global.register(
--- Takes a player's real name, current silly name, and old silly name and adjusts
-- the silly_regulars table accordingly
local function check_regular(real_name, silly_name, old_silly_name)
if UserGroups.is_regular(real_name) then
if Rank.equal(real_name, Ranks.regular) then
global.silly_regulars[silly_name] = true
if old_silly_name then
global.silly_regulars[old_silly_name] = nil
@ -227,7 +228,7 @@ Command.add(
{
description = 'Gets the index of a player',
arguments = {'player'},
admin_only = true,
required_rank = Ranks.admin,
allowed_by_server = true
},
get_player_id

View File

@ -143,8 +143,13 @@ return {
light_gray = {r = 211, g = 211, b = 211},
gainsboro = {r = 220, g = 220, b = 220},
white_smoke = {r = 245, g = 245, b = 245},
white = {r = 255, g = 255, b = 255},
jailed = {r = 255, g = 255, b = 255},
probation = {r = 255, g = 255, b = 255},
guest = {r = 255, g = 255, b = 255},
auto_trusted = {r = 192, g = 192, b = 192},
regular = {r = 0.155, g = 0.540, b = 0.898},
donator = {r = 172.6, g = 70.2, b = 215.8},
admin = {r = 0.093, g = 0.768, b = 0.172}
admin = {r = 0.093, g = 0.768, b = 0.172},
donator = {r = 172.6, g = 70.2, b = 215.8}
}

View File

@ -0,0 +1,4 @@
return {
rank = 0x1,
train = 0x2
}

View File

@ -1,10 +0,0 @@
local Module = {}
Module.donator_perk_flags = {
rank = 0x1,
train = 0x2
}
Module.donators = {}
return Module

7
resources/ranks.lua Normal file
View File

@ -0,0 +1,7 @@
return {
probation = -1,
guest = 0,
auto_trusted = 1,
regular = 2,
admin = 3,
}

View File

@ -1,13 +1,17 @@
require 'utils.table'
local UserGroups = require 'features.user_groups'
local Rank = require 'features.rank_system'
local Event = require 'utils.event'
local Game = require 'utils.game'
local Donator = require 'features.donator'
local Ranks = require 'resources.ranks'
local insert = table.insert
local format = string.format
local next = next
local serialize = serpent.line
local match = string.match
local gmatch = string.gmatch
local get_rank_name = Rank.get_rank_name
local Command = {}
@ -29,13 +33,13 @@ local option_names = {
['description'] = 'A description of the command',
['arguments'] = 'A table of arguments, example: {"foo", "bar"} would map the first 2 arguments to foo and bar',
['default_values'] = 'A default value for a given argument when omitted, example: {bar = false}',
['regular_only'] = 'Set this to true if only regulars may execute this command',
['admin_only'] = 'Set this to true if only admins may execute this command',
['required_rank'] = 'Set this to determins what rank is required to execute a command',
['donator_only'] = 'Set this to true if only donators may execute this command',
['debug_only'] = 'Set this to true if it should be registered when _DEBUG is true',
['cheat_only'] = 'Set this to true if it should be registered when _CHEATS is true',
['allowed_by_server'] = 'Set to true if the server (host) may execute this command',
['allowed_by_player'] = 'Set to false to disable players from executing this command',
['log_command'] = 'Set to true to log commands. Always true when admin_only is enabled',
['log_command'] = 'Set to true to log commands. Always true when admin is required',
['capture_excess_arguments'] = 'Allows the last argument to be the remaining text in the command',
['custom_help_text'] = 'Sets a custom help text to override the auto-generated help',
}
@ -62,8 +66,8 @@ end
--- description = 'A description of the command',
--- arguments = {'foo', 'bar'}, -- maps arguments to these names in the given sequence
--- default_values = {bar = false}, -- gives a default value to 'bar' when omitted
--- regular_only = true, -- defaults to false
--- admin_only = true, -- defaults to false
--- required_rank = Ranks.regular, -- defaults to Ranks.guest
--- donator_only = true, -- defaults to false
--- debug_only = true, -- registers the command if _DEBUG is set to true, defaults to false
--- cheat_only = true, -- registers the command if _CHEATS is set to true, defaults to false
--- allowed_by_server = false, -- lets the server execute this, defaults to false
@ -84,15 +88,15 @@ function Command.add(command_name, options, callback)
local description = options.description or '[Undocumented command]'
local arguments = options.arguments or {}
local default_values = options.default_values or {}
local regular_only = options.regular_only or false
local admin_only = options.admin_only or false
local required_rank = options.required_rank or Ranks.guest
local donator_only = options.donator_only or false
local debug_only = options.debug_only or false
local cheat_only = options.cheat_only or false
local capture_excess_arguments = options.capture_excess_arguments or false
local custom_help_text = options.custom_help_text or false
local allowed_by_server = options.allowed_by_server or false
local allowed_by_player = options.allowed_by_player
local log_command = options.log_command or options.admin_only or false
local log_command = options.log_command or (required_rank >= Ranks.admin) or false
local argument_list_size = table_size(arguments)
local argument_list = ''
@ -129,11 +133,11 @@ function Command.add(command_name, options, callback)
local extra = ''
if allowed_by_server and not allowed_by_player then
extra = ' (Server Only)'
elseif allowed_by_player and admin_only then
extra = ' (Admin Only)'
elseif allowed_by_player and regular_only then
extra = ' (Regulars Only)'
extra = ' (Server only)'
elseif allowed_by_player and (required_rank > Ranks.guest) then
extra = format(' (Rank %s or above only)', get_rank_name(required_rank))
elseif allowed_by_player and donator_only then
extra = ' (Donator only)'
end
local help_text = custom_help_text or argument_list .. description .. extra
@ -157,13 +161,13 @@ function Command.add(command_name, options, callback)
return
end
if admin_only and not player.admin then
print(format("The command '%s' requires admin status to be be executed.", command_name))
if Rank.less_than(player_name, required_rank) then
print(format("The command '%s' requires %s rank or higher to be be executed.", command_name, get_rank_name(required_rank)))
return
end
if regular_only and not UserGroups.is_regular(player_name) and not player.admin then
print(format("The command '%s' is not available to guests.", command_name))
if donator_only and not Donator.is_donator(player_name) then
print(format("The command '%s' is only allowed for donators.", command_name))
return
end
end
@ -171,7 +175,7 @@ function Command.add(command_name, options, callback)
local named_arguments = {}
local from_command = {}
local raw_parameter_index = 1
for param in string.gmatch(command.parameter or '', '%S+') do
for param in gmatch(command.parameter or '', '%S+') do
if capture_excess_arguments and raw_parameter_index == argument_list_size then
if not from_command[raw_parameter_index] then
from_command[raw_parameter_index] = param
@ -217,7 +221,7 @@ function Command.add(command_name, options, callback)
end
if log_command then
log(format('[%s Command] %s, used: %s %s', admin_only and 'Admin' or 'Player', player_name, command_name, serialize(named_arguments)))
log(format('[%s Command] %s, used: %s %s', (options.required_rank >= Ranks.admin) and 'Admin' or 'Player', player_name, command_name, serialize(named_arguments)))
end
local success, error = pcall(function ()

View File

@ -2,6 +2,7 @@ local Global = require 'utils.global'
local Game = require 'utils.game'
local PlayerStats = require 'features.player_stats'
local Command = require 'utils.command'
local Ranks = require 'resources.ranks'
local format = string.format
local abs = math.abs
@ -110,7 +111,7 @@ Command.add(
description = 'Gives a reward to a target player (removes if quantity is negative)',
arguments = {'target', 'quantity', 'reason'},
default_values = {reason = false},
admin_only = true,
required_rank = Ranks.admin,
capture_excess_arguments = true,
allowed_by_server = true,
allowed_by_player = true