diff --git a/include/Client.h b/include/Client.h index 10ba839..2f85991 100644 --- a/include/Client.h +++ b/include/Client.h @@ -14,10 +14,10 @@ class TServer; class TClient final { public: - using TSetOfVehicleData = std::unordered_set; + using TSetOfVehicleData = std::vector; struct TVehicleDataLockPair { - TSetOfVehicleData& VehicleData; + TSetOfVehicleData* VehicleData; std::unique_lock Lock; }; @@ -31,6 +31,7 @@ public: void SetName(const std::string& Name) { mName = Name; } void SetRoles(const std::string& Role) { mRole = Role; } void AddIdentifier(const std::string& ID) { mIdentifiers.insert(ID); }; + void EraseVehicle(TVehicleData& VehicleData); std::string GetCarData(int Ident); void SetUDPAddr(sockaddr_in Addr) { mUDPAddress = Addr; } void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; } @@ -67,6 +68,8 @@ public: int SecondsSinceLastPing(); private: + void InsertVehicle(int ID, const std::string& Data); + TServer& mServer; bool mIsConnected = false; bool mIsSynced = false; diff --git a/include/VehicleData.h b/include/VehicleData.h index 7aac080..f8a6d3d 100644 --- a/include/VehicleData.h +++ b/include/VehicleData.h @@ -6,20 +6,25 @@ class TVehicleData final { public: TVehicleData(int ID, std::string Data); ~TVehicleData(); + // We cannot delete this, since vector needs to be able to copy when it resizes. + // Deleting this causes some wacky template errors which are hard to decipher, + // and end up making no sense, so let's just leave the copy ctor. + // TVehicleData(const TVehicleData&) = delete; [[nodiscard]] bool IsInvalid() const { return mID == -1; } [[nodiscard]] int ID() const { return mID; } [[nodiscard]] std::string Data() const { return mData; } - void SetData(const std::string& Data) const { mData = Data; } + void SetData(const std::string& Data) { mData = Data; } bool operator==(const TVehicleData& v) const { return mID == v.mID; } private: int mID { -1 }; - mutable std::string mData; + std::string mData; }; +// TODO: unused now, remove? namespace std { template <> struct hash { diff --git a/src/Client.cpp b/src/Client.cpp index d6da252..fbdade3 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -9,12 +9,24 @@ void TClient::DeleteCar(int Ident) { std::unique_lock lock(mVehicleDataMutex); for (auto& v : mVehicleData) { if (v.ID() == Ident) { - mVehicleData.erase(v); + EraseVehicle(v); break; } } } +void TClient::EraseVehicle(TVehicleData& VehicleData) { + std::unique_lock lock(mVehicleDataMutex); + auto iter = std::find_if(mVehicleData.begin(), mVehicleData.end(), [&](auto& elem) { + return VehicleData.ID() == elem.ID(); + }); + if (iter != mVehicleData.end()) { + mVehicleData.erase(iter); + } else { + debug("tried to erase a vehicle that doesn't exist!"); + } +} + void TClient::ClearCars() { std::unique_lock lock(mVehicleDataMutex); mVehicleData.clear(); @@ -37,11 +49,11 @@ int TClient::GetOpenCarID() const { void TClient::AddNewCar(int Ident, const std::string& Data) { std::unique_lock lock(mVehicleDataMutex); - mVehicleData.emplace(Ident, Data); + mVehicleData.emplace_back(Ident, Data); } TClient::TVehicleDataLockPair TClient::GetAllCars() { - return { mVehicleData, std::unique_lock(mVehicleDataMutex) }; + return { &mVehicleData, std::unique_lock(mVehicleDataMutex) }; } std::string TClient::GetCarData(int Ident) { diff --git a/src/TLuaFile.cpp b/src/TLuaFile.cpp index 3af050c..a90737e 100644 --- a/src/TLuaFile.cpp +++ b/src/TLuaFile.cpp @@ -339,15 +339,15 @@ int lua_GetCars(lua_State* L) { auto MaybeClient = GetClient(Engine().Server(), ID); if (MaybeClient && !MaybeClient.value().expired()) { auto Client = MaybeClient.value().lock(); - TClient::TSetOfVehicleData VehicleData; + TClient::TSetOfVehicleData* VehicleData; { // Vehicle Data Lock Scope auto LockedData = Client->GetAllCars(); VehicleData = LockedData.VehicleData; } // End Vehicle Data Lock Scope - if (VehicleData.empty()) + if (VehicleData->empty()) return 0; lua_newtable(L); - for (const auto& v : VehicleData) { + for (const auto& v : *VehicleData) { lua_pushinteger(L, v.ID()); lua_pushstring(L, v.Data().substr(3).c_str()); lua_settable(L, -3); diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index b7629aa..15ea72f 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -88,7 +88,8 @@ void TNetwork::UDPServerMain() { ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { Client = ClientPtr.lock(); - }else return true; + } else + return true; } if (Client->GetID() == ID) { @@ -312,7 +313,8 @@ void TNetwork::Authentication(SOCKET TCPSock) { ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { Cl = ClientPtr.lock(); - } else return true; + } else + return true; } info("Client Iteration: Name -> " + Cl->GetName() + ", Guest -> " + std::to_string(Cl->IsGuest()) + ", Roles -> " + Cl->GetRoles()); if (Cl->GetName() == Client->GetName() && Cl->IsGuest() == Client->IsGuest()) { @@ -355,7 +357,7 @@ bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) { if (!IsSync) { if (c.IsSyncing()) { //std::unique_lock Lock(c.MissedPacketQueueMutex()); - if(!Data.empty()) { + if (!Data.empty()) { if (Data.at(0) == 'O' || Data.at(0) == 'A' || Data.at(0) == 'C' || Data.at(0) == 'E') { c.EnqueuePacket(Data); } @@ -364,7 +366,6 @@ bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) { } } - int32_t Size, Sent; std::string Send(4, 0); Size = int32_t(Data.size()); @@ -488,8 +489,8 @@ void TNetwork::ClientKick(TClient& c, const std::string& R) { c.SetStatus(-2); CloseSocketProper(c.GetTCPSock()); } -void TNetwork::Looper(const std::weak_ptr& c){ - while(!c.expired()) { +void TNetwork::Looper(const std::weak_ptr& c) { + while (!c.expired()) { auto Client = c.lock(); if (Client->GetStatus() < 0) { debug("client status < 0, breaking client loop"); @@ -521,7 +522,7 @@ void TNetwork::Looper(const std::weak_ptr& c){ break; } } - }else{ + } else { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } @@ -535,7 +536,7 @@ void TNetwork::TCPClient(const std::weak_ptr& c) { OnConnect(c); RegisterThread("(" + std::to_string(c.lock()->GetID()) + ") \"" + c.lock()->GetName() + "\""); - std::thread QueueSync(&TNetwork::Looper, this ,c); + std::thread QueueSync(&TNetwork::Looper, this, c); while (true) { if (c.expired()) @@ -553,7 +554,8 @@ void TNetwork::TCPClient(const std::weak_ptr& c) { } TServer::GlobalParser(c, res, mPPSMonitor, *this); } - if(QueueSync.joinable())QueueSync.join(); + if (QueueSync.joinable()) + QueueSync.join(); if (!c.expired()) { auto Client = c.lock(); @@ -583,12 +585,12 @@ void TNetwork::OnDisconnect(const std::weak_ptr& ClientPtr, bool kicked TClient& c = *LockedClientPtr; info(c.GetName() + (" Connection Terminated")); std::string Packet; - TClient::TSetOfVehicleData VehicleData; + TClient::TSetOfVehicleData* VehicleData; { // Vehicle Data Lock Scope auto LockedData = c.GetAllCars(); VehicleData = LockedData.VehicleData; } // End Vehicle Data Lock Scope - for (auto& v : VehicleData) { + for (auto& v : *VehicleData) { Packet = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(v.ID()); SendToAll(&c, Packet, false, true); } @@ -836,15 +838,16 @@ bool TNetwork::SyncClient(const std::weak_ptr& c) { ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { client = ClientPtr.lock(); - } else return true; + } else + return true; } - TClient::TSetOfVehicleData VehicleData; + TClient::TSetOfVehicleData* VehicleData; { // Vehicle Data Lock Scope auto LockedData = client->GetAllCars(); VehicleData = LockedData.VehicleData; } // End Vehicle Data Lock Scope if (client != LockedClient) { - for (auto& v : VehicleData) { + for (auto& v : *VehicleData) { if (LockedClient->GetStatus() < 0) { Return = true; res = false; @@ -877,7 +880,8 @@ void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Re ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { Client = ClientPtr.lock(); - }else return true; + } else + return true; } if (Self || Client.get() != c) { if (Client->IsSynced() || Client->IsSyncing()) { @@ -886,7 +890,7 @@ void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Re if (Data.length() > 400) { std::string CMP(Comp(Data)); Client->EnqueuePacket("ABG:" + CMP); - }else{ + } else { Client->EnqueuePacket(Data); } //ret = SendLarge(*Client, Data);