From bf9d4d8f22f111821b10ee7d4f3d32d56c8d024e Mon Sep 17 00:00:00 2001 From: iAmir Date: Mon, 12 Aug 2024 08:20:29 +0330 Subject: [PATCH] cache generated BS for a short period of time for scoreboard rpc --- Server/Source/player_pool.hpp | 10 ++++++++-- Shared/NetCode/core.hpp | 21 ++++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Server/Source/player_pool.hpp b/Server/Source/player_pool.hpp index e7c775e16..bf27fead0 100644 --- a/Server/Source/player_pool.hpp +++ b/Server/Source/player_pool.hpp @@ -46,6 +46,7 @@ struct PlayerPool final : public IPlayerPool, public NetworkEventHandler, public bool* allowInteriorWeapons_; int* maxBots; StaticArray allowNickCharacter; + TimePoint lastScoresAndPingsCached; struct PlayerRequestSpawnRPCHandler : public SingleNetworkInEventHandler { @@ -95,9 +96,13 @@ struct PlayerPool final : public IPlayerPool, public NetworkEventHandler, public const TimePoint now = Time::now(); // SA:MP client is nice and makes this request every 3 seconds. - if (now - player.lastScoresAndPings_ >= Seconds(2)) + // But not every client is the official one... so I guess we need a hard limit for player here as well + if (now - player.lastScoresAndPings_ >= Seconds(3)) { - NetCode::RPC::SendPlayerScoresAndPings sendPlayerScoresAndPingsRPC(self.storage.entries()); + // There is also a cache tick diff we are sending to SendPlayerScoresAndPings constructor to use in SendPlayerScoresAndPings::write + // This is added to make sure we have a global cache and we don't recalculate and regenerate for every player and every request of theirs + // So instead it keeps a cache of our bitstream to use, which won't loop through player pool and gathering data + NetCode::RPC::SendPlayerScoresAndPings sendPlayerScoresAndPingsRPC(self.storage.entries(), now - self.lastScoresAndPingsCached); PacketHelper::send(sendPlayerScoresAndPingsRPC, peer); player.lastScoresAndPings_ = now; } @@ -1820,6 +1825,7 @@ struct PlayerPool final : public IPlayerPool, public NetworkEventHandler, public PlayerPool(ICore& core) : core(core) , networks(core.getNetworks()) + , lastScoresAndPingsCached(Time::now()) , playerRequestSpawnRPCHandler(*this) , playerRequestScoresAndPingsRPCHandler(*this) , onPlayerClickMapRPCHandler(*this) diff --git a/Shared/NetCode/core.hpp b/Shared/NetCode/core.hpp index f1b7bd0b1..c571f967a 100644 --- a/Shared/NetCode/core.hpp +++ b/Shared/NetCode/core.hpp @@ -1123,9 +1123,11 @@ namespace RPC struct SendPlayerScoresAndPings : NetworkPacketBase<155, NetworkPacketType::RPC, OrderingChannel_SyncRPC> { const FlatPtrHashSet& Players; + const Nanoseconds LastCachedTickDiff; - SendPlayerScoresAndPings(const FlatPtrHashSet& players) + SendPlayerScoresAndPings(const FlatPtrHashSet& players, Nanoseconds lastCachedTickDiff) : Players(players) + , LastCachedTickDiff(lastCachedTickDiff) { } @@ -1136,12 +1138,21 @@ namespace RPC void write(NetworkBitStream& bs) const { - for (IPlayer* player : Players) + // This is added to make sure we have a global cache and we don't recalculate and regenerate for every player and every request of theirs + // So instead it keeps a cache of our bitstream to use, which won't loop through player pool and gathering data + static NetworkBitStream cache; + if (LastCachedTickDiff >= Seconds(2)) { - bs.writeUINT16(player->getID()); - bs.writeINT32(player->getScore()); - bs.writeUINT32(player->getPing()); + cache.reset(); + for (IPlayer* player : Players) + { + cache.writeUINT16(player->getID()); + cache.writeINT32(player->getScore()); + cache.writeUINT32(player->getPing()); + } } + + bs.WriteBits(cache.GetData(), cache.GetNumberOfBitsUsed()); } };