/**
 * Give the async task time to do its work
 * Can only be called on the async task manager thread
 */
void FOnlineAsyncTaskSteamUpdateServer::Tick()
{
	FOnlineSessionSteamPtr SessionInt = StaticCastSharedPtr<FOnlineSessionSteam>(Subsystem->GetSessionInterface());
	FNamedOnlineSession* Session = SessionInt->GetNamedSession(SessionName);
	if (Session)
	{
		bool bUsesPresence = Session->SessionSettings.bUsesPresence;
		if (bUsesPresence != NewSessionSettings.bUsesPresence)
		{
			UE_LOG_ONLINE(Warning, TEXT("Can't change presence settings on existing session %s, ignoring."), *SessionName.ToString());
		}

		Session->SessionSettings = NewSessionSettings;
		Session->SessionSettings.bUsesPresence = bUsesPresence;

		if (bUpdateOnlineData)
		{
			UWorld* World = GetWorldForOnline(Subsystem->GetInstanceName());

			// Master server update
			UpdatePublishedSettings(World, Session);
		}

		bWasSuccessful = true;
	}
	else
	{
		UE_LOG_ONLINE(Warning, TEXT("No session %s found to update with Steam backend"), *SessionName.ToString());
	}

	bIsComplete = true;
}
int32 GetPortFromNetDriver(FName InstanceName)
{
	int32 Port = 0;
#if WITH_ENGINE
	if (GEngine)
	{
		UWorld* World = GetWorldForOnline(InstanceName);
		UNetDriver* NetDriver = World ? GEngine->FindNamedNetDriver(World, NAME_GameNetDriver) : NULL;
		if (NetDriver && NetDriver->GetNetMode() < NM_Client)
		{
			FString AddressStr = NetDriver->LowLevelGetNetworkNumber();
			int32 Colon = AddressStr.Find(":", ESearchCase::IgnoreCase, ESearchDir::FromEnd);
			if (Colon != INDEX_NONE)
			{
				FString PortStr = AddressStr.Mid(Colon + 1);
				if (!PortStr.IsEmpty())
				{
					Port = FCString::Atoi(*PortStr);
				}
			}
		}
	}
#endif
	return Port;
}
    /**
     * Give the async task a chance to marshal its data back to the game thread
     * Can only be called on the game thread by the async task manager
     */
    virtual void Finalize() override
    {
        FOnlineSessionMakeshiftPtr SessionInt = StaticCastSharedPtr<FOnlineSessionMakeshift>(Subsystem->GetSessionInterface());

        if (bWasSuccessful)
        {
            FNamedOnlineSession* Session = SessionInt->GetNamedSession(SessionName);
            if (Session)
            {
                // Setup the host session info
                FOnlineSessionInfoMakeshift* NewSessionInfo = new FOnlineSessionInfoMakeshift();
                NewSessionInfo->Init(*Subsystem);

                // Create the proper Steam P2P address for this machine
                NewSessionInfo->HostAddr = ISocketSubsystem::Get()->GetLocalBindAddr(*GLog);
                UE_LOG_ONLINE(Verbose, TEXT("Server IP: %s"), *NewSessionInfo->HostAddr->ToString(true));

                Session->SessionInfo = MakeShareable(NewSessionInfo);

                Session->SessionState = EOnlineSessionState::Pending;

                UWorld* World = GetWorldForOnline(Subsystem->GetInstanceName());
                //UpdatePublishedSettings(World, Session);

                SessionInt->RegisterLocalPlayers(Session);
            }
            else
            {
                UE_LOG_ONLINE(Warning, TEXT("No session %s found to update with Makeshift backend"), *SessionName.ToString());
            }
        }
        else
        {
            SessionInt->RemoveNamedSession(SessionName);
        }
    }
/**
 * Give the async task a chance to marshal its data back to the game thread
 * Can only be called on the game thread by the async task manager
 */
void FOnlineAsyncTaskSteamCreateServer::Finalize() 	
{
	FOnlineSessionSteamPtr SessionInt = StaticCastSharedPtr<FOnlineSessionSteam>(Subsystem->GetSessionInterface());
	if (bWasSuccessful)
	{
		FNamedOnlineSession* Session = SessionInt->GetNamedSession(SessionName);
		if (Session)
		{
			// Setup the host session info
			FOnlineSessionInfoSteam* NewSessionInfo = new FOnlineSessionInfoSteam(ESteamSession::AdvertisedSessionHost, *SessionInt->GameServerSteamId);
			NewSessionInfo->Init();

			ISteamGameServer* SteamGameServerPtr = SteamGameServer();
			check(SteamGameServerPtr);

			// Create the proper Steam P2P address for this machine
			NewSessionInfo->SteamP2PAddr = ISocketSubsystem::Get()->GetLocalBindAddr(*GLog);
			NewSessionInfo->SteamP2PAddr->SetPort(Subsystem->GetGameServerGamePort());
			UE_LOG_ONLINE(Verbose, TEXT("Server SteamP2P IP: %s"), *NewSessionInfo->SteamP2PAddr->ToString(true));

			// Create the proper ip address for this server
			NewSessionInfo->HostAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr(SteamGameServerPtr->GetPublicIP(), Subsystem->GetGameServerGamePort());
			UE_LOG_ONLINE(Verbose, TEXT("Server IP: %s"), *NewSessionInfo->HostAddr->ToString(true));

			if (!Session->OwningUserId.IsValid())
			{
				check(Session->SessionSettings.bIsDedicated);
				// Associate the dedicated server anonymous login as the owning user
				Session->OwningUserId = SessionInt->GameServerSteamId;
				Session->OwningUserName = Session->OwningUserId->ToString();
			}
			
			Session->SessionInfo = MakeShareable(NewSessionInfo);
			Session->SessionSettings.bAntiCheatProtected = SteamGameServerPtr->BSecure() != 0 ? true : false;

			Session->SessionState = EOnlineSessionState::Pending;

			UWorld* World = GetWorldForOnline(Subsystem->GetInstanceName());
			UpdatePublishedSettings(World, Session);

			SessionInt->RegisterLocalPlayers(Session);

			if (SteamUser())
			{
				SteamUser()->AdvertiseGame(NewSessionInfo->SessionId, SteamGameServerPtr->GetPublicIP(), Subsystem->GetGameServerGamePort());
			}
			
			// Set host rich presence string so we can find via FindFriendSession()
// 			FString ConnectionString = Sessions->GetSteamConnectionString(Session->SessionName);
// 			if (!SteamFriends()->SetRichPresence("connect", TCHAR_TO_UTF8(*ConnectionString)))
// 			{
// 				UE_LOG_ONLINE(Verbose, TEXT("Failed to set rich presence for session %s"), *Session->SessionName.ToString());
// 			}
		}
		else
		{
			UE_LOG_ONLINE(Warning, TEXT("No session %s found to update with Steam backend"), *SessionName.ToString());
		}
	}
	else
	{
		SessionInt->RemoveNamedSession(SessionName);
	}
}