diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index db4c52f313c..facd14ec8a0 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -33,6 +33,12 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define ADMIN_SPAWNED_1 (1<<15) //! was this spawned by an admin? used for stat tracking stuff. #define PREVENT_CONTENTS_EXPLOSION_1 (1<<16) #define UNPAINTABLE_1 (1<<17) +<<<<<<< HEAD +======= +#define HTML_USE_INITAL_ICON_1 (1<<18) //! Should we use the initial icon for display? Mostly used by overlay only objects +/// Does the supermatter skip over this atom? +#define SUPERMATTER_IGNORES_1 (1 << 18) //set this to 18 because tg has some other flags appearantly too if that gets ever ported fix this !!!! +>>>>>>> 000e1cd18a... icon2html optimizations (#7610) /// If the thing can reflect light (lasers/energy) #define RICOCHET_SHINY (1<<0) diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm index 64fc2dd8693..671882fcce9 100644 --- a/code/__HELPERS/icon_smoothing.dm +++ b/code/__HELPERS/icon_smoothing.dm @@ -1,18 +1,18 @@ //generic (by snowflake) tile smoothing code; smooth your icons with this! -/** +/** Each tile is divided in 4 corners, each corner has an appearance associated to it; the tile is then overlayed by these 4 appearances. To use this, just set your atom's 'smooth' var to 1. If your atom can be moved/unanchored, set its 'can_be_unanchored' var to 1. If you don't want your atom's icon to smooth with anything but atoms of the same type, set the list 'canSmoothWith' to null; Otherwise, put all types you want the atom icon to smooth with in 'canSmoothWith' INCLUDING THE TYPE OF THE ATOM ITSELF. Each atom has its own icon file with all the possible corner states. See 'smooth_wall.dmi' for a template. ### DIAGONAL SMOOTHING INSTRUCTIONS - + To make your atom smooth diagonally you need all the proper icon states (see 'smooth_wall.dmi' for a template) and to add the 'SMOOTH_DIAGONAL' flag to the atom's smooth var (in addition to either SMOOTH_TRUE or SMOOTH_MORE). For turfs, what appears under the diagonal corners depends on the turf that was in the same position previously: if you make a wall on a plating floor, you will see plating under the diagonal wall corner, if it was space, you will see space. If you wish to map a diagonal wall corner with a fixed underlay, you must configure the turf's 'fixed_underlay' list var, like so: - + ``` fixed_underlay = list("icon"='icon_file.dmi', "icon_state"="iconstatename") ``` @@ -112,6 +112,7 @@ if(!A || !A.smooth) return A.smooth &= ~SMOOTH_QUEUED + A.flags_1 |= HTML_USE_INITAL_ICON_1 if (!A.z) return if(QDELETED(A)) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index c0aafd25239..ec227f055a4 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1158,8 +1158,24 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 alpha += 25 obj_flags &= ~FROZEN +<<<<<<< HEAD /// 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 +======= +/// generates a filename for a given asset. +/// like generate_asset_name(), except returns the rsc reference and the rsc file hash as well as the asset name (sans extension) +/// used so that certain asset files dont have to be hashed twice +/proc/generate_and_hash_rsc_file(file, dmi_file_path) + var/rsc_ref = fcopy_rsc(file) + var/hash + //if we have a valid dmi file path we can trust md5'ing the rsc file because we know it doesnt have the bug described in http://www.byond.com/forum/post/2611357 + if(dmi_file_path) + hash = md5(rsc_ref) + else //otherwise, we need to do the expensive fcopy() workaround + hash = md5asfile(rsc_ref) + + return list(rsc_ref, hash, "asset.[hash]") +>>>>>>> 000e1cd18a... icon2html optimizations (#7610) /// Generate a filename for this asset /// The same asset will always lead to the same asset name @@ -1180,12 +1196,86 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico var/list/partial = splittext(iconData, "{") return replacetext(copytext_char(partial[2], 3, -5), "\n", "") -/proc/icon2html(thing, target, icon_state, dir = SOUTH, frame = 1, moving = FALSE, sourceonly = FALSE) +///given a text string, returns whether it is a valid dmi icons folder path +/proc/is_valid_dmi_file(icon_path) + if(!istext(icon_path) || !length(icon_path)) + return FALSE + + var/is_in_icon_folder = findtextEx(icon_path, "icons/") + var/is_dmi_file = findtextEx(icon_path, ".dmi") + + if(is_in_icon_folder && is_dmi_file) + return TRUE + return FALSE + +/// given an icon object, dmi file path, or atom/image/mutable_appearance, attempts to find and return an associated dmi file path. +/// a weird quirk about dm is that /icon objects represent both compile-time or dynamic icons in the rsc, +/// but stringifying rsc references returns a dmi file path +/// ONLY if that icon represents a completely unchanged dmi file from when the game was compiled. +/// so if the given object is associated with an icon that was in the rsc when the game was compiled, this returns a path. otherwise it returns "" +/proc/get_icon_dmi_path(icon/icon) + /// the dmi file path we attempt to return if the given object argument is associated with a stringifiable icon + /// if successful, this looks like "icons/path/to/dmi_file.dmi" + var/icon_path = "" + + if(isatom(icon) || istype(icon, /image) || istype(icon, /mutable_appearance)) + var/atom/atom_icon = icon + icon = atom_icon.icon + //atom icons compiled in from 'icons/path/to/dmi_file.dmi' are weird and not really icon objects that you generate with icon(). + //if theyre unchanged dmi's then they're stringifiable to "icons/path/to/dmi_file.dmi" + + if(isicon(icon) && isfile(icon)) + //icons compiled in from 'icons/path/to/dmi_file.dmi' at compile time are weird and arent really /icon objects, + ///but they pass both isicon() and isfile() checks. theyre the easiest case since stringifying them gives us the path we want + var/icon_ref = "\ref[icon]" + var/locate_icon_string = "[locate(icon_ref)]" + + icon_path = locate_icon_string + + else if(isicon(icon) && "[icon]" == "/icon") + // icon objects generated from icon() at runtime are icons, but they ARENT files themselves, they represent icon files. + // if the files they represent are compile time dmi files in the rsc, then + // the rsc reference returned by fcopy_rsc() will be stringifiable to "icons/path/to/dmi_file.dmi" + var/rsc_ref = fcopy_rsc(icon) + + var/icon_ref = "\ref[rsc_ref]" + + var/icon_path_string = "[locate(icon_ref)]" + + icon_path = icon_path_string + + else if(istext(icon)) + var/rsc_ref = fcopy_rsc(icon) + //if its the text path of an existing dmi file, the rsc reference returned by fcopy_rsc() will be stringifiable to a dmi path + + var/rsc_ref_ref = "\ref[rsc_ref]" + var/rsc_ref_string = "[locate(rsc_ref_ref)]" + + icon_path = rsc_ref_string + + if(is_valid_dmi_file(icon_path)) + return icon_path + + return FALSE + +/** + * generate an asset for the given icon or the icon of the given appearance for [thing], and send it to any clients in target. + * Arguments: + * * thing - either a /icon object, or an object that has an appearance (atom, image, mutable_appearance). + * * target - either a reference to or a list of references to /client's or mobs with clients + * * icon_state - string to force a particular icon_state for the icon to be used + * * dir - dir number to force a particular direction for the icon to be used + * * frame - what frame of the icon_state's animation for the icon being used + * * moving - whether or not to use a moving state for the given icon + * * sourceonly - if TRUE, only generate the asset and send back the asset url, instead of tags that display the icon to players + * * extra_clases - string of extra css classes to use when returning the icon string + */ +/proc/icon2html(atom/thing, client/target, icon_state, dir = SOUTH, frame = 1, moving = FALSE, sourceonly = FALSE) if (!thing) return var/key - var/icon/I = thing + var/icon/icon2collapse = thing if (!target) return if (target == world) @@ -1196,9 +1286,13 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico targets = list(target) else targets = target - if (!targets.len) - return - if (!isicon(I)) + if(!length(targets)) + return + + //check if the given object is associated with a dmi file in the icons folder. if it is then we dont need to do a lot of work + //for asset generation to get around byond limitations + var/icon_path = get_icon_dmi_path(thing) + if (!isicon(icon2collapse)) if (isfile(thing)) //special snowflake var/name = SANITIZE_FILENAME("[generate_asset_name(thing)].png") SSassets.transport.register_asset(name, thing) @@ -1207,24 +1301,24 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico if(sourceonly) return SSassets.transport.get_asset_url(name) return "" - var/atom/A = thing - I = A.icon + //its either an atom, image, or mutable_appearance, we want its icon var + icon2collapse = thing.icon if (isnull(icon_state)) - icon_state = A.icon_state + icon_state = thing.icon_state - if (!(icon_state in icon_states(I, 1))) - icon_state = initial(A.icon_state) + if (isnull(icon_state) || thing.flags_1 & HTML_USE_INITAL_ICON_1) + icon_state = initial(thing.icon_state) if (isnull(dir)) - dir = initial(A.dir) + dir = initial(thing.dir) if (isnull(dir)) - dir = A.dir + dir = thing.dir if (ishuman(thing)) // Shitty workaround for a BYOND issue. - var/icon/temp = I - I = icon() - I.Insert(temp, dir = SOUTH) + var/icon/temp = icon2collapse + icon2collapse = icon() + icon2collapse.Insert(temp, dir = SOUTH) dir = SOUTH else if (isnull(dir)) @@ -1232,12 +1326,17 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico if (isnull(icon_state)) icon_state = "" - I = icon(I, icon_state, dir, frame, moving) + icon2collapse = icon(icon2collapse, icon_state, dir, frame, moving) + + var/list/name_and_ref = generate_and_hash_rsc_file(icon2collapse, icon_path)//pretend that tuples exist + + var/rsc_ref = name_and_ref[1] //weird object thats not even readable to the debugger, represents a reference to the icons rsc entry + var/file_hash = name_and_ref[2] + key = "[name_and_ref[3]].png" - key = "[generate_asset_name(I)].png" - SSassets.transport.register_asset(key, I) - for (var/thing2 in targets) - SSassets.transport.send_assets(thing2, key) + SSassets.transport.register_asset(key, rsc_ref, file_hash, icon_path) + for (var/client_target in targets) + SSassets.transport.send_assets(client_target, key) if(sourceonly) return SSassets.transport.get_asset_url(key) return "" diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index b9509333ce5..c0eeb456477 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -52,6 +52,7 @@ normalspeed = 1 explosion_block = 1 hud_possible = list(DIAG_AIRLOCK_HUD) + flags_1 = PREVENT_CLICK_UNDER_1 & HTML_USE_INITAL_ICON_1 var/allow_repaint = TRUE //Set to FALSE if the airlock should not be allowed to be repainted. FASTDMM_PROP(\ @@ -1071,6 +1072,33 @@ user.visible_message("[user] pins [C] to [src].", "You pin [C] to [src].") note = C update_icon() +<<<<<<< HEAD +======= + else if(HAS_TRAIT(C, TRAIT_DOOR_PRYER) && user.a_intent != INTENT_HARM) + if(isElectrified() && C?.siemens_coefficient) + shock(user,100) + + if(locked) + to_chat(user, "The bolts are down, it won't budge!") + return + + if(welded) + to_chat(user, "It's welded, it won't budge!") + return + + var/time_to_open = 5 + if(hasPower() && !prying_so_hard && density) + time_to_open = 50 + playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE) + prying_so_hard = TRUE + to_chat(user, "You begin prying open the airlock...") + if(do_after(user, time_to_open, TRUE, src)) + if(!open(2) && density) + to_chat(user, "Despite your attempts, [src] refuses to open.") + prying_so_hard = FALSE + if(!hasPower()) + INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2) +>>>>>>> 000e1cd18a... icon2html optimizations (#7610) else return ..() diff --git a/code/modules/asset_cache/asset_cache_item.dm b/code/modules/asset_cache/asset_cache_item.dm index a650a3c3afc..eb90ac37f81 100644 --- a/code/modules/asset_cache/asset_cache_item.dm +++ b/code/modules/asset_cache/asset_cache_item.dm @@ -4,9 +4,13 @@ * An internal datum containing info on items in the asset cache. Mainly used to cache md5 info for speed. */ /datum/asset_cache_item + /// the name of this asset item, becomes the key in SSassets.cache list var/name + /// md5() of the file this asset item represents. var/hash + /// the file this asset represents var/resource + /// our file extension e.g. .png, .gif, etc var/ext = "" /// Should this file alsobut be sent via the legacy browse_rsc system /// when cdn transports are enabled? @@ -21,10 +25,20 @@ /// TRUE for keeping local asset names when browse_rsc backend is used var/keep_local_name = FALSE -/datum/asset_cache_item/New(name, file) +///pass in a valid file_hash if you have one to save it from needing to do it again. +///pass in a valid dmi file path string e.g. "icons/path/to/dmi_file.dmi" to make generating the hash less expensive +/datum/asset_cache_item/New(name, file, file_hash, dmi_file_path) if (!isfile(file)) file = fcopy_rsc(file) - hash = md5(file) + + hash = file_hash + + //the given file is directly from a dmi file and is thus in the rsc already, we know that its file_hash will be correct + if(!hash) + if(dmi_file_path) + hash = md5(file) + else + hash = md5asfile(file) //icons sent to the rsc md5 incorrectly when theyre given incorrect data if (!hash) hash = md5(fcopy_rsc(file)) if (!hash) diff --git a/code/modules/asset_cache/transports/asset_transport.dm b/code/modules/asset_cache/transports/asset_transport.dm index f5a1af4f057..9f1073c9c9f 100644 --- a/code/modules/asset_cache/transports/asset_transport.dm +++ b/code/modules/asset_cache/transports/asset_transport.dm @@ -25,15 +25,21 @@ addtimer(CALLBACK(src, .proc/send_assets_slow, C, preload), 1 SECONDS) -/// Register a browser asset with the asset cache system -/// asset_name - the identifier of the asset -/// asset - the actual asset file (or an asset_cache_item datum) -/// returns a /datum/asset_cache_item. -/// mutiple calls to register the same asset under the same asset_name return the same datum -/datum/asset_transport/proc/register_asset(asset_name, asset) +/** + * Register a browser asset with the asset cache system. + * returns a /datum/asset_cache_item. + * mutiple calls to register the same asset under the same asset_name return the same datum. + * + * Arguments: + * * asset_name - the identifier of the asset. + * * asset - the actual asset file (or an asset_cache_item datum). + * * file_hash - optional, a hash of the contents of the asset files contents. used so asset_cache_item doesnt have to hash it again + * * dmi_file_path - optional, means that the given asset is from the rsc and thus we dont need to do some expensive operations + */ +/datum/asset_transport/proc/register_asset(asset_name, asset, file_hash, dmi_file_path) var/datum/asset_cache_item/ACI = asset if (!istype(ACI)) - ACI = new(asset_name, asset) + ACI = new(asset_name, asset, file_hash, dmi_file_path) if (!ACI || !ACI.hash) CRASH("ERROR: Invalid asset: [asset_name]:[asset]:[ACI]") if (SSassets.cache[asset_name])