diff --git a/ext/crlib/cr-dict.h b/ext/crlib/cr-dict.h index 6a18d98..0fc36e2 100644 --- a/ext/crlib/cr-dict.h +++ b/ext/crlib/cr-dict.h @@ -22,9 +22,10 @@ CR_NAMESPACE_BEGIN -// template for hashing our string -template struct StringHash { - uint32 operator () (const K &key) const { +template struct Hash; + +template <> struct Hash { + uint32 operator () (const String &key) const noexcept { auto str = const_cast (key.chars ()); uint32 hash = 0; @@ -35,9 +36,32 @@ template struct StringHash { } }; -// template for hashing integers -template struct IntHash { - uint32 operator () (K key) const { +template <> struct Hash { + uint32 operator () (const StringRef &key) const noexcept { + auto str = const_cast (key.chars ()); + uint32 hash = 0; + + while (*str++) { + hash = ((hash << 5) + hash) + *str; + } + return hash; + } +}; + +template <> struct Hash { + uint32 operator () (const char *key) const noexcept { + auto str = const_cast (key); + uint32 hash = 0; + + while (*str++) { + hash = ((hash << 5) + hash) + *str; + } + return hash; + } +}; + +template <> struct Hash { + uint32 operator () (int32 key) const noexcept { key = ((key >> 16) ^ key) * 0x119de1f3; key = ((key >> 16) ^ key) * 0x119de1f3; key = (key >> 16) ^ key; @@ -46,225 +70,184 @@ template struct IntHash { } }; -// template for np hashing integers -template struct IntNoHash { - uint32 operator () (K key) const { +template struct EmptyHash { + uint32 operator () (T key) const noexcept { return static_cast (key); } }; namespace detail { - struct DictionaryList { - uint32 index; - DictionaryList *next; - }; - - template struct DictionaryBucket { - uint32 hash = static_cast (-1); + template struct HashEntry final : DenyCopying { + public: K key {}; V value {}; + bool used { false }; public: - DictionaryBucket () = default; - ~DictionaryBucket () = default; + HashEntry () = default; + ~HashEntry () = default; public: - DictionaryBucket (DictionaryBucket &&rhs) noexcept : hash (rhs.hash), key (cr::move (rhs.key)), value (cr::move (rhs.value)) + HashEntry (HashEntry &&rhs) noexcept : used (rhs.used), key (cr::move (rhs.key)), value (cr::move (rhs.value)) { } public: - DictionaryBucket &operator = (DictionaryBucket &&rhs) noexcept { + HashEntry &operator = (HashEntry &&rhs) noexcept { if (this != &rhs) { key = cr::move (rhs.key); value = cr::move (rhs.value); - hash = rhs.hash; + used = rhs.used; } return *this; } }; } -// basic dictionary -template , size_t HashSize = 36> class Dictionary final : public DenyCopying { +template > class HashMap final : public DenyCopying { +public: + using Entries = detail::HashEntry []; + private: - using DictBucket = detail::DictionaryBucket ; - using DictList = detail::DictionaryList; + size_t capacity_ {}; + size_t length_ {}; + H hash_; + + UniquePtr contents_; public: - enum : size_t { - InvalidIndex = static_cast (-1) - }; - -private: - Array contents_; - Array buckets_; - H hashFunction_; - -private: - uint32 hash (const K &key) const { - return hashFunction_ (key); + explicit HashMap (const size_t capacity = 3) : capacity_ (capacity), length_ (0) { + contents_ = cr::makeUnique (capacity); } - size_t find (const K &key, bool allocate) { - auto hashed = hash (key); - auto pos = hashed % contents_.length (); - - for (auto bucket = contents_[pos]; bucket != nullptr; bucket = bucket->next) { - if (buckets_[bucket->index].hash == hashed) { - return bucket->index; - } - } - - if (allocate) { - size_t created = buckets_.length (); - buckets_.resize (created + 1); - - auto allocated = alloc.allocate (); - - allocated->index = static_cast (created); - allocated->next = contents_[pos]; - - contents_[pos] = allocated; - - buckets_[created].key = key; - buckets_[created].hash = hashed; - - return created; - } - return InvalidIndex; - } - - size_t findIndex (const K &key) const { - return const_cast (this)->find (key, false); - } - -public: - explicit Dictionary () { - reset (); - } - - Dictionary (Dictionary &&rhs) noexcept : contents_ (cr::move (rhs.contents_)), buckets_ (cr::move (rhs.buckets_)), hashFunction_ (cr::move (rhs.hashFunction_)) + HashMap (HashMap &&rhs) noexcept : contents_ (cr::move (rhs.contents_)), hash_ (cr::move (rhs.hash_)), capacity_ (rhs.capacity_), length_ (rhs.length_) { } - ~Dictionary () { - clear (); + ~HashMap () = default; + +private: + size_t getIndex (const K &key, size_t length) const { + return hash_ (key) % length; + } + + void rehash () { + auto capacity = (capacity_ << 1); + auto contents = cr::makeUnique (capacity); + + for (size_t i = 0; i < capacity_; ++i) { + if (contents_[i].used) { + auto result = put (contents_[i].key, contents, capacity); + contents[result.second].value = cr::move (contents_[i].value); + } + } + contents_ = cr::move (contents); + capacity_ = capacity; + } + + Twin put (const K &key, UniquePtr &contents, const size_t capacity) { + size_t index = getIndex (key, capacity); + + for (size_t i = 0; i < capacity; ++i) { + if (!contents[index].used) { + contents[index].key = key; + contents[index].used = true; + + return { true, index }; + } + + if (contents[index].key == key) { + return { false, index }; + } + index++; + + if (index == capacity) { + index = 0; + } + } + return { false, 0 }; } public: - bool exists (const K &key) const { - return findIndex (key) != InvalidIndex; - } - bool empty () const { - return buckets_.empty (); + return !length_; } size_t length () const { - return buckets_.length (); + return length_; } - bool find (const K &key, V &value) const { - size_t index = findIndex (key); - - if (index == InvalidIndex) { + bool has (const K &key) const { + if (empty ()) { return false; } - value = buckets_[index].value; - return true; - } - - template bool push (const K &key, U &&value) { - operator [] (key) = cr::forward (value); - return true; - } - - bool remove (const K &key) { - auto hashed = hash (key); - - auto pos = hashed % contents_.length (); - auto *bucket = contents_[pos]; - - DictList *next = nullptr; - - while (bucket != nullptr) { - if (buckets_[bucket->index].hash == hashed) { - if (!next) { - contents_[pos] = bucket->next; - } - else { - next->next = bucket->next; - } - buckets_.erase (bucket->index, 1); - - alloc.deallocate (bucket); - bucket = nullptr; + size_t index = getIndex (key, capacity_); + for (size_t i = 0; i < capacity_; ++i) { + if (contents_[index].used && contents_[index].key == key) { return true; } - next = bucket; - bucket = bucket->next; + if (++index == capacity_) { + break; + } } return false; } - void clear () { - for (auto object : contents_) { - while (object != nullptr) { - auto next = object->next; + void erase (const K &key) { + size_t index = getIndex (key, capacity_); - alloc.deallocate (object); - object = next; + for (size_t i = 0; i < capacity_; ++i) { + if (contents_[index].used && contents_[index].key == key) { + contents_[index].used = false; + --length_; + + break; + } + if (++index == capacity_) { + break; } } - contents_.clear (); - buckets_.clear (); - - reset (); } - void reset () { - contents_.resize (HashSize); + void clear () { + length_ = 0; - for (size_t i = 0; i < HashSize; ++i) { - contents_[i] = nullptr; + for (size_t i = 0; i < capacity_; ++i) { + contents_[i].used = false; + } + rehash (); + } + + void foreach (Lambda callback) { + for (size_t i = 0; i < capacity_; ++i) { + if (contents_[i].used) { + callback (contents_[i].key, contents_[i].value); + } } } public: V &operator [] (const K &key) { - return buckets_[find (key, true)].value; + if ((length_ << 1) > capacity_) { + rehash (); + } + auto result = put (key, contents_, capacity_); + + if (result.first) { + ++length_; + } + return contents_[result.second].value; } - const V &operator [] (const K &key) const { - return buckets_[findIndex (key)].value; - } - - Dictionary &operator = (Dictionary &&rhs) noexcept { + HashMap &operator = (HashMap &&rhs) noexcept { if (this != &rhs) { contents_ = cr::move (rhs.contents_); - buckets_ = cr::move (rhs.buckets_); - hashFunction_ = cr::move (rhs.hashFunction_); + hash_ = cr::move (rhs.hash_); + + length_ = rhs.length_; + capacity_ = rhs.capacity_; } return *this; } - - // for range-based loops -public: - DictBucket *begin () { - return buckets_.begin (); - } - - DictBucket *begin () const { - return buckets_.begin (); - } - - DictBucket *end () { - return buckets_.end (); - } - - DictBucket *end () const { - return buckets_.end (); - } }; CR_NAMESPACE_END diff --git a/ext/crlib/cr-platform.h b/ext/crlib/cr-platform.h index f0e7317..5624411 100644 --- a/ext/crlib/cr-platform.h +++ b/ext/crlib/cr-platform.h @@ -97,6 +97,11 @@ CR_NAMESPACE_BEGIN # pragma warning (disable : 11074 11075) // remarks about inlining bla-bla-bla #endif +// msvc provides us placement new by default +#if defined (CR_CXX_MSVC) +# define __PLACEMENT_NEW_INLINE 1 +#endif + CR_NAMESPACE_END #if defined(CR_WINDOWS) diff --git a/inc/config.h b/inc/config.h index 162ace8..10593c8 100644 --- a/inc/config.h +++ b/inc/config.h @@ -73,8 +73,8 @@ private: StringArray m_logos; StringArray m_avatars; - Dictionary m_language; - Dictionary > m_difficulty; + HashMap m_language; + HashMap m_difficulty; // default tables for personality weapon preferences, overridden by weapon.cfg SmallArray m_normalWeaponPrefs = { 0, 2, 1, 4, 5, 6, 3, 12, 10, 24, 25, 13, 11, 8, 7, 22, 23, 18, 21, 17, 19, 15, 17, 9, 14, 16 }; diff --git a/inc/engine.h b/inc/engine.h index eaaa8f0..bbbe74c 100644 --- a/inc/engine.h +++ b/inc/engine.h @@ -628,23 +628,10 @@ private: # define HOOK_CAST SharedLibrary::Handle #endif -private: - template struct CharHash { - uint32 operator () (const char *key) const { - auto str = const_cast (key); - uint32 hash = 0; - - while (*str++) { - hash = ((hash << 5) + hash) + *str; - } - return hash; - } - }; - private: SharedLibrary m_self; SimpleHook m_dlsym; - Dictionary > m_exports; + HashMap m_exports; public: EntityLinkage () = default; diff --git a/inc/message.h b/inc/message.h index 1ca85a9..0091ad3 100644 --- a/inc/message.h +++ b/inc/message.h @@ -71,6 +71,7 @@ CR_DECLARE_SCOPED_ENUM (StatusIconCache, class MessageDispatcher final : public Singleton { private: using MsgFunc = void (MessageDispatcher::*) (); + using MsgHash = Hash ; private: struct Args { @@ -87,20 +88,22 @@ private: }; private: - Dictionary m_textMsgCache; // cache strings for faster access for textmsg - Dictionary m_showMenuCache; // cache for the showmenu message - Dictionary m_statusIconCache; // cache for status icon message - Dictionary m_teamInfoCache; // cache for teaminfo message + HashMap m_textMsgCache; // cache strings for faster access for textmsg + HashMap m_showMenuCache; // cache for the showmenu message + HashMap m_statusIconCache; // cache for status icon message + HashMap m_teamInfoCache; // cache for teaminfo message private: Bot *m_bot {}; // owner of a message NetMsg m_current {}; // ongoing message id SmallArray m_args; // args collected from write* functions - Dictionary m_wanted; // wanted messages - Dictionary > m_maps; // maps our message to id to engine message id - Dictionary > m_handlers; // maps our message id to handler function + HashMap m_wanted; // wanted messages + HashMap m_reverseMap; // maps engine message id to our message id + + HashMap m_maps; // maps our message to id to engine message id + HashMap m_handlers; // maps our message id to handler function private: void netMsgTextMsg (); diff --git a/inc/support.h b/inc/support.h index d20fc02..be86f97 100644 --- a/inc/support.h +++ b/inc/support.h @@ -36,8 +36,8 @@ private: SmallArray m_clients; SmallArray > m_tags; - Dictionary > m_weaponAlias; - Dictionary m_noiseCache; + HashMap m_weaponAlias; + HashMap m_noiseCache; SimpleHook m_sendToHook; public: diff --git a/src/botlib.cpp b/src/botlib.cpp index 7803ae0..18db4da 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -4938,45 +4938,45 @@ void Bot::showDebugOverlay () { static float timeDebugUpdate = 0.0f; static int index, goal, taskID; - static Dictionary > tasks; - static Dictionary > personalities; - static Dictionary > flags; + static HashMap tasks; + static HashMap personalities; + static HashMap flags; if (tasks.empty ()) { - tasks.push (Task::Normal, "Normal"); - tasks.push (Task::Pause, "Pause"); - tasks.push (Task::MoveToPosition, "Move"); - tasks.push (Task::FollowUser, "Follow"); - tasks.push (Task::PickupItem, "Pickup"); - tasks.push (Task::Camp, "Camp"); - tasks.push (Task::PlantBomb, "PlantBomb"); - tasks.push (Task::DefuseBomb, "DefuseBomb"); - tasks.push (Task::Attack, "Attack"); - tasks.push (Task::Hunt, "Hunt"); - tasks.push (Task::SeekCover, "SeekCover"); - tasks.push (Task::ThrowExplosive, "ThrowHE"); - tasks.push (Task::ThrowFlashbang, "ThrowFL"); - tasks.push (Task::ThrowSmoke, "ThrowSG"); - tasks.push (Task::DoubleJump, "DoubleJump"); - tasks.push (Task::EscapeFromBomb, "EscapeFromBomb"); - tasks.push (Task::ShootBreakable, "DestroyBreakable"); - tasks.push (Task::Hide, "Hide"); - tasks.push (Task::Blind, "Blind"); - tasks.push (Task::Spraypaint, "Spray"); + tasks[Task::Normal] = "Normal"; + tasks[Task::Pause] = "Pause"; + tasks[Task::MoveToPosition] = "Move"; + tasks[Task::FollowUser] = "Follow"; + tasks[Task::PickupItem] = "Pickup"; + tasks[Task::Camp] = "Camp"; + tasks[Task::PlantBomb] = "PlantBomb"; + tasks[Task::DefuseBomb] = "DefuseBomb"; + tasks[Task::Attack] = "Attack"; + tasks[Task::Hunt] = "Hunt"; + tasks[Task::SeekCover] = "SeekCover"; + tasks[Task::ThrowExplosive] = "ThrowHE"; + tasks[Task::ThrowFlashbang] = "ThrowFL"; + tasks[Task::ThrowSmoke] = "ThrowSG"; + tasks[Task::DoubleJump] = "DoubleJump"; + tasks[Task::EscapeFromBomb] = "EscapeFromBomb"; + tasks[Task::ShootBreakable] = "DestroyBreakable"; + tasks[Task::Hide] = "Hide"; + tasks[Task::Blind] = "Blind"; + tasks[Task::Spraypaint] = "Spray"; - personalities.push (Personality::Rusher, "Rusher"); - personalities.push (Personality::Normal, "Normal"); - personalities.push (Personality::Careful, "Careful"); + personalities[Personality::Rusher] = "Rusher"; + personalities[Personality::Normal] = "Normal"; + personalities[Personality::Careful] = "Careful"; - flags.push (AimFlags::Nav, "Nav"); - flags.push (AimFlags::Camp, "Camp"); - flags.push (AimFlags::PredictPath, "Predict"); - flags.push (AimFlags::LastEnemy, "LastEnemy"); - flags.push (AimFlags::Entity, "Entity"); - flags.push (AimFlags::Enemy, "Enemy"); - flags.push (AimFlags::Grenade, "Grenade"); - flags.push (AimFlags::Override, "Override"); - flags.push (AimFlags::Danger, "Danger"); + flags[AimFlags::Nav] = "Nav"; + flags[AimFlags::Camp] = "Camp"; + flags[AimFlags::PredictPath] = "Predict"; + flags[AimFlags::LastEnemy] = "LastEnemy"; + flags[AimFlags::Entity] = "Entity"; + flags[AimFlags::Enemy] = "Enemy"; + flags[AimFlags::Grenade] = "Grenade"; + flags[AimFlags::Override] = "Override"; + flags[AimFlags::Danger] = "Danger"; } if (m_tasks.empty ()) { @@ -5401,11 +5401,13 @@ Vector Bot::calcThrow (const Vector &start, const Vector &stop) { else if (time > 2.0f) { time = 1.2f; } + float half = time * 0.5f; + velocity = velocity * (1.0f / time); - velocity.z += gravity * time * 0.5f; + velocity.z += gravity * half; Vector apex = start + (stop - start) * 0.5f; - apex.z += 0.5f * gravity * (time * 0.5f) * (time * 0.5f); + apex.z += 0.5f * gravity * half * half; game.testHull (start, apex, TraceIgnore::None, head_hull, ent (), &tr); diff --git a/src/config.cpp b/src/config.cpp index 37270c7..88022ff 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -495,7 +495,7 @@ void BotConfig::loadLanguageConfig () { } if (!lang.second.empty () && !lang.first.empty ()) { - m_language.push (lang.first.trim (), lang.second.trim ()); + m_language[lang.first.trim ()] = lang.second.trim (); } } else if (line.startsWith ("[TRANSLATED]") && !temp.empty ()) { @@ -756,11 +756,9 @@ const char *BotConfig::translate (StringRef input) { if (game.isDedicated ()) { return input.chars (); } - static String result; - result.clear (); - if (m_language.find (input, result)) { - return result.chars (); + if (m_language.has (input)) { + return m_language[input.chars ()].chars (); } return input.chars (); // nothing found } \ No newline at end of file diff --git a/src/control.cpp b/src/control.cpp index fe2178d..f0c481f 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -127,20 +127,20 @@ int BotControl::cmdWeaponMode () { if (!hasArg (type)) { return BotCommandResult::BadFormat; } - Dictionary modes; + HashMap modes; - modes.push ("kinfe", 1); - modes.push ("pistol", 2); - modes.push ("shotgun", 3); - modes.push ("smg", 4); - modes.push ("rifle", 5); - modes.push ("sniper", 6); - modes.push ("standard", 7); + modes["kinfe"] = 1; + modes["pistol"] = 2; + modes["shotgun"] = 3; + modes["smg"] = 4; + modes["rifle"] = 5; + modes["sniper"] = 6; + modes["standard"] = 7; auto mode = strValue (type); // check if selected mode exists - if (!modes.exists (mode)) { + if (!modes.has (mode)) { return BotCommandResult::BadFormat; } bots.setWeaponMode (modes[mode]); @@ -276,7 +276,7 @@ int BotControl::cmdNode () { } // should be moved to class? - static Dictionary commands; + static HashMap commands; static StringArray descriptions; // fill only once @@ -286,7 +286,7 @@ int BotControl::cmdNode () { auto addGraphCmd = [&] (String cmd, String format, String help, Handler handler) -> void { BotCmd botCmd { cmd, cr::move (format), cr::move (help), cr::move (handler) }; - commands.push (cmd, cr::move (botCmd)); + commands[cmd] = cr::move (botCmd); descriptions.push (cmd); }; @@ -325,7 +325,7 @@ int BotControl::cmdNode () { addGraphCmd ("release_editor", "acquire_editor", "Releases graph editing rights.", &BotControl::cmdNodeAcquireEditor); } } - if (commands.exists (strValue (cmd))) { + if (commands.has (strValue (cmd))) { auto item = commands[strValue (cmd)]; // graph have only bad format return status @@ -336,7 +336,7 @@ int BotControl::cmdNode () { } } else { - if (strValue (cmd) == "help" && hasArg (cmd2) && commands.exists (strValue (cmd2))) { + if (strValue (cmd) == "help" && hasArg (cmd2) && commands.has (strValue (cmd2))) { auto &item = commands[strValue (cmd2)]; msg ("Command: \"%s %s %s\"\nFormat: %s\nHelp: %s", m_args[root], m_args[alias], item.name, item.format, item.help); diff --git a/src/engine.cpp b/src/engine.cpp index 4c58c53..a692ff9 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1161,21 +1161,21 @@ SharedLibrary::Handle EntityLinkage::lookup (SharedLibrary::Handle module, const if (self.handle () != module) { return resolve (module); } + + if (m_exports.has (function)) { + return m_exports[function]; + } auto botAddr = resolve (self.handle ()); if (!botAddr) { auto gameAddr = resolve (gamedll.handle ()); if (gameAddr) { - m_exports[function] = gameAddr; + return m_exports[function] = gameAddr; } } else { - m_exports[function] = botAddr; - } - - if (m_exports.exists (function)) { - return m_exports[function]; + return m_exports[function] = botAddr; } return nullptr; } diff --git a/src/message.cpp b/src/message.cpp index 7bee670..1b872a4 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -389,35 +389,35 @@ void MessageDispatcher::netMsgFlashBat () { MessageDispatcher::MessageDispatcher () { // register wanted message - auto pushWanted = [&] (StringRef name, NetMsg id, MsgFunc handler) -> void { + auto addWanted = [&] (StringRef name, NetMsg id, MsgFunc handler) -> void { m_wanted[name] = id; m_handlers[id] = handler; }; reset (); // we want to handle next messages - pushWanted ("TextMsg", NetMsg::TextMsg, &MessageDispatcher::netMsgTextMsg); - pushWanted ("VGUIMenu", NetMsg::VGUIMenu, &MessageDispatcher::netMsgVGUIMenu); - pushWanted ("ShowMenu", NetMsg::ShowMenu, &MessageDispatcher::netMsgShowMenu); - pushWanted ("WeaponList", NetMsg::WeaponList, &MessageDispatcher::netMsgWeaponList); - pushWanted ("CurWeapon", NetMsg::CurWeapon, &MessageDispatcher::netMsgCurWeapon); - pushWanted ("AmmoX", NetMsg::AmmoX, &MessageDispatcher::netMsgAmmoX); - pushWanted ("AmmoPickup", NetMsg::AmmoPickup, &MessageDispatcher::netMsgAmmoPickup); - pushWanted ("Damage", NetMsg::Damage, &MessageDispatcher::netMsgDamage); - pushWanted ("Money", NetMsg::Money, &MessageDispatcher::netMsgMoney); - pushWanted ("StatusIcon", NetMsg::StatusIcon, &MessageDispatcher::netMsgStatusIcon); - pushWanted ("DeathMsg", NetMsg::DeathMsg, &MessageDispatcher::netMsgDeathMsg); - pushWanted ("ScreenFade", NetMsg::ScreenFade, &MessageDispatcher::netMsgScreenFade); - pushWanted ("HLTV", NetMsg::HLTV, &MessageDispatcher::netMsgHLTV); - pushWanted ("TeamInfo", NetMsg::TeamInfo, &MessageDispatcher::netMsgTeamInfo); - pushWanted ("BarTime", NetMsg::BarTime, &MessageDispatcher::netMsgBarTime); - pushWanted ("ItemStatus", NetMsg::ItemStatus, &MessageDispatcher::netMsgItemStatus); - pushWanted ("NVGToggle", NetMsg::NVGToggle, &MessageDispatcher::netMsgNVGToggle); - pushWanted ("FlashBat", NetMsg::FlashBat, &MessageDispatcher::netMsgFlashBat); + addWanted ("TextMsg", NetMsg::TextMsg, &MessageDispatcher::netMsgTextMsg); + addWanted ("VGUIMenu", NetMsg::VGUIMenu, &MessageDispatcher::netMsgVGUIMenu); + addWanted ("ShowMenu", NetMsg::ShowMenu, &MessageDispatcher::netMsgShowMenu); + addWanted ("WeaponList", NetMsg::WeaponList, &MessageDispatcher::netMsgWeaponList); + addWanted ("CurWeapon", NetMsg::CurWeapon, &MessageDispatcher::netMsgCurWeapon); + addWanted ("AmmoX", NetMsg::AmmoX, &MessageDispatcher::netMsgAmmoX); + addWanted ("AmmoPickup", NetMsg::AmmoPickup, &MessageDispatcher::netMsgAmmoPickup); + addWanted ("Damage", NetMsg::Damage, &MessageDispatcher::netMsgDamage); + addWanted ("Money", NetMsg::Money, &MessageDispatcher::netMsgMoney); + addWanted ("StatusIcon", NetMsg::StatusIcon, &MessageDispatcher::netMsgStatusIcon); + addWanted ("DeathMsg", NetMsg::DeathMsg, &MessageDispatcher::netMsgDeathMsg); + addWanted ("ScreenFade", NetMsg::ScreenFade, &MessageDispatcher::netMsgScreenFade); + addWanted ("HLTV", NetMsg::HLTV, &MessageDispatcher::netMsgHLTV); + addWanted ("TeamInfo", NetMsg::TeamInfo, &MessageDispatcher::netMsgTeamInfo); + addWanted ("BarTime", NetMsg::BarTime, &MessageDispatcher::netMsgBarTime); + addWanted ("ItemStatus", NetMsg::ItemStatus, &MessageDispatcher::netMsgItemStatus); + addWanted ("NVGToggle", NetMsg::NVGToggle, &MessageDispatcher::netMsgNVGToggle); + addWanted ("FlashBat", NetMsg::FlashBat, &MessageDispatcher::netMsgFlashBat); // we're need next messages IDs but we're won't handle them, so they will be removed from wanted list as soon as they get engine IDs - pushWanted ("BotVoice", NetMsg::BotVoice, nullptr); - pushWanted ("SendAudio", NetMsg::SendAudio, nullptr); + addWanted ("BotVoice", NetMsg::BotVoice, nullptr); + addWanted ("SendAudio", NetMsg::SendAudio, nullptr); // register text msg cache m_textMsgCache["#CTs_Win"] = TextMsgCache::NeedHandle | TextMsgCache::CounterWin; @@ -464,10 +464,12 @@ MessageDispatcher::MessageDispatcher () { } int32 MessageDispatcher::add (StringRef name, int32 id) { - if (!m_wanted.exists (name)) { + if (!m_wanted.has (name)) { return id; } + m_maps[m_wanted[name]] = id; // add message from engine regusermsg + m_reverseMap[id] = m_wanted[name]; // add message from engine regusermsg return id; } @@ -475,12 +477,14 @@ int32 MessageDispatcher::add (StringRef name, int32 id) { void MessageDispatcher::start (edict_t *ent, int32 type) { reset (); + if (game.is (GameFlags::Metamod)) { + ensureMessages (); + } + // search if we need to handle this message - for (const auto &msg : m_maps) { - if (msg.value == type && m_handlers[msg.key]) { - m_current = msg.key; - break; - } + if (m_reverseMap.has (type)) { + auto msg = m_reverseMap[type]; + m_current = m_handlers[msg] ? msg : NetMsg::None; } // no messagem no processing @@ -513,19 +517,16 @@ void MessageDispatcher::ensureMessages () { // this function tries to associate appropriate message ids. // check if we're have one - if (m_maps.exists (NetMsg::Money)) { + if (m_maps.has (NetMsg::Money)) { return; } // re-register our message - for (const auto &msg : m_wanted) { - add (msg.key, GET_USER_MSG_ID (PLID, msg.key.chars (), nullptr)); - } + m_wanted.foreach ([&] (const String &key, const int32 &) { + add (key, GET_USER_MSG_ID (PLID, key.chars (), nullptr)); + }); } int32 MessageDispatcher::id (NetMsg msg) { - if (game.is (GameFlags::Metamod)) { - ensureMessages (); - } return m_maps[msg]; } diff --git a/src/support.cpp b/src/support.cpp index 0e855b4..85acc82 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -74,38 +74,38 @@ BotSupport::BotSupport () { m_noiseCache["doors/doorm"] = Noise::NeedHandle | Noise::Door; // register weapon aliases - m_weaponAlias.push (Weapon::USP, "usp"); // HK USP .45 Tactical - m_weaponAlias.push (Weapon::Glock18, "glock"); // Glock18 Select Fire - m_weaponAlias.push (Weapon::Deagle, "deagle"); // Desert Eagle .50AE - m_weaponAlias.push (Weapon::P228, "p228"); // SIG P228 - m_weaponAlias.push (Weapon::Elite, "elite"); // Dual Beretta 96G Elite - m_weaponAlias.push (Weapon::FiveSeven, "fn57"); // FN Five-Seven - m_weaponAlias.push (Weapon::M3, "m3"); // Benelli M3 Super90 - m_weaponAlias.push (Weapon::XM1014, "xm1014"); // Benelli XM1014 - m_weaponAlias.push (Weapon::MP5, "mp5"); // HK MP5-Navy - m_weaponAlias.push (Weapon::TMP, "tmp"); // Steyr Tactical Machine Pistol - m_weaponAlias.push (Weapon::P90, "p90"); // FN P90 - m_weaponAlias.push (Weapon::MAC10, "mac10"); // Ingram MAC-10 - m_weaponAlias.push (Weapon::UMP45, "ump45"); // HK UMP45 - m_weaponAlias.push (Weapon::AK47, "ak47"); // Automat Kalashnikov AK-47 - m_weaponAlias.push (Weapon::Galil, "galil"); // IMI Galil - m_weaponAlias.push (Weapon::Famas, "famas"); // GIAT FAMAS - m_weaponAlias.push (Weapon::SG552, "sg552"); // Sig SG-552 Commando - m_weaponAlias.push (Weapon::M4A1, "m4a1"); // Colt M4A1 Carbine - m_weaponAlias.push (Weapon::AUG, "aug"); // Steyr Aug - m_weaponAlias.push (Weapon::Scout, "scout"); // Steyr Scout - m_weaponAlias.push (Weapon::AWP, "awp"); // AI Arctic Warfare/Magnum - m_weaponAlias.push (Weapon::G3SG1, "g3sg1"); // HK G3/SG-1 Sniper Rifle - m_weaponAlias.push (Weapon::SG550, "sg550"); // Sig SG-550 Sniper - m_weaponAlias.push (Weapon::M249, "m249"); // FN M249 Para - m_weaponAlias.push (Weapon::Flashbang, "flash"); // Concussion Grenade - m_weaponAlias.push (Weapon::Explosive, "hegren"); // High-Explosive Grenade - m_weaponAlias.push (Weapon::Smoke, "sgren"); // Smoke Grenade - m_weaponAlias.push (Weapon::Armor, "vest"); // Kevlar Vest - m_weaponAlias.push (Weapon::ArmorHelm, "vesthelm"); // Kevlar Vest and Helmet - m_weaponAlias.push (Weapon::Defuser, "defuser"); // Defuser Kit - m_weaponAlias.push (Weapon::Shield, "shield"); // Tactical Shield - m_weaponAlias.push (Weapon::Knife, "knife"); // Knife + m_weaponAlias[Weapon::USP] = "usp"; // HK USP .45 Tactical + m_weaponAlias[Weapon::Glock18] = "glock"; // Glock18 Select Fire + m_weaponAlias[Weapon::Deagle] = "deagle"; // Desert Eagle .50AE + m_weaponAlias[Weapon::P228] = "p228"; // SIG P228 + m_weaponAlias[Weapon::Elite] = "elite"; // Dual Beretta 96G Elite + m_weaponAlias[Weapon::FiveSeven] = "fn57"; // FN Five-Seven + m_weaponAlias[Weapon::M3] = "m3"; // Benelli M3 Super90 + m_weaponAlias[Weapon::XM1014] = "xm1014"; // Benelli XM1014 + m_weaponAlias[Weapon::MP5] = "mp5"; // HK MP5-Navy + m_weaponAlias[Weapon::TMP] = "tmp"; // Steyr Tactical Machine Pistol + m_weaponAlias[Weapon::P90] = "p90"; // FN P90 + m_weaponAlias[Weapon::MAC10] = "mac10"; // Ingram MAC-10 + m_weaponAlias[Weapon::UMP45] = "ump45"; // HK UMP45 + m_weaponAlias[Weapon::AK47] = "ak47"; // Automat Kalashnikov AK-47 + m_weaponAlias[Weapon::Galil] = "galil"; // IMI Galil + m_weaponAlias[Weapon::Famas] = "famas"; // GIAT FAMAS + m_weaponAlias[Weapon::SG552] = "sg552"; // Sig SG-552 Commando + m_weaponAlias[Weapon::M4A1] = "m4a1"; // Colt M4A1 Carbine + m_weaponAlias[Weapon::AUG] = "aug"; // Steyr Aug + m_weaponAlias[Weapon::Scout] = "scout"; // Steyr Scout + m_weaponAlias[Weapon::AWP] = "awp"; // AI Arctic Warfare/Magnum + m_weaponAlias[Weapon::G3SG1] = "g3sg1"; // HK G3/SG-1 Sniper Rifle + m_weaponAlias[Weapon::SG550] = "sg550"; // Sig SG-550 Sniper + m_weaponAlias[Weapon::M249] = "m249"; // FN M249 Para + m_weaponAlias[Weapon::Flashbang] = "flash"; // Concussion Grenade + m_weaponAlias[Weapon::Explosive] = "hegren"; // High-Explosive Grenade + m_weaponAlias[Weapon::Smoke] = "sgren"; // Smoke Grenade + m_weaponAlias[Weapon::Armor] = "vest"; // Kevlar Vest + m_weaponAlias[Weapon::ArmorHelm] = "vesthelm"; // Kevlar Vest and Helmet + m_weaponAlias[Weapon::Defuser] = "defuser"; // Defuser Kit + m_weaponAlias[Weapon::Shield] = "shield"; // Tactical Shield + m_weaponAlias[Weapon::Knife] = "knife"; // Knife m_clients.resize (kGameMaxPlayers + 1); } @@ -718,7 +718,7 @@ int32 BotSupport::sendTo (int socket, const void *message, size_t length, int fl StringRef BotSupport::weaponIdToAlias (int32 id) { StringRef none = "none"; - if (m_weaponAlias.exists (id)) { + if (m_weaponAlias.has (id)) { return m_weaponAlias[id]; } return none;