world mob = /mob/new_player turf = /turf/space area = /area view = "15x15" // /world/proc/load_mode() var/text = file2text("data/mode.txt") if (text) var/list/lines = splittext(text, "\n") if (lines[1]) master_mode = lines[1] diary << "Saved mode is '[master_mode]'" /world/proc/save_mode(var/the_mode) var/F = file("data/mode.txt") fdel(F) F << the_mode /world/proc/load_intra_round_value(var/field) //Currently for solarium effects, could also be expanded to that pickle jar idea. var/path = "data/intra_round.sav" if (!fexists(path)) return null var/savefile/F = new /savefile(path, -1) F["[field]"] >> . /world/proc/save_intra_round_value(var/field, var/value) if (!field || isnull(value)) return -1 var/savefile/F = new /savefile("data/intra_round.sav", -1) F.Lock(-1) F["[field]"] << value return 0 /world/proc/load_motd() join_motd = file2text("config/motd.txt") /world/proc/load_rules() rules = file2text("config/rules.html") if (!rules) rules = "RulesThere are no rules! Go nuts!" /world/proc/load_admins() var/text = file2text("config/admins.txt") if (!text) diary << "Failed to load config/admins.txt\n" else var/list/lines = splittext(text, "\n") for(var/line in lines) if (!line) continue if (copytext(line, 1, 2) == ";") continue var/pos = findtext(line, " - ", 1, null) if (pos) var/m_key = copytext(line, 1, pos) var/a_lev = copytext(line, pos + 3, length(line) + 1) admins[m_key] = a_lev diary << ("ADMIN: [m_key] = [a_lev]") // dsingh for faster create panel loads /world/proc/precache_create_txt() if (!create_mob_html) var/mobjs = null mobjs = jointext(typesof(/mob), ";") create_mob_html = grabResource("html/admin/create_object.html") create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"") if (!create_object_html) var/objectjs = null objectjs = jointext(typesof(/obj), ";") create_object_html = grabResource("html/admin/create_object.html") create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"") if (!create_turf_html) var/turfjs = null turfjs = jointext(typesof(/turf), ";") create_turf_html = grabResource("html/admin/create_object.html") create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"") // drsingh for faster ban panel loads //Wire note: this has been gutted to only do stuff for jobbans until I get round to converting that system /world/proc/precache_unban_txt() building_jobbans = 1 global_jobban_cache_built = world.timeofday var/buf = "" jobban_count = 0 for(var/t in jobban_keylist) if (t) jobban_count++ buf += text("[t];") global_jobban_cache = buf global_jobban_cache_rev = 1 building_jobbans = 0 /world/proc/load_testers() var/text = file2text("config/testers.txt") if (!text) diary << "Failed to load config/testers.txt\n" else var/list/lines = splittext(text, "\n") for(var/line in lines) if (!line) continue if (copytext(line, 1, 2) == ";") continue var/pos = findtext(line, " - ", 1, null) if (pos) var/m_key = copytext(line, 1, pos) var/a_lev = copytext(line, pos + 3, length(line) + 1) admins[m_key] = a_lev var/f_color_selector_handler/F_Color_Selector /proc/buildMaterialCache() //material_cache var/materialList = typesof(/datum/material) - /datum/material for(var/mat in materialList) var/datum/material/M = new mat() material_cache.Add(M.mat_id) material_cache[M.mat_id] = M return /proc/connectDB() set background = 1 /* Old remote-mysql connection stuff if(config.sql_enabled) dbcon = new() var/dbi = "dbi:mysql:[config.sql_database]:[config.sql_hostname]:[config.sql_port]" dbcon.Connect(dbi, "[config.sql_username]", "[config.sql_password]") if (!dbcon.IsConnected()) logTheThing("admin", null, null, "Failed to connect to central database: [dbcon.ErrorMsg()]") logTheThing("diary", null, null, "Failed to connect to central database: [dbcon.ErrorMsg()]", "admin") else logTheThing("admin", null, null, "Connected to central database") logTheThing("diary", null, null, "Connected to central database", "admin") */ //Called BEFORE the map loads. Useful for objects that require certain things be set during init /datum/preMapLoad New() config = new /datum/configuration() config.load("config/config.txt") if (config.server_specific_configs && world.port > 0) var/specific_config = "config/config-[world.port].txt" if (fexists(specific_config)) config.load(specific_config) // apply some settings from config.. abandon_allowed = config.respawn cdn = config.cdn disableResourceCache = config.disableResourceCache /world/New() tick_lag = 0.5 // loop_checks = 0 diary = file("data/logs/[time2text(world.realtime, "YYYY/MM-Month/DD-Day")].log") diary << "" diary << "" diary << "Starting up. [time2text(world.timeofday, "hh:mm.ss")]" diary << "---------------------" diary << "" changelog = new /datum/changelog() admin_changelog = new /datum/admin_changelog() if(!delete_queue) delete_queue = new /datum/dynamicQueue(100) initLimiter() F_Color_Selector = new() buildMaterialCache() create_named_colors() #ifdef DATALOGGER game_stats = new #endif radio_controller = new /datum/controller/radio() sun = new /datum/sun() vote = new /datum/vote() data_core = new /obj/datacore() init_vox() if (load_intra_round_value("solarium_complete") == 1) derelict_mode = 1 was_eaten = world.load_intra_round_value("somebody_ate_the_fucking_thing") save_intra_round_value("solarium_complete", 0) save_intra_round_value("somebody_ate_the_fucking_thing", 0) // Must go after data_core get_all_functional_reagent_ids() wagesystem = new /datum/wage_system() shippingmarket = new /datum/shipping_market() hydro_controls = new /datum/hydroponics_controller() job_controls = new /datum/job_controller() manuf_controls = new /datum/manufacturing_controller() random_events = new /datum/event_controller() disease_controls = new /datum/disease_controller() mechanic_controls = new /datum/mechanic_controller() artifact_controls = new /datum/artifact_controller() mining_controls = new /datum/mining_controller() actions = new/datum/action_controller() explosions = new/datum/explosion_controller() if (config.env == "dev") //WIRE TODO: Only do this (fallback to local files) if the coder testing has no internet recursiveFileLoader("browserassets/") if (config) if (config.server_name != null && config.server_region != null) config.server_name += " [config.server_region]" if (config.server_name != null && config.server_suffix && world.port > 0) config.server_name += " [(world.port % 1000) / 100]" jobban_loadbanfile() jobban_updatelegacybans() oocban_loadbanfile() oocban_updatelegacybans() precache_unban_txt() //Wire: left in for now because jobbans still use the shitty system precache_create_txt() src.load_mode() src.load_motd() src.load_rules() src.load_admins() //create_random_station() //--Disabled because it's making initial geometry stuff take forever. Feel free to re-enable it if it's just throwing off the time count and not actually adding workload. makepowernets() materialsResearch = new() materialsResearch.setup() tele_man = new() tele_man.setup() for(var/A in (typesof(/datum/material_recipe) - /datum/material_recipe)) //Caching material recipes. var/datum/material_recipe/R = new A() materialRecipes.Add(R) for(var/A in (typesof(/datum/achievementReward) - /datum/achievementReward)) //Caching reward datums. var/datum/achievementReward/R = new A() rewardDB.Add(R.type) rewardDB[R.type] = R for(var/A in (typesof(/obj/trait) - /obj/trait)) //Creating trait objects. I hate this. var/obj/trait/T = new A( ) traitList.Add(T.id) traitList[T.id] = T var/list/datum/bioEffect/tempBioList = typesof(/datum/bioEffect) - /datum/bioEffect for(var/effect in tempBioList) var/datum/bioEffect/E = new effect(1) bioEffectList[E.id] = E //Caching instances for easy access to rarity and such. BECAUSE THERES NO PROPER CONSTANTS IN BYOND. E.dnaBlocks.GenerateBlocks() //Generate global sequence for this effect. // Set this stupid shit up here because byond's object tree output can't // cope with a list initializer that contains "[constant]" keys headset_channel_lookup = list("[R_FREQ_RESEARCH]"="Research","[R_FREQ_MEDICAL]"="Medical","[R_FREQ_ENGINEERING]"="Engineering", "[R_FREQ_COMMAND]"="Command","[R_FREQ_SECURITY]"="Security","[R_FREQ_CIVILIAN]"="Civilian") //screenOverlayLibrary ov1 var/overlayList = typesof(/datum/overlayComposition) - /datum/overlayComposition for(var/over in overlayList) var/datum/overlayComposition/E = new over() screenOverlayLibrary.Add(over) screenOverlayLibrary[over] = E plmaster = new /obj/overlay( ) plmaster.icon = 'icons/effects/tile_effects.dmi' plmaster.icon_state = "plasma" plmaster.layer = FLY_LAYER plmaster.mouse_opacity = 0 slmaster = new /obj/overlay( ) slmaster.icon = 'icons/effects/tile_effects.dmi' slmaster.icon_state = "sleeping_agent" slmaster.layer = FLY_LAYER slmaster.mouse_opacity = 0 /* w1master = new /obj/overlay( ) w1master.icon = 'icons/effects/tile_effects.dmi' w1master.icon_state = "water1" w1master.layer = TURF_LAYER + 0.1 w1master.mouse_opacity = 0 w2master = new /obj/overlay( ) w2master.icon = 'icons/effects/tile_effects.dmi' w2master.icon_state = "water2" w2master.layer = OBJ_LAYER + 0.5 w2master.mouse_opacity = 0 w3master = new /obj/overlay( ) w3master.icon = 'icons/effects/tile_effects.dmi' w3master.icon_state = "water3" w3master.layer = FLY_LAYER w3master.mouse_opacity = 0 */ spawn(world.tick_lag) processScheduler = new /datum/controller/processScheduler processScheduler.deferSetupFor(/datum/controller/process/ticker) processSchedulerView = new /datum/processSchedulerView for (var/area/Ar in world) Ar.build_sims_score() LAGCHECK(50) url_regex = new("(https?|byond|www)(\\.|:\\/\\/)", "i") processScheduler.setup() src.update_status() SetupOccupationsList() ircbot.event("serverstart") round_start_data() //Tell the hub site a round is starting if (time2text(world.realtime,"DDD") == "Fri") NT |= mentors spawn(world.tick_lag*30) Optimize() sleep_offline = 1 for (var/turf/simulated/wall/supernorn/T in world) // workaround for some strange bug T.update_icon() LAGCHECK(50) RL_Start() load_intraround_jars() //Local bans db automatic expiry stuff var/list/clearResponse = clearTempBansApiFallback() //The remote db keeps itself clean :giggity: if (clearResponse["error"]) logTheThing("debug", null, null, "Local API Error - Callback failed in clearTempBansApiFallback with message: [clearResponse["error"]]") logTheThing("diary", null, null, "Local API Error - Callback failed in clearTempBansApiFallback with message: [clearResponse["error"]]", "debug") var/clearCount = clearResponse["cleared"] if (text2num(clearCount) > 0) logTheThing("debug", null, null, "Local Bans: Cleared [clearCount] expired temporary bans") logTheThing("diary", null, null, "Local Bans: Cleared [clearCount] expired temporary ban/s", "debug") /* var/banParity = bansParityCheck() if (banParity) logTheThing("debug", null, null, "Ban DB Parity: [banParity]") logTheThing("diary", null, null, "Ban DB Parity: [banParity]", "debug") */ if (derelict_mode) creepify_station() voidify_world() solar_flare = 1 // heh bust_lights() master_mode = "disaster" // heh pt. 2 //SpyStructures and caches live here build_chem_structure() build_reagent_cache() build_supply_pack_cache() build_syndi_buylist_cache() build_camera_network() return //Crispy fullban /proc/Reboot_server() processScheduler.stop() save_intraround_jars() if (ticker && ticker.current_state < GAME_STATE_FINISHED) ticker.current_state = GAME_STATE_FINISHED spawn(world.tick_lag) for (var/mob/M in mobs) if (M.client) if (prob(40)) M << sound(pick('sound/misc/NewRound2.ogg', 'sound/misc/NewRound3.ogg', 'sound/misc/NewRound4.ogg')) else M << sound('sound/misc/NewRound.ogg') //Tell client browserOutput that a restart is happening RIGHT NOW ehjax.send(M.client, "browseroutput", "roundrestart") #ifdef DATALOGGER spawn(world.tick_lag*2) var/playercount = 0 var/admincount = 0 for(var/client/C) if(C.mob) if(C.holder) admincount++ playercount++ game_stats.SetValue("players", playercount) game_stats.SetValue("admins", admincount) //game_stats.WriteToFile("data/game_stats.txt") #endif sleep(50) // wait for sound to play if(config.update_check_enabled) world.installUpdate() world.Reboot() /world/proc/update_status() var/s = "" if (config && config.server_name) s += "[config.server_name] — " if(ticker && ticker.mode) s += "[istype(ticker.mode, /datum/game_mode/construction) ? "Construction Mode" : station_name()]"; else s += "[station_name()]"; s += " (" s += "" s += "Goon Station 13" s += "" s += " r" s += svn_revision // s += " — " // s += "blame " + svn_author s += ")" var/list/features = list() if (!ticker) features += "STARTING" if (ticker && master_mode) if (ticker.hide_mode) features += "secret" else features += master_mode if (!enter_allowed) features += "closed" if (abandon_allowed) features += "respawn" if (config && config.allow_vote_mode) features += "vote" if (config && config.allow_ai) features += "AI" var/n = 0 for (var/mob/M in mobs) if (M.client) n++ if (n > 1) features += "~[n] players" else if (n > 0) features += "~[n] player" /* is there a reason for this? the byond site shows 'hosted by X' when there is a proper host already. if (host) features += "hosted by [host]" */ if (!host && config && config.hostedby) features += "hosted by [config.hostedby]" if (features) s += ": [jointext(features, ", ")]" /* does this help? I do not know */ if (src.status != s) src.status = s /world/proc/installUpdate() // Simple check to see if a new dmb exists in the update folder logTheThing("diary", null, null, "Checking for updated [config.dmb_filename].dmb...", "admin") if(fexists("update/[config.dmb_filename].dmb")) logTheThing("diary", null, null, "Updated [config.dmb_filename].dmb found. Updating...", "admin") for(var/f in flist("update/")) logTheThing("diary", null, null, "\tMoving [f]...", "admin") fcopy("update/[f]", "[f]") fdel("update/[f]") // Delete .dyn.rsc so that stupid shit doesn't happen fdel("[config.dmb_filename].dyn.rsc") logTheThing("diary", null, null, "Update complete.", "admin") else logTheThing("diary", null, null, "No update found. Skipping update process.", "admin") /world/Topic(T, addr, master, key) diary << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]" if (T == "ping") var/x = 1 for (var/client/C) x++ return x else if(T == "players") var/n = 0 for(var/mob/M in mobs) if(M.client) n++ return n else if (T == "admins") var/list/s = list() var/n = 0 for(var/mob/M in mobs) if(M && M.client && M.client.holder && !M.client.stealth) s["admin[n]"] = M.client.key n++ s["admins"] = n return list2params(s) else if (T == "mentors") var/list/s = list() var/n = 0 for(var/mob/M in mobs) if(M && M.client && !M.client.holder && M.client.mentor == 1) s["mentor[n]"] = M.client.key n++ s["mentors"] = n return list2params(s) else if (T == "status") var/list/s = list() s["version"] = game_version s["mode"] = (ticker && ticker.hide_mode) ? "secret" : master_mode s["respawn"] = config ? abandon_allowed : 0 s["enter"] = enter_allowed s["vote"] = config.allow_vote_mode s["ai"] = config.allow_ai s["host"] = host ? host : null s["players"] = list() var/shuttle if (emergency_shuttle) if (emergency_shuttle.location == 1) shuttle = 0 - emergency_shuttle.timeleft() else shuttle = emergency_shuttle.timeleft() else shuttle = "welp" s["shuttle_time"] = shuttle var/elapsed if (ticker && ticker.current_state < GAME_STATE_FINISHED) if (ticker.current_state == GAME_STATE_PREGAME) elapsed = "pre" else if (ticker.current_state > GAME_STATE_PREGAME) elapsed = round(ticker.round_elapsed_ticks / 10) else if (ticker && ticker.current_state == GAME_STATE_FINISHED) elapsed = "post" else elapsed = "welp" s["elapsed"] = elapsed var/n = 0 for(var/mob/M in mobs) if(M.client) s["player[n]"] = "[(M.client.stealth || M.client.alt_key) ? M.client.fakekey : M.client.key]" n++ s["players"] = n return list2params(s) else // IRC bot communication (or callbacks) var/list/plist = params2list(T) switch(plist["type"]) if("irc") var/nick = plist["nick"] var/msg = plist["msg"] msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) logTheThing("ooc", null, null, "IRC OOC: [nick]: [msg]") if (nick == "buttbot") for (var/obj/machinery/bot/buttbot/B in machines) if(B.on) B.speak(msg) return 1 //This is important. else if (nick == "HeadSurgeon") for (var/obj/machinery/bot/medbot/head_surgeon/HS in machines) if (HS.on) HS.speak(msg) for (var/obj/item/clothing/suit/cardboard_box/head_surgeon/HS in world) HS.speak(msg) return 1 return 0 if("ooc") var/nick = plist["nick"] var/msg = plist["msg"] msg = trim(copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)) logTheThing("ooc", nick, null, "OOC: [msg]") logTheThing("diary", nick, null, ": [msg]", "ooc") var/rendered = "OOC: [nick]: [msg]" for (var/client/C) if (C.preferences && !C.preferences.listen_ooc) continue boutput(C, rendered) var/ircmsg[] = new() ircmsg["msg"] = msg return ircbot.response(ircmsg) if("asay") var/nick = plist["nick"] var/msg = plist["msg"] msg = trim(copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)) logTheThing("admin", null, null, "IRC ASAY: [nick]: [msg]") logTheThing("diary", null, null, "IRC ASAY: [nick]: [msg]", "admin") var/rendered = "ADMIN IRC: [nick]: [msg]" for (var/mob/M in mobs) if (M.client && M.client.holder) boutput(M, rendered) var/ircmsg[] = new() ircmsg["key"] = nick ircmsg["msg"] = msg return ircbot.response(ircmsg) if("fpm") var/server_name = plist["server_name"] if (!server_name) server_name = "LLJK-???" var/nick = plist["nick"] var/msg = plist["msg"] msg = trim(copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)) logTheThing("admin", null, null, "[server_name] PM: [nick]: [msg]") logTheThing("diary", null, null, "[server_name] PM: [nick]: [msg]", "admin") var/rendered = "[server_name] PM: [nick]: [msg]" for (var/mob/M in mobs) if (M.client && M.client.holder) boutput(M, rendered) var/ircmsg[] = new() ircmsg["key"] = nick ircmsg["msg"] = msg return ircbot.response(ircmsg) if("pm") var/nick = plist["nick"] var/msg = plist["msg"] var/who = lowertext(plist["target"]) var/mob/F for (var/mob/M in mobs) if (M.ckey && (findtext(M.real_name, who) || findtext(M.ckey, who))) if (M.client) F = M boutput(M, "Admin PM from-[nick] (IRC): [msg]") logTheThing("admin_help", null, M, "IRC: [nick] PM'd %target%: [msg]") logTheThing("diary", null, M, "IRC: [nick] PM'd %target%: [msg]", "ahelp") for (var/mob/K in mobs) if (K && K.client && K.client.holder && K.key != M.key) if (K.client.player_mode && !K.client.player_mode_ahelp) continue else boutput(K, "PM: [nick] (IRC) [key_name(M)]: [msg]") break if (F) var/ircmsg[] = new() ircmsg["key"] = nick ircmsg["key2"] = (F.client != null && F.client.key != null) ? F.client.key : "*no client*" ircmsg["name2"] = (F.real_name != null) ? F.real_name : "" ircmsg["msg"] = html_decode(msg) return ircbot.response(ircmsg) else return 0 if("mentorpm") var/nick = plist["nick"] var/msg = plist["msg"] var/who = lowertext(plist["target"]) var/mob/F for (var/mob/M in mobs) if (M.ckey && (findtext(M.real_name, who) || findtext(M.ckey, who))) if (M.client) F = M boutput(M, "MENTOR PM: FROM [nick] (IRC): [msg]") logTheThing("admin", null, M, "IRC: [nick] Mentor PM'd %target%: [msg]") logTheThing("diary", null, M, "IRC: [nick] Mentor PM'd %target%: [msg]", "admin") for (var/mob/K in mobs) if (K && K.client && ((K.client.mentor && K.client.see_mentor_pms) || K.client.holder) && K.key != M.key) if(K.client.holder) if (K.client.player_mode && !K.client.player_mode_mhelp) continue else boutput(K, "MENTOR PM: [nick] (IRC) [key_name(M,0,0,1)][(M.real_name ? "/"+M.real_name : "")] : [msg]") else boutput(K, "MENTOR PM: [nick] (IRC) [key_name(M,0,0,1)]: [msg]") break if (F) var/ircmsg[] = new() ircmsg["key"] = nick ircmsg["key2"] = (F.client != null && F.client.key != null) ? F.client.key : "*no client*" ircmsg["name2"] = (F.real_name != null) ? F.real_name : "" ircmsg["msg"] = html_decode(msg) return ircbot.response(ircmsg) else return 0 if("whois") var/who = plist["target"] var/whois = whois(who, 5) if (whois) var/list/parsedWhois = list() var/count = 0 for (var/mob/M in whois) count++ if (M.name) parsedWhois["name[count]"] = M.name if (M.key) parsedWhois["ckey[count]"] = M.key if (M.stat == 2) parsedWhois["dead[count]"] = 1 if (M.mind && M.mind.assigned_role) parsedWhois["role[count]"] = M.mind.assigned_role if (checktraitor(M)) parsedWhois["t[count]"] = 1 parsedWhois["count"] = count return ircbot.response(parsedWhois) else return 0 /* topic call, type=reboot reboots a server.. without a password, or any form of authentication. well there, i've fixed it. -drsingh if("reboot") var/ircmsg[] = new() ircmsg["msg"] = "Attempting to restart now" Reboot_server() return ircbot.response(ircmsg) */ if ("heal") var/nick = plist["nick"] var/who = lowertext(plist["target"]) var/list/found = list() for (var/mob/M in mobs) if (M.ckey && (findtext(M.real_name, who) || findtext(M.ckey, who))) M.full_heal() logTheThing("admin", nick, M, "healed / revived %target%") logTheThing("diary", nick, M, "healed / revived %target%", "admin") message_admins("Admin [nick] healed / revived [key_name(M)] from IRC!") var/ircmsg[] = new() ircmsg["type"] = "heal" ircmsg["who"] = who ircmsg["msg"] = "Admin [nick] healed / revived [M.ckey]" found.Add(ircmsg) if (found && found.len > 0) return ircbot.response(found) else return 0 if ("hubCallback") //logTheThing("debug", "Wire Debug: hubCallback hit from addr: [addr] with auth: [plist["auth"]] calling proc: [plist["proc"]] with data: [plist["data"]]") //world.log << "Wire Debug: hubCallback hit from addr: [addr] with auth: [plist["auth"]] calling proc: [plist["proc"]] with data: [plist["data"]]" if (addr != config.extserver_hostname) return 0 //ip filtering var/auth = plist["auth"] if (auth != md5(config.extserver_token)) return 0 //really bad md5 token security var/theProc = "/proc/[plist["proc"]]" var/list/ldata = parseCallbackData(plist["data"]) var/rVal = call(theProc)(2, ldata) //calls the second stage of whatever proc specified if (rVal) logTheThing("debug", null, null, "Callback Error - Hub callback failed in [theProc] with message: [rVal]") logTheThing("diary", null, null, "Callback Error - Hub callback failed in [theProc] with message: [rVal]", "debug") return 0 else return 1 if ("roundEnd") //if (addr != config.extserver_hostname) return 0 //ip filtering var/server = plist["server"] var/address = plist["address"] var/mode = plist["mode"] var/msg = "
---------------------
" msg += "A round just ended on LLJK#[server]
" msg += "It is running [mode]
" msg += "Click here to join it
" msg += "---------------------

" for (var/mob/M in mobs) if (M.stat == 2) boutput(M, msg) return 1 if ("mysteryPrint") if (addr != config.extserver_hostname) return 0 //ip filtering var/msgTitle = plist["print_title"] var/msgFile = "strings/mysteryprint/"+plist["print_file"] if (!fexists(msgFile)) return 0 var/msgText = file2text(msgFile) //Prints to every networked printer in the world for (var/obj/machinery/networked/printer/P in machines) P.print_buffer += "[msgTitle]&title;[msgText]" P.print() return 1 //Tells shitbot what the current AI laws are (if there are any custom ones) if ("ailaws") if (ticker && ticker.current_state > GAME_STATE_PREGAME) var/list/laws = ticker.centralized_ai_laws.format_for_irc() return ircbot.response(laws) else return 0 if ("health") var/ircmsg[] = new() ircmsg["cpu"] = world.cpu ircmsg["queue_len"] = delete_queue ? delete_queue.count() : 0 var/curtime = world.timeofday sleep(10) ircmsg["time"] = (world.timeofday - curtime) / 10 return ircbot.response(ircmsg) if ("rev") var/ircmsg[] = new() ircmsg["msg"] = "[svn_revision] by [svn_author]" return ircbot.response(ircmsg) /// EXPERIMENTAL STUFF var/opt_inactive = null /world/proc/Optimize() spawn(0) if(!opt_inactive) opt_inactive = world.timeofday if(world.timeofday - opt_inactive >= 600 || world.timeofday - opt_inactive < 0) KickInactiveClients() //if(mysql) //mysql.CleanQueries() opt_inactive = world.timeofday sleep(100) /world/proc/KickInactiveClients() for(var/client/C in clients) if(!C.holder && ((C.inactivity/10)/60) >= 15) boutput(C, "You have been inactive for more than 15 minutes and have been disconnected.") del(C) /// EXPERIMENTAL STUFF