From 14fed02701166a154489f487d52f3831a2373f69 Mon Sep 17 00:00:00 2001 From: CHOMPStation2StaffMirrorBot <94713762+CHOMPStation2StaffMirrorBot@users.noreply.github.com> Date: Sat, 16 Aug 2025 12:05:13 -0700 Subject: [PATCH] [MIRROR] Increased cached_icon_states usage and tweaks to unit testing (#11445) Co-authored-by: Drathek <76988376+Drulikar@users.noreply.github.com> --- code/_helpers/icons.dm | 10 +- code/_helpers/icons/flatten.dm | 2 +- code/controllers/subsystems/robot_sprites.dm | 2 +- code/game/mecha/mecha_appearance.dm | 2 +- code/game/objects/items/magazine.dm | 3 +- code/modules/asset_cache/asset_list.dm | 4 +- .../asset_cache/assets/research_designs.dm | 2 +- .../assets/spritesheets/vending.dm | 2 +- code/modules/clothing/clothing.dm | 2 +- code/modules/persistence/graffiti.dm | 8 +- code/modules/unit_tests/cosmetic_tests.dm | 62 +++--- code/modules/unit_tests/robot_tests.dm | 195 +++++++++--------- code/modules/unit_tests/spritesheets.dm | 11 +- code/modules/vore/eating/belly_import.dm | 4 +- .../panel_databackend/vorepanel_vore_data.dm | 4 +- 15 files changed, 160 insertions(+), 153 deletions(-) diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index 9351f87afc..ffe2a0d514 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -368,18 +368,22 @@ return composite GLOBAL_LIST_EMPTY(icon_state_lists) -/proc/cached_icon_states(var/icon/I) +/// Gets the cached icon_state for the provided icon (only cached if its a file). +/// mode=0 will only show the sub-states ("open 0,0" and so on) +/// mode=1 will show the main state names ("open") +/// mode=2 will show all of the states +/proc/cached_icon_states(icon/I, mode=1) if(!I) return list() var/key = I var/returnlist = GLOB.icon_state_lists[key] if(!returnlist) - returnlist = icon_states(I) + returnlist = icon_states(I, mode) if(isfile(I)) // It's something that will stick around GLOB.icon_state_lists[key] = returnlist return returnlist -/proc/expire_states_cache(var/key) +/proc/expire_states_cache(key) if(GLOB.icon_state_lists[key]) GLOB.icon_state_lists -= key return TRUE diff --git a/code/_helpers/icons/flatten.dm b/code/_helpers/icons/flatten.dm index e92fb896fb..36bd29d628 100644 --- a/code/_helpers/icons/flatten.dm +++ b/code/_helpers/icons/flatten.dm @@ -72,7 +72,7 @@ var/state = A.icon_state var/none = !icon if(!none) - var/list/states = icon_states(icon) + var/list/states = cached_icon_states(icon) if(!(state in states)) if(!("" in states)) none = TRUE diff --git a/code/controllers/subsystems/robot_sprites.dm b/code/controllers/subsystems/robot_sprites.dm index 0f45639d67..3d518d4133 100644 --- a/code/controllers/subsystems/robot_sprites.dm +++ b/code/controllers/subsystems/robot_sprites.dm @@ -141,7 +141,7 @@ SUBSYSTEM_DEF(robot_sprites) RS.icon_x = text2num(splitted[1]) RS.icon_y = text2num(splitted[2]) RS.vis_height = text2num(splitted[2]) - var/list/icon_states = icon_states(RS.sprite_icon) + var/list/icon_states = cached_icon_states(RS.sprite_icon) for(var/icon in icon_states) // testing whitelist functionality ckey-... if(findtext(icon, regex("ckey-"))) diff --git a/code/game/mecha/mecha_appearance.dm b/code/game/mecha/mecha_appearance.dm index 5136ef070b..4e779409c0 100644 --- a/code/game/mecha/mecha_appearance.dm +++ b/code/game/mecha/mecha_appearance.dm @@ -40,7 +40,7 @@ var/icon/Cutter - if("[initial_icon]_cutter" in icon_states(icon)) + if("[initial_icon]_cutter" in cached_icon_states(icon)) Cutter = new(src.icon, "[initial_icon]_cutter") if(Cutter) diff --git a/code/game/objects/items/magazine.dm b/code/game/objects/items/magazine.dm index dcbee8327b..6da89532e5 100644 --- a/code/game/objects/items/magazine.dm +++ b/code/game/objects/items/magazine.dm @@ -5,7 +5,6 @@ icon_state = "magazine" var/headline - var/static/list/tabloid_states = icon_states('icons/obj/magazine.dmi') var/static/list/tabloid_publishers = list( "\improper Solar Enquirer", "\improper Stellar Examiner", @@ -76,7 +75,7 @@ pixel_x = 5-rand(10) pixel_x = 5-rand(10) - icon_state = pick(tabloid_states) + icon_state = pick(cached_icon_states('icons/obj/magazine.dmi')) headline = pick(tabloid_headlines) name = pick(tabloid_publishers) diff --git a/code/modules/asset_cache/asset_list.dm b/code/modules/asset_cache/asset_list.dm index 69976d0cc9..fc5c1e9b1e 100644 --- a/code/modules/asset_cache/asset_list.dm +++ b/code/modules/asset_cache/asset_list.dm @@ -440,7 +440,7 @@ GLOBAL_LIST_EMPTY(asset_datums) /datum/asset/spritesheet/proc/queuedInsert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE) I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving) - if(!I || !length(icon_states(I))) // that direction or state doesn't exist + if(!I || !length(cached_icon_states(I))) // that direction or state doesn't exist return var/size_id = "[I.Width()]x[I.Height()]" var/size = sizes[size_id] @@ -476,7 +476,7 @@ GLOBAL_LIST_EMPTY(asset_datums) if(!directions) directions = list(SOUTH) - for(var/icon_state_name in icon_states(I)) + for(var/icon_state_name in cached_icon_states(I)) for(var/direction in directions) var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]-" : "" Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction) diff --git a/code/modules/asset_cache/assets/research_designs.dm b/code/modules/asset_cache/assets/research_designs.dm index 5a9dc19037..fd1bf1db9f 100644 --- a/code/modules/asset_cache/assets/research_designs.dm +++ b/code/modules/asset_cache/assets/research_designs.dm @@ -58,7 +58,7 @@ var/obj/machinery/computer/C = item var/screen = initial(C.icon_screen) var/keyboard = initial(C.icon_keyboard) - var/all_states = icon_states(icon_file) + var/all_states = cached_icon_states(icon_file) if (screen && (screen in all_states)) transform.blend_icon(uni_icon(icon_file, screen), ICON_OVERLAY) if (keyboard && (keyboard in all_states)) diff --git a/code/modules/asset_cache/assets/spritesheets/vending.dm b/code/modules/asset_cache/assets/spritesheets/vending.dm index 7a24d3a9fc..b8ad946d82 100644 --- a/code/modules/asset_cache/assets/spritesheets/vending.dm +++ b/code/modules/asset_cache/assets/spritesheets/vending.dm @@ -22,7 +22,7 @@ var/datum/universal_icon/I - var/icon_states_list = icon_states(icon_file) + var/icon_states_list = cached_icon_states(icon_file) if(icon_state in icon_states_list) I = uni_icon(icon_file, icon_state, SOUTH) var/c = initial(item.color) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index a53111c152..63bb0fbe13 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -1376,7 +1376,7 @@ // only override icon if a corresponding digitigrade replacement icon_state exists // otherwise, keep the old non-digi icon_define (or nothing) - if(icon_state && icon_states(update_icon_define_digi)?.Find(icon_state)) + if(icon_state && cached_icon_states(update_icon_define_digi):Find(icon_state)) update_icon_define = update_icon_define_digi diff --git a/code/modules/persistence/graffiti.dm b/code/modules/persistence/graffiti.dm index c5ab1cae8c..435f2974a8 100644 --- a/code/modules/persistence/graffiti.dm +++ b/code/modules/persistence/graffiti.dm @@ -25,10 +25,10 @@ author = _author /obj/effect/decal/writing/Initialize(mapload) - var/list/random_icon_states = icon_states(icon) - for(var/obj/effect/decal/writing/W in loc) - random_icon_states.Remove(W.icon_state) - if(random_icon_states.len) + var/list/random_icon_states = cached_icon_states(icon) + for(var/obj/effect/decal/writing/writing in loc) + random_icon_states.Remove(writing.icon_state) + if(length(random_icon_states)) icon_state = pick(random_icon_states) if(!mapload || !CONFIG_GET(flag/persistence_ignore_mapload)) SSpersistence.track_value(src, /datum/persistent/graffiti) diff --git a/code/modules/unit_tests/cosmetic_tests.dm b/code/modules/unit_tests/cosmetic_tests.dm index ef60de0217..a6f940a92d 100644 --- a/code/modules/unit_tests/cosmetic_tests.dm +++ b/code/modules/unit_tests/cosmetic_tests.dm @@ -13,48 +13,44 @@ validate_accessory_list(/datum/sprite_accessory/tail) validate_accessory_list(/datum/sprite_accessory/wing) -/datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_accessory_list(var/path) +/datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_accessory_list(path) var/list/collection = list() - for(var/SP in subtypesof(path)) - var/datum/sprite_accessory/A = new SP() - TEST_ASSERT(A, "[SP]: Cosmetic - Path resolved to null in list.") - if(!A) + for(var/datum/sprite_accessory/accessory as anything in subtypesof(path)) + if(accessory::name == DEVELOPER_WARNING_NAME) continue - TEST_ASSERT(A.name, "[A] - [A.type]: Cosmetic - Missing name.") + TEST_ASSERT(accessory::name, "[accessory::name] - [accessory::type]: Cosmetic - Missing name.") - if(A.name == DEVELOPER_WARNING_NAME) - continue + TEST_ASSERT(!collection[accessory::name], "[accessory::name] - [accessory::type]: Cosmetic - Name defined twice. Original def [collection[accessory::name]]") + if(!collection[accessory::name]) + collection[accessory::name] = accessory::type - TEST_ASSERT(!collection[A.name], "[A] - [A.type]: Cosmetic - Name defined twice. Original def [collection[A.name]]") - if(!collection[A.name]) - collection[A.name] = A.type - - if(istype(A,text2path("[path]/invisible"))) - TEST_ASSERT(!A.icon_state, "[A] - [A.type]: Cosmetic - Invisible subtype has icon_state.") - else if(!A.icon_state) - TEST_ASSERT(A.icon_state, "[A] - [A.type]: Cosmetic - Has no icon_state.") + if(ispath(accessory, text2path("[path]/invisible"))) + TEST_ASSERT(!accessory::icon_state, "[accessory::name] - [accessory::type]: Cosmetic - Invisible subtype has icon_state.") + else if(!accessory::icon_state) + TEST_FAIL("[accessory::name] - [accessory::type]: Cosmetic - Has no icon_state.") else // Check if valid icon - validate_icons(A) + validate_icons(accessory) - qdel(A) +/datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_icons(datum/sprite_accessory/accessory) + var/actual_icon_state = accessory::icon_state -/datum/unit_test/sprite_accessories_shall_be_unique/proc/validate_icons(datum/sprite_accessory/A) - var/actual_icon_state = A.icon_state + if(istype(accessory, /datum/sprite_accessory/hair)) + actual_icon_state += "_s" + TEST_ASSERT(actual_icon_state in cached_icon_states(accessory::icon), "[accessory::name] - [accessory::type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [accessory::icon].") + return - if(istype(A,/datum/sprite_accessory/hair)) - actual_icon_state = "[A.icon_state]_s" - TEST_ASSERT(actual_icon_state in cached_icon_states(A.icon), "[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].") + if(istype(accessory, /datum/sprite_accessory/facial_hair)) + actual_icon_state += "_s" + TEST_ASSERT(actual_icon_state in cached_icon_states(accessory::icon), "[accessory::name] - [accessory::type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [accessory::icon].") + return - if(istype(A,/datum/sprite_accessory/facial_hair)) - actual_icon_state = "[A.icon_state]_s" - TEST_ASSERT(actual_icon_state in cached_icon_states(A.icon), "[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].") + if(istype(accessory, /datum/sprite_accessory/marking)) + var/datum/sprite_accessory/marking/marking = accessory + for(var/body_part in marking.body_parts) + TEST_ASSERT(body_part in BP_ALL, "[accessory::name] - [accessory::type]: Cosmetic - Has an illegal bodypart \"[body_part]\". ONLY use parts listed in BP_ALL.") - if(istype(A,/datum/sprite_accessory/marking)) - var/datum/sprite_accessory/marking/MA = A - for(var/BP in MA.body_parts) - TEST_ASSERT(BP in BP_ALL, "[A] - [A.type]: Cosmetic - Has an illegal bodypart \"[BP]\". ONLY use parts listed in BP_ALL.") - - actual_icon_state = "[A.icon_state]-[BP]" - TEST_ASSERT(actual_icon_state in cached_icon_states(A.icon), "[A] - [A.type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [A.icon].") + actual_icon_state = "[accessory::icon_state]-[body_part]" + TEST_ASSERT(actual_icon_state in cached_icon_states(accessory::icon), "[accessory::name] - [accessory::type]: Cosmetic - Icon_state \"[actual_icon_state]\" is not present in [accessory::icon].") + return diff --git a/code/modules/unit_tests/robot_tests.dm b/code/modules/unit_tests/robot_tests.dm index c7f4a4776e..e8d25ec071 100644 --- a/code/modules/unit_tests/robot_tests.dm +++ b/code/modules/unit_tests/robot_tests.dm @@ -6,15 +6,16 @@ var/failed = 0 /datum/unit_test/all_robot_sprites_must_be_valid/Run() - for(var/sprite in subtypesof(/datum/robot_sprite)) - var/datum/robot_sprite/RS = new sprite() - if(!RS.name) // Parent type, ignore me + for(var/datum/robot_sprite/robot_type as anything in subtypesof(/datum/robot_sprite)) + if(!robot_type::name) // Parent type, ignore me continue - TEST_ASSERT(RS.sprite_icon, "[RS.type]: Robots - Robot sprite \"[RS.name]\", missing sprite_icon.") - if(!RS.sprite_icon) + if(!robot_type::sprite_icon) + TEST_FAIL("[robot_type]: Robots - Robot sprite \"[robot_type::name]\", missing sprite_icon.") continue + var/datum/robot_sprite/robot = new robot_type() + var/list/checks = list( "[ROBOT_HAS_SPEED_SPRITE]" = "-roll", "[ROBOT_HAS_SHIELD_SPRITE]" = "-shield", @@ -27,143 +28,143 @@ "[ROBOT_HAS_TASER_SPRITE]" = "-taser", "[ROBOT_HAS_DISABLER_SPRITE]" = "-disabler" ) - for(var/C in checks) - if(RS.sprite_flag_check(text2num(C))) - check_state(RS,checks[C]) + for(var/check in checks) + if(robot.sprite_flag_check(text2num(check))) + check_state(robot,checks[check]) // eyes, lights, markings - if(RS.has_eye_sprites) - check_state(RS,"-eyes") - if(RS.has_eye_light_sprites) - check_state(RS,"-lights") - if(LAZYLEN(RS.sprite_decals)) - for(var/decal in RS.sprite_decals) - check_state(RS,"-[decal]") - if(LAZYLEN(RS.sprite_animations)) - for(var/animation in RS.sprite_animations) - check_state(RS,"-[animation]") + if(robot.has_eye_sprites) + check_state(robot,"-eyes") + if(robot.has_eye_light_sprites) + check_state(robot,"-lights") + if(LAZYLEN(robot.sprite_decals)) + for(var/decal in robot.sprite_decals) + check_state(robot,"-[decal]") + if(LAZYLEN(robot.sprite_animations)) + for(var/animation in robot.sprite_animations) + check_state(robot,"-[animation]") // Control panel - if(RS.has_custom_open_sprites) - check_state(RS,"-openpanel_nc") - check_state(RS,"-openpanel_c") - check_state(RS,"-openpanel_w") + if(robot.has_custom_open_sprites) + check_state(robot,"-openpanel_nc") + check_state(robot,"-openpanel_c") + check_state(robot,"-openpanel_w") // Glow State - if(RS.has_glow_sprites) - check_state(RS,"-glow") + if(robot.has_glow_sprites) + check_state(robot,"-glow") // Bellies - if(RS.has_vore_belly_sprites && !RS.belly_capacity_list) - if(RS.has_sleeper_light_indicator) + if(robot.has_vore_belly_sprites && !robot.belly_capacity_list) + if(robot.has_sleeper_light_indicator) // belly r/g light - check_state(RS,"-sleeper-r") - check_state(RS,"-sleeper-g") - if(RS.has_vore_belly_resting_sprites) - for(var/rest_style in RS.rest_sprite_options) + check_state(robot,"-sleeper-r") + check_state(robot,"-sleeper-g") + if(robot.has_vore_belly_resting_sprites) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-sleeper-r-[rest_style]") - check_state(RS,"-sleeper-g-[rest_style]") + check_state(robot,"-sleeper-r-[rest_style]") + check_state(robot,"-sleeper-g-[rest_style]") // struggling - if(RS.has_vore_struggle_sprite) - check_state(RS,"-sleeper-r-struggle") - check_state(RS,"-sleeper-g-struggle") - if(RS.has_vore_belly_resting_sprites) - for(var/rest_style in RS.rest_sprite_options) + if(robot.has_vore_struggle_sprite) + check_state(robot,"-sleeper-r-struggle") + check_state(robot,"-sleeper-g-struggle") + if(robot.has_vore_belly_resting_sprites) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-sleeper-r-[rest_style]-struggle") - check_state(RS,"-sleeper-g-[rest_style]-struggle") + check_state(robot,"-sleeper-r-[rest_style]-struggle") + check_state(robot,"-sleeper-g-[rest_style]-struggle") else // belly - check_state(RS,"-sleeper") - if(RS.has_vore_belly_resting_sprites) - for(var/rest_style in RS.rest_sprite_options) + check_state(robot,"-sleeper") + if(robot.has_vore_belly_resting_sprites) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-sleeper-[rest_style]") + check_state(robot,"-sleeper-[rest_style]") // struggling - if(RS.has_vore_struggle_sprite) - check_state(RS,"-sleeper-struggle") - if(RS.has_vore_belly_resting_sprites) - for(var/rest_style in RS.rest_sprite_options) + if(robot.has_vore_struggle_sprite) + check_state(robot,"-sleeper-struggle") + if(robot.has_vore_belly_resting_sprites) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-sleeper-[rest_style]-struggle") - else if (RS.belly_capacity_list) - for(var/belly in RS.belly_capacity_list) - for(var/num = 1 to RS.belly_capacity_list[belly]) + check_state(robot,"-sleeper-[rest_style]-struggle") + else if(robot.belly_capacity_list) + for(var/belly in robot.belly_capacity_list) + for(var/num = 1 to robot.belly_capacity_list[belly]) // big belly - check_state(RS,"-[belly]-[num]") - if(RS.has_vore_belly_resting_sprites) - for(var/rest_style in RS.rest_sprite_options) + check_state(robot,"-[belly]-[num]") + if(robot.has_vore_belly_resting_sprites) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-[belly]-[num]-[rest_style]") + check_state(robot,"-[belly]-[num]-[rest_style]") // struggling - if(RS.has_vore_struggle_sprite) - check_state(RS,"-[belly]-[num]-struggle") - if(RS.has_vore_belly_resting_sprites) - for(var/rest_style in RS.rest_sprite_options) + if(robot.has_vore_struggle_sprite) + check_state(robot,"-[belly]-[num]-struggle") + if(robot.has_vore_belly_resting_sprites) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-[belly]-[num]-[rest_style]-struggle") - if(RS.belly_light_list) - for(var/belly in RS.belly_light_list) - for(var/num = 1 to RS.belly_light_list[belly]) + check_state(robot,"-[belly]-[num]-[rest_style]-struggle") + if(robot.belly_light_list) + for(var/belly in robot.belly_light_list) + for(var/num = 1 to robot.belly_light_list[belly]) // multi belly r/g light - check_state(RS,"-[belly]-[num]-r") - check_state(RS,"-[belly]-[num]-g") - if(RS.has_vore_belly_resting_sprites) - for(var/rest_style in RS.rest_sprite_options) + check_state(robot,"-[belly]-[num]-r") + check_state(robot,"-[belly]-[num]-g") + if(robot.has_vore_belly_resting_sprites) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-[belly]-[num]-r-[rest_style]") - check_state(RS,"-[belly]-[num]-g-[rest_style]") + check_state(robot,"-[belly]-[num]-r-[rest_style]") + check_state(robot,"-[belly]-[num]-g-[rest_style]") // struggling - if(RS.has_vore_struggle_sprite) - check_state(RS,"-[belly]-[num]-r-struggle") - check_state(RS,"-[belly]-[num]-g-struggle") - if(RS.has_vore_belly_resting_sprites) - for(var/rest_style in RS.rest_sprite_options) + if(robot.has_vore_struggle_sprite) + check_state(robot,"-[belly]-[num]-r-struggle") + check_state(robot,"-[belly]-[num]-g-struggle") + if(robot.has_vore_belly_resting_sprites) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-[belly]-[num]-r-[rest_style]-struggle") - check_state(RS,"-[belly]-[num]-g-[rest_style]-struggle") + check_state(robot,"-[belly]-[num]-r-[rest_style]-struggle") + check_state(robot,"-[belly]-[num]-g-[rest_style]-struggle") // reseting - for(var/rest_style in RS.rest_sprite_options) + for(var/rest_style in robot.rest_sprite_options) rest_style = lowertext(rest_style) if(rest_style == "default") rest_style = "rest" - check_state(RS,"-[rest_style]") - if(RS.has_glow_sprites) - check_state(RS,"-[rest_style]-glow") - if(RS.has_rest_lights_sprites) - check_state(RS,"-[rest_style]-lights") - if(RS.has_rest_eyes_sprites) - check_state(RS,"-[rest_style]-eyes") + check_state(robot,"-[rest_style]") + if(robot.has_glow_sprites) + check_state(robot,"-[rest_style]-glow") + if(robot.has_rest_lights_sprites) + check_state(robot,"-[rest_style]-lights") + if(robot.has_rest_eyes_sprites) + check_state(robot,"-[rest_style]-eyes") // death - if(RS.has_dead_sprite) - check_state(RS,"-wreck") - if(RS.has_dead_sprite_overlay) // Only one per dmi - TEST_ASSERT("wreck-overlay" in cached_icon_states(RS.sprite_icon), "[RS.type]: Robots - Robot sprite \"[RS.name]\", missing icon_state wreck-overlay, in dmi \"[RS.sprite_icon]\".") + if(robot.has_dead_sprite) + check_state(robot,"-wreck") + if(robot.has_dead_sprite_overlay) // Only one per dmi + TEST_ASSERT("wreck-overlay" in cached_icon_states(robot.sprite_icon), "[robot.type]: Robots - Robot sprite \"[robot.name]\", missing icon_state wreck-overlay, in dmi \"[robot.sprite_icon]\".") // offset - var/icon/I = new(RS.sprite_icon) - TEST_ASSERT_EQUAL(RS.icon_x, I.Width(), "[RS.type]: Robots - Robot sprite \"[RS.name]\", icon_x \"[RS.icon_x]\" did not match dmi configured width \"[I.Width()]\"") - TEST_ASSERT_EQUAL(RS.icon_y, I.Height(), "[RS.type]: Robots - Robot sprite \"[RS.name]\", icon_y \"[RS.icon_y]\" did not match dmi configured height \"[I.Height()]\"") - TEST_ASSERT_EQUAL(RS.icon_y, RS.vis_height, "[RS.type]: Robots - Robot sprite \"[RS.name]\", vis_height \"[RS.vis_height]\" did not match icon_y \"[RS.icon_y]\"") + var/icon/I = new(robot.sprite_icon) + TEST_ASSERT_EQUAL(robot.icon_x, I.Width(), "[robot.type]: Robots - Robot sprite \"[robot.name]\", icon_x \"[robot.icon_x]\" did not match dmi configured width \"[I.Width()]\"") + TEST_ASSERT_EQUAL(robot.icon_y, I.Height(), "[robot.type]: Robots - Robot sprite \"[robot.name]\", icon_y \"[robot.icon_y]\" did not match dmi configured height \"[I.Height()]\"") + TEST_ASSERT_EQUAL(robot.icon_y, robot.vis_height, "[robot.type]: Robots - Robot sprite \"[robot.name]\", vis_height \"[robot.vis_height]\" did not match icon_y \"[robot.icon_y]\"") var/legal_offset = (I.Width() - world.icon_size) / 2 - TEST_ASSERT_EQUAL(RS.pixel_x, -legal_offset, "[RS.type]: Robots - Robot sprite \"[RS.name]\", pixel_x \"[RS.pixel_x]\" did not have correct offset, should be \"[-legal_offset]\"") + TEST_ASSERT_EQUAL(robot.pixel_x, -legal_offset, "[robot.type]: Robots - Robot sprite \"[robot.name]\", pixel_x \"[robot.pixel_x]\" did not have correct offset, should be \"[-legal_offset]\"") qdel(I) - qdel(RS) + qdel(robot) -/datum/unit_test/all_robot_sprites_must_be_valid/proc/check_state(datum/robot_sprite/RS, append) - var/check_state = "[RS.sprite_icon_state][append]" - TEST_ASSERT(check_state in cached_icon_states(RS.sprite_icon), "[RS.type]: Robots - Robot sprite \"[RS.name]\", enabled but missing icon_state \"[check_state]\", in dmi \"[RS.sprite_icon]\".") +/datum/unit_test/all_robot_sprites_must_be_valid/proc/check_state(datum/robot_sprite/robot, append) + var/check_state = "[robot.sprite_icon_state][append]" + TEST_ASSERT(check_state in cached_icon_states(robot.sprite_icon), "[robot.type]: Robots - Robot sprite \"[robot.name]\", enabled but missing icon_state \"[check_state]\", in dmi \"[robot.sprite_icon]\".") diff --git a/code/modules/unit_tests/spritesheets.dm b/code/modules/unit_tests/spritesheets.dm index 16666dac17..eeec51fab6 100644 --- a/code/modules/unit_tests/spritesheets.dm +++ b/code/modules/unit_tests/spritesheets.dm @@ -2,23 +2,30 @@ /datum/unit_test/spritesheets /datum/unit_test/spritesheets/Run() + var/regex/valid_css_class = new(@"^([\l_][\w\-]|[\l_\-][\l_])") for(var/datum/asset/spritesheet/sheet as anything in subtypesof(/datum/asset/spritesheet)) if(!initial(sheet.name)) //Ignore abstract types continue - if (sheet == initial(sheet._abstract)) + if(sheet == initial(sheet._abstract)) continue sheet = get_asset_datum(sheet) for(var/sprite_name in sheet.sprites) if(!sprite_name) TEST_FAIL("Spritesheet [sheet.type] has a nameless icon state.") + if(!valid_css_class.Find(sprite_name)) + // https://www.w3.org/TR/CSS2/syndata.html#value-def-identifier + TEST_FAIL("Spritesheet [sheet.type] has a icon state that doesn't comply with css standards: '[sprite_name]'.") // Test IconForge generated sheets as well for(var/datum/asset/spritesheet_batched/sheet as anything in subtypesof(/datum/asset/spritesheet_batched)) if(!initial(sheet.name)) //Ignore abstract types continue - if (sheet == initial(sheet._abstract)) + if(sheet == initial(sheet._abstract)) continue sheet = get_asset_datum(sheet) for(var/sprite_name in sheet.sprites) if(!sprite_name) TEST_FAIL("Spritesheet [sheet.type] has a nameless icon state.") + if(!valid_css_class.Find(sprite_name)) + // https://www.w3.org/TR/CSS2/syndata.html#value-def-identifier + TEST_FAIL("Spritesheet [sheet.type] has a icon state that doesn't comply with css standards: '[sprite_name]'.") diff --git a/code/modules/vore/eating/belly_import.dm b/code/modules/vore/eating/belly_import.dm index daec2fb835..500a38b441 100644 --- a/code/modules/vore/eating/belly_import.dm +++ b/code/modules/vore/eating/belly_import.dm @@ -835,9 +835,9 @@ if(new_disable_hud == 1) new_belly.disable_hud = TRUE - var/possible_fullscreens = icon_states('icons/mob/screen_full_vore_list.dmi') + var/possible_fullscreens = cached_icon_states('icons/mob/screen_full_vore_list.dmi') if(!new_belly.colorization_enabled) - possible_fullscreens = icon_states('icons/mob/screen_full_vore.dmi') + possible_fullscreens = cached_icon_states('icons/mob/screen_full_vore.dmi') if(!(new_belly.belly_fullscreen in possible_fullscreens)) new_belly.belly_fullscreen = "" diff --git a/code/modules/vore/eating/panel_databackend/vorepanel_vore_data.dm b/code/modules/vore/eating/panel_databackend/vorepanel_vore_data.dm index 2bc1a5fdfb..2f068804eb 100644 --- a/code/modules/vore/eating/panel_databackend/vorepanel_vore_data.dm +++ b/code/modules/vore/eating/panel_databackend/vorepanel_vore_data.dm @@ -225,9 +225,9 @@ ) var/list/belly_fullscreens if(selected.colorization_enabled) - belly_fullscreens = icon_states('icons/mob/screen_full_vore_list.dmi') //Makes any icons inside of here selectable. + belly_fullscreens = cached_icon_states('icons/mob/screen_full_vore_list.dmi') //Makes any icons inside of here selectable. else - belly_fullscreens = icon_states('icons/mob/screen_full_vore.dmi') //Non colorable + belly_fullscreens = cached_icon_states('icons/mob/screen_full_vore.dmi') //Non colorable var/list/vs_flags = list() for(var/flag_name in selected.vore_sprite_flag_list)