safety? what's that?
* maybe table-breaking change
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
|
||||
Here's how to use the chat system with configs
|
||||
|
||||
send2adminchat is a simple function that broadcasts to admin channels
|
||||
|
||||
send2chat is a bit verbose but can be very specific
|
||||
|
||||
The second parameter is a string, this string should be read from a config.
|
||||
What this does is dictacte which TGS4 channels can be sent to.
|
||||
|
||||
For example if you have the following channels in tgs4 set up
|
||||
- Channel 1, Tag: asdf
|
||||
- Channel 2, Tag: bombay,asdf
|
||||
- Channel 3, Tag: Hello my name is asdf
|
||||
- Channel 4, No Tag
|
||||
- Channel 5, Tag: butts
|
||||
|
||||
and you make the call:
|
||||
|
||||
send2chat("I sniff butts", CONFIG_GET(string/where_to_send_sniff_butts))
|
||||
|
||||
and the config option is set like:
|
||||
|
||||
WHERE_TO_SEND_SNIFF_BUTTS asdf
|
||||
|
||||
It will be sent to channels 1 and 2
|
||||
|
||||
Alternatively if you set the config option to just:
|
||||
|
||||
WHERE_TO_SEND_SNIFF_BUTTS
|
||||
|
||||
it will be sent to all connected chats.
|
||||
|
||||
In TGS3 it will always be sent to all connected designated game chats.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sends a message to TGS chat channels.
|
||||
*
|
||||
* message - The message to send.
|
||||
* channel_tag - Required. If "", the message with be sent to all connected (Game-type for TGS3) channels. Otherwise, it will be sent to TGS4 channels with that tag (Delimited by ','s).
|
||||
*/
|
||||
/proc/send2chat(message, channel_tag)
|
||||
if(channel_tag == null || !world.TgsAvailable())
|
||||
return
|
||||
|
||||
var/datum/tgs_version/version = world.TgsVersion()
|
||||
if(channel_tag == "" || version.suite == 3)
|
||||
world.TgsTargetedChatBroadcast(message, FALSE)
|
||||
return
|
||||
|
||||
var/list/channels_to_use = list()
|
||||
for(var/I in world.TgsChatChannelInfo())
|
||||
var/datum/tgs_chat_channel/channel = I
|
||||
var/list/applicable_tags = splittext(channel.custom_tag, ",")
|
||||
if(channel_tag in applicable_tags)
|
||||
channels_to_use += channel
|
||||
|
||||
if(channels_to_use.len)
|
||||
world.TgsChatBroadcast(message, channels_to_use)
|
||||
|
||||
/**
|
||||
* Sends a message to TGS admin chat channels.
|
||||
*
|
||||
* category - The category of the mssage.
|
||||
* message - The message to send.
|
||||
*/
|
||||
/proc/send2adminchat(category, message, embed_links = FALSE)
|
||||
category = replacetext(replacetext(category, "\proper", ""), "\improper", "")
|
||||
message = replacetext(replacetext(message, "\proper", ""), "\improper", "")
|
||||
// if(!embed_links)
|
||||
// message = GLOB.has_discord_embeddable_links.Replace(replacetext(message, "`", ""), " ```$1``` ")
|
||||
world.TgsTargetedChatBroadcast("[category] | [message]", TRUE)
|
||||
@@ -204,7 +204,7 @@
|
||||
|
||||
var/survival_rate = GLOB.joined_player_list.len ? "[PERCENT(popcount[POPCOUNT_SURVIVORS]/GLOB.joined_player_list.len)]%" : "there's literally no player"
|
||||
|
||||
send2irc("Server", "A round of [mode.name] just ended[mode_result == "undefined" ? "." : " with a [mode_result]."] Survival rate: [survival_rate]")
|
||||
send2adminchat("Server", "A round of [mode.name] just ended[mode_result == "undefined" ? "." : " with a [mode_result]."] Survival rate: [survival_rate]")
|
||||
|
||||
if(length(CONFIG_GET(keyed_list/cross_server)))
|
||||
send_news_report()
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
* SQL sanitization
|
||||
*/
|
||||
|
||||
// Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts.
|
||||
/proc/sanitizeSQL(t)
|
||||
return SSdbcore.Quote("[t]")
|
||||
|
||||
/proc/format_table_name(table as text)
|
||||
return CONFIG_GET(string/feedback_tableprefix) + table
|
||||
|
||||
|
||||
@@ -1575,33 +1575,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
for(var/i in 1 to items_list[each_item])
|
||||
new each_item(where_to)
|
||||
|
||||
//sends a message to chat
|
||||
//config_setting should be one of the following
|
||||
//null - noop
|
||||
//empty string - use TgsTargetBroadcast with admin_only = FALSE
|
||||
//other string - use TgsChatBroadcast with the tag that matches config_setting, only works with TGS4, if using TGS3 the above method is used
|
||||
/proc/send2chat(message, config_setting)
|
||||
if(config_setting == null)
|
||||
return
|
||||
|
||||
UNTIL(GLOB.tgs_initialized)
|
||||
if(!world.TgsAvailable())
|
||||
return
|
||||
|
||||
var/datum/tgs_version/version = world.TgsVersion()
|
||||
if(config_setting == "" || version.suite == 3)
|
||||
world.TgsTargetedChatBroadcast(message, FALSE)
|
||||
return
|
||||
|
||||
var/list/channels_to_use = list()
|
||||
for(var/I in world.TgsChatChannelInfo())
|
||||
var/datum/tgs_chat_channel/channel = I
|
||||
if(channel.tag == config_setting)
|
||||
channels_to_use += channel
|
||||
|
||||
if(channels_to_use.len)
|
||||
world.TgsChatBroadcast()
|
||||
|
||||
//Checks to see if either the victim has a garlic necklace or garlic in their blood
|
||||
/proc/blood_sucking_checks(var/mob/living/carbon/target, check_neck, check_blood)
|
||||
//Bypass this if the target isnt carbon.
|
||||
|
||||
+2
-2
@@ -48,7 +48,7 @@
|
||||
to_chat(src, "<span class='warning'>You're experiencing a bug. Reconnect immediately to fix it. Admins have been notified.</span>")
|
||||
if(REALTIMEOFDAY >= chnotify + 9000)
|
||||
chnotify = REALTIMEOFDAY
|
||||
send2irc_adminless_only("NOCHEAT", message)
|
||||
send2tgs_adminless_only("NOCHEAT", message)
|
||||
return
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
@@ -113,7 +113,7 @@
|
||||
A.AICtrlClick(src)
|
||||
/mob/living/silicon/ai/AltClickOn(var/atom/A)
|
||||
A.AIAltClick(src)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
The following criminally helpful code is just the previous code cleaned up;
|
||||
|
||||
@@ -319,6 +319,11 @@
|
||||
|
||||
/datum/config_entry/flag/panic_bunker // prevents people the server hasn't seen before from connecting
|
||||
|
||||
/datum/config_entry/number/panic_bunker_living // living time in minutes that a player needs to pass the panic bunker
|
||||
|
||||
/datum/config_entry/string/panic_bunker_message
|
||||
config_entry_value = "Sorry but the server is currently not accepting connections from never before seen players."
|
||||
|
||||
/datum/config_entry/number/notify_new_player_age // how long do we notify admins of a new player
|
||||
min_val = -1
|
||||
|
||||
|
||||
@@ -14,12 +14,14 @@ SUBSYSTEM_DEF(blackbox)
|
||||
"explosion" = 2,
|
||||
"time_dilation_current" = 3,
|
||||
"science_techweb_unlock" = 2,
|
||||
"round_end_stats" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
|
||||
"round_end_stats" = 2,
|
||||
"testmerged_prs" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
|
||||
|
||||
/datum/controller/subsystem/blackbox/Initialize()
|
||||
triggertime = world.time
|
||||
record_feedback("amount", "random_seed", Master.random_seed)
|
||||
record_feedback("amount", "dm_version", DM_VERSION)
|
||||
record_feedback("amount", "dm_build", DM_BUILD)
|
||||
record_feedback("amount", "byond_version", world.byond_version)
|
||||
record_feedback("amount", "byond_build", world.byond_build)
|
||||
. = ..()
|
||||
@@ -95,18 +97,24 @@ SUBSYSTEM_DEF(blackbox)
|
||||
if (!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
var/list/special_columns = list(
|
||||
"datetime" = "NOW()"
|
||||
)
|
||||
var/list/sqlrowlist = list()
|
||||
|
||||
for (var/datum/feedback_variable/FV in feedback)
|
||||
var/sqlversion = 1
|
||||
if(FV.key in versions)
|
||||
sqlversion = versions[FV.key]
|
||||
sqlrowlist += list(list("datetime" = "Now()", "round_id" = GLOB.round_id, "key_name" = "'[sanitizeSQL(FV.key)]'", "key_type" = "'[FV.key_type]'", "version" = "[sqlversion]", "json" = "'[sanitizeSQL(json_encode(FV.json))]'"))
|
||||
sqlrowlist += list(list(
|
||||
"round_id" = GLOB.round_id,
|
||||
"key_name" = FV.key,
|
||||
"key_type" = FV.key_type,
|
||||
"version" = versions[FV.key] || 1,
|
||||
"json" = json_encode(FV.json)
|
||||
))
|
||||
|
||||
if (!length(sqlrowlist))
|
||||
return
|
||||
|
||||
SSdbcore.MassInsert(format_table_name("feedback"), sqlrowlist, ignore_errors = TRUE, delayed = TRUE)
|
||||
SSdbcore.MassInsert(format_table_name("feedback"), sqlrowlist, ignore_errors = TRUE, delayed = TRUE, special_columns = special_columns)
|
||||
|
||||
|
||||
/datum/controller/subsystem/blackbox/proc/Seal()
|
||||
if(sealed)
|
||||
@@ -176,7 +184,7 @@ feedback data can be recorded in 5 formats:
|
||||
"tally"
|
||||
used to track the number of occurances of multiple related values i.e. how many times each type of gun is fired
|
||||
further calls to the same key will:
|
||||
add or subtract from the saved value of the data key if it already exists
|
||||
add or subtract from the saved value of the data key if it already exists
|
||||
append the key and it's value if it doesn't exist
|
||||
calls: SSblackbox.record_feedback("tally", "example", 1, "sample data")
|
||||
SSblackbox.record_feedback("tally", "example", 4, "sample data")
|
||||
@@ -188,7 +196,7 @@ feedback data can be recorded in 5 formats:
|
||||
the final element in the data list is used as the tracking key, all prior elements are used for nesting
|
||||
all data list elements must be strings
|
||||
further calls to the same key will:
|
||||
add or subtract from the saved value of the data key if it already exists in the same multi-dimensional position
|
||||
add or subtract from the saved value of the data key if it already exists in the same multi-dimensional position
|
||||
append the key and it's value if it doesn't exist
|
||||
calls: SSblackbox.record_feedback("nested tally", "example", 1, list("fruit", "orange", "apricot"))
|
||||
SSblackbox.record_feedback("nested tally", "example", 2, list("fruit", "orange", "orange"))
|
||||
@@ -289,6 +297,7 @@ Versioning
|
||||
query_log_ahelp.Execute()
|
||||
qdel(query_log_ahelp)
|
||||
|
||||
|
||||
/datum/controller/subsystem/blackbox/proc/ReportDeath(mob/living/L)
|
||||
set waitfor = FALSE
|
||||
if(sealed)
|
||||
|
||||
@@ -268,7 +268,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(!GLOB.Debug2)
|
||||
if(!can_continue)
|
||||
log_game("[mode.name] failed pre_setup, cause: [mode.setup_error]")
|
||||
send2irc("SSticker", "[mode.name] failed pre_setup, cause: [mode.setup_error]")
|
||||
send2adminchat("SSticker", "[mode.name] failed pre_setup, cause: [mode.setup_error]")
|
||||
message_admins("<span class='notice'>[mode.name] failed pre_setup, cause: [mode.setup_error]</span>")
|
||||
QDEL_NULL(mode)
|
||||
to_chat(world, "<B>Error setting up [GLOB.master_mode].</B> Reverting to pre-game lobby.")
|
||||
@@ -334,7 +334,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
var/list/adm = get_admin_counts()
|
||||
var/list/allmins = adm["present"]
|
||||
send2irc("Server", "Round [GLOB.round_id ? "#[GLOB.round_id]:" : "of"] [hide_mode ? "secret":"[mode.name]"] has started[allmins.len ? ".":" with no active admins online!"]")
|
||||
send2adminchat("Server", "Round [GLOB.round_id ? "#[GLOB.round_id]:" : "of"] [hide_mode ? "secret":"[mode.name]"] has started[allmins.len ? ".":" with no active admins online!"]")
|
||||
setup_done = TRUE
|
||||
|
||||
for(var/i in GLOB.start_landmarks_list)
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
if(!is_new_ckey)
|
||||
log_admin("AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
|
||||
message_admins("AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
|
||||
send2irc("Panic Bunker", "AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
|
||||
send2adminchat("Panic Bunker", "AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
|
||||
return "Success"
|
||||
|
||||
/datum/world_topic/ahelp_relay
|
||||
|
||||
@@ -80,8 +80,11 @@
|
||||
var/client/banned_client = banned_mob?.client
|
||||
var/banned_mob_guest_key = had_banned_mob && IsGuestKey(banned_mob.key)
|
||||
banned_mob = null
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
var/datum/db_query/query_add_ban_get_ckey = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
|
||||
var/datum/db_query/query_add_ban_get_ckey = SSdbcore.NewQuery({"
|
||||
SELECT 1
|
||||
FROM [format_table_name("player")]
|
||||
WHERE ckey = :ckey"},
|
||||
list("ckey" = ckey))
|
||||
if(!query_add_ban_get_ckey.warn_execute())
|
||||
qdel(query_add_ban_get_ckey)
|
||||
return
|
||||
@@ -122,10 +125,11 @@
|
||||
else
|
||||
adminwho += ", [C]"
|
||||
|
||||
reason = sanitizeSQL(reason)
|
||||
var/sql_a_ckey = sanitizeSQL(a_ckey)
|
||||
if(maxadminbancheck)
|
||||
var/datum/db_query/query_check_adminban_amt = SSdbcore.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[sql_a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
var/datum/db_query/query_check_adminban_amt = SSdbcore.NewQuery({"
|
||||
SELECT count(id) AS num FROM [format_table_name("ban")]
|
||||
WHERE (a_ckey = :a_ckey) AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)
|
||||
"}, list("a_ckey" = a_ckey))
|
||||
if(!query_check_adminban_amt.warn_execute())
|
||||
qdel(query_check_adminban_amt)
|
||||
return
|
||||
@@ -143,13 +147,15 @@
|
||||
computerid = "0"
|
||||
if(!ip)
|
||||
ip = "0.0.0.0"
|
||||
var/sql_job = sanitizeSQL(job)
|
||||
var/sql_computerid = sanitizeSQL(computerid)
|
||||
var/sql_ip = sanitizeSQL(ip)
|
||||
var/sql_a_computerid = sanitizeSQL(a_computerid)
|
||||
var/sql_a_ip = sanitizeSQL(a_ip)
|
||||
var/sql = "INSERT INTO [format_table_name("ban")] (`bantime`,`server_ip`,`server_port`,`round_id`,`bantype`,`reason`,`job`,`duration`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]', '[bantype_str]', '[reason]', '[sql_job]', [(duration)?"[duration]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[sql_ckey]', '[sql_computerid]', INET_ATON('[sql_ip]'), '[sql_a_ckey]', '[sql_a_computerid]', INET_ATON('[sql_a_ip]'), '[who]', '[adminwho]')"
|
||||
var/datum/db_query/query_add_ban = SSdbcore.NewQuery(sql)
|
||||
var/datum/db_query/query_add_ban = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("ban")] (`bantime`,`server_ip`,`server_port`,`round_id`,`bantype`,`reason`,`job`,`duration`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`)
|
||||
VALUES (Now(), INET_ATON(:internet_address), :port, :round_id, :bantype_str, :reason, :job, :duration, Now() + INTERVAL :expiration_time MINUTE, :ckey, :computerid, INET_ATON(:ip), :a_ckey, :a_computerid, INET_ATON(:a_ip), :who, :adminwho)
|
||||
"}, list("internet_address" = world.internet_address ? world.internet_address : 0,
|
||||
"port" = world.port, "round_id" = GLOB.round_id, "bantype_str" = bantype_str, "reason" = reason,
|
||||
"job" = job, "duration" = duration ? "[duration]":"0", "expiration_time" = (duration > 0) ? duration : 0,
|
||||
"ckey" = ckey, "computerid" = computerid, "ip" = ip,
|
||||
"a_ckey" = a_ckey, "a_computerid" = a_computerid, "a_ip" = a_ip, "who" = who, "adminwho" = adminwho
|
||||
))
|
||||
if(!query_add_ban.warn_execute())
|
||||
qdel(query_add_ban)
|
||||
return
|
||||
@@ -160,7 +166,7 @@
|
||||
var/datum/admin_help/AH = admin_ticket_log(ckey, msg)
|
||||
|
||||
if(announceinirc)
|
||||
send2irc("BAN ALERT","[a_key] applied a [bantype_str] on [bankey]")
|
||||
send2adminchat("BAN ALERT","[a_key] applied a [bantype_str] on [bankey]")
|
||||
|
||||
if(kickbannedckey)
|
||||
if(AH)
|
||||
@@ -212,11 +218,11 @@
|
||||
bantype_sql = "(bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now() ) )"
|
||||
else
|
||||
bantype_sql = "bantype = '[bantype_str]'"
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
var/sql = "SELECT id FROM [format_table_name("ban")] WHERE ckey = '[sql_ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
|
||||
var/sql = "SELECT id FROM [format_table_name("ban")] WHERE ckey = :ckey AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
|
||||
var/list/sql_args = list("ckey" = ckey)
|
||||
if(job)
|
||||
var/sql_job = sanitizeSQL(job)
|
||||
sql += " AND job = '[sql_job]'"
|
||||
sql += " AND job = :job"
|
||||
sql_args["job"] = job
|
||||
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
@@ -224,7 +230,7 @@
|
||||
var/ban_id
|
||||
var/ban_number = 0 //failsafe
|
||||
|
||||
var/datum/db_query/query_unban_get_id = SSdbcore.NewQuery(sql)
|
||||
var/datum/db_query/query_unban_get_id = SSdbcore.NewQuery(sql, sql_args)
|
||||
if(!query_unban_get_id.warn_execute())
|
||||
qdel(query_unban_get_id)
|
||||
return
|
||||
@@ -278,14 +284,12 @@
|
||||
return
|
||||
qdel(query_edit_ban_get_details)
|
||||
|
||||
reason = sanitizeSQL(reason)
|
||||
var/value
|
||||
|
||||
switch(param)
|
||||
if("reason")
|
||||
if(!value)
|
||||
value = input("Insert the new reason for [p_key]'s ban", "New Reason", "[reason]", null) as null|text
|
||||
value = sanitizeSQL(value)
|
||||
if(!value)
|
||||
to_chat(usr, "Cancelled")
|
||||
return
|
||||
@@ -448,20 +452,28 @@
|
||||
|
||||
if(adminckey || playerckey || ip || cid)
|
||||
var/list/searchlist = list()
|
||||
var/list/searchlist_args = list()
|
||||
if(playerckey)
|
||||
searchlist += "ckey = '[sanitizeSQL(ckey(playerckey))]'"
|
||||
searchlist += "ckey = :playerckey"
|
||||
searchlist_args["playerckey"] = playerckey
|
||||
if(adminckey)
|
||||
searchlist += "a_ckey = '[sanitizeSQL(ckey(adminckey))]'"
|
||||
searchlist += "a_ckey = :adminckey"
|
||||
searchlist_args["adminckey"] = adminckey
|
||||
if(ip)
|
||||
searchlist += "ip = INET_ATON('[sanitizeSQL(ip)]')"
|
||||
searchlist += "ip = INET_ATON(:ip)"
|
||||
searchlist_args["ip"] = ip
|
||||
if(cid)
|
||||
searchlist += "computerid = '[sanitizeSQL(cid)]'"
|
||||
var/search = searchlist.Join(" AND ")
|
||||
searchlist += "computerid = :cid"
|
||||
searchlist_args["cid"] = cid
|
||||
var/search = searchlist.Join(" AND ") // x = x AND y = z
|
||||
var/bancount = 0
|
||||
var/bansperpage = 15
|
||||
var/pagecount = 0
|
||||
page = text2num(page)
|
||||
var/datum/db_query/query_count_bans = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("ban")] WHERE [search]")
|
||||
var/datum/db_query/query_count_bans = SSdbcore.NewQuery({"
|
||||
SELECT COUNT(id) FROM [format_table_name("ban")]
|
||||
WHERE [search]
|
||||
"}, searchlist_args)
|
||||
if(!query_count_bans.warn_execute())
|
||||
qdel(query_count_bans)
|
||||
return
|
||||
@@ -489,7 +501,11 @@
|
||||
output += "<th width='15%'><b>OPTIONS</b></th>"
|
||||
output += "</tr>"
|
||||
var/limit = " LIMIT [bansperpage * page], [bansperpage]"
|
||||
var/datum/db_query/query_search_bans = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), unbanned, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].unbanned_ckey), unbanned_ckey), unbanned_datetime, edits, round_id FROM [format_table_name("ban")] WHERE [search] ORDER BY bantime DESC[limit]")
|
||||
|
||||
var/datum/db_query/query_search_bans = SSdbcore.NewQuery({"
|
||||
SELECT id, bantime, bantype, reason, job, duration, expiration_time, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), unbanned, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].unbanned_ckey), unbanned_ckey), unbanned_datetime, edits, round_id
|
||||
FROM [format_table_name("ban")]
|
||||
WHERE [search] ORDER BY bantime DESC[limit]"}, searchlist_args)
|
||||
if(!query_search_bans.warn_execute())
|
||||
qdel(query_search_bans)
|
||||
return
|
||||
|
||||
@@ -119,16 +119,12 @@ GLOBAL_PROTECT(protected_ranks)
|
||||
set waitfor = FALSE
|
||||
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='admin prefix'>Admin rank DB Sync blocked: Advanced ProcCall detected.</span>")
|
||||
to_chat(usr, "<span class='admin prefix'>Admin rank DB Sync blocked: Advanced ProcCall detected.</span>", confidential = TRUE)
|
||||
return
|
||||
|
||||
var/list/sql_ranks = list()
|
||||
for(var/datum/admin_rank/R in GLOB.protected_ranks)
|
||||
var/sql_rank = sanitizeSQL(R.name)
|
||||
var/sql_flags = sanitizeSQL(R.include_rights)
|
||||
var/sql_exclude_flags = sanitizeSQL(R.exclude_rights)
|
||||
var/sql_can_edit_flags = sanitizeSQL(R.can_edit_rights)
|
||||
sql_ranks += list(list("rank" = "'[sql_rank]'", "flags" = "[sql_flags]", "exclude_flags" = "[sql_exclude_flags]", "can_edit_flags" = "[sql_can_edit_flags]"))
|
||||
sql_ranks += list(list("rank" = R.name, "flags" = R.include_rights, "exclude_flags" = R.exclude_rights, "can_edit_flags" = R.can_edit_rights))
|
||||
SSdbcore.MassInsert(format_table_name("admin_ranks"), sql_ranks, duplicate_key = TRUE)
|
||||
|
||||
//load our rank - > rights associations
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
return FALSE
|
||||
|
||||
if(!M.client) //no cache. fallback to a datum/db_query
|
||||
var/datum/db_query/query_jobban_check_ban = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(M.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[sanitizeSQL(rank)]'")
|
||||
var/datum/db_query/query_jobban_check_ban = SSdbcore.NewQuery({"
|
||||
SELECT reason FROM [format_table_name("ban")]
|
||||
WHERE ckey = :ckey AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = :rank
|
||||
"}, list("ckey" = M.ckey, "rank" = rank))
|
||||
if(!query_jobban_check_ban.warn_execute())
|
||||
qdel(query_jobban_check_ban)
|
||||
return
|
||||
@@ -28,7 +31,10 @@
|
||||
return
|
||||
if(C && istype(C))
|
||||
C.jobbancache = list()
|
||||
var/datum/db_query/query_jobban_build_cache = SSdbcore.NewQuery("SELECT job, reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(C.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
var/datum/db_query/query_jobban_build_cache = SSdbcore.NewQuery({"
|
||||
SELECT job, reason FROM [format_table_name("ban")]
|
||||
WHERE ckey = :ckey AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)
|
||||
"}, list("ckey" = C.ckey))
|
||||
if(!query_jobban_build_cache.warn_execute())
|
||||
qdel(query_jobban_build_cache)
|
||||
return
|
||||
|
||||
@@ -34,8 +34,9 @@
|
||||
var/endtime = input("Set end time for poll as format YYYY-MM-DD HH:MM:SS. All times in server time. HH:MM:SS is optional and 24-hour. Must be later than starting time for obvious reasons.", "Set end time", SQLtime()) as text
|
||||
if(!endtime)
|
||||
return
|
||||
endtime = sanitizeSQL(endtime)
|
||||
var/datum/db_query/query_validate_time = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[endtime]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[endtime]','%Y-%c-%d %T'), 0)")
|
||||
var/datum/db_query/query_validate_time = SSdbcore.NewQuery({"
|
||||
SELECT IF(STR_TO_DATE(:endtime,'%Y-%c-%d %T') > NOW(), STR_TO_DATE(:endtime,'%Y-%c-%d %T'), 0)
|
||||
"}, list("endtime" = endtime))
|
||||
if(!query_validate_time.warn_execute() || QDELETED(usr) || !src)
|
||||
qdel(query_validate_time)
|
||||
return
|
||||
@@ -63,11 +64,9 @@
|
||||
dontshow = 0
|
||||
else
|
||||
return
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
var/question = input("Write your question","Question") as message|null
|
||||
if(!question)
|
||||
return
|
||||
question = sanitizeSQL(question)
|
||||
var/list/sql_option_list = list()
|
||||
if(polltype != POLLTYPE_TEXT)
|
||||
var/add_option = 1
|
||||
@@ -75,7 +74,6 @@
|
||||
var/option = input("Write your option","Option") as message|null
|
||||
if(!option)
|
||||
return
|
||||
option = sanitizeSQL(option)
|
||||
var/default_percentage_calc = 0
|
||||
if(polltype != POLLTYPE_IRV)
|
||||
switch(alert("Should this option be included by default when poll result percentages are generated?",,"Yes","No","Cancel"))
|
||||
@@ -92,32 +90,22 @@
|
||||
var/descmax = ""
|
||||
if(polltype == POLLTYPE_RATING)
|
||||
minval = input("Set minimum rating value.","Minimum rating") as num|null
|
||||
if(minval)
|
||||
minval = sanitizeSQL(minval)
|
||||
else if(minval == null)
|
||||
if(minval == null)
|
||||
return
|
||||
maxval = input("Set maximum rating value.","Maximum rating") as num|null
|
||||
if(maxval)
|
||||
maxval = sanitizeSQL(maxval)
|
||||
if(minval >= maxval)
|
||||
to_chat(src, "Maximum rating value can't be less than or equal to minimum rating value")
|
||||
continue
|
||||
else if(maxval == null)
|
||||
if(maxval == null)
|
||||
return
|
||||
descmin = input("Optional: Set description for minimum rating","Minimum rating description") as message|null
|
||||
if(descmin)
|
||||
descmin = sanitizeSQL(descmin)
|
||||
else if(descmin == null)
|
||||
if(descmin == null)
|
||||
return
|
||||
descmid = input("Optional: Set description for median rating","Median rating description") as message|null
|
||||
if(descmid)
|
||||
descmid = sanitizeSQL(descmid)
|
||||
else if(descmid == null)
|
||||
if(descmid == null)
|
||||
return
|
||||
descmax = input("Optional: Set description for maximum rating","Maximum rating description") as message|null
|
||||
if(descmax)
|
||||
descmax = sanitizeSQL(descmax)
|
||||
else if(descmax == null)
|
||||
if(descmax == null)
|
||||
return
|
||||
sql_option_list += list(list("text" = "'[option]'", "minval" = "'[minval]'", "maxval" = "'[maxval]'", "descmin" = "'[descmin]'", "descmid" = "'[descmid]'", "descmax" = "'[descmax]'", "default_percentage_calc" = "'[default_percentage_calc]'"))
|
||||
switch(alert(" ",,"Add option","Finish", "Cancel"))
|
||||
@@ -129,7 +117,13 @@
|
||||
return 0
|
||||
var/m1 = "[key_name(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"] - Question: [question]"
|
||||
var/m2 = "[key_name_admin(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"]<br>Question: [question]"
|
||||
var/datum/db_query/query_polladd_question = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip, dontshow) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', INET_ATON('[address]'), '[dontshow]')")
|
||||
var/datum/db_query/query_polladd_question = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip, dontshow)
|
||||
VALUES (:polltype, :starttime, :endtime, :question, :adminonly, :choice_amount, :ckey, INET_ATON(:address), '[dontshow]')
|
||||
"}, list("polltype" = polltype, "starttime" = starttime, "endtime" = endtime,
|
||||
"question" = question, "adminonly" = adminonly, "choice_amount" = choice_amount,
|
||||
"ckey" = ckey, "address" = address, "dontshow" = dontshow
|
||||
))
|
||||
if(!query_polladd_question.warn_execute())
|
||||
qdel(query_polladd_question)
|
||||
return
|
||||
|
||||
@@ -205,7 +205,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
MessageNoRecipient(msg)
|
||||
|
||||
//send it to irc if nobody is on and tell us how many were on
|
||||
var/admin_number_present = send2irc_adminless_only(initiator_ckey, "Ticket #[id]: [name]")
|
||||
var/admin_number_present = send2tgs_adminless_only(initiator_ckey, "Ticket #[id]: [name]")
|
||||
log_admin_private("Ticket #[id]: [key_name(initiator)]: [name] - heard by [admin_number_present] non-AFK admins who have +BAN.")
|
||||
if(admin_number_present <= 0)
|
||||
to_chat(C, "<span class='notice'>No active admins are online, your adminhelp was sent to the admin irc.</span>")
|
||||
@@ -222,7 +222,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
/datum/admin_help/proc/AddInteraction(formatted_message)
|
||||
if(heard_by_no_admins && usr && usr.ckey != initiator_ckey)
|
||||
heard_by_no_admins = FALSE
|
||||
send2irc(initiator_ckey, "Ticket #[id]: Answered by [key_name(usr)]")
|
||||
send2adminchat(initiator_ckey, "Ticket #[id]: Answered by [key_name(usr)]")
|
||||
_interactions += "[TIME_STAMP("hh:mm:ss", FALSE)]: [formatted_message]"
|
||||
|
||||
//Removes the ahelp verb and returns it after 2 minutes
|
||||
@@ -573,7 +573,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
. = list("total" = list(), "noflags" = list(), "afk" = list(), "stealth" = list(), "present" = list())
|
||||
for(var/client/X in GLOB.admins)
|
||||
.["total"] += X
|
||||
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
|
||||
if(requiredflags != NONE && !check_rights_for(X, requiredflags))
|
||||
.["noflags"] += X
|
||||
else if(X.is_afk())
|
||||
.["afk"] += X
|
||||
@@ -582,7 +582,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
else
|
||||
.["present"] += X
|
||||
|
||||
/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
|
||||
/proc/send2tgs_adminless_only(source, msg, requiredflags = R_BAN)
|
||||
var/list/adm = get_admin_counts(requiredflags)
|
||||
var/list/activemins = adm["present"]
|
||||
. = activemins.len
|
||||
@@ -596,29 +596,52 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
final = "[msg] - No admins online"
|
||||
else
|
||||
final = "[msg] - All admins stealthed\[[english_list(stealthmins)]\], AFK\[[english_list(afkmins)]\], or lacks +BAN\[[english_list(powerlessmins)]\]! Total: [allmins.len] "
|
||||
send2irc(source,final)
|
||||
send2adminchat(source,final)
|
||||
send2otherserver(source,final)
|
||||
|
||||
|
||||
/proc/send2irc(msg,msg2)
|
||||
msg = replacetext(replacetext(msg, "\proper", ""), "\improper", "")
|
||||
msg2 = replacetext(replacetext(msg2, "\proper", ""), "\improper", "")
|
||||
world.TgsTargetedChatBroadcast("[msg] | [msg2]", TRUE)
|
||||
|
||||
/proc/send2otherserver(source,msg,type = "Ahelp")
|
||||
var/comms_key = CONFIG_GET(string/comms_key)
|
||||
if(!comms_key)
|
||||
/**
|
||||
* Sends a message to a set of cross-communications-enabled servers using world topic calls
|
||||
*
|
||||
* Arguments:
|
||||
* * source - Who sent this message
|
||||
* * msg - The message body
|
||||
* * type - The type of message, becomes the topic command under the hood
|
||||
* * target_servers - A collection of servers to send the message to, defined in config
|
||||
* * additional_data - An (optional) associated list of extra parameters and data to send with this world topic call
|
||||
*/
|
||||
/proc/send2otherserver(source, msg, type = "Ahelp", target_servers, list/additional_data = list())
|
||||
if(!CONFIG_GET(string/comms_key))
|
||||
debug_world_log("Server cross-comms message not sent for lack of configured key")
|
||||
return
|
||||
var/list/message = list()
|
||||
message["message_sender"] = source
|
||||
message["message"] = msg
|
||||
message["source"] = "([CONFIG_GET(string/cross_comms_name)])"
|
||||
message["key"] = comms_key
|
||||
message += type
|
||||
|
||||
var/our_id = CONFIG_GET(string/cross_comms_name)
|
||||
additional_data["message_sender"] = source
|
||||
additional_data["message"] = msg
|
||||
additional_data["source"] = "([our_id])"
|
||||
additional_data += type
|
||||
|
||||
var/list/servers = CONFIG_GET(keyed_list/cross_server)
|
||||
for(var/I in servers)
|
||||
world.Export("[servers[I]]?[list2params(message)]")
|
||||
if(I == our_id) //No sending to ourselves
|
||||
continue
|
||||
if(target_servers && !(I in target_servers))
|
||||
continue
|
||||
world.send_cross_comms(I, additional_data)
|
||||
|
||||
/// Sends a message to a given cross comms server by name (by name for security).
|
||||
/world/proc/send_cross_comms(server_name, list/message, auth = TRUE)
|
||||
set waitfor = FALSE
|
||||
if (auth)
|
||||
var/comms_key = CONFIG_GET(string/comms_key)
|
||||
if(!comms_key)
|
||||
debug_world_log("Server cross-comms message not sent for lack of configured key")
|
||||
return
|
||||
message["key"] = comms_key
|
||||
var/list/servers = CONFIG_GET(keyed_list/cross_server)
|
||||
var/server_url = servers[server_name]
|
||||
if (!server_url)
|
||||
CRASH("Invalid cross comms config: [server_name]")
|
||||
world.Export("[server_url]?[list2params(message)]")
|
||||
|
||||
|
||||
/proc/ircadminwho()
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
to_chat(src, "<span class='notice'>PM to-<b>Admins</b>: <span class='linkify'>[rawmsg]</span></span>", confidential = TRUE)
|
||||
var/datum/admin_help/AH = admin_ticket_log(src, "<font color='red'>Reply PM from-<b>[key_name(src, TRUE, TRUE)]</b> to <i>External</i>: [keywordparsedmsg]</font>")
|
||||
ircreplyamount--
|
||||
send2irc("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg)
|
||||
send2adminchat("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg)
|
||||
|
||||
else
|
||||
var/badmin = FALSE //Lets figure out if an admin is getting bwoinked.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
if (new_pb && !SSdbcore.Connect())
|
||||
message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.")
|
||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Panic Bunker", "[new_pb ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
send2irc("Panic Bunker", "[key_name(usr)] has toggled the Panic Bunker, it is now [new_pb ? "enabled" : "disabled"].")
|
||||
send2adminchat("Panic Bunker", "[key_name(usr)] has toggled the Panic Bunker, it is now [new_pb ? "enabled" : "disabled"].")
|
||||
|
||||
/client/proc/addbunkerbypass(ckeytobypass as text)
|
||||
set category = "Special Verbs"
|
||||
@@ -28,7 +28,7 @@
|
||||
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
|
||||
log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
send2irc("Panic Bunker", "[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
send2adminchat("Panic Bunker", "[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
|
||||
/client/proc/revokebunkerbypass(ckeytobypass as text)
|
||||
set category = "Special Verbs"
|
||||
@@ -42,4 +42,4 @@
|
||||
SSpersistence.SavePanicBunker()
|
||||
log_admin("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
message_admins("[key_name_admin(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
send2irc("Panic Bunker", "[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
send2adminchat("Panic Bunker", "[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
/obj/item/clothing/under/suit/white, // white is a weird color for a groom but some people are weird
|
||||
/obj/item/clothing/under/suit/polychromic,
|
||||
/obj/item/clothing/under/suit/polychromic, // in case you can't be satisfied with the most fitting choices, of course.
|
||||
/obj/item/clothing/under/dress/wedding,
|
||||
/obj/item/clothing/under/dress/wedding,
|
||||
/obj/item/clothing/under/dress/wedding, // this is what you actually bought the crate for. You can't get these anywhere else.
|
||||
/obj/item/clothing/under/dress/wedding/orange,
|
||||
/obj/item/clothing/under/dress/wedding/orange,
|
||||
@@ -333,4 +333,4 @@
|
||||
/obj/item/storage/fancy/ringbox/silver,
|
||||
/obj/item/storage/fancy/ringbox/silver) //diamond rings cost the same price as this crate via cargo so we're not giving you two for free. Wedding rings are traditionally less valuable anyway.
|
||||
crate_name = "wedding crate"
|
||||
|
||||
|
||||
|
||||
@@ -42,18 +42,21 @@
|
||||
|
||||
/datum/supply_pack/misc/book_crate
|
||||
name = "Book Crate"
|
||||
desc = "Surplus from the Nanotrasen Archives, these five books are sure to be good reads."
|
||||
desc = "Surplus from the Nanotrasen Archives, these seven books are sure to be good reads."
|
||||
// cost = CARGO_CRATE_VALUE * 3
|
||||
cost = 1500
|
||||
contains = list(/obj/item/book/codex_gigas,
|
||||
/obj/item/book/manual/random/,
|
||||
/obj/item/book/manual/random/,
|
||||
/obj/item/book/manual/random/,
|
||||
/obj/item/book/random/triple)
|
||||
/obj/item/book/random,
|
||||
/obj/item/book/random,
|
||||
/obj/item/book/random)
|
||||
crate_type = /obj/structure/closet/crate/wooden
|
||||
|
||||
/datum/supply_pack/misc/paper
|
||||
name = "Bureaucracy Crate"
|
||||
desc = "High stacks of papers on your desk Are a big problem - make it Pea-sized with these bureaucratic supplies! Contains five pens, some camera film, hand labeler supplies, a paper bin, three folders, two clipboards and two stamps as well as a briefcase."//that was too forced
|
||||
desc = "High stacks of papers on your desk Are a big problem - make it Pea-sized with these bureaucratic supplies! Contains six pens, some camera film, hand labeler supplies, a paper bin, a carbon paper bin, three folders, a laser pointer, two clipboards and two stamps."//that was too forced
|
||||
cost = 1500
|
||||
contains = list(/obj/structure/filingcabinet/chestdrawer/wheeled,
|
||||
/obj/item/camera_film,
|
||||
@@ -61,9 +64,11 @@
|
||||
/obj/item/hand_labeler_refill,
|
||||
/obj/item/hand_labeler_refill,
|
||||
/obj/item/paper_bin,
|
||||
/obj/item/paper_bin/carbon,
|
||||
/obj/item/pen/fourcolor,
|
||||
/obj/item/pen/fourcolor,
|
||||
/obj/item/pen,
|
||||
/obj/item/pen/fountain,
|
||||
/obj/item/pen/blue,
|
||||
/obj/item/pen/red,
|
||||
/obj/item/folder/blue,
|
||||
@@ -73,7 +78,7 @@
|
||||
/obj/item/clipboard,
|
||||
/obj/item/stamp,
|
||||
/obj/item/stamp/denied,
|
||||
/obj/item/storage/briefcase)
|
||||
/obj/item/laser_pointer/purple)
|
||||
crate_name = "bureaucracy crate"
|
||||
|
||||
/datum/supply_pack/misc/captain_pen
|
||||
@@ -94,6 +99,30 @@
|
||||
crate_type = /obj/structure/closet/crate/wooden
|
||||
crate_name = "calligraphy crate"
|
||||
|
||||
/datum/supply_pack/misc/toner
|
||||
name = "Toner Crate"
|
||||
desc = "Spent too much ink printing butt pictures? Fret not, with these six toner refills, you'll be printing butts 'till the cows come home!'"
|
||||
cost = 200 * 4
|
||||
contains = list(/obj/item/toner,
|
||||
/obj/item/toner,
|
||||
/obj/item/toner,
|
||||
/obj/item/toner,
|
||||
/obj/item/toner,
|
||||
/obj/item/toner)
|
||||
crate_name = "toner crate"
|
||||
|
||||
/datum/supply_pack/misc/toner_large
|
||||
name = "Toner Crate (Large)"
|
||||
desc = "Tired of changing toner cartridges? These six extra heavy duty refills contain roughly five times as much toner as the base model!"
|
||||
cost = 200 * 6
|
||||
contains = list(/obj/item/toner/large,
|
||||
/obj/item/toner/large,
|
||||
/obj/item/toner/large,
|
||||
/obj/item/toner/large,
|
||||
/obj/item/toner/large,
|
||||
/obj/item/toner/large)
|
||||
crate_name = "large toner crate"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////// Entertainment ///////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -415,7 +415,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if (nnpa >= 0)
|
||||
message_admins("New user: [key_name_admin(src)] is connecting here for the first time.")
|
||||
if (CONFIG_GET(flag/irc_first_connection_alert))
|
||||
send2irc_adminless_only("New-user", "[key_name(src)] is connecting for the first time!")
|
||||
send2tgs_adminless_only("New-user", "[key_name(src)] is connecting for the first time!")
|
||||
else if (isnum(cached_player_age) && cached_player_age < nnpa)
|
||||
message_admins("New user: [key_name_admin(src)] just connected with an age of [cached_player_age] day[(player_age==1?"":"s")]")
|
||||
if(CONFIG_GET(flag/use_account_age_for_jobs) && account_age >= 0)
|
||||
@@ -423,7 +423,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if(account_age >= 0 && account_age < nnpa)
|
||||
message_admins("[key_name_admin(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].")
|
||||
if (CONFIG_GET(flag/irc_first_connection_alert))
|
||||
send2irc_adminless_only("new_byond_user", "[key_name(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].")
|
||||
send2tgs_adminless_only("new_byond_user", "[key_name(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].")
|
||||
get_message_output("watchlist entry", ckey)
|
||||
check_ip_intel()
|
||||
validate_key_in_db()
|
||||
@@ -519,7 +519,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
"Forever alone :("\
|
||||
)
|
||||
|
||||
send2irc("Server", "[cheesy_message] (No admins online)")
|
||||
send2adminchat("Server", "[cheesy_message] (No admins online)")
|
||||
QDEL_LIST_ASSOC_VAL(char_render_holders)
|
||||
if(movingmob != null)
|
||||
movingmob.client_mobs_in_contents -= mob
|
||||
@@ -576,7 +576,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
var/living_recs = CONFIG_GET(number/panic_bunker_living)
|
||||
//Relies on pref existing, but this proc is only called after that occurs, so we're fine.
|
||||
var/minutes = get_exp_living(pure_numeric = TRUE)
|
||||
if(minutes <= living_recs && !CONFIG_GET(flag/panic_bunker_interview))
|
||||
if(minutes <= living_recs) // && !CONFIG_GET(flag/panic_bunker_interview)
|
||||
var/reject_message = "Failed Login: [key] - Account attempting to connect during panic bunker, but they do not have the required living time [minutes]/[living_recs]"
|
||||
log_access(reject_message)
|
||||
message_admins("<span class='adminnotice'>[reject_message]</span>")
|
||||
|
||||
@@ -1331,9 +1331,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
/datum/preferences/proc/process_link(mob/user, list/href_list)
|
||||
if(href_list["jobbancheck"])
|
||||
var/job = sanitizeSQL(href_list["jobbancheck"])
|
||||
var/sql_ckey = sanitizeSQL(user.ckey)
|
||||
var/datum/db_query/query_get_jobban = SSdbcore.NewQuery("SELECT reason, bantime, duration, expiration_time, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey) FROM [format_table_name("ban")] WHERE ckey = '[sql_ckey]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[job]'")
|
||||
var/job = href_list["jobbancheck"]
|
||||
var/datum/db_query/query_get_jobban = SSdbcore.NewQuery({"
|
||||
SELECT reason, bantime, duration, expiration_time, IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey)
|
||||
FROM [format_table_name("ban")] WHERE ckey = :ckey AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = :job
|
||||
"}, list("ckey" = user.ckey, "job" = job))
|
||||
if(!query_get_jobban.warn_execute())
|
||||
qdel(query_get_jobban)
|
||||
return
|
||||
@@ -1348,7 +1350,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(text2num(duration) > 0)
|
||||
text += ". The ban is for [duration] minutes and expires on [expiration_time] (server time)"
|
||||
text += ".</span>"
|
||||
to_chat(user, text)
|
||||
to_chat(user, text, confidential = TRUE)
|
||||
qdel(query_get_jobban)
|
||||
return
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
|
||||
to_chat(usr, "<span class='notice'>Sorry, that function is not enabled on this server.</span>")
|
||||
return
|
||||
|
||||
browse_messages(null, usr.ckey, null, TRUE, override = TRUE)
|
||||
browse_messages(null, usr.ckey, null, TRUE)
|
||||
|
||||
/client/proc/self_playtime()
|
||||
set name = "View tracked playtime"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
GLOBAL_LIST_EMPTY(exp_to_update)
|
||||
GLOBAL_PROTECT(exp_to_update)
|
||||
|
||||
|
||||
// Procs
|
||||
/datum/job/proc/required_playtime_remaining(client/C)
|
||||
if(!C)
|
||||
@@ -57,6 +56,7 @@ GLOBAL_PROTECT(exp_to_update)
|
||||
amount += explist[job]
|
||||
return amount
|
||||
|
||||
// todo: port tgui exp
|
||||
/client/proc/get_exp_report()
|
||||
if(!CONFIG_GET(flag/use_exp_tracking))
|
||||
return "Tracking is disabled in the server configuration file."
|
||||
@@ -121,12 +121,11 @@ GLOBAL_PROTECT(exp_to_update)
|
||||
return_text += "</LI></UL>"
|
||||
return return_text
|
||||
|
||||
|
||||
/client/proc/get_exp_living()
|
||||
if(!prefs.exp)
|
||||
return "No data"
|
||||
/client/proc/get_exp_living(pure_numeric = FALSE)
|
||||
if(!prefs.exp || !prefs.exp[EXP_TYPE_LIVING])
|
||||
return pure_numeric ? 0 : "No data"
|
||||
var/exp_living = text2num(prefs.exp[EXP_TYPE_LIVING])
|
||||
return get_exp_format(exp_living)
|
||||
return pure_numeric ? exp_living : get_exp_format(exp_living)
|
||||
|
||||
/proc/get_exp_format(expnum)
|
||||
if(expnum > 60)
|
||||
@@ -148,7 +147,7 @@ GLOBAL_PROTECT(exp_to_update)
|
||||
set waitfor = FALSE
|
||||
var/list/old_minutes = GLOB.exp_to_update
|
||||
GLOB.exp_to_update = null
|
||||
SSdbcore.MassInsert(format_table_name("role_time"), old_minutes, "ON DUPLICATE KEY UPDATE minutes = minutes + VALUES(minutes)")
|
||||
SSdbcore.MassInsert(format_table_name("role_time"), old_minutes, duplicate_key = "ON DUPLICATE KEY UPDATE minutes = minutes + VALUES(minutes)")
|
||||
|
||||
//resets a client's exp to what was in the db.
|
||||
/client/proc/set_exp_from_db()
|
||||
@@ -262,8 +261,8 @@ GLOBAL_PROTECT(exp_to_update)
|
||||
CRASH("invalid job value [jtype]:[jvalue]")
|
||||
LAZYINITLIST(GLOB.exp_to_update)
|
||||
GLOB.exp_to_update.Add(list(list(
|
||||
"job" = "'[sanitizeSQL(jtype)]'",
|
||||
"ckey" = "'[sanitizeSQL(ckey)]'",
|
||||
"job" = jtype,
|
||||
"ckey" = ckey,
|
||||
"minutes" = jvalue)))
|
||||
prefs.exp[jtype] += jvalue
|
||||
addtimer(CALLBACK(SSblackbox,/datum/controller/subsystem/blackbox/proc/update_exp_db),20,TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
@@ -289,4 +288,3 @@ GLOBAL_PROTECT(exp_to_update)
|
||||
prefs.db_flags = 0 //This PROBABLY won't happen, but better safe than sorry.
|
||||
qdel(flags_read)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -440,7 +440,7 @@
|
||||
if(!GLOB.news_network)
|
||||
alert("No news network found on station. Aborting.")
|
||||
var/channelexists = 0
|
||||
for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
|
||||
for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels)
|
||||
if(FC.channel_name == "Nanotrasen Book Club")
|
||||
channelexists = 1
|
||||
break
|
||||
@@ -490,9 +490,9 @@
|
||||
if(href_list["printbible"])
|
||||
if(printer_cooldown < world.time)
|
||||
var/obj/item/storage/book/bible/B = new /obj/item/storage/book/bible(src.loc)
|
||||
if(GLOB.bible_icon_state && GLOB.bible_inhand_icon_state)
|
||||
if(GLOB.bible_icon_state && GLOB.bible_item_state)
|
||||
B.icon_state = GLOB.bible_icon_state
|
||||
B.inhand_icon_state = GLOB.bible_inhand_icon_state
|
||||
B.item_state = GLOB.bible_item_state
|
||||
B.name = GLOB.bible_name
|
||||
B.deity_name = GLOB.deity
|
||||
printer_cooldown = world.time + PRINTER_COOLDOWN
|
||||
|
||||
@@ -456,20 +456,30 @@
|
||||
//lets add the vote, first we generate an insert statement.
|
||||
|
||||
var/sqlrowlist = ""
|
||||
var/list/sql_args = list("pollid" = pollid, "ckey" = ckey, "address" = address, "rank" = rank) // will always exist
|
||||
var/__unique_N = 0
|
||||
for (var/vote in numberedvotelist)
|
||||
__unique_N++
|
||||
if (sqlrowlist != "")
|
||||
sqlrowlist += ", " //a comma (,) at the start of the first row to insert will trigger a SQL error
|
||||
sqlrowlist += "(Now(), [pollid], [vote], '[sanitizeSQL(ckey)]', INET_ATON('[sanitizeSQL(address)]'), '[sanitizeSQL(rank)]')"
|
||||
sqlrowlist += "(Now(), :pollid, :vote[__unique_N], :ckey, INET_ATON(:address), :rank)"
|
||||
sql_args["vote[__unique_N]"] = vote
|
||||
|
||||
//now lets delete their old votes (if any)
|
||||
var/datum/db_query/query_irv_del_old = SSdbcore.NewQuery("DELETE FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
|
||||
var/datum/db_query/query_irv_del_old = SSdbcore.NewQuery({"
|
||||
DELETE FROM [format_table_name("poll_vote")]
|
||||
WHERE pollid = :pollid AND ckey = :ckey
|
||||
"}, list("pollid" = pollid, "ckey" = ckey))
|
||||
if(!query_irv_del_old.warn_execute())
|
||||
qdel(query_irv_del_old)
|
||||
return 0
|
||||
qdel(query_irv_del_old)
|
||||
|
||||
//now to add the new ones.
|
||||
var/datum/db_query/query_irv_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES [sqlrowlist]")
|
||||
var/datum/db_query/query_irv_vote = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank)
|
||||
VALUES [sqlrowlist]
|
||||
"}, sql_args)
|
||||
if(!query_irv_vote.warn_execute())
|
||||
qdel(query_irv_vote)
|
||||
return 0
|
||||
@@ -493,10 +503,13 @@
|
||||
var/voted = poll_check_voted(pollid)
|
||||
if(isnull(voted) || voted) //Failed or already voted.
|
||||
return
|
||||
var/adminrank = sanitizeSQL(poll_rank())
|
||||
var/adminrank = poll_rank()
|
||||
if(!adminrank)
|
||||
return
|
||||
var/datum/db_query/query_option_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]')")
|
||||
var/datum/db_query/query_option_vote = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank)
|
||||
VALUES (Now(), :pollid, :optionid, :ckey, INET_ATON(:address), :adminrank)
|
||||
"}, list("pollid" = pollid, "optionid" = optionid, "ckey" = ckey, "address" = client.address, "adminrank" = adminrank))
|
||||
if(!query_option_vote.warn_execute())
|
||||
qdel(query_option_vote)
|
||||
return
|
||||
@@ -522,18 +535,23 @@
|
||||
var/voted = poll_check_voted(pollid, text = TRUE, silent = TRUE)
|
||||
if(isnull(voted))
|
||||
return
|
||||
var/adminrank = sanitizeSQL(poll_rank())
|
||||
var/adminrank = poll_rank()
|
||||
if(!adminrank)
|
||||
return
|
||||
replytext = sanitizeSQL(replytext)
|
||||
if(!(length(replytext) > 0) || !(length(replytext) <= 8000))
|
||||
to_chat(usr, "The text you entered was invalid or too long. Please correct the text and submit again.")
|
||||
return
|
||||
var/datum/db_query/query_text_vote
|
||||
if(!voted)
|
||||
query_text_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (Now(), [pollid], '[ckey]', INET_ATON('[client.address]'), '[replytext]', '[adminrank]')")
|
||||
query_text_vote = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("poll_textreply")] (datetime, pollid, ckey, ip, replytext, adminrank)
|
||||
VALUES (Now(), :pollid, :ckey, INET_ATON(:address), :replytext, :adminrank)
|
||||
"}, list("pollid" = pollid, "ckey" = ckey, "address" = client.address, "replytext" = replytext, "adminrank" = adminrank))
|
||||
else
|
||||
query_text_vote = SSdbcore.NewQuery("UPDATE [format_table_name("poll_textreply")] SET datetime = Now(), ip = INET_ATON('[client.address]'), replytext = '[replytext]' WHERE pollid = '[pollid]' AND ckey = '[ckey]'")
|
||||
query_text_vote = SSdbcore.NewQuery({"
|
||||
UPDATE [format_table_name("poll_textreply")]
|
||||
SET datetime = Now(), ip = INET_ATON(:address), replytext = :replytext WHERE pollid = :pollid AND ckey = :ckey
|
||||
"}, list("address" = client.address, "replytext" = replytext, "pollid" = pollid, "ckey" = ckey))
|
||||
if(!query_text_vote.warn_execute())
|
||||
qdel(query_text_vote)
|
||||
return
|
||||
@@ -565,8 +583,10 @@
|
||||
var/adminrank = "Player"
|
||||
if(client.holder)
|
||||
adminrank = client.holder.rank.name
|
||||
adminrank = sanitizeSQL(adminrank)
|
||||
var/datum/db_query/query_numval_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]', [(isnull(rating)) ? "null" : rating])")
|
||||
var/datum/db_query/query_numval_vote = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("poll_vote")] (datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating)
|
||||
VALUES (Now(), :pollid, :optionid, :ckey, INET_ATON(:address), :adminrank, :rating)
|
||||
"}, list("pollid" = pollid, "optionid" = optionid, "ckey" = ckey, "address" = client.address, "adminrank" = adminrank, "rating" = isnull(rating) ? "null" : rating))
|
||||
if(!query_numval_vote.warn_execute())
|
||||
qdel(query_numval_vote)
|
||||
return
|
||||
@@ -609,8 +629,10 @@
|
||||
var/adminrank = "Player"
|
||||
if(!QDELETED(client) && client.holder)
|
||||
adminrank = client.holder.rank.name
|
||||
adminrank = sanitizeSQL(adminrank)
|
||||
var/datum/db_query/query_multi_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]')")
|
||||
var/datum/db_query/query_multi_vote = SSdbcore.NewQuery({"
|
||||
INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank)
|
||||
VALUES (Now(), :pollid, :optionid, :ckey, INET_ATON(:address), :adminrank)
|
||||
"}, list("pollid" = pollid, "optionid" = optionid, "ckey" = ckey, "address" = client.address, "adminrank" = adminrank))
|
||||
if(!query_multi_vote.warn_execute())
|
||||
qdel(query_multi_vote)
|
||||
return 1
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
break
|
||||
var/msg = "[key_name_admin(src)] [ADMIN_JMP(src)] was found to have no .loc with an attached client, if the cause is unknown it would be wise to ask how this was accomplished."
|
||||
message_admins(msg)
|
||||
send2irc_adminless_only("Mob", msg, R_ADMIN)
|
||||
send2tgs_adminless_only("Mob", msg, R_ADMIN)
|
||||
log_game("[key_name(src)] was found to have no .loc with an attached client.")
|
||||
|
||||
// This is a temporary error tracker to make sure we've caught everything
|
||||
|
||||
@@ -398,7 +398,7 @@
|
||||
return
|
||||
mode = SHUTTLE_DOCKED
|
||||
setTimer(SSshuttle.emergencyDockTime)
|
||||
send2irc("Server", "The Emergency Shuttle has docked with the station.")
|
||||
send2adminchat("Server", "The Emergency Shuttle has docked with the station.")
|
||||
priority_announce("The Emergency Shuttle has docked with the station. You have [timeLeft(600)] minutes to board the Emergency Shuttle.", null, "shuttledock", "Priority")
|
||||
ShuttleDBStuff()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user