diff --git a/KurtzPelRegionPicker.sln b/KurtzPelRegionPicker.sln
new file mode 100644
index 0000000..c50380b
--- /dev/null
+++ b/KurtzPelRegionPicker.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28803.202
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KurtzPelRegionPicker", "KurtzPelRegionPicker\KurtzPelRegionPicker.csproj", "{CA6D150E-65AE-4577-956F-FBF677C913D5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CA6D150E-65AE-4577-956F-FBF677C913D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CA6D150E-65AE-4577-956F-FBF677C913D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CA6D150E-65AE-4577-956F-FBF677C913D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CA6D150E-65AE-4577-956F-FBF677C913D5}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4874B466-2064-4B66-836C-0252C1679394}
+ EndGlobalSection
+EndGlobal
diff --git a/KurtzPelRegionPicker/App.config b/KurtzPelRegionPicker/App.config
new file mode 100644
index 0000000..2d2a12d
--- /dev/null
+++ b/KurtzPelRegionPicker/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/KurtzPelRegionPicker/App.xaml b/KurtzPelRegionPicker/App.xaml
new file mode 100644
index 0000000..6b49a6c
--- /dev/null
+++ b/KurtzPelRegionPicker/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/KurtzPelRegionPicker/App.xaml.cs b/KurtzPelRegionPicker/App.xaml.cs
new file mode 100644
index 0000000..3c032fb
--- /dev/null
+++ b/KurtzPelRegionPicker/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace KurtzPelRegionPicker
+{
+ ///
+ /// Logique d'interaction pour App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/KurtzPelRegionPicker/Extensions.cs b/KurtzPelRegionPicker/Extensions.cs
new file mode 100644
index 0000000..5768a39
--- /dev/null
+++ b/KurtzPelRegionPicker/Extensions.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace KurtzPelRegionPicker
+{
+ public static class Extensions
+ {
+ public static int IndexOf(this T[] array, T value)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ if (array[i].Equals(value))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+ }
+}
diff --git a/KurtzPelRegionPicker/KurtzPel.ico b/KurtzPelRegionPicker/KurtzPel.ico
new file mode 100644
index 0000000..aec3522
Binary files /dev/null and b/KurtzPelRegionPicker/KurtzPel.ico differ
diff --git a/KurtzPelRegionPicker/KurtzPelRegionPicker.csproj b/KurtzPelRegionPicker/KurtzPelRegionPicker.csproj
new file mode 100644
index 0000000..82d6946
--- /dev/null
+++ b/KurtzPelRegionPicker/KurtzPelRegionPicker.csproj
@@ -0,0 +1,112 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {CA6D150E-65AE-4577-956F-FBF677C913D5}
+ WinExe
+ KurtzPelRegionPicker
+ KurtzPelRegionPicker
+ v4.6
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ KurtzPel.ico
+
+
+ app.manifest
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KurtzPelRegionPicker/MainWindow.xaml b/KurtzPelRegionPicker/MainWindow.xaml
new file mode 100644
index 0000000..b9c4761
--- /dev/null
+++ b/KurtzPelRegionPicker/MainWindow.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
diff --git a/KurtzPelRegionPicker/MainWindow.xaml.cs b/KurtzPelRegionPicker/MainWindow.xaml.cs
new file mode 100644
index 0000000..e0acaba
--- /dev/null
+++ b/KurtzPelRegionPicker/MainWindow.xaml.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net.NetworkInformation;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace KurtzPelRegionPicker
+{
+ ///
+ /// Logique d'interaction pour MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ public const string HOSTS_PATH = @"C:\Windows\System32\drivers\etc\hosts";
+ public const string COMMENT = "# KurtzPelRegionPicker";
+ // language=regex
+ public const string IP_REGEX = @"\[(?.+)\]";
+
+ private List _regions = new List()
+ {
+ new Region("Europe", "gs.live.europe.kurtzpel.playkog.com"),
+ new Region("America", "gs.live.northamerica.kurtzpel.playkog.com"),
+ new Region("Test", "gs.qa1.japan.kurtzpel.playkog.com")
+ };
+
+ public MainWindow()
+ {
+ InitializeComponent();
+
+ ComboBox_Source_Region.ItemsSource = _regions.Where(x => x.Name != "Test");
+ ComboBox_Fake_Region.ItemsSource = _regions;
+ }
+
+ private void Button_Apply_Click(object sender, RoutedEventArgs e)
+ {
+ if (ComboBox_Source_Region.SelectedItem is Region source && ComboBox_Fake_Region.SelectedItem is Region destination)
+ {
+ ApplyRegion(source, destination);
+
+ MessageBox.Show("Region applied", "Success", MessageBoxButton.OK, MessageBoxImage.Information);
+ Environment.Exit(0);
+ }
+ }
+
+ private void ApplyRegion(Region source, Region destination)
+ {
+ string[] content = File.ReadAllLines(HOSTS_PATH);
+ string[] newContent;
+
+ if (content.Contains(COMMENT))
+ {
+ // Purge
+ int index = content.IndexOf(COMMENT);
+
+ var list = content.ToList();
+
+ list.RemoveAt(index);
+ list.RemoveAt(index);
+
+ content = list.ToArray();
+ File.WriteAllLines(HOSTS_PATH, content);
+ }
+
+ string line = $"{GetRealIP(destination.DNS)} {source.DNS}";
+
+ newContent = new string[content.Length + 2];
+ content.CopyTo(newContent, 0);
+
+ newContent[newContent.Length - 2] = COMMENT;
+ newContent[newContent.Length - 1] = line;
+
+ File.WriteAllLines(HOSTS_PATH, newContent);
+ }
+
+ private string GetRealIP(string dns)
+ {
+ var process = new Process()
+ {
+ StartInfo = new ProcessStartInfo("ping.exe", $"-n 1 -w 10 {dns}")
+ {
+ CreateNoWindow = true,
+ RedirectStandardOutput = true,
+ UseShellExecute = false,
+ WindowStyle = ProcessWindowStyle.Hidden
+ }
+ };
+
+ process.Start();
+ process.WaitForExit();
+
+ string output = process.StandardOutput.ReadToEnd();
+ string ip = Regex.Match(output, IP_REGEX).Groups["ip"].Value;
+
+ if (ip == "")
+ {
+ MessageBox.Show($"Can't resolve hostname: {dns}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ Environment.Exit(1);
+ }
+
+ return ip;
+ }
+ }
+}
diff --git a/KurtzPelRegionPicker/Properties/AssemblyInfo.cs b/KurtzPelRegionPicker/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e13644c
--- /dev/null
+++ b/KurtzPelRegionPicker/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// Les informations générales relatives à un assembly dépendent de
+// l'ensemble d'attributs suivant. Pour modifier les informations
+// associées à un assembly.
+[assembly: AssemblyTitle("KurtzPelRegionPicker")]
+[assembly: AssemblyDescription("KPRP: Play on any KurtzPel server without VPN")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Ilyx")]
+[assembly: AssemblyProduct("KurtzPelRegionPicker")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("Ilyx")]
+[assembly: AssemblyCulture("")]
+
+// L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly
+// aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de
+// COM, affectez la valeur True à l'attribut ComVisible sur ce type.
+[assembly: ComVisible(false)]
+
+//Pour commencer à générer des applications localisables, définissez
+//CultureUtiliséePourCoder dans votre fichier .csproj
+//dans . Par exemple, si vous utilisez le français
+//dans vos fichiers sources, définissez à fr-FR. Puis, supprimez les marques de commentaire de
+//l'attribut NeutralResourceLanguage ci-dessous. Mettez à jour "fr-FR" dans
+//la ligne ci-après pour qu'elle corresponde au paramètre UICulture du fichier projet.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //où se trouvent les dictionnaires de ressources spécifiques à un thème
+ //(utilisé si une ressource est introuvable dans la page,
+ // ou dictionnaires de ressources de l'application)
+ ResourceDictionaryLocation.SourceAssembly //où se trouve le dictionnaire de ressources générique
+ //(utilisé si une ressource est introuvable dans la page,
+ // dans l'application ou dans l'un des dictionnaires de ressources spécifiques à un thème)
+)]
+
+
+// Les informations de version pour un assembly se composent des quatre valeurs suivantes :
+//
+// Version principale
+// Version secondaire
+// Numéro de build
+// Révision
+//
+// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut
+// en utilisant '*', comme indiqué ci-dessous :
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/KurtzPelRegionPicker/Properties/Resources.Designer.cs b/KurtzPelRegionPicker/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..2c1c8f0
--- /dev/null
+++ b/KurtzPelRegionPicker/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// Ce code a été généré par un outil.
+// Version du runtime :4.0.30319.42000
+//
+// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
+// le code est régénéré.
+//
+//------------------------------------------------------------------------------
+
+namespace KurtzPelRegionPicker.Properties {
+ using System;
+
+
+ ///
+ /// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
+ ///
+ // Cette classe a été générée automatiquement par la classe StronglyTypedResourceBuilder
+ // à l'aide d'un outil, tel que ResGen ou Visual Studio.
+ // Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
+ // avec l'option /str ou régénérez votre projet VS.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KurtzPelRegionPicker.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Remplace la propriété CurrentUICulture du thread actuel pour toutes
+ /// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/KurtzPelRegionPicker/Properties/Resources.resx b/KurtzPelRegionPicker/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/KurtzPelRegionPicker/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/KurtzPelRegionPicker/Properties/Settings.Designer.cs b/KurtzPelRegionPicker/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..718b3da
--- /dev/null
+++ b/KurtzPelRegionPicker/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// Ce code a été généré par un outil.
+// Version du runtime :4.0.30319.42000
+//
+// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
+// le code est régénéré.
+//
+//------------------------------------------------------------------------------
+
+namespace KurtzPelRegionPicker.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/KurtzPelRegionPicker/Properties/Settings.settings b/KurtzPelRegionPicker/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/KurtzPelRegionPicker/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KurtzPelRegionPicker/Region.cs b/KurtzPelRegionPicker/Region.cs
new file mode 100644
index 0000000..4d6ec26
--- /dev/null
+++ b/KurtzPelRegionPicker/Region.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace KurtzPelRegionPicker
+{
+ class Region
+ {
+ public string Name { get; }
+ public string DNS { get; }
+
+ public Region(string name, string dNS)
+ {
+ Name = name;
+ DNS = dNS;
+ }
+
+ public override string ToString() => Name;
+ }
+}
diff --git a/KurtzPelRegionPicker/app.manifest b/KurtzPelRegionPicker/app.manifest
new file mode 100644
index 0000000..3011005
--- /dev/null
+++ b/KurtzPelRegionPicker/app.manifest
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+