From e007b3dcabcbf2e1f78493a7ce81bd76ac15df01 Mon Sep 17 00:00:00 2001 From: William Wallace Date: Wed, 6 May 2020 13:00:39 +0100 Subject: [PATCH] reduce amount of lists that exist during runtime for custom materials (#50832) --- code/controllers/subsystem/materials.dm | 22 ++++++++++++++++ code/game/atoms.dm | 26 +++++++------------ code/game/objects/items/stacks/stack.dm | 18 ++++++++----- code/game/objects/structures/signs/_signs.dm | 2 +- code/game/turfs/turf.dm | 10 ++----- .../mob/living/silicon/robot/robot_modules.dm | 2 +- .../boxes_magazines/_box_magazine.dm | 12 +++++---- .../modules/research/machinery/_production.dm | 2 +- 8 files changed, 54 insertions(+), 40 deletions(-) diff --git a/code/controllers/subsystem/materials.dm b/code/controllers/subsystem/materials.dm index 3ed9a26d1e8..a1cdd1566c4 100644 --- a/code/controllers/subsystem/materials.dm +++ b/code/controllers/subsystem/materials.dm @@ -14,6 +14,8 @@ SUBSYSTEM_DEF(materials) var/list/materials_by_category ///Dictionary of category || list of material types, mostly used by rnd machines like autolathes. var/list/materialtypes_by_category + ///A cache of all material combinations that have been used + var/list/list/material_combos ///List of stackcrafting recipes for materials using rigid materials var/list/rigid_stack_recipes = list( new /datum/stack_recipe("Chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), @@ -27,6 +29,7 @@ SUBSYSTEM_DEF(materials) materials = list() materials_by_category = list() materialtypes_by_category = list() + material_combos = list() for(var/type in subtypesof(/datum/material)) var/datum/material/ref = new type materials[type] = ref @@ -38,3 +41,22 @@ SUBSYSTEM_DEF(materials) if(!materials) InitializeMaterials() return materials[fakemat] || fakemat + +///Returns a list to be used as an object's custom_materials. Lists will be cached and re-used based on the parameters. +/datum/controller/subsystem/materials/proc/FindOrCreateMaterialCombo(list/materials_declaration, multiplier) + if(!material_combos) + InitializeMaterials() + var/list/combo_params = list() + for(var/x in materials_declaration) + var/datum/material/mat = x + var/path_name = ispath(mat) ? "[mat]" : "[mat.type]" + combo_params += "[path_name]=[materials_declaration[mat] * multiplier]" + sortTim(combo_params, /proc/cmp_text_asc) // We have to sort now in case the declaration was not in order + var/combo_index = combo_params.Join("-") + var/list/combo = material_combos[combo_index] + if(!combo) + combo = list() + for(var/mat in materials_declaration) + combo[GetMaterialRef(mat)] = materials_declaration[mat] * multiplier + material_combos[combo_index] = combo + return combo diff --git a/code/game/atoms.dm b/code/game/atoms.dm index c0a5e2ad0ae..99a742fde4a 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -79,6 +79,7 @@ var/rad_insulation = RAD_NO_INSULATION ///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.) + ///The list referenced by this var can be shared by multiple objects and should not be directly modified. Instead, use [set_custom_materials][/atom/proc/set_custom_materials]. var/list/custom_materials ///Bitfield for how the atom handles materials. var/material_flags = NONE @@ -185,12 +186,8 @@ if (canSmoothWith) canSmoothWith = typelist("canSmoothWith", canSmoothWith) - var/temp_list = list() - for(var/i in custom_materials) - temp_list[SSmaterials.GetMaterialRef(i)] = custom_materials[i] //Get the proper instanced version - - custom_materials = null //Null the list to prepare for applying the materials properly - set_custom_materials(temp_list) + // apply materials properly from the default custom_materials value + set_custom_materials(custom_materials) ComponentInitialize() @@ -1272,26 +1269,21 @@ ///Sets the custom materials for an item. /atom/proc/set_custom_materials(list/materials, multiplier = 1) - - if(!materials) - materials = custom_materials - if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways for(var/i in custom_materials) var/datum/material/custom_material = SSmaterials.GetMaterialRef(i) custom_material.on_removed(src, material_flags) //Remove the current materials if(!length(materials)) + custom_materials = null return - custom_materials = list() //Reset the list + if(!(material_flags & MATERIAL_NO_EFFECTS)) + for(var/x in materials) + var/datum/material/custom_material = SSmaterials.GetMaterialRef(x) + custom_material.on_applied(src, materials[x] * multiplier * material_modifier, material_flags) - for(var/x in materials) - var/datum/material/custom_material = SSmaterials.GetMaterialRef(x) - - if(!(material_flags & MATERIAL_NO_EFFECTS)) - custom_material.on_applied(src, materials[custom_material] * multiplier * material_modifier, material_flags) - custom_materials[custom_material] += materials[x] * multiplier + custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier) /** * Returns true if this atom has gravity for the passed in turf diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 0b079b99158..b9f7c8670db 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -320,10 +320,13 @@ if (amount < used) return FALSE amount -= used - if(check) - zero_amount() - for(var/i in mats_per_unit) - custom_materials[i] = amount * mats_per_unit[i] + if(check && zero_amount()) + return FALSE + if(length(mats_per_unit)) + var/temp_materials = custom_materials.Copy() + for(var/i in mats_per_unit) + temp_materials[i] = mats_per_unit[i] * src.amount + set_custom_materials(temp_materials) update_icon() update_weight() return TRUE @@ -355,10 +358,11 @@ source.add_charge(amount * cost) else src.amount += amount - if(mats_per_unit && mats_per_unit.len) + if(length(mats_per_unit)) + var/temp_materials = custom_materials.Copy() for(var/i in mats_per_unit) - custom_materials[i] = mats_per_unit[i] * src.amount - set_custom_materials() //Refresh + temp_materials[i] = mats_per_unit[i] * src.amount + set_custom_materials(temp_materials) update_icon() update_weight() diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index 2836dbcf50d..e1bdd57ee18 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -84,7 +84,7 @@ unwrenched_sign.desc = "[desc] It can be placed on a wall." unwrenched_sign.icon_state = icon_state unwrenched_sign.sign_path = type - unwrenched_sign.custom_materials = custom_materials //This is here so picture frames and wooden things don't get messed up. + unwrenched_sign.set_custom_materials(custom_materials) //This is here so picture frames and wooden things don't get messed up. unwrenched_sign.is_editable = is_editable unwrenched_sign.obj_integrity = obj_integrity //Transfer how damaged it is. unwrenched_sign.setDir(dir) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 8d5140a50a8..193ea19eb39 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -89,14 +89,8 @@ GLOBAL_LIST_EMPTY(station_turfs) if (opacity) has_opaque_atom = TRUE - if(custom_materials) - - var/temp_list = list() - for(var/i in custom_materials) - temp_list[SSmaterials.GetMaterialRef(i)] = custom_materials[i] //Get the proper instanced version - - custom_materials = null //Null the list to prepare for applying the materials properly - set_custom_materials(temp_list) + // apply materials properly from the default custom_materials value + set_custom_materials(custom_materials) ComponentInitialize() diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index e4175c26a8c..5b5a64716ae 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -113,7 +113,7 @@ S.source = get_or_create_estorage(/datum/robot_energy_storage/pipe_cleaner) if(S && S.source) - S.custom_materials = null + S.set_custom_materials(null) S.is_cyborg = 1 if(I.loc != src) diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm index 3311212cd9b..d80821ebba2 100644 --- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm +++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm @@ -130,11 +130,13 @@ if(AMMO_BOX_FULL_EMPTY) icon_state = "[initial(icon_state)]-[shells_left ? "[max_ammo]" : "0"]" desc = "[initial(desc)] There [(shells_left == 1) ? "is" : "are"] [shells_left] shell\s left!" - for (var/material in bullet_cost) - var/material_amount = bullet_cost[material] - material_amount = (material_amount*stored_ammo.len) + base_cost[material] - custom_materials[material] = material_amount - set_custom_materials(custom_materials)//make sure we setup the correct properties again + if(length(bullet_cost)) + var/temp_materials = custom_materials.Copy() + for (var/material in bullet_cost) + var/material_amount = bullet_cost[material] + material_amount = (material_amount*stored_ammo.len) + base_cost[material] + temp_materials[material] = material_amount + set_custom_materials(temp_materials) ///Count of number of bullets in the magazine /obj/item/ammo_box/magazine/proc/ammo_count(countempties = TRUE) diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index b8848c40a4b..d1b7a9f0ef3 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -93,7 +93,7 @@ var/obj/item/I = new path(get_turf(src)) if(efficient_with(I.type)) I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this. - I.set_custom_materials(matlist.Copy()) + I.set_custom_materials(matlist) SSblackbox.record_feedback("nested tally", "item_printed", amount, list("[type]", "[path]")) /obj/machinery/rnd/production/proc/check_mat(datum/design/being_built, var/mat) // now returns how many times the item can be built with the material