UE SessionFrontd(会话前端)源码解析

4 篇文章 0 订阅
public class SessionServices : ModuleRules
{
	public SessionServices(ReadOnlyTargetRules Target) : base(Target)
	{
		PublicDependencyModuleNames.AddRange(
			new string[] {
				"Core",
			});

		PrivateDependencyModuleNames.AddRange(
			new string[] {
				"CoreUObject",
				"EngineMessages",
				"SessionMessages",
			});

		PrivateIncludePathModuleNames.AddRange(
			new string[] {
				"Messaging",
				"MessagingCommon",
			});
	}
}

SessionService依赖SessionMessages这个模块。用到了MessagingCommnMessaging这连个模块内的头文件。

定义的接口

ISessionService

ISessionService表示一个会话的服务。

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"

/**
 * Interface for application session services.
 */
class ISessionService
{
public:

	/**
	 * Checks whether the service is running.
	 *
	 * @return true if the service is running, false otherwise.
	 * @see Start, Stop
	 */
	virtual bool IsRunning() = 0;

	/**
	 * Starts the service.
	 *
	 * @return true if the service was started, false otherwise.
	 * @see IsRunning, Stop
	 */
	virtual bool Start() = 0;

	/**
	 * Stops the service.
	 *
	 * @see IsRunning, Start
	 */
	virtual void Stop() = 0;

public:

	/** Virtual destructor. */
	virtual ~ISessionService() { }
};

简单的三个方法:

  • Run
  • Stop
  • IsRunning

加上一个必备的虚析构函数。

ISessionManager

ISessionManager中定义了如何管理这个Session的一些方法。

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "ISessionInstanceInfo.h"
#include "ISessionInfo.h"
#include "SessionLogMessage.h"

/**
 * Interface for the session manager.
 */
class ISessionManager
{
public:

	/**
	 * Adds an owner whose sessions we are interested in
	 *
	 * @param InOwner Session owner we want to view sessions from
	 */
	virtual void AddOwner( const FString& InOwner ) = 0;

	/**
	  * Gets the collection of currently selected engine instances.
	  *
	  * @return The selected instances.
	  */
	virtual const TArray<TSharedPtr<ISessionInstanceInfo>>& GetSelectedInstances() const = 0;

	/**
	 * Get the selected session - as chosen in the session browser
	 *
	 * @return The session ID selected
	 */
	virtual const TSharedPtr<ISessionInfo>& GetSelectedSession() const = 0;

	/**
	 * Gets the list of all discovered sessions.
	 *
	 * @param OutSessions Will hold the collection of sessions.
	 */
	virtual void GetSessions( TArray<TSharedPtr<ISessionInfo>>& OutSessions ) const = 0;

	/**
	 * Checks whether the given instance is currently selected.
	 *
	 * @return true if the instance is selected, false otherwise.
	 */
	virtual bool IsInstanceSelected( const TSharedRef<ISessionInstanceInfo>& Instance ) const = 0;

	/**
	 * Removes an owner whose sessions we are no longer interested in
	 *
	 * @param InOwner Session owner we want to remove
	 */
	virtual void RemoveOwner( const FString& InOwner ) = 0;

	/**
	 * Selects the specified session.
	 *
	 * @param Session The session to the select (can be NULL to select none).
	 * @return true if the session was selected, false otherwise.
	 */
	virtual bool SelectSession( const TSharedPtr<ISessionInfo>& Session ) = 0;

	/**
	 * Marks the specified item as selected or unselected.
	 *
	 * @param Instance The instance to mark.
	 * @param Selected Whether the instance should be selected (true) or unselected (false).
	 * @return true if the instance was selected, false otherwise.
	 */
	virtual bool SetInstanceSelected( const TSharedRef<ISessionInstanceInfo>& Instance, bool Selected ) = 0;

public:

	/**
	 * Returns a delegate that is executed before a session is being selected.
	 *
	 * @return The delegate.
	 */
	DECLARE_EVENT_TwoParams(ISessionManager, FCanSelectSessionEvent, const TSharedPtr<ISessionInfo>& /*Session*/, bool& /*OutCanSelect*/)
	virtual FCanSelectSessionEvent& OnCanSelectSession() = 0;

	/**
	 * Returns a delegate that is executed when an instance changes its selection state.
	 *
	 * @return The delegate.
	 */
	DECLARE_EVENT_TwoParams(ISessionManager, FInstanceSelectionChangedEvent, const TSharedPtr<ISessionInstanceInfo>& /*Instance*/, bool /*Selected*/)
	virtual FInstanceSelectionChangedEvent& OnInstanceSelectionChanged() = 0;

	/**
	 * Returns a delegate that is executed when the selected session received a log message from one of its instances.
	 *
	 * @return The delegate.
	 */
	DECLARE_EVENT_ThreeParams(ISessionManager, FLogReceivedEvent, const TSharedRef<ISessionInfo>& /*OwnerSession*/, const TSharedRef<ISessionInstanceInfo>& /*SessionInstance*/, const TSharedRef<FSessionLogMessage>& /*LogMessage*/);
	virtual FLogReceivedEvent& OnLogReceived() = 0;

	/**
	 * Returns a delegate that is executed when the selected session changed.
	 *
	 * @return The delegate.
	 */
	DECLARE_EVENT_OneParam(ISessionManager, FSelectedSessionChangedEvent, const TSharedPtr<ISessionInfo>& /*SelectedSession*/)
	virtual FSelectedSessionChangedEvent& OnSelectedSessionChanged() = 0;

	/**
	 * Returns a delegate that is executed when the list of sessions has changed.
	 *
	 * @return The delegate.
	 */
	virtual FSimpleMulticastDelegate& OnSessionsUpdated() = 0;

	/**
	 * Returns a delegate that is executed when a session instance is updated.
	 *
	 * @return The delegate.
	 */
	virtual FSimpleMulticastDelegate& OnSessionInstanceUpdated() = 0;

public:

	/** Virtual destructor. */
	virtual ~ISessionManager() { }
};

我们一个一个来分析:

  • AddOwner,添加一个Session感兴趣的所有者。
  • RemoveOwner,一出一个Session不再感兴趣的所有者。
  • GetSelectedInstances,获取当前所选择的所有引擎实例集合。
  • GetSelectedSession,获取选择的Session实例,也就是相当于在ui中点击选中的Session。
  • GetSessions,获取所有已经发现的Session列表。
  • IsInstanceSelected,检查当前是否选择了给定的实例。
  • SelectSession,选择一个指定的Session
  • SetInstanceSelected,设置一个指定的实例选中或者不选中。

接下来是事件相关:

DECLARE_EVENT_TwoParams(ISessionManager, FCanSelectSessionEvent, const TSharedPtr<ISessionInfo>& /*Session*/, bool& /*OutCanSelect*/)
virtual FCanSelectSessionEvent& OnCanSelectSession() = 0;

在选择一个Session开始时执行的委托。

DECLARE_EVENT_TwoParams(ISessionManager, FInstanceSelectionChangedEvent, const TSharedPtr<ISessionInstanceInfo>& /*Instance*/, bool /*Selected*/)
virtual FInstanceSelectionChangedEvent& OnInstanceSelectionChanged() = 0;

选择的实例改变后执行的委托。

DECLARE_EVENT_ThreeParams(ISessionManager, FLogReceivedEvent, const TSharedRef<ISessionInfo>& /*OwnerSession*/, const TSharedRef<ISessionInstanceInfo>& /*SessionInstance*/, const TSharedRef<FSessionLogMessage>& /*LogMessage*/);
virtual FLogReceivedEvent& OnLogReceived() = 0;

接收日志后执行的委托。

DECLARE_EVENT_OneParam(ISessionManager, FSelectedSessionChangedEvent, const TSharedPtr<ISessionInfo>& /*SelectedSession*/)
virtual FSelectedSessionChangedEvent& OnSelectedSessionChanged() = 0;

选择的Session改变后执行的委托。

virtual FSimpleMulticastDelegate& OnSessionsUpdated() = 0;

当Session更新后执行的委托。

virtual FSimpleMulticastDelegate& OnSessionInstanceUpdated() = 0;

当Session实例更新后执行的委托。

ISessionModule

这个接口仅仅简单包装了一下IModuleInterface

/**
 * Interface for session core modules.
 */
class ISessionServicesModule
	: public IModuleInterface
{
public:

	/**
	 * Gets the session manager.
	 *
	 * @return The session manager.
	 * @see GetSessionService
	 */
	virtual TSharedPtr<ISessionManager> GetSessionManager() = 0;

	/** 
	 * Gets the session service.
	 *
	 * @return The session service.
	 * @see GetSessionManager
	 */
	virtual TSharedPtr<ISessionService> GetSessionService() = 0;

public:

	/** Virtual destructor. */
	virtual ~ISessionServicesModule() { }
};

其中两个方法:

  • GetSessionManager,得到一个当前模块的SessionManager
  • GetSessionService,得到一个当前模块的SessionService

实现

传递的消息

在模块SessionMessages SessionServiceMessage.h中

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Misc/Guid.h"
#include "SessionServiceMessages.generated.h"


/* Session discovery messages
 *****************************************************************************/

/**
 * Implements a message that is published to discover existing application sessions.
 */
USTRUCT()
struct FSessionServicePing
{
	GENERATED_USTRUCT_BODY()

	/** The name of the user who sent this ping. */
	UPROPERTY(EditAnywhere, Category="Message")
	FString UserName;

	/** Default constructor. */
	FSessionServicePing() { }

	/** Creates and initializes a new instance. */
	FSessionServicePing(const FString& InUserName)
		: UserName(InUserName)
	{ }
};


/**
 * Implements a message that is published in response to FSessionServicePing.
 */
USTRUCT()
struct FSessionServicePong
{
	GENERATED_USTRUCT_BODY()

	/** Indicates whether the pinging user is authorized to interact with this session. */
	UPROPERTY(EditAnywhere, Category="Message")
	bool Authorized = true;

	/** Holds the application's build date. */
	UPROPERTY(EditAnywhere, Category="Message")
	FString BuildDate;

	/** Holds the name of the device that the application is running on. */
	UPROPERTY(EditAnywhere, Category="Message")
	FString DeviceName;

	/** Holds the application's instance identifier. */
	UPROPERTY(EditAnywhere, Category="Message")
	FGuid InstanceId;

	/** Holds the application's instance name. */
	UPROPERTY(EditAnywhere, Category="Message")
	FString InstanceName;

	/** Holds the name of the platform that the application is running on. */
	UPROPERTY(EditAnywhere, Category="Message")
	FString PlatformName;

	/** Holds the identifier of the session that the application belongs to. */
	UPROPERTY(EditAnywhere, Category="Message")
	FGuid SessionId;

	/** Holds the user defined name of the session. */
	UPROPERTY(EditAnywhere, Category="Message")
	FString SessionName;

	/** Holds the name of the user that started the session. */
	UPROPERTY(EditAnywhere, Category="Message")
	FString SessionOwner;

	/** Indicates whether the application is the only one in that session. */
	UPROPERTY(EditAnywhere, Category="Message")
	bool Standalone = true;
};


/* Session status messages
 *****************************************************************************/

/**
 * Implements a message that contains a console log entry.
 */
USTRUCT()
struct FSessionServiceLog
{
	GENERATED_USTRUCT_BODY()

	/** Holds the log message category. */
	UPROPERTY(EditAnywhere, Category="Message")
	FName Category;

	/** Holds the log message data. */
	UPROPERTY(EditAnywhere, Category="Message")
	FString Data;

	/** Holds the application instance identifier. */
	UPROPERTY(EditAnywhere, Category="Message")
	FGuid InstanceId;

	/** Holds the time in seconds since the application was started. */
	UPROPERTY(EditAnywhere, Category="Message")
	double TimeSeconds = 0.0;

	/** Holds the log message's verbosity level. */
	UPROPERTY(EditAnywhere, Category="Message")
	uint8 Verbosity;

public:

	/** Default constructor. */
	FSessionServiceLog() : TimeSeconds(0.0), Verbosity(0) { }

	/**
	 * Creates and initializes a new instance.
	 */
	FSessionServiceLog(const FName& InCategory, const FString& InData, const FGuid& InInstanceId, double InTimeSeconds, uint8 InVerbosity)
		: Category(InCategory)
		, Data(InData)
		, InstanceId(InInstanceId)
		, TimeSeconds(InTimeSeconds)
		, Verbosity(InVerbosity)
	{ }
};


/**
 * Implements a message to subscribe to an application's console log.
 */
USTRUCT()
struct FSessionServiceLogSubscribe
{
	GENERATED_USTRUCT_BODY()
};


/**
 * Implements a message to unsubscribe from an application's console log.
 */
USTRUCT()
struct FSessionServiceLogUnsubscribe
{
	GENERATED_USTRUCT_BODY()
};

我们可以看见有如下消息用于通信

  • Ping
  • Pong
  • FSessionServiceLog,日志消息
  • FSessionServiceLogUnsubscribe,表示取消订阅订阅日志。

FSessionService

SessionService.h

class FSessionService
	: public FOutputDevice
	, public ISessionService

FSessionService继承于FOutputDevice,ISessionService。

private:	
/** Holds the list of log subscribers. */
	TArray<FMessageAddress> LogSubscribers;

	/** Holds a critical section for the log subscribers array. */
	FCriticalSection LogSubscribersLock;

	/** Holds a weak pointer to the message bus. */
	TWeakPtr<IMessageBus, ESPMode::ThreadSafe> MessageBusPtr;

	/** Holds the message endpoint. */
	TSharedPtr<FMessageEndpoint, ESPMode::ThreadSafe> MessageEndpoint;

	/** Set to true while in SendLog, used to avoid recursion */
	bool IsInSendLog;
  • LogSubscribers,一组订阅了日志的端点地址。
  • MessageBusPtr,消息总线的弱引用。
  • MessageEndpoint,service的消息端点。

构造函数:

FSessionService::FSessionService(const TSharedRef<IMessageBus, ESPMode::ThreadSafe>& InMessageBus)
    : MessageBusPtr(InMessageBus)
{ }

使用一个const TSharedRef<IMessageBus, ESPMode::ThreadSafe>&来构造MessageBusPtr。

析构函数:

FSessionService::~FSessionService()
{
    Stop();
}

其中Stop的定义:

void FSessionService::Stop()
{
	if (IsRunning())
	{
		GLog->RemoveOutputDevice(this);
		MessageEndpoint.Reset();
	}
}

如果IsRunning返回true,就重置MessageEndpoint。然后从GLog中移除自身。

IsRunning实现就是简单的检查MessageEndpoint是否合法:

	virtual bool IsRunning() override
	{
		return MessageEndpoint.IsValid();
	}

Start,也就是启动过程如下:

bool FSessionService::Start()
{
	auto MessageBus = MessageBusPtr.Pin();

	if (!MessageBus.IsValid())
	{
		return false;
	}

	// initialize messaging
	MessageEndpoint = FMessageEndpoint::Builder("FSessionService", MessageBus.ToSharedRef())
		.Handling<FSessionServiceLogSubscribe>(this, &FSessionService::HandleSessionLogSubscribeMessage)
		.Handling<FSessionServiceLogUnsubscribe>(this, &FSessionService::HandleSessionLogUnsubscribeMessage)
		.Handling<FSessionServicePing>(this, &FSessionService::HandleSessionPingMessage);

	if (!MessageEndpoint.IsValid())
	{
		return false;
	}

	MessageEndpoint->Subscribe<>();
	GLog->AddOutputDevice(this);

	return true;
}
  1. 因为MessageBusPtr是一个弱引用,所以每次使用前都需要Pin一下,然后检查是否有效。
  2. 使用FMessageEndpoint::Builder构建一个MessageEndpoint并检查
  3. 使端点订阅FSessionServicePing这个消息。
  4. 向GLog中添加自身这个输出设备。
  5. 返回

对于MessageEndpoint构建过程中的Handling:

Handling<FSessionServiceLogSubscribe(this,&FSessionService::HandleSessionLogSubscribeMessage)处理的是收到订阅日志消息后如何处理:

void FSessionService::HandleSessionLogSubscribeMessage(const FSessionServiceLogSubscribe& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context)
{
	FScopeLock Lock(&LogSubscribersLock);
	LogSubscribers.AddUnique(Context->GetSender());
}
  1. 上锁
  2. 向LogSubscriber中添加发送者。

处理取消订阅消息:

void FSessionService::HandleSessionLogUnsubscribeMessage(const FSessionServiceLogUnsubscribe& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context)
{
	FScopeLock Lock(&LogSubscribersLock);
	LogSubscribers.Remove(Context->GetSender());
}
  1. 上锁
  2. 然后删除发送者。

处理Ping消息:

void FSessionService::HandleSessionPingMessage(const FSessionServicePing& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context)
{
    SendPong(Context, Message.UserName);
}

简单的会送一个Pong消息。

SendPong定义如下:

void FSessionService::SendPong(const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context, const FString& UserName)
{
    if (!MessageEndpoint.IsValid())
    {
       return;
    }

    FSessionServicePong* Message = new FSessionServicePong();
    {
       Message->Authorized = FApp::IsAuthorizedUser(UserName);
       Message->BuildDate = FApp::GetBuildDate();
       Message->DeviceName = FPlatformProcess::ComputerName();
       Message->InstanceId = FApp::GetInstanceId();
       Message->InstanceName = FApp::GetInstanceName();
       Message->PlatformName = FPlatformProperties::PlatformName();
       Message->SessionId = FApp::GetSessionId();
       Message->SessionName = FApp::GetSessionName();
       Message->SessionOwner = FApp::GetSessionOwner();
       Message->Standalone = FApp::IsStandalone();
    }

    MessageEndpoint->Send(Message, Context->GetSender());
}
  1. 检查Endpoint是否合法
  2. 构建FSessionServicePong
  3. 使用Send方法发送构建出来的Pong信息。

FSessionServiceManager

第一部分的私有成员

/** The address of the automation controller to where we can forward any automation workers found. */
FGuid AutomationControllerAddress;

/** Holds the time at which the last ping was sent. */
FDateTime LastPingTime;

/** Holds a pointer to the message bus. */
TWeakPtr<IMessageBus, ESPMode::ThreadSafe> MessageBusPtr;

/** Holds the messaging endpoint. */
TSharedPtr<FMessageEndpoint, ESPMode::ThreadSafe> MessageEndpoint;

/** Holds the list of currently selected instances. */
TArray<TSharedPtr<ISessionInstanceInfo>> SelectedInstances;

/** Holds a reference to the currently selected session. */
TSharedPtr<ISessionInfo> SelectedSession;

/** Holds the collection of discovered sessions. */
//为每个发现的Session都分配了一个FGuid
TMap<FGuid, TSharedPtr<FSessionInfo>> Sessions;

每个变量的作用注释中已经说明。

第二部分的私有成员:

private:

    /** Holds a delegate to be invoked before a session is selected. */
    FCanSelectSessionEvent CanSelectSessionDelegate;

    /** Holds a delegate to be invoked when an instance changes its selection state. */
    FInstanceSelectionChangedEvent InstanceSelectionChangedDelegate;

    /** Owner filter list. */
    TArray<FString> FilteredOwners;

    /** Holds a delegate to be invoked when the selected session received a log message. */
    FLogReceivedEvent LogReceivedEvent;

    /** Holds a delegate to be invoked when the selected session changed. */
    FSelectedSessionChangedEvent SelectedSessionChangedEvent;

    /** Holds a delegate to be invoked when the session list was updated. */
    FSimpleMulticastDelegate SessionsUpdatedDelegate;

    /** Holds a delegate to be invoked when a session instance is updated. */
    FSimpleMulticastDelegate SessionInstanceUpdatedDelegate;

    /** Holds a delegate to be invoked when the widget ticks. */
    FDelegateHandle TickDelegateHandle;

分别对应接口中的事件。

发布Ping消息:

void FSessionManager::SendPing()
{
    QUICK_SCOPE_CYCLE_COUNTER(STAT_FSessionmanager_SendPing);

	if (MessageEndpoint.IsValid())
	{
		MessageEndpoint->Publish(new FEngineServicePing(), EMessageScope::Network);
		MessageEndpoint->Publish(new FSessionServicePing(FPlatformProcess::UserName(false)), EMessageScope::Network);
	}

	LastPingTime = FDateTime::UtcNow();
}

每次发布一次Ping消息,都会更新LastPingTime,以便周期性发布Ping:

bool FSessionManager::HandleTicker(float DeltaTime)
{
    QUICK_SCOPE_CYCLE_COUNTER(STAT_FSessionmanager_HandleTicker);

	FDateTime Now = FDateTime::UtcNow();

	// @todo gmp: don't expire sessions for now
//	FindExpiredSessions(Now);

	if (Now >= LastPingTime + FTimespan::FromSeconds(SESSION_MANAGER_PING_INTERVAL))
	{
		SendPing();
	}

	return true;
}

构造函数:

FSessionManager::FSessionManager(const TSharedRef<IMessageBus, ESPMode::ThreadSafe>& InMessageBus)
	: MessageBusPtr(InMessageBus)
{
	// fill in the owner array
	FString Filter;
	// 命令解析
	if (FParse::Value(FCommandLine::Get(), TEXT("SessionFilter="), Filter))
	{
		// Allow support for -SessionFilter=Filter1+Filter2+Filter3
		int32 PlusIdx = Filter.Find(TEXT("+"), ESearchCase::CaseSensitive);

		while (PlusIdx != INDEX_NONE)
		{
			FString Owner = Filter.Left(PlusIdx);
			FilteredOwners.Add(Owner);
			Filter.RightInline(Filter.Len() - (PlusIdx + 1), false);
			PlusIdx = Filter.Find(TEXT("+"), ESearchCase::CaseSensitive);
		}

		FilteredOwners.Add(Filter);
	}

	// connect to message bus
	MessageEndpoint = FMessageEndpoint::Builder("FSessionManager", InMessageBus)
		.Handling<FEngineServicePong>(this, &FSessionManager::HandleEnginePongMessage)
		.Handling<FSessionServicePong>(this, &FSessionManager::HandleSessionPongMessage);

	// initialize ticker,注册HandleTicker到CoreTicker目的是为了周期性的发送Ping
	TickDelegateHandle = FTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateRaw(this, &FSessionManager::HandleTicker), SESSION_MANAGER_PING_INTERVAL);

	SendPing();
}

析构函数:

FSessionManager::~FSessionManager()
{
	FTicker::GetCoreTicker().RemoveTicker(TickDelegateHandle);
}

将Ticker注销。

FSessionServiceModule

SessionServiceModule.cpp:

private:
	
	/** Holds a weak pointer to the message bus. */
	TWeakPtr<IMessageBus, ESPMode::ThreadSafe> MessageBusPtr;

	/** Holds the session manager singleton. */
	TSharedPtr<ISessionManager> SessionManager;

	/** Holds the session service singleton. */
	TSharedPtr<ISessionService> SessionService;

私有的三个成员:

  • MessageBusPtr,消息总线的弱引用指针。
  • SessionManager,一个ISessionManager的实例。

启动模块:

virtual void StartupModule() override
	{
		MessageBusPtr = IMessagingModule::Get().GetDefaultBus();
	}

使用IMessagingModule::Get().GetDefaultBus();获取一个系统默认的消息总线。

关闭模块:

	virtual void ShutdownModule() override
	{
		SessionManager.Reset();
		SessionService.Reset();
	}

仅仅是重置两个指针。

SessionManager和SessionService使用惰性初始化的方式。

	virtual TSharedPtr<ISessionManager> GetSessionManager() override
	{
		if (!SessionManager.IsValid() && MessageBusPtr.IsValid())
		{
			SessionManager = MakeShareable(new FSessionManager(MessageBusPtr.Pin().ToSharedRef()));
		}

		return SessionManager;
	}

	virtual TSharedPtr<ISessionService> GetSessionService() override
	{
		if (!SessionService.IsValid() && MessageBusPtr.IsValid())
		{
			SessionService = MakeShareable(new FSessionService(MessageBusPtr.Pin().ToSharedRef()));
		}

		return SessionService;
	}

消息传递

简单的来说客户端和编辑器段做的内容大致如下:

客户端

  • 每个游戏客户端持有一个SessionService,内包含一个MessageEndpoint用于通信。
  • 会处理日志订阅消息。
  • 会处理日志取消订阅消息。
  • 订阅Ping信息,处理Ping信息。然后SendPong。
  • 记录了订阅日志消息的编辑器,向这些编辑器发送自己的日志。

编辑器

  • 编辑器端持有一个SessionManager用于管理各个Session。
  • 包含一个Endpoint端点用于通信。
  • 会处理FEngineServicePong消息。
  • 会处理FSessionServicePong消息。
  • 周期性发布Ping消息,以便订阅了Ping消息的SessionService接收到。

注意下SessionManager会发送两种Ping,一种是自定义的FSessionSericePing,这种Ping由SessionService处理。

另一种是FEngineServicePing,这种Ping由引擎内部处理,Pong返回关于引擎的一些信息。

UI

在UI中,将使用到SessionInfo,SessionInstanceInfo,SessionManager中的其他方法和成员,比如点击一个正在主机上运行的游戏,就订阅这个游戏的日志,类似这种UI逻辑,都会在UI中实现。UI部分是编辑器特有的,Runtime并不会包含。

使用控件反射器可以定位到实现的源码。

SessionBrowser

在这里插入图片描述

private:

	/** Holds an unfiltered list of available sessions. */
	TArray<TSharedPtr<ISessionInfo>> AvailableSessions;

	/** Holds the command bar. */
	TSharedPtr<SSessionBrowserCommandBar> CommandBar;

	/** Whether to ignore events from the session manager. */
	bool IgnoreSessionManagerEvents;

	/** Whether to ignore events from the session tree view. */
	bool updatingTreeExpansion;

	/** Maps session and instance GUIDs to existing tree items. */
	TMap<FGuid, TSharedPtr<FSessionBrowserTreeItem>> ItemMap;

	/** Holds a reference to the session manager. */
	TSharedPtr<ISessionManager> SessionManager;	//ISessionMessager的实例

	/** Holds the filtered list of tree items. */
	TArray<TSharedPtr<FSessionBrowserTreeItem>> SessionTreeItems;

	/** Holds the session tree view. */
	TSharedPtr<STreeView<TSharedPtr<FSessionBrowserTreeItem>>> SessionTreeView;
private:

	/** The session tree item that holds this application's session. */
	TSharedPtr<FSessionBrowserGroupTreeItem> AppGroupItem;

	/** The session tree item that holds other user's sessions. */
	TSharedPtr<FSessionBrowserGroupTreeItem> OtherGroupItem; //其他会话

	/** The session tree item that holds the owner's remote sessions. */
	TSharedPtr<FSessionBrowserGroupTreeItem> OwnerGroupItem; //我的会话

	/** The session tree item that holds other user's standalone instances. */
	TSharedPtr<FSessionBrowserGroupTreeItem> StandaloneGroupItem; //独立实例

	/** This app's instance session */
	TWeakPtr<FSessionBrowserTreeItem> ThisAppInstance;	//此应用程序

	/** True if we should set the default selection the next time the tree view if refreshed. */
	bool bCanSetDefaultSelection;	

UI部分的构建不是很重要,我们主要看SessionManager和UI的交互逻辑。

void SSessionBrowser::Construct( const FArguments& InArgs, TSharedRef<ISessionManager> InSessionManager )
{
	IgnoreSessionManagerEvents = false;
	updatingTreeExpansion = false;
	bCanSetDefaultSelection = true;
	SessionManager = InSessionManager;

构造函数中需要通过一个共享指针来传入SessionManager。构造SessionManager。

//TODO

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值