TGUI Preferences Menu + total rewrite of the preferences backend (#17368)

* It compiles

* It opens

* Sync 1

* Add asset caching

* Sync 2

* It opens without dev now

* Update a few packages

* Sync 3

* Sync 4

keybind fix

* start of dehardcoded species

* Small fixes

* Add more individual preferences

* ASS sync
This commit is contained in:
Ling
2023-01-06 23:29:16 +01:00
committed by GitHub
parent 651e75f606
commit 588db2e83b
230 changed files with 11679 additions and 3966 deletions

View File

@@ -171,8 +171,6 @@
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_FLAG
/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game
/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overridden by gamemodes.
/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station

View File

@@ -531,3 +531,6 @@
/// logs all timers in buckets on automatic bucket reset (Useful for timer debugging)
/datum/config_entry/flag/log_timers_on_bucket_reset
/datum/config_entry/flag/cache_assets
default = TRUE

View File

@@ -0,0 +1,19 @@
/// Allows us to lazyload asset datums
/// Anything inserted here will fully load if directly gotten
/// So this just serves to remove the requirement to load assets fully during init
SUBSYSTEM_DEF(asset_loading)
name = "Asset Loading"
priority = FIRE_PRIORITY_ASSETS
flags = SS_NO_INIT
runlevels = RUNLEVEL_LOBBY|RUNLEVELS_DEFAULT
var/list/datum/asset/generate_queue = list()
/datum/controller/subsystem/asset_loading/fire(resumed)
while(length(generate_queue))
var/datum/asset/to_load = generate_queue[generate_queue.len]
to_load.queued_generation()
if(MC_TICK_CHECK)
return
generate_queue.len--

View File

@@ -5,7 +5,7 @@ SUBSYSTEM_DEF(assets)
loading_points = 3 SECONDS // Yogs -- loading times
var/list/cache = list()
var/list/datum/asset_cache_item/cache = list()
var/list/preload = list()
var/datum/asset_transport/transport = new()
@@ -29,7 +29,7 @@ SUBSYSTEM_DEF(assets)
for(var/type in typesof(/datum/asset))
var/datum/asset/A = type
if (type != initial(A._abstract))
get_asset_datum(type)
load_asset_datum(type)
transport.Initialize(cache)

View File

@@ -19,6 +19,9 @@ SUBSYSTEM_DEF(atoms)
var/init_start_time
/// Atoms that will be deleted once the subsystem is initialized
var/list/queued_deletions = list()
initialized = INITIALIZATION_INSSATOMS
/datum/controller/subsystem/atoms/Initialize(timeofday)
@@ -51,6 +54,12 @@ SUBSYSTEM_DEF(atoms)
A.LateInitialize()
testing("Late initialized [late_loaders.len] atoms")
late_loaders.Cut()
for (var/queued_deletion in queued_deletions)
qdel(queued_deletion)
testing("[queued_deletions.len] atoms were queued for deletion.")
queued_deletions.Cut()
/// Actually creates the list of atoms. Exists soley so a runtime in the creation logic doesn't cause initalized to totally break
/datum/controller/subsystem/atoms/proc/CreateAtoms(list/atoms)
@@ -191,6 +200,14 @@ SUBSYSTEM_DEF(atoms)
if(fails & BAD_INIT_SLEPT)
. += "- Slept during Initialize()\n"
/// Prepares an atom to be deleted once the atoms SS is initialized.
/datum/controller/subsystem/atoms/proc/prepare_deletion(atom/target)
if (initialized == INITIALIZATION_INNEW_REGULAR)
// Atoms SS has already completed, just kill it now.
qdel(target)
else
queued_deletions += WEAKREF(target)
/datum/controller/subsystem/atoms/Shutdown()
var/initlog = InitLog()
if(initlog)

View File

@@ -0,0 +1,24 @@
/// Initializes any assets that need to be loaded ASAP.
/// This houses preference menu assets, since they can be loaded at any time,
/// most dangerously before the atoms SS initializes.
/// Thus, we want it to fail consistently in CI as if it would've if a player
/// opened it up early.
SUBSYSTEM_DEF(early_assets)
name = "Early Assets"
init_order = INIT_ORDER_EARLY_ASSETS
flags = SS_NO_FIRE
/datum/controller/subsystem/early_assets/Initialize()
for (var/datum/asset/asset_type as anything in subtypesof(/datum/asset))
if (initial(asset_type._abstract) == asset_type)
continue
if (!initial(asset_type.early))
continue
if (!load_asset_datum(asset_type))
stack_trace("Could not initialize early asset [asset_type]!")
CHECK_TICK
return SS_INIT_SUCCESS

View File

@@ -22,7 +22,6 @@ SUBSYSTEM_DEF(job)
SetupOccupations()
if(CONFIG_GET(flag/load_jobs_from_txt))
LoadJobs()
generate_selectable_species()
set_overflow_role(CONFIG_GET(string/overflow_job))
return SS_INIT_SUCCESS
@@ -74,6 +73,7 @@ SUBSYSTEM_DEF(job)
return name_occupations[rank]
/datum/controller/subsystem/job/proc/GetJobType(jobtype)
RETURN_TYPE(/datum/job)
if(!occupations.len)
SetupOccupations()
return type_occupations[jobtype]
@@ -436,26 +436,33 @@ SUBSYSTEM_DEF(job)
//We couldn't find a job from prefs for this guy.
/datum/controller/subsystem/job/proc/HandleUnassigned(mob/dead/new_player/player)
var/jobless_role = player.client.prefs.read_preference(/datum/preference/choiced/jobless_role)
if(PopcapReached())
RejectPlayer(player)
else if(player.client.prefs.joblessrole == BEOVERFLOW)
var/allowed_to_be_a_loser = !is_banned_from(player.ckey, SSjob.overflow_role)
if(QDELETED(player) || !allowed_to_be_a_loser)
RejectPlayer(player)
else
if(!AssignRole(player, SSjob.overflow_role))
return
switch (jobless_role)
if (BEOVERFLOW)
var/datum/job/overflow_role_datum = GetJobType(overflow_role)
var/allowed_to_be_a_loser = !is_banned_from(player.ckey, overflow_role_datum.title)
if(QDELETED(player) || !allowed_to_be_a_loser)
RejectPlayer(player)
else if(player.client.prefs.joblessrole == BERANDOMJOB)
if(!GiveRandomJob(player))
else
if(!AssignRole(player, overflow_role_datum))
RejectPlayer(player)
if (BERANDOMJOB)
if(!GiveRandomJob(player))
RejectPlayer(player)
if (RETURNTOLOBBY)
RejectPlayer(player)
else if(player.client.prefs.joblessrole == RETURNTOLOBBY)
RejectPlayer(player)
else //Something gone wrong if we got here.
var/message = "DO: [player] fell through handling unassigned"
JobDebug(message)
log_game(message)
message_admins(message)
RejectPlayer(player)
else //Something gone wrong if we got here.
var/message = "DO: [player] fell through handling unassigned"
JobDebug(message)
log_game(message)
message_admins(message)
RejectPlayer(player)
//Gives the player the stuff he should have with his rank
/datum/controller/subsystem/job/proc/EquipRank(mob/M, rank, joined_late = FALSE)
var/mob/dead/new_player/newplayer

View File

@@ -368,7 +368,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
var/pmv = CONFIG_GET(flag/preference_map_voting)
if(pmv)
for (var/client/c in GLOB.clients)
var/vote = c.prefs.preferred_map
var/vote = c.prefs.read_preference(/datum/preference/choiced/preferred_map)
if (!vote)
if (global.config.defaultmap)
mapvotes[global.config.defaultmap.map_name] += 1

View File

@@ -14,8 +14,6 @@ SUBSYSTEM_DEF(persistence)
var/list/picture_logging_information = list()
var/list/obj/structure/sign/picture_frame/photo_frames = list()
var/list/obj/item/storage/photo_album/photo_albums = list()
var/list/obj/structure/sign/painting/painting_frames = list()
var/list/paintings = list()
/datum/controller/subsystem/persistence/Initialize()
LoadPoly()
@@ -26,7 +24,6 @@ SUBSYSTEM_DEF(persistence)
if(CONFIG_GET(flag/use_antag_rep))
LoadAntagReputation()
LoadRandomizedRecipes()
LoadPaintings()
return SS_INIT_SUCCESS
/datum/controller/subsystem/persistence/proc/LoadPoly()
@@ -151,7 +148,6 @@ SUBSYSTEM_DEF(persistence)
if(CONFIG_GET(flag/use_antag_rep))
CollectAntagReputation()
SaveRandomizedRecipes()
SavePaintings()
SaveScars()
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
@@ -332,22 +328,6 @@ SUBSYSTEM_DEF(persistence)
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/LoadPaintings()
var/json_file = file("data/paintings.json")
if(fexists(json_file))
paintings = json_decode(file2text(json_file))
for(var/obj/structure/sign/painting/P in painting_frames)
P.load_persistent()
/datum/controller/subsystem/persistence/proc/SavePaintings()
for(var/obj/structure/sign/painting/P in painting_frames)
P.save_persistent()
var/json_file = file("data/paintings.json")
fdel(json_file)
WRITE_FILE(json_file, json_encode(paintings))
/datum/controller/subsystem/persistence/proc/SaveScars()
for(var/i in GLOB.joined_player_list)
var/mob/living/carbon/human/ending_human = get_mob_by_ckey(i)

View File

@@ -0,0 +1,29 @@
SUBSYSTEM_DEF(persistent_paintings)
name = "Persistent Paintings"
init_order = INIT_ORDER_PERSISTENT_PAINTINGS
flags = SS_NO_FIRE
/// A list of painting frames that this controls
var/list/obj/structure/sign/painting/painting_frames = list()
/// A map of identifiers (such as library) to paintings from paintings.json
var/list/paintings = list()
/datum/controller/subsystem/persistent_paintings/Initialize(start_timeofday)
var/json_file = file("data/paintings.json")
if(fexists(json_file))
paintings = json_decode(file2text(json_file))
for(var/obj/structure/sign/painting/painting_frame as anything in painting_frames)
painting_frame.load_persistent()
return SS_INIT_SUCCESS
/// Saves all persistent paintings
/datum/controller/subsystem/persistent_paintings/proc/save_paintings()
for(var/obj/structure/sign/painting/painting_frame as anything in painting_frames)
painting_frame.save_persistent()
var/json_file = file("data/paintings.json")
fdel(json_file)
WRITE_FILE(json_file, json_encode(paintings))

View File

@@ -57,3 +57,64 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
badquirk = TRUE
if(badquirk)
cli.prefs.save_character()
/// Takes a list of quirk names and returns a new list of quirks that would
/// be valid.
/// If no changes need to be made, will return the same list.
/// Expects all quirk names to be unique, but makes no other expectations.
/datum/controller/subsystem/processing/quirks/proc/filter_invalid_quirks(list/quirks)
var/list/new_quirks = list()
var/list/positive_quirks = list()
var/balance = 0
for (var/quirk_name in quirks)
var/datum/quirk/quirk = SSquirks.quirks[quirk_name]
if (isnull(quirk))
continue
if (initial(quirk.mood_quirk) && CONFIG_GET(flag/disable_human_mood))
continue
var/blacklisted = FALSE
for (var/list/blacklist as anything in quirk_blacklist)
if (!(quirk in blacklist))
continue
for (var/other_quirk in blacklist)
if (other_quirk in new_quirks)
blacklisted = TRUE
break
if (blacklisted)
break
if (blacklisted)
continue
var/value = initial(quirk.value)
if (value > 0)
if (positive_quirks.len == MAX_QUIRKS)
continue
positive_quirks[quirk_name] = value
balance += value
new_quirks += quirk_name
if (balance > 0)
var/balance_left_to_remove = balance
for (var/positive_quirk in positive_quirks)
var/value = positive_quirks[positive_quirk]
balance_left_to_remove -= value
new_quirks -= positive_quirk
if (balance_left_to_remove <= 0)
break
// It is guaranteed that if no quirks are invalid, you can simply check through `==`
if (new_quirks.len == quirks.len)
return quirks
return new_quirks

View File

@@ -69,7 +69,7 @@ SUBSYSTEM_DEF(vote)
else if(mode == "map")
for (var/non_voter_ckey in non_voters)
var/client/C = non_voters[non_voter_ckey]
var/preferred_map = C.prefs.preferred_map
var/preferred_map = C.prefs.read_preference(/datum/preference/choiced/preferred_map)
if(isnull(global.config.defaultmap))
continue
if(!preferred_map)