bool NUTNet::CreateFakePlayer(UWorld* InWorld, UNetDriver*& InNetDriver, FString ServerIP, FNetworkNotify* InNotify/*=NULL*/, bool bSkipJoin/*=false*/, FUniqueNetIdRepl* InNetID/*=NULL*/, bool bBeaconConnect/*=false*/, FString InBeaconType/*=TEXT("")*/) { bool bSuccess = false; if (InNetDriver == NULL) { InNetDriver = (InWorld != NULL ? NUTNet::CreateUnitTestNetDriver(InWorld) : NULL); } if (InNetDriver != NULL) { if (InNotify == NULL) { FNetworkNotifyHook* NotifyHook = new FNetworkNotifyHook(); InNotify = NotifyHook; auto DefaultRejectChan = [](UChannel* Channel) { UE_LOG(LogUnitTest, Log, TEXT("UnitTestNetDriver: NotifyAcceptingChannel: %s"), *Channel->Describe()); return false; }; NotifyHook->NotifyAcceptingChannelDelegate.BindLambda(DefaultRejectChan); } FURL DefaultURL; FURL TravelURL(&DefaultURL, *ServerIP, TRAVEL_Absolute); FString ConnectionError; if (InNetDriver->InitConnect(InNotify, TravelURL, ConnectionError)) { UNetConnection* TargetConn = InNetDriver->ServerConnection; UE_LOG(LogUnitTest, Log, TEXT("Successfully kicked off connect to IP '%s'"), *ServerIP); int ControlBunchSequence = 0; FOutBunch* ControlChanBunch = NUTNet::CreateChannelBunch(ControlBunchSequence, TargetConn, CHTYPE_Control, 0); // Need to send 'NMT_Hello' to start off the connection (the challenge is not replied to) uint8 IsLittleEndian = uint8(PLATFORM_LITTLE_ENDIAN); // We need to construct the NMT_Hello packet manually, for the initial connection uint8 MessageType = NMT_Hello; *ControlChanBunch << MessageType; *ControlChanBunch << IsLittleEndian; #if TARGET_UE4_CL >= CL_FNETWORKVERSION // Starting with 4.8.0, the network protocol has changed slightly // @todo JohnB: Refactor this, to toggle at compile time only, based on CL (might require more accurate UT integrate CLs) FString VersionStr = GEngineVersion.ToString(EVersionComponent::Minor); int32 VersionDelim = VersionStr.Find(TEXT(".")); int32 MajorVersion = FCString::Atoi(*VersionStr.Left(VersionDelim)); int32 MinorVersion = FCString::Atoi(*VersionStr.Mid(VersionDelim+1)); bool bOldProtocol = (MajorVersion <= 4 && MinorVersion <= 7) && /** Exception for UT (treat 4.7 as having the new protocol) */ (FString(FApp::GetGameName()) != TEXT("UnrealTournament") || (MajorVersion <= 4 && MinorVersion <= 6)); if (bOldProtocol) #endif { int32 EngineMinNetVersion = GEngineMinNetVersion; *ControlChanBunch << EngineMinNetVersion; int32 EngineNetVersion = GEngineNetVersion; *ControlChanBunch << EngineNetVersion; *ControlChanBunch << (FGuid&)GetDefault<UGeneralProjectSettings>()->ProjectID; } #if TARGET_UE4_CL >= CL_FNETWORKVERSION else { uint32 LocalNetworkVersion = FNetworkVersion::GetLocalNetworkVersion(); *ControlChanBunch << LocalNetworkVersion; } #endif if (bBeaconConnect) { if (!bSkipJoin) { MessageType = NMT_BeaconJoin; *ControlChanBunch << MessageType; *ControlChanBunch << InBeaconType; // Also immediately ack the beacon GUID setup; we're just going to let the server setup the client beacon, // through the actor channel MessageType = NMT_BeaconNetGUIDAck; *ControlChanBunch << MessageType; *ControlChanBunch << InBeaconType; } } else { // Then send NMT_Login #if TARGET_UE4_CL < CL_CONSTUNIQUEID TSharedPtr<FUniqueNetId> DudPtr = MakeShareable(new FUniqueNetIdString(TEXT("Dud"))); #else TSharedPtr<const FUniqueNetId> DudPtr = MakeShareable(new FUniqueNetIdString(TEXT("Dud"))); #endif FUniqueNetIdRepl PlayerUID(DudPtr); FString BlankStr = TEXT(""); FString ConnectURL = UUnitTest::UnitEnv->GetDefaultClientConnectURL(); if (InNetID != NULL) { PlayerUID = *InNetID; } MessageType = NMT_Login; *ControlChanBunch << MessageType; *ControlChanBunch << BlankStr; *ControlChanBunch << ConnectURL; *ControlChanBunch << PlayerUID; // Now send NMT_Join, to trigger a fake player, which should then trigger replication of basic actor channels if (!bSkipJoin) { MessageType = NMT_Join; *ControlChanBunch << MessageType; } } // Big hack: Store OutRec value on the unit test control channel, to enable 'retry-send' code TargetConn->Channels[0]->OutRec = ControlChanBunch; TargetConn->SendRawBunch(*ControlChanBunch, true); bSuccess = true; } else { UE_LOG(LogUnitTest, Log, TEXT("Failed to kickoff connect to IP '%s', error: %s"), *ServerIP, *ConnectionError); } } else if (InNetDriver == NULL) { UE_LOG(LogUnitTest, Log, TEXT("Failed to create an instance of the unit test net driver")); } else { UE_LOG(LogUnitTest, Log, TEXT("Failed to get a reference to WorldContext")); } return bSuccess; }