Skip to content

Commit

Permalink
Some initial fleshing out of the invasion mechanics / some general pr…
Browse files Browse the repository at this point in the history
…otobuf deciphering.
  • Loading branch information
TLeonardUK committed Aug 22, 2021
1 parent b19d3d9 commit f223215
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 49 deletions.
87 changes: 54 additions & 33 deletions Protobuf/Frpg2RequestMessage.proto
Original file line number Diff line number Diff line change
Expand Up @@ -762,76 +762,86 @@ message PushRequestRejectSign {
// Invader << RequestGetBreakInTargetListResponse
// Invader >> RequestBreakInTarget
// Host << PushRequestBreakInTarget
// Host >> Optional: RequestRejectBreakInTarget (I think this is how its used)
// Invader & Host << PushRequestAllowBreakInTarget (Or PushRequestRejectBreakInTarget on failure)
// Host >> RequestRejectBreakInTarget or RequestSendMessageToPlayers (containing PushRequestAllowBreakInTarget)
// Invader & Host << PushRequestAllowBreakInTarget PushRequestRejectBreakInTarget
// Invader >> RequestNotifyBreakInResult

message BreakInTargetData {
required uint32 player_id = 1;
required string steam_id = 2;
}

// Sent by invader looking for worlds to invade
message RequestGetBreakInTargetList {
required uint32 map_id = 1;
required uint32 online_area_id = 2;
required uint32 unknown_1 = 3;
required uint32 max_targets = 3;
required MatchingParameter matching_parameter = 4;
required uint32 unknown_2 = 5;
required uint32 unknown_5 = 5; // 0
}

// Received by invader looking for worlds to invade
message RequestGetBreakInTargetListResponse {
required uint32 map_id = 1;
required uint32 online_area_id = 2;
repeated BreakInTargetData break_in_target_data = 3;
repeated BreakInTargetData target_data = 3;
}

// Received by invader and host, notifies that the server has allowed invading.
message PushRequestAllowBreakInTarget {
required PushMessageId push_message_id = 1;
required uint32 player_id = 2; // Host playerid
required string data = 3;
required uint32 unknown_2 = 4; // 0
required uint32 player_id = 2; // Host playerid
required string player_struct = 3;
required uint32 unknown_4 = 4; // 0
}

// Recieved by invaider, notifies that server has rejected invasion.
message PushRequestRejectBreakInTarget {
required PushMessageId push_message_id = 1;
// Unknown
required PushMessageId push_message_id = 1;

// Unknown - The fields in this have been figured out based on reading ghidra, not seen in the wild.
required uint32 unknown_2 = 2;
required uint32 unknown_3 = 3;
required string unknown_4 = 4; // WIRETYPE_LENGTH_DELIMITED, guessing string, might be BreakInTargetData
required uint32 unknown_5 = 5;
}

// Received by host
message PushRequestBreakInTarget {
required PushMessageId push_message_id = 1;
required uint32 player_id = 2; // invading playerid
required uint32 player_id = 2; // invading playerid
required string steam_id = 3;
required uint32 unknown_2 = 4; // 0
required uint32 unknown_4 = 4; // 0
required uint32 map_id = 5;
required uint32 online_area_id = 6;
}

message PushRequestRemoveBreakInTarget {
required PushMessageId push_message_id = 1;

// Unknown - The fields in this have been figured out based on reading ghidra, not seen in the wild.

This comment has been minimized.

Copy link
@garyttierney

garyttierney Aug 24, 2021

You might be able to get this to fire by blocking the host on Steam.

required uint32 unknown_2 = 2;
required string unknown_3 = 3; // WIRETYPE_LENGTH_DELIMITED, guessing string, might be BreakInTargetData
required uint32 unknown_4 = 4;
}

// Send by invaded to ask to invade host.
message RequestBreakInTarget {
required uint32 map_id = 1;
required uint32 online_area_id = 2;
required uint32 player_id = 3;
required uint32 unknown_1 = 4; // Seems to always be 0
required uint32 unknown_4 = 4; // Seems to always be 0
}

message RequestBreakInTargetResponse {
// Unknown
message RequestRejectBreakInTarget {
// Unknown - The fields in this have been figured out based on reading ghidra, not seen in the wild.
required uint32 unknown_1 = 1;
required uint32 unknown_2 = 2;
required uint32 unknown_3 = 3;
required uint32 unknown_4 = 4;
required uint32 unknown_5 = 5;
}

message RequestRejectBreakInTarget {
// Unknown
message RequestBreakInTargetResponse {
// Unknown - If like summon signs, probably not sent.
}

message RequestRejectBreakInTargetResponse {
// Unknown
// Unknown - If like summon signs, probably not sent.
}

// ------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -913,10 +923,6 @@ message RequestVisit {
required bytes metadata = 5;
}

message RequestVisitResponse {
// Seems to never be sent by server.
}

message PushRequestVisit {
required PushMessageId push_message_id = 1; // 951 - Push message id
required uint32 player_id = 2;
Expand All @@ -928,16 +934,31 @@ message PushRequestVisit {
}

message RequestRejectVisit {
// Unknown
}

message RequestRejectVisitResponse {
// Unknown
// Unknown - The fields in this have been figured out based on reading ghidra, not seen in the wild.
required uint32 unknown_1 = 1;
required uint32 unknown_2 = 2;
required uint32 unknown_3 = 3;
required uint32 unknown_4 = 4;
required uint32 unknown_5 = 5;
}

message PushRequestRejectVisit {
required PushMessageId push_message_id = 1;
// Unknown

// Unknown - The fields in this have been figured out based on reading ghidra, not seen in the wild.
required uint32 unknown_2 = 2;
required uint32 unknown_3 = 3;
required uint32 unknown_4 = 4; // WIRETYPE_LENGTH_DELIMITED, guessing string, might be BreakInTargetData
required uint32 unknown_5 = 5;
}

message RequestVisitResponse {
// Seems to never be sent by server.
}

message RequestRejectVisitResponse {
// Unknown - If like summon signs, probably not sent.
}

// ------------------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ MessageHandleResult BloodMessageManager::Handle_RequestGetBloodMessageList(GameC
continue;
}

Log("[%s] Returning blood message %i in area %i.", Client->GetName().c_str(), AreaMsg->MessageId, AreaMsg->OnlineAreaId);
//Log("[%s] Returning blood message %i in area %i.", Client->GetName().c_str(), AreaMsg->MessageId, AreaMsg->OnlineAreaId);

Frpg2RequestMessage::BloodMessageData& Data = *Response.mutable_messages()->Add();
Data.set_player_id(Player.PlayerId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ MessageHandleResult BloodstainManager::Handle_RequestGetBloodstainList(GameClien
continue;
}

Log("[%s] Returning blood stain %i in area %i.", Client->GetName().c_str(), AreaMsg->BloodstainId, AreaMsg->OnlineAreaId);
//Log("[%s] Returning blood stain %i in area %i.", Client->GetName().c_str(), AreaMsg->BloodstainId, AreaMsg->OnlineAreaId);

Frpg2RequestMessage::BloodstainInfo& Data = *Response.mutable_bloodstains()->Add();
Data.set_online_area_id((uint32_t)AreaMsg->OnlineAreaId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "Server/GameService/GameManagers/BreakIn/BreakInManager.h"
#include "Server/GameService/GameClient.h"
#include "Server/GameService/GameService.h"
#include "Server/Streams/Frpg2ReliableUdpMessage.h"
#include "Server/Streams/Frpg2ReliableUdpMessageStream.h"

Expand All @@ -17,8 +18,13 @@

#include "Core/Utils/Logging.h"

BreakInManager::BreakInManager(Server* InServerInstance)
BreakInManager::BreakInManager(Server* InServerInstance, GameService* InGameServiceInstance)
: ServerInstance(InServerInstance)
, GameServiceInstance(InGameServiceInstance)
{
}

void BreakInManager::OnLostPlayer(GameClient* Client)
{
}

Expand All @@ -40,13 +46,38 @@ MessageHandleResult BreakInManager::OnMessageRecieved(GameClient* Client, const
return MessageHandleResult::Unhandled;
}

bool BreakInManager::CanMatchWith(const Frpg2RequestMessage::MatchingParameter& Request, const std::shared_ptr<GameClient>& Match)
{
// TODO: Actually apply some matching rules here.

return true;
}

MessageHandleResult BreakInManager::Handle_RequestGetBreakInTargetList(GameClient* Client, const Frpg2ReliableUdpMessage& Message)
{
Frpg2RequestMessage::RequestGetBreakInTargetList* Request = (Frpg2RequestMessage::RequestGetBreakInTargetList*)Message.Protobuf.get();

// TODO: Implement

std::vector<std::shared_ptr<GameClient>> PotentialTargets = GameServiceInstance->FindClients([Request](const std::shared_ptr<GameClient>& OtherClient) {
/*
if (OtherClient->GetPlayerState().CurrentArea != (OnlineAreaId)Request->online_area_id())
{
return false;
}
*/
return CanMatchWith(Request->matching_parameter(), OtherClient);
});

Frpg2RequestMessage::RequestGetBreakInTargetListResponse Response;
Response.set_map_id(Request->map_id());
Response.set_online_area_id(Request->online_area_id());

for (std::shared_ptr<GameClient> OtherClient : PotentialTargets)
{
Frpg2RequestMessage::BreakInTargetData* a = Response.add_break_in_target_data();
a->set_player_id(OtherClient->GetPlayerState().PlayerId);
a->set_steam_id(OtherClient->GetPlayerState().SteamId);
}

if (!Client->MessageStream->Send(&Response, &Message))
{
Warning("[%s] Disconnecting client as failed to send RequestGetBreakInTargetListResponse response.", Client->GetName().c_str());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,37 @@
#pragma once

#include "Server/GameService/GameManager.h"
#include "Protobuf/Protobufs.h"

#include <memory>

struct Frpg2ReliableUdpMessage;
class Server;
class GameService;

// Handles client requests for invading other games.

class BreakInManager
: public GameManager
{
public:
BreakInManager(Server* InServerInstance);
BreakInManager(Server* InServerInstance, GameService* InGameServiceInstance);

virtual MessageHandleResult OnMessageRecieved(GameClient* Client, const Frpg2ReliableUdpMessage& Message) override;

virtual std::string GetName() override;

virtual void OnLostPlayer(GameClient* Client) override;

protected:
static bool CanMatchWith(const Frpg2RequestMessage::MatchingParameter& Client, const std::shared_ptr<GameClient>& Match);

MessageHandleResult Handle_RequestGetBreakInTargetList(GameClient* Client, const Frpg2ReliableUdpMessage& Message);
MessageHandleResult Handle_RequestBreakInTarget(GameClient* Client, const Frpg2ReliableUdpMessage& Message);
MessageHandleResult Handle_RequestRejectBreakInTarget(GameClient* Client, const Frpg2ReliableUdpMessage& Message);

private:
Server* ServerInstance;
GameService* GameServiceInstance;

};
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ MessageHandleResult GhostManager::Handle_RequestGetGhostDataList(GameClient* Cli
continue;
}

Log("[%s] Returning ghost %i in area %i.", Client->GetName().c_str(), AreaMsg->GhostId, AreaMsg->OnlineAreaId);
//Log("[%s] Returning ghost %i in area %i.", Client->GetName().c_str(), AreaMsg->GhostId, AreaMsg->OnlineAreaId);

Frpg2RequestMessage::GhostData& Data = *Response.mutable_ghosts()->Add();
Data.set_unknown_1(1); // TODO: Figure out what this is.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ MessageHandleResult PlayerDataManager::Handle_RequestUpdatePlayerStatus(GameClie
uint32_t LowerArea = Request->status().player_location().online_area_id_lower();
uint32_t UpperArea = Request->status().player_location().online_area_id_upper();
OnlineAreaId AreaId = static_cast<OnlineAreaId>(UpperArea);
if (AreaId != State.CurrentArea)
if (AreaId != State.CurrentArea && AreaId != OnlineAreaId::None)
{
Log("[%s] User has entered '%s'", Client->GetName().c_str(), GetEnumString(AreaId).c_str());
State.CurrentArea = AreaId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ MessageHandleResult SignManager::Handle_RequestGetSignList(GameClient* Client, c
continue;
}

Log("[%s] Returning sign %i in area %i.", Client->GetName().c_str(), Sign->SignId, Sign->OnlineAreaId);
//Log("[%s] Returning sign %i in area %i.", Client->GetName().c_str(), Sign->SignId, Sign->OnlineAreaId);

// If client already has sign data we only need to return a limited set of data.
if (ClientExistingSignId.count(Sign->SignId) > 0)
Expand Down Expand Up @@ -166,6 +166,14 @@ MessageHandleResult SignManager::Handle_RequestCreateSign(GameClient* Client, co
Sign->PlayerStruct.assign(Request->player_struct().data(), Request->player_struct().data() + Request->player_struct().size());
Sign->MatchingParameters = Request->matching_parameter();

// The client seems to queue up removal messages and send them periodically, but will send CreateSign instantly. This
// can lead to multiple signs existing at once. We just purge here and ignore future remove requests for old id's.
for (std::shared_ptr<SummonSign> OtherSign : Client->ActiveSummonSigns)
{
LiveCache.Remove(OtherSign->OnlineAreaId, OtherSign->SignId);
}
Client->ActiveSummonSigns.clear();

LiveCache.Add(Sign->OnlineAreaId, Sign->SignId, Sign);
Client->ActiveSummonSigns.push_back(Sign);

Expand All @@ -188,8 +196,8 @@ MessageHandleResult SignManager::Handle_RequestRemoveSign(GameClient* Client, co
std::shared_ptr<SummonSign> Sign = LiveCache.Find((OnlineAreaId)Request->online_area_id(), Request->sign_id());
if (!Sign)
{
Warning("[%s] Disconnecting client as attempted to remove non-existant summon sign, %i.", Client->GetName().c_str(), Request->sign_id());
return MessageHandleResult::Error;
Warning("[%s] Client as attempted to remove non-existant summon sign, %i, has probably already been cleaned up by CreateSummonSign.", Client->GetName().c_str(), Request->sign_id());
return MessageHandleResult::Handled;
}

if (auto Iter = std::find(Client->ActiveSummonSigns.begin(), Client->ActiveSummonSigns.end(), Sign); Iter != Client->ActiveSummonSigns.end())
Expand Down
19 changes: 17 additions & 2 deletions Source/Server/Server/GameService/GameService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ GameService::GameService(Server* OwningServer, RSAKeyPair* InServerRSAKey)
Managers.push_back(std::make_shared<GhostManager>(ServerInstance));
Managers.push_back(std::make_shared<RankingManager>(ServerInstance));
Managers.push_back(std::make_shared<QuickMatchManager>(ServerInstance));
Managers.push_back(std::make_shared<BreakInManager>(ServerInstance));
Managers.push_back(std::make_shared<BreakInManager>(ServerInstance, this));
Managers.push_back(std::make_shared<VisitorManager>(ServerInstance));
Managers.push_back(std::make_shared<MarkManager>(ServerInstance));
Managers.push_back(std::make_shared<MiscManager>(ServerInstance));
Expand Down Expand Up @@ -253,4 +253,19 @@ std::shared_ptr<GameClient> GameService::FindClientByPlayerId(uint32_t PlayerId)
}
}
return nullptr;
}
}

std::vector<std::shared_ptr<GameClient>> GameService::FindClients(std::function<bool(const std::shared_ptr<GameClient>&)> Predicate)
{
std::vector<std::shared_ptr<GameClient>> Result;

for (std::shared_ptr<GameClient>& Client : Clients)
{
if (Predicate(Client))
{
Result.push_back(Client);
}
}

return Result;
}
2 changes: 2 additions & 0 deletions Source/Server/Server/GameService/GameService.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <memory>
#include <vector>
#include <unordered_map>
#include <functional>

class Server;
class GameClient;
Expand Down Expand Up @@ -58,6 +59,7 @@ class GameService
const std::vector<std::shared_ptr<GameManager>>& GetManagers() { return Managers; }

std::shared_ptr<GameClient> FindClientByPlayerId(uint32_t PlayerId);
std::vector<std::shared_ptr<GameClient>> FindClients(std::function<bool(const std::shared_ptr<GameClient>&)> Predicate);

protected:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ bool Frpg2ReliableUdpMessageStream::Send(google::protobuf::MessageLite* Message,
return true;
}

Log("[%s] >> %s", Connection->GetName().c_str(), Message->GetTypeName().c_str());
//Log("[%s] >> %s", Connection->GetName().c_str(), Message->GetTypeName().c_str());

return true;
}
Expand Down Expand Up @@ -179,8 +179,7 @@ bool Frpg2ReliableUdpMessageStream::Recieve(Frpg2ReliableUdpMessage* Message)
return false;
}

Log("[%s] << %s", Connection->GetName().c_str(), Message->Protobuf->GetTypeName().c_str());

//Log("[%s] << %s", Connection->GetName().c_str(), Message->Protobuf->GetTypeName().c_str());
//Log("[%s] Recieving message: type=0x%08x index=0x%08x", Connection->GetName().c_str(), Message->Header.msg_type, Message->Header.msg_index)

return true;
Expand Down

0 comments on commit f223215

Please sign in to comment.