Base implementation of /datum/persistent_client (#89449)

## About The Pull Request
Converts `/datum/player_details` into `/datum/persistent_client`.
Persistent Clients persist across connections. The only time a mob's
persistent client will change is if the ckey it's bound to logs into a
different mob, or the mob is deleted (duh).

Also adds PossessByPlayer() so that transfering mob control is cleaner
and makes more immediate sense if you don't know byond-fu.

## Why It's Good For The Game
Clients are an abstract representation of a connection that can be
dropped at almost any moment so putting things that should be stable to
access at any time onto an undying object is ideal. This allows for
future expansions like abstracting away client.screen and managing
everything cleanly.
This commit is contained in:
Kapu1178
2025-02-25 13:52:24 -06:00
committed by GitHub
parent 575972e3f8
commit a0e862d575
87 changed files with 226 additions and 173 deletions
+15 -14
View File
@@ -249,6 +249,17 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
GLOB.clients += src
GLOB.directory[ckey] = src
var/reconnecting = FALSE
if(GLOB.persistent_clients_by_ckey[ckey])
reconnecting = TRUE
persistent_client = GLOB.persistent_clients_by_ckey[ckey]
persistent_client.byond_build = byond_build
persistent_client.byond_version = byond_version
else
persistent_client = new(ckey)
persistent_client.byond_build = byond_build
persistent_client.byond_version = byond_version
if(byond_version >= 516)
winset(src, null, list("browser-options" = "find,refresh,byondstorage"))
@@ -328,18 +339,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
else
message_admins(span_danger("<B>[message_type]: </B></span><span class='notice'>Connecting player [key_name_admin(src)] has the same [matches] as [joined_player_ckey](no longer logged in)<b>[in_round]</b>. "))
log_admin_private("[message_type]: Connecting player [key_name(src)] has the same [matches] as [joined_player_ckey](no longer logged in)[in_round].")
var/reconnecting = FALSE
if(GLOB.player_details[ckey])
reconnecting = TRUE
player_details = GLOB.player_details[ckey]
player_details.byond_version = byond_version
player_details.byond_build = byond_build
else
player_details = new(ckey)
player_details.byond_version = byond_version
player_details.byond_build = byond_build
GLOB.player_details[ckey] = player_details
. = ..() //calls mob.Login()
@@ -586,6 +585,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
GLOB.clients -= src
GLOB.directory -= ckey
persistent_client.client = null
log_access("Logout: [key_name(src)]")
GLOB.ahelp_tickets.ClientLogout(src)
GLOB.interviews.client_logout(src)
@@ -1040,11 +1041,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
///Redirect proc that makes it easier to call the unlock achievement proc. Achievement type is the typepath to the award, user is the mob getting the award, and value is an optional variable used for leaderboard value increments
/client/proc/give_award(achievement_type, mob/user, value = 1)
return player_details.achievements.unlock(achievement_type, user, value)
return persistent_client.achievements.unlock(achievement_type, user, value)
///Redirect proc that makes it easier to get the status of an achievement. Achievement type is the typepath to the award.
/client/proc/get_award_status(achievement_type, mob/user, value = 1)
return player_details.achievements.get_achievement_status(achievement_type)
return persistent_client.achievements.get_achievement_status(achievement_type)
///Gives someone hearted status for OOC, from behavior commendations
/client/proc/adjust_heart(duration = 24 HOURS)