World.dm Refactor (#27268)

* Cleanup world/New

* Moves some things from OnReboot SS Shutdowns

* Move mode handling procs to ticker

* Moves delayed reboot to ticker
Cleans up round end sound setting
Splits round end animation between SStitle and SSticker

* Moves PR announcement to where it can use the define

* Clean this bit up

* Move out datacore Initialization

* Fix some stuff

* Fix this for

* Different PR

* Gives admins reboot options

* Make it smaller
This commit is contained in:
Cyberboss
2017-05-18 07:53:46 -04:00
committed by Jordie
parent 83e90cca22
commit ee404b2170
14 changed files with 151 additions and 125 deletions

View File

@@ -40,6 +40,7 @@
// Subsystem init_order, from highest priority to lowest priority
// The numbers just define the ordering, they are meaningless otherwise.
#define INIT_ORDER_SERVER_MAINT 16
#define INIT_ORDER_JOBS 15
#define INIT_ORDER_EVENTS 14
#define INIT_ORDER_TICKER 13

View File

@@ -8,7 +8,7 @@ GLOBAL_VAR_INIT(fileaccess_timer, 0)
GLOBAL_VAR_INIT(TAB, "    ")
GLOBAL_DATUM(data_core, /datum/datacore)
GLOBAL_DATUM_INIT(data_core, /datum/datacore, new)
GLOBAL_VAR_INIT(CELLRATE, 0.002) // multiplier for watts per tick <> cell storage (eg: .002 means if there is a load of 1000 watts, 20 units will be taken from a cell per second)
GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second)

View File

@@ -83,6 +83,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
sortTim(subsystems, /proc/cmp_subsystem_init)
reverseRange(subsystems)
for(var/datum/controller/subsystem/ss in subsystems)
testing("Shutdown [ss.name] subsystem")
ss.Shutdown()
// Returns 1 if we created a new mc, 0 if we couldn't due to a recent restart,

View File

@@ -54,6 +54,8 @@ SUBSYSTEM_DEF(blackbox)
return FALSE
/datum/controller/subsystem/blackbox/Shutdown()
set_val("ahelp_unresolved", GLOB.ahelp_tickets.active_tickets.len)
var/pda_msg_amt = 0
var/rc_msg_amt = 0

View File

@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(server_maint)
wait = 6
flags = SS_POST_FIRE_TIMING
priority = 10
init_order = INIT_ORDER_SERVER_MAINT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun
@@ -37,4 +38,11 @@ SUBSYSTEM_DEF(server_maint)
if (MC_TICK_CHECK) //one day, when ss13 has 1000 people per server, you guys are gonna be glad I added this tick check
return
/datum/controller/subsystem/server_maint/Shutdown()
kick_clients_in_lobby("<span class='boldannounce'>The round came to an end with you in the lobby.</span>", TRUE) //second parameter ensures only afk clients are kicked
for(var/thing in GLOB.clients)
var/client/C = thing
if(C && config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[config.server]")
#undef PING_BUFFER_TIME

View File

@@ -20,6 +20,7 @@ SUBSYSTEM_DEF(ticker)
var/login_music //music played in pregame lobby
var/round_end_sound //music/jingle played when the world reboots
var/round_end_sound_sent = TRUE //If all clients have loaded it
var/list/datum/mind/minds = list() //The characters in the game. Used for objective tracking.
@@ -61,6 +62,7 @@ SUBSYSTEM_DEF(ticker)
var/list/round_start_events
/datum/controller/subsystem/ticker/Initialize(timeofday)
load_mode()
var/list/music = world.file2list(ROUND_START_MUSIC_LIST, "\n")
login_music = pick(music)
@@ -616,9 +618,9 @@ SUBSYSTEM_DEF(ticker)
sleep(50)
if(mode.station_was_nuked)
world.Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke")
Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke")
else
world.Reboot("Round ended.", "end_proper", "proper completion")
Reboot("Round ended.", "end_proper", "proper completion")
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
var/m
@@ -779,3 +781,69 @@ SUBSYSTEM_DEF(ticker)
start_at = world.time + newtime
else
timeLeft = newtime
/datum/controller/subsystem/ticker/proc/load_mode()
var/mode = trim(file2text("data/mode.txt"))
if(mode)
GLOB.master_mode = mode
else
GLOB.master_mode = "extended"
log_game("Saved mode is '[GLOB.master_mode]'")
/datum/controller/subsystem/ticker/proc/save_mode(the_mode)
var/F = file("data/mode.txt")
fdel(F)
F << the_mode
/datum/controller/subsystem/ticker/proc/SetRoundEndSound(the_sound)
set waitfor = FALSE
round_end_sound_sent = FALSE
round_end_sound = fcopy_rsc(the_sound)
for(var/thing in GLOB.clients)
var/client/C = thing
if (!C)
continue
C.Export("##action=load_rsc", round_end_sound)
round_end_sound_sent = TRUE
/datum/controller/subsystem/ticker/proc/Reboot(reason, feedback_c, feedback_r, delay)
set waitfor = FALSE
if(usr && !check_rights(R_SERVER, TRUE))
return
if(!delay)
delay = config.round_end_countdown * 10
if(delay_end)
to_chat(world, "<span class='boldannounce'>An admin has delayed the round end.</span>")
return
to_chat(world, "<span class='boldannounce'>Rebooting World in [delay/10] [(delay >= 10 && delay < 20) ? "second" : "seconds"]. [reason]</span>")
var/start_wait = world.time
UNTIL(round_end_sound_sent && (world.time - start_wait) > (delay * 2)) //don't wait forever
sleep(delay - (world.time - start_wait))
if(delay_end)
to_chat(world, "<span class='boldannounce'>Reboot was cancelled by an admin.</span>")
return
SSblackbox.set_details("[feedback_c]","[feedback_r]")
log_game("<span class='boldannounce'>Rebooting World. [reason]</span>")
world.Reboot()
/datum/controller/subsystem/ticker/Shutdown()
if(!round_end_sound)
round_end_sound = pick(\
'sound/roundend/newroundsexy.ogg',
'sound/roundend/apcdestroyed.ogg',
'sound/roundend/bangindonk.ogg',
'sound/roundend/leavingtg.ogg',
'sound/roundend/its_only_game.ogg',
'sound/roundend/yeehaw.ogg',
'sound/roundend/disappointed.ogg'\
)
world << sound(round_end_sound)

View File

@@ -55,6 +55,12 @@ SUBSYSTEM_DEF(title)
var/F = file("data/previous_title.dat")
F << file_path
for(var/thing in GLOB.clients)
if(!thing)
continue
var/obj/screen/splash/S = new(thing, FALSE)
S.Fade(FALSE,FALSE)
/datum/controller/subsystem/title/Recover()
icon = SStitle.icon
splash_turf = SStitle.splash_turf

View File

@@ -118,7 +118,7 @@ SUBSYSTEM_DEF(vote)
restart = 1
if("gamemode")
if(GLOB.master_mode != .)
world.save_mode(.)
SSticker.save_mode(.)
if(SSticker.HasRoundStarted())
restart = 1
else
@@ -130,7 +130,7 @@ SUBSYSTEM_DEF(vote)
active_admins = 1
break
if(!active_admins)
world.Reboot("Restart vote successful.", "end_error", "restart vote")
SSticker.Reboot("Restart vote successful.", "end_error", "restart vote")
else
to_chat(world, "<span style='boldannounce'>Notice:Restart vote will not restart the server automatically because there are active admins on.</span>")
message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.")

View File

@@ -459,8 +459,7 @@
var/datum/game_mode/nuclear/NM = SSticker.mode
NM.nukes_left --
if(!SSticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is
spawn()
world.Reboot("Station destroyed by Nuclear Device.", "end_error", "nuke - unhandled ending")
SSticker.Reboot("Station destroyed by Nuclear Device.", "end_error", "nuke - unhandled ending")
/*

View File

@@ -421,13 +421,18 @@
set desc="Restarts the world immediately"
if (!usr.client.holder)
return
var/confirm = alert("Restart the game world?", "Restart", "Yes", "Cancel")
if(confirm == "Cancel")
return
if(confirm == "Yes")
SSticker.delay_end = 0
var/list/options = list("Regular Restart", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)")
var result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options
if(result)
SSblackbox.add_details("admin_verb","Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
world.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "end_error", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10)
switch(result)
if("Regular Restart")
SSticker.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "end_error", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10)
if("Hard Restart (No Delay, No Feeback Reason)")
world.Reboot()
if("Hardest Restart (No actions, just reboot)")
world.Reboot(fast_track = TRUE)
/datum/admins/proc/end_round()
set category = "Server"

View File

@@ -1206,7 +1206,7 @@
message_admins("<span class='adminnotice'>[key_name_admin(usr)] set the mode as [GLOB.master_mode].</span>")
to_chat(world, "<span class='adminnotice'><b>The mode is now: [GLOB.master_mode]</b></span>")
Game() // updates the main game menu
world.save_mode(GLOB.master_mode)
SSticker.save_mode(GLOB.master_mode)
.(href, list("c_mode"=1))
else if(href_list["f_secret2"])

View File

@@ -52,10 +52,7 @@
if(!check_rights(R_SOUNDS))
return
if(SSticker)
SSticker.round_end_sound = fcopy_rsc(S)
else
return
SSticker.SetRoundEndSound(S)
log_admin("[key_name(src)] set the round end sound to [S]")
message_admins("[key_name_admin(src)] set the round end sound to [S]")

View File

@@ -636,3 +636,7 @@ GLOBAL_LIST(external_rsc_urls)
CRASH("change_view called without argument.")
view = new_size
/client/proc/AnnouncePR(announcement)
if(prefs && prefs.chat_toggles & CHAT_PULLR)
to_chat(src, announcement)

View File

@@ -16,6 +16,32 @@
/world/New()
log_world("World loaded at [time_stamp()]")
SetupExternalRSC()
GLOB.config_error_log = file("data/logs/config_error.log") //temporary file used to record errors with loading config, moved to log directory once logging is set bl
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
config = new
SetRoundID()
SetupLogs()
GLOB.revdata.DownloadPRDetails()
load_motd()
load_admins()
load_menu()
if(config.usewhitelist)
load_whitelist()
LoadBans()
GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
Master.Initialize(10, FALSE)
/world/proc/SetupExternalRSC()
#if (PRELOAD_RSC == 0)
external_rsc_urls = world.file2list("config/external_rsc_urls.txt","\n")
var/i=1
@@ -25,10 +51,8 @@
else
external_rsc_urls.Cut(i,i+1)
#endif
GLOB.config_error_log = file("data/logs/config_error.log") //temporary file used to record errors with loading config, moved to log directory once logging is set bl
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
config = new
GLOB.log_directory = "data/logs/[time2text(world.realtime, "YYYY/MM/DD")]/round-"
/world/proc/SetRoundID()
if(config.sql_enabled)
if(SSdbcore.Connect())
log_world("Database connection established.")
@@ -38,10 +62,14 @@
query_feedback_max_id.Execute()
if(query_feedback_max_id.NextRow())
GLOB.round_id = query_feedback_max_id.item[1]
GLOB.log_directory += "[GLOB.round_id]"
else
log_world("Your server failed to establish a connection with the database.")
if(!GLOB.round_id)
/world/proc/SetupLogs()
GLOB.log_directory = "data/logs/[time2text(world.realtime, "YYYY/MM/DD")]/round-"
if(GLOB.round_id)
GLOB.log_directory += "[GLOB.round_id]"
else
GLOB.log_directory += "[replacetext(time_stamp(), ":", ".")]"
GLOB.world_game_log = file("[GLOB.log_directory]/game.log")
GLOB.world_attack_log = file("[GLOB.log_directory]/attack.log")
@@ -58,21 +86,6 @@
if(GLOB.round_id)
log_game("Round ID: [GLOB.round_id]")
GLOB.revdata.DownloadPRDetails()
load_mode()
load_motd()
load_admins()
load_menu()
if(config.usewhitelist)
load_whitelist()
LoadBans()
GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
GLOB.data_core = new /datum/datacore()
Master.Initialize(10, FALSE)
#define IRC_STATUS_THROTTLE 50
/world/Topic(T, addr, master, key)
if(config && config.log_world_topic)
@@ -198,99 +211,21 @@
if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
return
#define CHAT_PULLR 64 //defined in preferences.dm, but not available here at compilation time
var/final_composed = "<span class='announce'>PR: [announcement]</span>"
for(var/client/C in GLOB.clients)
if(C.prefs && (C.prefs.chat_toggles & CHAT_PULLR))
C << "<span class='announce'>PR: [announcement]</span>"
#undef CHAT_PULLR
C.AnnouncePR(final_composed)
#define WORLD_REBOOT(X) log_world("World rebooted at [time_stamp()]"); ..(X); return;
/world/Reboot(var/reason, var/feedback_c, var/feedback_r, var/time)
if (reason == 1) //special reboot, do none of the normal stuff
/world/Reboot(reason = 0, fast_track = FALSE)
if (reason || fast_track) //special reboot, do none of the normal stuff
if (usr)
log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools")
message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools")
to_chat(world, "<span class='boldannounce'>Rebooting World immediately due to host request</span>")
WORLD_REBOOT(1)
var/delay
if(time)
delay = time
else
delay = config.round_end_countdown * 10
if(SSticker.delay_end)
to_chat(world, "<span class='boldannounce'>An admin has delayed the round end.</span>")
return
to_chat(world, "<span class='boldannounce'>Rebooting World in [delay/10] [(delay >= 10 && delay < 20) ? "second" : "seconds"]. [reason]</span>")
var/round_end_sound_sent = FALSE
if(SSticker.round_end_sound)
round_end_sound_sent = TRUE
for(var/thing in GLOB.clients)
var/client/C = thing
if (!C)
continue
C.Export("##action=load_rsc", SSticker.round_end_sound)
sleep(delay)
if(SSticker.delay_end)
to_chat(world, "<span class='boldannounce'>Reboot was cancelled by an admin.</span>")
return
OnReboot(reason, feedback_c, feedback_r, round_end_sound_sent)
WORLD_REBOOT(0)
#undef WORLD_REBOOT
/world/proc/OnReboot(reason, feedback_c, feedback_r, round_end_sound_sent)
SSblackbox.set_details("[feedback_c]","[feedback_r]")
log_game("<span class='boldannounce'>Rebooting World. [reason]</span>")
SSblackbox.set_val("ahelp_unresolved", GLOB.ahelp_tickets.active_tickets.len)
Master.Shutdown() //run SS shutdowns
RoundEndAnimation(round_end_sound_sent)
kick_clients_in_lobby("<span class='boldannounce'>The round came to an end with you in the lobby.</span>", 1) //second parameter ensures only afk clients are kicked
to_chat(world, "<span class='boldannounce'>Rebooting world...</span>")
for(var/thing in GLOB.clients)
var/client/C = thing
if(C && config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[config.server]")
/world/proc/RoundEndAnimation(round_end_sound_sent)
set waitfor = FALSE
var/round_end_sound
if(SSticker.round_end_sound)
round_end_sound = SSticker.round_end_sound
if (!round_end_sound_sent)
for(var/thing in GLOB.clients)
var/client/C = thing
if (!C)
continue
C.Export("##action=load_rsc", round_end_sound)
else
round_end_sound = pick(\
'sound/roundend/newroundsexy.ogg',
'sound/roundend/apcdestroyed.ogg',
'sound/roundend/bangindonk.ogg',
'sound/roundend/leavingtg.ogg',
'sound/roundend/its_only_game.ogg',
'sound/roundend/yeehaw.ogg',
'sound/roundend/disappointed.ogg'\
)
for(var/thing in GLOB.clients)
var/obj/screen/splash/S = new(thing, FALSE)
S.Fade(FALSE,FALSE)
world << sound(round_end_sound)
/world/proc/load_mode()
var/mode = trim(file2text("data/mode.txt"))
if(mode)
GLOB.master_mode = mode
else
GLOB.master_mode = "extended"
log_game("Saved mode is '[GLOB.master_mode]'")
/world/proc/save_mode(the_mode)
var/F = file("data/mode.txt")
fdel(F)
F << the_mode
to_chat(world, "<span class='boldannounce'>Rebooting world...</span>")
Master.Shutdown() //run SS shutdowns
log_world("World rebooted at [time_stamp()]");
..()
/world/proc/load_motd()
GLOB.join_motd = file2text("config/motd.txt") + "<br>" + GLOB.revdata.GetTestMergeInfo()