From 926bc8b7d4060a034058e82986faf8929e91ce7e Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Thu, 2 Mar 2023 04:38:40 -0800 Subject: [PATCH] cache valid materials on world load --- plugins/buildingplan/buildingplan.cpp | 58 ++++++++++++++++++++++++--- plugins/lua/buildingplan.lua | 2 + 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/plugins/buildingplan/buildingplan.cpp b/plugins/buildingplan/buildingplan.cpp index 43f15ff5d..476d1863d 100644 --- a/plugins/buildingplan/buildingplan.cpp +++ b/plugins/buildingplan/buildingplan.cpp @@ -52,6 +52,7 @@ void set_config_bool(PersistentDataItem &c, int index, bool value) { static PersistentDataItem config; // for use in counting available materials for the UI +static vector mat_cache; static unordered_map, BuildingTypeKeyHash> job_item_cache; static unordered_map cur_heat_safety; static unordered_map cur_item_filters; @@ -142,6 +143,47 @@ static const vector & get_job_items(color_ostream &out, Bu return jitems; } +static void cache_matched(int16_t type, int32_t index) { + static const df::dfhack_material_category building_material_categories( + df::dfhack_material_category::mask_glass | + df::dfhack_material_category::mask_metal | + df::dfhack_material_category::mask_soap | + df::dfhack_material_category::mask_stone | + df::dfhack_material_category::mask_wood + ); + + MaterialInfo mi; + mi.decode(type, index); + if (mi.matches(building_material_categories)) { + DEBUG(status).print("cached material: %s\n", mi.toString().c_str()); + mat_cache.emplace_back(mi); + } + else + TRACE(status).print("not matched: %s\n", mi.toString().c_str()); +} + +static void load_material_cache() { + df::world_raws &raws = world->raws; + for (int i = 1; i < DFHack::MaterialInfo::NUM_BUILTIN; ++i) + if (raws.mat_table.builtin[i]) + cache_matched(i, -1); + + for (size_t i = 0; i < raws.inorganics.size(); i++) + cache_matched(0, i); + + for (size_t i = 0; i < raws.plants.all.size(); i++) { + df::plant_raw *p = raws.plants.all[i]; + if (p->material.size() <= 1) + continue; + for (size_t j = 0; j < p->material.size(); j++) { + if (p->material[j]->id == "WOOD") { + cache_matched(DFHack::MaterialInfo::PLANT_BASE+j, i); + break; + } + } + } +} + static HeatSafety get_heat_safety_filter(const BuildingTypeKey &key) { if (cur_heat_safety.count(key)) return cur_heat_safety.at(key); @@ -221,6 +263,7 @@ static void clear_state(color_ostream &out) { } } job_item_cache.clear(); + mat_cache.clear(); } DFhackCExport command_result plugin_load_data (color_ostream &out) { @@ -236,6 +279,8 @@ DFhackCExport command_result plugin_load_data (color_ostream &out) { DEBUG(status,out).print("loading persisted state\n"); clear_state(out); + load_material_cache(); + vector filter_configs; World::GetPersistentData(&filter_configs, FILTER_CONFIG_KEY); for (auto &cfg : filter_configs) { @@ -250,7 +295,7 @@ DFhackCExport command_result plugin_load_data (color_ostream &out) { PlannedBuilding pb(out, building_configs[idx]); df::building *bld = df::building::find(pb.id); if (!bld) { - INFO(status).print("building %d no longer exists; skipping\n", pb.id); + INFO(status,out).print("building %d no longer exists; skipping\n", pb.id); pb.remove(out); continue; } @@ -639,7 +684,7 @@ static void clearFilter(color_ostream &out, df::building_type type, int16_t subt TRACE(status,out).print("entering clearFilter\n"); BuildingTypeKey key(type, subtype, custom); auto &filters = get_item_filters(out, key); - if (filters.getItemFilters().size() <= index) + if (index < 0 || filters.getItemFilters().size() <= (size_t)index) return; filters.setItemFilter(out, ItemFilter(), index); call_buildingplan_lua(&out, "signal_reset"); @@ -661,8 +706,8 @@ static int getMaterialFilter(lua_State *L) { DEBUG(status,*out).print( "entering getMaterialFilter building_type=%d subtype=%d custom=%d index=%d\n", type, subtype, custom, index); - vector filter; - Lua::PushVector(L, filter); + map counts_per_material; + Lua::Push(L, counts_per_material); return 1; } @@ -697,7 +742,7 @@ static void setQualityFilter(color_ostream &out, df::building_type type, int16_t DEBUG(status,out).print("entering setQualityFilter\n"); BuildingTypeKey key(type, subtype, custom); auto &filters = get_item_filters(out, key).getItemFilters(); - if (filters.size() <= index) + if (index < 0 || filters.size() <= (size_t)index) return; ItemFilter filter = filters[index]; filter.setDecoratedOnly(decorated != 0); @@ -825,7 +870,8 @@ DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_LUA_FUNCTION(isPlannedBuilding), DFHACK_LUA_FUNCTION(addPlannedBuilding), DFHACK_LUA_FUNCTION(doCycle), - DFHACK_LUA_FUNCTION(scheduleCycle), DFHACK_LUA_FUNCTION(countAvailableItems), + DFHACK_LUA_FUNCTION(scheduleCycle), + DFHACK_LUA_FUNCTION(countAvailableItems), DFHACK_LUA_FUNCTION(hasFilter), DFHACK_LUA_FUNCTION(clearFilter), DFHACK_LUA_FUNCTION(setMaterialFilter), diff --git a/plugins/lua/buildingplan.lua b/plugins/lua/buildingplan.lua index 2aaa34bbb..413dd545a 100644 --- a/plugins/lua/buildingplan.lua +++ b/plugins/lua/buildingplan.lua @@ -868,6 +868,8 @@ function QualityAndMaterialsPage:refresh() subviews.min_quality:setOption(quality.min_quality) subviews.max_quality:setOption(quality.max_quality) + local materials = getMaterialFilter(ibs.building_type, uibs.building_subtype, uibs.custom_type, self.index-1) + self.summary = summary self.dirty = false end