Skip to content

Commit a8be2b9

Browse files
authored
replaces pray with ping gm system (#7344)
1 parent ef10c0a commit a8be2b9

File tree

46 files changed

+1494
-249
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1494
-249
lines changed

citadel.dme

Lines changed: 103 additions & 92 deletions
Large diffs are not rendered by default.

code/__DEFINES/_cooldowns.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898

9999
//* /mob *//
100100
#define TIMER_CD_INDEX_MOB_VERB_INVERT_SELF "mob-verb-invert_self"
101+
#define TIMER_CD_INDEX_MOB_VERB_PING_GMS "mob-verb-ping_gms"
101102

102103
//* /client *//
103104
#define TIMER_CD_INDEX_CLIENT_CHARACTER_DIRECTORY "client-verb-character_directory"

code/__DEFINES/_planes+layers.dm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,13 @@
332332
#define DEBUG_LAYER_MAP_HELPERS 250
333333
#define DEBUG_LAYER_SHUTTLE_MARKERS 500
334334

335+
/**
336+
*! -- Admin Plane
337+
*? For things like GM pings. This plane is only visible to admins.
338+
*/
339+
#define ADMIN_PLANE 24
340+
#define ADMIN_LAYER_GM_PING 100
341+
335342
/**
336343
*! -- Ghost Plane
337344
*? Where ghosts live.

code/__DEFINES/admin/verbs.dm

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/**
55
* Declares an admin verb.
66
*
7-
* * Verbs declared in this way will have the caller as `client/caller`. Do not define your
7+
* * Verbs declared in this way will have the calling client as `client/invoker`. Do not define your
88
* own client / usr calls.
99
* * You may safely assume that the verb is only accessible by them if they have the right permissions.
1010
* * Set `CATEGORY` to null to not have it show up in verb panel.
@@ -15,7 +15,7 @@
1515
/**
1616
* Declares an admin verb that does not show up in the popup menu.
1717
*
18-
* * Verbs declared in this way will have the caller as `client/caller`. Do not define your
18+
* * Verbs declared in this way will have the calling client as `client/invoker`. Do not define your
1919
* own client / usr calls.
2020
* * You may safely assume that the verb is only accessible by them if they have the right permissions.
2121
* * Set `CATEGORY` to null to not have it show up in verb panel.
@@ -44,11 +44,12 @@
4444
}; \
4545
do { \
4646
metric_increment_nested_numerical(/datum/metric/nested_numerical/admin_verb_invocation, #PATH_SUFFIX, 1); \
47+
log_admin("[key_name(usr)] invoked admin verb '[#PATH_SUFFIX]'"); \
4748
}; \
4849
while(FALSE); \
4950
call(usr.client, /datum/admin_verb_abstraction::verb__invoke_##PATH_SUFFIX())(arglist(list(usr.client) + args)); \
5051
}; \
51-
/datum/admin_verb_abstraction/proc/verb__invoke_##PATH_SUFFIX(client/caller, ##HEADER)
52+
/datum/admin_verb_abstraction/proc/verb__invoke_##PATH_SUFFIX(client/invoking, ##HEADER)
5253

5354
/**
5455
* Abstract datum with no variables. Used to hold the proc definitions for admin verbs.

code/__DEFINES/interface/verbs.dm

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
#define VERB_CATEGORY_OBJECT "Object"
77
#define VERB_CATEGORY_SYSTEM "System"
88

9-
// todo: admin verb categories too
10-
9+
/// For admin verbs only!
1110
#define VERB_CATEGORY_ADMIN "Admin"
11+
/// For admin verbs only!
1212
#define VERB_CATEGORY_DEBUG "Debug"
13+
/// For admin verbs only!
1314
#define VERB_CATEGORY_GAME "Game"
15+
/// For admin verbs only!
1416
#define VERB_CATEGORY_SERVER "Server"

code/__DEFINES/spans.dm

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,13 @@
154154
* Spans that use embedded tgui components:
155155
* Sorted alphabetically
156156
*/
157-
#define SPAN_TOOLTIP(tip, str) ("<span data-component=\"Tooltip\" data-content=\"[tip]\" class=\"tooltip\">[str]</span>")
157+
158+
/// Displays a tooltip. Tooltip is text-only, and HTML will be ignored.
159+
/// * SPAN_LINKIFY doesn't work here.
160+
#define SPAN_TOOLTIP(tip, str) ("<span data-component=\"Tooltip\" data-content=\"[html_encode(tip)]\" class=\"tooltip\">[str]</span>")
161+
/// Displays a tooltip. Accepts HTML. For the love of all that is holy, ensure input is trusted.
162+
/// * SPAN_LINKIFY doesn't work here.
163+
#define SPAN_TOOLTIP_DANGEROUS_HTML(tip, str) ("<span data-component=\"TooltipHTML\" data-html=\"[html_encode(tip)]\" class=\"tooltip\">[str]</span>")
158164

159165
/**
160166
* Special Macros
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
3+
4+
/**
5+
* Projects a context tag up to the world for admins to see.
6+
*/
7+
/datum/component/gm_ping
8+
registered_type = /datum/component/gm_ping
9+
dupe_mode = COMPONENT_DUPE_ALLOWED
10+
/// owning datum
11+
var/datum/gm_ping/owner
12+
13+
/datum/component/gm_ping/Initialize(datum/gm_ping/owner)
14+
. = ..()
15+
if(. == COMPONENT_INCOMPATIBLE)
16+
return
17+
src.owner = owner
18+
19+
/datum/component/gm_ping/Destroy()
20+
owner.context_component = null
21+
return ..()
22+
23+
/datum/component/gm_ping/RegisterWithParent()
24+
..()
25+
construct()
26+
if(ismovable(parent))
27+
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(update))
28+
RegisterSignal(parent, COMSIG_PARENT_PREQDELETED, PROC_REF(on_parent_preqdel))
29+
30+
/datum/component/gm_ping/UnregisterFromParent()
31+
..()
32+
if(ismovable(parent))
33+
UnregisterSignal(parent, COMSIG_MOVABLE_MOVED)
34+
teardown()
35+
36+
/datum/component/gm_ping/proc/update(atom/source, atom/old_loc)
37+
if(source.loc == old_loc)
38+
return
39+
// don't need to re-update if we're going from turf to turf; we register on movable only,
40+
// unless the component itself is on a turf.
41+
if(isturf(source.loc) && isturf(old_loc))
42+
return
43+
teardown(old_loc)
44+
construct(source.loc)
45+
46+
/datum/component/gm_ping/proc/on_parent_preqdel(atom/source)
47+
SIGNAL_HANDLER
48+
owner.pull_ui_panel_context_data()
49+
50+
/datum/component/gm_ping/proc/teardown(atom/root = parent:loc)
51+
var/atom/last = parent
52+
while(ismovable(root))
53+
UnregisterSignal(root, COMSIG_MOVABLE_MOVED, PROC_REF(update))
54+
last = root
55+
root = root.loc
56+
var/datum/component/gm_ping_topmost/holder = last.LoadComponent(/datum/component/gm_ping_topmost)
57+
holder.remove_ping(src)
58+
59+
/datum/component/gm_ping/proc/construct(atom/root = parent:loc)
60+
var/atom/last = parent
61+
while(ismovable(root))
62+
RegisterSignal(root, COMSIG_MOVABLE_MOVED, PROC_REF(update))
63+
last = root
64+
root = root.loc
65+
var/datum/component/gm_ping_topmost/holder = last.LoadComponent(/datum/component/gm_ping_topmost)
66+
holder.add_ping(src)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
3+
4+
/datum/component/gm_ping_topmost
5+
registered_type = /datum/component/gm_ping_topmost
6+
/// components part of us
7+
var/list/datum/component/gm_ping/pings = list()
8+
/// renderer
9+
var/atom/movable/render/gm_ping_topmost/renderer
10+
11+
/datum/component/gm_ping_topmost/Initialize()
12+
. = ..()
13+
if(. == COMPONENT_INCOMPATIBLE)
14+
return
15+
if(!isatom(parent))
16+
return COMPONENT_INCOMPATIBLE
17+
18+
/datum/component/gm_ping_topmost/Destroy()
19+
qdel(renderer)
20+
return ..()
21+
22+
/datum/component/gm_ping_topmost/proc/add_ping(datum/component/gm_ping/ping)
23+
pings += ping
24+
update_render()
25+
26+
/datum/component/gm_ping_topmost/proc/remove_ping(datum/component/gm_ping/ping)
27+
pings -= ping
28+
if(!length(pings))
29+
qdel(src)
30+
else
31+
update_render()
32+
33+
/datum/component/gm_ping_topmost/proc/update_render()
34+
if(!renderer)
35+
renderer = new(parent, src)
36+
renderer.update()
37+
if(renderer.loc != parent)
38+
renderer.abstract_move(parent)
39+
stack_trace("a gm ping render somehow got moved..?")

code/datums/gm_ping.dm

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
//* This file is explicitly licensed under the MIT license. *//
2+
//* Copyright (c) 2025 Citadel Station Developers *//
3+
4+
GLOBAL_LIST_EMPTY_TYPED(gm_pings, /datum/gm_ping)
5+
GLOBAL_VAR_INIT(gm_ping_ghost_allowed, FALSE)
6+
7+
/**
8+
* Contextual GM ping system.
9+
*/
10+
/datum/gm_ping
11+
/// unique id, lazy
12+
/// * not for persistent purposes, that comes later
13+
/// * not guaranteed to be unique, just used to filter/resolve with ref()
14+
var/lazy_unsafe_uid
15+
var/static/lazy_unsafe_uid_next = 0
16+
17+
/// originating ckey
18+
var/originating_ckey
19+
/// originating key because it's prettier than ckey
20+
var/originating_key
21+
22+
/// where was the ping made?
23+
var/turf/created_at
24+
25+
/// originating mob weakref, if any
26+
var/datum/weakref/originating_mob_weakref
27+
/// cached tgui data for originating mob if it's deleted, if any
28+
var/list/originating_mob_ui_data_snapshot
29+
30+
/// original message. NOT SANITIZED. treat as saycode pre-parse.
31+
var/unsanitized_message
32+
33+
/// linked component. if it exists, we have in-world-context using it.
34+
var/datum/component/gm_ping/context_component
35+
/// linked component ui data snapshot if it's deleted, if any
36+
var/list/context_component_ui_data_snapshot
37+
38+
/datum/gm_ping/New()
39+
++lazy_unsafe_uid_next
40+
if(lazy_unsafe_uid_next >= SHORT_REAL_LIMIT)
41+
lazy_unsafe_uid_next = -(SHORT_REAL_LIMIT - 1)
42+
lazy_unsafe_uid = num2text(lazy_unsafe_uid_next, 999)
43+
44+
/datum/gm_ping/Destroy()
45+
originating_mob_weakref = null
46+
GLOB.gm_pings -= src
47+
QDEL_NULL(context_component)
48+
return ..()
49+
50+
/datum/gm_ping/proc/chat_output()
51+
var/rendered = say_emphasis(html_encode(unsanitized_message))
52+
return "[lazy_unsafe_uid] @ [context_component?.parent] - From '[originating_ckey]', a '[SPAN_TOOLTIP(rendered, "[length_char(unsanitized_message)] character message")]'"
53+
54+
/datum/gm_ping/proc/link_context(atom/target)
55+
if(context_component)
56+
QDEL_NULL(context_component)
57+
if(target)
58+
context_component = target.AddComponent(/datum/component/gm_ping, src)
59+
if(QDELETED(context_component))
60+
context_component = null
61+
62+
// for stuff that may change; refreshing will pull an update
63+
/datum/gm_ping/proc/ui_panel_data()
64+
return list(
65+
"pingOrigination" = pull_ui_panel_mob_data(),
66+
"pingContext" = pull_ui_panel_context_data(),
67+
)
68+
69+
// for stuff that never changes; even refreshing won't change it
70+
/datum/gm_ping/proc/ui_panel_static_data()
71+
return list(
72+
"ref" = ref(src),
73+
"lazyUid" = lazy_unsafe_uid,
74+
"playerCkey" = originating_ckey,
75+
"playerKey" = originating_key,
76+
// DO NOT REMOVE THE FUCKING HTML ENCODE OR YOU WILL XSS THE ADMINS!!!
77+
"messageAsHtml" = say_emphasis(html_encode(unsanitized_message)),
78+
"pingLocation" = encode_ui_panel_location_data(),
79+
)
80+
81+
/datum/gm_ping/proc/encode_ui_location(atom/target)
82+
. = list()
83+
var/turf/l_turf = get_turf(target)
84+
if(l_turf)
85+
.["coords"] = list(
86+
"name" = l_turf.name,
87+
"x" = l_turf.x,
88+
"y" = l_turf.y,
89+
"z" = l_turf.z,
90+
)
91+
else
92+
.["coords"] = null
93+
if(l_turf)
94+
var/datum/map/l_map = SSmapping.ordered_levels[l_turf.z]?.parent_map
95+
if(l_map)
96+
.["sector"] = list(
97+
"id" = l_map.id,
98+
"name" = l_map.name,
99+
)
100+
else
101+
.["sector"] = null
102+
var/obj/overmap/entity/l_overmap = get_overmap_sector(l_turf)
103+
if(l_overmap)
104+
.["overmap"] = list(
105+
"entity" = l_overmap.name,
106+
"x" = l_overmap.get_tile_x_f(),
107+
"y" = l_overmap.get_tile_y_f(),
108+
"map" = l_overmap.overmap?.name,
109+
)
110+
else
111+
.["overmap"] = null
112+
else
113+
.["sector"] = null
114+
.["overmap"] = null
115+
116+
/datum/gm_ping/proc/encode_ui_panel_location_data()
117+
return list(
118+
"name" = created_at.name,
119+
"location" = encode_ui_location(created_at),
120+
)
121+
122+
/datum/gm_ping/proc/encode_ui_panel_mob_data(mob/target)
123+
return list(
124+
"name" = target.real_name,
125+
"visibleName" = target.name,
126+
"location" = encode_ui_location(target)
127+
)
128+
129+
/datum/gm_ping/proc/pull_ui_panel_mob_data()
130+
var/mob/resolved = originating_mob_weakref?.resolve()
131+
if(resolved)
132+
var/list/encoded = encode_ui_panel_mob_data(resolved)
133+
originating_mob_ui_data_snapshot = encoded
134+
return list(
135+
"deleted" = FALSE,
136+
"data" = encoded,
137+
)
138+
else if(originating_mob_ui_data_snapshot)
139+
return list(
140+
"deleted" = TRUE,
141+
"data" = originating_mob_ui_data_snapshot,
142+
)
143+
else
144+
// if we never got a snapshot for some reason treat it as gone
145+
return null
146+
147+
/datum/gm_ping/proc/encode_ui_panel_context_data(datum/component/gm_ping/target)
148+
return list(
149+
// bite me it's an /atom component
150+
"name" = target.parent:name,
151+
"location" = encode_ui_location(target.parent),
152+
"ref" = REF(target.parent),
153+
)
154+
155+
/datum/gm_ping/proc/pull_ui_panel_context_data()
156+
if(QDELETED(context_component))
157+
if(context_component_ui_data_snapshot)
158+
return list(
159+
"deleted" = TRUE,
160+
"data" = context_component_ui_data_snapshot,
161+
)
162+
// if we never got a snapshot for some reason treat it as gone
163+
else
164+
return null
165+
else
166+
var/list/encoded = encode_ui_panel_context_data(context_component)
167+
context_component_ui_data_snapshot = encoded
168+
return list(
169+
"deleted" = FALSE,
170+
"data" = encoded,
171+
)

code/datums/mind.dm

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,11 @@
168168
associate(new_character)
169169
return
170170

171-
var/mob/old_character = current
172-
173171
disassociate()
174172

175173
if(!isnull(new_character.mind))
176174
new_character.mind.disassociate()
177175

178-
SStgui.on_transfer(old_character, new_character)
179-
SSnanoui.user_transferred(old_character, new_character)
180-
181176
associate(new_character)
182177

183178
/datum/mind/proc/store_memory(new_text)

0 commit comments

Comments
 (0)