#pragma once #include #include #include #include struct GameUUID { uint64_t hi = 0; uint64_t lo = 0; bool isValid() const { return hi != 0 || lo != 0; } // String conversion std::string toDashed() const; std::string toUndashed() const; std::wstring toWDashed() const; static GameUUID fromDashed(const std::string& s); static GameUUID fromUndashed(const std::string& s); // Generation static GameUUID generateV4(); static GameUUID generateOffline(const std::string& playerName); // Comparison bool operator==(const GameUUID& o) const { return hi == o.hi && lo == o.lo; } bool operator!=(const GameUUID& o) const { return !(*this == o); } bool operator<(const GameUUID& o) const { return hi < o.hi || (hi == o.hi && lo < o.lo); } // Hash support for unordered containers struct Hash { size_t operator()(const GameUUID& u) const { size_t h = std::hash{}(u.hi); h ^= std::hash{}(u.lo) + 0x9e3779b9 + (h << 6) + (h >> 2); return h; } }; }; inline const GameUUID INVALID_UUID = {}; // Stream extraction for _fromString compatibility inline std::wistream& operator>>(std::wistream& is, GameUUID& uuid) { std::wstring ws; is >> ws; std::string s(ws.begin(), ws.end()); uuid = GameUUID::fromDashed(s); return is; } // Specialise std::hash so unordered_map works without explicit Hash argument namespace std { template<> struct hash { size_t operator()(const GameUUID& u) const { return GameUUID::Hash{}(u); } }; }