From 8df93ba39ecbbde0b5bee88bbe27837f3a76536a Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Tue, 11 Aug 2020 18:51:43 -0700 Subject: [PATCH] [Ready] CDN browser assets! (#52681) Rewrites the asset_cache system to handle sending assets to a CDN via a webroot. see https://github.com/MrStonedOne/tgstation/blob/asset-cdn/code/modules/asset_cache/readme.md Fixed a lot of bugs with assets, removed some dead code. Changes: Moved asset cache code to transport datums, the currently loaded one is located at SSassets.transport, asset cache calls made before the config is loaded use the simple browse_rsc transport. Added subsystem call for when the config loads or reloads. Added a webroot CDN asset transport. assets are saved to a file in a format based on the file's hash (currently md5). Assets that don't use get_asset_url or get_url_mappings (such as browser assets referred to by static html files like changelog.html or static css files) can be saved to browse_rsc even when in cdn asset mode by setting legacy to TRUE on the datum returned by register_assets Added a system for saving assets on a cdn in a hash based namespace (folder), assets within the same namespace will always be able to refer to each other by relative names. (used to allow cdn'ing font awesome without having to make something that regenerates it's css files.). The simple/namespaced asset cache datum helper will handle generating a namespace composed of the combined md5 of everything in the same datum, as well as registering them properly. Moved external resource from a snowflake loaded file to a config entry, added it to resources.txt To ensure the system breaks in local testing in any situation that wouldn't work in cdn mode, the simple transport will mutate the filenames of non-legacy and non-namespaced assets and return this with get_asset_url. Simple transport's passive send of all roundstart assets to all clients is now a config that defaults to off. this is to break race conditions during local testings from devs accidentally relying on this instead of using send() properly. cl refactor: Interface assets (js/css/images) can now be managed using an external webserver instead of byond's one at a time file transfer queue. admin: Adds admin verb toggle-cdn that allows admins to disable the external webserver asset transport and revert to the old system. Useful if the webserver backing this goes down (thanks cloudflare). config: New config file, resources.txt, (must be loaded by an $include statement from the main config) server: The external_rsc_urls.txt config has been moved to the main config system. /cl Porting notes: Interface webpages must refer to their assets (css/js/image/etc) by a generated url, or the asset must register itself as a legacy asset. The system is designed to break in localtest (on simple/legacy mode) in most situations that would break in cdn mode. Requires latest tgui. The webserver must set the proper CORS headers for font files or font awesome (and other fonts) won't load. /tg/'s webserver config: https://gist.github.com/MrStonedOne/523388b2f161af832292d98a8aad0eae --- code/__HELPERS/files.dm | 5 - code/__HELPERS/icons.dm | 20 ++- code/__HELPERS/type2type.dm | 5 + .../configuration/configuration.dm | 3 + .../configuration/entries/resources.dm | 30 ++++ code/controllers/master.dm | 5 + code/controllers/subsystem.dm | 2 + code/controllers/subsystem/assets.dm | 21 ++- code/datums/browser.dm | 33 ++--- code/game/machinery/computer/arcade.dm | 2 - code/game/machinery/computer/card.dm | 1 - .../game/machinery/computer/communications.dm | 1 - code/game/machinery/computer/dna_console.dm | 4 + code/game/machinery/computer/medical.dm | 1 - code/game/machinery/computer/pod.dm | 1 - .../machinery/computer/prisoner/management.dm | 1 - code/game/machinery/computer/security.dm | 3 +- code/game/machinery/computer/warrant.dm | 1 - .../embedded_controller/access_controller.dm | 1 - .../embedded_controller_base.dm | 1 - code/game/machinery/newscaster.dm | 1 - code/game/machinery/requests_console.dm | 1 - code/game/machinery/slotmachine.dm | 1 - .../machinery/telecomms/computers/message.dm | 1 - code/game/objects/structures/musician.dm | 1 - code/game/world.dm | 12 -- code/modules/admin/admin_verbs.dm | 6 +- code/modules/admin/permissionedit.dm | 8 +- code/modules/admin/sql_message_system.dm | 2 +- code/modules/admin/verbs/beakerpanel.dm | 6 +- code/modules/admin/verbs/diagnostics.dm | 28 ++++ .../admin/view_variables/view_variables.dm | 2 +- code/modules/asset_cache/asset_cache.dm | 110 -------------- .../modules/asset_cache/asset_cache_client.dm | 16 +- code/modules/asset_cache/asset_cache_item.dm | 26 +++- code/modules/asset_cache/asset_list.dm | 82 ++++++++-- code/modules/asset_cache/asset_list_items.dm | 38 ++++- code/modules/asset_cache/readme.md | 37 +++++ .../asset_cache/transports/asset_transport.dm | 140 ++++++++++++++++++ .../transports/webroot_transport.dm | 87 +++++++++++ code/modules/asset_cache/validate_assets.html | 2 +- code/modules/client/client_procs.dm | 25 ++-- code/modules/library/lib_machines.dm | 3 - code/modules/mining/aux_base.dm | 1 - .../modules/mob/dead/new_player/new_player.dm | 3 +- code/modules/mob/dead/new_player/poll.dm | 4 +- code/modules/mob/dead/observer/orbit.dm | 5 + .../mob/living/silicon/pai/software.dm | 2 +- code/modules/power/generator.dm | 1 - code/modules/research/server.dm | 1 - code/modules/shuttle/computer.dm | 1 - code/modules/tgui/tgui.dm | 11 +- code/modules/tgui/tgui_window.dm | 6 +- config/config.txt | 1 + config/resources.txt | 39 +++++ html/{ => admin}/panels.css | 0 html/{ => admin}/search.js | 0 interface/interface.dm | 4 +- tgstation.dme | 4 +- tools/localhost-asset-webroot-server.py | 15 ++ 60 files changed, 614 insertions(+), 260 deletions(-) create mode 100644 code/controllers/configuration/entries/resources.dm delete mode 100644 code/modules/asset_cache/asset_cache.dm create mode 100644 code/modules/asset_cache/readme.md create mode 100644 code/modules/asset_cache/transports/asset_transport.dm create mode 100644 code/modules/asset_cache/transports/webroot_transport.dm create mode 100644 config/resources.txt rename html/{ => admin}/panels.css (100%) rename html/{ => admin}/search.js (100%) create mode 100644 tools/localhost-asset-webroot-server.py diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm index 521ce0d08e2..f102a96adfe 100644 --- a/code/__HELPERS/files.dm +++ b/code/__HELPERS/files.dm @@ -1,8 +1,3 @@ -//Sends resource files to client cache -/client/proc/getFiles(...) - for(var/file in args) - src << browse_rsc(file) - /client/proc/browse_files(root_type=BROWSE_ROOT_ALL_LOGS, max_iterations=10, list/valid_extensions=list("txt","log","htm", "html")) // wow why was this ever a parameter var/root = "data/logs/" diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index bb46a9b6542..884c8efe0c5 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1103,6 +1103,14 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 /// Save file used in icon2base64. Used for converting icons to base64. GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of icons for the browser output + +/// Generate a filename for this asset +/// The same asset will always lead to the same asset name +/// (Generated names do not include file extention.) +/proc/generate_asset_name(file) + return "asset.[md5(fcopy_rsc(file))]" + + /** * Converts an icon to base64. Operates by putting the icon in the iconCache savefile, * exporting it as text, and then parsing the base64 from that. @@ -1138,10 +1146,10 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico if (isfile(thing)) //special snowflake var/name = sanitize_filename("[generate_asset_name(thing)].png") if (!SSassets.cache[name]) - register_asset(name, thing) + SSassets.transport.register_asset(name, thing) for (var/thing2 in targets) - send_asset(thing2, key) - return "" + SSassets.transport.send_assets(thing2, name) + return "" var/atom/A = thing if (isnull(dir)) dir = A.dir @@ -1163,11 +1171,11 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico key = "[generate_asset_name(I)].png" if(!SSassets.cache[key]) - register_asset(key, I) + SSassets.transport.register_asset(key, I) for (var/thing2 in targets) - send_asset(thing2, key) + SSassets.transport.send_assets(thing2, key) - return "" + return "" /proc/icon2base64html(thing) if (!thing) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 4873e35d0b3..ec4523ea27c 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -487,3 +487,8 @@ GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH, return "turf" else //regex everything else (works for /proc too) return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", "")) + +/// Return html to load a url. +/// for use inside of browse() calls to html assets that might be loaded on a cdn. +/proc/url2htmlloader(url) + return {""} diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 4070964c330..be69d77a9cb 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -52,6 +52,9 @@ LoadMOTD() LoadPolicy() LoadChatFilter() + + if (Master) + Master.OnConfigLoad() /datum/controller/configuration/proc/full_wipe() if(IsAdminAdvancedProcCall()) diff --git a/code/controllers/configuration/entries/resources.dm b/code/controllers/configuration/entries/resources.dm new file mode 100644 index 00000000000..c839ccc078d --- /dev/null +++ b/code/controllers/configuration/entries/resources.dm @@ -0,0 +1,30 @@ +/datum/config_entry/keyed_list/external_rsc_urls + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_FLAG + +/datum/config_entry/flag/asset_simple_preload + +/datum/config_entry/string/asset_transport +/datum/config_entry/string/asset_transport/ValidateAndSet(str_val) + return (lowertext(str_val) in list("simple", "webroot")) && ..(lowertext(str_val)) + +/datum/config_entry/string/asset_cdn_webroot + protection = CONFIG_ENTRY_LOCKED + +/datum/config_entry/string/asset_cdn_webroot/ValidateAndSet(str_var) + if (!str_var || trim(str_var) == "") + return FALSE + if (str_var && str_var[length(str_var)] != "/") + str_var += "/" + return ..(str_var) + +/datum/config_entry/string/asset_cdn_url + protection = CONFIG_ENTRY_LOCKED + default = null + +/datum/config_entry/string/asset_cdn_url/ValidateAndSet(str_var) + if (!str_var || trim(str_var) == "") + return FALSE + if (str_var && str_var[length(str_var)] != "/") + str_var += "/" + return ..(str_var) diff --git a/code/controllers/master.dm b/code/controllers/master.dm index d7fcda6c5aa..ffe29172f2e 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -633,3 +633,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new processing = CONFIG_GET(number/mc_tick_rate/base_mc_tick_rate) else if (client_count > CONFIG_GET(number/mc_tick_rate/high_pop_mc_mode_amount)) processing = CONFIG_GET(number/mc_tick_rate/high_pop_mc_tick_rate) + +/datum/controller/master/proc/OnConfigLoad() + for (var/thing in subsystems) + var/datum/controller/subsystem/SS = thing + SS.OnConfigLoad() diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index 574ed33311c..d9b16624232 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -208,6 +208,8 @@ if(SS_SLEEPING) state = SS_PAUSING +/// Called after the config has been loaded or reloaded. +/datum/controller/subsystem/proc/OnConfigLoad() //used to initialize the subsystem AFTER the map has loaded /datum/controller/subsystem/Initialize(start_timeofday) diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm index 7285298283c..4f02d32ad0f 100644 --- a/code/controllers/subsystem/assets.dm +++ b/code/controllers/subsystem/assets.dm @@ -4,6 +4,23 @@ SUBSYSTEM_DEF(assets) flags = SS_NO_FIRE var/list/cache = list() var/list/preload = list() + var/datum/asset_transport/transport = new() + +/datum/controller/subsystem/assets/OnConfigLoad() + var/newtransporttype = /datum/asset_transport + switch (CONFIG_GET(string/asset_transport)) + if ("webroot") + newtransporttype = /datum/asset_transport/webroot + + if (newtransporttype == transport.type) + return + + var/datum/asset_transport/newtransport = new newtransporttype () + if (newtransport.validate_config()) + transport = newtransport + transport.Load() + + /datum/controller/subsystem/assets/Initialize(timeofday) for(var/type in typesof(/datum/asset)) @@ -11,8 +28,6 @@ SUBSYSTEM_DEF(assets) if (type != initial(A._abstract)) get_asset_datum(type) - preload = cache.Copy() //don't preload assets generated during the round + transport.Initialize(cache) - for(var/client/C in GLOB.clients) - addtimer(CALLBACK(GLOBAL_PROC, .proc/getFilesSlow, C, preload, FALSE), 10) ..() diff --git a/code/datums/browser.dm b/code/datums/browser.dm index b18b23ddfe7..0d44759a6f3 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -8,11 +8,11 @@ var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id var/stylesheets[0] var/scripts[0] - var/title_image var/head_elements var/body_elements var/head_content = "" var/content = "" + var/static/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common) /datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null) @@ -27,7 +27,6 @@ height = nheight if (nref) ref = nref - add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs /datum/browser/proc/add_head_content(nhead_content) head_content = nhead_content @@ -35,9 +34,6 @@ /datum/browser/proc/set_window_options(nwindow_options) window_options = nwindow_options -/datum/browser/proc/set_title_image(ntitle_image) - //title_image = ntitle_image - /datum/browser/proc/add_stylesheet(name, file) if (istype(name, /datum/asset/spritesheet)) var/datum/asset/spritesheet/sheet = name @@ -48,11 +44,11 @@ stylesheets[asset_name] = file if (!SSassets.cache[asset_name]) - register_asset(asset_name, file) + SSassets.transport.register_asset(asset_name, file) /datum/browser/proc/add_script(name, file) scripts["[ckey(name)].js"] = file - register_asset("[ckey(name)].js", file) + SSassets.transport.register_asset("[ckey(name)].js", file) /datum/browser/proc/set_content(ncontent) content = ncontent @@ -62,15 +58,13 @@ /datum/browser/proc/get_header() var/file + head_content += "" for (file in stylesheets) - head_content += "" + head_content += "" + for (file in scripts) - head_content += "" - - var/title_attributes = "class='uiTitle'" - if (title_image) - title_attributes = "class='uiTitle icon' style='background-image: url([title_image]);'" + head_content += "" return {" @@ -81,7 +75,7 @@
- [title ? "
[title]
" : ""] + [title ? "
[title]
" : ""]
"} //" This is here because else the rest of the file looks like a string in notepad++. @@ -107,10 +101,11 @@ var/window_size = "" if (width && height) window_size = "size=[width]x[height];" + common_asset.send(user) if (stylesheets.len) - send_asset_list(user, stylesheets) + SSassets.transport.send_assets(user, stylesheets) if (scripts.len) - send_asset_list(user, scripts) + SSassets.transport.send_assets(user, scripts) user << browse(get_content(), "window=[window_id];[window_size][window_options]") if (use_onclose) setup_onclose() @@ -419,12 +414,6 @@ if (A.selectedbutton) return list("button" = A.selectedbutton, "settings" = A.settings) -// This will allow you to show an icon in the browse window -// This is added to mob so that it can be used without a reference to the browser object -// There is probably a better place for this... -/mob/proc/browse_rsc_icon(icon, icon_state, dir = -1) - - // Registers the on-close verb for a browse window (client/verb/.windowclose) // this will be called when the close-button of a window is pressed. // diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index b7ff2fb3705..2e40d75c13a 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -277,7 +277,6 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( if(user.client) //mainly here to avoid a runtime when the player gets gibbed when losing the emag mode. var/datum/browser/popup = new(user, "arcade", "Space Villain 2000") popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() @@ -844,7 +843,6 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( dat += "

Close

" var/datum/browser/popup = new(user, "arcade", "The Orion Trail",400,700) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() return diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index cccbbc02a87..2777173442e 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -355,7 +355,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) dat = list("", header.Join(), body, "
") var/datum/browser/popup = new(user, "id_com", src.name, 900, 620) popup.set_content(dat.Join()) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/card/Topic(href, href_list) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 88f555748a6..e9d7d75a4e9 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -445,7 +445,6 @@ var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) if(issilicon(user)) var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index 9697f2892e5..c0c074a4556 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -251,6 +251,10 @@ if(!ui) ui = new(user, src, "DnaConsole") ui.open() + +/obj/machinery/computer/scan_consolenew/ui_assets() + . = ..() || list() + . += get_asset_datum(/datum/asset/simple/genetics) /obj/machinery/computer/scan_consolenew/ui_data(mob/user) var/list/data = list() diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index dc733dd78ef..ac4dcd4abc3 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -172,7 +172,6 @@ dat += "{Log In}" var/datum/browser/popup = new(user, "med_rec", "Medical Records Console", 600, 400) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/machinery/computer/med_data/Topic(href, href_list) diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index dce48531d61..cf7b2818b49 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -67,7 +67,6 @@ add_fingerprint(usr) var/datum/browser/popup = new(user, "computer", title, 400, 500) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/machinery/computer/pod/process() diff --git a/code/game/machinery/computer/prisoner/management.dm b/code/game/machinery/computer/prisoner/management.dm index 837918d5f1a..dc69e0e7c69 100644 --- a/code/game/machinery/computer/prisoner/management.dm +++ b/code/game/machinery/computer/prisoner/management.dm @@ -65,7 +65,6 @@ dat += "
{Log Out}" var/datum/browser/popup = new(user, "computer", "Prisoner Management Console", 400, 500) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() return diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 0fa1ed99bb9..8079e397260 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -55,7 +55,7 @@ dat += {" - + +
@@ -137,7 +139,7 @@ if(IsAdminAdvancedProcCall()) to_chat(usr, "Admin Edit blocked: Advanced ProcCall detected.", confidential = TRUE) return - var/datum/asset/permissions_assets = get_asset_datum(/datum/asset/simple/permissions) + var/datum/asset/permissions_assets = get_asset_datum(/datum/asset/simple/namespaced/common) permissions_assets.send(src) var/admin_key = href_list["key"] var/admin_ckey = ckey(admin_key) diff --git a/code/modules/admin/sql_message_system.dm b/code/modules/admin/sql_message_system.dm index 3ba309bc24a..be2e7499b75 100644 --- a/code/modules/admin/sql_message_system.dm +++ b/code/modules/admin/sql_message_system.dm @@ -502,7 +502,7 @@ alphatext = "filter: alpha(opacity=[alpha]); opacity: [alpha/100];" var/list/data = list("

") if(severity) - data += " " + data += " " data += "[timestamp] | [server] | [admin_key][secret ? " | - Secret" : ""]" if(expire_timestamp) data += " | Expires [expire_timestamp]" diff --git a/code/modules/admin/verbs/beakerpanel.dm b/code/modules/admin/verbs/beakerpanel.dm index d280a03fff4..d07049e1a4f 100644 --- a/code/modules/admin/verbs/beakerpanel.dm +++ b/code/modules/admin/verbs/beakerpanel.dm @@ -65,14 +65,16 @@ set name = "Spawn reagent container" if(!check_rights()) return - + var/datum/asset/asset_datum = get_asset_datum(/datum/asset/simple/namespaced/common) + asset_datum.send() + //Could somebody tell me why this isn't using the browser datum, given that it copypastes all of browser datum's html var/dat = {" - + diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index 01472ae1ed8..82ca517abd4 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -79,3 +79,31 @@ load_admins() SSblackbox.record_feedback("tally", "admin_verb", 1, "Reload All Admins") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! message_admins("[key_name_admin(usr)] manually reloaded admins") + +/client/proc/toggle_cdn() + set name = "Toggle CDN" + set category = "Server" + var/static/admin_disabled_cdn_transport = null + if (alert(usr, "Are you sure you want to toggle the CDN asset transport?", "Confirm", "Yes", "No") != "Yes") + return + var/current_transport = CONFIG_GET(string/asset_transport) + if (!current_transport || current_transport == "simple") + if (admin_disabled_cdn_transport) + CONFIG_SET(string/asset_transport, admin_disabled_cdn_transport) + admin_disabled_cdn_transport = null + SSassets.OnConfigLoad() + message_admins("[key_name_admin(usr)] re-enabled the CDN asset transport") + log_admin("[key_name(usr)] re-enabled the CDN asset transport") + else + to_chat(usr, "The CDN is not enabled!") + if (alert(usr, "The CDN asset transport is not enabled! If you having issues with assets you can also try disabling filename mutations.", "The CDN asset transport is not enabled!", "Try disabling filename mutations", "Nevermind") == "Try disabling filename mutations") + SSassets.transport.dont_mutate_filenames = !SSassets.transport.dont_mutate_filenames + message_admins("[key_name_admin(usr)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms") + log_admin("[key_name(usr)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms") + else + admin_disabled_cdn_transport = current_transport + CONFIG_SET(string/asset_transport, "simple") + SSassets.OnConfigLoad() + SSassets.transport.dont_mutate_filenames = TRUE + message_admins("[key_name_admin(usr)] disabled the CDN asset transport") + log_admin("[key_name(usr)] disabled the CDN asset transport") diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index 62d9ff62fb9..3851008d865 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -95,7 +95,7 @@ [title] - + - \ No newline at end of file + diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 1a8baf65ef1..e455db34fd1 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -204,9 +204,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( /////////// //CONNECT// /////////// -#if (PRELOAD_RSC == 0) -GLOBAL_LIST_EMPTY(external_rsc_urls) -#endif /client/New(TopicData) var/tdata = TopicData //save this for later use @@ -874,29 +871,25 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) return inactivity return FALSE -//send resources to the client. It's here in its own proc so we can move it around easiliy if need be +/// Send resources to the client. +/// Sends both game resources and browser assets. /client/proc/send_resources() #if (PRELOAD_RSC == 0) var/static/next_external_rsc = 0 - if(GLOB.external_rsc_urls && GLOB.external_rsc_urls.len) - next_external_rsc = WRAP(next_external_rsc+1, 1, GLOB.external_rsc_urls.len+1) - preload_rsc = GLOB.external_rsc_urls[next_external_rsc] + var/list/external_rsc_urls = CONFIG_GET(keyed_list/external_rsc_urls) + if(length(external_rsc_urls.len)) + next_external_rsc = WRAP(next_external_rsc+1, 1, external_rsc_urls.len+1) + preload_rsc = external_rsc_urls[next_external_rsc] #endif - //get the common files - getFiles( - 'html/search.js', - 'html/panels.css', - 'html/browser/common.css', - 'html/browser/scannernew.css', - 'html/browser/playeroptions.css', - ) + spawn (10) //removing this spawn causes all clients to not get verbs. //load info on what assets the client has src << browse('code/modules/asset_cache/validate_assets.html', "window=asset_cache_browser") //Precache the client with all other assets slowly, so as to not block other browse() calls - addtimer(CALLBACK(GLOBAL_PROC, /proc/getFilesSlow, src, SSassets.preload, FALSE), 5 SECONDS) + if (CONFIG_GET(flag/asset_simple_preload)) + addtimer(CALLBACK(SSassets.transport, /datum/asset_transport.proc/send_assets_slow, src, SSassets.transport.preload), 5 SECONDS) #if (PRELOAD_RSC == 0) for (var/name in GLOB.vox_sounds) diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 81f6d99e750..35e7474d2a5 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -101,7 +101,6 @@ dat += "\[Go Back\]
" var/datum/browser/popup = new(user, "publiclibrary", name, 600, 400) popup.set_content(jointext(dat, "")) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/libraryconsole/Topic(href, href_list) @@ -325,7 +324,6 @@ var/datum/browser/popup = new(user, "library", name, 600, 400) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/computer/bookmanagement/proc/findscanner(viewrange) @@ -545,7 +543,6 @@ dat += "
" var/datum/browser/popup = new(user, "scanner", name, 600, 400) popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() /obj/machinery/libraryscanner/Topic(href, href_list) diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm index b867eb48f47..2726d08689c 100644 --- a/code/modules/mining/aux_base.dm +++ b/code/modules/mining/aux_base.dm @@ -68,7 +68,6 @@ interface with the mining shuttle at the landing site if a mobile beacon is also var/datum/browser/popup = new(user, "computer", "base management", 550, 300) //width, height popup.set_content("

[dat]
") - popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state)) popup.open() diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index f60d1b2a0fc..d2d2a78ca6f 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -41,6 +41,8 @@ return /mob/dead/new_player/proc/new_player_panel() + var/datum/asset/asset_datum = get_asset_datum(/datum/asset/simple/lobby) + asset_datum.send(client) var/output = "

Setup Character

" if(SSticker.current_state <= GAME_STATE_PREGAME) @@ -91,7 +93,6 @@ output += "
" - //src << browse(output,"window=playersetup;size=210x240;can_close=0") var/datum/browser/popup = new(src, "playersetup", "
New Player Options
", 250, 265) popup.set_window_options("can_close=0") popup.set_content(output) diff --git a/code/modules/mob/dead/new_player/poll.dm b/code/modules/mob/dead/new_player/poll.dm index 231e3deafea..cda26aaeca3 100644 --- a/code/modules/mob/dead/new_player/poll.dm +++ b/code/modules/mob/dead/new_player/poll.dm @@ -253,8 +253,8 @@ prepared_options = shuffle(poll.options) var/list/output = list({" - - + +