mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-07-13 10:13:42 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 573bd77bbd | |||
| 770e03e3c6 | |||
| 11d4522dc7 | |||
| 830bc47987 | |||
| bec698fbdc | |||
| 60cc835daf | |||
| a85ce18589 | |||
| 1228c2fabe | |||
| 3da0af37e4 | |||
| baa41dd65a | |||
| 534b457f48 | |||
| 029cf94e68 | |||
| 15f7a6ba85 | |||
| 86b5d91579 | |||
| 31486bcb56 | |||
| 08660d83dc | |||
| 6d8f75a577 | |||
| 018246cea5 | |||
| a584e25bf3 | |||
| d4d773b769 | |||
| 56a02f0215 | |||
| 7231c69e10 | |||
| 3c68dfaeaf |
@@ -22,7 +22,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
release_name: ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: |
|
||||
|
||||
@@ -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
@@ -14,10 +14,10 @@ class TServer;
|
||||
|
||||
class TClient final {
|
||||
public:
|
||||
using TSetOfVehicleData = std::unordered_set<TVehicleData>;
|
||||
using TSetOfVehicleData = std::vector<TVehicleData>;
|
||||
|
||||
struct TVehicleDataLockPair {
|
||||
TSetOfVehicleData& VehicleData;
|
||||
TSetOfVehicleData* VehicleData;
|
||||
std::unique_lock<std::mutex> Lock;
|
||||
};
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; }
|
||||
void SetTCPSock(SOCKET CSock) { mSocket[0] = CSock; }
|
||||
void SetStatus(int Status) { mStatus = Status; }
|
||||
// locks
|
||||
void DeleteCar(int Ident);
|
||||
[[nodiscard]] std::set<std::string> GetIdentifiers() const { return mIdentifiers; }
|
||||
[[nodiscard]] sockaddr_in GetUDPAddr() const { return mUDPAddress; }
|
||||
@@ -43,12 +44,14 @@ public:
|
||||
[[nodiscard]] SOCKET GetTCPSock() const { return mSocket[0]; }
|
||||
[[nodiscard]] std::string GetRoles() const { return mRole; }
|
||||
[[nodiscard]] std::string GetName() const { return mName; }
|
||||
void SetUnicycleID(int ID) { mUnicycleID = ID; }
|
||||
void SetID(int ID) { mID = ID; }
|
||||
[[nodiscard]] int GetOpenCarID() const;
|
||||
[[nodiscard]] int GetCarCount() const;
|
||||
void ClearCars();
|
||||
[[nodiscard]] int GetStatus() const { return mStatus; }
|
||||
[[nodiscard]] int GetID() const { return mID; }
|
||||
[[nodiscard]] int GetUnicycleID() const { return mUnicycleID; }
|
||||
[[nodiscard]] bool IsConnected() const { return mIsConnected; }
|
||||
[[nodiscard]] bool IsSynced() const { return mIsSynced; }
|
||||
[[nodiscard]] bool IsSyncing() const { return mIsSyncing; }
|
||||
@@ -57,9 +60,9 @@ public:
|
||||
void SetIsSynced(bool NewIsSynced) { mIsSynced = NewIsSynced; }
|
||||
void SetIsSyncing(bool NewIsSyncing) { mIsSyncing = NewIsSyncing; }
|
||||
void EnqueuePacket(const std::string& Packet);
|
||||
[[nodiscard]] std::queue<std::string>& MissedPacketQueue() { return mMissedPacketsDuringSyncing; }
|
||||
[[nodiscard]] const std::queue<std::string>& MissedPacketQueue() const { return mMissedPacketsDuringSyncing; }
|
||||
[[nodiscard]] size_t MissedPacketQueueSize() const { return mMissedPacketsDuringSyncing.size(); }
|
||||
[[nodiscard]] std::queue<std::string>& MissedPacketQueue() { return mPacketsSync; }
|
||||
[[nodiscard]] const std::queue<std::string>& MissedPacketQueue() const { return mPacketsSync; }
|
||||
[[nodiscard]] size_t MissedPacketQueueSize() const { return mPacketsSync.size(); }
|
||||
[[nodiscard]] std::mutex& MissedPacketQueueMutex() const { return mMissedPacketsMutex; }
|
||||
void SetIsConnected(bool NewIsConnected) { mIsConnected = NewIsConnected; }
|
||||
[[nodiscard]] TServer& Server() const;
|
||||
@@ -67,12 +70,14 @@ public:
|
||||
int SecondsSinceLastPing();
|
||||
|
||||
private:
|
||||
void InsertVehicle(int ID, const std::string& Data);
|
||||
|
||||
TServer& mServer;
|
||||
bool mIsConnected = false;
|
||||
bool mIsSynced = false;
|
||||
bool mIsSyncing = false;
|
||||
mutable std::mutex mMissedPacketsMutex;
|
||||
std::queue<std::string> mMissedPacketsDuringSyncing;
|
||||
std::queue<std::string> mPacketsSync;
|
||||
std::set<std::string> mIdentifiers;
|
||||
bool mIsGuest = false;
|
||||
std::mutex mVehicleDataMutex;
|
||||
@@ -80,6 +85,7 @@ private:
|
||||
std::string mName = "Unknown Client";
|
||||
SOCKET mSocket[2] { SOCKET(-1) };
|
||||
sockaddr_in mUDPAddress {}; // is this initialization OK? yes it is
|
||||
int mUnicycleID = -1;
|
||||
std::string mRole;
|
||||
std::string mDID;
|
||||
int mStatus = 0;
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public:
|
||||
// Causes all threads to finish up and exit gracefull gracefully
|
||||
static void GracefullyShutdown();
|
||||
static TConsole& Console() { return *mConsole; }
|
||||
static std::string ServerVersion() { return "2.0.1"; }
|
||||
static std::string ServerVersion() { return "2.0.3"; }
|
||||
static std::string ClientVersion() { return "2.0"; }
|
||||
static std::string PPS() { return mPPS; }
|
||||
static void SetPPS(std::string NewPPS) { mPPS = NewPPS; }
|
||||
|
||||
+1
-1
@@ -44,6 +44,6 @@ private:
|
||||
void OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked);
|
||||
void Parse(TClient& c, const std::string& Packet);
|
||||
void SendFile(TClient& c, const std::string& Name);
|
||||
static bool TCPSendRaw(SOCKET C, char* Data, int32_t Size);
|
||||
static bool TCPSendRaw(TClient& C, SOCKET socket, char* Data, int32_t Size);
|
||||
static void SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std::string& Name);
|
||||
};
|
||||
|
||||
@@ -31,5 +31,7 @@ private:
|
||||
TClientSet mClients;
|
||||
mutable RWMutex mClientsMutex;
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -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<TVehicleData> {
|
||||
|
||||
+1
-1
Submodule include/commandline updated: 412ece748d...0860266a2a
+28
-17
@@ -6,15 +6,19 @@
|
||||
// FIXME: add debug prints
|
||||
|
||||
void TClient::DeleteCar(int Ident) {
|
||||
for (auto& v : mVehicleData) {
|
||||
if (v.ID() == Ident) {
|
||||
mVehicleData.erase(v);
|
||||
break;
|
||||
}
|
||||
std::unique_lock lock(mVehicleDataMutex);
|
||||
auto iter = std::find_if(mVehicleData.begin(), mVehicleData.end(), [&](auto& elem) {
|
||||
return Ident == elem.ID();
|
||||
});
|
||||
if (iter != mVehicleData.end()) {
|
||||
mVehicleData.erase(iter);
|
||||
} else {
|
||||
debug("tried to erase a vehicle that doesn't exist (not an error)");
|
||||
}
|
||||
}
|
||||
|
||||
void TClient::ClearCars() {
|
||||
std::unique_lock lock(mVehicleDataMutex);
|
||||
mVehicleData.clear();
|
||||
}
|
||||
|
||||
@@ -34,30 +38,37 @@ int TClient::GetOpenCarID() const {
|
||||
}
|
||||
|
||||
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() {
|
||||
return { mVehicleData, std::unique_lock(mVehicleDataMutex) };
|
||||
return { &mVehicleData, std::unique_lock(mVehicleDataMutex) };
|
||||
}
|
||||
|
||||
std::string TClient::GetCarData(int Ident) {
|
||||
for (auto& v : mVehicleData) {
|
||||
if (v.ID() == Ident) {
|
||||
return v.Data();
|
||||
{ // lock
|
||||
std::unique_lock lock(mVehicleDataMutex);
|
||||
for (auto& v : mVehicleData) {
|
||||
if (v.ID() == Ident) {
|
||||
return v.Data();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // unlock
|
||||
DeleteCar(Ident);
|
||||
return "";
|
||||
}
|
||||
|
||||
void TClient::SetCarData(int Ident, const std::string& Data) {
|
||||
for (auto& v : mVehicleData) {
|
||||
if (v.ID() == Ident) {
|
||||
v.SetData(Data);
|
||||
return;
|
||||
{ // lock
|
||||
std::unique_lock lock(mVehicleDataMutex);
|
||||
for (auto& v : mVehicleData) {
|
||||
if (v.ID() == Ident) {
|
||||
v.SetData(Data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // unlock
|
||||
DeleteCar(Ident);
|
||||
}
|
||||
|
||||
@@ -71,7 +82,7 @@ TServer& TClient::Server() const {
|
||||
|
||||
void TClient::EnqueuePacket(const std::string& Packet) {
|
||||
std::unique_lock Lock(mMissedPacketsMutex);
|
||||
mMissedPacketsDuringSyncing.push(Packet);
|
||||
mPacketsSync.push(Packet);
|
||||
}
|
||||
|
||||
TClient::TClient(TServer& Server)
|
||||
|
||||
+1
-1
@@ -342,7 +342,7 @@ int lua_GetCars(lua_State* L) {
|
||||
TClient::TSetOfVehicleData VehicleData;
|
||||
{ // Vehicle Data Lock Scope
|
||||
auto LockedData = Client->GetAllCars();
|
||||
VehicleData = LockedData.VehicleData;
|
||||
VehicleData = *LockedData.VehicleData;
|
||||
} // End Vehicle Data Lock Scope
|
||||
if (VehicleData.empty())
|
||||
return 0;
|
||||
|
||||
+28
-24
@@ -88,11 +88,11 @@ void TNetwork::UDPServerMain() {
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
Client = ClientPtr.lock();
|
||||
}else return true;
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Client->GetID() == ID) {
|
||||
Client->UpdatePingTime();
|
||||
Client->SetUDPAddr(client);
|
||||
Client->SetIsConnected(true);
|
||||
TServer::GlobalParser(ClientPtr, Data.substr(2), mPPSMonitor, *this);
|
||||
@@ -312,7 +312,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()) {
|
||||
@@ -354,8 +355,7 @@ std::shared_ptr<TClient> TNetwork::CreateClient(SOCKET TCPSock) {
|
||||
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 +364,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());
|
||||
@@ -391,6 +390,7 @@ bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
|
||||
return false;
|
||||
}
|
||||
Sent += Temp;
|
||||
c.UpdatePingTime();
|
||||
} while (Sent < Size);
|
||||
return true;
|
||||
}
|
||||
@@ -488,8 +488,8 @@ void TNetwork::ClientKick(TClient& c, const std::string& R) {
|
||||
c.SetStatus(-2);
|
||||
CloseSocketProper(c.GetTCPSock());
|
||||
}
|
||||
void TNetwork::Looper(const std::weak_ptr<TClient>& c){
|
||||
while(!c.expired()) {
|
||||
void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
|
||||
while (!c.expired()) {
|
||||
auto Client = c.lock();
|
||||
if (Client->GetStatus() < 0) {
|
||||
debug("client status < 0, breaking client loop");
|
||||
@@ -521,7 +521,7 @@ void TNetwork::Looper(const std::weak_ptr<TClient>& c){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
@@ -535,7 +535,7 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& 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 +553,8 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
||||
}
|
||||
TServer::GlobalParser(c, res, mPPSMonitor, *this);
|
||||
}
|
||||
if(QueueSync.joinable())QueueSync.join();
|
||||
if (QueueSync.joinable())
|
||||
QueueSync.join();
|
||||
|
||||
if (!c.expired()) {
|
||||
auto Client = c.lock();
|
||||
@@ -574,7 +575,8 @@ void TNetwork::UpdatePlayer(TClient& Client) {
|
||||
return true;
|
||||
});
|
||||
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) {
|
||||
@@ -586,7 +588,7 @@ void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked
|
||||
TClient::TSetOfVehicleData VehicleData;
|
||||
{ // Vehicle Data Lock Scope
|
||||
auto LockedData = c.GetAllCars();
|
||||
VehicleData = LockedData.VehicleData;
|
||||
VehicleData = *LockedData.VehicleData;
|
||||
} // End Vehicle Data Lock Scope
|
||||
for (auto& v : VehicleData) {
|
||||
Packet = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(v.ID());
|
||||
@@ -755,7 +757,7 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std
|
||||
if (Diff > Split) {
|
||||
f.seekg(Sent, std::ios_base::beg);
|
||||
f.read(Data, Split);
|
||||
if (!TCPSendRaw(TCPSock, Data, Split)) {
|
||||
if (!TCPSendRaw(c, TCPSock, Data, Split)) {
|
||||
if (c.GetStatus() > -1)
|
||||
c.SetStatus(-1);
|
||||
break;
|
||||
@@ -764,7 +766,7 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std
|
||||
} else {
|
||||
f.seekg(Sent, std::ios_base::beg);
|
||||
f.read(Data, Diff);
|
||||
if (!TCPSendRaw(TCPSock, Data, int32_t(Diff))) {
|
||||
if (!TCPSendRaw(c, TCPSock, Data, int32_t(Diff))) {
|
||||
if (c.GetStatus() > -1)
|
||||
c.SetStatus(-1);
|
||||
break;
|
||||
@@ -776,16 +778,17 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std
|
||||
f.close();
|
||||
}
|
||||
|
||||
bool TNetwork::TCPSendRaw(SOCKET C, char* Data, int32_t Size) {
|
||||
bool TNetwork::TCPSendRaw(TClient& C, SOCKET socket, char* Data, int32_t Size) {
|
||||
intmax_t Sent = 0;
|
||||
do {
|
||||
intmax_t Temp = send(C, &Data[Sent], int(Size - Sent), 0);
|
||||
intmax_t Temp = send(socket, &Data[Sent], int(Size - Sent), 0);
|
||||
if (Temp < 1) {
|
||||
info("Socket Closed! " + std::to_string(C));
|
||||
CloseSocketProper(C);
|
||||
info("Socket Closed! " + std::to_string(socket));
|
||||
CloseSocketProper(socket);
|
||||
return false;
|
||||
}
|
||||
Sent += Temp;
|
||||
C.UpdatePingTime();
|
||||
} while (Sent < Size);
|
||||
return true;
|
||||
}
|
||||
@@ -836,12 +839,13 @@ bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
client = ClientPtr.lock();
|
||||
} else return true;
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
TClient::TSetOfVehicleData VehicleData;
|
||||
{ // Vehicle Data Lock Scope
|
||||
auto LockedData = client->GetAllCars();
|
||||
VehicleData = LockedData.VehicleData;
|
||||
VehicleData = *LockedData.VehicleData;
|
||||
} // End Vehicle Data Lock Scope
|
||||
if (client != LockedClient) {
|
||||
for (auto& v : VehicleData) {
|
||||
@@ -851,7 +855,6 @@ bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
||||
return false;
|
||||
}
|
||||
res = Respond(*LockedClient, v.Data(), true, true);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
+4
-6
@@ -36,17 +36,15 @@ void TPPSMonitor::operator()() {
|
||||
ReadLock Lock(mServer.GetClientMutex());
|
||||
if (!ClientPtr.expired()) {
|
||||
c = ClientPtr.lock();
|
||||
} else return true;
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
if (c->GetCarCount() > 0) {
|
||||
C++;
|
||||
V += c->GetCarCount();
|
||||
}
|
||||
if (!c->IsSynced() || c->IsSyncing()) {
|
||||
c->UpdatePingTime();
|
||||
}
|
||||
// kick on "no ping"
|
||||
if (c->SecondsSinceLastPing() > 60 && c->IsSynced() && !c->IsSyncing()) {
|
||||
if (c->SecondsSinceLastPing() > (5 * 60)) {
|
||||
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);
|
||||
}
|
||||
@@ -54,7 +52,7 @@ void TPPSMonitor::operator()() {
|
||||
return true;
|
||||
});
|
||||
for (auto& ClientToKick : TimedOutClients) {
|
||||
Network().ClientKick(*ClientToKick, "Timeout (no ping for >60 seconds)");
|
||||
Network().ClientKick(*ClientToKick, "Timeout (no ping for >5 min)");
|
||||
}
|
||||
TimedOutClients.clear();
|
||||
if (C == 0 || mInternalPPS == 0) {
|
||||
|
||||
+41
-7
@@ -108,7 +108,6 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::string Pac
|
||||
} else {
|
||||
Network.UpdatePlayer(*LockedClient);
|
||||
}
|
||||
LockedClient->UpdatePingTime();
|
||||
return;
|
||||
case 'O':
|
||||
if (Packet.length() > 1000) {
|
||||
@@ -164,6 +163,29 @@ void TServer::HandleEvent(TClient& c, const std::string& Data) {
|
||||
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) {
|
||||
if (Pckt.length() < 4)
|
||||
@@ -181,9 +203,15 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
||||
if (Data.at(0) == '0') {
|
||||
int CarID = c.GetOpenCarID();
|
||||
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);
|
||||
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)) {
|
||||
// TODO: handle
|
||||
}
|
||||
@@ -192,9 +220,6 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
||||
// TODO: handle
|
||||
}
|
||||
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;
|
||||
@@ -212,10 +237,15 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
||||
auto Res = TriggerLuaEvent(("onVehicleEdited"), false, nullptr,
|
||||
std::make_unique<TLuaArg>(TLuaArg { { c.GetID(), VID, Packet.substr(3) } }),
|
||||
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);
|
||||
Apply(c, VID, Packet);
|
||||
} else {
|
||||
if(c.GetUnicycleID() == VID){
|
||||
c.SetUnicycleID(-1);
|
||||
}
|
||||
std::string Destroy = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(VID);
|
||||
if (!Network.Respond(c, Destroy, true)) {
|
||||
// TODO: handle
|
||||
@@ -235,6 +265,9 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
||||
VID = stoi(vid);
|
||||
}
|
||||
if (PID != -1 && VID != -1 && PID == c.GetID()) {
|
||||
if(c.GetUnicycleID() == VID){
|
||||
c.SetUnicycleID(-1);
|
||||
}
|
||||
Network.SendToAll(nullptr, Packet, true, true);
|
||||
TriggerLuaEvent(("onVehicleDeleted"), false, nullptr,
|
||||
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) {
|
||||
std::string Packet = pckt.substr(pckt.find('{')), VD = c.GetCarData(VID);
|
||||
std::string Header = VD.substr(0, VD.find('{'));
|
||||
|
||||
VD = VD.substr(VD.find('{'));
|
||||
rapidjson::Document Veh, Pack;
|
||||
Veh.Parse(VD.c_str());
|
||||
|
||||
Reference in New Issue
Block a user