fixed the issues with uf::hashed_string keys for hook system (because of a lot of annoying things)

This commit is contained in:
ecker 2026-06-10 20:37:42 -05:00
parent 5931a5dc6f
commit 334b897e19
10 changed files with 69 additions and 123 deletions

View File

@ -1,8 +1,8 @@
{
"import": "./base_sourceengine.json",
"assets": [
{ "filename": "./maps/mds_mcdonalds.bsp" }
// { "filename": "./maps/mds_mcdonalds/graph.json" }
// { "filename": "./maps/mds_mcdonalds.bsp" }
{ "filename": "./maps/mds_mcdonalds/graph.json" }
],
"metadata": {
"graph": {

View File

@ -1,7 +1,7 @@
{
// "import": "./rp_downtown_v2.json"
// "import": "./ss2_medsci1.json"
// "import": "./mds_mcdonalds.json"
"import": "./cs_office.json"
"import": "./mds_mcdonalds.json"
// "import": "./cs_office.json"
// "import": "./gm_construct.json"
}

View File

@ -110,10 +110,9 @@ namespace uf {
template<typename T> T loadChild( const uf::Serializer&, bool = true );
template<typename T> T loadChild( const uf::stl::string&, bool = true );
#if UF_HOOKS_HASH_KEYS
uf::hashed_string formatHookName( const uf::stl::string& n );
static uf::hashed_string formatHookName( const uf::stl::string& n, size_t uid, bool fetch = false );
inline uf::hashed_string formatHookName( const uf::stl::string_view& n );
static inline uf::hashed_string formatHookName( const uf::stl::string_view& n, size_t uid, bool fetch = false );
inline size_t resolveHookKey( size_t hash ) const { return hash; }
inline size_t resolveHookKey( const uf::stl::string& name ) { return this->formatHookName(name); }
@ -125,7 +124,7 @@ namespace uf {
template<typename K> inline void queueHook( const K& name, float timeout = 0 );
template<typename K, typename V> inline void queueHook( const K& name, const V&, float = 0 );
template<typename K, typename... Args> uf::Hooks::return_t lazyCallHook(const K& name, Args&&... args) {
template<typename K, typename... Args> inline uf::Hooks::return_t lazyCallHook(const K& name, Args&&... args) {
if ( uf::Object::deferLazyCalls ) {
this->queueHook(name, std::forward<Args>(args)..., 0.0f);
return {};
@ -136,27 +135,6 @@ namespace uf {
template<typename K, typename... Args> inline uf::Hooks::return_t callHook( const K& name, Args&&... args ) {
return uf::hooks.call( this->resolveHookKey(name), std::forward<Args>(args)... );
}
#else
uf::stl::string formatHookName( const uf::stl::string& n );
static uf::stl::string formatHookName( const uf::stl::string& n, size_t uid, bool fetch = false );
template<typename T> size_t addHook( const uf::stl::string& name, T function );
template<typename K> inline void queueHook( const K& name, float timeout = 0 );
template<typename K, typename V> inline void queueHook( const K& name, const V&, float = 0 );
template<typename K, typename... Args> uf::Hooks::return_t lazyCallHook(const K& name, Args&&... args) {
if ( uf::Object::deferLazyCalls ) {
this->queueHook(name, std::forward<Args>(args)..., 0.0f);
return {};
}
return this->callHook( name, std::forward<Args>(args)... );
}
template<typename K, typename... Args> inline uf::Hooks::return_t callHook( const K& name, Args&&... args ) {
return uf::hooks.call( this->formatHookName( name ), std::forward<Args>(args)... );
}
#endif
uf::stl::string resolveURI( const uf::stl::string& filename, const uf::stl::string& root = "" );
uf::asset::Payload resolveToPayload( const uf::stl::string& filename, const uf::stl::string& mime = "" );

View File

@ -17,7 +17,39 @@ T uf::Object::loadChild( const uf::stl::string& filename, bool initialize ) {
return this->loadChild(filename, initialize);
}
#if UF_HOOKS_HASH_KEYS
uf::hashed_string uf::Object::formatHookName( const uf::stl::string_view& n ) {
constexpr uf::stl::string_view PARENT_UID_SUFFIX = "%P-UID%";
constexpr uf::stl::string_view UID_SUFFIX = "%UID%";
if ( n.ends_with(PARENT_UID_SUFFIX) ) {
size_t uid = this->hasParent() ? this->getParent().getUid() : this->getUid();
uf::hashed_string hash{uf::stl::string_view(n).substr(0, n.size() - PARENT_UID_SUFFIX.size())};
return uf::algo::fnv1a( ::fmt::format("{}", uid), hash );
}
if ( n.ends_with(UID_SUFFIX) ) {
size_t uid = this->getUid();
uf::hashed_string hash{uf::stl::string_view(n).substr(0, n.size() - UID_SUFFIX.size())};
return uf::algo::fnv1a( ::fmt::format("{}", uid), hash );
}
return n;
}
uf::hashed_string uf::Object::formatHookName( const uf::stl::string_view& n, size_t uid, bool fetch ) {
if ( fetch ) {
auto* object = (uf::Object*) uf::Entity::globalFindByUid( uid );
if ( object ) return object->formatHookName( n );
}
constexpr uf::stl::string_view UID_SUFFIX = "%UID%";
if ( n.ends_with(UID_SUFFIX) ) {
uf::hashed_string hash = uf::stl::string_view(n).substr(0, n.size() - UID_SUFFIX.size());
return uf::algo::fnv1a( ::fmt::format("{}", uid), hash );
}
return n;
}
template<typename T>
size_t uf::Object::addHook( const size_t& name, T callback ) {
size_t id = uf::hooks.addHook( name, callback );
@ -25,16 +57,6 @@ size_t uf::Object::addHook( const size_t& name, T callback ) {
metadata.hooks.bound[name].emplace_back(id);
return id;
}
#else
template<typename T>
size_t uf::Object::addHook( const uf::stl::string& n, T callback ) {
auto name = this->formatHookName( n );
size_t id = uf::hooks.addHook( name, callback );
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
metadata.hooks.bound[name].emplace_back(id);
return id;
}
#endif
template<typename K> inline void uf::Object::queueHook( const K& name, float d ) {
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();

View File

@ -18,7 +18,7 @@ namespace spec {
typedef pod::Vector2i vector_t;
struct Event {
uf::stl::string name;
uf::Hooks::name_t name; // ugh
pod::Hook::userdata_t payload;
};
protected:

View File

@ -36,7 +36,7 @@ namespace pod {
};
}
#define UF_HOOKS_HASH_KEYS 0
#define UF_HOOKS_HASH_KEYS 1
namespace uf {
class UF_API Hooks {

View File

@ -19,23 +19,19 @@ namespace uf {
using FNV = FNV1a<sizeof(size_t)>;
constexpr size_t fnv1a(const char* str, size_t hash = FNV::basis) {
return *str ? fnv1a(str + 1, (hash ^ static_cast<size_t>(*str)) * FNV::prime) : hash;
return *str ? fnv1a(str + 1, (hash ^ static_cast<size_t>(static_cast<uint8_t>(*str))) * FNV::prime) : hash;
}
constexpr size_t fnv1a(const uf::stl::string_view str) {
size_t hash = FNV::basis;
constexpr size_t fnv1a(const uf::stl::string_view str, size_t hash = FNV::basis) {
for (char c : str) hash = (hash ^ static_cast<size_t>(c)) * FNV::prime;
return hash;
}
/*
inline size_t fnv1a(const uf::stl::string& str) {
return fnv1a(uf::stl::string_view(str));
inline size_t fnv1a(const uf::stl::string& str, size_t hash = FNV::basis) {
return fnv1a(uf::stl::string_view(str), hash);
}
*/
template<typename T, std::enable_if_t<std::is_trivially_copyable_v<T>, int> = 0>
inline size_t fnv1a(const T& v) {
size_t hash = FNV::basis;
template<typename T, std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_array_v<T> && !std::is_pointer_v<T>, int> = 0>
inline size_t fnv1a(const T& v, size_t hash = FNV::basis) {
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&v);
for (size_t i = 0; i < sizeof(T); ++i) {
hash = (hash ^ static_cast<size_t>(bytes[i])) * FNV::prime;
@ -43,10 +39,13 @@ namespace uf {
return hash;
}
template<typename T>
inline size_t fnv1a(const uf::stl::vector<T>& values) {
size_t hash = FNV::basis;
template<size_t N>
constexpr size_t fnv1a(const char (&str)[N], size_t hash = FNV::basis) {
return fnv1a(uf::stl::string_view(str, N - 1), hash);
}
template<typename T>
inline size_t fnv1a(const uf::stl::vector<T>& values, size_t hash = FNV::basis) {
if constexpr (std::is_same_v<T, bool>) {
for (bool b : values) {
hash = (hash ^ static_cast<size_t>(b)) * FNV::prime;

View File

@ -22,12 +22,13 @@ namespace uf {
typedef size_t hash_t;
size_t hash;
uf::stl::string string;
constexpr hashed_string() : hash(0), string("NULL") {}
constexpr hashed_string(size_t h) : hash(h), string("NULL") {}
constexpr hashed_string(const char* s) : hash(uf::algo::fnv1a(s)), string(s) {}
inline hashed_string(const uf::stl::string& s) : hash(uf::algo::fnv1a(s)), string(s) {}
constexpr hashed_string() : hash(0) {}
constexpr hashed_string(size_t h) : hash(h) {}
constexpr hashed_string(const char* s) : hash(uf::algo::fnv1a(s)) {}
template<size_t N> constexpr hashed_string(const char (&s)[N]) : hash(uf::algo::fnv1a(s)) {}
inline hashed_string(const uf::stl::string& s) : hash(uf::algo::fnv1a(s)) {}
inline hashed_string(const uf::stl::string_view& s) : hash(uf::algo::fnv1a(s)) {}
constexpr operator size_t() const { return hash; }

View File

@ -65,62 +65,6 @@ void uf::Object::queueDeletion() {
this->callHook("entity:Destroy.%UID%");
}
#if UF_HOOKS_HASH_KEYS
uf::hashed_string uf::Object::formatHookName( const uf::stl::string& n, size_t uid, bool fetch ) {
if ( fetch ) {
auto* object = (uf::Object*) uf::Entity::globalFindByUid( uid );
if ( object ) return object->formatHookName( n );
}
size_t hash = {};
uf::hash( hash, n );
if ( n.ends_with("%UID%") ) uf::hash( hash, uid );
uf::hashed_string res = hash;
res.string = n;
return res;
}
uf::hashed_string uf::Object::formatHookName( const uf::stl::string& n ) {
size_t uid = this->getUid();
size_t parent = this->hasParent() ? this->getParent().getUid() : uid;
size_t hash = {};
uf::hash( hash, n );
if ( n.ends_with("%P-UID%") ) uf::hash( hash, parent );
else if ( n.ends_with("%UID%") ) uf::hash( hash, uid );
uf::hashed_string res = hash;
res.string = n;
return res;
}
#else
uf::stl::string uf::Object::formatHookName( const uf::stl::string& n, size_t uid, bool fetch ) {
if ( fetch ) {
auto* object = (uf::Object*) uf::Entity::globalFindByUid( uid );
if ( object ) return object->formatHookName( n );
}
uf::stl::string res = n;
if ( n.ends_with("%UID%") ) res = uf::string::replace( res, "%UID%", ::fmt::format( "{}", uid ) );
return res;
}
uf::stl::string uf::Object::formatHookName( const uf::stl::string& n ) {
size_t uid = this->getUid();
size_t parent = this->hasParent() ? this->getParent().getUid() : uid;
uf::stl::string res = n;
if ( n.ends_with("%P-UID%") ) res = uf::string::replace( res, "%P-UID%", ::fmt::format( "{}", parent ) );
else if ( n.ends_with("%UID%") ) res = uf::string::replace( res, "%UID%", ::fmt::format( "{}", uid ) );
return res;
}
#endif
bool uf::Object::load( const uf::stl::string& f, bool inheritRoot ) {
uf::Serializer json;
uf::stl::string root = "";

View File

@ -865,7 +865,7 @@ void spec::win32::Window::processEvents() {
};
#if UF_HOOK_USE_JSON
ext::json::Value json;
json["type"] = event.type + "." + ((event.key.state == -1)?"Pressed":"Released");
json["type"] = ::fmt::format("{}.{}", event.type, (event.key.state == -1) ? "Pressed" : "Released");
json["invoker"] = event.invoker;
json["key"]["code"] = "";
json["key"]["raw"] = 0;
@ -881,15 +881,16 @@ void spec::win32::Window::processEvents() {
event.key.code = code;
event.key.raw = key;
auto eventName = ::fmt::format("{}.{}", event.type, code);
#if UF_HOOK_USE_USERDATA
this->pushEvent(event.type, event);
this->pushEvent(event.type + "." + code, event);
this->pushEvent(eventName, event);
#endif
#if UF_HOOK_USE_JSON
json["key"]["code"] = code;
json["key"]["raw"] = key;
this->pushEvent(event.type, json);
this->pushEvent(event.type + "." + code, json);
this->pushEvent(eventName, json);
#endif
}
}
@ -1144,13 +1145,14 @@ void spec::win32::Window::processEvent(UINT message, WPARAM wParam, LPARAM lPara
}
}
};
auto eventName = ::fmt::format("{}.{}", event.type, event.key.code);
#if UF_HOOK_USE_USERDATA
this->pushEvent(event.type, event);
this->pushEvent(event.type + "." + event.key.code, event);
this->pushEvent(eventName, event);
#endif
#if UF_HOOK_USE_JSON
ext::json::Value json;
json["type"] = event.type + "." + ((event.key.state == -1)?"Pressed":"Released");
json["type"] = ::fmt::format("{}.{}", event.type, (event.key.state == -1) ? "Pressed" : "Released");
json["invoker"] = event.invoker;
json["key"]["state"] = (event.key.state == -1) ? "Down" : "Up";
json["key"]["async"] = event.key.async;
@ -1163,7 +1165,7 @@ void spec::win32::Window::processEvent(UINT message, WPARAM wParam, LPARAM lPara
json["key"]["raw"] = event.key.raw;
json["key"]["lparam"] = lParam;
this->pushEvent(event.type, json);
this->pushEvent(event.type + "." + event.key.code, json);
this->pushEvent(eventName, json);
#endif
}
} break;