Skip to content

Commit

Permalink
Network fixes + Sign Improvements
Browse files Browse the repository at this point in the history
- Fixed ack sequence going out of sync if large amounts of messages are recieved on the same update.
- We will now notify players with awareness of a sign that its been removed when appropriate.
- Packet length for TCP connections increased, steam tickets can be chonky.
  • Loading branch information
TLeonardUK committed Feb 12, 2022
1 parent 49de66c commit e6057a1
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Source/Server/Config/BuildConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class BuildConfig
inline static const double AUTH_TICKET_TIMEOUT = 30.0;

// Maximum length of a packet in an Frpg2PacketStream.
inline static const int MAX_PACKET_LENGTH = 2048;
inline static const int MAX_PACKET_LENGTH = 8192;

// Maximum backlog of data in a packet streams send queue. Sending
// packets beyond this will result in disconnect.
Expand Down
7 changes: 7 additions & 0 deletions Source/Server/Server/Database/DatabaseTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

#include "Protobuf/Protobufs.h"

#include <unordered_set>

// Blood message stored in the database or live cache.
struct BloodMessage
{
Expand Down Expand Up @@ -71,6 +73,11 @@ struct SummonSign
std::vector<uint8_t> PlayerStruct;

uint32_t BeingSummonedByPlayerId = 0;

// These are all the players that are aware of this sign via
// requesting it. We use this to send removal messages when the
// sign is destroyed.
std::unordered_set<uint32_t> AwarePlayerIds;
};

// Individual ranking in a leaderboard.
Expand Down
57 changes: 31 additions & 26 deletions Source/Server/Server/GameService/GameManagers/Signs/SignManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,36 @@ void SignManager::OnLostPlayer(GameClient* Client)
// Remove all the players signs from the cache.
for (std::shared_ptr<SummonSign> Sign : Client->ActiveSummonSigns)
{
LiveCache.Remove(Sign->OnlineAreaId, Sign->SignId);
RemoveSignAndNotifyAware(Sign);
}
Client->ActiveSummonSigns.clear();
}

void SignManager::RemoveSignAndNotifyAware(const std::shared_ptr<SummonSign>& Sign)
{
LiveCache.Remove((OnlineAreaId)Sign->OnlineAreaId, Sign->SignId);

// Tell anyone who is aware of this sign that its been removed.
for (uint32_t AwarePlayerId : Sign->AwarePlayerIds)
{
if (std::shared_ptr<GameClient> OtherClient = GameServiceInstance->FindClientByPlayerId(AwarePlayerId))
{
Frpg2RequestMessage::PushRequestRemoveSign PushMessage;
PushMessage.set_push_message_id(Frpg2RequestMessage::PushID_PushRequestRemoveSign);
PushMessage.mutable_message()->set_player_id(Sign->PlayerId);
PushMessage.mutable_message()->set_sign_id(Sign->SignId);

if (!OtherClient->MessageStream->Send(&PushMessage))
{
WarningS(OtherClient->GetName().c_str(), "Failed to send PushRequestRemoveSign to aware player.");
}
}
}

Sign->BeingSummonedByPlayerId = 0;
Sign->AwarePlayerIds.clear();
}

void SignManager::Poll()
{
}
Expand Down Expand Up @@ -163,6 +188,9 @@ MessageHandleResult SignManager::Handle_RequestGetSignList(GameClient* Client, c
SignData->set_is_red_sign(Sign->IsRedSign);
}

// Make sure user is marked as aware of the sign so we can clear up when the sign is removed.
Sign->AwarePlayerIds.insert(Player.GetPlayerId());

RemainingSignCount--;
}
}
Expand Down Expand Up @@ -232,31 +260,8 @@ MessageHandleResult SignManager::Handle_RequestRemoveSign(GameClient* Client, co
return MessageHandleResult::Error;
}

LiveCache.Remove((OnlineAreaId)Request->online_area_id(), Request->sign_id());

// If anyone is trying to summon this sign right now, send them a notice that its been removed.
if (Sign->BeingSummonedByPlayerId != 0)
{
if (std::shared_ptr<GameClient> OtherClient = GameServiceInstance->FindClientByPlayerId(Sign->BeingSummonedByPlayerId))
{
Frpg2RequestMessage::PushRequestRemoveSign PushMessage;
PushMessage.set_push_message_id(Frpg2RequestMessage::PushID_PushRequestRemoveSign);
PushMessage.mutable_message()->set_player_id(Sign->PlayerId);
PushMessage.mutable_message()->set_sign_id(Sign->SignId);

if (!OtherClient->MessageStream->Send(&PushMessage))
{
WarningS(Client->GetName().c_str(), "Failed to send PushRequestRemoveSign to summoner.");
return MessageHandleResult::Error;
}
}
else
{
WarningS(Client->GetName().c_str(), "PlayerId summoning sign no longer exists, nothing to reject.");
}

Sign->BeingSummonedByPlayerId = 0;
}
// Tell anyone who is aware of this sign that its been removed.
RemoveSignAndNotifyAware(Sign);

// Empty response, not sure what purpose this serves really other than saying message-recieved. Client
// doesn't work without it though.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class SignManager
protected:
bool CanMatchWith(const Frpg2RequestMessage::MatchingParameter& Client, const Frpg2RequestMessage::MatchingParameter& Match, bool IsRedSign);

void RemoveSignAndNotifyAware(const std::shared_ptr<SummonSign>& Sign);

MessageHandleResult Handle_RequestGetSignList(GameClient* Client, const Frpg2ReliableUdpMessage& Message);
MessageHandleResult Handle_RequestCreateSign(GameClient* Client, const Frpg2ReliableUdpMessage& Message);
MessageHandleResult Handle_RequestRemoveSign(GameClient* Client, const Frpg2ReliableUdpMessage& Message);
Expand Down
11 changes: 9 additions & 2 deletions Source/Server/Server/Streams/Frpg2ReliableUdpPacketStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,20 +210,27 @@ void Frpg2ReliableUdpPacketStream::HandleIncoming()
}

HandleIncomingPacket(ReliablePacket);

ConsumeIncomingPackets();
}

ConsumeIncomingPackets();
}

void Frpg2ReliableUdpPacketStream::ConsumeIncomingPackets()
{
// Process as many packets as we can off the pending queue.
while (PendingRecieveQueue.size() > 0)
{
Frpg2ReliableUdpPacket& Next = PendingRecieveQueue[0];

uint32_t Local, Remote;
Next.Header.GetAckCounters(Local, Remote);

if (Local == GetNextRemoteSequenceIndex())
{
ProcessPacket(Next);

PendingRecieveQueue.erase(PendingRecieveQueue.begin());

RemoteSequenceIndex = (RemoteSequenceIndex + 1) % MAX_ACK_VALUE;
Expand Down
7 changes: 4 additions & 3 deletions Source/Server/Server/Streams/Frpg2ReliableUdpPacketStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class Frpg2ReliableUdpPacketStream
bool EncodeReliablePacket(const Frpg2ReliableUdpPacket& Message, Frpg2UdpPacket& Packet);

void HandleIncoming();
void ConsumeIncomingPackets();
void HandleIncomingPacket(const Frpg2ReliableUdpPacket& Packet);
void ProcessPacket(const Frpg2ReliableUdpPacket& Packet);

Expand Down Expand Up @@ -149,18 +150,18 @@ class Frpg2ReliableUdpPacketStream
double ResendSynTimer = 0.0;

// We stop sending packets and queue them up until we start recieving acks.
const int MAX_PACKETS_IN_FLIGHT = 64;
const int MAX_PACKETS_IN_FLIGHT = 32;

// We reeeeeeeaaaallly want this to be exponential backoff, but this works for now.
const float RETRANSMIT_INTERVAL = 0.5f; // 500ms

const float RETRANSMIT_CYCLE_INTERVAL = 0.2f; // 200ms

const uint32_t RETRANSMIT_MAX_ATTEMPTS = 64;
const uint32_t RETRANSMIT_MAX_ATTEMPTS = 32;

const float RESEND_SYN_INTERVAL = 0.5f;

const double MIN_TIME_BETWEEN_RESEND_ACK = 0.1;
const double MIN_TIME_BETWEEN_RESEND_ACK = 0.15;

// How many seconds to wait for a graceful disconnection.
const double CONNECTION_CLOSE_TIMEOUT = 3.0;
Expand Down

0 comments on commit e6057a1

Please sign in to comment.