diff --git a/rename-ue-project/Program.cs b/rename-ue-project/Program.cs
new file mode 100644
index 0000000..c11a8fe
--- /dev/null
+++ b/rename-ue-project/Program.cs
@@ -0,0 +1,91 @@
+using System.Text.RegularExpressions;
+
+namespace rename_ue_project
+{
+ internal class Program
+ {
+ const string OLD_PROJECT_NAME = "MotionMatching";
+ const string UE_PROJECT_EXTENSION = ".uproject";
+ const string GITIGNORE = ".gitignore";
+ const string README = "READ.ME";
+ const string CONFIG_FOLDER = "config";
+ const string DEGAULT_GAME_INI = "DefaultGame.ini";
+
+ // todo: test this!!
+ ///
+ /// Replaces folder and ue project file with new project name. Also replaces occurrences in .gitignore and projectName in DefaultGame.ini
+ ///
+ ///
+ /// 0: absolute path to unreal project root
+ /// 1: new project name, must be no longer than 20 chars and [a-zA-Z0-9-_]
+ /// 2: long description for your game, can be markdown is used for READ.ME
+ ///
+ ///
+ /// if a file was not where expected
+ /// if an app parameter was invalid
+ static async Task Main(string[] args)
+ {
+ var projectPath = args[0];
+ var projectName = args[1];
+ var descLong = args[2];
+
+
+ if (!Directory.Exists(projectPath))
+ {
+ throw new IOException($"Directory {projectPath} does not exist");
+ }
+
+ // step 0: validate ue project name
+ var rgxName = "'^[a-zA-Z0-9_-]+$";
+ Match m = Regex.Match(projectName, rgxName, RegexOptions.IgnoreCase);
+ if (m.Success)
+ {
+ throw new ArgumentException("Unreal project names can not be longer than 20 chars and must not contain special chars, except - and _");
+ }
+
+ // step 1: rename directory
+ if (!Directory.Exists(OLD_PROJECT_NAME))
+ {
+ throw new IOException($"Directory {OLD_PROJECT_NAME} does not exist");
+ }
+
+ Directory.Move(
+ Path.Combine(projectPath, OLD_PROJECT_NAME),
+ Path.Combine(projectPath, projectName)
+ );
+ Console.WriteLine("Renamed project directory");
+
+ // step 2: rename project file
+ File.Move(
+ Path.Combine(projectPath, projectName, $"{OLD_PROJECT_NAME}{UE_PROJECT_EXTENSION}"),
+ Path.Combine(projectPath, projectName, $"{projectName}{UE_PROJECT_EXTENSION}")
+ );
+
+ // step 3: replace everything in gitignore
+ var ignoreContent = await File.ReadAllTextAsync(Path.Combine(projectPath, GITIGNORE));
+ ignoreContent = ignoreContent.Replace(OLD_PROJECT_NAME, projectName);
+ Console.WriteLine("Replaced project name in gitignore");
+
+ // step 4: write read.me in format # projectName + new line + descrLong
+ var readMe = @$"# {projectName}{Environment.NewLine}{descLong}";
+ await File.WriteAllTextAsync(Path.Combine(projectPath, README), readMe);
+ Console.WriteLine("Wrote READ.ME");
+
+ // step 5: replace name in DefaultGame.ini
+ var configPath = Path.Combine(projectPath, projectName, CONFIG_FOLDER, DEGAULT_GAME_INI);
+ if (!File.Exists(configPath))
+ {
+ throw new IOException($"Unreal config {DEGAULT_GAME_INI} not found at {configPath} - can not replace project name");
+ }
+
+ var defaultGameIni = await File.ReadAllTextAsync(configPath);
+ var rgxPrjName = @"(?<=ProjectName=)[^\s]+";
+
+ // Perform the replacement
+ defaultGameIni = Regex.Replace(defaultGameIni, rgxPrjName, projectName);
+ await File.WriteAllTextAsync(configPath, defaultGameIni);
+ Console.WriteLine($"Replaced project name in {DEGAULT_GAME_INI}");
+
+ }
+ }
+}
diff --git a/rename-ue-project/rename-ue-project.csproj b/rename-ue-project/rename-ue-project.csproj
new file mode 100644
index 0000000..c14f5be
--- /dev/null
+++ b/rename-ue-project/rename-ue-project.csproj
@@ -0,0 +1,11 @@
+
+
+
+ Exe
+ net8.0
+ rename_ue_project
+ enable
+ enable
+
+
+
diff --git a/rename-ue-project/rename-ue-project.sln b/rename-ue-project/rename-ue-project.sln
new file mode 100644
index 0000000..a6f6b52
--- /dev/null
+++ b/rename-ue-project/rename-ue-project.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.10.35013.160
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "rename-ue-project", "rename-ue-project.csproj", "{A8D865C3-BFF0-4276-8260-EC60FC6493F9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A8D865C3-BFF0-4276-8260-EC60FC6493F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A8D865C3-BFF0-4276-8260-EC60FC6493F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A8D865C3-BFF0-4276-8260-EC60FC6493F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A8D865C3-BFF0-4276-8260-EC60FC6493F9}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {EF1712C3-E679-4CE7-9977-5B49871CA26D}
+ EndGlobalSection
+EndGlobal