Browse Source

Port of Replays from Yogstation (#48579)

* demos (ported from yogstation)

rustg update + write with no format

use external hook for logging

use proper log vars

fix + clarifying comment

don't start the log

release build of rust-g

fix something caught by the lint

Update code/__DEFINES/subsystems.dm

Co-Authored-By: Jordan Brown <Cyberboss@users.noreply.github.com>

Update code/controllers/subsystem/demo.dm

Co-Authored-By: JJRcop <jrubcop@gmail.com>

Update code/controllers/subsystem/demo.dm

Co-Authored-By: JJRcop <jrubcop@gmail.com>

moves hooks out of a dedicated file

len = 0 to Cut(), remove semicolons

untyped loop

* updated rust_g

* 513 updates
pride
Rob Bailey 4 months ago
committed by GitHub
parent
commit
c20a04543b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 909 additions and 433 deletions
  1. +1
    -1
      code/__DEFINES/rust_g.dm
  2. +3
    -0
      code/__DEFINES/subsystems.dm
  3. +5
    -3
      code/__HELPERS/_logging.dm
  4. +3
    -0
      code/_globalvars/logging.dm
  5. +5
    -0
      code/_onclick/item_attack.dm
  6. +3
    -1
      code/controllers/subsystem/chat.dm
  7. +427
    -0
      code/controllers/subsystem/demo.dm
  8. +5
    -0
      code/controllers/subsystem/garbage.dm
  9. +6
    -0
      code/game/atoms.dm
  10. +4
    -0
      code/game/atoms_movable.dm
  11. +1
    -0
      code/game/machinery/doors/airlock.dm
  12. +1
    -0
      code/game/machinery/doors/poddoor.dm
  13. +1
    -0
      code/game/machinery/doors/windowdoor.dm
  14. +1
    -0
      code/game/turfs/change_turf.dm
  15. +4
    -0
      code/game/turfs/turf.dm
  16. +2
    -0
      code/game/world.dm
  17. +1
    -1
      code/modules/admin/IsBanned.dm
  18. +31
    -31
      code/modules/admin/admin.dm
  19. +1
    -1
      code/modules/admin/admin_investigate.dm
  20. +2
    -2
      code/modules/admin/admin_ranks.dm
  21. +10
    -10
      code/modules/admin/admin_verbs.dm
  22. +12
    -12
      code/modules/admin/callproc/callproc.dm
  23. +4
    -4
      code/modules/admin/create_poll.dm
  24. +6
    -6
      code/modules/admin/fun_balloon.dm
  25. +2
    -2
      code/modules/admin/holder2.dm
  26. +4
    -4
      code/modules/admin/outfits.dm
  27. +13
    -13
      code/modules/admin/permissionedit.dm
  28. +6
    -6
      code/modules/admin/secrets.dm
  29. +7
    -7
      code/modules/admin/sound_emitter.dm
  30. +15
    -15
      code/modules/admin/sql_ban_system.dm
  31. +13
    -13
      code/modules/admin/sql_message_system.dm
  32. +23
    -23
      code/modules/admin/stickyban.dm
  33. +2
    -2
      code/modules/admin/team_panel.dm
  34. +56
    -56
      code/modules/admin/topic.dm
  35. +1
    -1
      code/modules/admin/verbs/BrokenInhands.dm
  36. +23
    -23
      code/modules/admin/verbs/SDQL2/SDQL_2.dm
  37. +1
    -1
      code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
  38. +13
    -13
      code/modules/admin/verbs/adminhelp.dm
  39. +12
    -12
      code/modules/admin/verbs/adminjump.dm
  40. +27
    -27
      code/modules/admin/verbs/adminpm.dm
  41. +1
    -1
      code/modules/admin/verbs/adminsay.dm
  42. +6
    -6
      code/modules/admin/verbs/atmosdebug.dm
  43. +1
    -1
      code/modules/admin/verbs/bluespacearty.dm
  44. +1
    -1
      code/modules/admin/verbs/borgpanel.dm
  45. +3
    -3
      code/modules/admin/verbs/deadsay.dm
  46. +14
    -14
      code/modules/admin/verbs/debug.dm
  47. +1
    -1
      code/modules/admin/verbs/fix_air.dm
  48. +1
    -1
      code/modules/admin/verbs/fps.dm
  49. +1
    -1
      code/modules/admin/verbs/getlogs.dm
  50. +5
    -5
      code/modules/admin/verbs/map_template_loadverb.dm
  51. +5
    -5
      code/modules/admin/verbs/mapping.dm
  52. +1
    -1
      code/modules/admin/verbs/panicbunker.dm
  53. +11
    -11
      code/modules/admin/verbs/playsound.dm
  54. +1
    -1
      code/modules/admin/verbs/possess.dm
  55. +7
    -7
      code/modules/admin/verbs/pray.dm
  56. +32
    -32
      code/modules/admin/verbs/randomverbs.dm
  57. +1
    -1
      code/modules/admin/verbs/reestablish_db_connection.dm
  58. +1
    -1
      code/modules/admin/verbs/spawnobjasmob.dm
  59. +4
    -4
      code/modules/admin/verbs/tripAI.dm
  60. +16
    -16
      code/modules/admin/view_variables/mass_edit_variables.dm
  61. +16
    -16
      code/modules/admin/view_variables/modify_variables.dm
  62. +6
    -6
      code/modules/admin/view_variables/topic.dm
  63. +3
    -3
      code/modules/admin/view_variables/topic_basic.dm
  64. +1
    -1
      code/modules/admin/view_variables/view_variables.dm
  65. +2
    -0
      code/modules/client/client_procs.dm
  66. +7
    -4
      code/modules/goonchat/browserOutput.dm
  67. +1
    -0
      code/modules/mob/login.dm
  68. +2
    -0
      code/modules/shuttle/on_move.dm
  69. BIN
      rust_g.dll
  70. +1
    -0
      tgstation.dme

+ 1
- 1
code/__DEFINES/rust_g.dm View File

@@ -11,7 +11,7 @@
#define rustg_git_revparse(rev) call(RUST_G, "rg_git_revparse")(rev)
#define rustg_git_commit_date(rev) call(RUST_G, "rg_git_commit_date")(rev)

#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text)
#define rustg_log_write(fname, text, format) call(RUST_G, "log_write")(fname, text, format)
/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")()

// RUST-G defines & procs for HTTP component


+ 3
- 0
code/__DEFINES/subsystems.dm View File

@@ -134,6 +134,7 @@
#define INIT_ORDER_PATH -50
#define INIT_ORDER_DISCORD -60
#define INIT_ORDER_PERSISTENCE -95
#define INIT_ORDER_DEMO -99 // o avoid a bunch of changes related to initialization being written, do this last
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.

// Subsystem fire priority, from lowest to highest priority
@@ -205,6 +206,8 @@
}\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
if(isturf(A)){SSdemo.mark_turf(A);}\
else if(isobj(A) || ismob(A)){SSdemo.mark_dirty(A);}\
}

// Air subsystem subtasks


+ 5
- 3
code/__HELPERS/_logging.dm View File

@@ -4,7 +4,9 @@
#define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound)
#define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text)
#define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text)
#define WRITE_LOG(log, text) rustg_log_write(log, text)
//This is an external call, "true" and "false" are how rust parses out booleans
#define WRITE_LOG(log, text) rustg_log_write(log, text, "true")
#define WRITE_LOG_NO_FORMAT(log, text) rustg_log_write(log, text, "false")

//print a warning message to world.log
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [UNLINT(src)] usr: [usr].")
@@ -190,8 +192,8 @@
/proc/log_mapping(text)
WRITE_LOG(GLOB.world_map_error_log, text)

/* ui logging */
/* ui logging */
/proc/log_tgui(text)
WRITE_LOG(GLOB.tgui_log, text)



+ 3
- 0
code/_globalvars/logging.dm View File

@@ -45,6 +45,9 @@ GLOBAL_PROTECT(world_shuttle_log)
GLOBAL_VAR(discord_api_log)
GLOBAL_PROTECT(discord_api_log)
GLOBAL_VAR(demo_log)
GLOBAL_PROTECT(demo_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
GLOBAL_LIST_EMPTY(admin_log)


+ 5
- 0
code/_onclick/item_attack.dm View File

@@ -8,6 +8,11 @@
* * [/obj/item/proc/afterattack]. The return value does not matter.
*/
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
SSdemo.mark_dirty(src)
if(isturf(target))
SSdemo.mark_turf(target)
else
SSdemo.mark_dirty(target)
if(tool_behaviour && target.tool_act(user, src, tool_behaviour))
return
if(pre_attack(target, user, params))


+ 3
- 1
code/controllers/subsystem/chat.dm View File

@@ -18,7 +18,7 @@ SUBSYSTEM_DEF(chat)
return


/datum/controller/subsystem/chat/proc/queue(target, message, handle_whitespace = TRUE, trailing_newline = TRUE)
/datum/controller/subsystem/chat/proc/queue(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = TRUE)
if(!target || !message)
return

@@ -39,6 +39,8 @@ SUBSYSTEM_DEF(chat)
if (trailing_newline)
message += "<br>"

if(!confidential)
SSdemo.write_chat(target, message)

//url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
//Do the double-encoding here to save nanoseconds


+ 427
- 0
code/controllers/subsystem/demo.dm View File

@@ -0,0 +1,427 @@
SUBSYSTEM_DEF(demo)
name = "Demo"
wait = 1
flags = SS_TICKER
init_order = INIT_ORDER_DEMO
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY

var/list/pre_init_lines = list() // stuff like chat before the init
var/list/icon_cache = list()
var/list/icon_state_caches = list()
var/list/name_cache = list()

var/list/marked_dirty = list()
var/list/marked_new = list()
var/list/marked_turfs = list()
var/list/del_list = list()

var/last_written_time = null
var/last_chat_message = null

// stats stuff
var/last_queued = 0
var/last_completed = 0

/datum/controller/subsystem/demo/proc/write_time()
var/new_time = world.time
if(last_written_time != new_time)
if(initialized)
WRITE_LOG_NO_FORMAT(GLOB.demo_log, "time [new_time]\n")
else
pre_init_lines += "time [new_time]"
last_written_time = new_time

/datum/controller/subsystem/demo/proc/write_event_line(line)
write_time()
if(initialized)
WRITE_LOG_NO_FORMAT(GLOB.demo_log, "[line]\n")
else
pre_init_lines += line

/datum/controller/subsystem/demo/proc/write_chat(target, text)
var/target_text = ""
if(target == GLOB.clients)
target_text = "world"
else if(islist(target))
var/list/target_keys = list()
for(var/T in target)
var/client/C = CLIENT_FROM_VAR(T)
if(C)
target_keys += C.ckey
if(!target_keys.len)
return
target_text = jointext(target_keys, ",")
else
var/client/C = CLIENT_FROM_VAR(target)
if(C)
target_text = C.ckey
else
return
write_event_line("chat [target_text] [last_chat_message == text ? "=" : json_encode(text)]")
last_chat_message = text

/datum/controller/subsystem/demo/Initialize()
WRITE_LOG_NO_FORMAT(GLOB.demo_log, "demo version 1\n") // increment this if you change the format
if(GLOB.revdata)
WRITE_LOG_NO_FORMAT(GLOB.demo_log, "commit [GLOB.revdata.originmastercommit || GLOB.revdata.commit]\n")

// write a "snapshot" of the world at this point.
// start with turfs
log_world("Writing turfs...")
WRITE_LOG_NO_FORMAT(GLOB.demo_log, "init [world.maxx] [world.maxy] [world.maxz]\n")
marked_turfs.Cut()
for(var/z in 1 to world.maxz)
var/row_list = list()
var/last_appearance
var/rle_count = 1
for(var/y in 1 to world.maxy)
for(var/x in 1 to world.maxx)
var/turf/T = locate(x,y,z)
T.demo_last_appearance = T.appearance
var/this_appearance
// space turfs are difficult to RLE otherwise, because they all
// have different appearances despite being the same thing.
if(T.type == /turf/open/space || T.type == /turf/open/space/basic)
this_appearance = "s" // save the bytes
else if(istype(T, /turf/open/space/transit))
this_appearance = "t[T.dir]"
else
this_appearance = T.appearance
if(this_appearance == last_appearance)
rle_count++
else
if(rle_count > 1)
row_list += rle_count
rle_count = 1
if(istext(this_appearance))
row_list += this_appearance
else
// do a diff with the previous turf to save those bytes
row_list += encode_appearance(this_appearance, istext(last_appearance) ? null : last_appearance)
last_appearance = this_appearance
if(rle_count > 1)
row_list += rle_count
WRITE_LOG_NO_FORMAT(GLOB.demo_log, jointext(row_list, ",") + "\n")
CHECK_TICK
// then do objects
log_world("Writing objects")
marked_new.Cut()
marked_dirty.Cut()
for(var/z in 1 to world.maxz)
var/spacing = 0
var/row_list = list()
for(var/y in 1 to world.maxy)
for(var/x in 1 to world.maxx)
var/turf/T = locate(x,y,z)
var/list/turf_list = list()
for(var/C in T.contents)
var/atom/movable/as_movable = C
if(as_movable.loc != T)
continue
if(isobj(C) || ismob(C))
turf_list += encode_init_obj(C)
if(turf_list.len)
if(spacing)
row_list += spacing
spacing = 0
row_list += turf_list
spacing++
CHECK_TICK // This is a bit risky because something might change but meh, its not a big deal.
WRITE_LOG_NO_FORMAT(GLOB.demo_log, jointext(row_list, ",") + "\n")

// track objects that exist in nullspace
var/nullspace_list = list()
for(var/M in world)
if(!isobj(M) && !ismob(M))
continue
var/atom/movable/AM = M
if(AM.loc != null)
continue
nullspace_list += encode_init_obj(AM)
CHECK_TICK
WRITE_LOG_NO_FORMAT(GLOB.demo_log, jointext(nullspace_list, ",") + "\n")

for(var/line in pre_init_lines)
WRITE_LOG_NO_FORMAT(GLOB.demo_log, "[line]\n")

return ..()

/datum/controller/subsystem/demo/fire()
if(!src.marked_new.len && !src.marked_dirty.len && !src.marked_turfs.len && !src.del_list.len)
return // nothing to do

last_queued = src.marked_new.len + src.marked_dirty.len + src.marked_turfs.len
last_completed = 0

write_time()
if(src.del_list.len)
var/s = "del [jointext(src.del_list, ",")]\n" // if I don't do it like this I get "incorrect number of macro arguments" because byond is stupid and sucks
WRITE_LOG_NO_FORMAT(GLOB.demo_log, s)
src.del_list.Cut()

var/canceled = FALSE

var/list/marked_dirty = src.marked_dirty
var/list/dirty_updates = list()
while(marked_dirty.len)
last_completed++
var/atom/movable/M = marked_dirty[marked_dirty.len]
marked_dirty.len--
if(M.gc_destroyed || !M)
continue
if(M.loc == M.demo_last_loc && M.appearance == M.demo_last_appearance)
continue
var/loc_string = "="
if(M.loc != M.demo_last_loc)
loc_string = "null"
if(isturf(M.loc))
loc_string = "[M.x],[M.y],[M.z]"
else if(ismovable(M.loc))
loc_string = "\ref[M.loc]"
M.demo_last_loc = M.loc
var/appearance_string = "="
if(M.appearance != M.demo_last_appearance)
appearance_string = encode_appearance(M.appearance, M.demo_last_appearance)
M.demo_last_appearance = M.appearance
dirty_updates += "\ref[M] [loc_string] [appearance_string]"
if(MC_TICK_CHECK)
canceled = TRUE
break
if(dirty_updates.len)
var/s = "update [jointext(dirty_updates, ",")]\n"
WRITE_LOG_NO_FORMAT(GLOB.demo_log, s)
if(canceled)
return


var/list/marked_new = src.marked_new
var/list/new_updates = list()
while(marked_new.len)
last_completed++
var/atom/movable/M = marked_new[marked_new.len]
marked_new.len--
if(M.gc_destroyed || !M)
continue
var/loc_string = "null"
if(isturf(M.loc))
loc_string = "[M.x],[M.y],[M.z]"
else if(ismovable(M.loc))
loc_string = "\ref[M.loc]"
M.demo_last_appearance = M.appearance
new_updates += "\ref[M] [loc_string] [encode_appearance(M.appearance)]"
if(MC_TICK_CHECK)
canceled = TRUE
break
if(new_updates.len)
var/s = "new [jointext(new_updates, ",")]\n"
WRITE_LOG_NO_FORMAT(GLOB.demo_log, s)
if(canceled)
return


var/list/marked_turfs = src.marked_turfs
var/list/turf_updates = list()
while(marked_turfs.len)
last_completed++
var/turf/T = marked_turfs[marked_turfs.len]
marked_turfs.len--
if(T && T.appearance != T.demo_last_appearance)
turf_updates += "([T.x],[T.y],[T.z])=[encode_appearance(T.appearance, T.demo_last_appearance)]"
T.demo_last_appearance = T.appearance
if(MC_TICK_CHECK)
canceled = TRUE
break
if(turf_updates.len)
var/s = "turf [jointext(turf_updates, ",")]\n"
WRITE_LOG_NO_FORMAT(GLOB.demo_log, s)
if(canceled)
return

/datum/controller/subsystem/demo/proc/encode_init_obj(atom/movable/M)
M.demo_last_loc = M.loc
M.demo_last_appearance = M.appearance
var/encoded_appearance = encode_appearance(M.appearance)
var/list/encoded_contents = list()
for(var/C in M.contents)
if(isobj(C) || ismob(C))
encoded_contents += encode_init_obj(C)
return "\ref[M]=[encoded_appearance][(encoded_contents.len ? "([jointext(encoded_contents, ",")])" : "")]"

// please make sure the order you call this function in is the same as the order you write
/datum/controller/subsystem/demo/proc/encode_appearance(image/appearance, image/diff_appearance, diff_remove_overlays = FALSE)
if(appearance == null)
return "n"
if(appearance == diff_appearance)
return "="

var/icon_txt = "[appearance.icon]"
var/cached_icon = icon_cache[icon_txt] || icon_txt
var/list/icon_state_cache
if(!isnum(cached_icon))
icon_cache[icon_txt] = icon_cache.len + 1
icon_state_cache = (icon_state_caches[++icon_state_caches.len] = list())
else
icon_state_cache = icon_state_caches[cached_icon]

var/list/cached_icon_state = icon_state_cache[appearance.icon_state] || appearance.icon_state
if(!isnum(cached_icon_state))
icon_state_cache[appearance.icon_state] = icon_state_cache.len + 1

var/cached_name = name_cache[appearance.name] || appearance.name
if(!isnum(cached_name))
name_cache[appearance.name] = name_cache.len + 1

var/color_string = appearance.color || "w"
if(islist(color_string))
var/list/old_list = appearance.color
var/list/inted = list()
inted.len = old_list.len
for(var/i in 1 to old_list.len)
inted[i] += round(old_list[i] * 255)
color_string = jointext(inted, ",")
var/overlays_string = "\[]"
if(appearance.overlays.len)
var/list/overlays_list = list()
for(var/i in 1 to appearance.overlays.len)
var/image/overlay = appearance.overlays[i]
overlays_list += encode_appearance(overlay, appearance, TRUE)
overlays_string = "\[[jointext(overlays_list, ",")]]"

var/underlays_string = "\[]"
if(appearance.underlays.len)
var/list/underlays_list = list()
for(var/i in 1 to appearance.underlays.len)
var/image/underlay = appearance.underlays[i]
underlays_list += encode_appearance(underlay, appearance, TRUE)
underlays_string = "\[[jointext(underlays_list, ",")]]"

var/appearance_transform_string = "i"
if(appearance.transform)
var/matrix/M = appearance.transform
appearance_transform_string = "[M.a],[M.b],[M.c],[M.d],[M.e],[M.f]"
if(appearance_transform_string == "1,0,0,0,1,0")
appearance_transform_string = "i"
var/list/appearance_list = list(
json_encode(cached_icon),
json_encode(cached_icon_state),
json_encode(cached_name),
appearance.appearance_flags,
appearance.layer,
appearance.plane == -32767 ? "" : appearance.plane,
appearance.dir == 2 ? "" : appearance.dir,
appearance.color ? color_string : "",
appearance.alpha == 255 ? "" : appearance.alpha,
appearance.pixel_x == 0 ? "" : appearance.pixel_x,
appearance.pixel_y == 0 ? "" : appearance.pixel_y,
appearance.blend_mode <= 1 ? "" : appearance.blend_mode,
appearance_transform_string != "i" ? appearance_transform_string : "",
appearance:invisibility == 0 ? "" : appearance:invisibility, // colon because dreamchecker is dumb
appearance.pixel_w == 0 ? "" : appearance.pixel_w,
appearance.pixel_z == 0 ? "" : appearance.pixel_z,
appearance.overlays.len ? overlays_string : "",
appearance.underlays.len ? underlays_string : ""
)
while(appearance_list[appearance_list.len] == "" && appearance_list.len > 0)
appearance_list.len--

var/undiffed_string = "{[jointext(appearance_list, ";")]}"

if(diff_appearance)
var/overlays_identical = TRUE
if(diff_remove_overlays)
overlays_identical = (appearance.overlays.len == 0)
else if(appearance.overlays.len != diff_appearance.overlays.len)
overlays_identical = FALSE
else
for(var/i in 1 to appearance.overlays.len)
if(appearance.overlays[i] != diff_appearance.overlays[i])
overlays_identical = FALSE
break

var/underlays_identical = TRUE
if(diff_remove_overlays)
underlays_identical = (appearance.underlays.len == 0)
else if(appearance.underlays.len != diff_appearance.underlays.len)
underlays_identical = FALSE
else
for(var/i in 1 to appearance.underlays.len)
if(appearance.underlays[i] != diff_appearance.underlays[i])
underlays_identical = FALSE
break

var/diff_transform_string = "i"
if(diff_appearance.transform)
var/matrix/M = diff_appearance.transform
diff_transform_string = "[M.a],[M.b],[M.c],[M.d],[M.e],[M.f]"
if(diff_transform_string == "1,0,0,0,1,0")
diff_transform_string = "i"

var/list/diffed_appearance_list = list(
json_encode(cached_icon),
json_encode(cached_icon_state),
json_encode(cached_name),
appearance.appearance_flags == diff_appearance.appearance_flags ? "" : appearance.appearance_flags,
appearance.layer == diff_appearance.layer ? "" : appearance.layer,
appearance.plane == diff_appearance.plane ? "" : appearance.plane,
appearance.dir == diff_appearance.dir ? "" : appearance.dir,
appearance.color == diff_appearance.color ? "" : color_string,
appearance.alpha == diff_appearance.alpha ? "" : appearance.alpha,
appearance.pixel_x == diff_appearance.pixel_x ? "" : appearance.pixel_x,
appearance.pixel_y == diff_appearance.pixel_y ? "" : appearance.pixel_y,
appearance.blend_mode == diff_appearance.blend_mode ? "" : appearance.blend_mode,
appearance_transform_string == diff_transform_string ? "" : appearance_transform_string,
appearance:invisibility == diff_appearance:invisibility ? "" : appearance:invisibility, // colon because dreamchecker is too dumb
appearance.pixel_w == diff_appearance.pixel_w ? "" : appearance.pixel_w,
appearance.pixel_z == diff_appearance.pixel_z ? "" : appearance.pixel_z,
overlays_identical ? "" : overlays_string,
underlays_identical ? "" :underlays_string
)
while(diffed_appearance_list[diffed_appearance_list.len] == "" && diffed_appearance_list.len > 0)
diffed_appearance_list.len--

var/diffed_string = "~{[jointext(diffed_appearance_list, ";")]}"
if(length(diffed_string) < length(undiffed_string))
return diffed_string
return undiffed_string

/datum/controller/subsystem/demo/stat_entry(msg)
msg += "Remaining: {"
msg += "Trf:[marked_turfs.len]|"
msg += "New:[marked_new.len]|"
msg += "Upd:[marked_dirty.len]|"
msg += "Del:[del_list.len]"
msg += "}"
..(msg)

/datum/controller/subsystem/demo/proc/mark_turf(turf/T)
if(!isturf(T))
return
marked_turfs[T] = TRUE

/datum/controller/subsystem/demo/proc/mark_new(atom/movable/M)
if(!isobj(M) && !ismob(M))
return
if(M.gc_destroyed)
return
marked_new[M] = TRUE
if(marked_dirty[M])
marked_dirty -= M

// I can't wait for when TG ports this and they make this a #define macro.
/datum/controller/subsystem/demo/proc/mark_dirty(atom/movable/M)
if(!isobj(M) && !ismob(M))
return
if(M.gc_destroyed)
return
if(!marked_new[M])
marked_dirty[M] = TRUE

/datum/controller/subsystem/demo/proc/mark_destroyed(atom/movable/M)
if(!isobj(M) && !ismob(M))
return
if(marked_new[M])
marked_new -= M
if(marked_dirty[M])
marked_dirty -= M
if(initialized)
del_list["\ref[M]"] = 1

+ 5
- 0
code/controllers/subsystem/garbage.dm View File

@@ -279,6 +279,7 @@ SUBSYSTEM_DEF(garbage)
SSgarbage.Queue(D)
if (QDEL_HINT_IWILLGC)
D.gc_destroyed = world.time
SSdemo.mark_destroyed(D)
return
if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
if(!force)
@@ -298,8 +299,10 @@ SUBSYSTEM_DEF(garbage)

SSgarbage.Queue(D)
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete
SSdemo.mark_destroyed(D)
SSgarbage.Queue(D, GC_QUEUE_HARDDELETE)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
SSdemo.mark_destroyed(D)
SSgarbage.HardDelete(D)
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.Queue(D)
@@ -318,6 +321,8 @@ SUBSYSTEM_DEF(garbage)
#endif
I.no_hint++
SSgarbage.Queue(D)
if(D)
SSdemo.mark_destroyed(D)
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")



+ 6
- 0
code/game/atoms.dm View File

@@ -92,6 +92,9 @@
///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
var/list/targeted_by
/// Last appearance of the atom for demo saving purposes
var/image/demo_last_appearance
/**
* Called when an atom is created in byond (built in engine proc)
*
@@ -116,6 +119,7 @@
if(SSatoms.InitAtom(src, args))
//we were deleted
return
SSdemo.mark_new(src)
/**
* The primary method that objects are setup in SS13 with
@@ -556,6 +560,7 @@
add_overlay(new_overlays)
. = TRUE
SSdemo.mark_dirty(src)
SEND_SIGNAL(src, COMSIG_ATOM_UPDATED_ICON, signalOut, .)
/// Updates the icon state of the atom
@@ -832,6 +837,7 @@
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir)
dir = newdir
SSdemo.mark_dirty(src)
///Handle melee attack by a mech
/atom/proc/mech_melee_attack(obj/mecha/M)


+ 4
- 0
code/game/atoms_movable.dm View File

@@ -43,6 +43,9 @@
var/zfalling = FALSE
///Last location of the atom for demo recording purposes
var/atom/demo_last_loc
/// Either FALSE, [EMISSIVE_BLOCK_GENERIC], or [EMISSIVE_BLOCK_UNIQUE]
var/blocks_emissive = FALSE
///Internal holder for emissive blocker object, do not use directly use blocks_emissive
@@ -392,6 +395,7 @@
if (length(client_mobs_in_contents))
update_parallax_contents()
SSdemo.mark_dirty(src)
return TRUE
/atom/movable/Destroy(force)


+ 1
- 0
code/game/machinery/doors/airlock.dm View File

@@ -431,6 +431,7 @@
if(AIRLOCK_DENY, AIRLOCK_OPENING, AIRLOCK_CLOSING, AIRLOCK_EMAG)
icon_state = "nonexistenticonstate" //MADNESS
set_airlock_overlays(state)
SSdemo.mark_dirty(src)

/obj/machinery/door/airlock/proc/set_airlock_overlays(state)
var/mutable_appearance/frame_overlay


+ 1
- 0
code/game/machinery/doors/poddoor.dm View File

@@ -87,6 +87,7 @@
icon_state = "closed"
else
icon_state = "open"
SSdemo.mark_dirty(src)
/obj/machinery/door/poddoor/try_to_activate_door(mob/user)
return


+ 1
- 0
code/game/machinery/doors/windowdoor.dm View File

@@ -54,6 +54,7 @@
icon_state = base_state
else
icon_state = "[base_state]open"
SSdemo.mark_dirty(src)
/obj/machinery/door/window/proc/open_and_close()
if(!open())


+ 1
- 0
code/game/turfs/change_turf.dm View File

@@ -132,6 +132,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(

for(var/turf/open/space/S in RANGE_TURFS(1, src)) //RANGE_TURFS is in code\__HELPERS\game.dm
S.update_starlight()
SSdemo.mark_turf(W)

return W



+ 4
- 0
code/game/turfs/turf.dm View File

@@ -547,3 +547,7 @@
. = ..()
if(. != BULLET_ACT_FORCE_PIERCE)
. = BULLET_ACT_TURF

/turf/setDir()
. = ..()
SSdemo.mark_turf(src)

+ 2
- 0
code/game/world.dm View File

@@ -140,6 +140,8 @@ GLOBAL_VAR(restart_counter)
GLOB.world_shuttle_log = "[GLOB.log_directory]/shuttle.log"
GLOB.discord_api_log = "[GLOB.log_directory]/discord_api_log.log"
GLOB.demo_log = "[GLOB.log_directory]/demo.log"
#ifdef UNIT_TESTS
GLOB.test_log = file("[GLOB.log_directory]/tests.log")
start_log(GLOB.test_log)


+ 1
- 1
code/modules/admin/IsBanned.dm View File

@@ -212,7 +212,7 @@
return null
if (C) //user is already connected!.
to_chat(C, "<span class='redtext'>You are about to get disconnected for matching a sticky ban after you connected. If this turns out to be the ban evasion detection system going haywire, we will automatically detect this and revert the matches. if you feel that this is the case, please wait EXACTLY 6 seconds then reconnect using file -> reconnect to see if the match was automatically reversed.</span>")
to_chat(C, "<span class='redtext'>You are about to get disconnected for matching a sticky ban after you connected. If this turns out to be the ban evasion detection system going haywire, we will automatically detect this and revert the matches. if you feel that this is the case, please wait EXACTLY 6 seconds then reconnect using file -> reconnect to see if the match was automatically reversed.</span>", confidential = TRUE)
var/desc = "\nReason:(StickyBan) You, or another user of this computer or connection ([bannedckey]) is banned from playing here. The ban reason is:\n[ban["message"]]\nThis ban was applied by [ban["admin"]]\nThis is a BanEvasion Detection System ban, if you think this ban is a mistake, please wait EXACTLY 6 seconds, then try again before filing an appeal.\n"
. = list("reason" = "Stickyban", "desc" = desc)


+ 31
- 31
code/modules/admin/admin.dm View File

@@ -2,11 +2,11 @@
////////////////////////////////
/proc/message_admins(msg)
msg = "<span class=\"admin\"><span class=\"prefix\">ADMIN LOG:</span> <span class=\"message linkify\">[msg]</span></span>"
to_chat(GLOB.admins, msg)
to_chat(GLOB.admins, msg, confidential = TRUE)
/proc/relay_msg_admins(msg)
msg = "<span class=\"admin\"><span class=\"prefix\">RELAY:</span> <span class=\"message linkify\">[msg]</span></span>"
to_chat(GLOB.admins, msg)
to_chat(GLOB.admins, msg, confidential = TRUE)
///////////////////////////////////////////////////////////////////////////////////////////////Panels
@@ -22,7 +22,7 @@
log_admin("[key_name(usr)] checked the individual player panel for [key_name(M)][isobserver(usr)?"":" while in game"].")
if(!M)
to_chat(usr, "<span class='warning'>You seem to be selecting a mob that doesn't exist anymore.</span>")
to_chat(usr, "<span class='warning'>You seem to be selecting a mob that doesn't exist anymore.</span>", confidential = TRUE)
return
var/body = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>Options for [M.key]</title></head>"
@@ -199,7 +199,7 @@
if (!istype(src, /datum/admins))
src = usr.client.holder
if (!istype(src, /datum/admins))
to_chat(usr, "Error: you are not an admin!")
to_chat(usr, "Error: you are not an admin!", confidential = TRUE)
return
var/dat
dat = text("<HEAD><TITLE>Admin Newscaster</TITLE></HEAD><H3>Admin Newscaster Unit</H3>")
@@ -515,7 +515,7 @@
if(message)
if(!check_rights(R_SERVER,0))
message = adminscrub(message,500)
to_chat(world, "<span class='adminnotice'><b>[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:</b></span>\n \t [message]")
to_chat(world, "<span class='adminnotice'><b>[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:</b></span>\n \t [message]", confidential = TRUE)
log_admin("Announce: [key_name(usr)] : [message]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Announce") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -537,7 +537,7 @@
else
message_admins("[key_name(usr)] set the admin notice.")
log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]")
to_chat(world, "<span class='adminnotice'><b>Admin Notice:</b>\n \t [new_admin_notice]</span>")
to_chat(world, "<span class='adminnotice'><b>Admin Notice:</b>\n \t [new_admin_notice]</span>", confidential = TRUE)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Admin Notice") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
GLOB.admin_notice = new_admin_notice
return
@@ -596,9 +596,9 @@
set name="Toggle Entering"
GLOB.enter_allowed = !( GLOB.enter_allowed )
if (!( GLOB.enter_allowed ))
to_chat(world, "<B>New players may no longer enter the game.</B>")
to_chat(world, "<B>New players may no longer enter the game.</B>", confidential = TRUE)
else
to_chat(world, "<B>New players may now enter the game.</B>")
to_chat(world, "<B>New players may now enter the game.</B>", confidential = TRUE)
log_admin("[key_name(usr)] toggled new player game entering.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled new player game entering.</span>")
world.update_status()
@@ -611,9 +611,9 @@
var/alai = CONFIG_GET(flag/allow_ai)
CONFIG_SET(flag/allow_ai, !alai)
if (alai)
to_chat(world, "<B>The AI job is no longer chooseable.</B>")
to_chat(world, "<B>The AI job is no longer chooseable.</B>", confidential = TRUE)
else
to_chat(world, "<B>The AI job is chooseable now.</B>")
to_chat(world, "<B>The AI job is chooseable now.</B>", confidential = TRUE)
log_admin("[key_name(usr)] toggled AI allowed.")
world.update_status()
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle AI", "[!alai ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -625,9 +625,9 @@
var/new_nores = !CONFIG_GET(flag/norespawn)
CONFIG_SET(flag/norespawn, new_nores)
if (!new_nores)
to_chat(world, "<B>You may now respawn.</B>")
to_chat(world, "<B>You may now respawn.</B>", confidential = TRUE)
else
to_chat(world, "<B>You may no longer respawn :(</B>")
to_chat(world, "<B>You may no longer respawn :(</B>", confidential = TRUE)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled respawn to [!new_nores ? "On" : "Off"].</span>")
log_admin("[key_name(usr)] toggled respawn to [!new_nores ? "On" : "Off"].")
world.update_status()
@@ -646,10 +646,10 @@
SSticker.SetTimeLeft(newtime)
SSticker.start_immediately = FALSE
if(newtime < 0)
to_chat(world, "<b>The game start has been delayed.</b>")
to_chat(world, "<b>The game start has been delayed.</b>", confidential = TRUE)
log_admin("[key_name(usr)] delayed the round start.")
else
to_chat(world, "<b>The game will start in [DisplayTimeText(newtime)].</b>")
to_chat(world, "<b>The game will start in [DisplayTimeText(newtime)].</b>", confidential = TRUE)
SEND_SOUND(world, sound('sound/ai/attention.ogg'))
log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -745,10 +745,10 @@
set name = "Show Traitor Panel"
if(!istype(M))
to_chat(usr, "This can only be used on instances of type /mob")
to_chat(usr, "This can only be used on instances of type /mob", confidential = TRUE)
return
if(!M.mind)
to_chat(usr, "This mob has no mind!")
to_chat(usr, "This mob has no mind!", confidential = TRUE)
return
M.mind.traitor_panel()
@@ -761,9 +761,9 @@
set name="Toggle tinted welding helmes"
GLOB.tinted_weldhelh = !( GLOB.tinted_weldhelh )
if (GLOB.tinted_weldhelh)
to_chat(world, "<B>The tinted_weldhelh has been enabled!</B>")
to_chat(world, "<B>The tinted_weldhelh has been enabled!</B>", confidential = TRUE)
else
to_chat(world, "<B>The tinted_weldhelh has been disabled!</B>")
to_chat(world, "<B>The tinted_weldhelh has been disabled!</B>", confidential = TRUE)
log_admin("[key_name(usr)] toggled tinted_weldhelh.")
message_admins("[key_name_admin(usr)] toggled tinted_weldhelh.")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Tinted Welding Helmets", "[GLOB.tinted_weldhelh ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -775,9 +775,9 @@
var/new_guest_ban = !CONFIG_GET(flag/guest_ban)
CONFIG_SET(flag/guest_ban, new_guest_ban)
if (new_guest_ban)
to_chat(world, "<B>Guests may no longer enter the game.</B>")
to_chat(world, "<B>Guests may no longer enter the game.</B>", confidential = TRUE)
else
to_chat(world, "<B>Guests may now enter the game.</B>")
to_chat(world, "<B>Guests may now enter the game.</B>", confidential = TRUE)
log_admin("[key_name(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.</span>")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Guests", "[!new_guest_ban ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -788,37 +788,37 @@
var/mob/living/silicon/S = i
ai_number++
if(isAI(S))
to_chat(usr, "<b>AI [key_name(S, usr)]'s laws:</b>")
to_chat(usr, "<b>AI [key_name(S, usr)]'s laws:</b>", confidential = TRUE)
else if(iscyborg(S))
var/mob/living/silicon/robot/R = S
to_chat(usr, "<b>CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [key_name(R.connected_ai)])":"(Independent)"]: laws:</b>")
to_chat(usr, "<b>CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [key_name(R.connected_ai)])":"(Independent)"]: laws:</b>", confidential = TRUE)
else if (ispAI(S))
to_chat(usr, "<b>pAI [key_name(S, usr)]'s laws:</b>")
to_chat(usr, "<b>pAI [key_name(S, usr)]'s laws:</b>", confidential = TRUE)
else
to_chat(usr, "<b>SOMETHING SILICON [key_name(S, usr)]'s laws:</b>")
to_chat(usr, "<b>SOMETHING SILICON [key_name(S, usr)]'s laws:</b>", confidential = TRUE)
if (S.laws == null)
to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.")
to_chat(usr, "[key_name(S, usr)]'s laws are null?? Contact a coder.", confidential = TRUE)
else
S.laws.show_laws(usr)
if(!ai_number)
to_chat(usr, "<b>No AIs located</b>" )
to_chat(usr, "<b>No AIs located</b>" , confidential = TRUE)
/datum/admins/proc/output_all_devil_info()
var/devil_number = 0
for(var/datum/mind/D in SSticker.mode.devils)
devil_number++
var/datum/antagonist/devil/devil = D.has_antag_datum(/datum/antagonist/devil)
to_chat(usr, "Devil #[devil_number]:<br><br>" + devil.printdevilinfo())
to_chat(usr, "Devil #[devil_number]:<br><br>" + devil.printdevilinfo(), confidential = TRUE)
if(!devil_number)
to_chat(usr, "<b>No Devils located</b>" )
to_chat(usr, "<b>No Devils located</b>" , confidential = TRUE)
/datum/admins/proc/output_devil_info(mob/living/M)
if(is_devil(M))
var/datum/antagonist/devil/devil = M.mind.has_antag_datum(/datum/antagonist/devil)
to_chat(usr, devil.printdevilinfo())
to_chat(usr, devil.printdevilinfo(), confidential = TRUE)
else
to_chat(usr, "<b>[M] is not a devil.")
to_chat(usr, "<b>[M] is not a devil.", confidential = TRUE)
/datum/admins/proc/manage_free_slots()
if(!check_rights())
@@ -921,7 +921,7 @@
if(kick_only_afk && !C.is_afk()) //Ignore clients who are not afk
continue
if(message)
to_chat(C, message)
to_chat(C, message, confidential = TRUE)
kicked_client_names.Add("[C.key]")
qdel(C)
return kicked_client_names


+ 1
- 1
code/modules/admin/admin_investigate.dm View File

@@ -37,6 +37,6 @@
var/F = file("[GLOB.log_directory]/[selected].html")
if(!fexists(F))
to_chat(src, "<span class='danger'>No [selected] logfile was found.</span>")
to_chat(src, "<span class='danger'>No [selected] logfile was found.</span>", confidential = TRUE)
return
src << browse(F,"window=investigate[selected];size=800x300")

+ 2
- 2
code/modules/admin/admin_ranks.dm View File

@@ -112,7 +112,7 @@ 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()
@@ -127,7 +127,7 @@ GLOBAL_PROTECT(protected_ranks)
//load our rank - > rights associations
/proc/load_admin_ranks(dbfail, no_update)
if(IsAdminAdvancedProcCall())
to_chat(usr, "<span class='admin prefix'>Admin Reload blocked: Advanced ProcCall detected.</span>")
to_chat(usr, "<span class='admin prefix'>Admin Reload blocked: Advanced ProcCall detected.</span>", confidential = TRUE)
return
GLOB.admin_ranks.Cut()
GLOB.protected_ranks.Cut()


+ 10
- 10
code/modules/admin/admin_verbs.dm View File

@@ -302,7 +302,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
remove_admin_verbs()
verbs += /client/proc/show_verbs

to_chat(src, "<span class='interface'>Almost all of your adminverbs have been hidden.</span>")
to_chat(src, "<span class='interface'>Almost all of your adminverbs have been hidden.</span>", confidential = TRUE)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Hide All Adminverbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return

@@ -313,7 +313,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
verbs -= /client/proc/show_verbs
add_admin_verbs()

to_chat(src, "<span class='interface'>All of your adminverbs are now visible.</span>")
to_chat(src, "<span class='interface'>All of your adminverbs are now visible.</span>", confidential = TRUE)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Adminverbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!


@@ -337,7 +337,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
ghost.reenter_corpse()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin Reenter") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
else if(isnewplayer(mob))
to_chat(src, "<font color='red'>Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.</font>")
to_chat(src, "<font color='red'>Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.</font>", confidential = TRUE)
return FALSE
else
//ghostize
@@ -356,10 +356,10 @@ GLOBAL_PROTECT(admin_verbs_hideable)
if(holder && mob)
if(mob.invisibility == INVISIBILITY_OBSERVER)
mob.invisibility = initial(mob.invisibility)
to_chat(mob, "<span class='boldannounce'>Invisimin off. Invisibility reset.</span>")
to_chat(mob, "<span class='boldannounce'>Invisimin off. Invisibility reset.</span>", confidential = TRUE)
else
mob.invisibility = INVISIBILITY_OBSERVER
to_chat(mob, "<span class='adminnotice'><b>Invisimin on. You are now as invisible as a ghost.</b></span>")
to_chat(mob, "<span class='adminnotice'><b>Invisimin on. You are now as invisible as a ghost.</b></span>", confidential = TRUE)

/client/proc/check_antagonists()
set name = "Check Antagonists"
@@ -517,7 +517,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
if (isnull(ex_power))
return
var/range = round((2 * ex_power)**GLOB.DYN_EX_SCALE)
to_chat(usr, "Estimated Explosive Range: (Devastation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])")
to_chat(usr, "Estimated Explosive Range: (Devastation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])", confidential = TRUE)

/client/proc/get_dynex_power()
set category = "Debug"
@@ -528,7 +528,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
if (isnull(ex_range))
return
var/power = (0.5 * ex_range)**(1/GLOB.DYN_EX_SCALE)
to_chat(usr, "Estimated Explosive Power: [power]")
to_chat(usr, "Estimated Explosive Power: [power]", confidential = TRUE)

/client/proc/set_dynex_scale()
set category = "Debug"
@@ -584,7 +584,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
set name = "Give Disease"
set desc = "Gives a Disease to a mob."
if(!istype(T))
to_chat(src, "<span class='notice'>You can only give a disease to a mob of type /mob/living.</span>")
to_chat(src, "<span class='notice'>You can only give a disease to a mob of type /mob/living.</span>", confidential = TRUE)
return
var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in sortList(SSdisease.diseases, /proc/cmp_typepaths_asc)
if(!D)
@@ -633,7 +633,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)

holder.deactivate()

to_chat(src, "<span class='interface'>You are now a normal player.</span>")
to_chat(src, "<span class='interface'>You are now a normal player.</span>", confidential = TRUE)
log_admin("[src] deadmined themself.")
message_admins("[src] deadmined themself.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Deadmin")
@@ -658,7 +658,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
if (!holder)
return //This can happen if an admin attempts to vv themself into somebody elses's deadmin datum by getting ref via brute force

to_chat(src, "<span class='interface'>You are now an admin.</span>")
to_chat(src, "<span class='interface'>You are now an admin.</span>", confidential = TRUE)
message_admins("[src] re-adminned themselves.")
log_admin("[src] re-adminned themselves.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Readmin")


+ 12
- 12
code/modules/admin/callproc/callproc.dm View File

@@ -20,7 +20,7 @@
return
target = value["value"]
if(!istype(target))
to_chat(usr, "<span class='danger'>Invalid target.</span>")
to_chat(usr, "<span class='danger'>Invalid target.</span>", confidential = TRUE)
return
if("No")
target = null
@@ -40,12 +40,12 @@

if(targetselected)
if(!hascall(target, procname))
to_chat(usr, "<span class='warning'>Error: callproc(): type [target.type] has no [proctype] named [procpath].</span>")
to_chat(usr, "<span class='warning'>Error: callproc(): type [target.type] has no [proctype] named [procpath].</span>", confidential = TRUE)
return
else
procpath = "/[proctype]/[procname]"
if(!text2path(procpath))
to_chat(usr, "<span class='warning'>Error: callproc(): [procpath] does not exist.</span>")
to_chat(usr, "<span class='warning'>Error: callproc(): [procpath] does not exist.</span>", confidential = TRUE)
return

var/list/lst = get_callproc_args()
@@ -54,7 +54,7 @@

if(targetselected)
if(!target)
to_chat(usr, "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>")
to_chat(usr, "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>", confidential = TRUE)
return
var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
log_admin(msg)
@@ -71,7 +71,7 @@
get_retval += returnval
. = get_callproc_returnval(returnval, procname)
if(.)
to_chat(usr, .)
to_chat(usr, ., confidential = TRUE)

GLOBAL_VAR(AdminProcCaller)
GLOBAL_PROTECT(AdminProcCaller)
@@ -89,11 +89,11 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/// Wrapper for proccalls where the datum is flagged as vareditted
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
if(target && procname == "Del")
to_chat(usr, "Calling Del() is not allowed")
to_chat(usr, "Calling Del() is not allowed", confidential = TRUE)
return

if(target != GLOBAL_PROC && !target.CanProcCall(procname))
to_chat(usr, "Proccall on [target.type]/proc/[procname] is disallowed!")
to_chat(usr, "Proccall on [target.type]/proc/[procname] is disallowed!", confidential = TRUE)
return
var/current_caller = GLOB.AdminProcCaller
var/ckey = usr ? usr.client.ckey : GLOB.AdminProcCaller
@@ -101,10 +101,10 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]")
if(current_caller && current_caller != ckey)
if(!GLOB.AdminProcCallSpamPrevention[ckey])
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>", confidential = TRUE)
GLOB.AdminProcCallSpamPrevention[ckey] = TRUE
UNTIL(!GLOB.AdminProcCaller)
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
to_chat(usr, "<span class='adminnotice'>Running your proc</span>", confidential = TRUE)
GLOB.AdminProcCallSpamPrevention -= ckey
else
UNTIL(!GLOB.AdminProcCaller)
@@ -145,14 +145,14 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!procname)
return
if(!hascall(A,procname))
to_chat(usr, "<font color='red'>Error: callproc_datum(): type [A.type] has no proc named [procname].</font>")
to_chat(usr, "<font color='red'>Error: callproc_datum(): type [A.type] has no proc named [procname].</font>", confidential = TRUE)
return
var/list/lst = get_callproc_args()
if(!lst)
return

if(!A || !IsValidSrc(A))
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>")
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>", confidential = TRUE)
return
log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
@@ -163,7 +163,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc
. = get_callproc_returnval(returnval,procname)
if(.)
to_chat(usr, .)
to_chat(usr, ., confidential = TRUE)

/client/proc/get_callproc_args()
var/argnum = input("Number of arguments","Number:",0) as num|null


+ 4
- 4
code/modules/admin/create_poll.dm View File

@@ -4,7 +4,7 @@
if(!check_rights(R_POLL))
return
if(!SSdbcore.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
var/polltype = input("Choose poll type.","Poll Type") as null|anything in list("Single Option","Text Reply","Rating","Multiple Choice", "Instant Runoff Voting")
var/choice_amount = 0
@@ -20,7 +20,7 @@
choice_amount = input("How many choices should be allowed?","Select choice amount") as num|null
switch(choice_amount)
if(0)
to_chat(src, "Multiple choice poll must have at least one choice allowed.")
to_chat(src, "Multiple choice poll must have at least one choice allowed.", confidential = TRUE)
return
if(1)
polltype = POLLTYPE_OPTION
@@ -42,7 +42,7 @@
if(query_validate_time.NextRow())
var/checktime = text2num(query_validate_time.item[1])
if(!checktime)
to_chat(src, "Datetime entered is improperly formatted or not later than current server time.")
to_chat(src, "Datetime entered is improperly formatted or not later than current server time.", confidential = TRUE)
qdel(query_validate_time)
return
endtime = query_validate_time.item[1]
@@ -100,7 +100,7 @@
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")
to_chat(src, "Maximum rating value can't be less than or equal to minimum rating value", confidential = TRUE)
continue
else if(maxval == null)
return


+ 6
- 6
code/modules/admin/fun_balloon.dm View File

@@ -58,7 +58,7 @@
var/mob/dead/observer/C = pick_n_take(candidates)
var/mob/living/body = pick_n_take(bodies)

to_chat(body, "<span class='warning'>Your mob has been taken over by a ghost!</span>")
to_chat(body, "<span class='warning'>Your mob has been taken over by a ghost!</span>", confidential = TRUE)
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(body)])")
body.ghostize(0)
body.key = C.key
@@ -83,7 +83,7 @@
var/turf/T = find_safe_turf()
new /obj/effect/temp_visual/gravpush(get_turf(M))
M.forceMove(T)
to_chat(M, "<span class='notice'>Pop!</span>")
to_chat(M, "<span class='notice'>Pop!</span>", confidential = TRUE)

/obj/effect/station_crash
name = "station crash"
@@ -121,16 +121,16 @@

var/mob/living/L = AM
if(L.pulling && istype(L.pulling, /obj/item/bodypart/head))
to_chat(L, "<span class='notice'>Your offering is accepted. You may pass.</span>")
to_chat(L, "<span class='notice'>Your offering is accepted. You may pass.</span>", confidential = TRUE)
qdel(L.pulling)
var/turf/LA = get_turf(pick(warp_points))
L.forceMove(LA)
L.hallucination = 0
to_chat(L, "<span class='reallybig redtext'>The battle is won. Your bloodlust subsides.</span>")
to_chat(L, "<span class='reallybig redtext'>The battle is won. Your bloodlust subsides.</span>", confidential = TRUE)
for(var/obj/item/chainsaw/doomslayer/chainsaw in L)
qdel(chainsaw)
else
to_chat(L, "<span class='warning'>You are not yet worthy of passing. Drag a severed head to the barrier to be allowed entry to the hall of champions.</span>")
to_chat(L, "<span class='warning'>You are not yet worthy of passing. Drag a severed head to the barrier to be allowed entry to the hall of champions.</span>", confidential = TRUE)

/obj/effect/landmark/shuttle_arena_safe
name = "hall of champions"
@@ -157,7 +157,7 @@
var/obj/effect/landmark/LA = pick(warp_points)
var/mob/living/M = AM
M.forceMove(get_turf(LA))
to_chat(M, "<span class='reallybig redtext'>You're trapped in a deadly arena! To escape, you'll need to drag a severed head to the escape portals.</span>")
to_chat(M, "<span class='reallybig redtext'>You're trapped in a deadly arena! To escape, you'll need to drag a severed head to the escape portals.</span>", confidential = TRUE)
INVOKE_ASYNC(src, .proc/do_bloodbath, M)

/obj/effect/forcefield/arena_shuttle_entrance/proc/do_bloodbath(mob/living/L)


+ 2
- 2
code/modules/admin/holder2.dm View File

@@ -156,7 +156,7 @@ generally it would be used like so:
/proc/admin_proc()
if(!check_rights(R_ADMIN))
return
to_chat(world, "you have enough rights!")
to_chat(world, "you have enough rights!", confidential = TRUE)
NOTE: it checks usr! not src! So if you're checking somebody's rank in a proc which they did not call
you will have to do something like if(client.rights & R_ADMIN) yourself.
@@ -167,7 +167,7 @@ you will have to do something like if(client.rights & R_ADMIN) yourself.
return 1
else
if(show_msg)
to_chat(usr, "<font color='red'>Error: You do not have sufficient rights to do that. You require one of the following flags:[rights2text(rights_required," ")].</font>")
to_chat(usr, "<font color='red'>Error: You do not have sufficient rights to do that. You require one of the following flags:[rights2text(rights_required," ")].</font>", confidential = TRUE)
return 0
//probably a bit iffy - will hopefully figure out a better solution


+ 4
- 4
code/modules/admin/outfits.dm View File

@@ -28,7 +28,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
/datum/admins/proc/delete_outfit(mob/admin,datum/outfit/O)
GLOB.custom_outfits -= O
qdel(O)
to_chat(admin,"<span class='notice'>Outfit deleted.</span>")
to_chat(admin,"<span class='notice'>Outfit deleted.</span>", confidential = TRUE)
outfit_manager(admin)

/datum/admins/proc/load_outfit(mob/admin)
@@ -38,15 +38,15 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/filedata = file2text(outfit_file)
var/json = json_decode(filedata)
if(!json)
to_chat(admin,"<span class='warning'>JSON decode error.</span>")
to_chat(admin,"<span class='warning'>JSON decode error.</span>", confidential = TRUE)
return
var/otype = text2path(json["outfit_type"])
if(!ispath(otype,/datum/outfit))
to_chat(admin,"<span class='warning'>Malformed/Outdated file.</span>")
to_chat(admin,"<span class='warning'>Malformed/Outdated file.</span>", confidential = TRUE)
return
var/datum/outfit/O = new otype
if(!O.load_from(json))
to_chat(admin,"<span class='warning'>Malformed/Outdated file.</span>")
to_chat(admin,"<span class='warning'>Malformed/Outdated file.</span>", confidential = TRUE)
return
GLOB.custom_outfits += O
outfit_manager(admin)


+ 13
- 13
code/modules/admin/permissionedit.dm View File

@@ -130,7 +130,7 @@
log_admin("[key_name(usr)] attempted to edit admin permissions without sufficient rights.")
return
if(IsAdminAdvancedProcCall())
to_chat(usr, "<span class='admin prefix'>Admin Edit blocked: Advanced ProcCall detected.</span>")
to_chat(usr, "<span class='admin prefix'>Admin Edit blocked: Advanced ProcCall detected.</span>", confidential = TRUE)
return
var/datum/asset/permissions_assets = get_asset_datum(/datum/asset/simple/permissions)
permissions_assets.send(src)
@@ -145,19 +145,19 @@
skip = TRUE
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_admins) && task == "rank")
if(admin_ckey in GLOB.protected_admins)
to_chat(usr, "<span class='admin prefix'>Editing the rank of this admin is blocked by server configuration.</span>")
to_chat(usr, "<span class='admin prefix'>Editing the rank of this admin is blocked by server configuration.</span>", confidential = TRUE)
return
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_ranks) && task == "permissions")
if(D.rank in GLOB.protected_ranks)
to_chat(usr, "<span class='admin prefix'>Editing the flags of this rank is blocked by server configuration.</span>")
to_chat(usr, "<span class='admin prefix'>Editing the flags of this rank is blocked by server configuration.</span>", confidential = TRUE)
return
if(CONFIG_GET(flag/load_legacy_ranks_only) && (task == "add" || task == "rank" || task == "permissions"))
to_chat(usr, "<span class='admin prefix'>Database rank loading is disabled, only temporary changes can be made to a rank's permissions and permanently creating a new rank is blocked.</span>")
to_chat(usr, "<span class='admin prefix'>Database rank loading is disabled, only temporary changes can be made to a rank's permissions and permanently creating a new rank is blocked.</span>", confidential = TRUE)
legacy_only = TRUE
if(check_rights(R_DBRANKS, FALSE))
if(!skip)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Unable to connect to database, changes are temporary only.</span>")
to_chat(usr, "<span class='danger'>Unable to connect to database, changes are temporary only.</span>", confidential = TRUE)
use_db = FALSE
else
use_db = alert("Permanent changes are saved to the database for future rounds, temporary changes will affect only the current round", "Permanent or Temporary?", "Permanent", "Temporary", "Cancel")
@@ -209,7 +209,7 @@
if(!.)
return FALSE
if(!admin_ckey && (. in GLOB.admin_datums+GLOB.deadmins))
to_chat(usr, "<span class='danger'>[admin_key] is already an admin.</span>")
to_chat(usr, "<span class='danger'>[admin_key] is already an admin.</span>", confidential = TRUE)
return FALSE
if(use_db)
. = sanitizeSQL(.)
@@ -220,7 +220,7 @@
return FALSE
if(query_admin_in_db.NextRow())
qdel(query_admin_in_db)
to_chat(usr, "<span class='danger'>[admin_key] already listed in admin database. Check the Management tab if they don't appear in the list of admins.</span>")
to_chat(usr, "<span class='danger'>[admin_key] already listed in admin database. Check the Management tab if they don't appear in the list of admins.</span>", confidential = TRUE)
return FALSE
qdel(query_admin_in_db)
var/datum/DBQuery/query_add_admin = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin")] (ckey, `rank`) VALUES ('[.]', 'NEW ADMIN')")
@@ -272,7 +272,7 @@
D.deactivate() //after logs so the deadmined admin can see the message.

/datum/admins/proc/auto_deadmin()
to_chat(owner, "<span class='interface'>You are now a normal player.</span>")
to_chat(owner, "<span class='interface'>You are now a normal player.</span>", confidential = TRUE)
var/old_owner = owner
deactivate()
message_admins("[old_owner] deadmined via auto-deadmin config.")
@@ -427,13 +427,13 @@
return
for(var/datum/admin_rank/R in GLOB.admin_ranks)
if(R.name == admin_rank && (!(R.rights & usr.client.holder.rank.can_edit_rights) == R.rights))
to_chat(usr, "<span class='admin prefix'>You don't have edit rights to all the rights this rank has, rank deletion not permitted.</span>")
to_chat(usr, "<span class='admin prefix'>You don't have edit rights to all the rights this rank has, rank deletion not permitted.</span>", confidential = TRUE)
return
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_ranks) && (admin_rank in GLOB.protected_ranks))
to_chat(usr, "<span class='admin prefix'>Deletion of protected ranks is not permitted, it must be removed from admin_ranks.txt.</span>")
to_chat(usr, "<span class='admin prefix'>Deletion of protected ranks is not permitted, it must be removed from admin_ranks.txt.</span>", confidential = TRUE)
return
if(CONFIG_GET(flag/load_legacy_ranks_only))
to_chat(usr, "<span class='admin prefix'>Rank deletion not permitted while database rank loading is disabled.</span>")
to_chat(usr, "<span class='admin prefix'>Rank deletion not permitted while database rank loading is disabled.</span>", confidential = TRUE)
return
admin_rank = sanitizeSQL(admin_rank)
var/datum/DBQuery/query_admins_with_rank = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("admin")] WHERE `rank` = '[admin_rank]'")
@@ -442,7 +442,7 @@
return
if(query_admins_with_rank.NextRow())
qdel(query_admins_with_rank)
to_chat(usr, "<span class='danger'>Error: Rank deletion attempted while rank still used; Tell a coder, this shouldn't happen.</span>")
to_chat(usr, "<span class='danger'>Error: Rank deletion attempted while rank still used; Tell a coder, this shouldn't happen.</span>", confidential = TRUE)
return
qdel(query_admins_with_rank)
if(alert("Are you sure you want to remove [admin_rank]?","Confirm Removal","Do it","Cancel") == "Do it")
@@ -471,4 +471,4 @@
qdel(query_sync_lastadminrank)
return
qdel(query_sync_lastadminrank)
to_chat(usr, "<span class='admin'>Sync of [admin_key] successful.</span>")
to_chat(usr, "<span class='admin'>Sync of [admin_key] successful.</span>", confidential = TRUE)

+ 6
- 6
code/modules/admin/secrets.dm View File

@@ -237,7 +237,7 @@
message_admins("[key_name_admin(usr)] [new_perma ? "stopped" : "started"] the arrivals shuttle")
log_admin("[key_name(usr)] [new_perma ? "stopped" : "started"] the arrivals shuttle")
else
to_chat(usr, "<span class='admin'>There is no arrivals shuttle.</span>")
to_chat(usr, "<span class='admin'>There is no arrivals shuttle.</span>", confidential = TRUE)
if("showailaws")
if(!check_rights(R_ADMIN))
return
@@ -420,7 +420,7 @@
if(droptype == "Yes")
ADD_TRAIT(I, TRAIT_NODROP, ADMIN_TRAIT)
else
to_chat(H, "<span class='warning'>You're not kawaii enough for this!</span>")
to_chat(H, "<span class='warning'>You're not kawaii enough for this!</span>", confidential = TRUE)

if("whiteout")
if(!check_rights(R_FUN))
@@ -455,7 +455,7 @@
return
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Mass Braindamage"))
for(var/mob/living/carbon/human/H in GLOB.player_list)
to_chat(H, "<span class='boldannounce'>You suddenly feel stupid.</span>")
to_chat(H, "<span class='boldannounce'>You suddenly feel stupid.</span>", confidential = TRUE)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 60, 80)
message_admins("[key_name_admin(usr)] made everybody retarded")

@@ -642,7 +642,7 @@
var/list/prefs = settings["mainsettings"]

if (prefs["amount"]["value"] < 1 || prefs["portalnum"]["value"] < 1)
to_chat(usr, "<span class='warning'>Number of portals and mobs to spawn must be at least 1.</span>")
to_chat(usr, "<span class='warning'>Number of portals and mobs to spawn must be at least 1.</span>", confidential = TRUE)
return

var/mob/pathToSpawn = prefs["typepath"]["value"]
@@ -650,7 +650,7 @@
pathToSpawn = text2path(pathToSpawn)

if (!ispath(pathToSpawn))
to_chat(usr, "<span class='notice'>Invalid path [pathToSpawn].</span>")
to_chat(usr, "<span class='notice'>Invalid path [pathToSpawn].</span>", confidential = TRUE)
return

var/list/candidates = list()
@@ -699,7 +699,7 @@
if (usr)
log_admin("[key_name(usr)] used secret [item]")
if (ok)
to_chat(world, text("<B>A secret has been activated by []!</B>", usr.key))
to_chat(world, text("<B>A secret has been activated by []!</B>", usr.key), confidential = TRUE)

/proc/portalAnnounce(announcement, playlightning)
set waitfor = 0


+ 7
- 7
code/modules/admin/sound_emitter.dm View File

@@ -54,7 +54,7 @@
/obj/effect/sound_emitter/AltClick(mob/user)
if(check_rights_for(user.client, R_SOUND))
activate(user)
to_chat(user, "<span class='notice'>Sound emitter activated.</span>")
to_chat(user, "<span class='notice'>Sound emitter activated.</span>", confidential = TRUE)

/obj/effect/sound_emitter/proc/edit_emitter(mob/user)
var/dat = ""
@@ -82,20 +82,20 @@
if(!new_label)
return
maptext = new_label
to_chat(user, "<span class='notice'>Label set to [maptext].</span>")
to_chat(user, "<span class='notice'>Label set to [maptext].</span>", confidential = TRUE)
if(href_list["edit_sound_file"])
var/new_file = input(user, "Choose a sound file.", "Sound Emitter") as null|sound
if(!new_file)
return
sound_file = new_file
to_chat(user, "<span class='notice'>New sound file set to [sound_file].</span>")
to_chat(user, "<span class='notice'>New sound file set to [sound_file].</span>", confidential = TRUE)
if(href_list["edit_volume"])
var/new_volume = input(user, "Choose a volume.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_volume))
return
new_volume = clamp(new_volume, 0, 100)
sound_volume = new_volume
to_chat(user, "<span class='notice'>Volume set to [sound_volume]%.</span>")
to_chat(user, "<span class='notice'>Volume set to [sound_volume]%.</span>", confidential = TRUE)
if(href_list["edit_mode"])
var/new_mode
var/mode_list = list("Local (normal sound)" = SOUND_EMITTER_LOCAL, "Direct (not affected by environment/location)" = SOUND_EMITTER_DIRECT)
@@ -103,7 +103,7 @@
if(!new_mode)
return
motus_operandi = mode_list[new_mode]
to_chat(user, "<span class='notice'>Mode set to [motus_operandi].</span>")
to_chat(user, "<span class='notice'>Mode set to [motus_operandi].</span>", confidential = TRUE)
if(href_list["edit_range"])
var/new_range
var/range_list = list("Radius (all mobs within a radius)" = SOUND_EMITTER_RADIUS, "Z-Level (all mobs on the same z)" = SOUND_EMITTER_ZLEVEL, "Global (all players)" = SOUND_EMITTER_GLOBAL)
@@ -111,14 +111,14 @@
if(!new_range)
return
emitter_range = range_list[new_range]
to_chat(user, "<span class='notice'>Range set to [emitter_range].</span>")
to_chat(user, "<span class='notice'>Range set to [emitter_range].</span>", confidential = TRUE)
if(href_list["edit_radius"])
var/new_radius = input(user, "Choose a radius.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_radius))
return
new_radius = clamp(new_radius, 0, 127)
play_radius = new_radius
to_chat(user, "<span class='notice'>Audible radius set to [play_radius].</span>")
to_chat(user, "<span class='notice'>Audible radius set to [play_radius].</span>", confidential = TRUE)
if(href_list["play"])
activate(user)
edit_emitter(user) //Refresh the UI to see our changes


+ 15
- 15
code/modules/admin/sql_ban_system.dm View File

@@ -282,7 +282,7 @@
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
var/list/error_state = list()
var/player_key
@@ -388,7 +388,7 @@
else
error_state += "No ban type was selected."
if(error_state.len)
to_chat(usr, "<span class='danger'>Ban not [edit_id ? "edited" : "created"] because the following errors were present:\n[error_state.Join("\n")]</span>")
to_chat(usr, "<span class='danger'>Ban not [edit_id ? "edited" : "created"] because the following errors were present:\n[error_state.Join("\n")]</span>", confidential = TRUE)
return
if(edit_id)
edit_ban(edit_id, player_key, ip_check, player_ip, cid_check, player_cid, use_last_connection, applies_to_admins, duration, interval, reason, mirror_edit, old_key, old_ip, old_cid, old_applies, page, admin_key, changes)
@@ -399,7 +399,7 @@
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
var/player_ckey = sanitizeSQL(ckey(player_key))
player_ip = sanitizeSQL(player_ip)
@@ -438,7 +438,7 @@
if(R_EVERYTHING && !(R_EVERYTHING & rank.can_edit_rights)) //edit rights are a more effective way to check hierarchical rank since many non-headmins have R_PERMISSIONS now
max_adminbans = MAX_ADMINBANS_PER_HEADMIN
if(adminban_count >= max_adminbans)
to_chat(usr, "<span class='danger'>You've already logged [max_adminbans] admin ban(s) or more. Do not abuse this function!</span>")
to_chat(usr, "<span class='danger'>You've already logged [max_adminbans] admin ban(s) or more. Do not abuse this function!</span>", confidential = TRUE)
qdel(query_check_adminban_count)
return
qdel(query_check_adminban_count)
@@ -499,7 +499,7 @@
var/is_admin = FALSE
if(C)
build_ban_cache(C)
to_chat(C, "<span class='boldannounce'>You have been [applies_to_admins ? "admin " : ""]banned by [usr.client.key] from [roles_to_ban[1] == "Server" ? "the server" : " Roles: [roles_to_ban.Join(", ")]"].\nReason: [reason]</span><br><span class='danger'>This ban is [isnull(duration) ? "permanent." : "temporary, it will be removed in [time_message]."] The round ID is [GLOB.round_id].</span><br><span class='danger'>To appeal this ban go to [appeal_url]</span>")
to_chat(C, "<span class='boldannounce'>You have been [applies_to_admins ? "admin " : ""]banned by [usr.client.key] from [roles_to_ban[1] == "Server" ? "the server" : " Roles: [roles_to_ban.Join(", ")]"].\nReason: [reason]</span><br><span class='danger'>This ban is [isnull(duration) ? "permanent." : "temporary, it will be removed in [time_message]."] The round ID is [GLOB.round_id].</span><br><span class='danger'>To appeal this ban go to [appeal_url]</span>", confidential = TRUE)
if(GLOB.admin_datums[C.ckey] || GLOB.deadmins[C.ckey])
is_admin = TRUE
if(roles_to_ban[1] == "Server" && (!is_admin || (is_admin && applies_to_admins)))
@@ -509,7 +509,7 @@
for(var/client/i in GLOB.clients - C)
if(i.address == player_ip || i.computer_id == player_cid)
build_ban_cache(i)
to_chat(i, "<span class='boldannounce'>You have been [applies_to_admins ? "admin " : ""]banned by [usr.client.key] from [roles_to_ban[1] == "Server" ? "the server" : " Roles: [roles_to_ban.Join(", ")]"].\nReason: [reason]</span><br><span class='danger'>This ban is [isnull(duration) ? "permanent." : "temporary, it will be removed in [time_message]."] The round ID is [GLOB.round_id].</span><br><span class='danger'>To appeal this ban go to [appeal_url]</span>")
to_chat(i, "<span class='boldannounce'>You have been [applies_to_admins ? "admin " : ""]banned by [usr.client.key] from [roles_to_ban[1] == "Server" ? "the server" : " Roles: [roles_to_ban.Join(", ")]"].\nReason: [reason]</span><br><span class='danger'>This ban is [isnull(duration) ? "permanent." : "temporary, it will be removed in [time_message]."] The round ID is [GLOB.round_id].</span><br><span class='danger'>To appeal this ban go to [appeal_url]</span>", confidential = TRUE)
if(GLOB.admin_datums[i.ckey] || GLOB.deadmins[i.ckey])
is_admin = TRUE
if(roles_to_ban[1] == "Server" && (!is_admin || (is_admin && applies_to_admins)))
@@ -519,7 +519,7 @@
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
var/datum/browser/unban_panel = new(usr, "unbanpanel", "Unbanning Panel", 850, 600)
unban_panel.add_stylesheet("unbanpanelcss", 'html/admin/unbanpanel.css')
@@ -614,7 +614,7 @@
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
var/target = ban_target_string(player_key, player_ip, player_cid)
if(alert(usr, "Please confirm unban of [target] from [role].", "Unban confirmation", "Yes", "No") == "No")
@@ -635,18 +635,18 @@
var/client/C = GLOB.directory[player_key]
if(C)
build_ban_cache(C)
to_chat(C, "<span class='boldannounce'>[usr.client.key] has removed a ban from [role] for your key.</span>")
to_chat(C, "<span class='boldannounce'>[usr.client.key] has removed a ban from [role] for your key.</span>", confidential = TRUE)
for(var/client/i in GLOB.clients - C)
if(i.address == player_ip || i.computer_id == player_cid)
build_ban_cache(i)
to_chat(i, "<span class='boldannounce'>[usr.client.key] has removed a ban from [role] for your IP or CID.</span>")
to_chat(i, "<span class='boldannounce'>[usr.client.key] has removed a ban from [role] for your IP or CID.</span>", confidential = TRUE)
unban_panel(player_key, admin_key, player_ip, player_cid, page)

/datum/admins/proc/edit_ban(ban_id, player_key, ip_check, player_ip, cid_check, player_cid, use_last_connection, applies_to_admins, duration, interval, reason, mirror_edit, old_key, old_ip, old_cid, old_applies, admin_key, page, list/changes)
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
ban_id = sanitizeSQL(ban_id)
var/player_ckey = sanitizeSQL(ckey(player_key))
@@ -688,7 +688,7 @@
if(R_EVERYTHING && !(R_EVERYTHING & rank.can_edit_rights)) //edit rights are a more effective way to check hierarchical rank since many non-headmins have R_PERMISSIONS now
max_adminbans = MAX_ADMINBANS_PER_HEADMIN
if(adminban_count >= max_adminbans)
to_chat(usr, "<span class='danger'>You've already logged [max_adminbans] admin ban(s) or more. Do not abuse this function!</span>")
to_chat(usr, "<span class='danger'>You've already logged [max_adminbans] admin ban(s) or more. Do not abuse this function!</span>", confidential = TRUE)
qdel(query_check_adminban_count)
return
qdel(query_check_adminban_count)
@@ -730,18 +730,18 @@
var/client/C = GLOB.directory[old_key]
if(C)
build_ban_cache(C)
to_chat(C, "<span class='boldannounce'>[usr.client.key] has edited the [changes_keys_text] of a ban for your key.</span>")
to_chat(C, "<span class='boldannounce'>[usr.client.key] has edited the [changes_keys_text] of a ban for your key.</span>", confidential = TRUE)
for(var/client/i in GLOB.clients - C)
if(i.address == old_ip || i.computer_id == old_cid)
build_ban_cache(i)
to_chat(i, "<span class='boldannounce'>[usr.client.key] has edited the [changes_keys_text] of a ban for your IP or CID.</span>")
to_chat(i, "<span class='boldannounce'>[usr.client.key] has edited the [changes_keys_text] of a ban for your IP or CID.</span>", confidential = TRUE)
unban_panel(player_key, null, null, null, page)

/datum/admins/proc/ban_log(ban_id)
if(!check_rights(R_BAN))
return
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
ban_id = sanitizeSQL(ban_id)
var/datum/DBQuery/query_get_ban_edits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("ban")] WHERE id = '[ban_id]'")


+ 13
- 13
code/modules/admin/sql_message_system.dm View File

@@ -1,6 +1,6 @@
/proc/create_message(type, target_key, admin_ckey, text, timestamp, server, secret, logged = 1, browse, expiry, note_severity)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
if(!type)
return
@@ -67,7 +67,7 @@
if(query_validate_expire_time.NextRow())
var/checktime = text2num(query_validate_expire_time.item[1])
if(!checktime)
to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.")
to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.", confidential = TRUE)
qdel(query_validate_expire_time)
return
expiry = query_validate_expire_time.item[1]
@@ -96,7 +96,7 @@

/proc/delete_message(message_id, logged = 1, browse)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
message_id = text2num(message_id)
if(!message_id)
@@ -132,7 +132,7 @@

/proc/edit_message(message_id, browse)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
message_id = text2num(message_id)
if(!message_id)
@@ -171,7 +171,7 @@

/proc/edit_message_expiry(message_id, browse)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
message_id = text2num(message_id)
if(!message_id)
@@ -206,7 +206,7 @@
if(query_validate_expire_time_edit.NextRow())
var/checktime = text2num(query_validate_expire_time_edit.item[1])
if(!checktime)
to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.")
to_chat(usr, "Datetime entered is improperly formatted or not later than current server time.", confidential = TRUE)
qdel(query_validate_expire_time_edit)
qdel(query_find_edit_expiry_message)
return
@@ -229,7 +229,7 @@

/proc/edit_message_severity(message_id)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
message_id = text2num(message_id)
if(!message_id)
@@ -268,7 +268,7 @@

/proc/toggle_message_secrecy(message_id)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
message_id = text2num(message_id)
if(!message_id)
@@ -300,7 +300,7 @@

/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
var/list/output = list()
var/ruler = "<hr style='background:#000000; border:0; height:3px'>"
@@ -510,7 +510,7 @@

/proc/get_message_output(type, target_ckey)
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>", confidential = TRUE)
return
if(!type)
return
@@ -589,7 +589,7 @@
/*alternatively this proc can be run once to pass through every note and attempt to convert it before deleting the file, if done then AUTOCONVERT_NOTES should be turned off
this proc can take several minutes to execute fully if converting and cause DD to hang if converting a lot of notes; it's not advised to do so while a server is live
/proc/mass_convert_notes()
to_chat(world, "Beginning mass note conversion")
to_chat(world, "Beginning mass note conversion", confidential = TRUE)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile)
log_game("Error: Cannot access [NOTESFILE]")
@@ -597,7 +597,7 @@ this proc can take several minutes to execute fully if converting and cause DD t
notesfile.cd = "/"
for(var/ckey in notesfile.dir)
convert_notes_sql(ckey)
to_chat(world, "Deleting NOTESFILE")
to_chat(world, "Deleting NOTESFILE", confidential = TRUE)
fdel(NOTESFILE)
to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES")*/
to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES", confidential = TRUE)*/
#undef NOTESFILE

+ 23
- 23
code/modules/admin/stickyban.dm View File

@@ -21,7 +21,7 @@
ban["ckey"] = ckey

if (get_stickyban_from_ckey(ckey))
to_chat(usr, "<span class='adminnotice'>Error: Can not add a stickyban: User already has a current sticky ban</span>")
to_chat(usr, "<span class='adminnotice'>Error: Can not add a stickyban: User already has a current sticky ban</span>", confidential = TRUE)
return

if (data["reason"])
@@ -56,12 +56,12 @@

var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
if (alert("Are you sure you want to remove the sticky ban on [ckey]?","Are you sure","Yes","No") == "No")
return
if (!get_stickyban_from_ckey(ckey))
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return
world.SetConfig("ban",ckey, null)
SSstickyban.cache -= ckey
@@ -87,12 +87,12 @@
var/alt = ckey(data["alt"])
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return

var/key = LAZYACCESS(ban["keys"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>")
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>", confidential = TRUE)
return

if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them, Use \[E] to exempt them","Are you sure","Yes","No") == "No")
@@ -101,13 +101,13 @@
//we have to do this again incase something changes
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return

key = LAZYACCESS(ban["keys"], alt)

if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] link to [ckey]'s sticky ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: [alt] link to [ckey]'s sticky ban disappeared.</span>", confidential = TRUE)
return

LAZYREMOVE(ban["keys"], alt)
@@ -129,7 +129,7 @@
var/ckey = data["ckey"]
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return
var/oldreason = ban["message"]
var/reason = input(usr,"Reason","Reason","[ban["message"]]") as text|null
@@ -138,7 +138,7 @@
//we have to do this again incase something changed while we waited for input
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return
ban["message"] = "[reason]"

@@ -163,12 +163,12 @@
var/alt = ckey(data["alt"])
var/ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>")
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!</span>", confidential = TRUE)
return

var/key = LAZYACCESS(ban["keys"], alt)
if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>")
to_chat(usr, "<span class='adminnotice'>Error: [alt] is not linked to [ckey]'s sticky ban!</span>", confidential = TRUE)
return

if (alert("Are you sure you want to exempt [alt] from [ckey]'s sticky ban?","Are you sure","Yes","No") == "No")
@@ -177,13 +177,13 @@
//we have to do this again incase something changes
ban = get_stickyban_from_ckey(ckey)
if (!ban)
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: The ban disappeared.</span>", confidential = TRUE)
return

key = LAZYACCESS(ban["keys"], alt)

if (!key)
to_chat(usr, "<span class='adminnotice'>Error: [alt]'s link to [ckey]'s sticky ban disappeared.</span>")
to_chat(usr, "<span class='adminnotice'>Error: [alt]'s link to [ckey]'s sticky ban disappeared.</span>", confidential = TRUE)
return
LAZYREMOVE(ban["keys"], alt)
key["exempt"] = TRUE
@@ -210,12 +210,12 @@
var/alt = ckey(data["alt"])
var/ban = get_stickyban_from_ckey(ckey)