Commiting launcher 1.0.1.3 modified version as init commit
41
.gitignore
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# Autosave files
|
||||||
|
*~
|
||||||
|
|
||||||
|
# build
|
||||||
|
[Oo]bj/
|
||||||
|
[Bb]in/
|
||||||
|
TestResults/
|
||||||
|
|
||||||
|
# globs
|
||||||
|
Makefile.in
|
||||||
|
*.DS_Store
|
||||||
|
*.sln.cache
|
||||||
|
*.suo
|
||||||
|
*.cache
|
||||||
|
*.pidb
|
||||||
|
*.userprefs
|
||||||
|
*.usertasks
|
||||||
|
config.log
|
||||||
|
config.make
|
||||||
|
config.status
|
||||||
|
aclocal.m4
|
||||||
|
install-sh
|
||||||
|
autom4te.cache/
|
||||||
|
*.user
|
||||||
|
*.tar.gz
|
||||||
|
tarballs/
|
||||||
|
test-results/
|
||||||
|
Thumbs.db
|
||||||
|
.vs/
|
||||||
|
packages/
|
||||||
|
|
||||||
|
# Mac bundle stuff
|
||||||
|
*.dmg
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# resharper
|
||||||
|
*_Resharper.*
|
||||||
|
*.Resharper
|
||||||
|
|
||||||
|
# dotCover
|
||||||
|
*.dotCover
|
6
CleanAndLaunch/App.config
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
|
||||||
|
</startup>
|
||||||
|
</configuration>
|
52
CleanAndLaunch/CleanAndLaunch.csproj
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>CleanAndLaunch</RootNamespace>
|
||||||
|
<AssemblyName>CleanAndLaunch</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
120
CleanAndLaunch/Program.cs
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Timers;
|
||||||
|
|
||||||
|
// The goal of this application is just to clean old files in the system and launch the new launcher... EZ RIGHT ? The app is called after the self updater included in the whole NaturalLauncher.
|
||||||
|
// This is not used anymore. Meh !
|
||||||
|
namespace CleanAndLaunch
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
public static string curDir = Directory.GetCurrentDirectory();
|
||||||
|
public static string ProcessName = "NaturalLauncher.exe";
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
DeleteOldFiles();
|
||||||
|
|
||||||
|
System.Timers.Timer ReLaunchTimer = new System.Timers.Timer();
|
||||||
|
ReLaunchTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
|
||||||
|
ReLaunchTimer.Interval = 100;
|
||||||
|
ReLaunchTimer.Enabled = true;
|
||||||
|
Console.Read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnTimedEvent(object source, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
if (IsProcessOpen(ProcessName)==false)
|
||||||
|
{
|
||||||
|
Launch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Launch()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Launching...");
|
||||||
|
|
||||||
|
Process myprocess = new Process();
|
||||||
|
myprocess.StartInfo.FileName = curDir + Path.DirectorySeparatorChar + ProcessName;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProcessStartInfo processInfo = new ProcessStartInfo();
|
||||||
|
processInfo.WorkingDirectory = curDir;
|
||||||
|
processInfo.FileName = ProcessName;
|
||||||
|
processInfo.ErrorDialog = true;
|
||||||
|
processInfo.UseShellExecute = false;
|
||||||
|
processInfo.RedirectStandardOutput = true;
|
||||||
|
processInfo.RedirectStandardError = true;
|
||||||
|
Process proc = Process.Start(processInfo);
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.ToString());
|
||||||
|
Console.ReadKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsProcessOpen(string name)
|
||||||
|
{
|
||||||
|
foreach (Process clsProcess in Process.GetProcesses())
|
||||||
|
{
|
||||||
|
if (clsProcess.ProcessName.Contains(name))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DeleteOldFiles()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Cleaning old and update files ...");
|
||||||
|
foreach (string file in Directory.GetFiles(curDir))
|
||||||
|
{
|
||||||
|
// Cleaning BAK files
|
||||||
|
if (Path.GetExtension(file) == ".bak")
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
string localPath = ToLocalPath(curDir, file);
|
||||||
|
|
||||||
|
// Cleaning UpdateLogs files
|
||||||
|
if (localPath.StartsWith("/UpdateLog"))
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToLocalPath(string root, string dir)
|
||||||
|
{
|
||||||
|
return dir.Replace(root, "").Replace("\\", "/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
CleanAndLaunch/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// Les informations générales relatives à un assembly dépendent de
|
||||||
|
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
|
||||||
|
// associées à un assembly.
|
||||||
|
[assembly: AssemblyTitle("CleanAndLaunch")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("CleanAndLaunch")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[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)]
|
||||||
|
|
||||||
|
// Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM
|
||||||
|
[assembly: Guid("8e7856fd-fa68-4356-9c88-54c9ef5a9d20")]
|
||||||
|
|
||||||
|
// 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")]
|
25
LICENSE
|
@ -1,16 +1,15 @@
|
||||||
MIT License
|
This programm is an updater to keep your Natural Selection 1 mod folder up with the latest updates.
|
||||||
|
|
||||||
Copyright (c) 2018 ENSL
|
Copyright (C) <2018> <Mael "Khelben" Vignaux>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
This program is free software: you can redistribute it and/or modify
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
it under the terms of the GNU General Public License as published by
|
||||||
in the Software without restriction, including without limitation the rights
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
(at your option) any later version. Commercial use is prohibited.
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
This program is distributed in the hope that it will be useful,
|
||||||
copies or substantial portions of the Software.
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
@ -19,3 +18,9 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
6
ManifestBuilder/App.config
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
|
||||||
|
</startup>
|
||||||
|
</configuration>
|
40
ManifestBuilder/LauncherManifest.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace ManifestBuilder
|
||||||
|
{
|
||||||
|
class LauncherManifest
|
||||||
|
{
|
||||||
|
public LauncherManifest()
|
||||||
|
{
|
||||||
|
Files = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, string> Files
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
58
ManifestBuilder/ManifestBuilder.csproj
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>ManifestBuilder</RootNamespace>
|
||||||
|
<AssemblyName>ManifestBuilder</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="LauncherManifest.cs" />
|
||||||
|
<Compile Include="ManifestBuildor.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
86
ManifestBuilder/ManifestBuildor.cs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace ManifestBuilder
|
||||||
|
{
|
||||||
|
class ManifestBuildor
|
||||||
|
{
|
||||||
|
public static string ManifestName = "Manifest.txt";
|
||||||
|
|
||||||
|
public static void BuildManifest(string directory)
|
||||||
|
{
|
||||||
|
|
||||||
|
LauncherManifest manifest = new LauncherManifest();
|
||||||
|
|
||||||
|
md5 = MD5.Create();
|
||||||
|
|
||||||
|
RecursiveBuildManifest(directory, "", manifest);
|
||||||
|
|
||||||
|
string ManifestPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + ManifestName;
|
||||||
|
File.WriteAllText(ManifestPath, JsonConvert.SerializeObject(manifest, Formatting.Indented));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MD5 md5;
|
||||||
|
|
||||||
|
private static void RecursiveBuildManifest(string projectRoot, string dir, LauncherManifest manifest)
|
||||||
|
{
|
||||||
|
string path = projectRoot + dir;
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(path))
|
||||||
|
{
|
||||||
|
string localPath = ToLocalPath(projectRoot, file);
|
||||||
|
string hash = ComputeMD5(file);
|
||||||
|
|
||||||
|
if(!localPath.EndsWith("_.cfg") && localPath != "/ManifestBuilder.exe" && localPath != "/Manifest.txt"
|
||||||
|
&& localPath != "/Newtonsoft.Json.dll") //we don't want cfg files to get updated here cept config.cfg which is in ignore.list
|
||||||
|
manifest.Files[localPath] = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string nextDir in Directory.GetDirectories(path))
|
||||||
|
{
|
||||||
|
RecursiveBuildManifest(projectRoot, ToLocalPath(projectRoot, nextDir), manifest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ToLocalPath(string root, string dir)
|
||||||
|
{
|
||||||
|
return dir.Replace(root, "").Replace("\\", "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ComputeMD5(string file)
|
||||||
|
{
|
||||||
|
MD5 md5 = MD5.Create();
|
||||||
|
|
||||||
|
string hash = "";
|
||||||
|
using (var stream = File.OpenRead(file))
|
||||||
|
{
|
||||||
|
hash = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
39
ManifestBuilder/Program.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace ManifestBuilder
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
string curDir = Directory.GetCurrentDirectory();
|
||||||
|
Console.WriteLine("Building manifest in : " + curDir);
|
||||||
|
ManifestBuildor.BuildManifest(curDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
ManifestBuilder/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// Les informations générales relatives à un assembly dépendent de
|
||||||
|
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
|
||||||
|
// associées à un assembly.
|
||||||
|
[assembly: AssemblyTitle("ManifestBuilder")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("ManifestBuilder")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[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)]
|
||||||
|
|
||||||
|
// Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM
|
||||||
|
[assembly: Guid("6a7dbe40-6bfb-49f5-bfc1-9f0752ec31be")]
|
||||||
|
|
||||||
|
// 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")]
|
4
ManifestBuilder/packages.config
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net462" />
|
||||||
|
</packages>
|
37
NaturalLauncher.sln
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27703.2042
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NaturalLauncher", "NaturalLauncher\NaturalLauncher.csproj", "{0138DD06-7386-4820-9BCE-3F8412CAD801}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManifestBuilder", "ManifestBuilder\ManifestBuilder.csproj", "{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanAndLaunch", "CleanAndLaunch\CleanAndLaunch.csproj", "{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{0138DD06-7386-4820-9BCE-3F8412CAD801}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0138DD06-7386-4820-9BCE-3F8412CAD801}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0138DD06-7386-4820-9BCE-3F8412CAD801}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0138DD06-7386-4820-9BCE-3F8412CAD801}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {06E5B626-B631-47BF-84D5-A157442007E0}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
44
NaturalLauncher/App.config
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<configSections>
|
||||||
|
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<section name="NaturalLauncher.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||||
|
</sectionGroup>
|
||||||
|
</configSections>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
|
||||||
|
</startup>
|
||||||
|
<userSettings>
|
||||||
|
<NaturalLauncher.Properties.Settings>
|
||||||
|
<setting name="ConfigurationUrl" serializeAs="String">
|
||||||
|
<value>http://ensl.gk-servers.de/</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="IndexURL" serializeAs="String">
|
||||||
|
<value>http://ensl.gk-servers.de/</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="CreditURL" serializeAs="String">
|
||||||
|
<value>http://ensl.gk-servers.de/</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="GameUrl" serializeAs="String">
|
||||||
|
<value>http://ensl.gk-servers.de/ns</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="GatherURL" serializeAs="String">
|
||||||
|
<value>https://www.ensl.org/gathers/latest/ns1</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="NineLegendUrl" serializeAs="String">
|
||||||
|
<value>http://www.elseware-experience.com/vignauxmael/NaturalLauncher/NLPack</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="LauncherUrl" serializeAs="String">
|
||||||
|
<value>http://ensl.gk-servers.de/Launcher/</value>
|
||||||
|
</setting>
|
||||||
|
</NaturalLauncher.Properties.Settings>
|
||||||
|
</userSettings>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
9
NaturalLauncher/App.xaml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<Application x:Class="NaturalLauncher.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:NaturalLauncher"
|
||||||
|
StartupUri="MainWindow.xaml">
|
||||||
|
<Application.Resources>
|
||||||
|
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
12
NaturalLauncher/App.xaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logique d'interaction pour App.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
123
NaturalLauncher/ConsoleManager.cs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security;
|
||||||
|
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
[SuppressUnmanagedCodeSecurity]
|
||||||
|
public static class ConsoleManager
|
||||||
|
{
|
||||||
|
private const string Kernel32_DllName = "kernel32.dll";
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern bool AllocConsole();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern bool FreeConsole();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern IntPtr GetConsoleWindow();
|
||||||
|
|
||||||
|
[DllImport(Kernel32_DllName)]
|
||||||
|
private static extern int GetConsoleOutputCP();
|
||||||
|
|
||||||
|
public static bool HasConsole
|
||||||
|
{
|
||||||
|
get { return GetConsoleWindow() != IntPtr.Zero; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new console instance if the process is not attached to a console already.
|
||||||
|
/// </summary>
|
||||||
|
public static void Show()
|
||||||
|
{
|
||||||
|
//#if DEBUG
|
||||||
|
if (!HasConsole)
|
||||||
|
{
|
||||||
|
AllocConsole();
|
||||||
|
InvalidateOutAndError();
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
|
||||||
|
/// </summary>
|
||||||
|
public static void Hide()
|
||||||
|
{
|
||||||
|
//#if DEBUG
|
||||||
|
if (HasConsole)
|
||||||
|
{
|
||||||
|
SetOutAndErrorNull();
|
||||||
|
FreeConsole();
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Toggle()
|
||||||
|
{
|
||||||
|
if (HasConsole)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InvalidateOutAndError()
|
||||||
|
{
|
||||||
|
Type type = typeof(System.Console);
|
||||||
|
|
||||||
|
System.Reflection.FieldInfo _out = type.GetField("_out",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
System.Reflection.FieldInfo _error = type.GetField("_error",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
Debug.Assert(_out != null);
|
||||||
|
Debug.Assert(_error != null);
|
||||||
|
|
||||||
|
Debug.Assert(_InitializeStdOutError != null);
|
||||||
|
|
||||||
|
_out.SetValue(null, null);
|
||||||
|
_error.SetValue(null, null);
|
||||||
|
|
||||||
|
_InitializeStdOutError.Invoke(null, new object[] { true });
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetOutAndErrorNull()
|
||||||
|
{
|
||||||
|
Console.SetOut(TextWriter.Null);
|
||||||
|
Console.SetError(TextWriter.Null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
275
NaturalLauncher/Launcher.cs
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using System.Windows;
|
||||||
|
using DiscordRPC;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
class Launcher
|
||||||
|
{
|
||||||
|
public static string curDir = Directory.GetCurrentDirectory();
|
||||||
|
public static Uri MainPageURL = new Uri(Properties.Settings.Default.IndexURL);
|
||||||
|
public static Uri CreditPageURL = new Uri(Properties.Settings.Default.CreditURL);
|
||||||
|
|
||||||
|
public static string HLFolder = "";
|
||||||
|
public static string NSFolder;
|
||||||
|
|
||||||
|
public static string VersionFileName = "app.version";
|
||||||
|
public static string ManifestName = "Manifest.txt";
|
||||||
|
public static string NLManifestName = "NLManifest.txt";
|
||||||
|
public static string configName = "Launcher.xml";
|
||||||
|
|
||||||
|
public static bool keepLauncherAlive = true;
|
||||||
|
public static DateTime LAUNCHTIME = System.DateTime.UtcNow;
|
||||||
|
public static string discordCustomStatus = "Currently In The Launcher";
|
||||||
|
|
||||||
|
public static void PlayGame()
|
||||||
|
{
|
||||||
|
LAUNCHTIME = System.DateTime.UtcNow; //new time is launch time
|
||||||
|
UpdateDiscord(true); //doesnt work cause the timer set it back to false. need static var TODO
|
||||||
|
Process.Start("steam://rungameid/17558255459196993606");
|
||||||
|
//Environment.Exit(0); // not stopping the process to let discord rpc live
|
||||||
|
if (!keepLauncherAlive)
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void UpdateDiscord(bool InGame)
|
||||||
|
{
|
||||||
|
int gatherPlayers = Util.ReadGathererCount();
|
||||||
|
UpdatePubServ(out int pubPlayers, out int maxPlayers);
|
||||||
|
|
||||||
|
int displayPlayers = pubPlayers; //by default
|
||||||
|
string discordState = "Players in public";
|
||||||
|
|
||||||
|
if (gatherPlayers > 6)
|
||||||
|
{
|
||||||
|
displayPlayers = gatherPlayers;
|
||||||
|
discordState = "Gather forming";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InGame)
|
||||||
|
{
|
||||||
|
MainWindow.Discordclient.SetPresence(new RichPresence()
|
||||||
|
{
|
||||||
|
Details = discordCustomStatus,
|
||||||
|
State = discordState,
|
||||||
|
/*Secrets = new Secrets()
|
||||||
|
{
|
||||||
|
JoinSecret = "MTI4NzM0OjFpMmhuZToxMjMxMjM",
|
||||||
|
},*/
|
||||||
|
Party = new Party()
|
||||||
|
{
|
||||||
|
ID = "ae488379 - 351d - 4a4f - ad32 - 2b9b01c91657",
|
||||||
|
Size = displayPlayers,
|
||||||
|
Max = 12,
|
||||||
|
},
|
||||||
|
Timestamps = new Timestamps()
|
||||||
|
{
|
||||||
|
Start = LAUNCHTIME,
|
||||||
|
},
|
||||||
|
Assets = new Assets()
|
||||||
|
{
|
||||||
|
LargeImageKey = "portrait_png",
|
||||||
|
LargeImageText = "Natural Selection Enhanced Launcher",
|
||||||
|
SmallImageKey = "skulku_png",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (InGame)
|
||||||
|
{
|
||||||
|
MainWindow.Discordclient.SetPresence(new RichPresence()
|
||||||
|
{
|
||||||
|
Details = "In Game",
|
||||||
|
State = "Next gather",
|
||||||
|
Party = new Party()
|
||||||
|
{
|
||||||
|
ID = "ae488379 - 351d - 4a4f - ad32 - 2b9b01c91657",
|
||||||
|
Size = Util.ReadGathererCount(),
|
||||||
|
Max = 12,
|
||||||
|
},
|
||||||
|
Timestamps = new Timestamps()
|
||||||
|
{
|
||||||
|
Start = LAUNCHTIME,
|
||||||
|
},
|
||||||
|
Assets = new Assets()
|
||||||
|
{
|
||||||
|
LargeImageKey = "portrait_png",
|
||||||
|
LargeImageText = "Natural Selection Enhanced Launcher",
|
||||||
|
SmallImageKey = "skulku_png",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LaunchWebsite(string Url)
|
||||||
|
{
|
||||||
|
Process.Start(Url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RefreshInternetPageAsync(string whichPage)
|
||||||
|
{
|
||||||
|
using (var webClient = new WebClient())
|
||||||
|
{
|
||||||
|
if(whichPage == "Main")
|
||||||
|
{
|
||||||
|
string FileName = "index.html";
|
||||||
|
webClient.DownloadFileAsync(MainPageURL, FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (whichPage == "Credit")
|
||||||
|
{
|
||||||
|
string CreditFileName = "credit.html";
|
||||||
|
webClient.DownloadFileAsync(CreditPageURL, CreditFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CheckInstallDirectory()
|
||||||
|
{
|
||||||
|
bool NeedDirectory = false;
|
||||||
|
|
||||||
|
if (File.Exists(curDir + Path.DirectorySeparatorChar + configName))
|
||||||
|
{
|
||||||
|
string IndicatedFolder = "";
|
||||||
|
bool IsNLPack = false;
|
||||||
|
XmlBuilder.ReadConfigXml(out IndicatedFolder, out IsNLPack, out string discordStatus, out bool keepAlive);
|
||||||
|
|
||||||
|
if (IndicatedFolder.Length >0)
|
||||||
|
{
|
||||||
|
HLFolder = IndicatedFolder;
|
||||||
|
discordCustomStatus = discordStatus;
|
||||||
|
keepLauncherAlive = keepAlive;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NeedDirectory = true;
|
||||||
|
|
||||||
|
if (!Directory.Exists(IndicatedFolder))
|
||||||
|
NeedDirectory = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NeedDirectory = true;
|
||||||
|
|
||||||
|
if (NeedDirectory)
|
||||||
|
{
|
||||||
|
string folderPath = Util.AskForHLFolder();
|
||||||
|
|
||||||
|
if (folderPath!=null)
|
||||||
|
{
|
||||||
|
HLFolder = folderPath;
|
||||||
|
NSFolder = HLFolder + Path.DirectorySeparatorChar + "ns";
|
||||||
|
XmlBuilder.CreateConfigXml();
|
||||||
|
|
||||||
|
if (Directory.Exists(NSFolder))
|
||||||
|
{
|
||||||
|
if(System.Windows.Forms.MessageBox.Show("Warning, you are updating an existing NS installation: "
|
||||||
|
+ Environment.NewLine + "A backup of your old ns folder can be made under the name ns_saved.zip"
|
||||||
|
+ Environment.NewLine + "Please choose if you want to backup your current ns folder.", "", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1)== DialogResult.Yes)
|
||||||
|
{ Util.ZipDirectory(NSFolder); }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(NSFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Environment.Exit(0); //stop the process
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSFolder = HLFolder + Path.DirectorySeparatorChar + "ns";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsNLPack()
|
||||||
|
{
|
||||||
|
bool Result = false; //by default
|
||||||
|
if (File.Exists(curDir + Path.DirectorySeparatorChar + configName))
|
||||||
|
{
|
||||||
|
string IndicatedFolder = "";
|
||||||
|
XmlBuilder.ReadConfigXml(out IndicatedFolder, out Result, out string plop, out bool noob);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Util.PlaySoundFX("error");
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Launcher Config file not found");
|
||||||
|
|
||||||
|
CheckInstallDirectory();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetIsNLPack(bool IsNlPack)
|
||||||
|
{
|
||||||
|
XmlBuilder.CreateConfigXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddToIgnoreList()
|
||||||
|
{
|
||||||
|
Util.GetIgnoreManifest(true); //let's verify we have a ignore list from the start
|
||||||
|
|
||||||
|
string IgnorePath = curDir + Path.DirectorySeparatorChar + "customignore.list";
|
||||||
|
string IgnoreString = File.ReadAllText(IgnorePath);
|
||||||
|
LauncherManifest IgnoreManifest = JsonConvert.DeserializeObject<LauncherManifest>(IgnoreString);// then get it
|
||||||
|
|
||||||
|
var dialog = new System.Windows.Forms.OpenFileDialog();
|
||||||
|
|
||||||
|
dialog.InitialDirectory = NSFolder;
|
||||||
|
dialog.Multiselect = true;
|
||||||
|
|
||||||
|
dialog.Title = "Please indicate what file(s) to add in the ignore list !";
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
||||||
|
{
|
||||||
|
foreach(string file in dialog.FileNames)
|
||||||
|
{
|
||||||
|
string localPath = Util.ToLocalPath(NSFolder, file);
|
||||||
|
IgnoreManifest.Files[localPath] = "1"; //we using the launchermanifest but set "1" to ignore verify and update ("0" is ignore only update)
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(IgnorePath, JsonConvert.SerializeObject(IgnoreManifest, Formatting.Indented));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void UpdatePubServ(out int publicPlayers, out int maxPlayers)
|
||||||
|
{
|
||||||
|
// TO BE CONTINUED but so far we can retrieve pub serv info...
|
||||||
|
string serverIP = "104.156.251.121"; //public us
|
||||||
|
int port = 27015;
|
||||||
|
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(serverIP), port);
|
||||||
|
|
||||||
|
var ServInfo = new ServerChecker.A2S_INFO(remoteEP);
|
||||||
|
|
||||||
|
publicPlayers = ServInfo.Players; //out
|
||||||
|
maxPlayers = ServInfo.MaxPlayers; //out
|
||||||
|
// Check for the launcher to self update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
NaturalLauncher/LauncherManifest.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
class LauncherManifest
|
||||||
|
{
|
||||||
|
public LauncherManifest()
|
||||||
|
{
|
||||||
|
Files = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, string> Files
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
76
NaturalLauncher/MainWindow.xaml
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<Window x:Name="Launcher_Window" x:Class="NaturalLauncher.MainWindow"
|
||||||
|
Closed="MainWindow_Closed"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:NaturalLauncher"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="Natural Launcher v ...." Height="615.5" Width="930" MinWidth="930" MinHeight="550" BorderThickness="0,0,0,0">
|
||||||
|
<Window.TaskbarItemInfo>
|
||||||
|
<TaskbarItemInfo Description="The Natural Launcher"
|
||||||
|
ProgressValue="0" ProgressState="Normal"/>
|
||||||
|
</Window.TaskbarItemInfo>
|
||||||
|
<Window.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<MenuItem Header="Open Natural Selection Folder" Click="OpenNSFolder"/>
|
||||||
|
<MenuItem Header="Check for updaters update" Click="CheckLauncherUpdate"/>
|
||||||
|
<MenuItem Header="Add files to ignore list" Click="AddToIgnore"/>
|
||||||
|
<Separator />
|
||||||
|
<MenuItem Header="Join the official Discord !" Click="JoinDiscord"/>
|
||||||
|
<MenuItem Header="Credits" Click="SeeCredit"/>
|
||||||
|
<Separator />
|
||||||
|
<MenuItem Header="Build Manifest (dev)" Click="BuildManifest"/>
|
||||||
|
</ContextMenu>
|
||||||
|
</Window.ContextMenu>
|
||||||
|
<Window.Icon>
|
||||||
|
<ImageSource>Ressources/nsl_icon.ico</ImageSource>
|
||||||
|
</Window.Icon>
|
||||||
|
<Window.Background>
|
||||||
|
<ImageBrush ImageSource="Ressources/background_blur.png"/>
|
||||||
|
</Window.Background>
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="9*"/>
|
||||||
|
<ColumnDefinition Width="598*"/>
|
||||||
|
<ColumnDefinition Width="268*"/>
|
||||||
|
<ColumnDefinition Width="47*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label x:Name="TitleLabel" Content="Natural Selection Launcher" HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top" FontSize="24" FontFamily="Britannic Bold" FontWeight="Bold" Height="32" Width="336" Foreground="#FFEEC160" RenderTransformOrigin="0.5,0.5" Grid.Column="1">
|
||||||
|
<Label.RenderTransform>
|
||||||
|
<TransformGroup>
|
||||||
|
<ScaleTransform/>
|
||||||
|
<SkewTransform/>
|
||||||
|
<RotateTransform Angle="-0.229"/>
|
||||||
|
<TranslateTransform/>
|
||||||
|
</TransformGroup>
|
||||||
|
</Label.RenderTransform>
|
||||||
|
</Label>
|
||||||
|
<Rectangle Fill="#A50D0D0C" Margin="0,0,10,32" Stroke="Black" Grid.ColumnSpan="3" Height="46" VerticalAlignment="Bottom" Grid.Column="1"/>
|
||||||
|
<Label x:Name="VersionLabel" Content="checking" Margin="341,10,0,0" VerticalAlignment="Top" FontStyle="Italic" Background="#00000000" Foreground="#FF5ACAFF" Height="38" Grid.Column="1" FontWeight="Bold" FontSize="14" HorizontalAlignment="Left" Width="74" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
||||||
|
<WebBrowser x:Name="MainWebBrowser" Margin="0,47,10,83" UseLayoutRounding="False" RenderTransformOrigin="0.498,0.492" Grid.ColumnSpan="3" Grid.Column="1"/>
|
||||||
|
<Button x:Name="StartButton" Content="Start" Margin="0,0,10,32" FontWeight="Bold" FontSize="24" Background="#A5151513" Padding="1,1,1,3" Height="46" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="296" Click="Start_Click" Grid.Column="2" BorderBrush="#FF5A71FF" Foreground="#FF2149D3" BorderThickness="2,1" Grid.ColumnSpan="2"/>
|
||||||
|
<Button x:Name="WebsiteButton" Content="Join Gather" HorizontalAlignment="Left" Margin="0,0,0,32" Width="218" FontSize="18" Background="#A5151513" Padding="1,1,1,3" Height="46" VerticalAlignment="Bottom" Click="Website_Click" BorderBrush="#FFCD6E52" Grid.Column="1" Foreground="#FF2EB2F0" FontWeight="Bold"/>
|
||||||
|
<Button x:Name="SettingButton" Content="Settings" Margin="223,0,0,32" FontSize="18" Background="#A5151513" Padding="1,1,1,3" Height="46" VerticalAlignment="Bottom" Click="Setting_Click" Grid.Column="1" BorderBrush="#FF787539" HorizontalAlignment="Left" Width="180" Foreground="#FF2EB2F0" FontWeight="Bold"/>
|
||||||
|
<ProgressBar x:Name="UpdateProgressBar" Margin="0,0,0,6" Grid.ColumnSpan="2" Height="21" VerticalAlignment="Bottom" Foreground="#FF8CC197" Grid.Column="1">
|
||||||
|
<ProgressBar.Background>
|
||||||
|
<SolidColorBrush Color="#FFD8D8D8" Opacity="0.6"/>
|
||||||
|
</ProgressBar.Background>
|
||||||
|
</ProgressBar>
|
||||||
|
<Label x:Name="ProgressLabel" Content="" Margin="48,0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.ColumnSpan="2" Height="32" VerticalAlignment="Bottom" Foreground="Black" Grid.Column="1" FontWeight="Bold" FontSize="14"/>
|
||||||
|
<Button x:Name="VerifyButton" Content="Verify" Margin="408,0,0,32" FontSize="18" Background="#A5151513" Padding="1,1,1,3" Height="46" VerticalAlignment="Bottom" Click="Verify_Click" Grid.Column="1" BorderBrush="#FF239758" HorizontalAlignment="Left" Width="180" Foreground="#FF2EB2F0" FontWeight="Bold"/>
|
||||||
|
<Button x:Name="PauseButton" Content="" Grid.Column="3" Margin="5,0,10,6" FontWeight="Bold" FontStyle="Italic" FontSize="14" BorderBrush="#FF5993E6" Height="21" VerticalAlignment="Bottom" Click="Pause_Click">
|
||||||
|
<Button.Background>
|
||||||
|
<ImageBrush ImageSource="Ressources/pauseimage.png" Stretch="Uniform"/>
|
||||||
|
</Button.Background>
|
||||||
|
</Button>
|
||||||
|
<Image Grid.Column="2" Margin="9,24,0,0" Source="Ressources/steam_icon.png" Stretch="Fill" Height="18" VerticalAlignment="Top" HorizontalAlignment="Left" Width="25"/>
|
||||||
|
<Label x:Name="ServInfoLabel" Content="Public Server :" Grid.Column="2" HorizontalAlignment="Left" Margin="34,20,0,0" VerticalAlignment="Top" Foreground="White" FontFamily="Segoe WP Black" Width="224">
|
||||||
|
<Label.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<MenuItem Header="Join the server" Click="JoinPublicServer"/>
|
||||||
|
</ContextMenu>
|
||||||
|
</Label.ContextMenu>
|
||||||
|
</Label>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
661
NaturalLauncher/MainWindow.xaml.cs
Normal file
|
@ -0,0 +1,661 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Threading;
|
||||||
|
using DiscordRPC;
|
||||||
|
using System.Timers;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Resources;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logique d'interaction pour MainWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
// TODO We need to know if ns files are being updated to lock the verify/update functions if so (with a file on the main serv).
|
||||||
|
|
||||||
|
public static bool IsDebugMode = false; //no use anymore, but stay here just in case I need him
|
||||||
|
public static bool IsVerification = true; //true by default since it's more commun to verify than to update
|
||||||
|
|
||||||
|
public static Settings sw;
|
||||||
|
|
||||||
|
public static string versionNumber;
|
||||||
|
public static string remoteVersionNumber;
|
||||||
|
|
||||||
|
public static bool downloadCancelled = false;
|
||||||
|
|
||||||
|
public BackgroundWorker backgroundWorker;
|
||||||
|
public static DiscordRpcClient Discordclient;
|
||||||
|
|
||||||
|
Uri LocalIndexURL = new Uri(String.Format("file:///{0}/index.html", Launcher.curDir));
|
||||||
|
|
||||||
|
private static string LogReportPath = Launcher.curDir;
|
||||||
|
TextWriter UpdateLog;
|
||||||
|
|
||||||
|
public void MainWindow_Closed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (sw != null)
|
||||||
|
{
|
||||||
|
sw.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
IsDebugMode = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SelfUpdater.DeleteOldFiles(); // not really needed since CleanAndLaunch.exe
|
||||||
|
|
||||||
|
SelfUpdater TheSelfUpdater = new SelfUpdater();
|
||||||
|
TheSelfUpdater.SetMainWindowRef(this);
|
||||||
|
TheSelfUpdater.UpdateLauncher();
|
||||||
|
|
||||||
|
|
||||||
|
if (SelfUpdater.LaucherRemoteVNumber != SelfUpdater.LaucherLocalVNumber && SelfUpdater.isSelfUpdating)
|
||||||
|
{
|
||||||
|
this.Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set the title of the window with the correct launcher version
|
||||||
|
if (SelfUpdater.isSelfUpdating)
|
||||||
|
Launcher_Window.Title = "Natural Launcher v " + SelfUpdater.LaucherLocalVNumber;
|
||||||
|
else
|
||||||
|
Launcher_Window.Title = "Natural Launcher";
|
||||||
|
|
||||||
|
// CHECK THE HL AND NS INSTALL DIR AND WRITE IT IN THE LAUNCHER XML
|
||||||
|
Launcher.CheckInstallDirectory();
|
||||||
|
|
||||||
|
//Util.ChangeAValueInCfg("net_graph", "2"); //this is not useful but might be someday, that's why I still let it live
|
||||||
|
|
||||||
|
// WE SET DISCORD PRESENCE
|
||||||
|
string ApplicationID = "474144509048127503";
|
||||||
|
Discordclient = new DiscordRpcClient(ApplicationID);
|
||||||
|
|
||||||
|
Discordclient.Initialize();
|
||||||
|
|
||||||
|
OnlineStatusAtLaunch();
|
||||||
|
|
||||||
|
System.Timers.Timer PresenceTimer = new System.Timers.Timer();
|
||||||
|
PresenceTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
|
||||||
|
PresenceTimer.Enabled = true;
|
||||||
|
PresenceTimer.Interval = 5000;
|
||||||
|
|
||||||
|
// *** Get the main index.html if connected *** \\
|
||||||
|
if (Util.CheckForInternetConnection(Launcher.MainPageURL.AbsoluteUri)) //if we are connected
|
||||||
|
{
|
||||||
|
Launcher.RefreshInternetPageAsync("Main"); // we refresh the page
|
||||||
|
MainWebBrowser.Source = Launcher.MainPageURL; // and display it from source
|
||||||
|
}
|
||||||
|
else // if not simply show the saved file
|
||||||
|
{
|
||||||
|
MainWebBrowser.Navigate(LocalIndexURL.AbsolutePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK APP.VERSION NUMBER
|
||||||
|
Check_Version();
|
||||||
|
|
||||||
|
if (versionNumber != remoteVersionNumber && versionNumber != "0.0.0.0")
|
||||||
|
{
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Update Needed !", "Update", MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
||||||
|
StartButton.Content = "Please Update";
|
||||||
|
IsVerification = false;
|
||||||
|
}
|
||||||
|
if (versionNumber == "0.0.0.0")
|
||||||
|
{
|
||||||
|
StartButton.Content = "Verify";
|
||||||
|
IsVerification = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (versionNumber == remoteVersionNumber && versionNumber != "0.0.0.0")
|
||||||
|
{
|
||||||
|
StartButton.Content = "Play"; // TODO The algorithm to verify btween local and remote manifest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void ReadyLauncherForUpdate(string FirstLogLine)
|
||||||
|
{
|
||||||
|
StartButton.IsEnabled = false;
|
||||||
|
VerifyButton.IsEnabled = false;
|
||||||
|
SettingButton.IsEnabled = false;
|
||||||
|
UpdateLog = new StreamWriter(LogReportPath + Path.DirectorySeparatorChar + "UpdateLog_" + Util.GetLongTimeString() + ".txt", true); // dt forget to close()
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + FirstLogLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTimedEvent(object source, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
Launcher.UpdateDiscord(false);
|
||||||
|
|
||||||
|
Delegate myDelegate = (Action)Update_gatherButton;
|
||||||
|
Delegate secondDelegate = (Action)Update_ServLabel;
|
||||||
|
WebsiteButton.Dispatcher.Invoke(myDelegate);
|
||||||
|
ServInfoLabel.Dispatcher.Invoke(secondDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnlineStatusAtLaunch()
|
||||||
|
{
|
||||||
|
Launcher.UpdateDiscord(false);
|
||||||
|
|
||||||
|
Delegate myDelegate = (Action)Update_gatherButton;
|
||||||
|
Delegate secondDelegate = (Action)Update_ServLabel;
|
||||||
|
WebsiteButton.Dispatcher.Invoke(myDelegate);
|
||||||
|
ServInfoLabel.Dispatcher.Invoke(secondDelegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update_gatherButton()
|
||||||
|
{
|
||||||
|
if(Util.ReadGathererCount()>0)
|
||||||
|
WebsiteButton.Content = "Join Gather ( " + Util.ReadGathererCount() + " / 12 )";
|
||||||
|
else
|
||||||
|
WebsiteButton.Content = "Join Gather";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update_ServLabel()
|
||||||
|
{
|
||||||
|
Launcher.UpdatePubServ(out int pubPlayers, out int maxPlayers);
|
||||||
|
ServInfoLabel.Content = "Public Server : " + pubPlayers + " / " + maxPlayers;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Check_Version()
|
||||||
|
{
|
||||||
|
// *** Get the version number *** \\
|
||||||
|
versionNumber = Util.LocalVersion(Launcher.curDir + Path.DirectorySeparatorChar + Launcher.VersionFileName);
|
||||||
|
remoteVersionNumber = Util.RemoteVersion(Properties.Settings.Default.IndexURL + Launcher.VersionFileName);
|
||||||
|
|
||||||
|
if (versionNumber != null)
|
||||||
|
{
|
||||||
|
VersionLabel.Content = versionNumber;
|
||||||
|
}
|
||||||
|
else //if it doesn exist, we need to inform the user
|
||||||
|
{
|
||||||
|
versionNumber = "0.0.0.0";
|
||||||
|
VersionLabel.Content = "Verify";
|
||||||
|
StartButton.Content = "Verify";
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Please verify the installation" + Environment.NewLine
|
||||||
|
+ "This message will show up if this is the first time you launch this software"
|
||||||
|
, "Alert", MessageBoxButton.OK, MessageBoxImage.Exclamation); //not true anymore
|
||||||
|
SettingButton.IsEnabled = false;
|
||||||
|
IsVerification = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region clicks
|
||||||
|
private void Start_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (SelfUpdater.CheckOneFileSignature("NaturalLauncher.exe") || !SelfUpdater.isSelfUpdating)
|
||||||
|
{
|
||||||
|
if (versionNumber != remoteVersionNumber || versionNumber == "0.0.0.0")
|
||||||
|
{
|
||||||
|
ReadyLauncherForUpdate("Start Update from play button");
|
||||||
|
StartButton.Content = "Verifying...";
|
||||||
|
IsVerification = false;
|
||||||
|
UpdateGame(); //verify the game with the right click context menu
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Launcher.PlayGame();
|
||||||
|
Util.PlaySoundFX("finish");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Util.PlaySoundFX("error");
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Your launcher is corrupted or out of date, please relaunch" + Environment.NewLine
|
||||||
|
+ "if the problem persist, please redownload the launcher from an official source (ensl.org)");
|
||||||
|
File.Delete(Launcher.curDir + Path.DirectorySeparatorChar + "launcher.version");
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Website_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Launcher.LaunchWebsite(Properties.Settings.Default.GatherURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Setting_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sw == null)
|
||||||
|
{
|
||||||
|
sw = new Settings();
|
||||||
|
}
|
||||||
|
sw.SetMainWindowRef(this);
|
||||||
|
sw.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Verify_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ReadyLauncherForUpdate("Verification started from launcher");
|
||||||
|
|
||||||
|
if (versionNumber != remoteVersionNumber || versionNumber == "0.0.0.0")
|
||||||
|
{
|
||||||
|
IsVerification = false;
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "but it's an update");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IsVerification = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateGame(); //verify the game with the right click context menu
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Pause_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var brush = new ImageBrush();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!downloadCancelled)
|
||||||
|
{
|
||||||
|
downloadCancelled = true;
|
||||||
|
backgroundWorker.CancelAsync();
|
||||||
|
|
||||||
|
Uri resourceUri = new Uri("Ressources/playimage.png", UriKind.Relative); //"pack://application:,,,/NaturalLauncher;component/Images/Resource_Image.png"
|
||||||
|
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
|
||||||
|
|
||||||
|
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
|
||||||
|
brush.ImageSource = temp;
|
||||||
|
|
||||||
|
PauseButton.Background = brush;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReadyLauncherForUpdate("Verification resumed from launcher");
|
||||||
|
UpdateGame(); //verify the game with the right click context menu
|
||||||
|
|
||||||
|
Uri resourceUri = new Uri("Ressources/pauseimage.png", UriKind.Relative);
|
||||||
|
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
|
||||||
|
|
||||||
|
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
|
||||||
|
brush.ImageSource = temp;
|
||||||
|
|
||||||
|
PauseButton.Background = brush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
downloadCancelled = false;
|
||||||
|
Uri resourceUri = new Uri("Ressources/pauseimage.png", UriKind.Relative);
|
||||||
|
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
|
||||||
|
|
||||||
|
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
|
||||||
|
brush.ImageSource = temp;
|
||||||
|
|
||||||
|
PauseButton.Background = brush;
|
||||||
|
} //I don't give a f if it doesnt catch shit
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ContextMenu
|
||||||
|
private void BuildManifest(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ManifestBuilder.BuildManifest(Launcher.NSFolder); // build the manifest of the file to update
|
||||||
|
}
|
||||||
|
private void VerifyTheGame(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
/*UpdateLog = new StreamWriter(LogReportPath + Path.DirectorySeparatorChar + "UpdateLog_" + Util.GetLongTimeString() + ".txt", true); // dt forget to close()
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Verification started from context menu");
|
||||||
|
UpdateGame(); //verify the game with the right click context menu*/ //not used anymore
|
||||||
|
}
|
||||||
|
private void CheckLauncherUpdate(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
SelfUpdater TheSelfUpdater = new SelfUpdater();
|
||||||
|
TheSelfUpdater.allowMessage = true;
|
||||||
|
TheSelfUpdater.UpdateLauncher();
|
||||||
|
}
|
||||||
|
private void JoinDiscord(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Process.Start("https://discord.gg/ZUSSBUA");
|
||||||
|
}
|
||||||
|
private void SeeCredit(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Process.Start("https://discord.gg/ZUSSBUA");
|
||||||
|
}
|
||||||
|
private void JoinPublicServer(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Process.Start("steam://connect/104.156.251.121:27015");
|
||||||
|
}
|
||||||
|
private void AddToIgnore(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Launcher.AddToIgnoreList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenNSFolder(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Process.Start(Launcher.NSFolder);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UpdateMaelAlgo
|
||||||
|
|
||||||
|
public void UpdateGame()
|
||||||
|
{
|
||||||
|
Util.PlaySoundFX("start");
|
||||||
|
TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal;
|
||||||
|
downloadCancelled = false;
|
||||||
|
backgroundWorker = new System.ComponentModel.BackgroundWorker();
|
||||||
|
backgroundWorker.WorkerReportsProgress = true;
|
||||||
|
backgroundWorker.WorkerSupportsCancellation = true;
|
||||||
|
backgroundWorker.DoWork += UpdateGame_Worker;
|
||||||
|
backgroundWorker.ProgressChanged += UpdateGame_ProgressChanged;
|
||||||
|
backgroundWorker.RunWorkerCompleted += UpdateGame_RunWorkerCompleted;
|
||||||
|
backgroundWorker.RunWorkerAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void CallUpdateGame() //same as updategame for now
|
||||||
|
{
|
||||||
|
ReadyLauncherForUpdate("update Called from a setting's change");
|
||||||
|
UpdateGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void UpdateGame_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Cancelled)
|
||||||
|
{
|
||||||
|
StartButton.Content = "Error";
|
||||||
|
UpdateProgressBar.Value = 0;
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Error while downloading, please try again");
|
||||||
|
ProgressLabel.Content = "Error while downloading, please try again";
|
||||||
|
TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloadCancelled)
|
||||||
|
{
|
||||||
|
ProgressLabel.Content = "Paused !";
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Stop requested by the user...");
|
||||||
|
TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Paused; //yellow thing
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProgressLabel.Content = "Up to date !";
|
||||||
|
StartButton.Content = "Play";
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Completed the update or verify work");
|
||||||
|
TaskbarItemInfo.ProgressValue = 0;
|
||||||
|
TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal;
|
||||||
|
Util.CreateLocalVersionFile(Launcher.curDir, Launcher.VersionFileName, remoteVersionNumber); //update the version with the new one
|
||||||
|
|
||||||
|
Check_Version(); // we should have a changed app.version file to check
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateLog.Close();
|
||||||
|
backgroundWorker.Dispose();
|
||||||
|
|
||||||
|
Util.PlaySoundFX("finish");
|
||||||
|
|
||||||
|
StartButton.IsEnabled = true;
|
||||||
|
SettingButton.IsEnabled = true;
|
||||||
|
VerifyButton.IsEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGame_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
||||||
|
{
|
||||||
|
ProgressLabel.Content = e.UserState as string;
|
||||||
|
UpdateProgressBar.Value = e.ProgressPercentage;
|
||||||
|
TaskbarItemInfo.ProgressValue = (double)((float)e.ProgressPercentage / 100f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGame_Worker(object sender, DoWorkEventArgs e)
|
||||||
|
{
|
||||||
|
backgroundWorker.ReportProgress(0, "Downloading Manifest...");
|
||||||
|
|
||||||
|
string ManifestURL = Launcher.MainPageURL.AbsoluteUri + Launcher.ManifestName;
|
||||||
|
|
||||||
|
WebClient webClient = new WebClient();
|
||||||
|
webClient.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
|
||||||
|
webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;
|
||||||
|
webClient.DownloadFileCompleted += webClient_DownloadFileCompleted;
|
||||||
|
|
||||||
|
string manifest = webClient.DownloadString(ManifestURL);
|
||||||
|
LauncherManifest RemoteManifest = JsonConvert.DeserializeObject<LauncherManifest>(manifest);
|
||||||
|
|
||||||
|
if (Launcher.IsNLPack())
|
||||||
|
{
|
||||||
|
string NLManifestURL = Launcher.MainPageURL.AbsoluteUri + Launcher.NLManifestName;
|
||||||
|
string NLmanifest = webClient.DownloadString(NLManifestURL);
|
||||||
|
LauncherManifest NLManifest = JsonConvert.DeserializeObject<LauncherManifest>(NLmanifest);
|
||||||
|
|
||||||
|
RemoteManifest = Util.CleanManifestWithOptions(RemoteManifest, NLManifest); //cleaning the manifest hash consequently
|
||||||
|
}
|
||||||
|
|
||||||
|
LauncherManifest IgnoreManifest = Util.GetIgnoreManifest(IsVerification); //attention, might not exist, if so it has to be downloaded, if not let's use it !
|
||||||
|
|
||||||
|
string gameInstallDir = Launcher.NSFolder;
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Install Directory located in : " + gameInstallDir);
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "NL Pack installed : " + Launcher.IsNLPack().ToString());
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Distant Manifest located at : " + ManifestURL);
|
||||||
|
|
||||||
|
var md5 = MD5.Create();
|
||||||
|
int totalFiles = RemoteManifest.Files.Count;
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Total file to update : " + totalFiles);
|
||||||
|
|
||||||
|
int curFile = 0;
|
||||||
|
|
||||||
|
// Update the standard files
|
||||||
|
foreach (KeyValuePair<string, string> kv in RemoteManifest.Files)
|
||||||
|
{
|
||||||
|
bool ShouldDownload = false;
|
||||||
|
string gameFilePath = gameInstallDir + kv.Key.Replace("/", Path.DirectorySeparatorChar.ToString());
|
||||||
|
IgnoreManifest.Files.TryGetValue(kv.Key, out string IgnoreValue); //get the ignore file value in manifest ("0" ignore only verif, "1" ignore verif + update)
|
||||||
|
|
||||||
|
bool Condition1 = File.Exists(gameFilePath) && IgnoreManifest.Files.ContainsKey(kv.Key) == false;//if the file exists and not in the ignore manifest, let's have it !
|
||||||
|
bool Condition2 = File.Exists(gameFilePath) && IgnoreManifest.Files.ContainsKey(kv.Key) && IgnoreValue == "0" && !IsVerification; //if the file exists, is in the ignore manifest, but is updatable and... it's update time !
|
||||||
|
|
||||||
|
if (Condition1 || Condition2)
|
||||||
|
{
|
||||||
|
int progress = (int)(((float)curFile / (float)totalFiles) * 100);
|
||||||
|
backgroundWorker.ReportProgress(progress, "(" + (curFile) + " / " + totalFiles + ") Checking " + kv.Key);
|
||||||
|
|
||||||
|
//Check its md5 hash
|
||||||
|
using (var stream = File.OpenRead(gameFilePath))
|
||||||
|
{
|
||||||
|
var hash = Util.ComputeMD5(gameFilePath);
|
||||||
|
|
||||||
|
if (hash != kv.Value)
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + gameFilePath + " needs to be updated");
|
||||||
|
ShouldDownload = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!File.Exists(gameFilePath))
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + gameFilePath + " not existing, needs downloading");
|
||||||
|
ShouldDownload = true;
|
||||||
|
}
|
||||||
|
if (File.Exists(gameFilePath) && IgnoreManifest.Files.ContainsKey(kv.Key) && IgnoreValue == "1") // ignore everything
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + gameFilePath + " Is Ignored for update, not checking");
|
||||||
|
ShouldDownload = false;
|
||||||
|
}
|
||||||
|
if (File.Exists(gameFilePath) && IgnoreManifest.Files.ContainsKey(kv.Key) && IsVerification && IgnoreValue == "0") //if we need to ignore update and it's verification, we ignore !
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + gameFilePath + " Is Ignored for verifications, not checking");
|
||||||
|
ShouldDownload = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ShouldDownload)
|
||||||
|
{
|
||||||
|
DownloadFile(curFile, totalFiles, kv, RemoteManifest, gameFilePath, Properties.Settings.Default.GameUrl, webClient);
|
||||||
|
|
||||||
|
var hash = Util.ComputeMD5(gameFilePath);
|
||||||
|
|
||||||
|
if (hash != kv.Value)
|
||||||
|
{
|
||||||
|
//MessageBox.Show("Failed Validating " + kv.Key + " : Redownloading"); //problem with double validation, is it too soon in the chain of event ?
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "failed to verify newly downloaded file, redownloading");
|
||||||
|
DownloadFile(curFile, totalFiles, kv, RemoteManifest, gameFilePath, Properties.Settings.Default.GameUrl, webClient);
|
||||||
|
}
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Download complete for file: " + kv.Key + " with new hash :" + hash + " for manifest hash : " + kv.Value);
|
||||||
|
}
|
||||||
|
if (backgroundWorker.CancellationPending)
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Update cancelled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
curFile++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the NineLegend pack files if requiered
|
||||||
|
/*if (Launcher.IsNLPack())
|
||||||
|
{
|
||||||
|
string NLManifestURL = Launcher.MainPageURL.AbsoluteUri + Launcher.NLManifestName;
|
||||||
|
string NLmanifest = webClient.DownloadString(NLManifestURL);
|
||||||
|
LauncherManifest NLManifest = JsonConvert.DeserializeObject<LauncherManifest>(NLmanifest);
|
||||||
|
curFile = curFile - NLManifest.Files.Count;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, string> kv in NLManifest.Files)
|
||||||
|
{
|
||||||
|
bool ShouldDownload = false;
|
||||||
|
string gameFilePath = gameInstallDir + kv.Key.Replace("/", Path.DirectorySeparatorChar.ToString());
|
||||||
|
if (File.Exists(gameFilePath))
|
||||||
|
{
|
||||||
|
int progress = (int)(((float)curFile / (float)totalFiles) * 100);
|
||||||
|
backgroundWorker.ReportProgress(progress, "(" + (curFile) + " / " + totalFiles + ") Checking " + kv.Key);
|
||||||
|
//Check its md5 hash
|
||||||
|
using (var stream = File.OpenRead(gameFilePath))
|
||||||
|
{
|
||||||
|
var hash = Util.ComputeMD5(gameFilePath);
|
||||||
|
|
||||||
|
if (hash != kv.Value)
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + gameFilePath + " needs to be updated");
|
||||||
|
ShouldDownload = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + gameFilePath + " not existing, needs downloading");
|
||||||
|
ShouldDownload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShouldDownload)
|
||||||
|
{
|
||||||
|
DownloadFile(curFile, totalFiles, kv, NLManifest, gameFilePath, Properties.Settings.Default.NineLegendUrl, webClient);
|
||||||
|
|
||||||
|
var hash = Util.ComputeMD5(gameFilePath);
|
||||||
|
|
||||||
|
if (hash != kv.Value)
|
||||||
|
{
|
||||||
|
//MessageBox.Show("Failed Validating " + kv.Key + " : Redownloading"); //problem with double validation, is it too soon in the chain of event ?
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "failed to verify newly downloaded file, redownloading");
|
||||||
|
DownloadFile(curFile, totalFiles, kv, NLManifest, gameFilePath, Properties.Settings.Default.NineLegendUrl, webClient);
|
||||||
|
}
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Download complete for NineLegend file: " + kv.Key + " with new hash :" + hash + " for manifest hash : " + kv.Value);
|
||||||
|
}
|
||||||
|
if (backgroundWorker.CancellationPending)
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Update cancelled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
curFile++;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
backgroundWorker.ReportProgress(100, "Writing Local Manifest");
|
||||||
|
|
||||||
|
/* string manifestDirectory = Launcher.curDir + Path.DirectorySeparatorChar + Launcher.ManifestName;
|
||||||
|
|
||||||
|
File.WriteAllText(manifestDirectory, manifest); // replace all with function in util */
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DownloadFile(int curFile, int totalFiles, KeyValuePair<string, string> kv, LauncherManifest RemoteManifest, string gameFilePath, string folderURL, WebClient webClient)
|
||||||
|
{
|
||||||
|
int progress = (int)(((float)curFile / (float)totalFiles) * 100);
|
||||||
|
|
||||||
|
string status = "(" + (curFile) + " / " + totalFiles + ") Downloading: " + kv.Key;
|
||||||
|
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Downloading file: " + kv.Key);
|
||||||
|
|
||||||
|
backgroundWorker.ReportProgress(progress, status);
|
||||||
|
|
||||||
|
string remoteFile = (folderURL + "/" + kv.Key.Substring(1));
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(gameFilePath));
|
||||||
|
if (File.Exists(gameFilePath))
|
||||||
|
{
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "File exist, deleting old file");
|
||||||
|
File.Delete(gameFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
webClient.DownloadFileAsync(new Uri(remoteFile), gameFilePath, status);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("new file not found");
|
||||||
|
UpdateLog.WriteLine(Util.GetShortTimeString() + "Failed Downloading file: " + kv.Key + "with message : " + e.Message);
|
||||||
|
backgroundWorker.CancelAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (webClient.IsBusy)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
|
||||||
|
{
|
||||||
|
string status = e.UserState as string + " ( " + Util.Size(e.BytesReceived) + " / " + Util.Size(e.TotalBytesToReceive) + " )";
|
||||||
|
backgroundWorker.ReportProgress(e.ProgressPercentage, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Error != null)
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show(e.Error.ToString());
|
||||||
|
backgroundWorker.CancelAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
74
NaturalLauncher/ManifestBuilder.cs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
class ManifestBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
private static MD5 md5;
|
||||||
|
|
||||||
|
public static void BuildManifest(string directory)
|
||||||
|
{
|
||||||
|
LauncherManifest manifest = new LauncherManifest();
|
||||||
|
|
||||||
|
md5 = MD5.Create();
|
||||||
|
|
||||||
|
RecursiveBuildManifest(directory, "", manifest);
|
||||||
|
|
||||||
|
/*SaveFileDialog dialog = new SaveFileDialog(); // commented but needed when you want to save a manifest somewhere else (could be usefull for a manifest builder console app
|
||||||
|
dialog.InitialDirectory = Environment.CurrentDirectory;
|
||||||
|
dialog.FileName = "Manifest.txt";
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
File.WriteAllText(dialog.FileName, JsonConvert.SerializeObject(manifest, Formatting.Indented));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
string ManifestPath = Launcher.curDir + Path.DirectorySeparatorChar + Launcher.ManifestName;
|
||||||
|
File.WriteAllText(ManifestPath, JsonConvert.SerializeObject(manifest, Formatting.Indented));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RecursiveBuildManifest(string projectRoot, string dir, LauncherManifest manifest)
|
||||||
|
{
|
||||||
|
string path = projectRoot + dir;
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(path))
|
||||||
|
{
|
||||||
|
string localPath = Util.ToLocalPath(projectRoot, file);
|
||||||
|
string hash = Util.ComputeMD5(file);
|
||||||
|
|
||||||
|
if (!localPath.EndsWith("_.cfg") && localPath != "/Manifest.txt" && localPath != "/ManifestBuilder.exe"
|
||||||
|
&& localPath != "/Newtonsoft.Json.dll") //we don't want cfg files to get updated here cept config.cfg which is in ignore.list
|
||||||
|
manifest.Files[localPath] = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string nextDir in Directory.GetDirectories(path))
|
||||||
|
{
|
||||||
|
RecursiveBuildManifest(projectRoot, Util.ToLocalPath(projectRoot, nextDir), manifest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
211
NaturalLauncher/NaturalLauncher.csproj
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{0138DD06-7386-4820-9BCE-3F8412CAD801}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<RootNamespace>NaturalLauncher</RootNamespace>
|
||||||
|
<AssemblyName>NaturalLauncher</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>true</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>true</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<TargetCulture>en</TargetCulture>
|
||||||
|
<ProductName>Natural Launcher</ProductName>
|
||||||
|
<PublisherName>Mael Vignaux</PublisherName>
|
||||||
|
<MinimumRequiredVersion>1.0.0.0</MinimumRequiredVersion>
|
||||||
|
<OpenBrowserOnPublish>false</OpenBrowserOnPublish>
|
||||||
|
<AutorunEnabled>true</AutorunEnabled>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationIcon>Ressources\nsl_icon.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ManifestCertificateThumbprint>D8B30162E74CFDDB757978150D09F39672490FAC</ManifestCertificateThumbprint>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ManifestKeyFile>NaturalLauncher_TemporaryKey.pfx</ManifestKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<GenerateManifests>true</GenerateManifests>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SignManifests>true</SignManifests>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="DiscordRPC, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\DiscordRPC.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="HtmlAgilityPack, Version=1.8.5.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\HtmlAgilityPack.1.8.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.IO.Compression" />
|
||||||
|
<Reference Include="System.IO.Compression.FileSystem" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xaml">
|
||||||
|
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ApplicationDefinition Include="App.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</ApplicationDefinition>
|
||||||
|
<Compile Include="ConsoleManager.cs" />
|
||||||
|
<Compile Include="LauncherManifest.cs" />
|
||||||
|
<Compile Include="ManifestBuilder.cs" />
|
||||||
|
<Compile Include="ProjectSettings.cs" />
|
||||||
|
<Compile Include="SelfUpdater.cs" />
|
||||||
|
<Compile Include="ServerChecker.cs" />
|
||||||
|
<Compile Include="Settings.xaml.cs">
|
||||||
|
<DependentUpon>Settings.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Util.cs" />
|
||||||
|
<Compile Include="XmlBuilder.cs" />
|
||||||
|
<Page Include="MainWindow.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
<Compile Include="App.xaml.cs">
|
||||||
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Launcher.cs" />
|
||||||
|
<Compile Include="MainWindow.xaml.cs">
|
||||||
|
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Page Include="Settings.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
</Compile>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<None Include="NaturalLauncher_TemporaryKey.pfx" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
<Resource Include="Ressources\Commande.lex" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Ressources\background.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Ressources\small_discordicon.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Ressources\nsl_icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="nsl_icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Ressources\background_blur.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include=".NETFramework,Version=v4.6.2">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Microsoft .NET Framework 4.6.2 %28x86 et x64%29</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Ressources\pauseimage.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Ressources\playimage.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Ressources\sdx_error.wav" />
|
||||||
|
<Resource Include="Ressources\sdx_finished.wav" />
|
||||||
|
<Resource Include="Ressources\sdx_started.wav" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Ressources\steam_icon.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
37
NaturalLauncher/NaturalLauncher.sln
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27703.2042
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NaturalLauncher", "NaturalLauncher\NaturalLauncher.csproj", "{0138DD06-7386-4820-9BCE-3F8412CAD801}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManifestBuilder", "ManifestBuilder\ManifestBuilder.csproj", "{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanAndLaunch", "CleanAndLaunch\CleanAndLaunch.csproj", "{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{0138DD06-7386-4820-9BCE-3F8412CAD801}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0138DD06-7386-4820-9BCE-3F8412CAD801}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0138DD06-7386-4820-9BCE-3F8412CAD801}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0138DD06-7386-4820-9BCE-3F8412CAD801}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6A7DBE40-6BFB-49F5-BFC1-9F0752EC31BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8E7856FD-FA68-4356-9C88-54C9EF5A9D20}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {06E5B626-B631-47BF-84D5-A157442007E0}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
30
NaturalLauncher/ProjectSettings.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace ArtefactsLauncher
|
||||||
|
{
|
||||||
|
public class ProjectSettings
|
||||||
|
{
|
||||||
|
// Attention, it is very important to keep the exact same names as in the json
|
||||||
|
public float ScreenPercentage;
|
||||||
|
public float BeeFactor;
|
||||||
|
}
|
||||||
|
}
|
53
NaturalLauncher/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
// Les informations générales relatives à un assembly dépendent de
|
||||||
|
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
|
||||||
|
// associées à un assembly.
|
||||||
|
[assembly: AssemblyTitle("NaturalLauncher")]
|
||||||
|
[assembly: AssemblyDescription("The launcher and updater for natural selection 1")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Mael Vignaux")]
|
||||||
|
[assembly: AssemblyProduct("NaturalLauncher")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[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
|
||||||
|
//<UICulture>CultureUtiliséePourCoder</UICulture> dans votre fichier .csproj
|
||||||
|
//dans <PropertyGroup>. Par exemple, si vous utilisez le français
|
||||||
|
//dans vos fichiers sources, définissez <UICulture> à 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")]
|
63
NaturalLauncher/Properties/Resources.Designer.cs
generated
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// 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é.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace NaturalLauncher.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
|
||||||
|
/// </summary>
|
||||||
|
// 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", "15.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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
|
||||||
|
/// </summary>
|
||||||
|
[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("NaturalLauncher.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remplace la propriété CurrentUICulture du thread actuel pour toutes
|
||||||
|
/// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
NaturalLauncher/Properties/Resources.resx
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
110
NaturalLauncher/Properties/Settings.Designer.cs
generated
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// 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é.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace NaturalLauncher.Properties {
|
||||||
|
|
||||||
|
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("http://ensl.gk-servers.de/")]
|
||||||
|
public string ConfigurationUrl {
|
||||||
|
get {
|
||||||
|
return ((string)(this["ConfigurationUrl"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["ConfigurationUrl"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("http://ensl.gk-servers.de/")]
|
||||||
|
public string IndexURL {
|
||||||
|
get {
|
||||||
|
return ((string)(this["IndexURL"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["IndexURL"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("http://ensl.gk-servers.de/")]
|
||||||
|
public string CreditURL {
|
||||||
|
get {
|
||||||
|
return ((string)(this["CreditURL"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["CreditURL"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("http://ensl.gk-servers.de/ns")]
|
||||||
|
public string GameUrl {
|
||||||
|
get {
|
||||||
|
return ((string)(this["GameUrl"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["GameUrl"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("https://www.ensl.org/gathers/latest/ns1")]
|
||||||
|
public string GatherURL {
|
||||||
|
get {
|
||||||
|
return ((string)(this["GatherURL"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["GatherURL"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("http://www.elseware-experience.com/vignauxmael/NaturalLauncher/NLPack")]
|
||||||
|
public string NineLegendUrl {
|
||||||
|
get {
|
||||||
|
return ((string)(this["NineLegendUrl"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["NineLegendUrl"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("http://ensl.gk-servers.de/Launcher/")]
|
||||||
|
public string LauncherUrl {
|
||||||
|
get {
|
||||||
|
return ((string)(this["LauncherUrl"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["LauncherUrl"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
NaturalLauncher/Properties/Settings.settings
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="NaturalLauncher.Properties" GeneratedClassName="Settings">
|
||||||
|
<Profiles />
|
||||||
|
<Settings>
|
||||||
|
<Setting Name="ConfigurationUrl" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">http://ensl.gk-servers.de/</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="IndexURL" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">http://ensl.gk-servers.de/</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="CreditURL" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">http://ensl.gk-servers.de/</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="GameUrl" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">http://ensl.gk-servers.de/ns</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="GatherURL" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">https://www.ensl.org/gathers/latest/ns1</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="NineLegendUrl" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">http://www.elseware-experience.com/vignauxmael/NaturalLauncher/NLPack</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="LauncherUrl" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">http://ensl.gk-servers.de/Launcher/</Value>
|
||||||
|
</Setting>
|
||||||
|
</Settings>
|
||||||
|
</SettingsFile>
|
144
NaturalLauncher/Ressources/Commande.lex
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
parameter
|
||||||
|
value
|
||||||
|
_snd_mixahead
|
||||||
|
ati_npatch
|
||||||
|
bgmvolume
|
||||||
|
bottomcolor
|
||||||
|
brightness
|
||||||
|
cl_allowdownload
|
||||||
|
cl_allowupload
|
||||||
|
cl_autohelp
|
||||||
|
cl_backspeed
|
||||||
|
cl_buildmessages
|
||||||
|
cl_centerentityid
|
||||||
|
cl_cmdbackup
|
||||||
|
cl_cmdrate
|
||||||
|
cl_cmhotkeys
|
||||||
|
cl_cross
|
||||||
|
cl_cross_alpha
|
||||||
|
cl_cross_bottom_line
|
||||||
|
cl_cross_color
|
||||||
|
cl_cross_dot_color
|
||||||
|
cl_cross_dot_outline
|
||||||
|
cl_cross_dot_size
|
||||||
|
cl_cross_gap
|
||||||
|
cl_cross_left_line
|
||||||
|
cl_cross_outline
|
||||||
|
cl_cross_outline_inner
|
||||||
|
cl_cross_right_line
|
||||||
|
cl_cross_size
|
||||||
|
cl_cross_thickness
|
||||||
|
cl_cross_top_line
|
||||||
|
cl_customcrosshair
|
||||||
|
cl_dlmax
|
||||||
|
cl_download_ingame
|
||||||
|
cl_dynamiclights
|
||||||
|
cl_forcedefaultfov
|
||||||
|
cl_forwardspeed
|
||||||
|
cl_gammaramp
|
||||||
|
cl_highdetail
|
||||||
|
cl_himodels
|
||||||
|
cl_hudmapzoom
|
||||||
|
cl_iconb
|
||||||
|
cl_icong
|
||||||
|
cl_iconr
|
||||||
|
cl_idealpitchscale
|
||||||
|
cl_labelhivesight
|
||||||
|
cl_labelmaps
|
||||||
|
cl_lc
|
||||||
|
cl_logocolor
|
||||||
|
cl_logofile
|
||||||
|
cl_lw
|
||||||
|
cl_mousegrab
|
||||||
|
cl_musicdelay
|
||||||
|
cl_musicdirectory
|
||||||
|
cl_musicenabled
|
||||||
|
cl_musicvolume
|
||||||
|
cl_particleinfo
|
||||||
|
cl_quickselecttime
|
||||||
|
cl_timeout
|
||||||
|
cl_updaterate
|
||||||
|
cl_vsmoothing
|
||||||
|
cl_widescreen
|
||||||
|
con_color
|
||||||
|
con_mono
|
||||||
|
console
|
||||||
|
crosshair
|
||||||
|
fps_max
|
||||||
|
gamma
|
||||||
|
gl_dither
|
||||||
|
gl_flipmatrix
|
||||||
|
gl_fog
|
||||||
|
gl_monolights
|
||||||
|
gl_overbright
|
||||||
|
gl_polyoffset
|
||||||
|
gl_vsync
|
||||||
|
hisound
|
||||||
|
hpk_maxsize
|
||||||
|
hud_capturemouse
|
||||||
|
hud_centerid
|
||||||
|
hud_classautokill
|
||||||
|
hud_draw
|
||||||
|
hud_fastswitch
|
||||||
|
hud_takesshots
|
||||||
|
joystick
|
||||||
|
lookspring
|
||||||
|
lookstrafe
|
||||||
|
m_customaccel
|
||||||
|
m_customaccel_exponent
|
||||||
|
m_customaccel_max
|
||||||
|
m_customaccel_scale
|
||||||
|
m_filter
|
||||||
|
m_forward
|
||||||
|
m_mousethread_sleep
|
||||||
|
m_pitch
|
||||||
|
m_rawinput
|
||||||
|
m_side
|
||||||
|
m_yaw
|
||||||
|
model
|
||||||
|
MP3FadeTime
|
||||||
|
MP3Volume
|
||||||
|
mp_decals
|
||||||
|
name
|
||||||
|
net_graph
|
||||||
|
net_scale
|
||||||
|
r_detailtextures
|
||||||
|
sensitivity
|
||||||
|
skin
|
||||||
|
suitvolume
|
||||||
|
sv_aim
|
||||||
|
sv_voiceenable
|
||||||
|
team
|
||||||
|
topcolor
|
||||||
|
viewsize
|
||||||
|
voice_enable
|
||||||
|
voice_forcemicrecord
|
||||||
|
voice_modenable
|
||||||
|
voice_scale
|
||||||
|
volume
|
||||||
|
sv_cheats
|
||||||
|
hud_style
|
||||||
|
cl_cmdrate
|
||||||
|
cl_updaterate
|
||||||
|
ex_extrapmax
|
||||||
|
cl_cmdbackup
|
||||||
|
rate
|
||||||
|
ex_interp
|
||||||
|
gl_wateramp
|
||||||
|
gl_zmax
|
||||||
|
gl_ztrick
|
||||||
|
r_drawviewmodel
|
||||||
|
r_mmx
|
||||||
|
r_dynamic
|
||||||
|
r_decals
|
||||||
|
r_mirroralpha
|
||||||
|
r_bmodelhighfrac
|
||||||
|
violence_ablood
|
||||||
|
violence_agibs
|
||||||
|
violence_hblood
|
||||||
|
violence_hgibs
|
||||||
|
cl_labelmaps
|
||||||
|
senslock
|
||||||
|
cl_ambientsound
|
||||||
|
cl_widescreen
|
||||||
|
sv_jumpmode
|
BIN
NaturalLauncher/Ressources/background.png
Normal file
After Width: | Height: | Size: 2 MiB |
BIN
NaturalLauncher/Ressources/background_blur.png
Normal file
After Width: | Height: | Size: 926 KiB |
BIN
NaturalLauncher/Ressources/nsl_icon.ico
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
NaturalLauncher/Ressources/pauseimage.png
Normal file
After Width: | Height: | Size: 890 B |
BIN
NaturalLauncher/Ressources/playimage.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
NaturalLauncher/Ressources/sdx_error.wav
Normal file
BIN
NaturalLauncher/Ressources/sdx_finished.wav
Normal file
BIN
NaturalLauncher/Ressources/sdx_started.wav
Normal file
BIN
NaturalLauncher/Ressources/small_discordicon.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
NaturalLauncher/Ressources/steam_icon.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
325
NaturalLauncher/SelfUpdater.cs
Normal file
|
@ -0,0 +1,325 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
class SelfUpdater
|
||||||
|
{
|
||||||
|
public static bool isSelfUpdating = true;
|
||||||
|
|
||||||
|
public static string LaucherLocalVNumber;
|
||||||
|
public static string LaucherRemoteVNumber;
|
||||||
|
public static string curDir = Directory.GetCurrentDirectory();
|
||||||
|
|
||||||
|
public static MainWindow MainWindowReference;
|
||||||
|
|
||||||
|
public static string LauncherFolderURL = Properties.Settings.Default.LauncherUrl;
|
||||||
|
public static string VersionFileName = "launcher.version";
|
||||||
|
public static string PublicKeyPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "NslKey.cer";
|
||||||
|
public static string manifestUrl = Properties.Settings.Default.IndexURL + "CryptoManifest.txt";
|
||||||
|
|
||||||
|
public static LauncherManifest CryptoManifest = new LauncherManifest();
|
||||||
|
|
||||||
|
public static int NumberOfFiles = 0;
|
||||||
|
|
||||||
|
public bool allowMessage=false;
|
||||||
|
|
||||||
|
public BackgroundWorker backgroundWorker;
|
||||||
|
|
||||||
|
public void SetMainWindowRef(MainWindow MainWindowRef)
|
||||||
|
{
|
||||||
|
MainWindowReference = MainWindowRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateLauncher()
|
||||||
|
{
|
||||||
|
if(isSelfUpdating)
|
||||||
|
{
|
||||||
|
CheckUpdaterVersion();
|
||||||
|
|
||||||
|
DeleteOldFiles(); //delete all the updatelog and .bak files
|
||||||
|
|
||||||
|
if (LaucherLocalVNumber != LaucherRemoteVNumber)
|
||||||
|
{
|
||||||
|
UpdateCryptoManifest();
|
||||||
|
|
||||||
|
// Move the files in the launcher directory to a name with .bak
|
||||||
|
MoveLauncherFiles(); //Attention, non recursive !!!
|
||||||
|
|
||||||
|
// falsify all the buttons
|
||||||
|
MainWindowReference.StartButton.IsEnabled = false;
|
||||||
|
MainWindowReference.VerifyButton.IsEnabled = false;
|
||||||
|
MainWindowReference.SettingButton.IsEnabled = false;
|
||||||
|
|
||||||
|
// We gotta update the launcher !
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("The Launcher Will be self updating !" + Environment.NewLine + "It will restart itself once done..."); //not true anymore
|
||||||
|
ConsoleManager.Show();
|
||||||
|
|
||||||
|
// background worker download the files and switch the launcher when over
|
||||||
|
backgroundWorker = new System.ComponentModel.BackgroundWorker();
|
||||||
|
backgroundWorker.WorkerSupportsCancellation = true;
|
||||||
|
backgroundWorker.DoWork += UpdateLauncher_Worker;
|
||||||
|
backgroundWorker.RunWorkerCompleted += UpdateLauncher_RunWorkerCompleted;
|
||||||
|
backgroundWorker.RunWorkerAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (allowMessage) //inform the player we don't need update (only when using context menu so far)
|
||||||
|
{
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("No Update Required !");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateCryptoManifest()
|
||||||
|
{
|
||||||
|
using (WebClient webClient = new WebClient())
|
||||||
|
{
|
||||||
|
Console.WriteLine("Downloading the CryptoManifest");
|
||||||
|
string dasManifest = webClient.DownloadString(new Uri(manifestUrl));
|
||||||
|
CryptoManifest = JsonConvert.DeserializeObject<LauncherManifest>(dasManifest);
|
||||||
|
NumberOfFiles = CryptoManifest.Files.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CheckUpdaterVersion()
|
||||||
|
{
|
||||||
|
LaucherLocalVNumber = Util.LocalVersion(curDir + Path.DirectorySeparatorChar + VersionFileName);
|
||||||
|
Console.WriteLine("Checking launcher's Version ...");
|
||||||
|
Console.WriteLine("Local Version of the updater is :" + LaucherLocalVNumber);
|
||||||
|
if (LaucherLocalVNumber != null)
|
||||||
|
{
|
||||||
|
LaucherRemoteVNumber = Util.RemoteVersion(Launcher.MainPageURL + VersionFileName);
|
||||||
|
Console.WriteLine("Got the remote version with success :" + LaucherRemoteVNumber);
|
||||||
|
}
|
||||||
|
else //if it doesn exist, we need to inform the user
|
||||||
|
{
|
||||||
|
LaucherLocalVNumber = "0.0.0.0";
|
||||||
|
Util.PlaySoundFX("error");
|
||||||
|
LaucherRemoteVNumber = Util.RemoteVersion(Launcher.MainPageURL + VersionFileName);
|
||||||
|
Console.WriteLine("Couldnt find remote version number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void MoveLauncherFiles()
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, string> kv in CryptoManifest.Files)
|
||||||
|
{
|
||||||
|
string fullpath = curDir + Path.DirectorySeparatorChar + kv.Key.Remove(0,1);
|
||||||
|
if (File.Exists(fullpath))
|
||||||
|
{
|
||||||
|
Console.WriteLine(fullpath + " : Changing to .bak extension ...");
|
||||||
|
System.IO.File.Move(fullpath, fullpath + ".bak");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public static void AddNewFilesToChangeList()
|
||||||
|
{
|
||||||
|
// Check the new files
|
||||||
|
List<string> NewFiles = Util.GetDirectoryFilesFromUrl(LauncherFolderURL);
|
||||||
|
|
||||||
|
// we add the new files into the changedlist
|
||||||
|
foreach (string file in NewFiles)
|
||||||
|
{
|
||||||
|
if (!ChangedFiles.Contains(file))
|
||||||
|
ChangedFiles.Add(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberOfFiles = ChangedFiles.Count;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public void UpdateLauncher_Worker(object sender, DoWorkEventArgs e)
|
||||||
|
{
|
||||||
|
WebClient webClient = new WebClient();
|
||||||
|
webClient.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
|
||||||
|
webClient.DownloadFileCompleted += webClient_DownloadFileCompleted;
|
||||||
|
|
||||||
|
// Download the changed files
|
||||||
|
foreach (KeyValuePair<string, string> kv in CryptoManifest.Files)
|
||||||
|
{
|
||||||
|
string smtg = kv.Key.Remove(0, 1);
|
||||||
|
DownloadLauncherFiles(kv.Key.Remove(0,1), webClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateLauncher_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!backgroundWorker.IsBusy && NumberOfFiles<=0) //double check but somehow it executed twice oO
|
||||||
|
{
|
||||||
|
CheckSignatureAndLaunch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DownloadLauncherFiles(string file, WebClient webClient)
|
||||||
|
{
|
||||||
|
Console.WriteLine(file + " : Downloading ...");
|
||||||
|
webClient.DownloadFileAsync(new Uri(LauncherFolderURL+ file), curDir + Path.DirectorySeparatorChar + file);
|
||||||
|
|
||||||
|
while (webClient.IsBusy)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Error != null)
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show(e.Error.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NumberOfFiles--;
|
||||||
|
Console.WriteLine("Downloaded !" + NumberOfFiles.ToString() + " more files to go !");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DeleteOldFiles()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Cleaning old and update files ...");
|
||||||
|
foreach (string file in Directory.GetFiles(curDir))
|
||||||
|
{
|
||||||
|
// Cleaning BAK files
|
||||||
|
if(Path.GetExtension(file)==".bak")
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
string localPath = Util.ToLocalPath(curDir, file);
|
||||||
|
|
||||||
|
// Cleaning UpdateLogs files
|
||||||
|
if (localPath.StartsWith("/UpdateLog"))
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CheckSignatureAndLaunch()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Starting signature check");
|
||||||
|
foreach (KeyValuePair<string, string> kv in CryptoManifest.Files)
|
||||||
|
{
|
||||||
|
string FullPath = curDir + Path.DirectorySeparatorChar + kv.Key.Remove(0, 1);
|
||||||
|
var stream = File.ReadAllBytes(FullPath);
|
||||||
|
string signatureHexaString = "";
|
||||||
|
CryptoManifest.Files.TryGetValue(kv.Key, out signatureHexaString);
|
||||||
|
|
||||||
|
if (!Verify(stream, PublicKeyPath, signatureHexaString))
|
||||||
|
{
|
||||||
|
Util.PlaySoundFX("error");
|
||||||
|
System.Windows.MessageBox.Show(kv.Key + " unvalidated. Your version is corrupted, please redownload the launcher from a trusted source (ensl.org)");
|
||||||
|
Console.WriteLine(kv.Key + " : UNVALIDATED and DELETED...");
|
||||||
|
File.Delete(FullPath);
|
||||||
|
Console.Read();
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Console.WriteLine(kv.Key + " : validated ...");
|
||||||
|
}
|
||||||
|
|
||||||
|
Task.Delay(10);
|
||||||
|
Console.WriteLine("Refreshing version Number");
|
||||||
|
Util.CreateLocalVersionFile(curDir, VersionFileName, LaucherRemoteVNumber);
|
||||||
|
|
||||||
|
Util.LaunchAgain(curDir + Path.DirectorySeparatorChar + "CleanAndLaunch.exe");
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Verify(byte[] data, string PublicKeyPath, string SignatureHexaString)
|
||||||
|
{
|
||||||
|
X509Certificate2 publicKey = LoadPublicKey(PublicKeyPath);
|
||||||
|
byte[] signature = StringToByte(SignatureHexaString);
|
||||||
|
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("data");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publicKey == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("publicKey");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signature == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("signature");
|
||||||
|
}
|
||||||
|
|
||||||
|
var provider = (RSACryptoServiceProvider)publicKey.PublicKey.Key;
|
||||||
|
|
||||||
|
return provider.VerifyData(data, new SHA1CryptoServiceProvider(), signature);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static X509Certificate2 LoadPublicKey(string PublicKeyPath)
|
||||||
|
{
|
||||||
|
return new X509Certificate2(PublicKeyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] StringToByte(string str)
|
||||||
|
{
|
||||||
|
String[] arr = str.Split('-');
|
||||||
|
byte[] array = new byte[arr.Length];
|
||||||
|
for (int i = 0; i < arr.Length; i++) array[i] = Convert.ToByte(arr[i], 16);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CheckOneFileSignature(string fileName)
|
||||||
|
{
|
||||||
|
UpdateCryptoManifest(); //first let's update the crypto manifest with latest values
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, string> kv in CryptoManifest.Files)
|
||||||
|
{
|
||||||
|
if (kv.Key.Remove(0, 1) == fileName) // we found the filename in the manifest
|
||||||
|
{
|
||||||
|
string FullPath = curDir + Path.DirectorySeparatorChar + kv.Key.Remove(0, 1);
|
||||||
|
var stream = File.ReadAllBytes(FullPath);
|
||||||
|
string signatureHexaString = "";
|
||||||
|
CryptoManifest.Files.TryGetValue(kv.Key, out signatureHexaString);
|
||||||
|
return Verify(stream, PublicKeyPath, signatureHexaString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
183
NaturalLauncher/ServerChecker.cs
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
class ServerChecker
|
||||||
|
{
|
||||||
|
public class A2S_INFO
|
||||||
|
{
|
||||||
|
// \xFF\xFF\xFF\xFFTSource Engine Query\x00 because UTF-8 doesn't like to encode 0xFF
|
||||||
|
public static readonly byte[] REQUEST = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x45, 0x6E, 0x67, 0x69, 0x6E, 0x65, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x00 };
|
||||||
|
#region Strong Typing Enumerators
|
||||||
|
[Flags]
|
||||||
|
public enum ExtraDataFlags : byte
|
||||||
|
{
|
||||||
|
GameID = 0x01,
|
||||||
|
SteamID = 0x10,
|
||||||
|
Keywords = 0x20,
|
||||||
|
Spectator = 0x40,
|
||||||
|
Port = 0x80
|
||||||
|
}
|
||||||
|
public enum VACFlags : byte
|
||||||
|
{
|
||||||
|
Unsecured = 0,
|
||||||
|
Secured = 1
|
||||||
|
}
|
||||||
|
public enum VisibilityFlags : byte
|
||||||
|
{
|
||||||
|
Public = 0,
|
||||||
|
Private = 1
|
||||||
|
}
|
||||||
|
public enum EnvironmentFlags : byte
|
||||||
|
{
|
||||||
|
Linux = 0x6C, //l
|
||||||
|
Windows = 0x77, //w
|
||||||
|
Mac = 0x6D, //m
|
||||||
|
MacOsX = 0x6F //o
|
||||||
|
}
|
||||||
|
public enum ServerTypeFlags : byte
|
||||||
|
{
|
||||||
|
Dedicated = 0x64, //d
|
||||||
|
Nondedicated = 0x6C, //l
|
||||||
|
SourceTV = 0x70 //p
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
public byte Header { get; set; } // I
|
||||||
|
public byte Protocol { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Map { get; set; }
|
||||||
|
public string Folder { get; set; }
|
||||||
|
public string Game { get; set; }
|
||||||
|
public short ID { get; set; }
|
||||||
|
public byte Players { get; set; }
|
||||||
|
public byte MaxPlayers { get; set; }
|
||||||
|
public byte Bots { get; set; }
|
||||||
|
public ServerTypeFlags ServerType { get; set; }
|
||||||
|
public EnvironmentFlags Environment { get; set; }
|
||||||
|
public VisibilityFlags Visibility { get; set; }
|
||||||
|
public VACFlags VAC { get; set; }
|
||||||
|
public string Version { get; set; }
|
||||||
|
public ExtraDataFlags ExtraDataFlag { get; set; }
|
||||||
|
#region Extra Data Flag Members
|
||||||
|
public ulong GameID { get; set; } //0x01
|
||||||
|
public ulong SteamID { get; set; } //0x10
|
||||||
|
public string Keywords { get; set; } //0x20
|
||||||
|
public string Spectator { get; set; } //0x40
|
||||||
|
public short SpectatorPort { get; set; } //0x40
|
||||||
|
public short Port { get; set; } //0x80
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public A2S_INFO(IPEndPoint ep)
|
||||||
|
{
|
||||||
|
UdpClient udp = new UdpClient();
|
||||||
|
udp.Send(REQUEST, REQUEST.Length, ep);
|
||||||
|
MemoryStream ms = new MemoryStream(udp.Receive(ref ep)); // Saves the received data in a memory buffer
|
||||||
|
BinaryReader br = new BinaryReader(ms, Encoding.UTF8); // A binary reader that treats charaters as Unicode 8-bit
|
||||||
|
ms.Seek(4, SeekOrigin.Begin); // skip the 4 0xFFs
|
||||||
|
Header = br.ReadByte();
|
||||||
|
Protocol = br.ReadByte();
|
||||||
|
Name = ReadNullTerminatedString(ref br);
|
||||||
|
Map = ReadNullTerminatedString(ref br);
|
||||||
|
Folder = ReadNullTerminatedString(ref br);
|
||||||
|
Game = ReadNullTerminatedString(ref br);
|
||||||
|
ID = br.ReadInt16();
|
||||||
|
Players = br.ReadByte();
|
||||||
|
MaxPlayers = br.ReadByte();
|
||||||
|
Bots = br.ReadByte();
|
||||||
|
ServerType = (ServerTypeFlags)br.ReadByte();
|
||||||
|
Environment = (EnvironmentFlags)br.ReadByte();
|
||||||
|
Visibility = (VisibilityFlags)br.ReadByte();
|
||||||
|
VAC = (VACFlags)br.ReadByte();
|
||||||
|
Version = ReadNullTerminatedString(ref br);
|
||||||
|
ExtraDataFlag = (ExtraDataFlags)br.ReadByte();
|
||||||
|
#region These EDF readers have to be in this order because that's the way they are reported
|
||||||
|
if (ExtraDataFlag.HasFlag(ExtraDataFlags.Port))
|
||||||
|
Port = br.ReadInt16();
|
||||||
|
if (ExtraDataFlag.HasFlag(ExtraDataFlags.SteamID))
|
||||||
|
SteamID = br.ReadUInt64();
|
||||||
|
if (ExtraDataFlag.HasFlag(ExtraDataFlags.Spectator))
|
||||||
|
{
|
||||||
|
SpectatorPort = br.ReadInt16();
|
||||||
|
Spectator = ReadNullTerminatedString(ref br);
|
||||||
|
}
|
||||||
|
if (ExtraDataFlag.HasFlag(ExtraDataFlags.Keywords))
|
||||||
|
Keywords = ReadNullTerminatedString(ref br);
|
||||||
|
if (ExtraDataFlag.HasFlag(ExtraDataFlags.GameID))
|
||||||
|
GameID = br.ReadUInt64();
|
||||||
|
#endregion
|
||||||
|
br.Close();
|
||||||
|
ms.Close();
|
||||||
|
udp.Close();
|
||||||
|
}
|
||||||
|
/// <summary>Reads a null-terminated string into a .NET Framework compatible string.</summary>
|
||||||
|
/// <param name="input">Binary reader to pull the null-terminated string from. Make sure it is correctly positioned in the stream before calling.</param>
|
||||||
|
/// <returns>String of the same encoding as the input BinaryReader.</returns>
|
||||||
|
public static string ReadNullTerminatedString(ref BinaryReader input)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
char read = input.ReadChar();
|
||||||
|
while (read != '\x00')
|
||||||
|
{
|
||||||
|
sb.Append(read);
|
||||||
|
read = input.ReadChar();
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles IPv4 and IPv6 notation.
|
||||||
|
public static IPEndPoint CreateIPEndPoint(string endPoint)
|
||||||
|
{
|
||||||
|
string[] ep = endPoint.Split(':');
|
||||||
|
if (ep.Length < 2) throw new FormatException("Invalid endpoint format");
|
||||||
|
IPAddress ip;
|
||||||
|
if (ep.Length > 2)
|
||||||
|
{
|
||||||
|
if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip))
|
||||||
|
{
|
||||||
|
throw new FormatException("Invalid ip-adress");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!IPAddress.TryParse(ep[0], out ip))
|
||||||
|
{
|
||||||
|
throw new FormatException("Invalid ip-adress");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int port;
|
||||||
|
if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port))
|
||||||
|
{
|
||||||
|
throw new FormatException("Invalid port");
|
||||||
|
}
|
||||||
|
return new IPEndPoint(ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
NaturalLauncher/Settings.xaml
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<Window x:Class="NaturalLauncher.Settings"
|
||||||
|
Closed="Window_Closed"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:NaturalLauncher"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="Settings" Height="350" Width="587" Background="#FF0D0D0C" MinWidth="568" MinHeight="280" MaxWidth="587" MaxHeight="350">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="95*"/>
|
||||||
|
<ColumnDefinition Width="97*"/>
|
||||||
|
<ColumnDefinition Width="195"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Canvas Margin="10" Background="#FF1E1E1C" Grid.ColumnSpan="3">
|
||||||
|
<Label Content="Options :" Canvas.Left="10" Canvas.Top="9" Height="27" Width="516" Foreground="#FFEEA160" FontWeight="Bold"/>
|
||||||
|
<Label Content="Nine Legend Pack :" Canvas.Left="60" Canvas.Top="253" Height="27" Width="127" Foreground="#FF5ACAFF" FontWeight="Bold" IsEnabled="False" Visibility="Collapsed"/>
|
||||||
|
<Label Content="Advanced UserConfig :" Canvas.Left="44" Canvas.Top="310" Height="27" Width="143" Foreground="#FF5ACAFF" FontWeight="Bold" IsEnabled="False" Visibility="Collapsed"/>
|
||||||
|
<Label Content="Change HL Folder :" Canvas.Left="48" Canvas.Top="216" Height="27" Width="127" Foreground="#FF5ACAFF" FontWeight="Bold" HorizontalContentAlignment="Center"/>
|
||||||
|
<Button x:Name="NLInstallButton" Content="Install" Canvas.Left="208" Canvas.Top="250" Width="133" Height="33" Click="NLInstallButton_Click" IsEnabled="False" Visibility="Collapsed"/>
|
||||||
|
<Button x:Name="NLUnInstallButton" Content="Uninstall" Canvas.Left="367" Canvas.Top="250" Width="133" Height="33" Click="NLUnInstallButton_Click" IsEnabled="False" Visibility="Collapsed"/>
|
||||||
|
<Button x:Name="AdvSettingsInstallButton" Content="Install" Canvas.Left="208" Canvas.Top="307" Width="133" Height="33" Click="AdvSettingsInstallButton_Click" IsEnabled="False" Visibility="Collapsed"/>
|
||||||
|
<Button x:Name="AdvSettingsUnInstallButton" Content="Uninstall" Canvas.Left="367" Canvas.Top="307" Width="133" Height="33" Click="AdvSettingsUnInstallButton_Click" IsEnabled="False" Visibility="Collapsed"/>
|
||||||
|
<Button x:Name="BrowseHLFolderButton" Content="Browse" Canvas.Left="252" Canvas.Top="215" Width="221" Height="33" Click="BrowseHLFolderButton_Click"/>
|
||||||
|
<Label Content="Change cfg parameter :" Canvas.Left="38" Canvas.Top="82" Height="27" Width="147" Foreground="#FF5ACAFF" FontWeight="Bold" HorizontalContentAlignment="Center"/>
|
||||||
|
<TextBox x:Name="ParamNameTxtbox" Height="27" Canvas.Left="212" TextWrapping="Wrap" Text="Parameter" Canvas.Top="83" Width="121" Foreground="#FF2B2F30" FontWeight="Bold" Background="#BFFFFFFF" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
||||||
|
<TextBox x:Name="ParamValueTxtbox" Height="27" Canvas.Left="392" TextWrapping="Wrap" Text="Value" Canvas.Top="83" Width="81" Foreground="#FF2B2F30" FontWeight="Bold" Background="#BFFFFFFF" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
||||||
|
<Button x:Name="FindParamButton" Content="Find" Canvas.Left="338" Canvas.Top="83" Width="49" Height="27" Background="#19000000" BorderBrush="#FF5ACAFF" Foreground="#FF5ACAFF" Click="FindParameter_Click"/>
|
||||||
|
<Button x:Name="ChangeValueButton" Content="Change" Canvas.Left="479" Canvas.Top="83" Width="49" Height="27" Background="#19000000" BorderBrush="#FF5ACAFF" Foreground="#FF5ACAFF" Click="ChangeParameter_Click"/>
|
||||||
|
<Label Content="HUD Syle :" Canvas.Left="59" Canvas.Top="39" Height="27" Width="105" Foreground="#FF5ACAFF" FontWeight="Bold" HorizontalContentAlignment="Center"/>
|
||||||
|
<RadioButton x:Name="ClassicRadioButton" Content="Classic" Canvas.Left="240" Canvas.Top="45" Foreground="#FF5AFF5A" Checked="ClassicRadioButton_Checked"/>
|
||||||
|
<RadioButton x:Name="MinimalRadioButton" Content="Minimal" Canvas.Left="326" Canvas.Top="45" Foreground="#FF5ACAFF" Checked="MinimalRadioButton_Checked"/>
|
||||||
|
<RadioButton x:Name="NLRadioButton" Content="Nine Legend" Canvas.Left="417" Canvas.Top="45" Foreground="#FFFFA55A" Checked="NLRadioButton_Checked"/>
|
||||||
|
<Label Content="Add files to ignore list :" Canvas.Left="39" Canvas.Top="172" Height="27" Width="145" Foreground="#FF5ACAFF" FontWeight="Bold" HorizontalContentAlignment="Center"/>
|
||||||
|
<Button x:Name="BrowseHLFolderButton_Copy" Content="Add file(s)" Canvas.Left="252" Canvas.Top="169" Width="221" Height="33" Click="AddToIgnoreButton_Click"/>
|
||||||
|
<CheckBox x:Name="KeepAliveChecker" Content="Keep Launcher alive when playing (and discord status)" Canvas.Left="108" Canvas.Top="266" FontWeight="Bold" Foreground="#FF5ACAFF" Width="343" HorizontalContentAlignment="Center" Click="StopAfterLaunch_Click"/>
|
||||||
|
<Label Content="Custom discord status :" Canvas.Left="38" Canvas.Top="128" Height="27" Width="145" Foreground="#FF5ACAFF" FontWeight="Bold" HorizontalContentAlignment="Center"/>
|
||||||
|
<TextBox x:Name="DiscordTxtbox" Height="27" Canvas.Left="212" TextWrapping="Wrap" Text="status" Canvas.Top="127" Width="261" Foreground="#FF2B2F30" FontWeight="Bold" Background="#BFFFFFFF" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
||||||
|
<Button x:Name="ChangeDiscordButton" Content="Change" Canvas.Left="479" Canvas.Top="127" Width="49" Height="27" Background="#19000000" BorderBrush="#FF5ACAFF" Foreground="#FF5ACAFF" Click="ChangeDiscord_Click"/>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
259
NaturalLauncher/Settings.xaml.cs
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logique d'interaction pour Settings.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class Settings : Window
|
||||||
|
{
|
||||||
|
|
||||||
|
public static MainWindow MainWindowReference;
|
||||||
|
public static bool windowfullyopen = false;
|
||||||
|
|
||||||
|
public Settings()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
ParamNameTxtbox.SpellCheck.IsEnabled = true;
|
||||||
|
ParamNameTxtbox.SpellCheck.CustomDictionaries.Add(new Uri("pack://application:,,,/Ressources/Commande.lex")); //add the command custom dictonary
|
||||||
|
|
||||||
|
//RefreshNLInstallButtonState(); //nl pack based
|
||||||
|
|
||||||
|
Util.GetAValueInCfg("hud_style",out string HUDStyleparam);
|
||||||
|
switch(HUDStyleparam)
|
||||||
|
{
|
||||||
|
case "0":
|
||||||
|
ClassicRadioButton.IsChecked = true;
|
||||||
|
break;
|
||||||
|
case "1":
|
||||||
|
MinimalRadioButton.IsChecked = true;
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
NLRadioButton.IsChecked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlBuilder.ReadConfigXml(out string uno, out bool dos, out string discordStatus, out bool keepAlive);
|
||||||
|
Launcher.keepLauncherAlive = keepAlive;
|
||||||
|
DiscordTxtbox.Text = discordStatus;
|
||||||
|
KeepAliveChecker.IsChecked = keepAlive;
|
||||||
|
|
||||||
|
windowfullyopen = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMainWindowRef(MainWindow MainWindowRef)
|
||||||
|
{
|
||||||
|
MainWindowReference = MainWindowRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Window_Closed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
MainWindow.sw = null;
|
||||||
|
windowfullyopen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FindParameter_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Util.GetAValueInCfg(ParamNameTxtbox.Text,out string ParamValue);
|
||||||
|
ParamValueTxtbox.Text = ParamValue;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ParamValueTxtbox.Text = "not found";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangeParameter_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(ParamValueTxtbox.Text != "not found")
|
||||||
|
{
|
||||||
|
Util.ChangeAValueInCfg(ParamNameTxtbox.Text, ParamValueTxtbox.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshNLInstallButtonState()
|
||||||
|
{
|
||||||
|
if (Launcher.IsNLPack())
|
||||||
|
{
|
||||||
|
NLInstallButton.IsEnabled = false;
|
||||||
|
NLUnInstallButton.IsEnabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NLInstallButton.IsEnabled = true;
|
||||||
|
NLUnInstallButton.IsEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NLInstallButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// TODO Install THE NL PACK, USING NL FOLDERS URL
|
||||||
|
Launcher.SetIsNLPack(true);
|
||||||
|
RefreshNLInstallButtonState();
|
||||||
|
MainWindowReference.CallUpdateGame();
|
||||||
|
MainWindowReference.SettingButton.IsEnabled = false;
|
||||||
|
this.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NLUnInstallButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// TODO REMOVE THE NL PACK FILES USING NL FOLDERS URL
|
||||||
|
// THEN REPAIR INSTALLATION
|
||||||
|
Launcher.SetIsNLPack(false);
|
||||||
|
RefreshNLInstallButtonState();
|
||||||
|
MainWindowReference.CallUpdateGame();
|
||||||
|
MainWindowReference.SettingButton.IsEnabled = false;
|
||||||
|
this.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AdvSettingsInstallButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// GET THE CONFIG FILES INSIDE THE GAME URL. SHOULDNT NEED A MANIFEST, JUST GET CFGs
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (System.Windows.Forms.MessageBox.Show("You are about to download a set of configuration files "
|
||||||
|
+ Environment.NewLine + "These files will override your current and existing configuration files if they exists."
|
||||||
|
+ Environment.NewLine + "Please chose if you want to continue.", "", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes)
|
||||||
|
{
|
||||||
|
using (WebClient webClient = new WebClient()) // yeah I know it's brutal :D
|
||||||
|
{
|
||||||
|
webClient.DownloadFile(new Uri(Properties.Settings.Default.GameUrl + "/config.cfg"), Launcher.NSFolder + System.IO.Path.DirectorySeparatorChar + "config.cfg");
|
||||||
|
webClient.DownloadFile(new Uri(Properties.Settings.Default.GameUrl + "/userconfig.cfg"), Launcher.NSFolder + System.IO.Path.DirectorySeparatorChar + "userconfig.cfg");
|
||||||
|
webClient.DownloadFile(new Uri(Properties.Settings.Default.GameUrl + "/alien_.cfg"), Launcher.NSFolder + System.IO.Path.DirectorySeparatorChar + "alien_.cfg");
|
||||||
|
webClient.DownloadFile(new Uri(Properties.Settings.Default.GameUrl + "/pistol_.cfg"), Launcher.NSFolder + System.IO.Path.DirectorySeparatorChar + "pistol_.cfg");
|
||||||
|
webClient.DownloadFile(new Uri(Properties.Settings.Default.GameUrl + "/reset_.cfg"), Launcher.NSFolder + System.IO.Path.DirectorySeparatorChar + "reset_.cfg");
|
||||||
|
webClient.DownloadFile(new Uri(Properties.Settings.Default.GameUrl + "/rine_.cfg"), Launcher.NSFolder + System.IO.Path.DirectorySeparatorChar + "rine_.cfg");
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Advanced settings Installed with success");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Advanced settings failed to install");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AdvSettingsUnInstallButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// REMOVE THE CFG FILES. ENDWITH(config.cfg) AND ENDWITH(_.cfg). GAME SHOULD RECREATE THE CONFIG FILE
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (string file in Directory.GetFiles(Launcher.NSFolder))
|
||||||
|
{
|
||||||
|
if (file.EndsWith("_.cfg") || file.EndsWith("config.cfg"))
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Advanced settings Removed with success");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Failed to remove settings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BrowseHLFolderButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// BROWSE AND CHANGE THE FOLDER FILE. DONT FORGET TO UPDATE THE GLOBAL VARIABLE
|
||||||
|
bool IsItNLPack = Launcher.IsNLPack();
|
||||||
|
string folderPath = Util.AskForHLFolder();
|
||||||
|
|
||||||
|
if (folderPath!=null)
|
||||||
|
{
|
||||||
|
XmlBuilder.CreateConfigXml();
|
||||||
|
Launcher.HLFolder = folderPath;
|
||||||
|
Launcher.NSFolder = folderPath + System.IO.Path.DirectorySeparatorChar + "ns";
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowReference.CallUpdateGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClassicRadioButton_Checked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if(windowfullyopen)
|
||||||
|
{
|
||||||
|
ClassicRadioButton.IsChecked = true;
|
||||||
|
MinimalRadioButton.IsChecked = false;
|
||||||
|
NLRadioButton.IsChecked = false;
|
||||||
|
Util.ChangeAValueInCfg("hud_style", "0", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MinimalRadioButton_Checked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (windowfullyopen)
|
||||||
|
{
|
||||||
|
ClassicRadioButton.IsChecked = false;
|
||||||
|
MinimalRadioButton.IsChecked = true;
|
||||||
|
NLRadioButton.IsChecked = false;
|
||||||
|
Util.ChangeAValueInCfg("hud_style", "1", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NLRadioButton_Checked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (windowfullyopen)
|
||||||
|
{
|
||||||
|
ClassicRadioButton.IsChecked = false;
|
||||||
|
MinimalRadioButton.IsChecked = false;
|
||||||
|
NLRadioButton.IsChecked = true;
|
||||||
|
Util.ChangeAValueInCfg("hud_style", "2", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddToIgnoreButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Launcher.AddToIgnoreList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopAfterLaunch_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Launcher.keepLauncherAlive = KeepAliveChecker.IsChecked.Value;
|
||||||
|
|
||||||
|
XmlBuilder.CreateConfigXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangeDiscord_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Launcher.discordCustomStatus = DiscordTxtbox.Text;
|
||||||
|
Launcher.UpdateDiscord(false);
|
||||||
|
XmlBuilder.CreateConfigXml();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
665
NaturalLauncher/Util.cs
Normal file
|
@ -0,0 +1,665 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using HtmlAgilityPack;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Windows.Resources;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
class Util
|
||||||
|
{
|
||||||
|
public static string ComputeMD5(string file)
|
||||||
|
{
|
||||||
|
MD5 md5 = MD5.Create();
|
||||||
|
|
||||||
|
string hash = "";
|
||||||
|
using (var stream = File.OpenRead(file))
|
||||||
|
{
|
||||||
|
hash = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string LocalVersion(string path)
|
||||||
|
{
|
||||||
|
string lv = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(path)
|
||||||
|
|| System.IO.Path.GetInvalidPathChars().Intersect(
|
||||||
|
path.ToCharArray()).Count() != 0
|
||||||
|
|| !new System.IO.FileInfo(path).Exists)
|
||||||
|
{
|
||||||
|
lv = null;
|
||||||
|
}
|
||||||
|
else if (new System.IO.FileInfo(path).Exists)
|
||||||
|
{
|
||||||
|
string s = System.IO.File.ReadAllText(path);
|
||||||
|
if (ValidateFile(s)) {
|
||||||
|
lv = s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string CreateLocalVersionFile(string folderPath,
|
||||||
|
string fileName, string version)
|
||||||
|
{
|
||||||
|
if (!new System.IO.DirectoryInfo(folderPath).Exists)
|
||||||
|
{
|
||||||
|
System.IO.Directory.CreateDirectory(folderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
string path = folderPath + Path.DirectorySeparatorChar + fileName;
|
||||||
|
|
||||||
|
if (new System.IO.FileInfo(path).Exists)
|
||||||
|
{
|
||||||
|
new System.IO.FileInfo(path).Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new System.IO.FileInfo(path).Exists)
|
||||||
|
{
|
||||||
|
System.IO.File.WriteAllText(path, version);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// method used to check internet connectivity
|
||||||
|
public static bool CheckForInternetConnection(string UrlToCheck)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new WebClient())
|
||||||
|
using (client.OpenRead(UrlToCheck)) // or http://clients3.google.com/generate_204
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ValidateFile(string contents)
|
||||||
|
{
|
||||||
|
bool val = false;
|
||||||
|
if (!string.IsNullOrEmpty(contents))
|
||||||
|
{
|
||||||
|
string pattern = "^([0-9]*\\.){3}[0-9]*$";
|
||||||
|
System.Text.RegularExpressions.Regex re =
|
||||||
|
new System.Text.RegularExpressions.Regex(pattern);
|
||||||
|
val = re.IsMatch(contents);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string RemoteVersion(string url)
|
||||||
|
{
|
||||||
|
string rv = "";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)
|
||||||
|
System.Net.WebRequest.Create(url);
|
||||||
|
System.Net.HttpWebResponse response =
|
||||||
|
(System.Net.HttpWebResponse)req.GetResponse();
|
||||||
|
System.IO.Stream receiveStream = response.GetResponseStream();
|
||||||
|
System.IO.StreamReader readStream =
|
||||||
|
new System.IO.StreamReader(receiveStream, Encoding.UTF8);
|
||||||
|
string s = readStream.ReadToEnd();
|
||||||
|
response.Close();
|
||||||
|
if (ValidateFile(s))
|
||||||
|
{
|
||||||
|
rv = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// Anything could have happened here but
|
||||||
|
// we don't want to stop the user
|
||||||
|
// from using the application.
|
||||||
|
rv = null;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Size(long bytes)
|
||||||
|
{
|
||||||
|
if (bytes > 1000000000)
|
||||||
|
{
|
||||||
|
return ((float)bytes / 1000000000f).ToString("f") + " GB";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes > 1000000)
|
||||||
|
{
|
||||||
|
return ((float)bytes / 1000000f).ToString("f") + " MB";
|
||||||
|
}
|
||||||
|
if (bytes > 1000)
|
||||||
|
{
|
||||||
|
return ((float)bytes / 1000f).ToString("f") + " KB";
|
||||||
|
}
|
||||||
|
return ((float)bytes).ToString("f") + " B";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToLocalPath(string root, string dir)
|
||||||
|
{
|
||||||
|
return dir.Replace(root, "").Replace("\\", "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetLongTimeString()
|
||||||
|
{
|
||||||
|
var src = DateTime.Now;
|
||||||
|
string StringToReturn = src.Month + "_" + src.Day + "_" + src.Hour + "_" + src.Minute + "_" + src.Second;
|
||||||
|
return StringToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetShortTimeString()
|
||||||
|
{
|
||||||
|
var src = DateTime.Now;
|
||||||
|
string StringToReturn = "[ " + src.Hour + " : " + src.Minute + " : " + src.Second + " ] : ";
|
||||||
|
return StringToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetSteamFolder(bool WantCommon) //just testing if ever needed
|
||||||
|
{
|
||||||
|
string path = "";
|
||||||
|
// HKEY_CURRENT_USER/Software/Valve/Steam
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Valve\\Steam"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
Object o = key.GetValue("SteamPath");
|
||||||
|
if (o != null)
|
||||||
|
{
|
||||||
|
path = o as String;
|
||||||
|
|
||||||
|
if(WantCommon)
|
||||||
|
path = path + "/steamapps/common";
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
|
||||||
|
Console.WriteLine(path);
|
||||||
|
|
||||||
|
// NEEDS A NUGGET PACKAGE GAMELOOP.VDF TO READ
|
||||||
|
// To get full list of game folders : steamapps\libraryfolders.vdf
|
||||||
|
/*string LibraryFoldersPath = path + Path.DirectorySeparatorChar + "steamapps" + Path.DirectorySeparatorChar + "libraryfolders.vdf";
|
||||||
|
|
||||||
|
// we need a function to extract folder directory
|
||||||
|
dynamic FolderLibrary = VdfConvert.Deserialize(File.ReadAllText(LibraryFoldersPath));
|
||||||
|
var FolderLibraryValues = FolderLibrary.Value;
|
||||||
|
var importantJsonObject = FolderLibrary.ToJson();*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
MessageBoxResult AlertBox = MessageBox.Show("Steam Folder not found");
|
||||||
|
path = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetHLFolder() //just testing if ever needed
|
||||||
|
{
|
||||||
|
string path = "";
|
||||||
|
// HKEY_CURRENT_USER/Software/Valve/Steam
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Valve\\Steam"))
|
||||||
|
{
|
||||||
|
if (key != null)
|
||||||
|
{
|
||||||
|
Object o = key.GetValue("ModInstallPath");
|
||||||
|
if (o != null)
|
||||||
|
{
|
||||||
|
path = o as String;
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
|
||||||
|
Console.WriteLine(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
MessageBoxResult AlertBox = MessageBox.Show("HL Folder not found","Alert", MessageBoxButton.OK , MessageBoxImage.Error);
|
||||||
|
path = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ReadGathererCount()
|
||||||
|
{
|
||||||
|
var url = Properties.Settings.Default.GatherURL;
|
||||||
|
var web = new HtmlWeb();
|
||||||
|
var doc = web.Load(url);
|
||||||
|
string htmlstring = doc.Text;
|
||||||
|
int Count = 0;
|
||||||
|
// need to retrieve this : <ul id="gatherers">
|
||||||
|
var nodal = doc.DocumentNode.Descendants("ul");
|
||||||
|
|
||||||
|
for(int i = 0; i < nodal.Count(); i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (nodal.ElementAt(i).Id == "gatherers")
|
||||||
|
{
|
||||||
|
Count = nodal.ElementAt(i).SelectNodes("li").Count(); //and count the <li> inside
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is here to compare the general "standard" ns install with the advanced "NlPack" install version
|
||||||
|
// If the user is using the NLPack then the manifest has to be updated consequently.
|
||||||
|
public static LauncherManifest CleanManifestWithOptions(LauncherManifest GeneralManifest, LauncherManifest NLManifest)
|
||||||
|
{
|
||||||
|
//string value = "";
|
||||||
|
foreach (KeyValuePair<string, string> kv in NLManifest.Files)
|
||||||
|
{
|
||||||
|
if (GeneralManifest.Files.ContainsKey(kv.Key))
|
||||||
|
{
|
||||||
|
// we should delete, not to verify this. Then a second period of the updater check changed with the nl folder and its own manifest.
|
||||||
|
// the following code is in case you want to change the value (commented)
|
||||||
|
|
||||||
|
/*NLManifest.Files.TryGetValue(kv.Key, out value);
|
||||||
|
GeneralManifest.Files[kv.Key] = value; */
|
||||||
|
|
||||||
|
GeneralManifest.Files.Remove(kv.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GeneralManifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool RemoteFileExists(string url)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//Creating the HttpWebRequest
|
||||||
|
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
|
||||||
|
//Setting the Request method HEAD, you can also use GET too.
|
||||||
|
request.Method = "HEAD";
|
||||||
|
//Getting the Web Response.
|
||||||
|
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
|
||||||
|
//Returns TRUE if the Status code == 200
|
||||||
|
response.Close();
|
||||||
|
return (response.StatusCode == HttpStatusCode.OK);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//Any exception will returns false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<string> TheDirectory = new List<string>();
|
||||||
|
|
||||||
|
public static List<string> GetDirectoryFilesFromUrl(string url)
|
||||||
|
{
|
||||||
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||||
|
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||||
|
{
|
||||||
|
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
|
||||||
|
{
|
||||||
|
string html = reader.ReadToEnd();
|
||||||
|
Regex regex = new Regex(GetDirectoryListingRegexForUrl(url));
|
||||||
|
MatchCollection matches = regex.Matches(html);
|
||||||
|
if (matches.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (Match match in matches)
|
||||||
|
{
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
TheDirectory.Add(match.Groups["name"].ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TheDirectory.Remove("Parent Directory");
|
||||||
|
|
||||||
|
return TheDirectory;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDirectoryListingRegexForUrl(string url)
|
||||||
|
{
|
||||||
|
if (url.Equals(url))
|
||||||
|
{
|
||||||
|
return "<a href=\".*\">(?<name>.*)</a>"; //problem with the .exe.config file
|
||||||
|
}
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AskForHLFolder()
|
||||||
|
{
|
||||||
|
string folderPath = "";
|
||||||
|
var dialog = new System.Windows.Forms.OpenFileDialog();
|
||||||
|
|
||||||
|
dialog.InitialDirectory = Util.GetHLFolder();
|
||||||
|
dialog.Filter = "Half life Executable|hl.exe";
|
||||||
|
|
||||||
|
dialog.Title = "Please indicate where is your Half Life steam executable !";
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
||||||
|
{
|
||||||
|
folderPath = dialog.FileName;
|
||||||
|
folderPath = folderPath.Remove(folderPath.Length + 1 - 8);
|
||||||
|
return folderPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Util.PlaySoundFX("error");
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("This launcher need your half life directory in order to function. Please relaunch.", "Alert", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
|
||||||
|
folderPath = null;
|
||||||
|
return folderPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LauncherManifest GetIgnoreManifest(bool isVerification)
|
||||||
|
{
|
||||||
|
// we first get the ignore.list used by dev
|
||||||
|
string IgnorePath = Launcher.curDir + Path.DirectorySeparatorChar + "ignore.list";
|
||||||
|
LauncherManifest NewManifest = new LauncherManifest();
|
||||||
|
|
||||||
|
if (File.Exists(IgnorePath) && isVerification) //then we can use the one in the folder. That's ok
|
||||||
|
{
|
||||||
|
string IgnoreString = File.ReadAllText(IgnorePath);
|
||||||
|
NewManifest = JsonConvert.DeserializeObject<LauncherManifest>(IgnoreString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (WebClient webClient = new WebClient()) // yeah I know it's brutal :D
|
||||||
|
{
|
||||||
|
webClient.DownloadFile(new Uri(Properties.Settings.Default.IndexURL + "/ignore.list"), IgnorePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
string IgnoreString = File.ReadAllText(IgnorePath);
|
||||||
|
NewManifest = JsonConvert.DeserializeObject<LauncherManifest>(IgnoreString);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
/*MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Could not retrieve a new ignore manifest file, Creating a void one...");
|
||||||
|
NewManifest.Files["/config.cfg"] = "";*/
|
||||||
|
Util.PlaySoundFX("error");
|
||||||
|
MessageBoxResult AlertBox = System.Windows.MessageBox.Show("Launcher couldn't find a correct ignore.list from online source, please verify you internet connection..."
|
||||||
|
, "Alert", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
|
||||||
|
throw new Exception("Launcher couldn't find a correct ignore.list from online source, please verify you internet connection...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// then we read the custom one on the disk
|
||||||
|
string CustomIgnorePath = Launcher.curDir + Path.DirectorySeparatorChar + "customignore.list";
|
||||||
|
LauncherManifest CustomignoreManifest = new LauncherManifest();
|
||||||
|
|
||||||
|
if (File.Exists(CustomIgnorePath))
|
||||||
|
{
|
||||||
|
string IgnoreString = File.ReadAllText(CustomIgnorePath);
|
||||||
|
CustomignoreManifest = JsonConvert.DeserializeObject<LauncherManifest>(IgnoreString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CustomignoreManifest.Files["/exemple.xpl"] = "1";
|
||||||
|
|
||||||
|
File.WriteAllText(CustomIgnorePath, JsonConvert.SerializeObject(CustomignoreManifest, Formatting.Indented)); //write the new voidy ignore manifest
|
||||||
|
}
|
||||||
|
|
||||||
|
// then we add both manifest to return the ignore list
|
||||||
|
foreach(KeyValuePair<string, string> kv in CustomignoreManifest.Files)
|
||||||
|
{
|
||||||
|
NewManifest.Files.Add(kv.Key, kv.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewManifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CopyDirectory(string SourcePath, string DestinationPath) //not used anymore.
|
||||||
|
{
|
||||||
|
//Now Create all of the directories
|
||||||
|
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*",
|
||||||
|
SearchOption.AllDirectories))
|
||||||
|
Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
|
||||||
|
|
||||||
|
ConsoleManager.Show();
|
||||||
|
//Copy all the files & Replaces any files with the same name
|
||||||
|
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*",
|
||||||
|
SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
/*string newdirr = Path.GetDirectoryName(newPath);
|
||||||
|
if (!newdirr.Contains("sound") || !newPath.Contains("maps") || !newPath.Contains("dlls") || !newPath.Contains("cl_dlls"))
|
||||||
|
{*/
|
||||||
|
Console.WriteLine(Path.GetFileName(newPath) + " being copied...");
|
||||||
|
File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), true);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleManager.Hide();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ZipDirectory(string SourceDirPath)
|
||||||
|
{
|
||||||
|
ConsoleManager.Show();
|
||||||
|
Console.WriteLine("Ziping directory...");
|
||||||
|
Console.WriteLine("This can take up to 2 minutes, please wait...");
|
||||||
|
ZipFile.CreateFromDirectory(SourceDirPath, SourceDirPath + "_saved.zip", CompressionLevel.Optimal,false);
|
||||||
|
Console.WriteLine("Ziping done !");
|
||||||
|
ConsoleManager.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool GetAValueInCfg(string ValueName, out string Value)
|
||||||
|
{
|
||||||
|
string[] CfgLines = File.ReadAllLines(Launcher.NSFolder + Path.DirectorySeparatorChar + "config.cfg");
|
||||||
|
string[] UCfgLines = File.ReadAllLines(Launcher.NSFolder + Path.DirectorySeparatorChar + "userconfig.cfg");
|
||||||
|
bool found = false;
|
||||||
|
Value = "not found";
|
||||||
|
|
||||||
|
// first we look in the config.cfg then we will look in userconfig and keep its value if it exists (as it's the last cfg executed)
|
||||||
|
foreach (string Line in CfgLines)
|
||||||
|
{
|
||||||
|
if(Line.StartsWith(ValueName))
|
||||||
|
{
|
||||||
|
Value = Line.Remove(0, ValueName.Length + 2); //on enleve tout le debut et le premier guillemet
|
||||||
|
Value = Value.Remove(Value.Length - 1, 1); // et le dernier
|
||||||
|
found = true;
|
||||||
|
//initialInt = Convert.ToInt32(initialValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's the userconfig, take that instead
|
||||||
|
foreach (string Line in UCfgLines)
|
||||||
|
{
|
||||||
|
if (Line.StartsWith(ValueName))
|
||||||
|
{
|
||||||
|
Value = Line.Remove(0, ValueName.Length + 2); //on enleve tout le debut et le premier guillemet
|
||||||
|
Value = Value.Remove(Value.Length - 1, 1); // et le dernier
|
||||||
|
found = true;
|
||||||
|
//initialInt = Convert.ToInt32(initialValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ChangeAValueInCfg(string ValueName,string Value,bool isStrictToConfig = false)
|
||||||
|
{
|
||||||
|
string[] CfgLines = File.ReadAllLines(Launcher.NSFolder + Path.DirectorySeparatorChar + "config.cfg");
|
||||||
|
string[] UCfgLines = File.ReadAllLines(Launcher.NSFolder + Path.DirectorySeparatorChar + "userconfig.cfg");
|
||||||
|
bool cfgchange = false;
|
||||||
|
bool ucfgchange = false;
|
||||||
|
bool found = false;
|
||||||
|
int loopindex = 0;
|
||||||
|
// first we look in the config.cfg then we will look in userconfig and keep its value if it exists (as it's the last cfg executed)
|
||||||
|
foreach (string Line in CfgLines)
|
||||||
|
{
|
||||||
|
if (Line.StartsWith(ValueName))
|
||||||
|
{
|
||||||
|
CfgLines[loopindex] = ValueName + " " + "\"" + Value + "\"";
|
||||||
|
found = true;
|
||||||
|
cfgchange = true;
|
||||||
|
}
|
||||||
|
loopindex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStrictToConfig) //if should only be in config.cfg, let's verify it's not in usercfg
|
||||||
|
{
|
||||||
|
loopindex = 0;
|
||||||
|
foreach (string Line in UCfgLines)
|
||||||
|
{
|
||||||
|
if (Line.StartsWith(ValueName))
|
||||||
|
{
|
||||||
|
UCfgLines[loopindex] = ""; //we remove the doublon
|
||||||
|
ucfgchange = true;
|
||||||
|
}
|
||||||
|
loopindex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isStrictToConfig) //we can check usercfg
|
||||||
|
{
|
||||||
|
loopindex = 0;
|
||||||
|
foreach (string Line in UCfgLines)
|
||||||
|
{
|
||||||
|
if (Line.StartsWith(ValueName))
|
||||||
|
{
|
||||||
|
UCfgLines[loopindex] = ValueName + " " + "\"" + Value + "\"";
|
||||||
|
found = true;
|
||||||
|
ucfgchange = true;
|
||||||
|
}
|
||||||
|
loopindex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found && !isStrictToConfig) //we didnt find it, let's add it to usercfg!
|
||||||
|
{
|
||||||
|
Array.Resize(ref UCfgLines, UCfgLines.Length + 1);
|
||||||
|
UCfgLines[UCfgLines.Length - 1] = ValueName + " " + "\"" + Value + "\"";
|
||||||
|
ucfgchange = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found && isStrictToConfig) //we didnt find it, let's add it to config cfg !
|
||||||
|
{
|
||||||
|
Array.Resize(ref CfgLines, CfgLines.Length + 1);
|
||||||
|
CfgLines[CfgLines.Length - 1] = ValueName + " " + "\"" + Value + "\"";
|
||||||
|
cfgchange = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ecrire le deux fichiers à l'emplacement source !
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(cfgchange)
|
||||||
|
{
|
||||||
|
File.WriteAllLines(Launcher.NSFolder + Path.DirectorySeparatorChar + "config.cfg", CfgLines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show("Could not write config.cfg, please verify the file is not read only !", "Read only", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (ucfgchange)
|
||||||
|
{
|
||||||
|
File.WriteAllLines(Launcher.NSFolder + Path.DirectorySeparatorChar + "userconfig.cfg", UCfgLines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
System.Windows.MessageBox.Show("Could not write userconfig.cfg, please verify the file is not read only !" + Environment.NewLine +
|
||||||
|
"This problem may also be caused by a hud_style setting in your userconfig.cfg file !", "Read only", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LaunchAgain(string PathToExe)
|
||||||
|
{
|
||||||
|
ProcessStartInfo processInfo = new ProcessStartInfo();
|
||||||
|
processInfo.WorkingDirectory = Path.GetDirectoryName(PathToExe);
|
||||||
|
processInfo.FileName = Path.GetFileName(PathToExe);
|
||||||
|
processInfo.ErrorDialog = true;
|
||||||
|
processInfo.UseShellExecute = false;
|
||||||
|
processInfo.RedirectStandardOutput = true;
|
||||||
|
processInfo.RedirectStandardError = true;
|
||||||
|
Process proc = Process.Start(processInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PlaySoundFX(string Type) //now only play when error because whiners
|
||||||
|
{
|
||||||
|
Uri resourceUri = new Uri("Ressources/sdx_error.wav", UriKind.Relative);
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case "error":
|
||||||
|
resourceUri = new Uri("Ressources/sdx_error.wav", UriKind.Relative);
|
||||||
|
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
|
||||||
|
|
||||||
|
System.Media.SoundPlayer player = new System.Media.SoundPlayer(streamInfo.Stream);
|
||||||
|
player.Play();
|
||||||
|
break;
|
||||||
|
case "start":
|
||||||
|
resourceUri = new Uri("Ressources/sdx_started.wav", UriKind.Relative);
|
||||||
|
break;
|
||||||
|
case "finish":
|
||||||
|
resourceUri = new Uri("Ressources/sdx_finished.wav", UriKind.Relative);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resourceUri = new Uri("Ressources/sdx_error.wav", UriKind.Relative);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
131
NaturalLauncher/XmlBuilder.cs
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Natural Launcher
|
||||||
|
|
||||||
|
Copyright (C) 2018 Mael "Khelben" Vignaux
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
You can contact me with any question at the mail : mael.vignaux@elseware-experience.com
|
||||||
|
*/
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace NaturalLauncher
|
||||||
|
{
|
||||||
|
class XmlBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
public static bool BuildXmlDocument(string ManifestRootPath)
|
||||||
|
{
|
||||||
|
DirectoryInfo dir = new DirectoryInfo(ManifestRootPath);
|
||||||
|
var doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"),
|
||||||
|
StartCreateXML(dir));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.WriteAllText(ManifestRootPath + Path.DirectorySeparatorChar + "Manifest.xml", doc.ToString()); //write the new voidy ignore manifest
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XElement StartCreateXML(DirectoryInfo dir) // create a full directory xml
|
||||||
|
{
|
||||||
|
var xmlInfo = new XElement("MainDirectory");
|
||||||
|
//get all the files first
|
||||||
|
foreach (var file in dir.GetFiles())
|
||||||
|
{
|
||||||
|
xmlInfo.Add(new XElement("file", new XAttribute("name", file.Name)));
|
||||||
|
}
|
||||||
|
//get subdirectories
|
||||||
|
var subdirectories = dir.GetDirectories().ToList().OrderBy(d => d.Name);
|
||||||
|
foreach (var subDir in subdirectories)
|
||||||
|
{
|
||||||
|
xmlInfo.Add(CreateSubdirectoryXML(subDir));
|
||||||
|
}
|
||||||
|
return xmlInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static XElement CreateSubdirectoryXML(DirectoryInfo dir)
|
||||||
|
{
|
||||||
|
//get directories
|
||||||
|
var xmlInfo = new XElement("folder", new XAttribute("name", dir.Name));
|
||||||
|
//get all the files first
|
||||||
|
foreach (var file in dir.GetFiles())
|
||||||
|
{
|
||||||
|
xmlInfo.Add(new XElement("file", new XAttribute("name", file.Name)));
|
||||||
|
}
|
||||||
|
//get subdirectories
|
||||||
|
var subdirectories = dir.GetDirectories().ToList().OrderBy(d => d.Name);
|
||||||
|
foreach (var subDir in subdirectories)
|
||||||
|
{
|
||||||
|
xmlInfo.Add(CreateSubdirectoryXML(subDir));
|
||||||
|
}
|
||||||
|
return xmlInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ReadConfigXml(out string HLFolder, out bool IsNlPack, out string customDiscordStatus, out bool keepLauncherAlive)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
doc.Load(Launcher.curDir + Path.DirectorySeparatorChar + Launcher.configName);
|
||||||
|
XmlNodeList nodelist = doc.SelectNodes("/LauncherConfiguration");
|
||||||
|
HLFolder = doc.SelectSingleNode("//HLFolder").InnerText;
|
||||||
|
IsNlPack = doc.SelectSingleNode("//NLPack").InnerText == "True";
|
||||||
|
customDiscordStatus = doc.SelectSingleNode("//DiscordStatus").InnerText;
|
||||||
|
keepLauncherAlive = doc.SelectSingleNode("//keeplauncherAlive").InnerText == "True";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
HLFolder = "";
|
||||||
|
IsNlPack = false;
|
||||||
|
customDiscordStatus = "Gather forming";
|
||||||
|
keepLauncherAlive = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CreateConfigXml()
|
||||||
|
{
|
||||||
|
var xmlInfo = new XElement("LauncherConfiguration");
|
||||||
|
xmlInfo.Add(new XElement("HLFolder", Launcher.HLFolder));
|
||||||
|
xmlInfo.Add(new XElement("NLPack", "False"/*Launcher.IsNLPack().ToString()*/)); //doesnt matter anymore, also, can't use this function cause it asks for the config file...
|
||||||
|
xmlInfo.Add(new XElement("DiscordStatus", Launcher.discordCustomStatus));
|
||||||
|
xmlInfo.Add(new XElement("keeplauncherAlive", Launcher.keepLauncherAlive.ToString()));
|
||||||
|
|
||||||
|
var doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), xmlInfo);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.WriteAllText(Launcher.curDir + Path.DirectorySeparatorChar + Launcher.configName, doc.ToString()); //write the new voidy ignore manifest
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
BIN
NaturalLauncher/nsl_icon.ico
Normal file
After Width: | Height: | Size: 27 KiB |
6
NaturalLauncher/packages.config
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="HtmlAgilityPack" version="1.8.5" targetFramework="net462" />
|
||||||
|
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net462" />
|
||||||
|
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net462" />
|
||||||
|
</packages>
|
BIN
NslKey.cer
Normal file
32
README.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# NaturalLauncher
|
||||||
|
|
||||||
|
*Natural selection launcher and updater. Allows for quick update of the natural selection folder.
|
||||||
|
|
||||||
|
|
||||||
|
#TO BUILD FROM SOURCES
|
||||||
|
*If you are building from sources, I imagine you don't want the .exe file to permanantly check for online consistency (public key required) nor self update.
|
||||||
|
*In order to do so, simply go in SelfUpdater.cs and set the variable "isSelfUpdating" to false.
|
||||||
|
*You are basicaly good to go !
|
||||||
|
|
||||||
|
#CHANGE THE ONLINE FILES THE LAUNCHER REFERS TO
|
||||||
|
*If you want you own files online, simply change, in the configuration setting of the natural launcher projet in VS, the IndexURL to your custom URL
|
||||||
|
*as well as the GameUrl to the game URL (sounds logical enough ?)
|
||||||
|
|
||||||
|
#TO COMMIT A NEW NS VERSION / PATCH
|
||||||
|
|
||||||
|
##FROM THE LAUNCHER:
|
||||||
|
*1 - Launch the launcher (tricky sentence)
|
||||||
|
*2 - Verify it has the right half life folder target
|
||||||
|
*3 - Right click in the launcher
|
||||||
|
*4 - Build Manifest
|
||||||
|
|
||||||
|
##FROM THE MANIFESTBUILDER.EXE
|
||||||
|
*1 - Place the manifestbuilder.exe app in the correct folder
|
||||||
|
*2 - Execute it
|
||||||
|
*3 - Enjoy
|
||||||
|
*4 - Really do it
|
||||||
|
|
||||||
|
##THEN
|
||||||
|
*5 - Upload files in the "Game" Folder of the ftp
|
||||||
|
*6 - Upload the manifest in the root folder.
|
||||||
|
*7 - Update the app.version with the new number in root folder
|