/
login.dm
158 lines (132 loc) · 5.42 KB
/
login.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* Run when a client is put in this mob or reconnets to byond and their client was on this mob.
* Anything that sleeps can result in the client reference being dropped, due to byond using that sleep to handle a client disconnect.
* You can save a lot of headache if you make Login use SHOULD_NOT_SLEEP, but that would require quite a bit of refactoring how Login code works.
*
* Things it does:
* * Adds player to player_list
* * sets lastKnownIP
* * sets computer_id
* * logs the login
* * tells the world to update it's status (for player count)
* * create mob huds for the mob if needed
* * reset next_move to 1
* * Set statobj to our mob
* * NOT the parent call. The only unique thing it does is a very obtuse move op, see the comment lower down
* * if the client exists set the perspective to the mob loc
* * call on_log on the loc (sigh)
* * reload the huds for the mob
* * reload all full screen huds attached to this mob
* * load any global alternate apperances
* * sync the mind datum via sync_mind()
* * call any client login callbacks that exist
* * grant any actions the mob has to the client
* * calls [auto_deadmin_on_login](mob.html#proc/auto_deadmin_on_login)
* * send signal COMSIG_MOB_CLIENT_LOGIN
* * attaches the ash listener element so clients can hear weather
* client can be deleted mid-execution of this proc, chiefly on parent calls, with lag
*/
/mob/Login()
if(!client)
return FALSE
canon_client = client
add_to_player_list()
lastKnownIP = client.address
computer_id = client.computer_id
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()
client.set_right_click_menu_mode(shift_to_open_context_menu)
if(!hud_used)
create_mob_hud() // creating a hud will add it to the client's screen, which can process a disconnect
if(!client)
return FALSE
if(hud_used)
hud_used.show_hud(hud_used.hud_version) // see above, this can process a disconnect
if(!client)
return FALSE
hud_used.update_ui_style(ui_style2icon(client.prefs?.read_preference(/datum/preference/choiced/ui_style)))
next_move = 1
client.statobj = src
// DO NOT CALL PARENT HERE
// BYOND's internal implementation of login does two things
// 1: Set statobj to the mob being logged into (We got this covered)
// 2: And I quote "If the mob has no location, place it near (1,1,1) if possible"
// See, near is doing an agressive amount of legwork there
// What it actually does is takes the area that (1,1,1) is in, and loops through all those turfs
// If you successfully move into one, it stops
// Because we want Move() to mean standard movements rather then just what byond treats it as (ALL moves)
// We don't allow moves from nullspace -> somewhere. This means the loop has to iterate all the turfs in (1,1,1)'s area
// For us, (1,1,1) is a space tile. This means roughly 200,000! calls to Move()
// You do not want this
if(!client)
return FALSE
enable_client_mobs_in_contents(client)
SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
if (key != client.key)
key = client.key
reset_perspective(loc)
if(loc)
loc.on_log(TRUE)
//readd this mob's HUDs (antag, med, etc)
reload_huds()
reload_fullscreen() // Reload any fullscreen overlays this mob has.
add_click_catcher()
sync_mind()
//Reload alternate appearances
for(var/v in GLOB.active_alternate_appearances)
if(!v)
continue
var/datum/atom_hud/alternate_appearance/AA = v
AA.onNewMob(src)
update_client_colour()
update_mouse_pointer()
refresh_looping_ambience()
if(client)
if(client.view_size)
client.view_size.resetToDefault() // Resets the client.view in case it was changed.
else
client.change_view(getScreenSize(client.prefs.read_preference(/datum/preference/toggle/widescreen)))
if(client.player_details.player_actions.len)
for(var/datum/action/A in client.player_details.player_actions)
A.Grant(src)
for(var/foo in client.player_details.post_login_callbacks)
var/datum/callback/CB = foo
CB.Invoke()
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)
log_mob_tag("TAG: [tag] NEW OWNER: [key_name(src)]")
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
SEND_SIGNAL(client, COMSIG_CLIENT_MOB_LOGIN, src)
client.init_verbs()
AddElement(/datum/element/weather_listener, /datum/weather/ash_storm, ZTRAIT_ASHSTORM, GLOB.ash_storm_sounds)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_LOGGED_IN, src)
return TRUE
/**
* Checks if the attached client is an admin and may deadmin them
*
* Configs:
* * flag/auto_deadmin_players
* * client.prefs?.toggles & DEADMIN_ALWAYS
* * User is antag and flag/auto_deadmin_antagonists or client.prefs?.toggles & DEADMIN_ANTAGONIST
* * or if their job demands a deadminning SSjob.handle_auto_deadmin_roles()
*
* Called from [login](mob.html#proc/Login)
*/
/mob/proc/auto_deadmin_on_login() //return true if they're not an admin at the end.
if(!client?.holder)
return TRUE
if(CONFIG_GET(flag/auto_deadmin_players) || (client.prefs?.toggles & DEADMIN_ALWAYS))
return client.holder.auto_deadmin()
if(mind.has_antag_datum(/datum/antagonist) && (CONFIG_GET(flag/auto_deadmin_antagonists) || client.prefs?.toggles & DEADMIN_ANTAGONIST))
return client.holder.auto_deadmin()
if(job)
return SSjob.handle_auto_deadmin_roles(client, job)