Skip to content

Commit

Permalink
Adds Mob Tag data to log messages + player panel (tgstation#79994)
Browse files Browse the repository at this point in the history
## About The Pull Request

Closes tgstation#79969 

In administration, things shouldn't be _required_ to have unique names.
I think that searching by ckey/key in logs should still work fine but I
can see the value in having the mob tag (which is also exposed in places
like `debug.log`, and in public spots too like `hallucinations.html`)
being added with all this data for even more trimming if you wanna find
all the rule-breaking stuff someone does as a very specific mob.

Anyways, the player details datum tracks both the name as well as the
mob tag in an associated list that we can access in order to do work
with it in stuff like the player panel.

We do this by the following
* Rework the player details list to be associated, as well as updating
all instances of the proc that sets this list.
* Make the code for handling duplicates a bit more explicit so it
actually works.
* Make the formatting in the player panel better as well.
* Also add the mob tag information to wherever we might need to log it
via a new proc `key_name_and_tag()`
* Also adds this information to the per-player player panel

## Why It's Good For The Game

Better administration tools, should be more helpful when it comes to
filtering as well as post-mortem cross-comparison for coders in order to
find out exactly _which_ mob was problematic when looking at debug.log
or whatever you may have.

```txt
[2023-11-28 01:25:37.434] GAME-SAY: San7890/(Katie Yossarian) (mob_2759) (DEAD) "deez nuts" (Primary Tool Storage (138,140,2))
[2023-11-28 01:25:39.478] GAME-SAY: San7890/(Katie Yossarian) (mob_2759) (DEAD) "as big chungus" (Primary Tool Storage (138,140,2))
[2023-11-28 01:25:40.617] GAME: *no key*/(Katie Yossarian) (mob_2759) *no key*/(Katie Yossarian) is no longer owning mob Katie Yossarian(/mob/dead/observer) (Primary Tool Storage (138,140,2))
[2023-11-28 01:25:40.618] GAME-ACCESS: Mob Login: San7890/(Katie Yossarian) was assigned to a /mob/living/carbon/human
[2023-11-28 01:25:40.624] GAME: San7890/(Katie Yossarian) (mob_2760) Client San7890/(Katie Yossarian) has taken ownership of mob Katie Yossarian(/mob/living/carbon/human) (Primary Tool Storage (138,140,2))
[2023-11-28 01:25:42.305] GAME-EMOTE: *no key*/(chasm lobstrosity) (mob_88) chitters. (Lavaland Wastes (126,178,3))
[2023-11-28 01:25:42.435] GAME-SAY: San7890/(Katie Yossarian) (mob_2760) "i hate it here" (Primary Tool Storage (138,140,2))
[2023-11-28 01:25:43.058] GAME-COMPAT: ADMIN: San7890/(Katie Yossarian) admin ghosted.
```


![image](https://github.com/tgstation/tgstation/assets/34697715/bbcfb021-2d1f-4e6b-8844-63c6ea4e4bd1)


![image](https://github.com/tgstation/tgstation/assets/34697715/8ae02f7c-8b68-45f9-94c0-41d679bc0b69)

this was taken over three rounds ignore discrepancies

i'm rather fond of having this information in the per-player panel
because otherwise you need to
A) scroll through the F6 window until you find your match
B) pull up three different VV windows

## Changelog

:cl:
admin: The Player Panel should now contain the unique mob tag associated
to a certain mob that a player might inhabit at one time, which is
stored on their player details datum on their client (which is
guaranteed to always exist).
admin: The "Old Names" details of a player is now visible in their own
personal per-player player panel.
/:cl:
  • Loading branch information
san7890 authored Dec 1, 2023
1 parent 1b8580a commit 2522944
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 28 deletions.
9 changes: 8 additions & 1 deletion code/__HELPERS/logging/_logging.dm
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ GLOBAL_LIST_INIT(testing_global_profiler, list("_PROFILE_NAME" = "Global"))
if(!log_globally)
return

var/log_text = "[key_name(src)] [message] [loc_name(src)]"
var/log_text = "[key_name_and_tag(src)] [message] [loc_name(src)]"
switch(message_type)
/// ship both attack logs and victim logs to the end of round attack.log just to ensure we don't lose information
if(LOG_ATTACK, LOG_VICTIM)
Expand Down Expand Up @@ -243,6 +243,13 @@ GLOBAL_LIST_INIT(testing_global_profiler, list("_PROFILE_NAME" = "Global"))
/proc/key_name_admin(whom, include_name = TRUE)
return key_name(whom, TRUE, include_name)

/proc/key_name_and_tag(whom, include_link = null, include_name = TRUE)
var/tag = "!tagless!" // whom can be null in key_name() so lets set this as a safety
if(isatom(whom))
var/atom/subject = whom
tag = subject.tag
return "[key_name(whom, include_link, include_name)] ([tag])"

/proc/loc_name(atom/A)
if(!istype(A))
return "(INVALID LOCATION)"
Expand Down
9 changes: 5 additions & 4 deletions code/__HELPERS/logging/mob.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@

// Cannot use the list as a map if the key is a number, so we stringify it (thank you BYOND)
var/smessage_type = num2text(message_type, MAX_BITFLAG_DIGITS)
var/datum/player_details/client_details = client?.player_details

if(client)
if(!islist(client.player_details.logging[smessage_type]))
client.player_details.logging[smessage_type] = list()
if(!isnull(client_details))
if(!islist(client_details.logging[smessage_type]))
client_details.logging[smessage_type] = list()

if(!islist(logging[smessage_type]))
logging[smessage_type] = list()
Expand All @@ -46,7 +47,7 @@
if(LOG_RADIO_EMOTE)
colored_message = "(RADIOEMOTE) [colored_message]"

var/list/timestamped_message = list("\[[time_stamp(format = "YYYY-MM-DD hh:mm:ss")]\] [key_name(src)] [loc_name(src)] (Event #[LAZYLEN(logging[smessage_type])])" = colored_message)
var/list/timestamped_message = list("\[[time_stamp(format = "YYYY-MM-DD hh:mm:ss")]\] [key_name_and_tag(src)] [loc_name(src)] (Event #[LAZYLEN(logging[smessage_type])])" = colored_message)

logging[smessage_type] += timestamped_message

Expand Down
20 changes: 9 additions & 11 deletions code/modules/admin/player_panel.dm
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@

body += "</td><td align='center'>";

body += "<font size='2'><b>"+job+" "+name+"</b><br><b>Real name "+real_name+"</b><br><b>Played by "+key+" ("+ip+")</b><br><b>Old names :"+old_names+"</b></font>";
body += "<font size='2'><b>"+job+" "+name+"</b><br><b>Real name "+real_name+"</b><br><b>Played by "+key+" ("+ip+")</b><br><b>Old names: "+old_names+"</b></font>";

body += "</td><td align='center'>";

Expand Down Expand Up @@ -274,20 +274,18 @@
else
M_job = "Ghost"

var/M_key = html_encode(M.key)
var/M_ip_address = isnull(M.lastKnownIP) ? "+localhost+" : M.lastKnownIP

var/M_name = html_encode(M.name)
var/M_rname = html_encode(M.real_name)
var/M_rname_as_key = html_encode(ckey(M.real_name)) // so you can ignore punctuation
if(M_rname == M_rname_as_key)
M_rname_as_key = null
var/M_key = html_encode(M.key)
var/previous_names = ""
if(M_key)
var/datum/player_details/P = GLOB.player_details[ckey(M_key)]
if(P)
previous_names = P.played_names.Join(",")
previous_names = html_encode(previous_names)

var/previous_names_string = ""
var/datum/player_details/readable = GLOB.player_details[M.ckey]
if(readable)
previous_names_string = readable.get_played_names()

//output for each mob
dat += {"
Expand All @@ -299,12 +297,12 @@
onmouseover='expand("data[i]","item[i]")'
>
<b id='search[i]'>[M_name] - [M_rname] - [M_key] ([M_job])</b>
<span hidden class='filter_data'>[M_name] [M_rname] [M_rname_as_key] [M_key] [M_job] [previous_names]</span>
<span hidden class='filter_data'>[M_name] [M_rname] [M_rname_as_key] [M_key] [M_job] [previous_names_string]</span>
<span hidden id="data[i]_name">[M_name]</span>
<span hidden id="data[i]_job">[M_job]</span>
<span hidden id="data[i]_rname">[M_rname]</span>
<span hidden id="data[i]_rname_as_key">[M_rname_as_key]</span>
<span hidden id="data[i]_prevnames">[previous_names]</span>
<span hidden id="data[i]_prevnames">[previous_names_string]</span>
<span hidden id="data[i]_key">[M_key]</span>
<span hidden id="data[i]_lastip">[M_ip_address]</span>
<span hidden id="data[i]_isantag">[is_antagonist]</span>
Expand Down
9 changes: 9 additions & 0 deletions code/modules/admin/verbs/admingame.dm
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@

body += "<b>Mob type</b> = [M.type]<br><br>"

if(M.client)
body += "<b>Old names:</b> "
var/datum/player_details/deets = GLOB.player_details[M.ckey]
if(deets)
body += deets.get_played_names()
else
body += "<i>None?!</i>"
body += "<br><br>"

body += "<A href='?_src_=holder;[HrefToken()];boot2=[REF(M)]'>Kick</A> | "
if(M.client)
body += "<A href='?_src_=holder;[HrefToken()];newbankey=[M.key];newbanip=[M.client.address];newbancid=[M.client.computer_id]'>Ban</A> | "
Expand Down
32 changes: 24 additions & 8 deletions code/modules/client/player_details.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ GLOBAL_LIST_EMPTY(player_details)
/// Callbacks invoked when this client logs out
var/list/post_logout_callbacks = list()
/// List of names this key played under this round
/// assoc list of name -> mob tag
var/list/played_names = list()
/// Lazylist of preference slots this client has joined the round under
/// Numbers are stored as strings
Expand All @@ -27,14 +28,29 @@ GLOBAL_LIST_EMPTY(player_details)
/datum/player_details/New(key)
achievements = new(key)

/proc/log_played_names(ckey, ...)
/// Writes all of the `played_names` into an HTML-escaped string.
/datum/player_details/proc/get_played_names()
var/list/previous_names = list()
for(var/previous_name in played_names)
previous_names += html_encode("[previous_name] ([played_names[previous_name]])")
return previous_names.Join("; ")

/// Adds the new names to the player's played_names list on their /datum/player_details for use of admins.
/// `ckey` should be their ckey, and `data` should be an associative list with the keys being the names they played under and the values being the unique mob ID tied to that name.
/proc/log_played_names(ckey, data)
if(!ckey)
return
if(args.len < 2)

var/datum/player_details/writable = GLOB.player_details[ckey]
if(isnull(writable))
return
var/list/names = args.Copy(2)
var/datum/player_details/P = GLOB.player_details[ckey]
if(P)
for(var/name in names)
if(name)
P.played_names |= name

for(var/name in data)
if(!name)
continue
var/mob_tag = data[name]
var/encoded_name = html_encode(name)
if(writable.played_names.Find("[encoded_name]"))
continue

writable.played_names += list("[encoded_name]" = mob_tag)
10 changes: 8 additions & 2 deletions code/modules/mob/login.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
add_to_player_list()
lastKnownIP = client.address
computer_id = client.computer_id
log_access("Mob Login: [key_name(src)] was assigned to a [type]")
log_access("Mob Login: [key_name(src)] was assigned to a [type] ([tag])")
world.update_status()
client.clear_screen() //remove hud items just in case
client.images = list()
Expand Down Expand Up @@ -112,7 +112,13 @@
for(var/foo in client.player_details.post_login_callbacks)
var/datum/callback/CB = foo
CB.Invoke()
log_played_names(client.ckey,name,real_name)
log_played_names(
client.ckey,
list(
"[name]" = tag,
"[real_name]" = tag,
),
)
auto_deadmin_on_login()

log_message("Client [key_name(src)] has taken ownership of mob [src]([src.type])", LOG_OWNERSHIP)
Expand Down
14 changes: 12 additions & 2 deletions code/modules/mob/mob.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1195,14 +1195,24 @@

log_message("[src] name changed from [oldname] to [newname]", LOG_OWNERSHIP)

log_played_names(ckey, newname)
log_played_names(
ckey,
list(
"[newname]" = tag,
),
)

real_name = newname
name = newname
if(mind)
mind.name = newname
if(mind.key)
log_played_names(mind.key,newname) //Just in case the mind is unsynced at the moment.
log_played_names(
ckey(mind.key),
list(
"[newname]" = tag,
),
) //Just in case the mind is unsynced at the moment.

if(oldname)
//update the datacore records! This is goig to be a bit costly.
Expand Down

0 comments on commit 2522944

Please sign in to comment.