mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-20 15:21:29 +00:00
world/Topic Refactor (#14850)
* world/Topic Refactor * These arent needed anymore * How could I forget this * Biggest edit ever * Forgot this * Mini refactor
This commit is contained in:
@@ -117,6 +117,17 @@
|
||||
if(R.selectable)
|
||||
GLOB.selectable_robolimbs[R.company] = R
|
||||
|
||||
// Setup world topic handlers
|
||||
for(var/topic_handler_type in subtypesof(/datum/world_topic_handler))
|
||||
var/datum/world_topic_handler/wth = new topic_handler_type()
|
||||
if(!wth.topic_key)
|
||||
stack_trace("[wth.type] has no topic key!")
|
||||
continue
|
||||
if(GLOB.world_topic_handlers[wth.topic_key])
|
||||
stack_trace("[wth.type] has the same topic key as [GLOB.world_topic_handlers[wth.topic_key]]! ([wth.topic_key])")
|
||||
continue
|
||||
GLOB.world_topic_handlers[wth.topic_key] = topic_handler_type
|
||||
|
||||
/* // Uncomment to debug chemical reaction list.
|
||||
/client/verb/debug_chemical_list()
|
||||
|
||||
|
||||
@@ -55,242 +55,41 @@ GLOBAL_LIST_INIT(map_transition_config, MAP_TRANSITION_CONFIG)
|
||||
investigate_reset() // This is part of the admin investigate system. PLEASE DONT SS THIS EITHER
|
||||
makeDatumRefLists() // Setups up lists of datums and their subtypes
|
||||
|
||||
//world/Topic(href, href_list[])
|
||||
// to_chat(world, "Received a Topic() call!")
|
||||
// to_chat(world, "[href]")
|
||||
// for(var/a in href_list)
|
||||
// to_chat(world, "[a]")
|
||||
// if(href_list["hello"])
|
||||
// to_chat(world, "Hello world!")
|
||||
// return "Hello world!"
|
||||
// to_chat(world, "End of Topic() call.")
|
||||
// ..()
|
||||
/// List of all world topic spam prevention handlers. See code/modules/world_topic/_spam_prevention_handler.dm
|
||||
GLOBAL_LIST_EMPTY(world_topic_spam_prevention_handlers)
|
||||
/// List of all world topic handler datums. Populated inside makeDatumRefLists()
|
||||
GLOBAL_LIST_EMPTY(world_topic_handlers)
|
||||
|
||||
GLOBAL_VAR_INIT(world_topic_spam_protect_ip, "0.0.0.0")
|
||||
GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday)
|
||||
|
||||
/world/Topic(T, addr, master, key)
|
||||
TGS_TOPIC
|
||||
log_misc("WORLD/TOPIC: \"[T]\", from:[addr], master:[master], key:[key]")
|
||||
|
||||
// Handle spam prevention
|
||||
if(!GLOB.world_topic_spam_prevention_handlers[address])
|
||||
GLOB.world_topic_spam_prevention_handlers[address] = new /datum/world_topic_spam_prevention_handler
|
||||
|
||||
var/datum/world_topic_spam_prevention_handler/sph = GLOB.world_topic_spam_prevention_handlers[address]
|
||||
|
||||
// Lock the user out and cancel their topic if needed
|
||||
if(sph.check_lockout())
|
||||
return
|
||||
|
||||
var/list/input = params2list(T)
|
||||
var/key_valid = (config.comms_password && input["key"] == config.comms_password) //no password means no comms, not any password
|
||||
|
||||
if("ping" in input)
|
||||
var/x = 1
|
||||
for(var/client/C)
|
||||
x++
|
||||
return x
|
||||
var/datum/world_topic_handler/wth
|
||||
|
||||
else if("players" in input)
|
||||
var/n = 0
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client)
|
||||
n++
|
||||
return n
|
||||
|
||||
else if("status" in input)
|
||||
var/list/s = list()
|
||||
var/list/admins = list()
|
||||
s["version"] = GLOB.game_version
|
||||
s["mode"] = GLOB.master_mode
|
||||
s["respawn"] = config ? GLOB.abandon_allowed : 0
|
||||
s["enter"] = GLOB.enter_allowed
|
||||
s["vote"] = config.allow_vote_mode
|
||||
s["ai"] = config.allow_ai
|
||||
s["host"] = host ? host : null
|
||||
s["players"] = list()
|
||||
s["roundtime"] = worldtime2text()
|
||||
s["stationtime"] = station_time_timestamp()
|
||||
s["oldstationtime"] = classic_worldtime2text() // more "consistent" indication of the round's running time
|
||||
s["listed"] = "Public"
|
||||
if(!hub_password)
|
||||
s["listed"] = "Invisible"
|
||||
var/player_count = 0
|
||||
var/admin_count = 0
|
||||
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(C.holder)
|
||||
if(C.holder.fakekey)
|
||||
continue //so stealthmins aren't revealed by the hub
|
||||
admin_count++
|
||||
admins += list(list(C.key, C.holder.rank))
|
||||
s["player[player_count]"] = C.key
|
||||
player_count++
|
||||
s["players"] = player_count
|
||||
s["admins"] = admin_count
|
||||
s["map_name"] = GLOB.map_name ? GLOB.map_name : "Unknown"
|
||||
|
||||
if(key_valid)
|
||||
if(SSticker && SSticker.mode)
|
||||
s["real_mode"] = SSticker.mode.name
|
||||
s["security_level"] = get_security_level()
|
||||
s["ticker_state"] = SSticker.current_state
|
||||
|
||||
if(SSshuttle && SSshuttle.emergency)
|
||||
// Shuttle status, see /__DEFINES/stat.dm
|
||||
s["shuttle_mode"] = SSshuttle.emergency.mode
|
||||
// Shuttle timer, in seconds
|
||||
s["shuttle_timer"] = SSshuttle.emergency.timeLeft()
|
||||
|
||||
for(var/i in 1 to admins.len)
|
||||
var/list/A = admins[i]
|
||||
s["admin[i - 1]"] = A[1]
|
||||
s["adminrank[i - 1]"] = A[2]
|
||||
|
||||
return list2params(s)
|
||||
|
||||
else if("manifest" in input)
|
||||
var/list/positions = list()
|
||||
var/list/set_names = list(
|
||||
"heads" = GLOB.command_positions,
|
||||
"sec" = GLOB.security_positions,
|
||||
"eng" = GLOB.engineering_positions,
|
||||
"med" = GLOB.medical_positions,
|
||||
"sci" = GLOB.science_positions,
|
||||
"car" = GLOB.supply_positions,
|
||||
"srv" = GLOB.service_positions,
|
||||
"civ" = GLOB.civilian_positions,
|
||||
"bot" = GLOB.nonhuman_positions
|
||||
)
|
||||
|
||||
for(var/datum/data/record/t in GLOB.data_core.general)
|
||||
var/name = t.fields["name"]
|
||||
var/rank = t.fields["rank"]
|
||||
var/real_rank = t.fields["real_rank"]
|
||||
|
||||
var/department = 0
|
||||
for(var/k in set_names)
|
||||
if(real_rank in set_names[k])
|
||||
if(!positions[k])
|
||||
positions[k] = list()
|
||||
positions[k][name] = rank
|
||||
department = 1
|
||||
if(!department)
|
||||
if(!positions["misc"])
|
||||
positions["misc"] = list()
|
||||
positions["misc"][name] = rank
|
||||
|
||||
return json_encode(positions)
|
||||
|
||||
else if("adminmsg" in input)
|
||||
/*
|
||||
We got an adminmsg from IRC bot lets split the input then validate the input.
|
||||
expected output:
|
||||
1. adminmsg = ckey of person the message is to
|
||||
2. msg = contents of message, parems2list requires
|
||||
3. validatationkey = the key the bot has, it should match the gameservers commspassword in it's configuration.
|
||||
4. sender = the ircnick that send the message.
|
||||
*/
|
||||
if(!key_valid)
|
||||
return keySpamProtect(addr)
|
||||
|
||||
var/client/C
|
||||
|
||||
for(var/client/K in GLOB.clients)
|
||||
if(K.ckey == input["adminmsg"])
|
||||
C = K
|
||||
for(var/H in GLOB.world_topic_handlers)
|
||||
if(H in input)
|
||||
wth = GLOB.world_topic_handlers[H]
|
||||
break
|
||||
if(!C)
|
||||
return "No client with that name on server"
|
||||
|
||||
var/message = "<font color='red'>Discord PM from <b><a href='?discord_msg=1'>[input["sender"]]</a></b>: [input["msg"]]</font>"
|
||||
var/amessage = "<font color='blue'>Discord PM from <a href='?discord_msg=1'>[input["sender"]]</a> to <b>[key_name(C)]</b>: [input["msg"]]</font>"
|
||||
if(!wth)
|
||||
return
|
||||
|
||||
// THESE TWO VARS DO VERY DIFFERENT THINGS. DO NOT ATTEMPT TO COMBINE THEM
|
||||
C.received_discord_pm = world.time
|
||||
C.last_discord_pm_time = 0
|
||||
|
||||
SEND_SOUND(C, 'sound/effects/adminhelp.ogg')
|
||||
to_chat(C, message)
|
||||
|
||||
for(var/client/A in GLOB.admins)
|
||||
if(A != C)
|
||||
to_chat(A, amessage)
|
||||
|
||||
return "Message Successful"
|
||||
|
||||
else if("notes" in input)
|
||||
/*
|
||||
We got a request for notes from the IRC Bot
|
||||
expected output:
|
||||
1. notes = ckey of person the notes lookup is for
|
||||
2. validationkey = the key the bot has, it should match the gameservers commspassword in it's configuration.
|
||||
*/
|
||||
if(!key_valid)
|
||||
return keySpamProtect(addr)
|
||||
|
||||
return show_player_info_irc(input["notes"])
|
||||
|
||||
else if("announce" in input)
|
||||
if(config.comms_password)
|
||||
if(input["key"] != config.comms_password)
|
||||
return "Bad Key"
|
||||
else
|
||||
var/prtext = input["announce"]
|
||||
var/pr_substring = copytext(prtext, 1, 23)
|
||||
if(pr_substring == "Pull Request merged by")
|
||||
GLOB.pending_server_update = TRUE
|
||||
for(var/client/C in GLOB.clients)
|
||||
to_chat(C, "<span class='announce'>PR: [prtext]</span>")
|
||||
|
||||
else if("kick" in input)
|
||||
/*
|
||||
We have a kick request over coms.
|
||||
Only needed portion is the ckey
|
||||
*/
|
||||
if(!key_valid)
|
||||
return keySpamProtect(addr)
|
||||
|
||||
var/client/C
|
||||
|
||||
for(var/client/K in GLOB.clients)
|
||||
if(K.ckey == input["kick"])
|
||||
C = K
|
||||
break
|
||||
if(!C)
|
||||
return "No client with that name on server"
|
||||
|
||||
qdel(C)
|
||||
|
||||
return "Kick Successful"
|
||||
|
||||
else if("setlog" in input)
|
||||
if(!key_valid)
|
||||
return keySpamProtect(addr)
|
||||
|
||||
SetupLogs()
|
||||
|
||||
return "Logs set to current date"
|
||||
|
||||
else if("setlist" in input)
|
||||
if(!key_valid)
|
||||
return keySpamProtect(addr)
|
||||
if(input["req"] == "public")
|
||||
hub_password = initial(hub_password)
|
||||
update_status()
|
||||
return "Set listed status to public."
|
||||
else
|
||||
hub_password = ""
|
||||
update_status()
|
||||
return "Set listed status to invisible."
|
||||
|
||||
|
||||
else if("hostannounce" in input)
|
||||
if(!key_valid)
|
||||
return keySpamProtect(addr)
|
||||
GLOB.pending_server_update = TRUE
|
||||
to_chat(world, "<hr><span style='color: #12A5F4'><b>Server Announcement:</b> [input["message"]]</span><hr>")
|
||||
|
||||
/proc/keySpamProtect(var/addr)
|
||||
if(GLOB.world_topic_spam_protect_ip == addr && abs(GLOB.world_topic_spam_protect_time - world.time) < 50)
|
||||
spawn(50)
|
||||
GLOB.world_topic_spam_protect_time = world.time
|
||||
return "Bad Key (Throttled)"
|
||||
|
||||
GLOB.world_topic_spam_protect_time = world.time
|
||||
GLOB.world_topic_spam_protect_ip = addr
|
||||
return "Bad Key"
|
||||
// If we are here, the handler exists, so it needs to be invoked
|
||||
wth = new wth()
|
||||
return wth.invoke(input)
|
||||
|
||||
/world/Reboot(var/reason, var/feedback_c, var/feedback_r, var/time)
|
||||
TgsReboot()
|
||||
|
||||
@@ -202,18 +202,3 @@
|
||||
output += ruler
|
||||
usr << browse(output, "window=show_notes;size=900x500")
|
||||
|
||||
/proc/show_player_info_irc(var/key as text)
|
||||
var/target_sql_ckey = ckey(key)
|
||||
var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT timestamp, notetext, adminckey, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp")
|
||||
if(!query_get_notes.Execute())
|
||||
var/err = query_get_notes.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining timestamp, notetext, adminckey, server, crew_playtime from notes table. Error : \[[err]\]\n")
|
||||
return
|
||||
var/output = " Info on [key]%0D%0A"
|
||||
while(query_get_notes.NextRow())
|
||||
var/timestamp = query_get_notes.item[1]
|
||||
var/notetext = query_get_notes.item[2]
|
||||
var/adminckey = query_get_notes.item[3]
|
||||
var/server = query_get_notes.item[4]
|
||||
output += "[notetext]%0D%0Aby [adminckey] on [timestamp] (Server: [server])%0D%0A%0D%0A"
|
||||
return output
|
||||
|
||||
5
code/modules/world_topic/README.MD
Normal file
5
code/modules/world_topic/README.MD
Normal file
@@ -0,0 +1,5 @@
|
||||
# NOTE
|
||||
|
||||
Please keep things in this directory standardised!
|
||||
|
||||
This means one topic handler per DM file, and the filename being the key. For an example, see `ping.dm`
|
||||
63
code/modules/world_topic/_spam_prevention_handler.dm
Normal file
63
code/modules/world_topic/_spam_prevention_handler.dm
Normal file
@@ -0,0 +1,63 @@
|
||||
#define WORLD_TOPIC_STRIKES_THRESHOLD 5
|
||||
#define WORLD_TOPIC_LOCKOUT_TIME 1 MINUTES
|
||||
|
||||
/datum/world_topic_spam_prevention_handler
|
||||
/// Amount of strikes. [WORLD_TOPIC_STRIKES_THRESHOLD] strikes is a lockout of [WORLD_TOPIC_LOCKOUT_TIME]
|
||||
var/strikes = 0
|
||||
/// Time of last request
|
||||
var/last_request = 0
|
||||
/// Is this IP currently locked out
|
||||
var/locked_out = FALSE
|
||||
/// Unlock time
|
||||
var/unlock_time = 0
|
||||
|
||||
/**
|
||||
* Lockout handler
|
||||
*
|
||||
* Updates strikes and timers of the most recent client to topic the server
|
||||
* including any relevant detail
|
||||
*/
|
||||
/datum/world_topic_spam_prevention_handler/proc/check_lockout()
|
||||
// Check if they are already locked out
|
||||
if(locked_out && (unlock_time >= world.time))
|
||||
// Relock out for another minute if youre spamming
|
||||
unlock_time = world.time + WORLD_TOPIC_LOCKOUT_TIME
|
||||
return TRUE
|
||||
|
||||
// If they were locked out and are now allowed, unlock them
|
||||
if(locked_out && (unlock_time < world.time))
|
||||
strikes = 0
|
||||
locked_out = FALSE
|
||||
|
||||
// Allow a grace period of 0.5 seconds per topic, or you get a strike
|
||||
if(last_request + 5 > world.time)
|
||||
strikes++
|
||||
if(strikes >= WORLD_TOPIC_STRIKES_THRESHOLD)
|
||||
locked_out = TRUE
|
||||
unlock_time = world.time + WORLD_TOPIC_LOCKOUT_TIME
|
||||
return TRUE
|
||||
|
||||
// If we got here, assume they arent locked out
|
||||
last_request = world.time
|
||||
return FALSE
|
||||
|
||||
/*
|
||||
|
||||
Uncomment this if you modify the topic limiter, trust me, youll need to test it
|
||||
|
||||
/client/verb/debug_limiter()
|
||||
if(!GLOB.world_topic_spam_prevention_handlers[address])
|
||||
GLOB.world_topic_spam_prevention_handlers[address] = new /datum/world_topic_spam_prevention_handler
|
||||
|
||||
var/datum/world_topic_spam_prevention_handler/sph = GLOB.world_topic_spam_prevention_handlers[address]
|
||||
var/result = sph.check_lockout()
|
||||
to_chat(usr, "Strikes: [sph.strikes]")
|
||||
to_chat(usr, "Last request: [sph.last_request]")
|
||||
to_chat(usr, "Locked out: [sph.locked_out]")
|
||||
to_chat(usr, "Unlock time: [sph.unlock_time]")
|
||||
to_chat(usr, "SPH Result: [result]")
|
||||
to_chat(usr, "World.time: [world.time]")
|
||||
to_chat(usr, "LR DIFF: [(sph.last_request - world.time)/10]s")
|
||||
to_chat(usr, "LO DIFF: [(sph.unlock_time - world.time)/10]s")
|
||||
to_chat(usr, "<hr>")
|
||||
*/
|
||||
36
code/modules/world_topic/_topic_base.dm
Normal file
36
code/modules/world_topic/_topic_base.dm
Normal file
@@ -0,0 +1,36 @@
|
||||
/datum/world_topic_handler
|
||||
/// Key which invokes this topic
|
||||
var/topic_key
|
||||
/// Set this to TRUE if the topic handler needs an authorised comms key
|
||||
var/requires_commskey = FALSE
|
||||
|
||||
|
||||
/**
|
||||
* Invokes the world/Topic handler
|
||||
*
|
||||
* This includes sanity checking for if the key is required, as well as other sanity checks
|
||||
* DO NOT OVERRIDE
|
||||
* Arguments:
|
||||
* * input - The list of topic data, sent from [world/Topic]
|
||||
*/
|
||||
/datum/world_topic_handler/proc/invoke(list/input)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
var/authorised = (config.comms_password && input["key"] == config.comms_password) // No password means no comms, not any password
|
||||
if(requires_commskey && !authorised)
|
||||
// Try keep all returns in JSON unless absolutely necessary (?ping for example)
|
||||
return(json_encode(list("error" = "Invalid Key")))
|
||||
|
||||
return execute(input, authorised)
|
||||
|
||||
/**
|
||||
* Actually executes the user's topic
|
||||
*
|
||||
* Override this to do your work in subtypes of this topic
|
||||
*
|
||||
* Arguments:
|
||||
* * input - The list of topic data, sent from [world/Topic]
|
||||
* * key_valid - Has the user entered the correct auth key
|
||||
*/
|
||||
/datum/world_topic_handler/proc/execute(list/input, key_valid = FALSE)
|
||||
PRIVATE_PROC(TRUE) // Ensures no one can call this arbitrarily without checking key auth
|
||||
CRASH("execute() not implemented/overridden for [type]")
|
||||
38
code/modules/world_topic/adminmsg.dm
Normal file
38
code/modules/world_topic/adminmsg.dm
Normal file
@@ -0,0 +1,38 @@
|
||||
/datum/world_topic_handler/adminmsg
|
||||
topic_key = "adminmsg"
|
||||
requires_commskey = TRUE
|
||||
|
||||
/datum/world_topic_handler/adminmsg/execute(list/input, key_valid)
|
||||
/*
|
||||
We got an adminmsg from the Discord bot, so lets split the input then validate the input. Expected output:
|
||||
1. adminmsg = ckey of person the message is to
|
||||
2. msg = contents of message, params2list requires
|
||||
3. sender = the discord name that send the message.
|
||||
*/
|
||||
|
||||
var/client/C
|
||||
|
||||
for(var/client/K in GLOB.clients)
|
||||
if(K.ckey == input["adminmsg"])
|
||||
C = K
|
||||
break
|
||||
if(!C)
|
||||
return json_encode(list("error" = "No client with that name on server"))
|
||||
|
||||
var/message = "<font color='red'>Discord PM from <b><a href='?discord_msg=1'>[input["sender"]]</a></b>: [input["msg"]]</font>"
|
||||
var/amessage = "<font color='blue'>Discord PM from <a href='?discord_msg=1'>[input["sender"]]</a> to <b>[key_name_admin(C)]</b>: [input["msg"]]</font>"
|
||||
|
||||
// THESE TWO VARS DO VERY DIFFERENT THINGS. DO NOT ATTEMPT TO COMBINE THEM
|
||||
C.received_discord_pm = world.time
|
||||
C.last_discord_pm_time = 0
|
||||
|
||||
SEND_SOUND(C, 'sound/effects/adminhelp.ogg')
|
||||
to_chat(C, message)
|
||||
|
||||
for(var/client/A in GLOB.admins)
|
||||
// GLOB.admins includes anyone with a holder datum (mentors too). This makes sure only admins see ahelps
|
||||
if(check_rights(R_ADMIN, FALSE, A.mob))
|
||||
if(A != C)
|
||||
to_chat(A, amessage)
|
||||
|
||||
return json_encode(list("success" = "Message Successful"))
|
||||
11
code/modules/world_topic/announce.dm
Normal file
11
code/modules/world_topic/announce.dm
Normal file
@@ -0,0 +1,11 @@
|
||||
/datum/world_topic_handler/announce
|
||||
topic_key = "announce"
|
||||
requires_commskey = TRUE
|
||||
|
||||
/datum/world_topic_handler/announce/execute(list/input, key_valid)
|
||||
var/prtext = input["announce"]
|
||||
var/pr_substring = copytext(prtext, 1, 23)
|
||||
if(pr_substring == "Pull Request merged by")
|
||||
GLOB.pending_server_update = TRUE
|
||||
for(var/client/C in GLOB.clients)
|
||||
to_chat(C, "<span class='announce'>PR: [prtext]</span>")
|
||||
7
code/modules/world_topic/hostannounce.dm
Normal file
7
code/modules/world_topic/hostannounce.dm
Normal file
@@ -0,0 +1,7 @@
|
||||
/datum/world_topic_handler/hostannounce
|
||||
topic_key = "hostannounce"
|
||||
requires_commskey = TRUE
|
||||
|
||||
/datum/world_topic_handler/hostannounce/execute(list/input, key_valid)
|
||||
GLOB.pending_server_update = TRUE
|
||||
to_chat(world, "<hr><span style='color: #12A5F4'><b>Server Announcement:</b> [input["message"]]</span><hr>")
|
||||
35
code/modules/world_topic/manifest.dm
Normal file
35
code/modules/world_topic/manifest.dm
Normal file
@@ -0,0 +1,35 @@
|
||||
/datum/world_topic_handler/manifest
|
||||
topic_key = "manifest"
|
||||
|
||||
/datum/world_topic_handler/manifest/execute(list/input, key_valid)
|
||||
var/list/positions = list()
|
||||
var/list/set_names = list(
|
||||
"heads" = GLOB.command_positions,
|
||||
"sec" = GLOB.security_positions,
|
||||
"eng" = GLOB.engineering_positions,
|
||||
"med" = GLOB.medical_positions,
|
||||
"sci" = GLOB.science_positions,
|
||||
"car" = GLOB.supply_positions,
|
||||
"srv" = GLOB.service_positions,
|
||||
"civ" = GLOB.civilian_positions,
|
||||
"bot" = GLOB.nonhuman_positions
|
||||
)
|
||||
|
||||
for(var/datum/data/record/t in GLOB.data_core.general)
|
||||
var/name = t.fields["name"]
|
||||
var/rank = t.fields["rank"]
|
||||
var/real_rank = t.fields["real_rank"]
|
||||
|
||||
var/department = FALSE
|
||||
for(var/k in set_names)
|
||||
if(real_rank in set_names[k])
|
||||
if(!positions[k])
|
||||
positions[k] = list()
|
||||
positions[k][name] = rank
|
||||
department = TRUE
|
||||
if(!department)
|
||||
if(!positions["misc"])
|
||||
positions["misc"] = list()
|
||||
positions["misc"][name] = rank
|
||||
|
||||
return json_encode(positions)
|
||||
14
code/modules/world_topic/ping.dm
Normal file
14
code/modules/world_topic/ping.dm
Normal file
@@ -0,0 +1,14 @@
|
||||
/datum/world_topic_handler/ping
|
||||
topic_key = "ping"
|
||||
|
||||
/datum/world_topic_handler/ping/execute(list/input, key_valid)
|
||||
/*
|
||||
Basically a more efficient version of
|
||||
|
||||
if("ping" in input)
|
||||
var/x = 1
|
||||
for(var/client/C)
|
||||
x++
|
||||
return x
|
||||
*/
|
||||
return length(GLOB.clients) + 1
|
||||
10
code/modules/world_topic/players.dm
Normal file
10
code/modules/world_topic/players.dm
Normal file
@@ -0,0 +1,10 @@
|
||||
/datum/world_topic_handler/playerlist
|
||||
topic_key = "playerlist"
|
||||
|
||||
/datum/world_topic_handler/playerlist/execute(list/input, key_valid)
|
||||
var/list/keys = list()
|
||||
for(var/I in GLOB.clients)
|
||||
var/client/C = I
|
||||
keys += C.key
|
||||
|
||||
return json_encode(keys)
|
||||
53
code/modules/world_topic/status.dm
Normal file
53
code/modules/world_topic/status.dm
Normal file
@@ -0,0 +1,53 @@
|
||||
/datum/world_topic_handler/status
|
||||
topic_key = "status"
|
||||
|
||||
/datum/world_topic_handler/status/execute(list/input, key_valid)
|
||||
var/list/status_info = list()
|
||||
var/list/admins = list()
|
||||
status_info["version"] = GLOB.revision_info.commit_hash
|
||||
status_info["mode"] = GLOB.master_mode
|
||||
status_info["respawn"] = GLOB.abandon_allowed
|
||||
status_info["enter"] = GLOB.enter_allowed
|
||||
status_info["vote"] = config.allow_vote_mode
|
||||
status_info["ai"] = config.allow_ai
|
||||
status_info["host"] = world.host ? world.host : null
|
||||
status_info["players"] = list()
|
||||
status_info["roundtime"] = worldtime2text()
|
||||
status_info["stationtime"] = station_time_timestamp()
|
||||
status_info["oldstationtime"] = classic_worldtime2text() // more "consistent" indication of the round's running time
|
||||
status_info["listed"] = "Public"
|
||||
if(!world.hub_password)
|
||||
status_info["listed"] = "Invisible"
|
||||
var/player_count = 0
|
||||
var/admin_count = 0
|
||||
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(C.holder)
|
||||
if(C.holder.fakekey)
|
||||
continue //so stealthmins aren't revealed by the hub
|
||||
admin_count++
|
||||
admins += list(list(C.key, C.holder.rank))
|
||||
player_count++
|
||||
status_info["players"] = player_count
|
||||
status_info["admins"] = admin_count
|
||||
status_info["map_name"] = GLOB.map_name ? GLOB.map_name : "Unknown"
|
||||
|
||||
// Add more info if we are authed
|
||||
if(key_valid)
|
||||
if(SSticker && SSticker.mode)
|
||||
status_info["real_mode"] = SSticker.mode.name
|
||||
status_info["security_level"] = get_security_level()
|
||||
status_info["ticker_state"] = SSticker.current_state
|
||||
|
||||
if(SSshuttle && SSshuttle.emergency)
|
||||
// Shuttle status, see /__DEFINES/stat.dm
|
||||
status_info["shuttle_mode"] = SSshuttle.emergency.mode
|
||||
// Shuttle timer, in seconds
|
||||
status_info["shuttle_timer"] = SSshuttle.emergency.timeLeft()
|
||||
|
||||
for(var/i in 1 to admins.len)
|
||||
var/list/A = admins[i]
|
||||
status_info["admin[i - 1]"] = A[1]
|
||||
status_info["adminrank[i - 1]"] = A[2]
|
||||
|
||||
return json_encode(status_info)
|
||||
@@ -2470,6 +2470,15 @@
|
||||
#include "code\modules\vehicle\speedbike.dm"
|
||||
#include "code\modules\vehicle\sportscar.dm"
|
||||
#include "code\modules\vehicle\vehicle.dm"
|
||||
#include "code\modules\world_topic\_spam_prevention_handler.dm"
|
||||
#include "code\modules\world_topic\_topic_base.dm"
|
||||
#include "code\modules\world_topic\adminmsg.dm"
|
||||
#include "code\modules\world_topic\announce.dm"
|
||||
#include "code\modules\world_topic\hostannounce.dm"
|
||||
#include "code\modules\world_topic\manifest.dm"
|
||||
#include "code\modules\world_topic\ping.dm"
|
||||
#include "code\modules\world_topic\players.dm"
|
||||
#include "code\modules\world_topic\status.dm"
|
||||
#include "goon\code\datums\browserOutput.dm"
|
||||
#include "interface\interface.dm"
|
||||
#include "interface\skin.dmf"
|
||||
|
||||
Reference in New Issue
Block a user