Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple replicated ActorComponents in one Actor#40 #77

Merged
merged 15 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Source/ChanneldUE/ChannelDataInterfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,16 @@ class CHANNELDUE_API IChannelDataProcessor
virtual bool UpdateChannelData(UObject* TargetObj, google::protobuf::Message* ChannelData) {return true;}
virtual bool OnChannelDataUpdated(UObject* TargetObj, google::protobuf::Message* ChannelData) {return true;}

virtual const google::protobuf::Message* GetStateFromChannelData(google::protobuf::Message* ChannelData, UClass* TargetClass, uint32 NetGUID, bool& bIsRemoved) = 0;
virtual const google::protobuf::Message* GetStateFromChannelData(google::protobuf::Message* ChannelData, UClass* TargetClass, UObject* TargetObject, uint32 NetGUID, bool& bIsRemoved) = 0;
/**
* @brief Set a replicator's state to the channel data. UChanneldReplicationComponent doesn't know what states are defined in the channel data, or how are they organized. So the child class should implement this logic.
* @param State The delta state of a replicator, collected during Tick(). If null, removed = true will be set for the state.
* @param ChannelData The data field in the ChannelDataUpdate message which will be sent to channeld.
* @param TargetClass The class associated with the replicator. E.g. AActor for FChanneldActorReplicator, and ACharacter for FChanneldCharacterReplicator.
* @param TargetObject The replicated object that associated with the state.
* @param NetGUID The NetworkGUID used for looking up the state in the channel data. Generally the key of the state map.
*/
virtual void SetStateToChannelData(const google::protobuf::Message* State, google::protobuf::Message* ChannelData, UClass* TargetClass, uint32 NetGUID) = 0;
virtual void SetStateToChannelData(const google::protobuf::Message* State, google::protobuf::Message* ChannelData, UClass* TargetClass, UObject* TargetObject, uint32 NetGUID) = 0;

virtual ~IChannelDataProcessor() {}
};
6 changes: 5 additions & 1 deletion Source/ChanneldUE/ChanneldNetConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ void UChanneldNetConnection::SendDestroyMessage(UObject* Object, EChannelCloseRe
}
}

void UChanneldNetConnection::SendRPCMessage(AActor* Actor, const FString& FuncName, TSharedPtr<google::protobuf::Message> ParamsMsg, Channeld::ChannelId ChId)
void UChanneldNetConnection::SendRPCMessage(AActor* Actor, const FString& FuncName, TSharedPtr<google::protobuf::Message> ParamsMsg, Channeld::ChannelId ChId, const FString& SubObjectPath)
{
if (GetMutableDefault<UChanneldSettings>()->bQueueUnexportedActorRPC)
{
Expand All @@ -318,6 +318,10 @@ void UChanneldNetConnection::SendRPCMessage(AActor* Actor, const FString& FuncNa
// RpcMsg.mutable_targetobj()->MergeFrom(*ChanneldUtils::GetRefOfObject(Actor));
RpcMsg.mutable_targetobj()->set_netguid(Driver->GuidCache->GetNetGUID(Actor).Value);
RpcMsg.set_functionname(TCHAR_TO_UTF8(*FuncName), FuncName.Len());
if (!SubObjectPath.IsEmpty())
{
RpcMsg.set_subobjectpath(TCHAR_TO_UTF8(*SubObjectPath), SubObjectPath.Len());
}
if (ParamsMsg)
{
RpcMsg.set_paramspayload(ParamsMsg->SerializeAsString());
Expand Down
2 changes: 1 addition & 1 deletion Source/ChanneldUE/ChanneldNetConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class CHANNELDUE_API UChanneldNetConnection : public UNetConnection
*/
void SendSpawnMessage(UObject* Object, ENetRole Role = ENetRole::ROLE_None, uint32 OwningChannelId = Channeld::InvalidChannelId, uint32 OwningConnId = 0, FVector* Location = nullptr);
void SendDestroyMessage(UObject* Object, EChannelCloseReason Reason = EChannelCloseReason::Destroyed);
void SendRPCMessage(AActor* Actor, const FString& FuncName, TSharedPtr<google::protobuf::Message> ParamsMsg = nullptr, Channeld::ChannelId ChId = Channeld::InvalidChannelId);
void SendRPCMessage(AActor* Actor, const FString& FuncName, TSharedPtr<google::protobuf::Message> ParamsMsg = nullptr, Channeld::ChannelId ChId = Channeld::InvalidChannelId, const FString& SubObjectPath = "");
// Flush the handshake packets that are queued before received AuthResultMessage to the server.
void FlushUnauthData();

Expand Down
42 changes: 33 additions & 9 deletions Source/ChanneldUE/ChanneldNetDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,17 @@ void UChanneldNetDriver::HandleCustomRPC(TSharedPtr<unrealpb::RemoteFunctionMess
//TSet<FNetworkGUID> UnmappedGUID;
bool bDelayRPC = false;
FName FuncName = UTF8_TO_TCHAR(Msg->functionname().c_str());
ReceivedRPC(Actor, FuncName, Msg->paramspayload(), bDelayRPC);
UObject* SubObject = nullptr;
if (Msg->subobjectpath().length() > 0)
{
SubObject = Actor->GetDefaultSubobjectByName(Msg->subobjectpath().c_str());
if(!SubObject)
{
UE_LOG(LogChanneld, Log, TEXT("Actor:%s, NetGuid:%d can not find Subobject:%s for Function:%s"),
*Actor->GetName(), Msg->targetobj().netguid(), *FString(Msg->subobjectpath().c_str()), *FuncName.ToString());
}
}
ReceivedRPC(Actor, FuncName, Msg->paramspayload(), bDelayRPC, SubObject);
if (bDelayRPC)
{
UE_LOG(LogChanneld, Log, TEXT("Deferred RPC '%s::%s' due to unmapped NetGUID: %d"), *Actor->GetName(), *FuncName.ToString(), Msg->targetobj().netguid());
Expand Down Expand Up @@ -887,8 +897,16 @@ void UChanneldNetDriver::ProcessRemoteFunction(class AActor* Actor, class UFunct
auto RepComp = Cast<UChanneldReplicationComponent>(Actor->FindComponentByClass(UChanneldReplicationComponent::StaticClass()));
if (RepComp)
{
UObject* TargetObject = Actor;
FString SubObjectPathName = "";
if (SubObject)
{
TargetObject = SubObject;
SubObjectPathName = SubObject->GetName();
}

bool bSuccess = true;
auto ParamsMsg = RepComp->SerializeFunctionParams(Actor, Function, Parameters, OutParms, bSuccess);
auto ParamsMsg = RepComp->SerializeFunctionParams(TargetObject, Function, Parameters, OutParms, bSuccess);
if (bSuccess)
{
UE_CLOG(bShouldLog && ParamsMsg.IsValid(), LogChanneld, VeryVerbose, TEXT("Serialized RPC parameters: %s"), UTF8_TO_TCHAR(ParamsMsg->DebugString().c_str()));
Expand All @@ -898,7 +916,7 @@ void UChanneldNetDriver::ProcessRemoteFunction(class AActor* Actor, class UFunct
// Server -> Client multicast RPC
if (ConnToChanneld->IsServer() && (Function->FunctionFlags & FUNC_NetMulticast))
{
if (ChannelDataView->SendMulticastRPC(Actor, FuncName, ParamsMsg))
if (ChannelDataView->SendMulticastRPC(Actor, FuncName, ParamsMsg, SubObjectPathName))
{
return;
}
Expand All @@ -909,7 +927,7 @@ void UChanneldNetDriver::ProcessRemoteFunction(class AActor* Actor, class UFunct
UChanneldNetConnection* NetConn = ConnToChanneld->IsClient() ? GetServerConnection() : Cast<UChanneldNetConnection>(Actor->GetNetConnection());
if (NetConn)
{
NetConn->SendRPCMessage(Actor, FuncName, ParamsMsg, OwningChId);
NetConn->SendRPCMessage(Actor, FuncName, ParamsMsg, OwningChId, SubObjectPathName);
return;
}
UE_LOG(LogChanneld, Warning, TEXT("Failed to send RPC %s::%s as the actor doesn't have any NetConn"), *Actor->GetName(), *FuncName);
Expand All @@ -920,6 +938,10 @@ void UChanneldNetDriver::ProcessRemoteFunction(class AActor* Actor, class UFunct
unrealpb::RemoteFunctionMessage RpcMsg;
RpcMsg.mutable_targetobj()->set_netguid(GuidCache->GetNetGUID(Actor).Value);
RpcMsg.set_functionname(TCHAR_TO_UTF8(*FuncName), FuncName.Len());
if (!SubObjectPathName.IsEmpty())
{
RpcMsg.set_subobjectpath(TCHAR_TO_UTF8(*SubObjectPathName), SubObjectPathName.Len());
}
if (ParamsMsg)
{
RpcMsg.set_paramspayload(ParamsMsg->SerializeAsString());
Expand Down Expand Up @@ -957,15 +979,17 @@ void UChanneldNetDriver::OnSentRPC(const unrealpb::RemoteFunctionMessage& RpcMsg
#endif
}

void UChanneldNetDriver::ReceivedRPC(AActor* Actor, const FName& FunctionName, const std::string& ParamsPayload, bool& bDeferredRPC)
void UChanneldNetDriver::ReceivedRPC(AActor* Actor, const FName& FunctionName, const std::string& ParamsPayload, bool& bDeferredRPC, UObject* SubObject)
{
const bool bShouldLog = FunctionName != ServerMovePackedFuncName && FunctionName != ClientMoveResponsePackedFuncName && FunctionName != ServerUpdateCameraFuncName;
UE_CLOG(bShouldLog, LogChanneld, Verbose, TEXT("Received RPC %s::%s"), *Actor->GetName(), *FunctionName.ToString());


UFunction* Function = Actor->FindFunction(FunctionName);
UObject* Obj = SubObject != nullptr ? SubObject : Actor;
UFunction* Function = Obj->FindFunction(FunctionName);
if (!Function)
{
UE_LOG(LogChanneld, Error, TEXT("RPC function %s doesn't exist on Actor %s"), *FunctionName.ToString(), *Actor->GetName());
UE_LOG(LogChanneld, Error, TEXT("RPC function %s doesn't exist on Obj %s"), *FunctionName.ToString(), *Actor->GetName());
return;
}

Expand All @@ -983,15 +1007,15 @@ void UChanneldNetDriver::ReceivedRPC(AActor* Actor, const FName& FunctionName, c
if (RepComp)
{
bool bSuccess = true;
TSharedPtr<void> Params = RepComp->DeserializeFunctionParams(Actor, Function, ParamsPayload, bSuccess, bDeferredRPC);
TSharedPtr<void> Params = RepComp->DeserializeFunctionParams(Obj, Function, ParamsPayload, bSuccess, bDeferredRPC);
if (bDeferredRPC)
{
return;
}

if (bSuccess)
{
Actor->ProcessEvent(Function, Params.Get());
Obj->ProcessEvent(Function, Params.Get());
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion Source/ChanneldUE/ChanneldNetDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class CHANNELDUE_API UChanneldNetDriver : public UNetDriver
UChanneldNetConnection* AddChanneldClientConnection(Channeld::ConnectionId ClientConnId, Channeld::ChannelId ChId);
void RemoveChanneldClientConnection(Channeld::ConnectionId ClientConnId);

void ReceivedRPC(AActor* Actor, const FName& FunctionName, const std::string& ParamsPayload, bool& bDeferredRPC);
void ReceivedRPC(AActor* Actor, const FName& FunctionName, const std::string& ParamsPayload, bool& bDeferredRPC, UObject* SubObject = nullptr);

UChanneldConnection* GetConnToChanneld() const { return ConnToChanneld; }

Expand Down
4 changes: 2 additions & 2 deletions Source/ChanneldUE/DefaultSpatialChannelDataProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ bool FDefaultSpatialChannelDataProcessor::UpdateChannelData(UObject* TargetObj,
}

const google::protobuf::Message* FDefaultSpatialChannelDataProcessor::GetStateFromChannelData(
google::protobuf::Message* ChannelData, UClass* TargetClass, uint32 NetGUID, bool& bIsRemoved)
google::protobuf::Message* ChannelData, UClass* TargetClass, UObject* TargetObject, uint32 NetGUID, bool& bIsRemoved)
{
if (TargetClass != UObject::StaticClass())
{
Expand All @@ -58,7 +58,7 @@ const google::protobuf::Message* FDefaultSpatialChannelDataProcessor::GetStateFr
}

void FDefaultSpatialChannelDataProcessor::SetStateToChannelData(const google::protobuf::Message* State,
google::protobuf::Message* ChannelData, UClass* TargetClass, uint32 NetGUID)
google::protobuf::Message* ChannelData, UClass* TargetClass, UObject* TargetObject, uint32 NetGUID)
{
if (TargetClass != UObject::StaticClass())
{
Expand Down
4 changes: 2 additions & 2 deletions Source/ChanneldUE/DefaultSpatialChannelDataProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ class CHANNELDUE_API FDefaultSpatialChannelDataProcessor : public IChannelDataPr

virtual bool UpdateChannelData(UObject* TargetObj, google::protobuf::Message* ChannelData) override;

virtual const google::protobuf::Message* GetStateFromChannelData(google::protobuf::Message* ChannelData, UClass* TargetClass, uint32 NetGUID, bool& bIsRemoved) override;
virtual void SetStateToChannelData(const google::protobuf::Message* State, google::protobuf::Message* ChannelData, UClass* TargetClass, uint32 NetGUID) override;
virtual const google::protobuf::Message* GetStateFromChannelData(google::protobuf::Message* ChannelData, UClass* TargetClass, UObject* TargetObject, uint32 NetGUID, bool& bIsRemoved) override;
virtual void SetStateToChannelData(const google::protobuf::Message* State, google::protobuf::Message* ChannelData, UClass* TargetClass, UObject* TargetObject, uint32 NetGUID) override;
};
4 changes: 2 additions & 2 deletions Source/ChanneldUE/FFlatStatesChannelDataProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ bool FFlatStatesChannelDataProcessor::Merge(const google::protobuf::Message* Src
return false;
}

const google::protobuf::Message* FFlatStatesChannelDataProcessor::GetStateFromChannelData(google::protobuf::Message* ChannelData, UClass* TargetClass, uint32 NetGUID, bool& bIsRemoved)
const google::protobuf::Message* FFlatStatesChannelDataProcessor::GetStateFromChannelData(google::protobuf::Message* ChannelData, UClass* TargetClass, UObject* TargetObject, uint32 NetGUID, bool& bIsRemoved)
{
bIsRemoved = false;
auto StateInProto = ChanneldReplication::FindReplicatorStateInProto(TargetClass);
Expand Down Expand Up @@ -64,7 +64,7 @@ const google::protobuf::Message* FFlatStatesChannelDataProcessor::GetStateFromCh
return State;
}

void FFlatStatesChannelDataProcessor::SetStateToChannelData(const google::protobuf::Message* State,google::protobuf::Message* ChannelData, UClass* TargetClass, uint32 NetGUID)
void FFlatStatesChannelDataProcessor::SetStateToChannelData(const google::protobuf::Message* State,google::protobuf::Message* ChannelData, UClass* TargetClass, UObject* TargetObject, uint32 NetGUID)
{
auto StateInProto = ChanneldReplication::FindReplicatorStateInProto(TargetClass);
if (!StateInProto)
Expand Down
4 changes: 2 additions & 2 deletions Source/ChanneldUE/FFlatStatesChannelDataProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class CHANNELDUE_API FFlatStatesChannelDataProcessor : IChannelDataProcessor
public:
virtual bool Merge(const google::protobuf::Message* SrcMsg, google::protobuf::Message* DstMsg) override;
virtual const google::protobuf::Message* GetStateFromChannelData(google::protobuf::Message* ChannelData,
UClass* TargetClass, uint32 NetGUID, bool& bIsRemoved) override;
UClass* TargetClass, UObject* TargetObject, uint32 NetGUID, bool& bIsRemoved) override;
virtual void SetStateToChannelData(const google::protobuf::Message* State, google::protobuf::Message* ChannelData,
UClass* TargetClass, uint32 NetGUID) override;
UClass* TargetClass, UObject* TargetObject, uint32 NetGUID) override;
};
14 changes: 7 additions & 7 deletions Source/ChanneldUE/Replication/ChanneldReplicationComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,14 @@ bool UChanneldReplicationComponent::UpdateChannelData(google::protobuf::Message*

if (IsRemoved())
{
Processor->SetStateToChannelData(nullptr, ChannelData, Replicator->GetTargetClass(), NetGUID);
Processor->SetStateToChannelData(nullptr, ChannelData, Replicator->GetTargetClass(), Replicator->GetTargetObject(), NetGUID);
continue;
}

Replicator->Tick(FApp::GetDeltaTime());
if (Replicator->IsStateChanged())
{
Processor->SetStateToChannelData(Replicator->GetDeltaState(), ChannelData, Replicator->GetTargetClass(), NetGUID);
Processor->SetStateToChannelData(Replicator->GetDeltaState(), ChannelData, Replicator->GetTargetClass(), Replicator->GetTargetObject(), NetGUID);
Replicator->ClearState();
bUpdated = true;
}
Expand Down Expand Up @@ -277,7 +277,7 @@ void UChanneldReplicationComponent::OnChannelDataUpdated(google::protobuf::Messa
continue;
}
bool bIsRemoved = false;
auto State = Processor->GetStateFromChannelData(ChannelData, Replicator->GetTargetClass(), NetGUID, bIsRemoved);
auto State = Processor->GetStateFromChannelData(ChannelData, Replicator->GetTargetClass(), Replicator->GetTargetObject(), NetGUID, bIsRemoved);
if (State)
{
if (bIsRemoved)
Expand All @@ -302,11 +302,11 @@ void UChanneldReplicationComponent::OnChannelDataUpdated(google::protobuf::Messa
}
}

TSharedPtr<google::protobuf::Message> UChanneldReplicationComponent::SerializeFunctionParams(AActor* Actor, UFunction* Func, void* Params, FOutParmRec* OutParams, bool& bSuccess)
TSharedPtr<google::protobuf::Message> UChanneldReplicationComponent::SerializeFunctionParams(UObject* Object, UFunction* Func, void* Params, FOutParmRec* OutParams, bool& bSuccess)
{
for (auto& Replicator : Replicators)
{
if (Replicator->GetTargetObject() == Actor)
if (Replicator->GetTargetObject() == Object)
{
auto ParamsMsg = Replicator->SerializeFunctionParams(Func, Params, OutParams, bSuccess);
if (bSuccess)
Expand All @@ -320,11 +320,11 @@ TSharedPtr<google::protobuf::Message> UChanneldReplicationComponent::SerializeFu
return nullptr;
}

TSharedPtr<void> UChanneldReplicationComponent::DeserializeFunctionParams(AActor* Actor, UFunction* Func, const std::string& ParamsPayload, bool& bSuccess, bool& bDeferredRPC)
TSharedPtr<void> UChanneldReplicationComponent::DeserializeFunctionParams(UObject* Object, UFunction* Func, const std::string& ParamsPayload, bool& bSuccess, bool& bDeferredRPC)
{
for (auto& Replicator : Replicators)
{
if (Replicator->GetTargetObject() == Actor)
if (Replicator->GetTargetObject() == Object)
{
TSharedPtr<void> Params = Replicator->DeserializeFunctionParams(Func, ParamsPayload, bSuccess, bDeferredRPC);
if (bSuccess)
Expand Down
4 changes: 2 additions & 2 deletions Source/ChanneldUE/Replication/ChanneldReplicationComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,6 @@ class CHANNELDUE_API UChanneldReplicationComponent : public UActorComponent, pub
virtual void OnChannelDataUpdated(google::protobuf::Message* ChannelData) override;
//~ End IChannelDataProvider Interface.

TSharedPtr<google::protobuf::Message> SerializeFunctionParams(AActor* Actor, UFunction* Func, void* Params, FOutParmRec* OutParams, bool& bSuccess);
TSharedPtr<void> DeserializeFunctionParams(AActor* Actor, UFunction* Func, const std::string& ParamsPayload, bool& bSuccess, bool& bDeferredRPC);
TSharedPtr<google::protobuf::Message> SerializeFunctionParams(UObject* Object, UFunction* Func, void* Params, FOutParmRec* OutParams, bool& bSuccess);
TSharedPtr<void> DeserializeFunctionParams(UObject* Object, UFunction* Func, const std::string& ParamsPayload, bool& bSuccess, bool& bDeferredRPC);
};
2 changes: 1 addition & 1 deletion Source/ChanneldUE/Replication/ChanneldReplicatorBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class CHANNELDUE_API FChanneldReplicatorBase_BP : public FChanneldReplicatorBase
public:
FChanneldReplicatorBase_BP(UObject* InTargetObj, const FString& BlueprintPath) : FChanneldReplicatorBase(InTargetObj)
{
BpClass = LoadClass<AActor>(nullptr, *FString::Printf(TEXT("Blueprint'%s'"), *BlueprintPath));
BpClass = LoadClass<UObject>(nullptr, *FString::Printf(TEXT("Blueprint'%s'"), *BlueprintPath));
}
virtual UClass* GetTargetClass() override { return BpClass; }

Expand Down
3 changes: 2 additions & 1 deletion Source/ChanneldUE/View/ChannelDataView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,11 +629,12 @@ Channeld::ChannelId UChannelDataView::GetOwningChannelId(AActor* Actor) const
return GetOwningChannelId(GetNetId(Actor));
}

bool UChannelDataView::SendMulticastRPC(AActor* Actor, const FString& FuncName, TSharedPtr<google::protobuf::Message> ParamsMsg)
bool UChannelDataView::SendMulticastRPC(AActor* Actor, const FString& FuncName, TSharedPtr<google::protobuf::Message> ParamsMsg, const FString& SubObjectPathName)
{
unrealpb::RemoteFunctionMessage RpcMsg;
RpcMsg.mutable_targetobj()->set_netguid(GetNetId(Actor).Value);
RpcMsg.set_functionname(TCHAR_TO_UTF8(*FuncName), FuncName.Len());
RpcMsg.set_subobjectpath(TCHAR_TO_UTF8(*SubObjectPathName), SubObjectPathName.Len());
if (ParamsMsg)
{
RpcMsg.set_paramspayload(ParamsMsg->SerializeAsString());
Expand Down
2 changes: 1 addition & 1 deletion Source/ChanneldUE/View/ChannelDataView.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class CHANNELDUE_API UChannelDataView : public UObject
virtual Channeld::ChannelId GetOwningChannelId(const FNetworkGUID NetId) const;
virtual Channeld::ChannelId GetOwningChannelId(AActor* Actor) const;

virtual bool SendMulticastRPC(AActor* Actor, const FString& FuncName, TSharedPtr<google::protobuf::Message> ParamsMsg);
virtual bool SendMulticastRPC(AActor* Actor, const FString& FuncName, TSharedPtr<google::protobuf::Message> ParamsMsg, const FString& SubObjectPathName);

int32 SendChannelUpdate(Channeld::ChannelId ChId);
int32 SendAllChannelUpdates();
Expand Down
Loading