Fix Itemtest map being extremely inefficient

This commit is contained in:
LightCat 2018-12-31 21:09:12 +01:00
parent f49a16d88b
commit 0378800529
3 changed files with 105 additions and 39 deletions

View File

@ -7,7 +7,7 @@
#pragma once
#include <map>
#include <unordered_map>
#include <string>
#include <vector>
@ -139,8 +139,8 @@ public:
void RegisterItem(std::string modelpath, k_EItemType type);
k_EItemType GetItemType(CachedEntity *entity);
std::map<std::string, k_EItemType> models;
std::map<uintptr_t, k_EItemType> map;
std::unordered_map<std::string, k_EItemType> models;
std::unordered_map<uintptr_t, k_EItemType> map;
};
class ItemManager
@ -151,7 +151,7 @@ public:
void RegisterSpecialMapping(ItemCheckerFn fn, k_EItemType type);
k_EItemType GetItemType(CachedEntity *ent);
std::map<ItemCheckerFn, k_EItemType> special_map;
std::unordered_map<ItemCheckerFn, k_EItemType> special_map;
std::vector<ItemSpecialMapperFn> specials;
ItemModelMapper mapper_special;
ItemModelMapper mapper;

View File

@ -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)

View File

@ -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;
}