Compare commits

..

15 Commits

Author SHA1 Message Date
Anonymous-275 3da0af37e4 V2.0.2 2021-03-31 20:56:08 +03:00
Anonymous-275 baa41dd65a Timeout set to 30 secs 2021-03-31 20:19:19 +03:00
Anonymous-275 534b457f48 Possible ghost connection ellimination 2021-03-31 20:15:42 +03:00
Anonymous-275 029cf94e68 UnicycleID reset 2021-03-31 19:58:02 +03:00
Anonymous-275 15f7a6ba85 Unicycle edit check 2021-03-31 19:49:52 +03:00
Anonymous-275 86b5d91579 Try to fix max car limit 2021-03-31 19:31:45 +03:00
Anonymous-275 31486bcb56 Car limit fix 2021-03-31 19:27:05 +03:00
Anonymous-275 08660d83dc Unicycle bypass vehicle limit 2021-03-31 19:18:32 +03:00
Anonymous-275 6d8f75a577 Queue on player list update 2021-03-31 17:51:38 +03:00
Lion Kortlepel 018246cea5 fix deadlock in GetCarData, SetCarData 2021-03-31 14:50:49 +02:00
Lion Kortlepel a584e25bf3 fix deadlock in DeleteCar 2021-03-31 14:44:50 +02:00
Lion Kortlepel d4d773b769 revert copy-fix, it broke mutex locked contexts 2021-03-31 12:15:26 +02:00
Lion Kortlepel 56a02f0215 fix vehicle copy on GetAllCars, TSetOfVehicleData is now vector<> 2021-03-31 12:12:01 +02:00
Anonymous-275 7231c69e10 Lock when accessing vehicles 2021-03-31 12:42:29 +03:00
Lion 3c68dfaeaf Update LICENSE 2021-03-31 01:31:06 +02:00
10 changed files with 116 additions and 54 deletions
+1 -1
View File
@@ -1 +1 @@
Copyright (c) 2019-present Anonymous275. BeamMP Server code is not in the public domain and is not free software. One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries, the only permission that has been granted is to use the software in its compiled form as distributed from the BeamMP.com website. Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository. Copyright (c) 2019-present Anonymous275 (@Anonymous-275), Lion Kortlepel (@lionkor). BeamMP-Server code is not in the public domain and is not free software. One must be granted explicit permission by the copyright holder(s) in order to modify or distribute any part of the source or binaries. Special permission to modify the source-code is implicitly granted only for the purpose of upstreaming those changes directly to github.com/BeamMP/BeamMP-Server via a GitHub pull-request.
+12 -6
View File
@@ -14,10 +14,10 @@ class TServer;
class TClient final { class TClient final {
public: public:
using TSetOfVehicleData = std::unordered_set<TVehicleData>; using TSetOfVehicleData = std::vector<TVehicleData>;
struct TVehicleDataLockPair { struct TVehicleDataLockPair {
TSetOfVehicleData& VehicleData; TSetOfVehicleData* VehicleData;
std::unique_lock<std::mutex> Lock; std::unique_lock<std::mutex> Lock;
}; };
@@ -36,6 +36,7 @@ public:
void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; } void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; }
void SetTCPSock(SOCKET CSock) { mSocket[0] = CSock; } void SetTCPSock(SOCKET CSock) { mSocket[0] = CSock; }
void SetStatus(int Status) { mStatus = Status; } void SetStatus(int Status) { mStatus = Status; }
// locks
void DeleteCar(int Ident); void DeleteCar(int Ident);
[[nodiscard]] std::set<std::string> GetIdentifiers() const { return mIdentifiers; } [[nodiscard]] std::set<std::string> GetIdentifiers() const { return mIdentifiers; }
[[nodiscard]] sockaddr_in GetUDPAddr() const { return mUDPAddress; } [[nodiscard]] sockaddr_in GetUDPAddr() const { return mUDPAddress; }
@@ -43,12 +44,14 @@ public:
[[nodiscard]] SOCKET GetTCPSock() const { return mSocket[0]; } [[nodiscard]] SOCKET GetTCPSock() const { return mSocket[0]; }
[[nodiscard]] std::string GetRoles() const { return mRole; } [[nodiscard]] std::string GetRoles() const { return mRole; }
[[nodiscard]] std::string GetName() const { return mName; } [[nodiscard]] std::string GetName() const { return mName; }
void SetUnicycleID(int ID) { mUnicycleID = ID; }
void SetID(int ID) { mID = ID; } void SetID(int ID) { mID = ID; }
[[nodiscard]] int GetOpenCarID() const; [[nodiscard]] int GetOpenCarID() const;
[[nodiscard]] int GetCarCount() const; [[nodiscard]] int GetCarCount() const;
void ClearCars(); void ClearCars();
[[nodiscard]] int GetStatus() const { return mStatus; } [[nodiscard]] int GetStatus() const { return mStatus; }
[[nodiscard]] int GetID() const { return mID; } [[nodiscard]] int GetID() const { return mID; }
[[nodiscard]] int GetUnicycleID() const { return mUnicycleID; }
[[nodiscard]] bool IsConnected() const { return mIsConnected; } [[nodiscard]] bool IsConnected() const { return mIsConnected; }
[[nodiscard]] bool IsSynced() const { return mIsSynced; } [[nodiscard]] bool IsSynced() const { return mIsSynced; }
[[nodiscard]] bool IsSyncing() const { return mIsSyncing; } [[nodiscard]] bool IsSyncing() const { return mIsSyncing; }
@@ -57,9 +60,9 @@ public:
void SetIsSynced(bool NewIsSynced) { mIsSynced = NewIsSynced; } void SetIsSynced(bool NewIsSynced) { mIsSynced = NewIsSynced; }
void SetIsSyncing(bool NewIsSyncing) { mIsSyncing = NewIsSyncing; } void SetIsSyncing(bool NewIsSyncing) { mIsSyncing = NewIsSyncing; }
void EnqueuePacket(const std::string& Packet); void EnqueuePacket(const std::string& Packet);
[[nodiscard]] std::queue<std::string>& MissedPacketQueue() { return mMissedPacketsDuringSyncing; } [[nodiscard]] std::queue<std::string>& MissedPacketQueue() { return mPacketsSync; }
[[nodiscard]] const std::queue<std::string>& MissedPacketQueue() const { return mMissedPacketsDuringSyncing; } [[nodiscard]] const std::queue<std::string>& MissedPacketQueue() const { return mPacketsSync; }
[[nodiscard]] size_t MissedPacketQueueSize() const { return mMissedPacketsDuringSyncing.size(); } [[nodiscard]] size_t MissedPacketQueueSize() const { return mPacketsSync.size(); }
[[nodiscard]] std::mutex& MissedPacketQueueMutex() const { return mMissedPacketsMutex; } [[nodiscard]] std::mutex& MissedPacketQueueMutex() const { return mMissedPacketsMutex; }
void SetIsConnected(bool NewIsConnected) { mIsConnected = NewIsConnected; } void SetIsConnected(bool NewIsConnected) { mIsConnected = NewIsConnected; }
[[nodiscard]] TServer& Server() const; [[nodiscard]] TServer& Server() const;
@@ -67,12 +70,14 @@ public:
int SecondsSinceLastPing(); int SecondsSinceLastPing();
private: private:
void InsertVehicle(int ID, const std::string& Data);
TServer& mServer; TServer& mServer;
bool mIsConnected = false; bool mIsConnected = false;
bool mIsSynced = false; bool mIsSynced = false;
bool mIsSyncing = false; bool mIsSyncing = false;
mutable std::mutex mMissedPacketsMutex; mutable std::mutex mMissedPacketsMutex;
std::queue<std::string> mMissedPacketsDuringSyncing; std::queue<std::string> mPacketsSync;
std::set<std::string> mIdentifiers; std::set<std::string> mIdentifiers;
bool mIsGuest = false; bool mIsGuest = false;
std::mutex mVehicleDataMutex; std::mutex mVehicleDataMutex;
@@ -80,6 +85,7 @@ private:
std::string mName = "Unknown Client"; std::string mName = "Unknown Client";
SOCKET mSocket[2] { SOCKET(-1) }; SOCKET mSocket[2] { SOCKET(-1) };
sockaddr_in mUDPAddress {}; // is this initialization OK? yes it is sockaddr_in mUDPAddress {}; // is this initialization OK? yes it is
int mUnicycleID = -1;
std::string mRole; std::string mRole;
std::string mDID; std::string mDID;
int mStatus = 0; int mStatus = 0;
+1 -1
View File
@@ -42,7 +42,7 @@ public:
// Causes all threads to finish up and exit gracefull gracefully // Causes all threads to finish up and exit gracefull gracefully
static void GracefullyShutdown(); static void GracefullyShutdown();
static TConsole& Console() { return *mConsole; } static TConsole& Console() { return *mConsole; }
static std::string ServerVersion() { return "2.0.1"; } static std::string ServerVersion() { return "2.0.2"; }
static std::string ClientVersion() { return "2.0"; } static std::string ClientVersion() { return "2.0"; }
static std::string PPS() { return mPPS; } static std::string PPS() { return mPPS; }
static void SetPPS(std::string NewPPS) { mPPS = NewPPS; } static void SetPPS(std::string NewPPS) { mPPS = NewPPS; }
+2
View File
@@ -31,5 +31,7 @@ private:
TClientSet mClients; TClientSet mClients;
mutable RWMutex mClientsMutex; mutable RWMutex mClientsMutex;
static void ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network); static void ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network);
static bool ShouldSpawn(TClient& c, const std::string& CarJson, int ID);
static bool IsUnicycle(TClient& c, const std::string& CarJson);
static void Apply(TClient& c, int VID, const std::string& pckt); static void Apply(TClient& c, int VID, const std::string& pckt);
}; };
+7 -2
View File
@@ -6,20 +6,25 @@ class TVehicleData final {
public: public:
TVehicleData(int ID, std::string Data); TVehicleData(int ID, std::string Data);
~TVehicleData(); ~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]] bool IsInvalid() const { return mID == -1; }
[[nodiscard]] int ID() const { return mID; } [[nodiscard]] int ID() const { return mID; }
[[nodiscard]] std::string Data() const { return mData; } [[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; } bool operator==(const TVehicleData& v) const { return mID == v.mID; }
private: private:
int mID { -1 }; int mID { -1 };
mutable std::string mData; std::string mData;
}; };
// TODO: unused now, remove?
namespace std { namespace std {
template <> template <>
struct hash<TVehicleData> { struct hash<TVehicleData> {
+28 -17
View File
@@ -6,15 +6,19 @@
// FIXME: add debug prints // FIXME: add debug prints
void TClient::DeleteCar(int Ident) { void TClient::DeleteCar(int Ident) {
for (auto& v : mVehicleData) { std::unique_lock lock(mVehicleDataMutex);
if (v.ID() == Ident) { auto iter = std::find_if(mVehicleData.begin(), mVehicleData.end(), [&](auto& elem) {
mVehicleData.erase(v); return Ident == elem.ID();
break; });
} if (iter != mVehicleData.end()) {
mVehicleData.erase(iter);
} else {
debug("tried to erase a vehicle that doesn't exist (not an error)");
} }
} }
void TClient::ClearCars() { void TClient::ClearCars() {
std::unique_lock lock(mVehicleDataMutex);
mVehicleData.clear(); mVehicleData.clear();
} }
@@ -34,30 +38,37 @@ int TClient::GetOpenCarID() const {
} }
void TClient::AddNewCar(int Ident, const std::string& Data) { void TClient::AddNewCar(int Ident, const std::string& Data) {
mVehicleData.emplace(Ident, Data); std::unique_lock lock(mVehicleDataMutex);
mVehicleData.emplace_back(Ident, Data);
} }
TClient::TVehicleDataLockPair TClient::GetAllCars() { TClient::TVehicleDataLockPair TClient::GetAllCars() {
return { mVehicleData, std::unique_lock(mVehicleDataMutex) }; return { &mVehicleData, std::unique_lock(mVehicleDataMutex) };
} }
std::string TClient::GetCarData(int Ident) { std::string TClient::GetCarData(int Ident) {
for (auto& v : mVehicleData) { { // lock
if (v.ID() == Ident) { std::unique_lock lock(mVehicleDataMutex);
return v.Data(); for (auto& v : mVehicleData) {
if (v.ID() == Ident) {
return v.Data();
}
} }
} } // unlock
DeleteCar(Ident); DeleteCar(Ident);
return ""; return "";
} }
void TClient::SetCarData(int Ident, const std::string& Data) { void TClient::SetCarData(int Ident, const std::string& Data) {
for (auto& v : mVehicleData) { { // lock
if (v.ID() == Ident) { std::unique_lock lock(mVehicleDataMutex);
v.SetData(Data); for (auto& v : mVehicleData) {
return; if (v.ID() == Ident) {
v.SetData(Data);
return;
}
} }
} } // unlock
DeleteCar(Ident); DeleteCar(Ident);
} }
@@ -71,7 +82,7 @@ TServer& TClient::Server() const {
void TClient::EnqueuePacket(const std::string& Packet) { void TClient::EnqueuePacket(const std::string& Packet) {
std::unique_lock Lock(mMissedPacketsMutex); std::unique_lock Lock(mMissedPacketsMutex);
mMissedPacketsDuringSyncing.push(Packet); mPacketsSync.push(Packet);
} }
TClient::TClient(TServer& Server) TClient::TClient(TServer& Server)
+1 -1
View File
@@ -342,7 +342,7 @@ int lua_GetCars(lua_State* L) {
TClient::TSetOfVehicleData VehicleData; TClient::TSetOfVehicleData VehicleData;
{ // Vehicle Data Lock Scope { // Vehicle Data Lock Scope
auto LockedData = Client->GetAllCars(); auto LockedData = Client->GetAllCars();
VehicleData = LockedData.VehicleData; VehicleData = *LockedData.VehicleData;
} // End Vehicle Data Lock Scope } // End Vehicle Data Lock Scope
if (VehicleData.empty()) if (VehicleData.empty())
return 0; return 0;
+21 -17
View File
@@ -88,11 +88,11 @@ void TNetwork::UDPServerMain() {
ReadLock Lock(mServer.GetClientMutex()); ReadLock Lock(mServer.GetClientMutex());
if (!ClientPtr.expired()) { if (!ClientPtr.expired()) {
Client = ClientPtr.lock(); Client = ClientPtr.lock();
}else return true; } else
return true;
} }
if (Client->GetID() == ID) { if (Client->GetID() == ID) {
Client->UpdatePingTime();
Client->SetUDPAddr(client); Client->SetUDPAddr(client);
Client->SetIsConnected(true); Client->SetIsConnected(true);
TServer::GlobalParser(ClientPtr, Data.substr(2), mPPSMonitor, *this); TServer::GlobalParser(ClientPtr, Data.substr(2), mPPSMonitor, *this);
@@ -312,7 +312,8 @@ void TNetwork::Authentication(SOCKET TCPSock) {
ReadLock Lock(mServer.GetClientMutex()); ReadLock Lock(mServer.GetClientMutex());
if (!ClientPtr.expired()) { if (!ClientPtr.expired()) {
Cl = ClientPtr.lock(); Cl = ClientPtr.lock();
} else return true; } else
return true;
} }
info("Client Iteration: Name -> " + Cl->GetName() + ", Guest -> " + std::to_string(Cl->IsGuest()) + ", Roles -> " + Cl->GetRoles()); info("Client Iteration: Name -> " + Cl->GetName() + ", Guest -> " + std::to_string(Cl->IsGuest()) + ", Roles -> " + Cl->GetRoles());
if (Cl->GetName() == Client->GetName() && Cl->IsGuest() == Client->IsGuest()) { if (Cl->GetName() == Client->GetName() && Cl->IsGuest() == Client->IsGuest()) {
@@ -354,8 +355,7 @@ std::shared_ptr<TClient> TNetwork::CreateClient(SOCKET TCPSock) {
bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) { bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
if (!IsSync) { if (!IsSync) {
if (c.IsSyncing()) { 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') { if (Data.at(0) == 'O' || Data.at(0) == 'A' || Data.at(0) == 'C' || Data.at(0) == 'E') {
c.EnqueuePacket(Data); c.EnqueuePacket(Data);
} }
@@ -364,7 +364,6 @@ bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
} }
} }
int32_t Size, Sent; int32_t Size, Sent;
std::string Send(4, 0); std::string Send(4, 0);
Size = int32_t(Data.size()); Size = int32_t(Data.size());
@@ -392,6 +391,7 @@ bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
} }
Sent += Temp; Sent += Temp;
} while (Sent < Size); } while (Sent < Size);
c.UpdatePingTime();
return true; return true;
} }
@@ -488,8 +488,8 @@ void TNetwork::ClientKick(TClient& c, const std::string& R) {
c.SetStatus(-2); c.SetStatus(-2);
CloseSocketProper(c.GetTCPSock()); CloseSocketProper(c.GetTCPSock());
} }
void TNetwork::Looper(const std::weak_ptr<TClient>& c){ void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
while(!c.expired()) { while (!c.expired()) {
auto Client = c.lock(); auto Client = c.lock();
if (Client->GetStatus() < 0) { if (Client->GetStatus() < 0) {
debug("client status < 0, breaking client loop"); debug("client status < 0, breaking client loop");
@@ -521,7 +521,7 @@ void TNetwork::Looper(const std::weak_ptr<TClient>& c){
break; break;
} }
} }
}else{ } else {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
} }
@@ -535,7 +535,7 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
OnConnect(c); OnConnect(c);
RegisterThread("(" + std::to_string(c.lock()->GetID()) + ") \"" + c.lock()->GetName() + "\""); 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) { while (true) {
if (c.expired()) if (c.expired())
@@ -553,7 +553,8 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
} }
TServer::GlobalParser(c, res, mPPSMonitor, *this); TServer::GlobalParser(c, res, mPPSMonitor, *this);
} }
if(QueueSync.joinable())QueueSync.join(); if (QueueSync.joinable())
QueueSync.join();
if (!c.expired()) { if (!c.expired()) {
auto Client = c.lock(); auto Client = c.lock();
@@ -574,7 +575,8 @@ void TNetwork::UpdatePlayer(TClient& Client) {
return true; return true;
}); });
Packet = Packet.substr(0, Packet.length() - 1); Packet = Packet.substr(0, Packet.length() - 1);
(void)Respond(Client, Packet, true); Client.EnqueuePacket(Packet);
//(void)Respond(Client, Packet, true);
} }
void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked) { void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked) {
@@ -586,7 +588,7 @@ void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked
TClient::TSetOfVehicleData VehicleData; TClient::TSetOfVehicleData VehicleData;
{ // Vehicle Data Lock Scope { // Vehicle Data Lock Scope
auto LockedData = c.GetAllCars(); auto LockedData = c.GetAllCars();
VehicleData = LockedData.VehicleData; VehicleData = *LockedData.VehicleData;
} // End Vehicle Data Lock Scope } // 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()); Packet = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(v.ID());
@@ -836,12 +838,13 @@ bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
ReadLock Lock(mServer.GetClientMutex()); ReadLock Lock(mServer.GetClientMutex());
if (!ClientPtr.expired()) { if (!ClientPtr.expired()) {
client = ClientPtr.lock(); client = ClientPtr.lock();
} else return true; } else
return true;
} }
TClient::TSetOfVehicleData VehicleData; TClient::TSetOfVehicleData VehicleData;
{ // Vehicle Data Lock Scope { // Vehicle Data Lock Scope
auto LockedData = client->GetAllCars(); auto LockedData = client->GetAllCars();
VehicleData = LockedData.VehicleData; VehicleData = *LockedData.VehicleData;
} // End Vehicle Data Lock Scope } // End Vehicle Data Lock Scope
if (client != LockedClient) { if (client != LockedClient) {
for (auto& v : VehicleData) { for (auto& v : VehicleData) {
@@ -877,7 +880,8 @@ void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Re
ReadLock Lock(mServer.GetClientMutex()); ReadLock Lock(mServer.GetClientMutex());
if (!ClientPtr.expired()) { if (!ClientPtr.expired()) {
Client = ClientPtr.lock(); Client = ClientPtr.lock();
}else return true; } else
return true;
} }
if (Self || Client.get() != c) { if (Self || Client.get() != c) {
if (Client->IsSynced() || Client->IsSyncing()) { 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) { if (Data.length() > 400) {
std::string CMP(Comp(Data)); std::string CMP(Comp(Data));
Client->EnqueuePacket("ABG:" + CMP); Client->EnqueuePacket("ABG:" + CMP);
}else{ } else {
Client->EnqueuePacket(Data); Client->EnqueuePacket(Data);
} }
//ret = SendLarge(*Client, Data); //ret = SendLarge(*Client, Data);
+2 -2
View File
@@ -46,7 +46,7 @@ void TPPSMonitor::operator()() {
c->UpdatePingTime(); c->UpdatePingTime();
} }
// kick on "no ping" // kick on "no ping"
if (c->SecondsSinceLastPing() > 60 && c->IsSynced() && !c->IsSyncing()) { if (c->SecondsSinceLastPing() > 30 && c->IsSynced() && !c->IsSyncing()) {
debug("client " + std::string("(") + std::to_string(c->GetID()) + ")" + c->GetName() + " timing out: " + std::to_string(c->SecondsSinceLastPing()) + ", pps: " + Application::PPS()); debug("client " + std::string("(") + std::to_string(c->GetID()) + ")" + c->GetName() + " timing out: " + std::to_string(c->SecondsSinceLastPing()) + ", pps: " + Application::PPS());
TimedOutClients.push_back(c); TimedOutClients.push_back(c);
} }
@@ -54,7 +54,7 @@ void TPPSMonitor::operator()() {
return true; return true;
}); });
for (auto& ClientToKick : TimedOutClients) { for (auto& ClientToKick : TimedOutClients) {
Network().ClientKick(*ClientToKick, "Timeout (no ping for >60 seconds)"); Network().ClientKick(*ClientToKick, "Timeout (no ping for >30 seconds)");
} }
TimedOutClients.clear(); TimedOutClients.clear();
if (C == 0 || mInternalPPS == 0) { if (C == 0 || mInternalPPS == 0) {
+41 -7
View File
@@ -108,7 +108,6 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
} else { } else {
Network.UpdatePlayer(*LockedClient); Network.UpdatePlayer(*LockedClient);
} }
LockedClient->UpdatePingTime();
return; return;
case 'O': case 'O':
if (Packet.length() > 1000) { if (Packet.length() > 1000) {
@@ -164,6 +163,29 @@ void TServer::HandleEvent(TClient& c, const std::string& Data) {
a++; a++;
} }
} }
bool TServer::IsUnicycle(TClient &c, const std::string &CarJson) {
rapidjson::Document Car;
Car.Parse(CarJson.c_str(), CarJson.size());
if(Car.HasParseError()){
error("Failed to parse vehicle data -> " + CarJson);
} else if (Car["jbm"].IsString() && std::string(Car["jbm"].GetString()) == "unicycle") {
return true;
}
return false;
}
bool TServer::ShouldSpawn(TClient& c, const std::string& CarJson, int ID) {
if(c.GetUnicycleID() > -1 && (c.GetCarCount() - 1) < Application::Settings.MaxCars){
return true;
}
if(IsUnicycle(c,CarJson)){
c.SetUnicycleID(ID);
return true;
}
return Application::Settings.MaxCars > c.GetCarCount();
}
void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network) { void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network) {
if (Pckt.length() < 4) if (Pckt.length() < 4)
@@ -181,9 +203,15 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
if (Data.at(0) == '0') { if (Data.at(0) == '0') {
int CarID = c.GetOpenCarID(); int CarID = c.GetOpenCarID();
debug(c.GetName() + (" created a car with ID ") + std::to_string(CarID)); debug(c.GetName() + (" created a car with ID ") + std::to_string(CarID));
Packet = "Os:" + c.GetRoles() + ":" + c.GetName() + ":" + std::to_string(c.GetID()) + "-" + std::to_string(CarID) + Packet.substr(4);
std::string CarJson = Packet.substr(5);
Packet = "Os:" + c.GetRoles() + ":" + c.GetName() + ":" + std::to_string(c.GetID()) + "-" + std::to_string(CarID) + ":" + CarJson;
auto Res = TriggerLuaEvent(("onVehicleSpawn"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), CarID, Packet.substr(3) } }), true); auto Res = TriggerLuaEvent(("onVehicleSpawn"), false, nullptr, std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), CarID, Packet.substr(3) } }), true);
if (c.GetCarCount() >= Application::Settings.MaxCars || std::any_cast<int>(Res)) {
if (ShouldSpawn(c, CarJson, CarID) && std::any_cast<int>(Res) == 0) {
c.AddNewCar(CarID, Packet);
Network.SendToAll(nullptr, Packet, true, true);
} else {
if (!Network.Respond(c, Packet, true)) { if (!Network.Respond(c, Packet, true)) {
// TODO: handle // TODO: handle
} }
@@ -192,9 +220,6 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
// TODO: handle // TODO: handle
} }
debug(c.GetName() + (" (force : car limit/lua) removed ID ") + std::to_string(CarID)); debug(c.GetName() + (" (force : car limit/lua) removed ID ") + std::to_string(CarID));
} else {
c.AddNewCar(CarID, Packet);
Network.SendToAll(nullptr, Packet, true, true);
} }
} }
return; return;
@@ -212,10 +237,15 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
auto Res = TriggerLuaEvent(("onVehicleEdited"), false, nullptr, auto Res = TriggerLuaEvent(("onVehicleEdited"), false, nullptr,
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID, Packet.substr(3) } }), std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID, Packet.substr(3) } }),
true); true);
if (!std::any_cast<int>(Res)) {
if ((c.GetUnicycleID() != VID || IsUnicycle(c,Packet.substr(Packet.find('{'))))
&& std::any_cast<int>(Res) == 0) {
Network.SendToAll(&c, Packet, false, true); Network.SendToAll(&c, Packet, false, true);
Apply(c, VID, Packet); Apply(c, VID, Packet);
} else { } else {
if(c.GetUnicycleID() == VID){
c.SetUnicycleID(-1);
}
std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(VID); std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(VID);
if (!Network.Respond(c, Destroy, true)) { if (!Network.Respond(c, Destroy, true)) {
// TODO: handle // TODO: handle
@@ -235,6 +265,9 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
VID = stoi(vid); VID = stoi(vid);
} }
if (PID != -1 && VID != -1 && PID == c.GetID()) { if (PID != -1 && VID != -1 && PID == c.GetID()) {
if(c.GetUnicycleID() == VID){
c.SetUnicycleID(-1);
}
Network.SendToAll(nullptr, Packet, true, true); Network.SendToAll(nullptr, Packet, true, true);
TriggerLuaEvent(("onVehicleDeleted"), false, nullptr, TriggerLuaEvent(("onVehicleDeleted"), false, nullptr,
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID } }), false); std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID } }), false);
@@ -280,6 +313,7 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
void TServer::Apply(TClient& c, int VID, const std::string& pckt) { void TServer::Apply(TClient& c, int VID, const std::string& pckt) {
std::string Packet = pckt.substr(pckt.find('{')), VD = c.GetCarData(VID); std::string Packet = pckt.substr(pckt.find('{')), VD = c.GetCarData(VID);
std::string Header = VD.substr(0, VD.find('{')); std::string Header = VD.substr(0, VD.find('{'));
VD = VD.substr(VD.find('{')); VD = VD.substr(VD.find('{'));
rapidjson::Document Veh, Pack; rapidjson::Document Veh, Pack;
Veh.Parse(VD.c_str()); Veh.Parse(VD.c_str());