mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 10:11:09 +00:00
SQL-Based Player Ranks and Player Ranks Subsystem (#23099)
* Initial draft, most of the stuff is implemented, not really tested or cleaned up yet * Refactors the handling into a datum-based approach, for more abstraction * Added migration, properly hooked up the verb to the new system * Removed some more dead code * Fixes some missing stuff from the .dme because VSC is stupid sometimes with merge conflicts * Fixes the schema * Wow I was really getting tired huh * A fool, I say, a fool! * I hate lists of lists I hate lists of lists I hate lists of lists * I somehow missed this one twice. TWICE! * This won't actually work if it's defaulting to true, lmao * Makes it not log stuff if the adding or removing of players is unsuccessful * Adds a way to update all of the unlock_contents for preferences datums once the donator list is initialized * Runs update_prefs_unlock_content on mob Login() (hopefully this helps) * Fixes the bajillion of runtimes caused by my dumb ass trying to make some client calls on ckeys * Man I was really tired that day * I had this ready for three hours and forgot to push it
This commit is contained in:
82
SQL/skyrat_schema.sql
Normal file
82
SQL/skyrat_schema.sql
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||||
|
/*!40101 SET NAMES utf8 */;
|
||||||
|
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||||
|
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||||
|
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||||
|
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||||
|
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||||
|
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `player_rank`.
|
||||||
|
--
|
||||||
|
DROP TABLE IF EXISTS `player_rank`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
|
CREATE TABLE `player_rank` (
|
||||||
|
`ckey` VARCHAR(32) NOT NULL,
|
||||||
|
`rank` VARCHAR(12) NOT NULL,
|
||||||
|
`admin_ckey` VARCHAR(32) NOT NULL,
|
||||||
|
`date_added` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`last_modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
`deleted` BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
PRIMARY KEY (`ckey`, `rank`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `player_rank_log`.
|
||||||
|
--
|
||||||
|
DROP TABLE IF EXISTS `player_rank_log`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
|
CREATE TABLE `player_rank_log` (
|
||||||
|
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`ckey` VARCHAR(32) NOT NULL,
|
||||||
|
`rank` VARCHAR(12) NOT NULL,
|
||||||
|
`admin_ckey` VARCHAR(32) NOT NULL,
|
||||||
|
`action` ENUM('ADDED', 'REMOVED') NOT NULL DEFAULT 'ADDED',
|
||||||
|
`date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Trigger structure for trigger `log_player_rank_additions`.
|
||||||
|
--
|
||||||
|
DROP TRIGGER IF EXISTS `log_player_rank_additions`;
|
||||||
|
CREATE TRIGGER `log_player_rank_additions`
|
||||||
|
AFTER INSERT ON `player_rank`
|
||||||
|
FOR EACH ROW
|
||||||
|
INSERT INTO player_rank_log (ckey, rank, admin_ckey, `action`) VALUES (NEW.ckey, NEW.rank, NEW.admin_ckey, 'ADDED');
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Trigger structure for trigger `log_player_rank_changes`.
|
||||||
|
--
|
||||||
|
DROP TRIGGER IF EXISTS `log_player_rank_changes`;
|
||||||
|
DELIMITER //
|
||||||
|
CREATE TRIGGER `log_player_rank_changes`
|
||||||
|
AFTER UPDATE ON `player_rank`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
IF NEW.deleted = 1 THEN
|
||||||
|
INSERT INTO player_rank_log (ckey, rank, admin_ckey, `action`) VALUES (NEW.ckey, NEW.rank, NEW.admin_ckey, 'REMOVED');
|
||||||
|
ELSE
|
||||||
|
INSERT INTO player_rank_log (ckey, rank, admin_ckey, `action`) VALUES (NEW.ckey, NEW.rank, NEW.admin_ckey, 'ADDED');
|
||||||
|
END IF;
|
||||||
|
END; //
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
|
||||||
|
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||||
|
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||||
|
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||||
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
@@ -134,6 +134,7 @@
|
|||||||
#define INIT_ORDER_BLACKBOX 94
|
#define INIT_ORDER_BLACKBOX 94
|
||||||
#define INIT_ORDER_SERVER_MAINT 93
|
#define INIT_ORDER_SERVER_MAINT 93
|
||||||
#define INIT_ORDER_INPUT 85
|
#define INIT_ORDER_INPUT 85
|
||||||
|
#define INIT_ORDER_PLAYER_RANKS 84 // SKYRAT EDIT - Player Ranks Subsystem
|
||||||
#define INIT_ORDER_SOUNDS 83
|
#define INIT_ORDER_SOUNDS 83
|
||||||
#define INIT_ORDER_INSTRUMENTS 82
|
#define INIT_ORDER_INSTRUMENTS 82
|
||||||
#define INIT_ORDER_GREYSCALE 81
|
#define INIT_ORDER_GREYSCALE 81
|
||||||
|
|||||||
@@ -940,7 +940,7 @@ SUBSYSTEM_DEF(job)
|
|||||||
return JOB_UNAVAILABLE_AGE
|
return JOB_UNAVAILABLE_AGE
|
||||||
|
|
||||||
//SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
|
//SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
|
||||||
if(possible_job.veteran_only && !is_veteran_player(player.client))
|
if(possible_job.veteran_only && !SSplayer_ranks.is_veteran(player.client))
|
||||||
JobDebug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_NOT_VETERAN)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]")
|
JobDebug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_NOT_VETERAN)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]")
|
||||||
return JOB_NOT_VETERAN
|
return JOB_NOT_VETERAN
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ SUBSYSTEM_DEF(ticker)
|
|||||||
var/discord_alerted = FALSE //SKYRAT EDIT - DISCORD PING SPAM PREVENTION
|
var/discord_alerted = FALSE //SKYRAT EDIT - DISCORD PING SPAM PREVENTION
|
||||||
|
|
||||||
/datum/controller/subsystem/ticker/Initialize()
|
/datum/controller/subsystem/ticker/Initialize()
|
||||||
load_mentors() // SKYRAT EDIT ADDITION - MENTORS STOPPED LOADING AUTOMATICALLY DUE TO RECENT TG CHANGES
|
|
||||||
var/list/byond_sound_formats = list(
|
var/list/byond_sound_formats = list(
|
||||||
"mid" = TRUE,
|
"mid" = TRUE,
|
||||||
"midi" = TRUE,
|
"midi" = TRUE,
|
||||||
|
|||||||
@@ -265,7 +265,8 @@ GLOBAL_PROTECT(admin_verbs_possess)
|
|||||||
/// SKYRAT EDIT BEGIN - Player Rank Manager - ORIGINAL: GLOBAL_LIST_INIT(admin_verbs_permissions, list(/client/proc/edit_admin_permissions))
|
/// SKYRAT EDIT BEGIN - Player Rank Manager - ORIGINAL: GLOBAL_LIST_INIT(admin_verbs_permissions, list(/client/proc/edit_admin_permissions))
|
||||||
GLOBAL_LIST_INIT(admin_verbs_permissions, list(
|
GLOBAL_LIST_INIT(admin_verbs_permissions, list(
|
||||||
/client/proc/edit_admin_permissions,
|
/client/proc/edit_admin_permissions,
|
||||||
/client/proc/manage_player_ranks
|
/client/proc/manage_player_ranks,
|
||||||
|
/client/proc/migrate_player_ranks,
|
||||||
))
|
))
|
||||||
/// SKYRAT EDIT END
|
/// SKYRAT EDIT END
|
||||||
GLOBAL_PROTECT(admin_verbs_permissions)
|
GLOBAL_PROTECT(admin_verbs_permissions)
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
/datum/preference_middleware/jobs/get_ui_static_data(mob/user)
|
/datum/preference_middleware/jobs/get_ui_static_data(mob/user)
|
||||||
var/list/data = list()
|
var/list/data = list()
|
||||||
// SKYRAT EDIT
|
// SKYRAT EDIT
|
||||||
if(is_veteran_player(user.client))
|
if(SSplayer_ranks.is_veteran(user.client))
|
||||||
data["is_veteran"] = TRUE
|
data["is_veteran"] = TRUE
|
||||||
// SKYRAT EDIT END
|
// SKYRAT EDIT END
|
||||||
var/list/required_job_playtime = get_required_job_playtime(user)
|
var/list/required_job_playtime = get_required_job_playtime(user)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
//SKYRAT EDIT ADDITION
|
//SKYRAT EDIT ADDITION
|
||||||
var/list/quirks = SSquirks.get_quirks()
|
var/list/quirks = SSquirks.get_quirks()
|
||||||
var/datum/quirk/quirk = quirks[quirk_name]
|
var/datum/quirk/quirk = quirks[quirk_name]
|
||||||
if(initial(quirk.veteran_only) && !is_veteran_player(preferences?.parent))
|
if(initial(quirk.veteran_only) && !SSplayer_ranks.is_veteran(preferences?.parent))
|
||||||
return FALSE
|
return FALSE
|
||||||
//SKYRAT EDIT END
|
//SKYRAT EDIT END
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
//SKYRAT EDIT ADDITION
|
//SKYRAT EDIT ADDITION
|
||||||
var/list/quirks = SSquirks.get_quirks()
|
var/list/quirks = SSquirks.get_quirks()
|
||||||
var/datum/quirk/quirk_datum = quirks[quirk]
|
var/datum/quirk/quirk_datum = quirks[quirk]
|
||||||
if(initial(quirk_datum.veteran_only) && !is_veteran_player(preferences?.parent))
|
if(initial(quirk_datum.veteran_only) && !SSplayer_ranks.is_veteran(preferences?.parent))
|
||||||
preferences.all_quirks -= quirk
|
preferences.all_quirks -= quirk
|
||||||
continue
|
continue
|
||||||
//SKYRAT EDIT END
|
//SKYRAT EDIT END
|
||||||
|
|||||||
@@ -165,7 +165,7 @@
|
|||||||
return JOB_UNAVAILABLE_LANGUAGE
|
return JOB_UNAVAILABLE_LANGUAGE
|
||||||
if(job.has_banned_quirk(client.prefs))
|
if(job.has_banned_quirk(client.prefs))
|
||||||
return JOB_UNAVAILABLE_QUIRK
|
return JOB_UNAVAILABLE_QUIRK
|
||||||
if(job.veteran_only && !is_veteran_player(client))
|
if(job.veteran_only && !SSplayer_ranks.is_veteran(client))
|
||||||
return JOB_NOT_VETERAN
|
return JOB_NOT_VETERAN
|
||||||
if(job.has_banned_species(client.prefs))
|
if(job.has_banned_species(client.prefs))
|
||||||
return JOB_UNAVAILABLE_SPECIES
|
return JOB_UNAVAILABLE_SPECIES
|
||||||
|
|||||||
@@ -25,11 +25,6 @@ PLAYER_SOFT_CAP 0
|
|||||||
## The non-IC name we send to OOC and adminsay.
|
## The non-IC name we send to OOC and adminsay.
|
||||||
#CROSS_SERVER_NAME
|
#CROSS_SERVER_NAME
|
||||||
|
|
||||||
## Comment this out if you want to use the SQL based mentor system, the legacy system uses mentors.txt.
|
|
||||||
## You need to set up your database to use the SQL based system.
|
|
||||||
## This flag is automatically enabled if SQL_ENABLED isn't
|
|
||||||
## But currently the SQL system is not implemented and it'll read from mentors.txt nonetheless
|
|
||||||
MENTOR_LEGACY_SYSTEM
|
|
||||||
|
|
||||||
ALERT_AMBER_UPTO A major security emergency has developed. Security staff may have weapons unholstered at all times. Random searches are allowed and advised.
|
ALERT_AMBER_UPTO A major security emergency has developed. Security staff may have weapons unholstered at all times. Random searches are allowed and advised.
|
||||||
ALERT_AMBER_DOWNTO A major security emergency is still underway. Non-security personnel are required to obey all relevant instructions from security staff.
|
ALERT_AMBER_DOWNTO A major security emergency is still underway. Non-security personnel are required to obey all relevant instructions from security staff.
|
||||||
@@ -141,3 +136,10 @@ SIZE_COLLAR_MINIMUM 15
|
|||||||
## Don't ever set this to 0, just disable MIN_FLAVOR_TEXT
|
## Don't ever set this to 0, just disable MIN_FLAVOR_TEXT
|
||||||
#FLAVOR_TEXT_CHARACTER_REQUIREMENT 150
|
#FLAVOR_TEXT_CHARACTER_REQUIREMENT 150
|
||||||
|
|
||||||
|
## Comment these out if you want to use the SQL-based player rank system, the
|
||||||
|
## legacy system uses the .txt files in the data folder instead.
|
||||||
|
## You need to set up your database to use the SQL-based system.
|
||||||
|
## These flags are automatically enabled if SQL_ENABLED isn't.
|
||||||
|
DONATOR_LEGACY_SYSTEM
|
||||||
|
MENTOR_LEGACY_SYSTEM
|
||||||
|
VETERAN_LEGACY_SYSTEM
|
||||||
|
|||||||
@@ -49,3 +49,18 @@
|
|||||||
// NEVER set this value to 0!!
|
// NEVER set this value to 0!!
|
||||||
/datum/config_entry/number/flavor_text_character_requirement
|
/datum/config_entry/number/flavor_text_character_requirement
|
||||||
default = 150
|
default = 150
|
||||||
|
|
||||||
|
/// Defines whether or not mentors can see ckeys alongside mobnames.
|
||||||
|
/datum/config_entry/flag/mentors_mobname_only
|
||||||
|
|
||||||
|
/// Defines whether the server uses the legacy donator system with donators.txt or the SQL system.
|
||||||
|
/datum/config_entry/flag/donator_legacy_system
|
||||||
|
protection = CONFIG_ENTRY_LOCKED
|
||||||
|
|
||||||
|
/// Defines whether the server uses the legacy mentor system with mentors.txt or the SQL system.
|
||||||
|
/datum/config_entry/flag/mentor_legacy_system
|
||||||
|
protection = CONFIG_ENTRY_LOCKED
|
||||||
|
|
||||||
|
/// Defines whether the server uses the legacy veteran system with veteran_players.txt or the SQL system.
|
||||||
|
/datum/config_entry/flag/veteran_legacy_system
|
||||||
|
protection = CONFIG_ENTRY_LOCKED
|
||||||
|
|||||||
@@ -51,6 +51,6 @@
|
|||||||
/datum/preference/text/headshot/is_accessible(datum/preferences/preferences)
|
/datum/preference/text/headshot/is_accessible(datum/preferences/preferences)
|
||||||
if(isnull(usr)) // Joining at roundstart
|
if(isnull(usr)) // Joining at roundstart
|
||||||
return ..()
|
return ..()
|
||||||
if(!is_veteran_player(usr?.client) && !GLOB.donator_list[usr?.ckey] && !is_admin(usr?.client))
|
if(!SSplayer_ranks.is_veteran(usr?.client) && !GLOB.donator_list[usr?.ckey] && !is_admin(usr?.client))
|
||||||
return FALSE
|
return FALSE
|
||||||
return ..()
|
return ..()
|
||||||
|
|||||||
10
modular_skyrat/master_files/code/modules/mob/login.dm
Normal file
10
modular_skyrat/master_files/code/modules/mob/login.dm
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/mob/Login()
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
if(!.)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(SSplayer_ranks.initialized)
|
||||||
|
SSplayer_ranks.update_prefs_unlock_content(client?.prefs)
|
||||||
|
|
||||||
|
return TRUE
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
/// The defines for the appropriate config files
|
|
||||||
#define SKYRAT_DONATOR_CONFIG_FILE "[global.config.directory]/skyrat/donators.txt"
|
|
||||||
#define SKYRAT_MENTOR_CONFIG_FILE "[global.config.directory]/skyrat/mentors.txt"
|
|
||||||
#define SKYRAT_VETERAN_CONFIG_FILE "[global.config.directory]/skyrat/veteran_players.txt"
|
|
||||||
|
|
||||||
/// The list of the available special player ranks
|
|
||||||
#define SKYRAT_PLAYER_RANKS list("Donator", "Mentor", "Veteran")
|
|
||||||
|
|
||||||
/client/proc/manage_player_ranks()
|
|
||||||
set category = "Admin"
|
|
||||||
set name = "Manage Player Ranks"
|
|
||||||
set desc = "Manage who has the special player ranks while the server is running."
|
|
||||||
|
|
||||||
if(!check_rights(R_PERMISSIONS))
|
|
||||||
return
|
|
||||||
usr.client?.holder.manage_player_ranks()
|
|
||||||
|
|
||||||
/// Proc for admins to change people's "player" ranks (donator, mentor, veteran, etc.)
|
|
||||||
/datum/admins/proc/manage_player_ranks()
|
|
||||||
if(!check_rights(R_PERMISSIONS))
|
|
||||||
return
|
|
||||||
|
|
||||||
var/choice = tgui_alert(usr, "Which rank would you like to manage?", "Manage Player Ranks", SKYRAT_PLAYER_RANKS)
|
|
||||||
if(!choice || !(choice in SKYRAT_PLAYER_RANKS))
|
|
||||||
return
|
|
||||||
|
|
||||||
manage_player_rank_in_group(choice)
|
|
||||||
|
|
||||||
/// Proc that helps a bit with repetition, basically an extension of `manage_player_ranks()`
|
|
||||||
/datum/admins/proc/manage_player_rank_in_group(group)
|
|
||||||
if(!(group in SKYRAT_PLAYER_RANKS))
|
|
||||||
CRASH("[key_name(usr)] attempted to add someone to an invalid \"[group]\" group.")
|
|
||||||
|
|
||||||
var/group_title = lowertext(group)
|
|
||||||
|
|
||||||
var/list/choices = list("Add", "Remove")
|
|
||||||
switch(tgui_alert(usr, "What would you like to do?", "Manage [group]s", choices))
|
|
||||||
if("Add")
|
|
||||||
var/name = input(usr, "Please enter the CKEY (case-insensitive) of the person you would like to make a [group_title]:", "Add a [group_title]") as null|text
|
|
||||||
if(!name)
|
|
||||||
return
|
|
||||||
|
|
||||||
var/player_to_be = ckey(name)
|
|
||||||
if(!player_to_be)
|
|
||||||
to_chat(usr, span_warning("\"[name]\" is not a valid CKEY."))
|
|
||||||
return
|
|
||||||
|
|
||||||
switch(group)
|
|
||||||
if ("Donator")
|
|
||||||
for(var/a_donator as anything in GLOB.donator_list)
|
|
||||||
if(player_to_be == a_donator)
|
|
||||||
to_chat(usr, span_warning("\"[player_to_be]\" is already a [group_title]!"))
|
|
||||||
return
|
|
||||||
// Now that we know that the ckey is valid and they're not already apart of that group, let's add them to it!
|
|
||||||
GLOB.donator_list[player_to_be] = TRUE
|
|
||||||
text2file(player_to_be, SKYRAT_DONATOR_CONFIG_FILE)
|
|
||||||
|
|
||||||
if("Mentor")
|
|
||||||
for(var/a_mentor as anything in GLOB.mentor_datums)
|
|
||||||
if(player_to_be == a_mentor)
|
|
||||||
to_chat(usr, span_warning("\"[player_to_be]\" is already a [group_title]!"))
|
|
||||||
return
|
|
||||||
// Now that we know that the ckey is valid and they're not already apart of that group, let's add them to it!
|
|
||||||
new /datum/mentors(player_to_be)
|
|
||||||
text2file(player_to_be, SKYRAT_MENTOR_CONFIG_FILE)
|
|
||||||
|
|
||||||
if ("Veteran")
|
|
||||||
for(var/a_veteran as anything in GLOB.veteran_players)
|
|
||||||
if(player_to_be == a_veteran)
|
|
||||||
to_chat(usr, span_warning("\"[player_to_be]\" is already a [group_title]!"))
|
|
||||||
return
|
|
||||||
// Now that we know that the ckey is valid and they're not already apart of that group, let's add them to it!
|
|
||||||
GLOB.veteran_players[player_to_be] = TRUE
|
|
||||||
text2file(player_to_be, SKYRAT_VETERAN_CONFIG_FILE)
|
|
||||||
|
|
||||||
else
|
|
||||||
return
|
|
||||||
|
|
||||||
message_admins("[key_name(usr)] has granted [group_title] status to [player_to_be].")
|
|
||||||
log_admin_private("[key_name(usr)] has granted [group_title] status to [player_to_be].")
|
|
||||||
|
|
||||||
|
|
||||||
if("Remove")
|
|
||||||
var/name = input(usr, "Please enter the CKEY (case-insensitive) of the person you would like to no longer be a [group_title]:", "Remove a [group_title]") as null|text
|
|
||||||
if(!name)
|
|
||||||
return
|
|
||||||
|
|
||||||
var/player_that_was = ckey(name)
|
|
||||||
if(!player_that_was)
|
|
||||||
to_chat(usr, span_warning("\"[name]\" is not a valid CKEY."))
|
|
||||||
return
|
|
||||||
|
|
||||||
var/changes = FALSE
|
|
||||||
switch(group)
|
|
||||||
if ("Donator")
|
|
||||||
for(var/a_donator as anything in GLOB.donator_list)
|
|
||||||
if(player_that_was == a_donator)
|
|
||||||
GLOB.donator_list -= player_that_was
|
|
||||||
changes = TRUE
|
|
||||||
if(!changes)
|
|
||||||
to_chat(usr, span_warning("\"[player_that_was]\" was already not a [group_title]."))
|
|
||||||
return
|
|
||||||
save_donators()
|
|
||||||
|
|
||||||
if("Mentor")
|
|
||||||
for(var/a_mentor as anything in GLOB.mentor_datums)
|
|
||||||
if(player_that_was == a_mentor)
|
|
||||||
var/datum/mentors/mentor_datum = GLOB.mentor_datums[a_mentor]
|
|
||||||
mentor_datum.remove_mentor()
|
|
||||||
changes = TRUE
|
|
||||||
if(!changes)
|
|
||||||
to_chat(usr, span_warning("\"[player_that_was]\" was already not a [group_title]."))
|
|
||||||
save_mentors()
|
|
||||||
|
|
||||||
if("Veteran")
|
|
||||||
for(var/a_veteran as anything in GLOB.veteran_players)
|
|
||||||
if(player_that_was == a_veteran)
|
|
||||||
GLOB.veteran_players -= player_that_was
|
|
||||||
changes = TRUE
|
|
||||||
if(!changes)
|
|
||||||
to_chat(usr, span_warning("\"[player_that_was]\" was already not a [group_title]."))
|
|
||||||
return
|
|
||||||
save_veteran_players()
|
|
||||||
|
|
||||||
else
|
|
||||||
return
|
|
||||||
message_admins("[key_name(usr)] has revoked [group_title] status from [player_that_was].")
|
|
||||||
log_admin_private("[key_name(usr)] has revoked [group_title] status from [player_that_was].")
|
|
||||||
|
|
||||||
else
|
|
||||||
return
|
|
||||||
|
|
||||||
#undef SKYRAT_DONATOR_CONFIG_FILE
|
|
||||||
#undef SKYRAT_MENTOR_CONFIG_FILE
|
|
||||||
#undef SKYRAT_VETERAN_CONFIG_FILE
|
|
||||||
#undef SKYRAT_PLAYER_RANKS
|
|
||||||
121
modular_skyrat/modules/admin/code/player_ranks.dm
Normal file
121
modular_skyrat/modules/admin/code/player_ranks.dm
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/// The list of the available special player ranks
|
||||||
|
#define SKYRAT_PLAYER_RANKS list("Donator", "Mentor", "Veteran")
|
||||||
|
|
||||||
|
/client/proc/manage_player_ranks()
|
||||||
|
set category = "Admin"
|
||||||
|
set name = "Manage Player Ranks"
|
||||||
|
set desc = "Manage who has the special player ranks while the server is running."
|
||||||
|
|
||||||
|
if(!check_rights(R_PERMISSIONS))
|
||||||
|
return
|
||||||
|
|
||||||
|
usr.client?.holder.manage_player_ranks()
|
||||||
|
|
||||||
|
/// Proc for admins to change people's "player" ranks (donator, mentor, veteran, etc.)
|
||||||
|
/datum/admins/proc/manage_player_ranks()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!check_rights(R_PERMISSIONS))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/choice = tgui_alert(usr, "Which rank would you like to manage?", "Manage Player Ranks", SKYRAT_PLAYER_RANKS)
|
||||||
|
if(!choice || !(choice in SKYRAT_PLAYER_RANKS))
|
||||||
|
return
|
||||||
|
|
||||||
|
manage_player_rank_in_group(choice)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles managing player ranks based on the name of the group that was chosen.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * group - The title of the player rank that was chosen to be managed.
|
||||||
|
*/
|
||||||
|
/datum/admins/proc/manage_player_rank_in_group(group)
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!(group in SKYRAT_PLAYER_RANKS))
|
||||||
|
CRASH("[key_name(usr)] attempted to add someone to an invalid \"[group]\" group.")
|
||||||
|
|
||||||
|
var/group_title = lowertext(group)
|
||||||
|
|
||||||
|
var/list/choices = list("Add", "Remove")
|
||||||
|
switch(tgui_alert(usr, "What would you like to do?", "Manage [group]s", choices))
|
||||||
|
if("Add")
|
||||||
|
var/name = input(usr, "Please enter the CKEY (case-insensitive) of the person you would like to make a [group_title]:", "Add a [group_title]") as null|text
|
||||||
|
if(!name)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/player_to_be = ckey(name)
|
||||||
|
if(!player_to_be)
|
||||||
|
to_chat(usr, span_warning("\"[name]\" is not a valid CKEY."))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/success = SSplayer_ranks.add_player_to_group(usr.client, player_to_be, group_title)
|
||||||
|
|
||||||
|
if(!success)
|
||||||
|
return
|
||||||
|
|
||||||
|
message_admins("[key_name(usr)] has granted [group_title] status to [player_to_be].")
|
||||||
|
log_admin_private("[key_name(usr)] has granted [group_title] status to [player_to_be].")
|
||||||
|
|
||||||
|
|
||||||
|
if("Remove")
|
||||||
|
var/name = input(usr, "Please enter the CKEY (case-insensitive) of the person you would like to no longer be a [group_title]:", "Remove a [group_title]") as null|text
|
||||||
|
if(!name)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/player_that_was = ckey(name)
|
||||||
|
if(!player_that_was)
|
||||||
|
to_chat(usr, span_warning("\"[name]\" is not a valid CKEY."))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/success = SSplayer_ranks.remove_player_from_group(usr.client, player_that_was, group_title)
|
||||||
|
|
||||||
|
if(!success)
|
||||||
|
return
|
||||||
|
|
||||||
|
message_admins("[key_name(usr)] has revoked [group_title] status from [player_that_was].")
|
||||||
|
log_admin_private("[key_name(usr)] has revoked [group_title] status from [player_that_was].")
|
||||||
|
|
||||||
|
else
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/client/proc/migrate_player_ranks()
|
||||||
|
set category = "Debug"
|
||||||
|
set name = "Migrate Player Ranks"
|
||||||
|
set desc = "Individually migrate the various player ranks from their legacy system to the SQL-based one."
|
||||||
|
|
||||||
|
if(!check_rights(R_PERMISSIONS | R_DEBUG | R_SERVER))
|
||||||
|
return
|
||||||
|
|
||||||
|
usr.client?.holder.migrate_player_ranks()
|
||||||
|
|
||||||
|
|
||||||
|
/datum/admins/proc/migrate_player_ranks()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!check_rights(R_PERMISSIONS | R_DEBUG | R_SERVER))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!CONFIG_GET(flag/sql_enabled))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/choice = tgui_alert(usr, "Which rank would you like to migrate?", "Migrate Player Ranks", SKYRAT_PLAYER_RANKS)
|
||||||
|
if(!choice || !(choice in SKYRAT_PLAYER_RANKS))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(tgui_alert(usr, "Are you sure that you would like to migrate [choice]s to the SQL-based system?", "Migrate Player Ranks", list("Yes", "No")) != "Yes")
|
||||||
|
return
|
||||||
|
|
||||||
|
log_admin("[key_name(usr)] is migrating the [choice] player rank from its legacy system to the SQL-based one.")
|
||||||
|
SSplayer_ranks.migrate_player_rank_to_sql(usr.client, choice)
|
||||||
|
|
||||||
|
|
||||||
|
#undef SKYRAT_PLAYER_RANKS
|
||||||
@@ -6,9 +6,6 @@
|
|||||||
populate_total_ui_len_by_block()
|
populate_total_ui_len_by_block()
|
||||||
populate_total_uf_len_by_block()
|
populate_total_uf_len_by_block()
|
||||||
make_augment_references()
|
make_augment_references()
|
||||||
//We're loading donators here because it's the least intrusive way modularly
|
|
||||||
load_donators()
|
|
||||||
load_veteran_players()
|
|
||||||
|
|
||||||
/proc/make_sprite_accessory_references()
|
/proc/make_sprite_accessory_references()
|
||||||
// Here we build the global list for all accessories
|
// Here we build the global list for all accessories
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
#define DONATORLISTFILE "[global.config.directory]/skyrat/donators.txt"
|
|
||||||
|
|
||||||
GLOBAL_LIST(donator_list)
|
|
||||||
|
|
||||||
/proc/load_donators()
|
|
||||||
GLOB.donator_list = list()
|
|
||||||
for(var/line in world.file2list(DONATORLISTFILE))
|
|
||||||
if(!line)
|
|
||||||
continue
|
|
||||||
if(findtextEx(line,"#",1,2))
|
|
||||||
continue
|
|
||||||
GLOB.donator_list[ckey(line)] = TRUE //Associative so we can check it much faster
|
|
||||||
|
|
||||||
/proc/save_donators()
|
|
||||||
/// Yes, this is incredibly long, deal with it. It's to keep that cute little comment at the top.
|
|
||||||
var/donators = "###############################################################################################\n# List for people who support us! They get cool loadout items #\n# Case is not important for ckey. #\n###############################################################################################\n"
|
|
||||||
for(var/donator in GLOB.donator_list)
|
|
||||||
donators += donator + "\n"
|
|
||||||
rustg_file_write(donators, DONATORLISTFILE)
|
|
||||||
|
|
||||||
#undef DONATORLISTFILE
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
/client/Destroy()
|
/client/Destroy()
|
||||||
if(GLOB.mentors[src])
|
if(GLOB.mentors[src])
|
||||||
GLOB.mentors -= src
|
GLOB.mentors -= src
|
||||||
|
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/client/proc/mentor_client_procs(href_list)
|
/client/proc/mentor_client_procs(href_list)
|
||||||
@@ -29,17 +30,20 @@
|
|||||||
mentor_unfollow()
|
mentor_unfollow()
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/client/proc/mentor_datum_set(admin)
|
/client/proc/mentor_datum_set()
|
||||||
mentor_datum = GLOB.mentor_datums[ckey]
|
mentor_datum = GLOB.mentor_datums[ckey]
|
||||||
if(!mentor_datum && check_rights_for(src, R_ADMIN,0)) // admin with no mentor datum?let's fix that
|
if(!mentor_datum && is_admin(src)) // admin with no mentor datum? let's fix that
|
||||||
new /datum/mentors(ckey)
|
new /datum/mentors(ckey)
|
||||||
|
|
||||||
if(mentor_datum)
|
if(mentor_datum)
|
||||||
mentor_datum.owner = src
|
mentor_datum.owner = src
|
||||||
GLOB.mentors[src] = TRUE
|
GLOB.mentors[src] = TRUE
|
||||||
add_mentor_verbs()
|
add_mentor_verbs()
|
||||||
if(check_rights_for(src, R_ADMIN,0) && prefs.read_preference(/datum/preference/toggle/admin/auto_dementor))
|
|
||||||
|
if(check_rights_for(src, R_ADMIN) && prefs.read_preference(/datum/preference/toggle/admin/auto_dementor))
|
||||||
cmd_mentor_dementor()
|
cmd_mentor_dementor()
|
||||||
|
|
||||||
|
|
||||||
/client/proc/is_mentor() // admins are mentors too.
|
/client/proc/is_mentor() // admins are mentors too.
|
||||||
if(mentor_datum || check_rights_for(src, R_ADMIN,0))
|
if(mentor_datum || check_rights_for(src, R_ADMIN))
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
/datum/configuration
|
|
||||||
var/mentors_mobname_only = FALSE // Only display mob name to mentors in mentorhelps
|
|
||||||
var/mentor_legacy_system = FALSE // Whether to use the legacy mentor system (flat file) instead of SQL
|
|
||||||
|
|
||||||
/datum/config_entry/flag/mentors_mobname_only
|
|
||||||
|
|
||||||
/datum/config_entry/flag/mentor_legacy_system //Defines whether the server uses the legacy mentor system with mentors.txt or the SQL system
|
|
||||||
protection = CONFIG_ENTRY_LOCKED
|
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
#define SKYRAT_MENTOR_CONFIG_FILE "[global.config.directory]/skyrat/mentors.txt"
|
|
||||||
|
|
||||||
GLOBAL_LIST_EMPTY(mentor_datums)
|
GLOBAL_LIST_EMPTY(mentor_datums)
|
||||||
GLOBAL_PROTECT(mentor_datums)
|
GLOBAL_PROTECT(mentor_datums)
|
||||||
|
|
||||||
GLOBAL_VAR_INIT(mentor_href_token, GenerateToken())
|
GLOBAL_VAR_INIT(mentor_href_token, GenerateToken())
|
||||||
GLOBAL_PROTECT(mentor_href_token)
|
GLOBAL_PROTECT(mentor_href_token)
|
||||||
|
|
||||||
//#define SKYRAT_MENTOR_CONFIG_FILE "[global.config.directory]/skyrat/mentors.txt"
|
|
||||||
|
|
||||||
/datum/mentors
|
/datum/mentors
|
||||||
var/name = "someone's mentor datum"
|
var/name = "someone's mentor datum"
|
||||||
var/client/owner // the actual mentor, client type
|
var/client/owner // the actual mentor, client type
|
||||||
@@ -70,64 +66,7 @@ GLOBAL_PROTECT(mentor_href_token)
|
|||||||
/proc/MentorHrefToken(forceGlobal = FALSE)
|
/proc/MentorHrefToken(forceGlobal = FALSE)
|
||||||
return "mentor_token=[RawMentorHrefToken(forceGlobal)]"
|
return "mentor_token=[RawMentorHrefToken(forceGlobal)]"
|
||||||
|
|
||||||
/proc/load_mentors()
|
|
||||||
usr = null
|
|
||||||
GLOB.mentor_datums.Cut()
|
|
||||||
for(var/it as anything in GLOB.mentors)
|
|
||||||
var/client/C = it
|
|
||||||
C.remove_mentor_verbs()
|
|
||||||
C.mentor_datum = null
|
|
||||||
GLOB.mentors.Cut()
|
|
||||||
//if(CONFIG_GET(flag/mentor_legacy_system))//legacy
|
|
||||||
var/list/lines = world.file2list(SKYRAT_MENTOR_CONFIG_FILE)
|
|
||||||
for(var/line in lines)
|
|
||||||
if(!length(line))
|
|
||||||
continue
|
|
||||||
if(findtextEx(line, "#", 1, 2))
|
|
||||||
continue
|
|
||||||
new /datum/mentors(line)
|
|
||||||
/*else//Database
|
|
||||||
if(!SSdbcore.Connect())
|
|
||||||
log_world("Failed to connect to database in load_mentors(). Reverting to legacy system.")
|
|
||||||
WRITE_FILE(GLOB.world_game_log, "Failed to connect to database in load_mentors(). Reverting to legacy system.")
|
|
||||||
CONFIG_SET(flag/mentor_legacy_system, TRUE)
|
|
||||||
load_mentors()
|
|
||||||
return
|
|
||||||
var/datum/DBQuery/query_load_mentors = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("mentor")]")
|
|
||||||
if(!query_load_mentors.Execute())
|
|
||||||
return
|
|
||||||
while(query_load_mentors.NextRow())
|
|
||||||
var/ckey = ckey(query_load_mentors.item[1])
|
|
||||||
new /datum/mentors(ckey)*/
|
|
||||||
|
|
||||||
/// Proc to save the current mentor list into the config, overwriting it.
|
|
||||||
/proc/save_mentors()
|
|
||||||
usr = null
|
|
||||||
var/mentor_list = ""
|
|
||||||
|
|
||||||
// This whole mess is just to create a cache of all the mentors that were in the config already
|
|
||||||
// so that we don't add every admin to the list, which would be a pain to maintain afterwards.
|
|
||||||
var/list/existing_mentor_config = world.file2list(SKYRAT_MENTOR_CONFIG_FILE)
|
|
||||||
var/list/existing_mentors = list()
|
|
||||||
for(var/line in existing_mentor_config)
|
|
||||||
if(!length(line))
|
|
||||||
continue
|
|
||||||
if(findtextEx(line, "#", 1, 2))
|
|
||||||
continue
|
|
||||||
var/existing_mentor = ckey(line)
|
|
||||||
if(!existing_mentor)
|
|
||||||
continue
|
|
||||||
existing_mentors[existing_mentor] = TRUE
|
|
||||||
|
|
||||||
for(var/mentor as anything in GLOB.mentor_datums)
|
|
||||||
// We're doing this check to not add admins to the file, as explained above.
|
|
||||||
if(existing_mentors[mentor] == TRUE)
|
|
||||||
mentor_list += mentor + "\n"
|
|
||||||
rustg_file_write(mentor_list, SKYRAT_MENTOR_CONFIG_FILE)
|
|
||||||
|
|
||||||
|
|
||||||
// new client var: mentor_datum. Acts the same way holder does towards admin: it holds the mentor datum. if set, the guy's a mentor.
|
|
||||||
/client
|
/client
|
||||||
|
/// Acts the same way holder does towards admin: it holds the mentor datum. if set, the guy's a mentor.
|
||||||
var/datum/mentors/mentor_datum
|
var/datum/mentors/mentor_datum
|
||||||
|
|
||||||
#undef SKYRAT_MENTOR_CONFIG_FILE
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ GLOBAL_PROTECT(mentor_verbs)
|
|||||||
|
|
||||||
/client/proc/add_mentor_verbs()
|
/client/proc/add_mentor_verbs()
|
||||||
if(mentor_datum)
|
if(mentor_datum)
|
||||||
add_verb(src,GLOB.mentor_verbs)
|
add_verb(src, GLOB.mentor_verbs)
|
||||||
|
|
||||||
/client/proc/remove_mentor_verbs()
|
/client/proc/remove_mentor_verbs()
|
||||||
remove_verb(src,GLOB.mentor_verbs)
|
remove_verb(src, GLOB.mentor_verbs)
|
||||||
|
|||||||
@@ -0,0 +1,227 @@
|
|||||||
|
/// The index of the ckey in the items of a given row in a query for player ranks.
|
||||||
|
#define INDEX_CKEY 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This datum is intended to be used as a method of abstraction for the different
|
||||||
|
* ways that each player rank handles adding and removing players from their global
|
||||||
|
* lists, as well as handling the legacy adding, removing, loading and saving of
|
||||||
|
* said lists.
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller
|
||||||
|
/// The name of the player rank in the database.
|
||||||
|
/// This **NEEDS** to be set by subtypes, otherwise you WILL run into severe
|
||||||
|
/// issues.
|
||||||
|
var/rank_title = null
|
||||||
|
/// The path to the legacy file holding all of the players that have this rank.
|
||||||
|
/// Should be set in `New()`, since it has a non-constant compile-time value.
|
||||||
|
var/legacy_file_path = null
|
||||||
|
/// The header for the legacy file, if any.
|
||||||
|
/// Leave as `""` if you don't have one.
|
||||||
|
var/legacy_file_header = ""
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/vv_edit_var(var_name, var_value)
|
||||||
|
// No touching the controller's vars, treat these as protected config.
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles adding this rank to a player by their ckey. This is only intended to
|
||||||
|
* be used for handling the in-game portion of adding this rank, and not to
|
||||||
|
* save this change anywhere. That should be handled by the caller.
|
||||||
|
*
|
||||||
|
* DO NOT FORGET TO ADD A `IsAdminAdvancedProcCall()` CHECK SO THAT ADMINS
|
||||||
|
* CAN'T JUST USE THAT TO SKIP PERMISSION CHECKS!!!
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/add_player(ckey)
|
||||||
|
SHOULD_CALL_PARENT(FALSE)
|
||||||
|
|
||||||
|
CRASH("[src] did not implement add_player()! Fix this ASAP!")
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles adding this rank to a player using the legacy system, updating the
|
||||||
|
* legacy config file in the process.
|
||||||
|
*
|
||||||
|
* Don't override this, everything should be handled from `add_player()`,
|
||||||
|
* this is mostly just a helper for convenience.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * ckey - The ckey of the player you want to now possess this player rank.
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/add_player_legacy(ckey)
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
add_player(ckey)
|
||||||
|
text2file(ckey, legacy_file_path)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles removing this rank from a player by their ckey. This is only
|
||||||
|
* intended to be used for handling the in-game portion of removing this rank,
|
||||||
|
* and not to save this change anywhere. That should be handled by the caller.
|
||||||
|
*
|
||||||
|
* DO NOT FORGET TO ADD A `IsAdminAdvancedProcCall()` CHECK SO THAT ADMINS
|
||||||
|
* CAN'T JUST USE THAT TO SKIP PERMISSION CHECKS!!!
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/remove_player(ckey)
|
||||||
|
SHOULD_CALL_PARENT(FALSE)
|
||||||
|
|
||||||
|
CRASH("[src] did not implement remove_player()! Fix this ASAP!")
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles removing this rank from a player using the legacy system, updating
|
||||||
|
* the legacy config file in the process.
|
||||||
|
*
|
||||||
|
* Don't override this, everything should be handled from `remove_player()`
|
||||||
|
* and `save_legacy()`, this is mostly just a helper for convenience.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * ckey - The ckey of the player you want to no longer possess this player
|
||||||
|
* rank.
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/remove_player_legacy(ckey)
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
remove_player(ckey)
|
||||||
|
// We have to save like this, because we're taking something out at an
|
||||||
|
// arbitrary point in the list.
|
||||||
|
save_legacy()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles loading the players that have this rank from an already-executed
|
||||||
|
* database query.
|
||||||
|
*
|
||||||
|
* Mostly just a helper to simplify the logic of the subsystem.
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/load_from_query(datum/db_query/query)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
clear_existing_rank_data()
|
||||||
|
|
||||||
|
while(query.NextRow())
|
||||||
|
var/ckey = ckey(query.item[INDEX_CKEY])
|
||||||
|
add_player(ckey)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles loading the players that have this rank from its legacy config file.
|
||||||
|
*
|
||||||
|
* Don't override this, use `clear_existing_rank_data()` to clear up anything
|
||||||
|
* that needs to be cleared/initialized before loading the rank, and
|
||||||
|
* `add_player()` for actually giving the rank to the ckey in-game.
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/load_legacy()
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
clear_existing_rank_data()
|
||||||
|
|
||||||
|
for(var/line in world.file2list(legacy_file_path))
|
||||||
|
if(!line)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if(findtextEx(line, "#", 1, 2))
|
||||||
|
continue
|
||||||
|
|
||||||
|
add_player(line)
|
||||||
|
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles saving the players that have this rank using its legacy config file.
|
||||||
|
*
|
||||||
|
* Don't override this, use `get_ckeys_for_legacy_save()` if you need to filter
|
||||||
|
* the list of ckeys that will get saved.
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/save_legacy()
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
var/save_file_contents = legacy_file_header
|
||||||
|
|
||||||
|
for(var/player in get_ckeys_for_legacy_save())
|
||||||
|
save_file_contents += player + "\n"
|
||||||
|
|
||||||
|
rustg_file_write(save_file_contents, legacy_file_path)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles returning a list of all the legacy ckeys that should be migrated
|
||||||
|
* from the legacy system to the database one.
|
||||||
|
*
|
||||||
|
* Returns a list of ckeys as strings.
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/get_ckeys_to_migrate()
|
||||||
|
SHOULD_NOT_OVERRIDE(TRUE)
|
||||||
|
RETURN_TYPE(/list)
|
||||||
|
|
||||||
|
var/list/ckeys_to_migrate = list()
|
||||||
|
|
||||||
|
for(var/line in world.file2list(legacy_file_path))
|
||||||
|
if(!line)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if(findtextEx(line, "#", 1, 2))
|
||||||
|
continue
|
||||||
|
|
||||||
|
var/to_migrate = ckey(line)
|
||||||
|
|
||||||
|
if(!to_migrate)
|
||||||
|
continue
|
||||||
|
|
||||||
|
ckeys_to_migrate += to_migrate
|
||||||
|
|
||||||
|
return ckeys_to_migrate
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple proc for subtypes to override for their own handling of obtaining
|
||||||
|
* a list of ckeys to save during a legacy save.
|
||||||
|
*
|
||||||
|
* DO NOT FORGET TO ADD A `IsAdminAdvancedProcCall()` CHECK SO THAT ADMINS
|
||||||
|
* CAN'T JUST ELEVATE PERMISSIONS TO ADD THEMSELVES TO A LEGACY SAVE!!!
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/get_ckeys_for_legacy_save()
|
||||||
|
SHOULD_CALL_PARENT(FALSE)
|
||||||
|
RETURN_TYPE(/list)
|
||||||
|
|
||||||
|
CRASH("[src] did not implement get_ckeys_for_legacy_save()! Fix this ASAP!")
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/proc/should_use_legacy_system()
|
||||||
|
SHOULD_CALL_PARENT(FALSE)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
stack_trace("[src] did not implement should_use_legacy_system(), defaulting to TRUE! Fix this ASAP!")
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple proc for subtypes to override for their own handling of clearing any
|
||||||
|
* lists that need to be cleared before loading the player rank data.
|
||||||
|
*
|
||||||
|
* DO NOT FORGET TO ADD A `IsAdminAdvancedProcCall()` CHECK SO THAT ADMINS
|
||||||
|
* CAN'T JUST ELEVATE PERMISSIONS TO CLEAR RANK DATA AND SCREW YOU OVER!!!
|
||||||
|
*/
|
||||||
|
/datum/player_rank_controller/proc/clear_existing_rank_data()
|
||||||
|
SHOULD_CALL_PARENT(FALSE)
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
CRASH("[src] did not implement clear_existing_rank_data()! Fix this ASAP!")
|
||||||
|
|
||||||
|
|
||||||
|
#undef INDEX_CKEY
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/// The list of all donators.
|
||||||
|
GLOBAL_LIST_EMPTY(donator_list)
|
||||||
|
GLOBAL_PROTECT(donator_list)
|
||||||
|
|
||||||
|
/datum/player_rank_controller/donator
|
||||||
|
rank_title = "donator"
|
||||||
|
// Yes, this is incredibly long, deal with it. It's to keep that cute little comment at the top.
|
||||||
|
legacy_file_header = "###############################################################################################\n# List for people who support us! They get cool loadout items #\n# Case is not important for ckey. #\n###############################################################################################\n"
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/donator/New()
|
||||||
|
. = ..()
|
||||||
|
legacy_file_path = "[global.config.directory]/skyrat/donators.txt"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/donator/add_player(ckey)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
ckey = ckey(ckey)
|
||||||
|
|
||||||
|
// Associative list for extra SPEED!
|
||||||
|
GLOB.donator_list[ckey] = TRUE
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/donator/remove_player(ckey)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
GLOB.donator_list -= ckey
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/donator/get_ckeys_for_legacy_save()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
return GLOB.donator_list
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/donator/should_use_legacy_system()
|
||||||
|
return CONFIG_GET(flag/donator_legacy_system)
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/donator/clear_existing_rank_data()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
GLOB.donator_list = list()
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
// The mentor system is a bit more complex than the other player ranks, so it's
|
||||||
|
// got its own handling and global lists declarations in the `mentor` module.
|
||||||
|
|
||||||
|
/datum/player_rank_controller/mentor
|
||||||
|
rank_title = "mentor"
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/mentor/New()
|
||||||
|
. = ..()
|
||||||
|
legacy_file_path = "[global.config.directory]/skyrat/mentors.txt"
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/mentor/add_player(ckey)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
ckey = ckey(ckey)
|
||||||
|
|
||||||
|
new /datum/mentors(ckey)
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/mentor/remove_player(ckey)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
var/datum/mentors/mentor_datum = GLOB.mentor_datums[ckey]
|
||||||
|
mentor_datum?.remove_mentor()
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/mentor/get_ckeys_for_legacy_save()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
// This whole mess is just to only save the mentors that were in the config
|
||||||
|
// already so that we don't add every admin to the config file, which would
|
||||||
|
// be a pain to maintain afterwards.
|
||||||
|
// We don't save mentors that are new to the `GLOB.mentor_datums` list,
|
||||||
|
// because they should have already been saved from `add_player_legacy()`.
|
||||||
|
var/list/mentors_to_save = list()
|
||||||
|
var/list/existing_mentor_config = world.file2list(legacy_file_path)
|
||||||
|
for(var/line in existing_mentor_config)
|
||||||
|
if(!length(line))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if(findtextEx(line, "#", 1, 2))
|
||||||
|
continue
|
||||||
|
|
||||||
|
var/existing_mentor = ckey(line)
|
||||||
|
if(!existing_mentor)
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Only save them if they're still in the mentor datums list in-game.
|
||||||
|
if(!GLOB.mentor_datums[existing_mentor])
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Associative list for extra SPEED!
|
||||||
|
mentors_to_save[existing_mentor] = TRUE
|
||||||
|
|
||||||
|
return mentors_to_save
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/mentor/should_use_legacy_system()
|
||||||
|
return CONFIG_GET(flag/mentor_legacy_system)
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/mentor/clear_existing_rank_data()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
GLOB.mentor_datums.Cut()
|
||||||
|
|
||||||
|
for(var/client/ex_mentor as anything in GLOB.mentors)
|
||||||
|
ex_mentor.remove_mentor_verbs()
|
||||||
|
ex_mentor.mentor_datum = null
|
||||||
|
|
||||||
|
GLOB.mentors.Cut()
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/// The list of all veteran players.
|
||||||
|
GLOBAL_LIST_EMPTY(veteran_list)
|
||||||
|
GLOBAL_PROTECT(veteran_list)
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/veteran
|
||||||
|
rank_title = "veteran"
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/veteran/New()
|
||||||
|
. = ..()
|
||||||
|
legacy_file_path = "[global.config.directory]/skyrat/veteran_players.txt"
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/veteran/add_player(ckey)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
ckey = ckey(ckey)
|
||||||
|
|
||||||
|
// Associative list for extra SPEED!
|
||||||
|
GLOB.veteran_list[ckey] = TRUE
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/veteran/remove_player(ckey)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
GLOB.veteran_list -= ckey
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/veteran/get_ckeys_for_legacy_save()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
return GLOB.veteran_list
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/veteran/should_use_legacy_system()
|
||||||
|
return CONFIG_GET(flag/veteran_legacy_system)
|
||||||
|
|
||||||
|
|
||||||
|
/datum/player_rank_controller/veteran/clear_existing_rank_data()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
GLOB.veteran_list = list()
|
||||||
@@ -0,0 +1,454 @@
|
|||||||
|
/// The name of the table on the database containing the player ranks.
|
||||||
|
/// See `skyrat_schema.sql` for the schema of the table.
|
||||||
|
#define PLAYER_RANK_TABLE_NAME "player_rank"
|
||||||
|
/// The index of the ckey in the items of a given row in a query for player ranks.
|
||||||
|
#define INDEX_CKEY 1
|
||||||
|
/// The name entered in the database for the admin_ckey for legacy migrations.
|
||||||
|
#define LEGACY_MIGRATION_ADMIN_CKEY "LEGACY"
|
||||||
|
|
||||||
|
|
||||||
|
SUBSYSTEM_DEF(player_ranks)
|
||||||
|
name = "Player Ranks"
|
||||||
|
flags = SS_NO_FIRE
|
||||||
|
init_order = INIT_ORDER_PLAYER_RANKS
|
||||||
|
// The following controllers handle most of the legacy system's functions,
|
||||||
|
// and provide a layer of abstraction for this subsystem to have cleaner
|
||||||
|
// logic.
|
||||||
|
/// The donator player rank controller.
|
||||||
|
var/datum/player_rank_controller/donator/donator_controller
|
||||||
|
/// The mentor player rank controller.
|
||||||
|
var/datum/player_rank_controller/mentor/mentor_controller
|
||||||
|
/// The veteran player rank controller.
|
||||||
|
var/datum/player_rank_controller/veteran/veteran_controller
|
||||||
|
|
||||||
|
|
||||||
|
/datum/controller/subsystem/player_ranks/Initialize()
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
load_donators()
|
||||||
|
load_mentors()
|
||||||
|
load_veterans()
|
||||||
|
|
||||||
|
return SS_INIT_SUCCESS
|
||||||
|
|
||||||
|
|
||||||
|
/datum/controller/subsystem/player_ranks/Destroy()
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
QDEL_NULL(donator_controller)
|
||||||
|
QDEL_NULL(mentor_controller)
|
||||||
|
QDEL_NULL(veteran_controller)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the user is qualified as a donator.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * user - The client to verify the donator status of.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/is_donator(client/user)
|
||||||
|
if(!istype(user))
|
||||||
|
CRASH("Invalid user type provided to is_donator(), expected 'client' and obtained '[user ? user.type : "null"]'.")
|
||||||
|
|
||||||
|
if(GLOB.donator_list[user.ckey])
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if(is_admin(user))
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the user is qualified as a mentor.
|
||||||
|
* Wrapper for the `is_mentor()` proc on the client, with a null check.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * user - The client to verify the mentor status of.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/is_mentor(client/user)
|
||||||
|
if(!istype(user))
|
||||||
|
CRASH("Invalid user type provided to is_mentor(), expected 'client' and obtained '[user ? user.type : "null"]'.")
|
||||||
|
|
||||||
|
return user.is_mentor()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the user is qualified as a veteran.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * user - The client to verify the veteran status of.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/is_veteran(client/user)
|
||||||
|
if(!istype(user))
|
||||||
|
CRASH("Invalid user type provided to is_veteran(), expected 'client' and obtained '[user ? user.type : "null"]'.")
|
||||||
|
|
||||||
|
if(GLOB.veteran_list[user.ckey])
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if(is_admin(user))
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
|
||||||
|
/// Handles loading donators either via SQL or using the legacy system,
|
||||||
|
/// based on configs.
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/load_donators()
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
donator_controller = new
|
||||||
|
|
||||||
|
if(CONFIG_GET(flag/donator_legacy_system))
|
||||||
|
donator_controller.load_legacy()
|
||||||
|
update_all_prefs_unlock_contents()
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!SSdbcore.Connect())
|
||||||
|
var/message = "Failed to connect to database in load_donators(). Reverting to legacy system."
|
||||||
|
log_config(message)
|
||||||
|
log_game(message)
|
||||||
|
message_admins(message)
|
||||||
|
CONFIG_SET(flag/donator_legacy_system, TRUE)
|
||||||
|
donator_controller.load_legacy()
|
||||||
|
return
|
||||||
|
|
||||||
|
load_player_rank_sql(donator_controller)
|
||||||
|
update_all_prefs_unlock_contents()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles updating all of the preferences datums to have the appropriate
|
||||||
|
* `unlock_content` and `max_save_slots` once donators are loaded.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/update_all_prefs_unlock_contents()
|
||||||
|
for(var/ckey as anything in GLOB.preferences_datums)
|
||||||
|
update_prefs_unlock_content(GLOB.preferences_datums[ckey])
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the `unlock_contents` and the `max_save_slots`
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * prefs - The preferences datum to check the unlock_content eligibility.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/update_prefs_unlock_content(datum/preferences/prefs)
|
||||||
|
if(!prefs)
|
||||||
|
return
|
||||||
|
|
||||||
|
prefs.unlock_content = !!prefs.parent.IsByondMember() || is_donator(prefs.parent)
|
||||||
|
if(prefs.unlock_content)
|
||||||
|
prefs.max_save_slots = 50
|
||||||
|
|
||||||
|
|
||||||
|
/// Handles loading mentors either via SQL or using the legacy system,
|
||||||
|
/// based on configs.
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/load_mentors()
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
mentor_controller = new
|
||||||
|
|
||||||
|
if(CONFIG_GET(flag/mentor_legacy_system))
|
||||||
|
mentor_controller.load_legacy()
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!SSdbcore.Connect())
|
||||||
|
var/message = "Failed to connect to database in load_mentors(). Reverting to legacy system."
|
||||||
|
log_config(message)
|
||||||
|
log_game(message)
|
||||||
|
message_admins(message)
|
||||||
|
CONFIG_SET(flag/mentor_legacy_system, TRUE)
|
||||||
|
mentor_controller.load_legacy()
|
||||||
|
return
|
||||||
|
|
||||||
|
load_player_rank_sql(mentor_controller)
|
||||||
|
|
||||||
|
|
||||||
|
/// Handles loading veteran players either via SQL or using the legacy system,
|
||||||
|
/// based on configs.
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/load_veterans()
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
veteran_controller = new
|
||||||
|
|
||||||
|
if(CONFIG_GET(flag/veteran_legacy_system))
|
||||||
|
veteran_controller.load_legacy()
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!SSdbcore.Connect())
|
||||||
|
var/message = "Failed to connect to database in load_veterans(). Reverting to legacy system."
|
||||||
|
log_config(message)
|
||||||
|
log_game(message)
|
||||||
|
message_admins(message)
|
||||||
|
CONFIG_SET(flag/veteran_legacy_system, TRUE)
|
||||||
|
veteran_controller.load_legacy()
|
||||||
|
return
|
||||||
|
|
||||||
|
load_player_rank_sql(veteran_controller)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles populating the player rank from the database.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * rank_controller - The player rank controller of the rank to load.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/load_player_rank_sql(datum/player_rank_controller/rank_controller)
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
var/datum/db_query/query_load_player_rank = SSdbcore.NewQuery(
|
||||||
|
"SELECT ckey FROM [format_table_name(PLAYER_RANK_TABLE_NAME)] WHERE deleted = 0 AND rank = :rank",
|
||||||
|
list("rank" = rank_controller.rank_title),
|
||||||
|
)
|
||||||
|
|
||||||
|
if(!query_load_player_rank.warn_execute())
|
||||||
|
return
|
||||||
|
|
||||||
|
rank_controller.load_from_query(query_load_player_rank)
|
||||||
|
|
||||||
|
|
||||||
|
/// Allows fetching the appropriate player_rank_controller based on its
|
||||||
|
/// `rank_title`, for convenience.
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/get_controller_for_group(rank_title)
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return null
|
||||||
|
|
||||||
|
rank_title = lowertext(rank_title)
|
||||||
|
|
||||||
|
// Can't make switch() statements with non-constant values.
|
||||||
|
if(rank_title == donator_controller.rank_title)
|
||||||
|
return donator_controller
|
||||||
|
|
||||||
|
if(rank_title == mentor_controller.rank_title)
|
||||||
|
return mentor_controller
|
||||||
|
|
||||||
|
if(rank_title == veteran_controller.rank_title)
|
||||||
|
return veteran_controller
|
||||||
|
|
||||||
|
CRASH("Invalid player_rank_controller \"[rank_title || "*null*"]\" used in get_controller_for_group()!")
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles adding the ckey to the proper player rank group, either on the database
|
||||||
|
* or in the legacy system.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * admin - The admin making the rank change.
|
||||||
|
* * ckey - The ckey of the player you want to now possess that player rank.
|
||||||
|
* * rank_title - The title of the group you want to add the ckey to.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/add_player_to_group(client/admin, ckey, rank_title)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(!ckey || !admin || !rank_title)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(!check_rights_for(admin, R_PERMISSIONS))
|
||||||
|
to_chat(admin, span_warning("You do not possess the permissions to do this."))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
rank_title = lowertext(rank_title)
|
||||||
|
|
||||||
|
var/datum/player_rank_controller/controller = get_controller_for_group(rank_title)
|
||||||
|
|
||||||
|
if(!controller)
|
||||||
|
stack_trace("Invalid player rank \"[rank_title]\" supplied in add_player_to_group()!")
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
ckey = ckey(ckey)
|
||||||
|
|
||||||
|
var/already_in_config = controller.get_ckeys_for_legacy_save()
|
||||||
|
|
||||||
|
if(already_in_config[ckey])
|
||||||
|
to_chat(admin, span_warning("\"[ckey]\" is already a [rank_title]!"))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(controller.should_use_legacy_system())
|
||||||
|
controller.add_player_legacy(ckey)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
return add_player_rank_sql(controller, ckey, admin.ckey)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles adding the ckey to the appropriate player rank table on the database,
|
||||||
|
* as well as in-game.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * controller - The controller of the player rank you want to add the ckey to.
|
||||||
|
* * ckey - The ckey of the player you want to now possess that player rank.
|
||||||
|
* * admin_ckey - The ckey of the admin that made the rank change.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/add_player_rank_sql(datum/player_rank_controller/controller, ckey, admin_ckey)
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
var/datum/db_query/query_add_player_rank = SSdbcore.NewQuery(
|
||||||
|
"INSERT INTO [format_table_name(PLAYER_RANK_TABLE_NAME)] (ckey, rank, admin_ckey) VALUES(:ckey, :rank, :admin_ckey) \
|
||||||
|
ON DUPLICATE KEY UPDATE deleted = 0, admin_ckey = :admin_ckey",
|
||||||
|
list("ckey" = ckey, "rank" = controller.rank_title, "admin_ckey" = admin_ckey),
|
||||||
|
)
|
||||||
|
|
||||||
|
if(!query_add_player_rank.warn_execute())
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
controller.add_player(ckey)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles removing the ckey from the proper player rank group, either on the database
|
||||||
|
* or in the legacy system.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * admin - The admin making the rank change.
|
||||||
|
* * ckey - The ckey of the player you want to no longer possess that player rank.
|
||||||
|
* * rank_title - The title of the group you want to remove the ckey from.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/remove_player_from_group(client/admin, ckey, rank_title)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(!ckey || !admin || !rank_title)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(!check_rights_for(admin, R_PERMISSIONS))
|
||||||
|
to_chat(admin, span_warning("You do not possess the permissions to do this."))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
rank_title = lowertext(rank_title)
|
||||||
|
|
||||||
|
var/datum/player_rank_controller/controller = get_controller_for_group(rank_title)
|
||||||
|
|
||||||
|
if(!controller)
|
||||||
|
stack_trace("Invalid player rank \"[rank_title]\" supplied in add_player_to_group()!")
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
ckey = ckey(ckey)
|
||||||
|
|
||||||
|
var/already_in_config = controller.get_ckeys_for_legacy_save()
|
||||||
|
|
||||||
|
if(!already_in_config[ckey])
|
||||||
|
to_chat(admin, span_warning("\"[ckey]\" is already not a [rank_title]!"))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(controller.should_use_legacy_system())
|
||||||
|
controller.remove_player_legacy(ckey)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
return remove_player_rank_sql(controller, ckey, admin.ckey)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles removing the ckey from the appropriate player rank table on the database,
|
||||||
|
* as well as in-game.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * controller - The controller of the player rank you want to remove the ckey from.
|
||||||
|
* * ckey - The ckey of the player you want to no longer possess that player rank.
|
||||||
|
* * admin_ckey - The ckey of the admin that made the rank change.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/remove_player_rank_sql(datum/player_rank_controller/controller, ckey, admin_ckey)
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
var/datum/db_query/query_remove_player_rank = SSdbcore.NewQuery(
|
||||||
|
"UPDATE [format_table_name(PLAYER_RANK_TABLE_NAME)] SET deleted = 1, admin_ckey = :admin_ckey WHERE ckey = :ckey AND rank = :rank",
|
||||||
|
list("ckey" = ckey, "rank" = controller.rank_title, "admin_ckey" = admin_ckey),
|
||||||
|
)
|
||||||
|
|
||||||
|
if(!query_remove_player_rank.warn_execute())
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
controller.remove_player(ckey)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles migrating a player rank system from the legacy system to the
|
||||||
|
* SQL-based version, from its `rank_title`
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * admin - The admin trying to do the migration.
|
||||||
|
* * rank_title - String of the name of the player rank to migrate
|
||||||
|
* (case-sensitive).
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/migrate_player_rank_to_sql(client/admin, rank_title)
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!check_rights_for(admin, R_PERMISSIONS | R_DEBUG | R_SERVER))
|
||||||
|
to_chat(admin, span_warning("You do not possess the permissions to do this."))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/datum/player_rank_controller/controller = get_controller_for_group(rank_title)
|
||||||
|
|
||||||
|
if(!controller)
|
||||||
|
return
|
||||||
|
|
||||||
|
migrate_player_rank_to_sql_from_controller(controller)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles migrating the ckeys of the players that were stored in a legacy
|
||||||
|
* player rank system into the SQL-based one instead. It will ensure to only
|
||||||
|
* add ckeys that were not already present in the database.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * controller - The player rank controller you want to migrate from the
|
||||||
|
* legacy system to the SQL one.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/player_ranks/proc/migrate_player_rank_to_sql_from_controller(datum/player_rank_controller/controller)
|
||||||
|
PROTECTED_PROC(TRUE)
|
||||||
|
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
return
|
||||||
|
|
||||||
|
var/list/ckeys_to_migrate = controller.get_ckeys_to_migrate()
|
||||||
|
|
||||||
|
// We explicitly don't check if they were deleted or not, because we
|
||||||
|
// EXPLICITLY want to avoid any kind of duplicates.
|
||||||
|
var/datum/db_query/query_get_existing_entries = SSdbcore.NewQuery(
|
||||||
|
"SELECT ckey FROM [format_table_name(PLAYER_RANK_TABLE_NAME)] WHERE rank = :rank",
|
||||||
|
list("rank" = controller.rank_title),
|
||||||
|
)
|
||||||
|
|
||||||
|
if(!query_get_existing_entries.warn_execute())
|
||||||
|
return
|
||||||
|
|
||||||
|
while(query_get_existing_entries.NextRow())
|
||||||
|
var/ckey = ckey(query_get_existing_entries.item[INDEX_CKEY])
|
||||||
|
ckeys_to_migrate -= ckey
|
||||||
|
|
||||||
|
var/list/rows_to_insert = list()
|
||||||
|
|
||||||
|
for(var/ckey in ckeys_to_migrate)
|
||||||
|
rows_to_insert += list(list("ckey" = ckey, "rank" = controller.rank_title, "admin_ckey" = LEGACY_MIGRATION_ADMIN_CKEY))
|
||||||
|
|
||||||
|
log_config("Migrating [length(rows_to_insert)] entries from \the [controller.rank_title] legacy system to the SQL-based system.")
|
||||||
|
SSdbcore.MassInsert(format_table_name(PLAYER_RANK_TABLE_NAME), rows_to_insert, warn = TRUE)
|
||||||
|
|
||||||
|
|
||||||
|
#undef PLAYER_RANK_TABLE_NAME
|
||||||
|
#undef INDEX_CKEY
|
||||||
|
#undef LEGACY_MIGRATION_ADMIN_CKEY
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#define VETERANPLAYERS "[global.config.directory]/skyrat/veteran_players.txt"
|
|
||||||
|
|
||||||
GLOBAL_LIST(veteran_players)
|
|
||||||
|
|
||||||
/proc/load_veteran_players()
|
|
||||||
GLOB.veteran_players = list()
|
|
||||||
for(var/line in world.file2list(VETERANPLAYERS))
|
|
||||||
if(!line)
|
|
||||||
continue
|
|
||||||
if(findtextEx(line,"#",1,2))
|
|
||||||
continue
|
|
||||||
GLOB.veteran_players[ckey(line)] = TRUE //Associative so we can check it much faster
|
|
||||||
|
|
||||||
/proc/save_veteran_players()
|
|
||||||
var/veteran_list = ""
|
|
||||||
for(var/veteran in GLOB.veteran_players)
|
|
||||||
veteran_list += veteran + "\n"
|
|
||||||
rustg_file_write(veteran_list, VETERANPLAYERS)
|
|
||||||
|
|
||||||
/proc/is_veteran_player(client/user)
|
|
||||||
if(isnull(user))
|
|
||||||
return FALSE
|
|
||||||
if(GLOB.veteran_players[user.ckey])
|
|
||||||
return TRUE
|
|
||||||
if(check_rights_for(user, R_ADMIN))
|
|
||||||
return TRUE
|
|
||||||
if(GLOB.deadmins[user.ckey])
|
|
||||||
return TRUE
|
|
||||||
return FALSE
|
|
||||||
|
|
||||||
#undef VETERANPLAYERS
|
|
||||||
@@ -5895,6 +5895,7 @@
|
|||||||
#include "modular_skyrat\master_files\code\modules\logging\categories\log_category_uplink.dm"
|
#include "modular_skyrat\master_files\code\modules\logging\categories\log_category_uplink.dm"
|
||||||
#include "modular_skyrat\master_files\code\modules\mapfluff\ruins\objects_and_mobs\necropolis_gate.dm"
|
#include "modular_skyrat\master_files\code\modules\mapfluff\ruins\objects_and_mobs\necropolis_gate.dm"
|
||||||
#include "modular_skyrat\master_files\code\modules\mining\equipment\explorer_gear.dm"
|
#include "modular_skyrat\master_files\code\modules\mining\equipment\explorer_gear.dm"
|
||||||
|
#include "modular_skyrat\master_files\code\modules\mob\login.dm"
|
||||||
#include "modular_skyrat\master_files\code\modules\mob\dead\new_player\latejoin_menu.dm"
|
#include "modular_skyrat\master_files\code\modules\mob\dead\new_player\latejoin_menu.dm"
|
||||||
#include "modular_skyrat\master_files\code\modules\mob\dead\new_player\preferences_setup.dm"
|
#include "modular_skyrat\master_files\code\modules\mob\dead\new_player\preferences_setup.dm"
|
||||||
#include "modular_skyrat\master_files\code\modules\mob\living\blood.dm"
|
#include "modular_skyrat\master_files\code\modules\mob\living\blood.dm"
|
||||||
@@ -5972,7 +5973,7 @@
|
|||||||
#include "modular_skyrat\modules\admin\code\aooc.dm"
|
#include "modular_skyrat\modules\admin\code\aooc.dm"
|
||||||
#include "modular_skyrat\modules\admin\code\fix_chat.dm"
|
#include "modular_skyrat\modules\admin\code\fix_chat.dm"
|
||||||
#include "modular_skyrat\modules\admin\code\loud_say.dm"
|
#include "modular_skyrat\modules\admin\code\loud_say.dm"
|
||||||
#include "modular_skyrat\modules\admin\code\manage_player_ranks.dm"
|
#include "modular_skyrat\modules\admin\code\player_ranks.dm"
|
||||||
#include "modular_skyrat\modules\admin\code\sooc.dm"
|
#include "modular_skyrat\modules\admin\code\sooc.dm"
|
||||||
#include "modular_skyrat\modules\admin\code\smites\pie.dm"
|
#include "modular_skyrat\modules\admin\code\smites\pie.dm"
|
||||||
#include "modular_skyrat\modules\advanced_engineering\code\adv_engineering.dm"
|
#include "modular_skyrat\modules\advanced_engineering\code\adv_engineering.dm"
|
||||||
@@ -6412,7 +6413,6 @@
|
|||||||
#include "modular_skyrat\modules\customization\game\objects\items\storage\belt.dm"
|
#include "modular_skyrat\modules\customization\game\objects\items\storage\belt.dm"
|
||||||
#include "modular_skyrat\modules\customization\game\objects\items\storage\rings.dm"
|
#include "modular_skyrat\modules\customization\game\objects\items\storage\rings.dm"
|
||||||
#include "modular_skyrat\modules\customization\game\objects\items\tanks\n2_tanks.dm"
|
#include "modular_skyrat\modules\customization\game\objects\items\tanks\n2_tanks.dm"
|
||||||
#include "modular_skyrat\modules\customization\modules\admin\donator_list.dm"
|
|
||||||
#include "modular_skyrat\modules\customization\modules\client\preferences.dm"
|
#include "modular_skyrat\modules\customization\modules\client\preferences.dm"
|
||||||
#include "modular_skyrat\modules\customization\modules\client\augment\_augment.dm"
|
#include "modular_skyrat\modules\customization\modules\client\augment\_augment.dm"
|
||||||
#include "modular_skyrat\modules\customization\modules\client\augment\implants.dm"
|
#include "modular_skyrat\modules\customization\modules\client\augment\implants.dm"
|
||||||
@@ -6883,7 +6883,6 @@
|
|||||||
#include "modular_skyrat\modules\medievalcrate_skyrat\code\vintageitems.dm"
|
#include "modular_skyrat\modules\medievalcrate_skyrat\code\vintageitems.dm"
|
||||||
#include "modular_skyrat\modules\mentor\code\_globalvars.dm"
|
#include "modular_skyrat\modules\mentor\code\_globalvars.dm"
|
||||||
#include "modular_skyrat\modules\mentor\code\client_procs.dm"
|
#include "modular_skyrat\modules\mentor\code\client_procs.dm"
|
||||||
#include "modular_skyrat\modules\mentor\code\config.dm"
|
|
||||||
#include "modular_skyrat\modules\mentor\code\dementor.dm"
|
#include "modular_skyrat\modules\mentor\code\dementor.dm"
|
||||||
#include "modular_skyrat\modules\mentor\code\follow.dm"
|
#include "modular_skyrat\modules\mentor\code\follow.dm"
|
||||||
#include "modular_skyrat\modules\mentor\code\logging.dm"
|
#include "modular_skyrat\modules\mentor\code\logging.dm"
|
||||||
@@ -7216,6 +7215,11 @@
|
|||||||
#include "modular_skyrat\modules\pixel_shift\code\pixel_shift_component.dm"
|
#include "modular_skyrat\modules\pixel_shift\code\pixel_shift_component.dm"
|
||||||
#include "modular_skyrat\modules\pixel_shift\code\pixel_shift_keybind.dm"
|
#include "modular_skyrat\modules\pixel_shift\code\pixel_shift_keybind.dm"
|
||||||
#include "modular_skyrat\modules\pixel_shift\code\pixel_shift_mob.dm"
|
#include "modular_skyrat\modules\pixel_shift\code\pixel_shift_mob.dm"
|
||||||
|
#include "modular_skyrat\modules\player_ranks\code\player_rank_controller\_player_rank_controller.dm"
|
||||||
|
#include "modular_skyrat\modules\player_ranks\code\player_rank_controller\donator_controller.dm"
|
||||||
|
#include "modular_skyrat\modules\player_ranks\code\player_rank_controller\mentor_controller.dm"
|
||||||
|
#include "modular_skyrat\modules\player_ranks\code\player_rank_controller\veteran_controller.dm"
|
||||||
|
#include "modular_skyrat\modules\player_ranks\code\subsystem\player_ranks.dm"
|
||||||
#include "modular_skyrat\modules\pod_locking\pod_locking.dm"
|
#include "modular_skyrat\modules\pod_locking\pod_locking.dm"
|
||||||
#include "modular_skyrat\modules\polarized_windows\capacitor.dm"
|
#include "modular_skyrat\modules\polarized_windows\capacitor.dm"
|
||||||
#include "modular_skyrat\modules\polarized_windows\polarization_controller.dm"
|
#include "modular_skyrat\modules\polarized_windows\polarization_controller.dm"
|
||||||
@@ -7414,7 +7418,6 @@
|
|||||||
#include "modular_skyrat\modules\verbs\code\subtle.dm"
|
#include "modular_skyrat\modules\verbs\code\subtle.dm"
|
||||||
#include "modular_skyrat\modules\veteran_only\code\job_types.dm"
|
#include "modular_skyrat\modules\veteran_only\code\job_types.dm"
|
||||||
#include "modular_skyrat\modules\veteran_only\code\species_types.dm"
|
#include "modular_skyrat\modules\veteran_only\code\species_types.dm"
|
||||||
#include "modular_skyrat\modules\veteran_players\code\veteran_players.dm"
|
|
||||||
#include "modular_skyrat\modules\vox_sprites\code\color.dm"
|
#include "modular_skyrat\modules\vox_sprites\code\color.dm"
|
||||||
#include "modular_skyrat\modules\vox_sprites\code\head.dm"
|
#include "modular_skyrat\modules\vox_sprites\code\head.dm"
|
||||||
#include "modular_skyrat\modules\vox_sprites\code\security.dm"
|
#include "modular_skyrat\modules\vox_sprites\code\security.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user