Beispiel #1
0
void Lacrimi::SetupZoneScripts()
{
    if(GetConfigBool("ZoneScripts", "EnableOutlandScripts", true))
        SetupOutlandScripts();
    if(GetConfigBool("ZoneScripts", "EnableKalimdorScripts", true))
        SetupKalimdorScripts();
    if(GetConfigBool("ZoneScripts", "EnableEbonHoldScripts", true))
        SetupEbonHoldScripts();
    if(GetConfigBool("ZoneScripts", "EnableNorthrendScripts", true))
        SetupNorthrendScripts();
    if(GetConfigBool("ZoneScripts", "EnableEasternKingdomScripts", true))
        SetupEasternKingdomScripts();
}
Beispiel #2
0
bool CConfigBool::GetValue()
{
    if (HasToRefresh())
        m_Value = GetConfigBool(GetSection(), GetKey(), m_Default);
    
    return m_Value;
}
Beispiel #3
0
bool Lacrimi::run()
{
    Delay(400);
    if(GetConfigBool("Features", "LuaEngine", true))
    {
        L_LuaEngineMgr = new LuaEngineMgr();
        L_LuaEngineMgr->Startup();
        Delay(100);
        while(LuaEngineIsStarting)
            Delay(100);
    }

    uint32 curTime = getMSTime();
    uint32 m_StatDumpTimer = curTime+15000, m_CleanupDelay = curTime+10000;
    while(GetThreadState() != THREADSTATE_SELF_TERMINATE)
    {
        curTime = getMSTime();
        if(!SetThreadState(THREADSTATE_BUSY))
            break;

        if(dumpstats)
        {
            if(curTime > m_StatDumpTimer)
            {
                DumpStats();
                m_StatDumpTimer = curTime+60000;
            }
        }

        if(curTime > m_CleanupDelay)
            Cleanup();
        if(!SetThreadState(THREADSTATE_SLEEPING))
            break;
        Delay(5);
    }
    sLog.Notice("Lacrimi", "Terminating...");

    FinalCleanup();
    if(database)
        _StopDB();
    OnShutdown();
    return true;
}
Beispiel #4
0
// Use sMgr for Script Mgr.
void Lacrimi::SetupScripts()
{
    sLog.Success("Lacrimi", "Lacrimi Engine Started");
    sLog.Success("","############################################################");
    sLog.Success("","# ##            #       ####### ####### ##    #    #    ## #");
    sLog.Success("","# ##           ###      ##      ##   ## ##   ###  ###   ## #");
    sLog.Success("","# ##          ## ##     ##      ##   ## ##   ###  ###   ## #");
    sLog.Success("","# ##         #######    ##      ####### ##  ## #### ##  ## #");
    sLog.Success("","# ##        ##     ##   ##      #####   ##  ## #### ##  ## #");
    sLog.Success("","# ##       ##       ##  ##      ##  ##  ## ##   ##   ## ## #");
    sLog.Success("","# ####### ##         ## ####### ##   ## ## ##   ##   ## ## #");
    sLog.Success("","# :::::::.::.........::.:::::::.::...::.::.::...::...::.:: #");
    sLog.Success("","############################################################");

    // Load our configs
    lacrimiIni = new CIniFile("./lacrimi.ini");
    if(lacrimiIni->ParseError())
        config = false;

    // Load our DBs
    if(_StartDB())
        database = true;

    dumpstats = GetConfigBool("StatDumper", "DumpStats", false);
    if(dumpstats)
    {
        sLog.Success("Lacrimi", "Stat Dumper Initialized");
        strcpy(Filename, GetConfigString("StatDumper", "Filename", "stats.xml").c_str());
    }

    sLog.Notice("Lacrimi", "C++ Loading scripts...");
    SetupCityScripts();
    SetupSpellScripts();
    SetupCustomScripts();

    SetupZoneScripts();
    SetupInstanceScripts();
}
int main(int argc, char *argv[])
{
    int done = FALSE;
    opterr = 0;

    //fprintf(stderr, "ctrack started.");
    c_control = C_RUN;

    srand((int)time(NULL));

	ErrorInit();    
    ConfigInit(); // initializes verbose; must be called before any output

   	ReadConfig(TRUE); // default loc.
    TorrentDBCreate();

    unsigned int p;
    while (!done) {
        switch (getopt(argc, argv, "+vqVhrdt:u:p:c:"))  { // + means "don't shuffle args"
            case '?': // invalid option
                PrintSyntax(1);
            case 'h': // help option
                PrintSyntax(0);
            case 'V':
            	printf("ctrack " VERSION "\n");
            	return 0;
                break;
            case 'v':
                SetConfigBool(CFG_VERBOSE, TRUE);
                log("Verbose mode");
                break;
            case 'q':
                SetConfigBool(CFG_VERBOSE, FALSE);
                log("Quiet mode");
                break;
            case 't':
                if (b_assign(atoi(optarg),1,65535,(int *)&p))
                    SetConfigUInt(CFG_HTTP_PORT, p);
                break;
            case 'u':
                if (b_assign(atoi(optarg),1,65535,(int *)&p))
                    SetConfigUInt(CFG_UDP_PORT, p);
                break;
            case 'p':
                if (b_assign(atoi(optarg),1,65535,(int *)&p))
                    SetConfigUInt(CFG_SERVER_PORT, p);
                break;
            case 'd':
                SetConfigBool(CFG_DAEMON, TRUE);
                break;
            case 'c': //config file
	            SetConfigString(CFG_CONFIG_FILE, optarg);
                ReadConfig(FALSE);
            	break;
            case -1:  //end of options
                done = TRUE;
                break;
            default:
                PrintSyntax(1);
                break;    
        }//switch
    }//while
    int i;
    for (i = optind; i < argc; i++) {
    	PTorrentInfo t;
    	char ibuffer[20];
    	if (strtohash(argv[i], ibuffer)) {
			NewTorrentInfo(&t, ibuffer);
		} else {
			errorm("Invalid hash: %s", argv[i]);
		}
    }//for

    //TODO:parse args
    //TODO:init torrent db

#ifdef DAEMON_SUPPORT
    if (GetConfigBool(CFG_DAEMON) == TRUE) {
    /* Our process ID and Session ID */
    pid_t pid, sid;

    /* Fork off the parent process */
    pid = fork();
    if (pid < 0) { exit(EXIT_FAILURE); }
    /* If we got a good PID, then we can exit the parent process. */
    if (pid > 0) { exit(EXIT_SUCCESS); }
    /* Change the file mode mask */
    umask(0);
        /* Create a new SID for the child process */
    sid = setsid();
    if (sid < 0) {
		errorm("setsid() failed: %s", str_error());
		exit(EXIT_FAILURE);
    }
    /* Change the current working directory */
    if ((chdir("/")) < 0) {
		errorm("chdir() failed: %s", str_error());
        exit(EXIT_FAILURE);
    }
    /* Close out the standard file descriptors */
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

	if (daemon(TRUE, FALSE) != 0) 
        errorf(E_SYSTEM, "daemon() failed: %S", str_error());
    } else {
		extern int asdaemon;
		asdaemon = TRUE;
    }
#endif

    //SetupSignalHandlers
	sigset_t set;
	int sig;

    while (c_control == C_RUN) {
    	sigfillset(&set);
    	pthread_sigmask(SIG_SETMASK, &set, NULL);

        if (GetConfigBool(CFG_HTTP_SERVER)) { // HTTP server
	        if (SetUpListener())
    	        HTTPThreadInit();
	    }

	    if (GetConfigBool(CFG_UDP_SERVER)) { // UDP server
	        UDPThreadInit();
	    }

		//TODO: sigwait
		while (c_control == C_RUN) {
		    sigwait(&set, &sig);
			logf("Caught signal #%d", sig);
			switch (sig) {
				case SIGINT:
	                c_control = C_TERMINATE;
    	            log("Exitting...");
        	        break;
				case SIGHUP:
	                c_control = C_RESTART;
	                log("Restarting...");
                   	ReadConfig(FALSE);
	                break;
				case SIGSEGV:
	                c_control = C_TERMINATE;
    	            log("Exitting...");
			}//switch
		}//while
        ThreadsDestroy();
    	CloseTCPSocket();
    	CloseUDPSocket();

        if (c_control == C_RESTART) { c_control = C_RUN; }
    }//while

  	log("exit ");
    return ((sig==SIGINT) ? EXIT_SUCCESS : EXIT_FAILURE);
}
int32 UGenerateGatherArchiveCommandlet::Main( const FString& Params )
{
    FInternationalization& I18N = FInternationalization::Get();

    // Parse command line - we're interested in the param vals
    TArray<FString> Tokens;
    TArray<FString> Switches;
    TMap<FString, FString> ParamVals;
    UCommandlet::ParseCommandLine(*Params, Tokens, Switches, ParamVals);

    //Set config file
    const FString* ParamVal = ParamVals.Find(FString(TEXT("Config")));
    FString GatherTextConfigPath;

    if ( ParamVal )
    {
        GatherTextConfigPath = *ParamVal;
    }
    else
    {
        UE_LOG(LogGenerateArchiveCommandlet, Error, TEXT("No config specified."));
        return -1;
    }

    //Set config section
    ParamVal = ParamVals.Find(FString(TEXT("Section")));
    FString SectionName;

    if ( ParamVal )
    {
        SectionName = *ParamVal;
    }
    else
    {
        UE_LOG(LogGenerateArchiveCommandlet, Error, TEXT("No config section specified."));
        return -1;
    }

    // Get manifest name.
    FString ManifestName;
    if( !GetConfigString( *SectionName, TEXT("ManifestName"), ManifestName, GatherTextConfigPath ) )
    {
        UE_LOG( LogGenerateArchiveCommandlet, Error, TEXT("No manifest name specified.") );
        return -1;
    }

    // Get source culture.
    FString SourceCulture;
    if( GetConfigString( *SectionName, TEXT("SourceCulture"), SourceCulture, GatherTextConfigPath ) )
    {
        if( I18N.GetCulture( SourceCulture ).IsValid() )
        {
            UE_LOG(LogGenerateArchiveCommandlet, Verbose, TEXT("Specified culture is not a valid runtime culture, but may be a valid base language: %s"), *(SourceCulture) );
        }
    }

    // Get cultures to generate.
    TArray<FString> CulturesToGenerate;
    GetConfigArray(*SectionName, TEXT("CulturesToGenerate"), CulturesToGenerate, GatherTextConfigPath);

    if( CulturesToGenerate.Num() == 0 )
    {
        UE_LOG(LogGenerateArchiveCommandlet, Error, TEXT("No cultures specified for generation."));
        return -1;
    }

    for(int32 i = 0; i < CulturesToGenerate.Num(); ++i)
    {
        if( I18N.GetCulture( CulturesToGenerate[i] ).IsValid() )
        {
            UE_LOG(LogGenerateArchiveCommandlet, Verbose, TEXT("Specified culture is not a valid runtime culture, but may be a valid base language: %s"), *(CulturesToGenerate[i]) );
        }
    }

    // Get destination path.
    FString DestinationPath;
    if( !GetConfigString( *SectionName, TEXT("DestinationPath"), DestinationPath, GatherTextConfigPath ) )
    {
        UE_LOG( LogGenerateArchiveCommandlet, Error, TEXT("No destination path specified.") );
        return -1;
    }

    if (FPaths::IsRelative(DestinationPath))
    {
        if (!FPaths::GameDir().IsEmpty())
        {
            DestinationPath = FPaths::Combine( *( FPaths::GameDir() ), *DestinationPath );
        }
        else
        {
            DestinationPath = FPaths::Combine( *( FPaths::EngineDir() ), *DestinationPath );
        }
    }

    // Get archive name.
    FString ArchiveName;
    if( !( GetConfigString(* SectionName, TEXT("ArchiveName"), ArchiveName, GatherTextConfigPath ) ) )
    {
        UE_LOG(LogGenerateArchiveCommandlet, Error, TEXT("No archive name specified."));
        return -1;
    }

    // Get bPurgeOldEmptyEntries option.
    bool ShouldPurgeOldEmptyEntries;
    if ( !GetConfigBool( *SectionName, TEXT("bPurgeOldEmptyEntries"), ShouldPurgeOldEmptyEntries, GatherTextConfigPath) )
    {
        ShouldPurgeOldEmptyEntries = false;
    }

    FString ManifestFilePath = DestinationPath / ManifestName;
    TSharedPtr<FJsonObject> ManifestJsonObject = ReadJSONTextFile( ManifestFilePath );

    if( !ManifestJsonObject.IsValid() )
    {
        UE_LOG(LogGenerateArchiveCommandlet, Error, TEXT("Could not read manifest file %s."), *ManifestFilePath);
        return -1;
    }

    FJsonInternationalizationManifestSerializer ManifestSerializer;
    TSharedRef< FInternationalizationManifest > InternationalizationManifest = MakeShareable( new FInternationalizationManifest );

    ManifestSerializer.DeserializeManifest( ManifestJsonObject.ToSharedRef(), InternationalizationManifest );

    for(int32 Culture = 0; Culture < CulturesToGenerate.Num(); Culture++)
    {
        TSharedRef< FInternationalizationArchive > InternationalizationArchive = MakeShareable( new FInternationalizationArchive );
        BuildArchiveFromManifest( InternationalizationManifest, InternationalizationArchive, SourceCulture, CulturesToGenerate[Culture] );

        const FString CulturePath = DestinationPath / CulturesToGenerate[Culture];
        FJsonInternationalizationArchiveSerializer ArchiveSerializer;
        TSharedRef< FInternationalizationArchive > OutputInternationalizationArchive = MakeShareable( new FInternationalizationArchive );

        // Read in any existing archive for this culture.
        FString ExistingArchiveFileName = CulturePath / ArchiveName;
        TSharedPtr< FJsonObject > ExistingArchiveJsonObject = NULL;

        if( FPaths::FileExists(ExistingArchiveFileName) )
        {
            ExistingArchiveJsonObject = ReadJSONTextFile( ExistingArchiveFileName );

            // Some of the existing archives were saved out with an "Unnamed" namespace for the root instead of the empty string.  We try to fix that here.
            if( ExistingArchiveJsonObject->HasField( FJsonInternationalizationArchiveSerializer::TAG_NAMESPACE ) )
            {
                FString RootNamespace = ExistingArchiveJsonObject->GetStringField( FJsonInternationalizationArchiveSerializer::TAG_NAMESPACE );
                if( RootNamespace == TEXT("Unnamed") )
                {
                    ExistingArchiveJsonObject->RemoveField( FJsonInternationalizationArchiveSerializer::TAG_NAMESPACE );
                    ExistingArchiveJsonObject->SetStringField( FJsonInternationalizationArchiveSerializer::TAG_NAMESPACE, TEXT("") );
                }
            }

            struct Local
            {
                // Purges this JSONObject of an entries with no translated text and purges empty namespaces.
                // Returns true if the object was modified, false if not.
                static bool PurgeNamespaceOfEmptyEntries(const TSharedPtr<FJsonObject>& JSONObject)
                {
                    bool ModifiedChildrenArray = false;
                    if( JSONObject->HasField( FJsonInternationalizationArchiveSerializer::TAG_CHILDREN ) )
                    {
                        TArray<TSharedPtr<FJsonValue>> ChildrenArray = JSONObject->GetArrayField(FJsonInternationalizationArchiveSerializer::TAG_CHILDREN);
                        for( int32 ChildIndex = ChildrenArray.Num() - 1; ChildIndex >= 0; --ChildIndex )
                        {
                            TSharedPtr<FJsonObject> Child = ChildrenArray[ ChildIndex ]->AsObject();
                            TSharedPtr<FJsonObject> TranslationObject = Child->GetObjectField(FJsonInternationalizationArchiveSerializer::TAG_TRANSLATION);

                            const FString& TranslatedText = TranslationObject->GetStringField(FJsonInternationalizationArchiveSerializer::TAG_TRANSLATION_TEXT);

                            if(TranslatedText.IsEmpty())
                            {
                                ChildrenArray.RemoveAt( ChildIndex );
                                Child = NULL;
                                ModifiedChildrenArray = true;
                            }
                        }
                        if(ModifiedChildrenArray)
                        {
                            JSONObject->RemoveField(FJsonInternationalizationArchiveSerializer::TAG_CHILDREN);
                            if(ChildrenArray.Num())
                            {
                                JSONObject->SetArrayField(FJsonInternationalizationArchiveSerializer::TAG_CHILDREN, ChildrenArray);
                            }
                        }
                    }

                    bool ModifiedSubnamespaceArray = false;
                    if( JSONObject->HasField( FJsonInternationalizationArchiveSerializer::TAG_SUBNAMESPACES ) )
                    {
                        TArray<TSharedPtr<FJsonValue>> SubnamespaceArray = JSONObject->GetArrayField(FJsonInternationalizationArchiveSerializer::TAG_SUBNAMESPACES);

                        for( int32 Index = SubnamespaceArray.Num() - 1; Index >= 0; --Index )
                        {
                            TSharedPtr<FJsonObject> Subnamespace = SubnamespaceArray[ Index ]->AsObject();
                            ModifiedSubnamespaceArray = PurgeNamespaceOfEmptyEntries(Subnamespace);

                            bool HasChildren = Subnamespace->HasField( FJsonInternationalizationArchiveSerializer::TAG_CHILDREN );
                            bool HasSubnamespaces = Subnamespace->HasField( FJsonInternationalizationArchiveSerializer::TAG_SUBNAMESPACES );

                            if(!HasChildren && !HasSubnamespaces)
                            {
                                SubnamespaceArray.RemoveAt( Index );
                                Subnamespace = NULL;
                                ModifiedSubnamespaceArray = true;
                            }
                        }
                        if(ModifiedSubnamespaceArray)
                        {
                            JSONObject->RemoveField(FJsonInternationalizationArchiveSerializer::TAG_SUBNAMESPACES);
                            if(SubnamespaceArray.Num())
                            {
                                JSONObject->SetArrayField(FJsonInternationalizationArchiveSerializer::TAG_SUBNAMESPACES, SubnamespaceArray);
                            }
                        }
                    }

                    return ModifiedChildrenArray || ModifiedSubnamespaceArray;
                }
            };

            if(ShouldPurgeOldEmptyEntries)
            {
                // Remove entries lacking translations from pre-existing archive.
                // If they are absent in the source manifest, we save on not translating non-existent text.
                // If they are present in the source manifest, then the newly generated entries will contain the empty text again.
                Local::PurgeNamespaceOfEmptyEntries(ExistingArchiveJsonObject);
            }

            ArchiveSerializer.DeserializeArchive( ExistingArchiveJsonObject.ToSharedRef(), OutputInternationalizationArchive );
        }

        if (InternationalizationArchive->GetFormatVersion() < FInternationalizationArchive::EFormatVersion::Latest)
        {
            UE_LOG( LogGenerateArchiveCommandlet, Error,TEXT("Archive version is out of date. Repair the archives or manually set the version to %d."), static_cast<int32>(FInternationalizationArchive::EFormatVersion::Latest));
            return -1;
        }

        // Combine the generated gather archive with the contents of the archive structure we will write out.
        AppendArchiveData( InternationalizationArchive, OutputInternationalizationArchive );
        InternationalizationArchive->SetFormatVersion(FInternationalizationArchive::EFormatVersion::Latest);

        TSharedRef< FJsonObject > OutputArchiveJsonObj = MakeShareable( new FJsonObject );
        ArchiveSerializer.SerializeArchive( OutputInternationalizationArchive, OutputArchiveJsonObj );

        if( !WriteArchiveToFile( OutputArchiveJsonObj, DestinationPath, *CulturesToGenerate[Culture], *ArchiveName ) )
        {
            UE_LOG( LogGenerateArchiveCommandlet, Error,TEXT("Failed to write archive to %s."), *DestinationPath );
            return -1;
        }
    }

    return 0;
}
int32 UGatherTextFromAssetsCommandlet::Main(const FString& Params)
{
	// Parse command line.
	TArray<FString> Tokens;
	TArray<FString> Switches;
	TMap<FString, FString> ParamVals;
	UCommandlet::ParseCommandLine(*Params, Tokens, Switches, ParamVals);

	//Set config file
	const FString* ParamVal = ParamVals.Find(FString(TEXT("Config")));
	FString GatherTextConfigPath;

	if ( ParamVal )
	{
		GatherTextConfigPath = *ParamVal;
	}
	else
	{
		UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No config specified."));
		return -1;
	}

	//Set config section
	ParamVal = ParamVals.Find(FString(TEXT("Section")));
	FString SectionName;

	if ( ParamVal )
	{
		SectionName = *ParamVal;
	}
	else
	{
		UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No config section specified."));
		return -1;
	}

	//Include paths
	TArray<FString> IncludePaths;
	GetConfigArray(*SectionName, TEXT("IncludePaths"), IncludePaths, GatherTextConfigPath);

	if (IncludePaths.Num() == 0)
	{
		UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("No include paths in section %s"), *SectionName);
		return -1;
	}

	//Exclude paths
	TArray<FString> ExcludePaths;
	GetConfigArray(*SectionName, TEXT("ExcludePaths"), ExcludePaths, GatherTextConfigPath);

	//package extensions
	TArray<FString> PackageExts;
	GetConfigArray(*SectionName, TEXT("PackageExtensions"), PackageExts, GatherTextConfigPath);

	if (PackageExts.Num() == 0)
	{
		UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("No package extensions specified in section %s, using defaults"), *SectionName);

		PackageExts.Add(FString("*") + FPackageName::GetAssetPackageExtension());
		PackageExts.Add(FString("*") + FPackageName::GetMapPackageExtension());
	}

	//asset class exclude
	TArray<FString> ExcludeClasses;
	GetConfigArray(*SectionName, TEXT("ExcludeClasses"), ExcludeClasses, GatherTextConfigPath);

	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
	AssetRegistryModule.Get().SearchAllAssets( true );
	FARFilter Filter;

	for(int32 i = 0; i < ExcludeClasses.Num(); i++)
	{
		UClass* FilterClass = FindObject<UClass>(ANY_PACKAGE, *ExcludeClasses[i]);
		if(FilterClass)
		{
			Filter.ClassNames.Add( FilterClass->GetFName() );
		}
		else
		{
			UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Invalid exclude class %s"), *ExcludeClasses[i]);
		}
	}

	TArray<FAssetData> AssetData;
	AssetRegistryModule.Get().GetAssets(Filter, AssetData);

	FString UAssetPackageExtension = FPackageName::GetAssetPackageExtension();
	TSet< FString > LongPackageNamesToExclude;
	for (int Index = 0; Index < AssetData.Num(); Index++)
	{
		LongPackageNamesToExclude.Add( FPackageName::LongPackageNameToFilename( AssetData[Index].PackageName.ToString(), UAssetPackageExtension ) );
	}

	//Get whether we should fix broken properties that we find.
	GetConfigBool(*SectionName, TEXT("bFixBroken"), bFixBroken, GatherTextConfigPath);

	// Add any manifest dependencies if they were provided
	TArray<FString> ManifestDependenciesList;
	GetConfigArray(*SectionName, TEXT("ManifestDependencies"), ManifestDependenciesList, GatherTextConfigPath);
	
	if( !ManifestInfo->AddManifestDependencies( ManifestDependenciesList ) )
	{
		UE_LOG(LogGatherTextFromAssetsCommandlet, Error, TEXT("The GatherTextFromAssets commandlet couldn't find all the specified manifest dependencies."));
		return -1;
	}

	//The main array of files to work from.
	TArray< FString > PackageFileNamesToLoad;
	TSet< FString > LongPackageNamesToProcess;

	TArray<FString> PackageFilesNotInIncludePath;
	TArray<FString> PackageFilesInExcludePath;
	TArray<FString> PackageFilesExcludedByClass;

	//Fill the list of packages to work from.
	uint8 PackageFilter = NORMALIZE_DefaultFlags;
	TArray<FString> Unused;	
	for ( int32 PackageFilenameWildcardIdx = 0; PackageFilenameWildcardIdx < PackageExts.Num(); PackageFilenameWildcardIdx++ )
	{
		const bool IsAssetPackage = PackageExts[PackageFilenameWildcardIdx] == ( FString( TEXT("*") )+ FPackageName::GetAssetPackageExtension() );

		TArray<FString> PackageFiles;
		if ( !NormalizePackageNames( Unused, PackageFiles, PackageExts[PackageFilenameWildcardIdx], PackageFilter) )
		{
			UE_LOG(LogGatherTextFromAssetsCommandlet, Display, TEXT("No packages found with extension %i: '%s'"), PackageFilenameWildcardIdx, *PackageExts[PackageFilenameWildcardIdx]);
			continue;
		}
		else
		{
			UE_LOG(LogGatherTextFromAssetsCommandlet, Display, TEXT("Found %i packages with extension %i: '%s'"), PackageFiles.Num(), PackageFilenameWildcardIdx, *PackageExts[PackageFilenameWildcardIdx]);
		}

		//Run through all the files found and add any that pass the include, exclude and filter constraints to OrderedPackageFilesToLoad
		for( int32 PackageFileIdx=0; PackageFileIdx<PackageFiles.Num(); ++PackageFileIdx )
		{
			bool bExclude = false;
			//Ensure it matches the include paths if there are some.
			for( int32 IncludePathIdx=0; IncludePathIdx<IncludePaths.Num() ; ++IncludePathIdx )
			{
				bExclude = true;
				if( PackageFiles[PackageFileIdx].MatchesWildcard(IncludePaths[IncludePathIdx]) )
				{
					bExclude = false;
					break;
				}
			}

			if ( bExclude )
			{
				PackageFilesNotInIncludePath.Add(PackageFiles[PackageFileIdx]);
			}

			//Ensure it does not match the exclude paths if there are some.
			for( int32 ExcludePathIdx=0; !bExclude && ExcludePathIdx<ExcludePaths.Num() ; ++ExcludePathIdx )
			{
				if( PackageFiles[PackageFileIdx].MatchesWildcard(ExcludePaths[ExcludePathIdx]) )
				{
					bExclude = true;
					PackageFilesInExcludePath.Add(PackageFiles[PackageFileIdx]);
					break;
				}
			}

			//Check that this is not on the list of packages that we don't care about e.g. textures.
			if ( !bExclude && IsAssetPackage && LongPackageNamesToExclude.Contains( PackageFiles[PackageFileIdx] ) )
			{
				bExclude = true;
				PackageFilesExcludedByClass.Add(PackageFiles[PackageFileIdx]);
			}

			//If we haven't failed one of the above checks, add it to the array of packages to process.
			if(!bExclude)
			{
				TScopedPointer< FArchive > FileReader( IFileManager::Get().CreateFileReader( *PackageFiles[PackageFileIdx] ) );
				if( FileReader )
				{
					// Read package file summary from the file
					FPackageFileSummary PackageSummary;
					(*FileReader) << PackageSummary;

					// Early out check if the package has been flagged as needing localization gathering
					if( PackageSummary.PackageFlags & PKG_RequiresLocalizationGather || PackageSummary.GetFileVersionUE4() < VER_UE4_PACKAGE_REQUIRES_LOCALIZATION_GATHER_FLAGGING )
					{
						PackageFileNamesToLoad.Add( PackageFiles[PackageFileIdx] );
					}
				}
			}
		}
	}

	if ( PackageFileNamesToLoad.Num() == 0 )
	{
		UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("No files found. Or none passed the include/exclude criteria."));
	}

	CollectGarbage( RF_Native );

	//Now go through the remaining packages in the main array and process them in batches.
	int32 PackagesPerBatchCount = 100;
	TArray< UPackage* > LoadedPackages;
	TArray< FString > LoadedPackageFileNames;
	TArray< FString > FailedPackageFileNames;
	TArray< UPackage* > PackagesToProcess;

	const int32 PackageCount = PackageFileNamesToLoad.Num();
	const int32 BatchCount = PackageCount / PackagesPerBatchCount + (PackageCount % PackagesPerBatchCount > 0 ? 1 : 0); // Add an extra batch for any remainder if necessary
	if(PackageCount > 0)
	{
		UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Loading %i packages in %i batches of %i."), PackageCount, BatchCount, PackagesPerBatchCount);
	}

	//Load the packages in batches
	int32 PackageIndex = 0;
	for( int32 BatchIndex = 0; BatchIndex < BatchCount; ++BatchIndex )
	{
		int32 PackagesInThisBatch = 0;
		for( PackageIndex; PackageIndex < PackageCount && PackagesInThisBatch < PackagesPerBatchCount; ++PackageIndex )
		{
			FString PackageFileName = PackageFileNamesToLoad[PackageIndex];

			UPackage *Package = LoadPackage( NULL, *PackageFileName, LOAD_None );
			if( Package )
			{
				LoadedPackages.Add(Package);
				LoadedPackageFileNames.Add(PackageFileName);

				// Because packages may not have been resaved after this flagging was implemented, we may have added packages to load that weren't flagged - potential false positives.
				// The loading process should have reflagged said packages so that only true positives will have this flag.
				if( Package->RequiresLocalizationGather() )
				{
					PackagesToProcess.Add( Package );
				}
			}
			else
			{
				FailedPackageFileNames.Add( PackageFileName );
				continue;
			}

			++PackagesInThisBatch;
		}

		UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Loaded %i packages in batch %i of %i."), PackagesInThisBatch, BatchIndex + 1, BatchCount);

		ProcessPackages(PackagesToProcess);
		PackagesToProcess.Empty(PackagesPerBatchCount);

		if( bFixBroken )
		{
			for( int32 LoadedPackageIndex=0; LoadedPackageIndex < LoadedPackages.Num() ; ++LoadedPackageIndex )
			{
				UPackage *Package = LoadedPackages[LoadedPackageIndex];
				const FString PackageName = LoadedPackageFileNames[LoadedPackageIndex];

				//Todo - link with source control.
				if( Package )
				{
					if( Package->IsDirty() )
					{
						if( SavePackageHelper( Package, *PackageName ) )
						{
							UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Saved Package %s."),*PackageName);
						}
						else
						{
							//TODO - Work out how to integrate with source control. The code from the source gatherer doesn't work.
							UE_LOG(LogGatherTextFromAssetsCommandlet, Log, TEXT("Could not save package %s. Probably due to source control. "),*PackageName);
						}
					}
				}
				else
				{
					UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Failed to find one of the loaded packages."));
				}
			}
		}

		CollectGarbage( RF_Native );
		LoadedPackages.Empty(PackagesPerBatchCount);	
		LoadedPackageFileNames.Empty(PackagesPerBatchCount);
	}

	for(auto i = ConflictTracker.Namespaces.CreateConstIterator(); i; ++i)
	{
		const FString& NamespaceName = i.Key();
		const FConflictTracker::FKeyTable& KeyTable = i.Value();
		for(auto j = KeyTable.CreateConstIterator(); j; ++j)
		{
			const FString& KeyName = j.Key();
			const FConflictTracker::FEntryArray& EntryArray = j.Value();

			for(int k = 0; k < EntryArray.Num(); ++k)
			{
				const FConflictTracker::FEntry& Entry = EntryArray[k];
				switch(Entry.Status)
				{
				case EAssetTextGatherStatus::MissingKey:
					{
						UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Detected missing key on asset \"%s\"."), *Entry.ObjectPath);
					}
					break;
				case EAssetTextGatherStatus::MissingKey_Resolved:
					{
						UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Fixed missing key on asset \"%s\"."), *Entry.ObjectPath);
					}
					break;
				case EAssetTextGatherStatus::IdentityConflict:
					{
						UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Detected duplicate identity with differing source on asset \"%s\"."), *Entry.ObjectPath);
					}
					break;
				case EAssetTextGatherStatus::IdentityConflict_Resolved:
					{
						UE_LOG(LogGatherTextFromAssetsCommandlet, Warning, TEXT("Fixed duplicate identity with differing source on asset \"%s\"."), *Entry.ObjectPath);
					}
					break;
				}
			}
		}
	}

	return 0;
}
Beispiel #8
0
int main( int argc, char** argv )
{
    InitTests(argc, argv);

    Describe("Config module")
        .use(dummyExceptionSandbox)

        .it("can be initialized empty.", [](){

            Require(InitConfig(0, NULL) == true);
            DestroyConfig();
        })

        .it("has a proper destructor.", [](){

            const char* argv[] = {"", "--aaa=bbb"};

            {
                Require(InitConfig(2, argv) == true);
                ConfigScope scope;
                Require(strcmp(GetConfigString("aaa",""), "bbb") == 0);
            }

            {
                Require(InitConfig(0, NULL) == true);
                ConfigScope scope;
                Require(GetConfigString("aaa",NULL) == NULL);
            }
        })

        .it("can parse arguments.", [](){

            const char* argv[] = {"", "--aaa=bbb", "--foo=bar", "--ccc=ddd"};

            Require(InitConfig(4, argv) == true);
            ConfigScope scope;

            Require(strcmp(GetConfigString("foo",""), "bar") == 0);
            Require(strcmp(GetConfigString("foo","yyy"), "bar") == 0);
            Require(strcmp(GetConfigString("foo",NULL), "bar") == 0);
            Require(strcmp(GetConfigString("xxx",""), "") == 0);
            Require(strcmp(GetConfigString("xxx","yyy"), "yyy") == 0);
            Require(GetConfigString("xxx",NULL) == NULL);
        })

        .it("can convert integer values.", [](){

            const char* argv[] = {"", "--aaa=42", "--bbb=1.1", "--ccc=1.9"};

            Require(InitConfig(4, argv) == true);
            ConfigScope scope;

            Require(GetConfigInt("aaa", 0) == 42);
            Require(GetConfigInt("bbb", 0) == 1);
            Require(GetConfigInt("ccc", 0) == 1);
            Require(GetConfigInt("xxx", 0) == 0);
        })

        .it("can convert floating point values.", [](){

            const char* argv[] = {"", "--aaa=42", "--bbb=1.1", "--ccc=1.9"};

            Require(InitConfig(4, argv) == true);
            ConfigScope scope;

            Require(GetConfigFloat("aaa", 0) == 42);
            Require(GetConfigFloat("bbb", 0) == 1.1f);
            Require(GetConfigFloat("ccc", 0) == 1.9f);
            Require(GetConfigFloat("xxx", 0.1f) == 0.1f);
        })

        .it("can convert boolean values.", [](){

            const char* argv[] = {
                "",
                "--aaa=42",
                "--bbb=1.1",
                "--ccc=1.9",
                "--ddd=0",
                "--eee=0.0",
                "--fff=true",
                "--ggg=false",
                "--hhh=yes",
                "--jjj=no"};

            Require(InitConfig(10, argv) == true);
            ConfigScope scope;

            Require(GetConfigBool("aaa", false) == true);
            Require(GetConfigBool("bbb", false) == true);
            Require(GetConfigBool("ccc", false) == true);
            Require(GetConfigBool("ddd", true) == false);
            Require(GetConfigBool("eee", true) == false);
            Require(GetConfigBool("fff", false) == true);
            Require(GetConfigBool("ggg", true) == false);
            Require(GetConfigBool("hhh", false) == true);
            Require(GetConfigBool("jjj", true) == false);

            Require(GetConfigBool("xxx", true) == true);
            Require(GetConfigBool("xxx", false) == false);
        })

        .it("can parse ini files.", [](){

            const char* argv[] = {"", "--config=config/Test.ini"};

            Require(InitConfig(2, argv) == true);
            ConfigScope scope;

            Require(GetConfigString("config", NULL) == NULL);
            Require(strcmp(GetConfigString("aaa", ""), "bbb") == 0);
            Require(strcmp(GetConfigString("foo.bar", ""), "baz") == 0);
            Require(strcmp(GetConfigString("foo.hello", ""), "Hello World") == 0);
        });

    return RunTests();
}
Beispiel #9
0
void InitWindow()
{
    const int width  = GetConfigInt("window.width",  640);
    const int height = GetConfigInt("window.height", 480);
    const char* title = GetConfigString("window.title", "Konstrukt");

    const bool debug = GetConfigBool("opengl.debug", false);
    const bool vsync = GetConfigBool("opengl.vsync", true);

    LogInfo("Compiled with GLFW %d.%d.%d",
             GLFW_VERSION_MAJOR,
             GLFW_VERSION_MINOR,
             GLFW_VERSION_REVISION);
    LogInfo("Using GLFW %s", glfwGetVersionString());

    assert(g_Window == NULL);
    glfwSetErrorCallback(OnGLFWError);
    if(!glfwInit())
        FatalError("GLFW init failed.");

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_DEPTH_BITS, GetConfigInt("opengl.depth-bits", 24));
    glfwWindowHint(GLFW_STENCIL_BITS, 0);
    glfwWindowHint(GLFW_SAMPLES, GetConfigInt("opengl.samples", 0));
    glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, debug ? GL_TRUE : GL_FALSE);

    g_Window = glfwCreateWindow(width, height, title, NULL, NULL);
    if(!g_Window)
        FatalError("Window creation failed.");

    glfwGetWindowSize(g_Window, &g_WindowWidth, &g_WindowHeight);
    glfwGetFramebufferSize(g_Window, &g_FramebufferWidth, &g_FramebufferHeight);

    glfwMakeContextCurrent(g_Window);

    if(!flextInit(g_Window))
        FatalError("Failed to load OpenGL extensions.");

    LogInfo("Using OpenGL %s\n"
            "Vendor: %s\n"
            "Renderer: %s\n"
            "GLSL: %s",
            glGetString(GL_VERSION),
            glGetString(GL_VENDOR),
            glGetString(GL_RENDERER),
            glGetString(GL_SHADING_LANGUAGE_VERSION));

    if(vsync)
    {
        if(glfwExtensionSupported("GLX_EXT_swap_control_tear") ||
           glfwExtensionSupported("WGL_EXT_swap_control_tear"))
            glfwSwapInterval(-1); // enable vsync (allow the driver to swap even if a frame arrives a little bit late)
        else
            glfwSwapInterval(1); // enable vsync
    }
    else
    {
        glfwSwapInterval(0); // disable vsync
    }

    glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    glfwSetInputMode(g_Window, GLFW_STICKY_KEYS, GL_FALSE);
    glfwSetInputMode(g_Window, GLFW_STICKY_MOUSE_BUTTONS, GL_FALSE);

    if(debug)
    {
        if(!FLEXT_ARB_debug_output)
            FatalError("Debug output requested, but it's not supported!");

        glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
        glDebugMessageCallbackARB(OnDebugEvent, NULL);
        LogInfo("Debug output supported! You may receive debug messages from your OpenGL driver.");
    }

    glfwSetWindowSizeCallback(g_Window, OnWindowResize);
    glfwSetFramebufferSizeCallback(g_Window, OnFramebufferResize);
    glfwSetMouseButtonCallback(g_Window, OnMouseButtonAction);
    glfwSetScrollCallback(g_Window, OnMouseScroll);
    glfwSetCursorPosCallback(g_Window, OnCursorMove);
    glfwSetKeyCallback(g_Window, OnKeyAction);
}
int32 UInternationalizationConditioningCommandlet::Main( const FString& Params )
{
	TArray<FString> Tokens;
	TArray<FString> Switches;
	TMap<FString, FString> ParamVals;
	UCommandlet::ParseCommandLine(*Params, Tokens, Switches, ParamVals);
	
	const FString* ParamVal = ParamVals.Find(FString(TEXT("Config")));

	if ( ParamVal )
	{
		GatherTextConfigPath = *ParamVal;
	}
	else
	{
		UE_LOG(LogInternationalizationConditioningCommandlet, Error, TEXT("No config specified."));
		return -1;
	}

	//Set config section
	ParamVal = ParamVals.Find(FString(TEXT("Section")));
	

	if ( ParamVal )
	{
		SectionName = *ParamVal;
	}
	else
	{
		UE_LOG(LogInternationalizationConditioningCommandlet, Error, TEXT("No config section specified."));
		return -1;
	}

	// Common settings
	FString SourcePath; // Source path to the root folder that manifest/archive files live in
	FString DestinationPath; // Destination path that we will write conditioned archive and manifest files to.  Language specific info will be appended to this path for archives.
	FString PrimaryLangExt;
	TArray<FString> LanguagesToProcess;

	// Settings for generating/appending to archive files from legacy localization files
	bool bGenerateArchiveFromLocIni = false;


	// Settings for generating or appending entries to manifest from legacy localization files
	bool bGenerateManifestFromLocIni = false;
	
	// Get the common settings from config
	GetConfigString( *SectionName, TEXT("SourcePath"), SourcePath, GatherTextConfigPath );
	GetConfigString( *SectionName, TEXT("DestinationPath"), DestinationPath, GatherTextConfigPath );
	GetConfigString( *SectionName, TEXT("PrimaryLanguage"), PrimaryLangExt, GatherTextConfigPath );
	GetConfigArray( *SectionName, TEXT("ProcessLanguage"), LanguagesToProcess, GatherTextConfigPath );

	GetConfigBool( *SectionName, TEXT("bGenerateManifestFromLocIni"), bGenerateManifestFromLocIni, GatherTextConfigPath );
	GetConfigBool( *SectionName, TEXT("bGenerateArchiveFromLocIni"), bGenerateArchiveFromLocIni, GatherTextConfigPath );

	// Load legacy localization files.
	LoadLegacyLocalizationFiles(SourcePath, PrimaryLangExt, LanguagesToProcess);

	// If features are enabled, we'll do those in order here
	if(  bGenerateManifestFromLocIni )
	{
		// Add to or create a manifest if desired
		if( !ProcessManifest( PrimaryLangExt, SourcePath, DestinationPath ) )
		{
			UE_LOG(LogInternationalizationConditioningCommandlet, Error, TEXT("Failed to generate manifest file from ini files."));
			return -1;
		}
	}

	if( bGenerateArchiveFromLocIni )
	{
		if( !ProcessArchive( PrimaryLangExt, SourcePath, DestinationPath ) )
		{
			UE_LOG(LogInternationalizationConditioningCommandlet, Error, TEXT("Failed to generate manifest file from ini files."));
			return -1;
		}
	}

	return 0;
}
bool UInternationalizationConditioningCommandlet::ProcessArchive( const FString& PrimaryLangExt, const FString& SourcePath, const FString& DestinationPath )
{
	FString ArchiveName = TEXT("Archive.txt");
	TArray<FString> LanguagesToProcess;
	TArray<FString> TargetCultures;
	bool bAppendToExistingArchive = true;

	GetConfigString( *SectionName, TEXT("ArchiveName"), ArchiveName, GatherTextConfigPath );
	GetConfigArray( *SectionName, TEXT("ProcessLanguage"), LanguagesToProcess, GatherTextConfigPath );
	GetConfigArray( *SectionName, TEXT("TargetCulture"), TargetCultures, GatherTextConfigPath );
	GetConfigBool( *SectionName, TEXT("bAppendToExistingArchive"), bAppendToExistingArchive, GatherTextConfigPath );

	// Build info about the primary language
	TArray<FString> PrimaryFilenames;
	TArray<FString> PathPrimaryFilenames;
	FString PrimaryLocDirectory = SourcePath / PrimaryLangExt + TEXT("/");
	FString PrimaryWildcardName = PrimaryLocDirectory + TEXT("*.") + PrimaryLangExt;
	// Grab the list of primary language loc files
	IFileManager::Get().FindFiles(PathPrimaryFilenames, *PrimaryWildcardName, true, false);
	for ( int32 FileIndex = 0; FileIndex < PathPrimaryFilenames.Num(); FileIndex++ )
	{
		FString* CompleteFilename = new(PrimaryFilenames) FString(PrimaryLocDirectory + PathPrimaryFilenames[FileIndex]);
	}

	if ( PrimaryFilenames.Num() == 0 )
	{
		UE_LOG(LogInternationalizationConditioningCommandlet, Warning, TEXT("No primary language(%s) loc files found!"), *PrimaryLangExt);
		return false;
	}

	for( int32 LanguageIndex = 0; LanguageIndex < LanguagesToProcess.Num(); LanguageIndex++ )
	{
		FString ForeignLangExt = LanguagesToProcess[LanguageIndex];
		TArray<FString> ForeignFilenames;
		TArray<FString> PathForeignFilenames;
		FString ForeignLocDirectory = SourcePath / ForeignLangExt + TEXT("/");
		FString ForeignWildcardName = ForeignLocDirectory + TEXT("*.") + ForeignLangExt;
		FString TargetSubfolder = TargetCultures.Num() > LanguageIndex ? TargetCultures[LanguageIndex] : ForeignLangExt;

		// Get a list of foreign loc files
		IFileManager::Get().FindFiles(PathForeignFilenames, *ForeignWildcardName, true, false);

		for ( int32 FileIndex = 0; FileIndex < PathForeignFilenames.Num(); FileIndex++ )
		{
			FString* CompleteFilename = new(ForeignFilenames) FString(ForeignLocDirectory + PathForeignFilenames[FileIndex]);
		}

		if ( ForeignFilenames.Num() == 0 )
		{
			UE_LOG(LogInternationalizationConditioningCommandlet, Warning, TEXT("No foreign loc files found using language extension '%s'"), *ForeignLangExt);
			continue;
		}

		ReadLocFiles(PrimaryFilenames, ForeignFilenames);

		TArray<FLocalizationFileEntry> ArchiveProperties;

		// FSor each file in the list, 
		for ( int32 i = 0; i < LocPairs.Num(); i++ )
		{
			FLocalizationFilePair& Pair = LocPairs[i];
			Pair.CompareFiles();

			Pair.GetTranslatedProperties( ArchiveProperties );
			Pair.GetIdenticalProperties( ArchiveProperties );

		}

		TSharedRef< FInternationalizationArchive > InternationalizationArchive = MakeShareable( new FInternationalizationArchive );
		FInternationalizationArchiveJsonSerializer ArchiveSerializer;

		const FString DestinationArchiveFileName = DestinationPath / TargetSubfolder / ArchiveName;

		// If we want to append to an existing archive, we first read it into our data structure
		if( bAppendToExistingArchive )
		{
			FString ExistingArchiveFileName = DestinationArchiveFileName;

			if( FPaths::FileExists(ExistingArchiveFileName) )
			{
				TSharedPtr< FJsonObject > ExistingArchiveJsonObject = ReadJSONTextFile( ExistingArchiveFileName );
				if( ExistingArchiveJsonObject.IsValid() )
				{
					ArchiveSerializer.DeserializeArchive( ExistingArchiveJsonObject.ToSharedRef(), InternationalizationArchive );
				}
			}
		}

		for( int PropIndex = 0; PropIndex < ArchiveProperties.Num(); PropIndex++ )
		{
			FLocalizationFileEntry& Prop = ArchiveProperties[PropIndex];
			FString NewNamespace = Prop.Namespace;

			FLocItem Source( Prop.SourceText );
			FLocItem Translation( Prop.TranslatedText );

			if( !InternationalizationArchive->AddEntry( NewNamespace, Source, Translation, NULL, false ) )
			{
				TSharedPtr<FArchiveEntry> ExistingConflictEntry = InternationalizationArchive->FindEntryBySource( NewNamespace, Source, NULL );

				if( !ExistingConflictEntry.IsValid() )
				{
					// Looks like we failed to add for a reason beyond conflicting translation, display an error and continue.
					UE_LOG(LogInternationalizationConditioningCommandlet, Warning, TEXT("Failed to add entry to archive Namespace [%s]: (DEFAULT TEXT): %s (EXISTING TRANSLATION): %s"), 
						*NewNamespace, *Prop.SourceText, *ExistingConflictEntry->Translation.Text );
					continue;
				}

				// If we can't add the entry, we find the existing conflicting entry and see if the translation is empty.  If it is empty we will
				// just overwrite the translation.  If it is not empty we will display info about the conflict.
				if( ExistingConflictEntry->Translation.Text.IsEmpty() )
				{
					ExistingConflictEntry->Translation.Text =  Prop.TranslatedText;
				}
				else
				{
					UE_LOG(LogInternationalizationConditioningCommandlet, Warning, TEXT("Conflicting translation ignored in Namespace [%s]: (DEFAULT TEXT): %s (EXISTING TRANSLATION): %s  (REJECTED TRANSLATION): %s"), 
						*NewNamespace, *Prop.SourceText, *ExistingConflictEntry->Translation.Text, *Prop.TranslatedText );
				}
			}
		}

		TSharedRef<FJsonObject> FinalArchiveJsonObj = MakeShareable( new FJsonObject );
		ArchiveSerializer.SerializeArchive( InternationalizationArchive, FinalArchiveJsonObj );

		WriteJSONToTextFile( FinalArchiveJsonObj, DestinationArchiveFileName, SourceControlInfo );

		LocPairs.Empty();
	}
	return true;
}