From 03788005291f6b9c7274414855f7d0f251003b1b Mon Sep 17 00:00:00 2001 From: LightCat Date: Mon, 31 Dec 2018 21:09:12 +0100 Subject: [PATCH] Fix Itemtest map being extremely inefficient --- include/itemtypes.hpp | 10 ++--- src/helpers.cpp | 87 ++++++++++++++++++++++++++++++++++++++++--- src/itemtypes.cpp | 47 ++++++++++------------- 3 files changed, 105 insertions(+), 39 deletions(-) diff --git a/include/itemtypes.hpp b/include/itemtypes.hpp index f20b57dd..306abd5f 100644 --- a/include/itemtypes.hpp +++ b/include/itemtypes.hpp @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include @@ -139,8 +139,8 @@ public: void RegisterItem(std::string modelpath, k_EItemType type); k_EItemType GetItemType(CachedEntity *entity); - std::map models; - std::map map; + std::unordered_map models; + std::unordered_map map; }; class ItemManager @@ -151,10 +151,10 @@ public: void RegisterSpecialMapping(ItemCheckerFn fn, k_EItemType type); k_EItemType GetItemType(CachedEntity *ent); - std::map special_map; + std::unordered_map special_map; std::vector specials; ItemModelMapper mapper_special; ItemModelMapper mapper; }; -extern ItemManager g_ItemManager; \ No newline at end of file +extern ItemManager g_ItemManager; diff --git a/src/helpers.cpp b/src/helpers.cpp index b1d657cb..d90dcc1c 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -481,12 +481,87 @@ void ReplaceString(std::string &input, const std::string &what, const std::strin } } -void ReplaceSpecials(std::string &input) -{ - ReplaceString(input, "\\015", "\015"); - ReplaceString(input, "\\n", "\n"); - ReplaceString(input, "\\r", "\r"); - ReplaceString(input, "\\u200F", "\u200F"); +void ReplaceSpecials(std::string &str) { + int val, i; + size_t c = 0, len = str.size(); + for (int i = 0; i + c < len; ++i) { + str[i] = str[i + c]; + if (str[i] != '\\') + continue; + if (i + c + 1 == len) + break; + switch (str[i + c + 1]) { + // Several control characters + case 'b': + ++c; + str[i] = '\b'; + break; + case 'n': + ++c; + str[i] = '\n'; + break; + case 'v': + ++c; + str[i] = '\v'; + break; + case 'r': + ++c; + str[i] = '\r'; + break; + case 't': + ++c; + str[i] = '\t'; + break; + case 'f': + ++c; + str[i] = '\f'; + break; + case 'a': + ++c; + str[i] = '\a'; + break; + case 'e': + ++c; + str[i] = '\e'; + break; + // Write escaped escape character as is + case '\\': + ++c; + break; + // Convert specified value from HEX + case 'x': + if (i + c + 4 > len) + continue; + std::sscanf(&str[i + c + 2], "%02X", &val); + c += 3; + str[i] = val; + break; + // Convert from unicode + case 'u': + if (i + c + 6 > len) + continue; + // 1. Scan 16bit HEX value + std::sscanf(&str[i + c + 2], "%04X", &val); + c += 5; + // 2. Convert value to UTF-8 + if (val <= 0x7F) { + str[i] = val; + } else if (val <= 0x7FF) { + str[i] = 0xC0 | ((val >> 6) & 0x1F); + str[i + 1] = 0x80 | (val & 0x3F); + ++i; + --c; + } else { + str[i] = 0xE0 | ((val >> 12) & 0xF); + str[i + 1] = 0x80 | ((val >> 6) & 0x3F); + str[i + 2] = 0x80 | (val & 0x3F); + i += 2; + c -= 2; + } + break; + } + } + str.resize(len - c); } powerup_type GetPowerupOnPlayer(CachedEntity *player) diff --git a/src/itemtypes.cpp b/src/itemtypes.cpp index 6f3d0370..36f6fc53 100644 --- a/src/itemtypes.cpp +++ b/src/itemtypes.cpp @@ -167,54 +167,45 @@ void ItemManager::RegisterModelMapping(std::string path, k_EItemType type) void ItemManager::RegisterSpecialMapping(ItemCheckerFn fn, k_EItemType type) { - special_map.emplace(fn, type); + special_map[fn] = type; } k_EItemType ItemManager::GetItemType(CachedEntity *ent) { - for (const auto &it : specials) - { - const auto type = it(ent); - if (type != ITEM_NONE) - return type; - } - for (const auto &it : special_map) - { - if (it.first(ent)) - return it.second; - } return mapper.GetItemType(ent); } void ItemModelMapper::RegisterItem(std::string modelpath, k_EItemType type) { - models.emplace(modelpath, type); + models[modelpath] = type; } k_EItemType ItemModelMapper::GetItemType(CachedEntity *entity) { - const uintptr_t model = (uintptr_t) RAW_ENT(entity)->GetModel(); - for (const auto &it : map) + const uintptr_t model = (uint64_t) RAW_ENT(entity)->GetModel(); + try { - if (it.first == model) - return it.second; + return map.at(model); + } + // Do Nothing + catch (std::out_of_range) + { + } std::string path(g_IModelInfo->GetModelName((const model_t *) model)); bool set = false; - for (const auto &it : models) + // Do Nothing + try { - // logging::Info("comparing [%s] to [%s]", path.c_str(), - // it.first.c_str()); - if (it.first == path) - { - // logging::Info("Found %s!", path.c_str()); - map.emplace(model, it.second); - set = true; - break; - } + models.at(path); + set = true; + } + catch (std::out_of_range) + { + } if (!set) - map.emplace(model, k_EItemType::ITEM_NONE); + map[model] = k_EItemType::ITEM_NONE; return k_EItemType::ITEM_NONE; }