Compare commits

...

18 commits

Author SHA1 Message Date
Junior
d45726a46b Update README.md 2025-04-29 17:21:18 -03:00
Junior
1692923e18 Changes for RustyHearts-API 1.3.0 2025-04-29 17:14:19 -03:00
Hamilton
558761943e
Bump Microsoft.Web.WebView2 from 1.0.2903.40 to 1.0.3179.45
Bump Microsoft.Web.WebView2 from 1.0.2903.40 to 1.0.3179.45
2025-04-08 08:40:06 -03:00
dependabot[bot]
5be5ff2e10
Bump Microsoft.Web.WebView2 from 1.0.2903.40 to 1.0.3179.45
Bumps Microsoft.Web.WebView2 from 1.0.2903.40 to 1.0.3179.45.

---
updated-dependencies:
- dependency-name: Microsoft.Web.WebView2
  dependency-version: 1.0.3179.45
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 13:48:40 +00:00
Junior
8526698244 Refactor zip handling for System.IO.Compression 2024-11-28 07:51:57 -03:00
Junior
9fb4b4a6af Update release.yml 2024-11-27 00:42:24 -03:00
Junior
7849b2001a Updated dependencies
Replaced deprecated DotNetZip with System.IO.Compression.
Changed target framework to net 9.0.
Removed DotNetZip package reference.
Updated Microsoft.Web.WebView2 to 1.0.2903.40.
Updated WindowsAPICodePack to 8.0.6.
2024-11-27 00:28:46 -03:00
Hamilton
3648b49bb3
Bump WindowsAPICodePack from 7.0.4 to 8.0.4
Bump WindowsAPICodePack from 7.0.4 to 8.0.4
2024-06-11 13:41:59 -03:00
Hamilton
6d31e23124
Bump Microsoft.Web.WebView2 from 1.0.2365.46 to 1.0.2535.41
Bump Microsoft.Web.WebView2 from 1.0.2365.46 to 1.0.2535.41
2024-06-11 13:41:46 -03:00
dependabot[bot]
56973cf95f
Bump WindowsAPICodePack from 7.0.4 to 8.0.4
Bumps [WindowsAPICodePack](https://github.com/Wagnerp/Windows-API-CodePack-NET) from 7.0.4 to 8.0.4.
- [Changelog](https://github.com/Wagnerp/Windows-API-CodePack-NET/blob/main/Changelog.md)
- [Commits](https://github.com/Wagnerp/Windows-API-CodePack-NET/commits)

---
updated-dependencies:
- dependency-name: WindowsAPICodePack
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 12:25:20 +00:00
dependabot[bot]
5baa8daa62
Bump Microsoft.Web.WebView2 from 1.0.2365.46 to 1.0.2535.41
Bumps Microsoft.Web.WebView2 from 1.0.2365.46 to 1.0.2535.41.

---
updated-dependencies:
- dependency-name: Microsoft.Web.WebView2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 13:05:14 +00:00
Hamilton
a0c4fd7a5e
Bump Microsoft.Web.WebView2 from 1.0.2210.55 to 1.0.2365.46
Bump Microsoft.Web.WebView2 from 1.0.2210.55 to 1.0.2365.46
2024-03-12 16:47:22 -03:00
dependabot[bot]
30a30145bc
Bump Microsoft.Web.WebView2 from 1.0.2210.55 to 1.0.2365.46
Bumps Microsoft.Web.WebView2 from 1.0.2210.55 to 1.0.2365.46.

---
updated-dependencies:
- dependency-name: Microsoft.Web.WebView2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 12:09:16 +00:00
Junior
e74d93fab9 Version 1.2.0 2024-01-04 22:59:30 -03:00
Junior
9b3a0e00a2
Merge pull request #10 from JuniorDark/dependabot/github_actions/actions/setup-dotnet-4
Bump actions/setup-dotnet from 3 to 4
2023-12-17 22:27:06 -03:00
dependabot[bot]
6431d0f0cd
Bump actions/setup-dotnet from 3 to 4
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3 to 4.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 12:16:43 +00:00
Junior
9c2b46b0d6
Merge pull request #9 from JuniorDark/dependabot/nuget/Microsoft.Web.WebView2-1.0.2151.40
Bump Microsoft.Web.WebView2 from 1.0.2045.28 to 1.0.2151.40
2023-12-05 12:34:25 -03:00
dependabot[bot]
300530e657
Bump Microsoft.Web.WebView2 from 1.0.2045.28 to 1.0.2151.40
Bumps Microsoft.Web.WebView2 from 1.0.2045.28 to 1.0.2151.40.

---
updated-dependencies:
- dependency-name: Microsoft.Web.WebView2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 12:47:53 +00:00
85 changed files with 110551 additions and 47681 deletions

View file

@ -6,19 +6,24 @@ on:
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v4
with:
dotnet-version: '7.0.x'
- name: Build
run: dotnet publish --configuration Release --self-contained false --runtime win-x86 /p:PublishSingleFile=true
- name: Zip output file
run: Compress-Archive -Path ./bin/Release/net7.0-windows7.0/win-x86/publish/Launcher.exe -DestinationPath Launcher.zip
dotnet-version: '9.0.x'
# Build with --self-contained false
- name: Build Rusty Hearts Launcher (No Self-Contained)
run: dotnet publish ./RHLauncher.sln --configuration Release --self-contained false --runtime win-x64 /p:PublishSingleFile=true /p:PublishDir=./publish/RustyHearts-Launcher_framework-dependent
- name: Zip output files (No Self-Contained)
run: Compress-Archive -Path "./publish/RustyHearts-Launcher_framework-dependent" -DestinationPath RustyHearts-Launcher.zip
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Launcher
path: Launcher.zip
path: RustyHearts-Launcher.zip

View file

@ -3,42 +3,50 @@ on:
workflow_dispatch:
release:
types: [created]
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '7.0.x'
- name: Get version from .csproj file
id: version
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
# Build with --self-contained false
- name: Build Rusty Hearts Launcher (No Self-Contained)
run: dotnet publish ./RHLauncher.sln --configuration Release --self-contained false --runtime win-x64 /p:PublishSingleFile=true /p:PublishDir=./publish/RustyHearts-Launcher_framework-dependent
- name: Zip output files (No Self-Contained)
run: Compress-Archive -Path "./publish/RustyHearts-Launcher_framework-dependent" -DestinationPath RustyHearts-Launcher-Framework-Dependent.zip
# Build with --self-contained true
- name: Build Rusty Hearts Launcher (Self-Contained)
run: dotnet publish ./RHLauncher.sln --configuration Release --self-contained true --runtime win-x64 /p:PublishSingleFile=false /p:PublishDir=./publish/RustyHearts-Launcher_self-contained
- name: Zip output files (Self-Contained)
run: Compress-Archive -Path "./publish/RustyHearts-Launcher_self-contained" -DestinationPath RustyHearts-Launcher-SelfContained.zip
- name: Get version from compiled assembly
id: version
run: |
echo "::set-output name=version::$(grep -m1 -o '<FileVersion>[^<]*' RHLauncher.csproj | sed 's/<FileVersion>//')"
- name: Build
run: dotnet publish --configuration Release --self-contained false --runtime win-x86 /p:PublishSingleFile=true
- name: Zip output file
run: Compress-Archive -Path ./bin/Release/net7.0-windows7.0/win-x86/publish/Launcher.exe -DestinationPath Launcher.zip
- name: Create Release
id: create_release
uses: actions/create-release@v1
$version = (Get-Command "./publish/RustyHearts-Launcher_self-contained/Launcher.dll").FileVersionInfo.FileVersion
echo "::set-output name=version::$version"
# Create Release and Upload Assets using softprops/action-gh-release
- name: Create GitHub Release and Upload Assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.version }}
release_name: v${{ steps.version.outputs.version }}
body: Automated release created by GitHub Actions.
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./Launcher.zip
asset_name: Launcher.zip
asset_content_type: application/zip
tag_name: v${{ steps.version.outputs.version }}
body: Automated pre-release created by GitHub Actions.
draft: true
prerelease: true
files: |
./RustyHearts-Launcher-Framework-Dependent.zip
./RustyHearts-Launcher-SelfContained.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

3
App.config Normal file
View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>

View file

@ -1,18 +0,0 @@
using System.Runtime.InteropServices;
namespace RHLauncher.DynamicLib
{
public static class NativeMethod
{
[DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
public static extern int LoadLibrary(
[MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
[DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
public static extern IntPtr GetProcAddress(int hModule,
[MarshalAs(UnmanagedType.LPStr)] string lpProcName);
[DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
public static extern bool FreeLibrary(int hModule);
}
}

View file

@ -1,73 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace RHLauncher.DynamicLib {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class ResourceDll {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal ResourceDll() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </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("RHLauncher.DynamicLib.ResourceDll", typeof(ResourceDll).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] ZlibDll {
get {
object obj = ResourceManager.GetObject("ZlibDll", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View file

@ -1,124 +0,0 @@
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
<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" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</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" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="ZlibDll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>ZlibDll.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View file

@ -1,39 +0,0 @@
using System.Runtime.InteropServices;
namespace RHLauncher.DynamicLib
{
public static class ZLibDll
{
//[DllImport("ZlibDll.dll", CallingConvention = CallingConvention.Cdecl)]
//public static extern int Decompress(byte[] compressed_buffer, int compressed_size, byte[] decompressed_buffer, ref int decompressed_size);
public delegate int DecompressDelegate(byte[] compressed_buffer, int compressed_size, byte[] decompressed_buffer, ref int decompressed_size);
public static DecompressDelegate? Decompress = null;
//[DllImport("ZlibDll.dll", CallingConvention = CallingConvention.Cdecl)]
//public static extern int Compress(byte[] decompressed_buffer, int decompressed_size, byte[] compressed_buffer, ref int compressed_size);
public delegate int CompressDelegate(byte[] decompressed_buffer, int decompressed_size, byte[] compressed_buffer, ref int compressed_size);
public static CompressDelegate? Compress = null;
static ZLibDll()
{
byte[] libBuffer = ResourceDll.ZlibDll;
string dllPath = Path.Combine(Path.GetTempPath(), "ZlibDll.dll");
try
{
File.WriteAllBytes(dllPath, libBuffer);
}
catch { }
int hModule = NativeMethod.LoadLibrary(dllPath);
if (hModule == 0) return;
IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "Decompress");
Decompress = (DecompressDelegate)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(DecompressDelegate));
intPtr = NativeMethod.GetProcAddress(hModule, "Compress");
Compress = (CompressDelegate)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(CompressDelegate));
}
}
}

Binary file not shown.

View file

@ -7,11 +7,13 @@ However, it requires further development to improve functionality and
ensure stability. Please check the GitHub repository for updates.
*/
using RHLauncher.RHLauncher.i8n;
namespace RHLauncher
{
internal static class Program
{
private static readonly Mutex mutex = new(false, "Launcher");
private static readonly Mutex mutex = new(false, "RHLauncher");
/// <summary>
/// The main entry point for the application.
/// </summary>
@ -29,7 +31,7 @@ namespace RHLauncher
}
else
{
MessageBox.Show("Only one instance of the launcher can run at a time.");
MessageBox.Show(LocalizedStrings.LauncherAlreadyRunning, LocalizedStrings.Error);
}
}
}

View file

@ -60,246 +60,6 @@ namespace RHLauncher.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap bg {
get {
object obj = ResourceManager.GetObject("bg", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_close_active {
get {
object obj = ResourceManager.GetObject("button_close_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_close_down {
get {
object obj = ResourceManager.GetObject("button_close_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_close_normal {
get {
object obj = ResourceManager.GetObject("button_close_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_login_active {
get {
object obj = ResourceManager.GetObject("button_login_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_login_active_ko {
get {
object obj = ResourceManager.GetObject("button_login_active_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_login_down {
get {
object obj = ResourceManager.GetObject("button_login_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_login_down_ko {
get {
object obj = ResourceManager.GetObject("button_login_down_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_login_normal {
get {
object obj = ResourceManager.GetObject("button_login_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_minimize_active {
get {
object obj = ResourceManager.GetObject("button_minimize_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_minimize_down {
get {
object obj = ResourceManager.GetObject("button_minimize_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_minimize_normal {
get {
object obj = ResourceManager.GetObject("button_minimize_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_register_active {
get {
object obj = ResourceManager.GetObject("button_register_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_register_active_ko {
get {
object obj = ResourceManager.GetObject("button_register_active_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_register_down {
get {
object obj = ResourceManager.GetObject("button_register_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_register_down_ko {
get {
object obj = ResourceManager.GetObject("button_register_down_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_register_normal {
get {
object obj = ResourceManager.GetObject("button_register_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap button_register_normal_ko {
get {
object obj = ResourceManager.GetObject("button_register_normal_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ChangePwwnd_button_email_active {
get {
object obj = ResourceManager.GetObject("ChangePwwnd_button_email_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ChangePwwnd_button_email_active_ko {
get {
object obj = ResourceManager.GetObject("ChangePwwnd_button_email_active_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ChangePwwnd_button_email_down {
get {
object obj = ResourceManager.GetObject("ChangePwwnd_button_email_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ChangePwwnd_button_email_down_ko {
get {
object obj = ResourceManager.GetObject("ChangePwwnd_button_email_down_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ChangePwwnd_button_email_normal {
get {
object obj = ResourceManager.GetObject("ChangePwwnd_button_email_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ChangePwwnd_button_email_normal_ko {
get {
object obj = ResourceManager.GetObject("ChangePwwnd_button_email_normal_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -389,355 +149,5 @@ namespace RHLauncher.Properties {
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap help_panel_bkg {
get {
object obj = ResourceManager.GetObject("help_panel_bkg", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap launchbutton_bkg_active {
get {
object obj = ResourceManager.GetObject("launchbutton_bkg_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap launchbutton_bkg_down {
get {
object obj = ResourceManager.GetObject("launchbutton_bkg_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap launchbutton_bkg_normal {
get {
object obj = ResourceManager.GetObject("launchbutton_bkg_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap launcher_bg {
get {
object obj = ResourceManager.GetObject("launcher_bg", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap launchoptionbutton_active {
get {
object obj = ResourceManager.GetObject("launchoptionbutton_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap launchoptionbutton_down {
get {
object obj = ResourceManager.GetObject("launchoptionbutton_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap launchoptionbutton_normal {
get {
object obj = ResourceManager.GetObject("launchoptionbutton_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap list_button_hover {
get {
object obj = ResourceManager.GetObject("list_button_hover", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap list_button_normal {
get {
object obj = ResourceManager.GetObject("list_button_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap login_bg {
get {
object obj = ResourceManager.GetObject("login_bg", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap menubutton_bkg_active {
get {
object obj = ResourceManager.GetObject("menubutton_bkg_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap menubutton_bkg_down {
get {
object obj = ResourceManager.GetObject("menubutton_bkg_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap menubutton_bkg_normal {
get {
object obj = ResourceManager.GetObject("menubutton_bkg_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap message_bkg {
get {
object obj = ResourceManager.GetObject("message_bkg", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap messagewnd_button_ok_active {
get {
object obj = ResourceManager.GetObject("messagewnd_button_ok_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap messagewnd_button_ok_active_ko {
get {
object obj = ResourceManager.GetObject("messagewnd_button_ok_active_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap messagewnd_button_ok_down {
get {
object obj = ResourceManager.GetObject("messagewnd_button_ok_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap messagewnd_button_ok_down_ko {
get {
object obj = ResourceManager.GetObject("messagewnd_button_ok_down_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap messagewnd_button_ok_normal {
get {
object obj = ResourceManager.GetObject("messagewnd_button_ok_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap messagewnd_button_ok_normal_ko {
get {
object obj = ResourceManager.GetObject("messagewnd_button_ok_normal_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwnd_button_continue_active {
get {
object obj = ResourceManager.GetObject("Registerwnd_button_continue_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwnd_button_continue_active_ko {
get {
object obj = ResourceManager.GetObject("Registerwnd_button_continue_active_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwnd_button_continue_down {
get {
object obj = ResourceManager.GetObject("Registerwnd_button_continue_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwnd_button_continue_down_ko {
get {
object obj = ResourceManager.GetObject("Registerwnd_button_continue_down_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwnd_button_continue_normal {
get {
object obj = ResourceManager.GetObject("Registerwnd_button_continue_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwnd_button_continue_normal_ko {
get {
object obj = ResourceManager.GetObject("Registerwnd_button_continue_normal_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwndwnd_button_sendemail_active {
get {
object obj = ResourceManager.GetObject("Registerwndwnd_button_sendemail_active", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwndwnd_button_sendemail_active_ko {
get {
object obj = ResourceManager.GetObject("Registerwndwnd_button_sendemail_active_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwndwnd_button_sendemail_down {
get {
object obj = ResourceManager.GetObject("Registerwndwnd_button_sendemail_down", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwndwnd_button_sendemail_down_ko {
get {
object obj = ResourceManager.GetObject("Registerwndwnd_button_sendemail_down_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwndwnd_button_sendemail_normal {
get {
object obj = ResourceManager.GetObject("Registerwndwnd_button_sendemail_normal", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Registerwndwnd_button_sendemail_normal_ko {
get {
object obj = ResourceManager.GetObject("Registerwndwnd_button_sendemail_normal_ko", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap tips_error {
get {
object obj = ResourceManager.GetObject("tips_error", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap tips_ok {
get {
object obj = ResourceManager.GetObject("tips_ok", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View file

@ -118,78 +118,6 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="bg" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bg\bg.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_close_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_close_active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_close_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_close_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_close_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_close_normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_login_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_login_active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_login_active_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_login_active_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_login_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_login_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_login_down_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_login_down_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_login_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_login_normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_minimize_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_minimize_active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_minimize_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_minimize_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_minimize_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_minimize_normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_register_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_register_active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_register_active_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_register_active_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_register_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_register_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_register_down_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_register_down_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_register_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_register_normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_register_normal_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\button_register_normal_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ChangePwwnd_button_email_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\ChangePwwnd.button.email.active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ChangePwwnd_button_email_active_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\ChangePwwnd_button_email_active_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ChangePwwnd_button_email_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\ChangePwwnd.button.email.down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ChangePwwnd_button_email_down_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\ChangePwwnd_button_email_down_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ChangePwwnd_button_email_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\ChangePwwnd.button.email.normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ChangePwwnd_button_email_normal_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\ChangePwwnd_button_email_normal_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="character_select_cut_angela" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bg\character_select_cut_angela.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -217,109 +145,4 @@
<data name="character_select_cut_tude" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bg\character_select_cut_tude.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="help_panel_bkg" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bg\help_panel_bkg.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="launchbutton_bkg_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\launchbutton_bkg_active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="launchbutton_bkg_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\launchbutton_bkg_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="launchbutton_bkg_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\launchbutton_bkg_normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="launcher_bg" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bg\launcher_bg.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="launchoptionbutton_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\launchoptionbutton_active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="launchoptionbutton_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\launchoptionbutton_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="launchoptionbutton_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\launchoptionbutton_normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="list_button_hover" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\list_button_hover.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="list_button_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\list_button_normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="login_bg" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bg\login_bg.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="menubutton_bkg_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\menubutton_bkg_active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="menubutton_bkg_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\menubutton_bkg_down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="menubutton_bkg_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\menubutton_bkg_normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="messagewnd_button_ok_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\messagewnd.button.ok.active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="messagewnd_button_ok_active_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\messagewnd.button.ok.active_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="messagewnd_button_ok_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\messagewnd.button.ok.down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="messagewnd_button_ok_down_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\messagewnd.button.ok.down_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="messagewnd_button_ok_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\messagewnd.button.ok.normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="messagewnd_button_ok_normal_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\messagewnd.button.ok.normal_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="message_bkg" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bg\message_bkg.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwndwnd_button_sendemail_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwndwnd.button.sendemail.active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwndwnd_button_sendemail_active_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwndwnd_button_sendemail_active_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwndwnd_button_sendemail_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwndwnd.button.sendemail.down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwndwnd_button_sendemail_down_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwndwnd_button_sendemail_down_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwndwnd_button_sendemail_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwndwnd.button.sendemail.normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwndwnd_button_sendemail_normal_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwndwnd_button_sendemail_normal_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwnd_button_continue_active" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwnd.button.continue.active.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwnd_button_continue_active_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwnd_button_continue_active_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwnd_button_continue_down" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwnd.button.continue.down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwnd_button_continue_down_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwnd_button_continue_down_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwnd_button_continue_normal" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwnd.button.continue.normal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Registerwnd_button_continue_normal_ko" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\buttons\Registerwnd_button_continue_normal_ko.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="tips_error" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons\tips_error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="tips_ok" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons\tips_ok.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -1,26 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace RHLauncher.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.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;
}
}
}
}

View file

@ -1,6 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
</SettingsFile>

View file

@ -23,15 +23,13 @@ Rusty Hearts Launcher is a custom launcher for the Rusty Hearts game client. It
* [Prerequisites for Building Locally/Development](#prerequisites-for-building-locallydevelopment)
* [System Requirements for Ready-to-use build](#system-requirements-for-ready-to-use-build)
* [License](#license)
* [Contributing](#contributing)
* [FAQ](#faq)
* [Building](#building)
* [Credits](#credits)
* [Support](#support)
* [Roadmap](#roadmap)
## Features
* Game Download: The launcher can download and install the client.
* Game Update: The launcher can automatically download and install game updates.
* Self-updating: The launcher can automatically update itself to the latest version.
* Automatic game update: The launcher can automatically download and install updates.
* Register account: Users can register a new account/change the password directly from the launcher.
* News window: The launcher displays the latest news and updates about the game.
@ -39,29 +37,32 @@ Rusty Hearts Launcher is a custom launcher for the Rusty Hearts game client. It
The launcher require the [Rusty Hearts API](https://github.com/JuniorDark/RustyHearts-API) to work. See the api documentation for instructions on setup.
### API URL
In order for the launcher to work it need to be conected to the api. To change the URL address of the launcher API open the Config.ini (it will be created when opening the launcher for the first time).
The default URL for the api can be changed on IniFile.cs
### Client region
The client region can be set on Service on Config.ini
The client region can be set on Config.ini or in the Config menu
* **Jpn** (SEGA) - Full api support
* **usa** (PWE) - Full api support
* **chn** (Xunlei) - Only launcher support
### Launcher self-update
In order for the launcher to automatically update itself, you need to use the launcher_info.ini in the `launcher_update` directory of the api. This file specifies the version of the launcher. After each update of the launcher, you need to change the version in the ini, as well in the launcher executable file.
### Client patch
### Client download
In order to download the client, you need to use the `client\download` directory of the api.
The tool for creating the client files is available in the repository: https://github.com/JuniorDark/RustyHearts-MIPTool
### Client patch
In order to create client patches, you need to use the `patch` directory of the api.
The tool for creating the patch files is available in the repository: https://github.com/JuniorDark/RustyHearts-MIPTool
### Launcher Language
The launcher language can be set on `Lang` on Config.ini
The launcher language can be changed on `Lang` on Config.ini or in the Config menu
* **en** - English (en-US) default language
* **ko** - Korean ("ko-KR) (Machine Translated)
@ -71,38 +72,37 @@ If you want to add a new language create a LocalizedStrings.<language>.resx with
If you want to change the text on the buttons/images used in the launcher you can use the Photoshop .psd files included in the PSD Resources.rar
## Prerequisites for Building Locally/Development
The launcher is built in .NET 7 and as such, the packages listed below are required to create a local and development build of the launcher. Furthermore, it uses many submodules and packages outside of this, which will automatically be loaded when the user sets up a local environment of the application.
* Visual Studio 2022 (Any Edition - 17.4 or later)
* Windows 10 SDK (10.0.19043.0) or Windows 11 SDK (10.0.22000.0) via Visual Studio Installer
* .NET: [.NET Core 7 SDK (7.0.100 or later)](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)
## Prerequisites for Development
* Visual Studio 2022 (Any Edition - 17.12 or later)
* Windows 10 SDK or Windows 11 SDK via Visual Studio Installer
* .NET Core 9 SDK (9.0.100 or later)
## System Requirements for Ready-to-use build
* OS: Windows 10 1809 Update (build 17763) or later / Windows 11 (Any builds)
* Architecture: x64/AMD64
## Building
If you wish to build the project yourself, follow these steps:
### Step 1
Install the [.NET 9.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/9.0).
Make sure your SDK version is higher or equal to the required version specified.
### Step 2
Either use `git clone https://github.com/JuniorDark/RustyHearts-Launcher` on the command line to clone the repository or use Code --> Download zip button to get the files.
### Step 3
To build Rusty Hearts Launcher, open a command prompt inside the project directory.
You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`.
Then type the following command: `dotnet build -c Release`.
The built files will be found in the newly created `bin` build directory.
## License
This project is licensed under the terms found in [`LICENSE-0BSD`](LICENSE).
## Contributing
Contributions from the community are welcome! If you encounter a bug or have a feature request, please submit an issue on GitHub. If you would like to contribute code, please fork the repository and submit a pull request.
## FAQ
* Q: How do I report a bug?
* A: Please submit an issue on GitHub with a detailed description of the bug and steps to reproduce it.
* Q: How do I request a new feature?
* A: Please submit an issue on GitHub with a detailed description of the feature and why it would be useful.
* Q: How do I contribute code?
* A: Please fork the repository, make your changes, and submit a pull request.
## Credits
The following third-party libraries, tools, and resources are used in this project:
* [Microsoft.Web.WebView2](https://www.nuget.org/packages/Microsoft.Web.WebView2)
* [Newtonsoft.Json](https://www.nuget.org/packages/Newtonsoft.Json)
## Support
If you need help with the launcher, please submit an issue on GitHub.
## Roadmap
* Add support for client download/repair
* Improve performance and stability
* [WindowsAPICodePack](https://www.nuget.org/packages/WindowsAPICodePack)

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
namespace RHLauncher
{
partial class ChangePwd
partial class ChangePwdForm
{
/// <summary>
/// Required designer variable.
@ -29,7 +29,7 @@
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ChangePwd));
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ChangePwdForm));
CloseButton = new Button();
imageListCloseBtn = new ImageList(components);
MinimizeButton = new Button();
@ -95,9 +95,9 @@
CloseButton.TabIndex = 9;
CloseButton.UseVisualStyleBackColor = false;
CloseButton.Click += CloseButton_Click;
CloseButton.MouseDown += CloseButton_OnMouseDown;
CloseButton.MouseLeave += CloseButton_MouseLeave;
CloseButton.MouseHover += CloseButton_MouseHover;
CloseButton.MouseDown += Button_MouseDown;
CloseButton.MouseLeave += Button_MouseLeave;
CloseButton.MouseHover += Button_MouseHover;
//
// imageListCloseBtn
//
@ -125,9 +125,9 @@
MinimizeButton.TabIndex = 8;
MinimizeButton.UseVisualStyleBackColor = false;
MinimizeButton.Click += MinimizeButton_Click;
MinimizeButton.MouseDown += MinimizeButton_OnMouseDown;
MinimizeButton.MouseLeave += MinimizeButton_MouseLeave;
MinimizeButton.MouseHover += MinimizeButton_MouseHover;
MinimizeButton.MouseDown += Button_MouseDown;
MinimizeButton.MouseLeave += Button_MouseLeave;
MinimizeButton.MouseHover += Button_MouseHover;
//
// imageListMinBtn
//
@ -180,9 +180,9 @@
ContinueButtonS1.TabIndex = 16;
ContinueButtonS1.UseVisualStyleBackColor = false;
ContinueButtonS1.Click += ContinueButtonS1_Click;
ContinueButtonS1.MouseDown += ContinueButtonS1_OnMouseDown;
ContinueButtonS1.MouseLeave += ContinueButtonS1_MouseLeave;
ContinueButtonS1.MouseHover += ContinueButtonS1_MouseHover;
ContinueButtonS1.MouseDown += Button_MouseDown;
ContinueButtonS1.MouseLeave += Button_MouseLeave;
ContinueButtonS1.MouseHover += Button_MouseHover;
//
// imageListContinueBtn
//
@ -242,9 +242,9 @@
SendEmailButton.TabIndex = 21;
SendEmailButton.UseVisualStyleBackColor = false;
SendEmailButton.Click += SendEmailButton_Click;
SendEmailButton.MouseDown += SendEmailButton_OnMouseDown;
SendEmailButton.MouseLeave += SendEmailButton_MouseLeave;
SendEmailButton.MouseHover += SendEmailButton_MouseHover;
SendEmailButton.MouseDown += Button_MouseDown;
SendEmailButton.MouseLeave += Button_MouseLeave;
SendEmailButton.MouseHover += Button_MouseHover;
//
// imageListSendEmailBtn
//
@ -506,6 +506,7 @@
ReturnLabelS2.AutoEllipsis = true;
ReturnLabelS2.AutoSize = true;
ReturnLabelS2.BackColor = Color.Transparent;
ReturnLabelS2.Cursor = Cursors.Hand;
ReturnLabelS2.Font = new Font("Segoe UI", 10F, FontStyle.Bold, GraphicsUnit.Point);
ReturnLabelS2.ForeColor = Color.Gainsboro;
ReturnLabelS2.ImeMode = ImeMode.NoControl;
@ -516,8 +517,8 @@
ReturnLabelS2.Text = "< Return";
ReturnLabelS2.TextAlign = ContentAlignment.TopCenter;
ReturnLabelS2.Click += ReturnLabel_Click;
ReturnLabelS2.MouseLeave += ReturnLabelS2_MouseLeave;
ReturnLabelS2.MouseHover += ReturnLabelS2_MouseHover;
ReturnLabelS2.MouseLeave += Label_MouseLeave;
ReturnLabelS2.MouseHover += Label_MouseHover;
//
// OkButtonS2
//
@ -535,9 +536,9 @@
OkButtonS2.TabIndex = 26;
OkButtonS2.UseVisualStyleBackColor = false;
OkButtonS2.Click += OkButtonS2_Click;
OkButtonS2.MouseDown += OkButtonS2_OnMouseDown;
OkButtonS2.MouseLeave += OkButtonS2_MouseLeave;
OkButtonS2.MouseHover += OkButtonS2_MouseHover;
OkButtonS2.MouseDown += Button_MouseDown;
OkButtonS2.MouseLeave += Button_MouseLeave;
OkButtonS2.MouseHover += Button_MouseHover;
//
// PasswordTextBox
//
@ -624,12 +625,12 @@
imageListOKBtn_ko.Images.SetKeyName(1, "messagewnd.button.ok.active.png");
imageListOKBtn_ko.Images.SetKeyName(2, "messagewnd.button.ok.down.png");
//
// ChangePwd
// ChangePwdForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = Color.Black;
BackgroundImage = Properties.Resources.bg;
BackgroundImage = (Image)resources.GetObject("$this.BackgroundImage");
BackgroundImageLayout = ImageLayout.Center;
ClientSize = new Size(800, 571);
Controls.Add(CloseButton);
@ -639,7 +640,7 @@
DoubleBuffered = true;
FormBorderStyle = FormBorderStyle.None;
Icon = (Icon)resources.GetObject("$this.Icon");
Name = "ChangePwd";
Name = "ChangePwdForm";
StartPosition = FormStartPosition.CenterScreen;
Text = "Change Password";
FormClosing += ChangePwd_FormClosing;

View file

@ -1,29 +1,27 @@
using RHLauncher.Helper;
using RHLauncher.RHLauncher;
using Newtonsoft.Json;
using RHLauncher.RHLauncher.Helper;
using RHLauncher.RHLauncher.i8n;
using System.Text.RegularExpressions;
namespace RHLauncher
{
public partial class ChangePwd : Form
public partial class ChangePwdForm : Form
{
private RegistryHandler registryHandler = new();
public string SendPasswordCodeUrl = Configuration.Default.SendPasswordCodeUrl;
public string VerifyCodeUrl = Configuration.Default.VerifyCodeUrl;
public string ChangePasswordUrl = Configuration.Default.ChangePasswordUrl;
public string Lang = Configuration.Default.Lang;
private readonly string SendPasswordCodeUrl = Configuration.Default.SendPasswordCodeUrl;
private readonly string VerifyCodeUrl = Configuration.Default.VerifyCodeUrl;
private readonly string ChangePasswordUrl = Configuration.Default.ChangePasswordUrl;
private readonly string Lang = Configuration.Default.Lang;
private List<Button>? buttons;
private List<ImageList>? imageLists;
private Dictionary<string, List<ImageList>>? languageImageLists;
private readonly System.Windows.Forms.Timer resendTimer = new();
private int secondsLeft = 60;
private readonly bool _shouldRestart;
public ChangePwd(bool shouldRestart = false)
public ChangePwdForm(bool shouldRestart = false)
{
InitializeComponent();
@ -39,7 +37,7 @@ namespace RHLauncher
LoadLocalizedStrings();
Text = LocalizedStrings.RegFormTitle;
Text = LocalizedStrings.ChangePwdFormTitle;
TitleLabelS1.Text = LocalizedStrings.ChangePassword;
TitleLabelS2.Text = LocalizedStrings.ChangePassword;
SubTitleLabelS1.Text = LocalizedStrings.RustyHearts;
@ -57,32 +55,49 @@ namespace RHLauncher
private void LoadLocalizedStrings()
{
// Initialize buttons and image lists
buttons = new List<Button> { ContinueButtonS1, SendEmailButton, OkButtonS2 };
imageLists = new List<ImageList> { imageListContinueBtn, imageListSendEmailBtn, imageListOKBtn };
buttons = [ContinueButtonS1, SendEmailButton, OkButtonS2];
imageLists = [imageListContinueBtn, imageListSendEmailBtn, imageListOKBtn];
// Initialize language-specific image lists
languageImageLists = new Dictionary<string, List<ImageList>>
{
{ "en", new List<ImageList> { imageListContinueBtn, imageListSendEmailBtn, imageListOKBtn } }, // English image lists
{ "ko", new List<ImageList> { imageListContinueBtn_ko, imageListSendEmailBtn_ko, imageListOKBtn_ko } }, // Korean image lists
// Add other languages and their respective image lists here
};
{
{ "en", new List<ImageList> { imageListContinueBtn, imageListSendEmailBtn, imageListOKBtn } }, // English image lists
{ "ko", new List<ImageList> { imageListContinueBtn_ko, imageListSendEmailBtn_ko, imageListOKBtn_ko } }, // Korean image lists
// Add other languages and their respective image lists here
};
// Load the appropriate resource file based on the selected language
LocalizationHelper.LoadLocalizedStrings(Lang, buttons, imageLists, languageImageLists);
}
#region Form Events
private void ChangePwd_Load(object sender, EventArgs e)
{
ContinueButtonS1.Enabled = false;
}
private void ChangePwd_FormClosing(object sender, FormClosingEventArgs e)
{
resendTimer.Dispose();
if (sender is ChangePwdForm changePwd)
{
changePwd.Dispose();
}
}
#endregion
#region Methods
private async Task<string> SendEmailRequestAsync()
{
using HttpClient client = new();
using HttpResponseMessage response = await client.PostAsync(SendPasswordCodeUrl, new FormUrlEncodedContent(new[]
{
using HttpResponseMessage response = await client.PostAsync(SendPasswordCodeUrl, new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("email", EmailTextBox.Text),
}));
]));
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
@ -90,45 +105,59 @@ namespace RHLauncher
{
Invoke((MethodInvoker)(() =>
{
switch (response)
try
{
case "EmailSent":
SendEmailButton.Enabled = false;
resendTimer.Start();
break;
case "ValidVerificationCode":
// Hide the firs panel and show the second panel
Stage1Panel.Visible = false;
Stage2Panel.Visible = true;
EmailLabelS2.Text = EmailTextBox.Text;
CodeDescLabel.Text = "";
CodePictureBox.Image = imageListTips.Images[1];
break;
case "PasswordChanged":
MsgBoxForm.Show(LocalizedStrings.PasswordChanged, LocalizedStrings.Success);
OnPasswordChanged();
break;
case "SamePassword":
MsgBoxForm.Show(LocalizedStrings.SamePassword, LocalizedStrings.Failed);
break;
case "AccountNotFound":
EmailDescLabel.Text = LocalizedStrings.AccountNotFound;
EmailDescLabel.ForeColor = Color.Red;
EmailPictureBox.Image = imageListTips.Images[0];
HttpResponse? httpResponse = JsonConvert.DeserializeObject<HttpResponse>(response);
if (httpResponse == null)
{
MsgBoxForm.Show(LocalizedStrings.Error + $": {LocalizedStrings.HttpResponseNull}", LocalizedStrings.Error);
return;
case "InvalidVerificationCode":
CodeDescLabel.Text = LocalizedStrings.InvalidVerificationCode;
CodeDescLabel.ForeColor = Color.Red;
CodePictureBox.Image = imageListTips.Images[0];
return;
case "ExpiredVerificationCode":
CodeDescLabel.Text = LocalizedStrings.ExpiredVerificationCode;
CodeDescLabel.ForeColor = Color.Red;
CodePictureBox.Image = imageListTips.Images[0];
return;
default:
MsgBoxForm.Show("Error:" + response, LocalizedStrings.Error);
break;
}
switch (httpResponse.Result)
{
case "EmailSent":
SendEmailButton.Enabled = false;
resendTimer.Start();
break;
case "ValidVerificationCode":
Stage1Panel.Visible = false;
Stage2Panel.Visible = true;
EmailLabelS2.Text = EmailTextBox.Text;
CodeDescLabel.Text = "";
CodePictureBox.Image = imageListTips.Images[1];
break;
case "PasswordChanged":
MsgBoxForm.Show(LocalizedStrings.PasswordChanged, LocalizedStrings.Success);
OnPasswordChanged();
break;
case "SamePassword":
MsgBoxForm.Show(LocalizedStrings.SamePassword, LocalizedStrings.Failed);
break;
case "AccountNotFound":
EmailDescLabel.Text = LocalizedStrings.AccountNotFound;
EmailDescLabel.ForeColor = Color.Red;
EmailPictureBox.Image = imageListTips.Images[0];
break;
case "InvalidVerificationCode":
CodeDescLabel.Text = LocalizedStrings.InvalidVerificationCode;
CodeDescLabel.ForeColor = Color.Red;
CodePictureBox.Image = imageListTips.Images[0];
break;
case "ExpiredVerificationCode":
CodeDescLabel.Text = LocalizedStrings.ExpiredVerificationCode;
CodeDescLabel.ForeColor = Color.Red;
CodePictureBox.Image = imageListTips.Images[0];
break;
default:
MsgBoxForm.Show($"{LocalizedStrings.Error}: " + httpResponse.Message, LocalizedStrings.Error);
break;
}
}
catch (JsonException)
{
MsgBoxForm.Show(LocalizedStrings.Error + $": {LocalizedStrings.HttpResponseParseError}", LocalizedStrings.Error);
}
}));
}
@ -153,28 +182,28 @@ namespace RHLauncher
private async Task<string> VerifyCodeSendRequestAsync()
{
using HttpClient client = new();
using HttpResponseMessage response = await client.PostAsync(VerifyCodeUrl, new FormUrlEncodedContent(new[]
{
using HttpResponseMessage response = await client.PostAsync(VerifyCodeUrl, new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("email", EmailTextBox.Text),
new KeyValuePair<string, string>("verification_code", CodeTextBox.Text),
new KeyValuePair<string, string>("verification_code_type", "Password"),
}));
new KeyValuePair<string, string>("verificationCode", CodeTextBox.Text),
new KeyValuePair<string, string>("verificationCodeType", "Password"),
]));
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
private async Task<string> ChangePasswordSendRequestAsync()
{
using HttpClient client = new();
using HttpResponseMessage response = await client.PostAsync(ChangePasswordUrl, new FormUrlEncodedContent(new[]
{
using HttpResponseMessage response = await client.PostAsync(ChangePasswordUrl, new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("email", EmailTextBox.Text),
new KeyValuePair<string, string>("password", PasswordTextBox.Text),
new KeyValuePair<string, string>("verification_code", CodeTextBox.Text),
}));
new KeyValuePair<string, string>("verificationCode", CodeTextBox.Text),
]));
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
@ -186,7 +215,10 @@ namespace RHLauncher
registryHandler.ClearPassword();
Invoke((MethodInvoker)(() => Close()));
Application.Restart();
Task.Delay(500).ContinueWith(_ =>
{
Application.Restart();
});
}
else
{
@ -223,9 +255,9 @@ namespace RHLauncher
try
{
string email = EmailTextBox.Text;
string pattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
if (Regex.IsMatch(email, pattern))
Regex emailRegex = RegexPatterns.EmailRegex();
if (emailRegex.IsMatch(EmailTextBox.Text))
{
// email is valid
EmailPictureBox.Image = imageListTips.Images[1];
@ -308,7 +340,7 @@ namespace RHLauncher
string password = PasswordTextBox.Text;
// Check for minimum length and maximum length
if (password.Length < 6 || password.Length > 16)
if (password.Length < 8 || password.Length > 16)
{
PwdDescLabel.Text = LocalizedStrings.PwdDescLabelSize;
PwdDescLabel.ForeColor = Color.Red;
@ -320,8 +352,9 @@ namespace RHLauncher
}
// Check for at least one uppercase, one lowercase letter, and one number
Regex regex = new(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$");
if (!regex.IsMatch(password))
Regex pwRegex = RegexPatterns.PWRegex();
if (!pwRegex.IsMatch(password))
{
PwdDescLabel.Text = LocalizedStrings.PwdDescLabelCriteria;
PwdDescLabel.ForeColor = Color.Red;
@ -335,8 +368,8 @@ namespace RHLauncher
}
// Check for additional character types such as symbols
regex = new Regex(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).+$");
if (regex.IsMatch(password))
Regex strongPWRegex = RegexPatterns.StrongPWRegex();
if (strongPWRegex.IsMatch(password))
{
PwdDescLabel.Text = "";
PwdPictureBox.Image = imageListTips.Images[1];
@ -383,7 +416,6 @@ namespace RHLauncher
CheckFormS2Validity();
}
private bool EmailTextBoxValid = false;
private void EmailTextBox_TextChanged(object sender, EventArgs e)
{
@ -396,9 +428,9 @@ namespace RHLauncher
}
try
{
string email = EmailTextBox.Text;
string pattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
if (Regex.IsMatch(email, pattern))
Regex emailRegex = RegexPatterns.EmailRegex();
if (emailRegex.IsMatch(EmailTextBox.Text))
{
// email is valid
EmailPictureBox.Image = imageListTips.Images[1];
@ -496,101 +528,46 @@ namespace RHLauncher
#endregion
#region Button Events
private void ContinueButtonS1_MouseHover(object sender, EventArgs e)
private void Button_MouseHover(object sender, EventArgs e)
{
ContinueButtonS1.ImageIndex = 1;
}
private void ContinueButtonS1_MouseLeave(object sender, EventArgs e)
{
ContinueButtonS1.ImageIndex = 0;
}
private void ContinueButtonS1_OnMouseDown(object sender, MouseEventArgs e)
{
ContinueButtonS1.ImageIndex = 2;
}
private void OkButtonS2_MouseHover(object sender, EventArgs e)
{
OkButtonS2.ImageIndex = 1;
}
private void OkButtonS2_MouseLeave(object sender, EventArgs e)
{
OkButtonS2.ImageIndex = 0;
}
private void OkButtonS2_OnMouseDown(object sender, MouseEventArgs e)
{
OkButtonS2.ImageIndex = 2;
}
private void SendEmailButton_MouseHover(object sender, EventArgs e)
{
SendEmailButton.ImageIndex = 1;
}
private void SendEmailButton_MouseLeave(object sender, EventArgs e)
{
SendEmailButton.ImageIndex = 0;
}
private void SendEmailButton_OnMouseDown(object sender, MouseEventArgs e)
{
SendEmailButton.ImageIndex = 2;
}
private void ChangePwd_FormClosing(object sender, FormClosingEventArgs e)
{
resendTimer.Dispose();
if (sender is ChangePwd changePwd)
if (sender is Button button)
{
changePwd.Dispose();
button.ImageIndex = 1;
}
}
private void MinimizeButton_MouseHover(object sender, EventArgs e)
private void Button_MouseLeave(object sender, EventArgs e)
{
MinimizeButton.ImageIndex = 1;
if (sender is Button button)
{
button.ImageIndex = 0;
}
}
private void MinimizeButton_MouseLeave(object sender, EventArgs e)
private void Button_MouseDown(object sender, MouseEventArgs e)
{
MinimizeButton.ImageIndex = 0;
}
private void MinimizeButton_OnMouseDown(object sender, MouseEventArgs e)
{
MinimizeButton.ImageIndex = 2;
if (sender is Button button)
{
button.ImageIndex = 2;
}
}
private void CloseButton_MouseHover(object sender, EventArgs e)
private void Label_MouseHover(object sender, EventArgs e)
{
CloseButton.ImageIndex = 1;
if (sender is Label label)
{
label.ForeColor = Color.White;
}
}
private void CloseButton_MouseLeave(object sender, EventArgs e)
private void Label_MouseLeave(object sender, EventArgs e)
{
CloseButton.ImageIndex = 0;
}
private void CloseButton_OnMouseDown(object sender, MouseEventArgs e)
{
CloseButton.ImageIndex = 2;
}
private void ReturnLabelS2_MouseHover(object sender, EventArgs e)
{
ReturnLabelS2.ForeColor = Color.White;
if (sender is Label label)
{
label.ForeColor = Color.Gainsboro;
}
}
private void ReturnLabelS2_MouseLeave(object sender, EventArgs e)
{
ReturnLabelS2.ForeColor = Color.Gainsboro;
}
private void ChangePwd_Load(object sender, EventArgs e)
{
ContinueButtonS1.Enabled = false;
}
#endregion
}
}

File diff suppressed because it is too large Load diff

248
RHLauncher.Forms/ConfigForm.Designer.cs generated Normal file
View file

@ -0,0 +1,248 @@
namespace RHLauncher
{
partial class ConfigForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ConfigForm));
CloseButton = new Button();
imageListCloseBtn = new ImageList(components);
imageListOKBtn = new ImageList(components);
TitleLabel = new Label();
imageListBtn = new ImageList(components);
cbLauncherLanguage = new ComboBox();
LanguageLabel = new Label();
OkButton = new Button();
VersionLabel = new Label();
toolTip = new ToolTip(components);
ServiceLabel = new Label();
cbLauncherService = new ComboBox();
SuspendLayout();
//
// CloseButton
//
CloseButton.BackColor = Color.Transparent;
CloseButton.FlatAppearance.BorderColor = Color.Black;
CloseButton.FlatAppearance.BorderSize = 0;
CloseButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
CloseButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
CloseButton.FlatStyle = FlatStyle.Flat;
CloseButton.ForeColor = Color.Transparent;
CloseButton.ImageIndex = 0;
CloseButton.ImageList = imageListCloseBtn;
CloseButton.ImeMode = ImeMode.NoControl;
CloseButton.Location = new Point(607, 9);
CloseButton.Name = "CloseButton";
CloseButton.Size = new Size(32, 29);
CloseButton.TabIndex = 8;
CloseButton.UseVisualStyleBackColor = false;
CloseButton.Click += CloseButton_Click;
CloseButton.MouseDown += Button_MouseDown;
CloseButton.MouseLeave += Button_MouseLeave;
CloseButton.MouseHover += Button_MouseHover;
//
// imageListCloseBtn
//
imageListCloseBtn.ColorDepth = ColorDepth.Depth32Bit;
imageListCloseBtn.ImageStream = (ImageListStreamer)resources.GetObject("imageListCloseBtn.ImageStream");
imageListCloseBtn.TransparentColor = Color.Transparent;
imageListCloseBtn.Images.SetKeyName(0, "button_close_normal.png");
imageListCloseBtn.Images.SetKeyName(1, "button_close_active.png");
imageListCloseBtn.Images.SetKeyName(2, "button_close_down.png");
//
// imageListOKBtn
//
imageListOKBtn.ColorDepth = ColorDepth.Depth32Bit;
imageListOKBtn.ImageStream = (ImageListStreamer)resources.GetObject("imageListOKBtn.ImageStream");
imageListOKBtn.TransparentColor = Color.Transparent;
imageListOKBtn.Images.SetKeyName(0, "messagewnd.button.ok.normal.png");
imageListOKBtn.Images.SetKeyName(1, "messagewnd.button.ok.active.png");
imageListOKBtn.Images.SetKeyName(2, "messagewnd.button.ok.down.png");
//
// TitleLabel
//
TitleLabel.Anchor = AnchorStyles.None;
TitleLabel.AutoEllipsis = true;
TitleLabel.AutoSize = true;
TitleLabel.BackColor = Color.Transparent;
TitleLabel.Font = new Font("Segoe UI", 11F, FontStyle.Bold);
TitleLabel.ForeColor = Color.White;
TitleLabel.ImageAlign = ContentAlignment.TopRight;
TitleLabel.ImeMode = ImeMode.NoControl;
TitleLabel.Location = new Point(287, 18);
TitleLabel.Name = "TitleLabel";
TitleLabel.Size = new Size(66, 20);
TitleLabel.TabIndex = 10;
TitleLabel.Text = "Settings";
TitleLabel.TextAlign = ContentAlignment.MiddleCenter;
//
// imageListBtn
//
imageListBtn.ColorDepth = ColorDepth.Depth32Bit;
imageListBtn.ImageStream = (ImageListStreamer)resources.GetObject("imageListBtn.ImageStream");
imageListBtn.TransparentColor = Color.Transparent;
imageListBtn.Images.SetKeyName(0, "button_normal.png");
imageListBtn.Images.SetKeyName(1, "button_active.png");
imageListBtn.Images.SetKeyName(2, "button_down.png");
//
// cbLauncherLanguage
//
cbLauncherLanguage.DropDownStyle = ComboBoxStyle.DropDownList;
cbLauncherLanguage.FormattingEnabled = true;
cbLauncherLanguage.Items.AddRange(new object[] { "English", "한국어" });
cbLauncherLanguage.Location = new Point(254, 91);
cbLauncherLanguage.Name = "cbLauncherLanguage";
cbLauncherLanguage.Size = new Size(145, 23);
cbLauncherLanguage.TabIndex = 12;
cbLauncherLanguage.SelectedIndexChanged += CbLauncherLanguage_SelectedIndexChanged;
//
// LanguageLabel
//
LanguageLabel.Anchor = AnchorStyles.None;
LanguageLabel.AutoEllipsis = true;
LanguageLabel.AutoSize = true;
LanguageLabel.BackColor = Color.Transparent;
LanguageLabel.Font = new Font("Segoe UI", 11F, FontStyle.Bold);
LanguageLabel.ForeColor = Color.White;
LanguageLabel.ImageAlign = ContentAlignment.TopRight;
LanguageLabel.ImeMode = ImeMode.NoControl;
LanguageLabel.Location = new Point(254, 68);
LanguageLabel.Name = "LanguageLabel";
LanguageLabel.Size = new Size(145, 20);
LanguageLabel.TabIndex = 13;
LanguageLabel.Text = "Launcher Language";
LanguageLabel.TextAlign = ContentAlignment.MiddleCenter;
//
// OkButton
//
OkButton.BackColor = Color.Transparent;
OkButton.FlatAppearance.BorderSize = 0;
OkButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
OkButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
OkButton.FlatStyle = FlatStyle.Flat;
OkButton.ImageIndex = 0;
OkButton.ImageList = imageListOKBtn;
OkButton.ImeMode = ImeMode.NoControl;
OkButton.Location = new Point(268, 218);
OkButton.Name = "OkButton";
OkButton.Size = new Size(110, 44);
OkButton.TabIndex = 14;
OkButton.UseVisualStyleBackColor = false;
OkButton.Click += OkButton_Click;
OkButton.MouseDown += Button_MouseDown;
OkButton.MouseLeave += Button_MouseLeave;
OkButton.MouseHover += Button_MouseHover;
//
// VersionLabel
//
VersionLabel.AutoSize = true;
VersionLabel.BackColor = Color.Transparent;
VersionLabel.Cursor = Cursors.Hand;
VersionLabel.Font = new Font("Segoe UI", 10F, FontStyle.Bold);
VersionLabel.ForeColor = Color.White;
VersionLabel.Location = new Point(5, 248);
VersionLabel.Name = "VersionLabel";
VersionLabel.Size = new Size(62, 19);
VersionLabel.TabIndex = 16;
VersionLabel.Text = "Version:";
toolTip.SetToolTip(VersionLabel, "Click to open github repository");
VersionLabel.Click += VersionLabel_Click;
//
// ServiceLabel
//
ServiceLabel.Anchor = AnchorStyles.None;
ServiceLabel.AutoEllipsis = true;
ServiceLabel.AutoSize = true;
ServiceLabel.BackColor = Color.Transparent;
ServiceLabel.Font = new Font("Segoe UI", 11F, FontStyle.Bold);
ServiceLabel.ForeColor = Color.White;
ServiceLabel.ImageAlign = ContentAlignment.TopRight;
ServiceLabel.ImeMode = ImeMode.NoControl;
ServiceLabel.Location = new Point(294, 119);
ServiceLabel.Name = "ServiceLabel";
ServiceLabel.Size = new Size(59, 20);
ServiceLabel.TabIndex = 18;
ServiceLabel.Text = "Service";
ServiceLabel.TextAlign = ContentAlignment.MiddleCenter;
//
// cbLauncherService
//
cbLauncherService.DropDownStyle = ComboBoxStyle.DropDownList;
cbLauncherService.FormattingEnabled = true;
cbLauncherService.Items.AddRange(new object[] { "JPN", "USA", "CHN", "JPN_BETA", "USA_BETA", "CHN_BETA" });
cbLauncherService.Location = new Point(254, 142);
cbLauncherService.Name = "cbLauncherService";
cbLauncherService.Size = new Size(145, 23);
cbLauncherService.TabIndex = 17;
cbLauncherService.SelectedIndexChanged += CbLauncherService_SelectedIndexChanged;
//
// ConfigForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = Color.Magenta;
BackgroundImage = (Image)resources.GetObject("$this.BackgroundImage");
ClientSize = new Size(646, 272);
Controls.Add(ServiceLabel);
Controls.Add(cbLauncherService);
Controls.Add(VersionLabel);
Controls.Add(OkButton);
Controls.Add(LanguageLabel);
Controls.Add(cbLauncherLanguage);
Controls.Add(TitleLabel);
Controls.Add(CloseButton);
DoubleBuffered = true;
FormBorderStyle = FormBorderStyle.None;
Icon = (Icon)resources.GetObject("$this.Icon");
Name = "ConfigForm";
ShowInTaskbar = false;
StartPosition = FormStartPosition.CenterScreen;
Text = "Message";
TransparencyKey = Color.Magenta;
FormClosing += ConfigForm_FormClosing;
Load += ConfigForm_Load;
ResumeLayout(false);
PerformLayout();
}
#endregion
private Button CloseButton;
private ImageList imageListCloseBtn;
private ImageList imageListOKBtn;
private Label TitleLabel;
private ImageList imageListBtn;
private ComboBox cbLauncherLanguage;
private Label LanguageLabel;
private Button OkButton;
private Label VersionLabel;
private ToolTip toolTip;
private Label ServiceLabel;
private ComboBox cbLauncherService;
}
}

View file

@ -0,0 +1,257 @@
using RHLauncher.RHLauncher.i8n;
using RHLauncher.RHLauncher.Helper;
using System.Diagnostics;
using System.Text;
namespace RHLauncher
{
public partial class ConfigForm : Form
{
private readonly RegistryHandler registryHandler = new();
private readonly string? installDirectory;
private readonly string Url = "https://github.com/JuniorDark/RustyHearts-Launcher";
private bool languageChanged = false;
readonly string currentLanguageCode = Configuration.Default.Lang;
private bool serviceChanged = false;
readonly string currentService = Configuration.Default.Service;
public ConfigForm()
{
InitializeComponent();
installDirectory = registryHandler.GetInstallDirectory();
string currentVersion = GetLauncherVersion.GetVersion();
cbLauncherLanguage.SelectedItem = GetLanguageName(currentLanguageCode);
cbLauncherService.SelectedItem = GetServiceName(currentService);
VersionLabel.Text = $"{LocalizedStrings.Version}: {currentVersion}";
Text = LocalizedStrings.ConfigFormTitle;
TitleLabel.Text = LocalizedStrings.Settings;
LanguageLabel.Text = LocalizedStrings.LauncherLanguage;
ServiceLabel.Text = LocalizedStrings.Service;
}
#region Form Events
private void ConfigForm_Load(object sender, EventArgs e)
{
TitleLabel.Left = (ClientSize.Width - TitleLabel.Width) / 2;
}
private void ConfigForm_FormClosing(object sender, FormClosingEventArgs e)
{
Dispose();
}
#endregion
#region Language Methods
private void CbLauncherLanguage_SelectedIndexChanged(object sender, EventArgs e)
{
if (cbLauncherLanguage.SelectedItem is string selectedItem)
{
string selectedLanguageCode = GetLanguageCode(selectedItem);
if (selectedLanguageCode != currentLanguageCode)
{
languageChanged = true;
}
else
{
languageChanged = false;
}
}
}
private static string GetLanguageCode(string? language)
{
return language switch
{
"English" => "en",
"한국어" => "ko",
_ => "en",
};
}
private static string GetLanguageName(string code)
{
return code switch
{
"en" => "English",
"ko" => "한국어",
_ => "English",
};
}
#endregion
#region Service Methods
private void CbLauncherService_SelectedIndexChanged(object sender, EventArgs e)
{
if (cbLauncherService.SelectedItem is string selectedItem)
{
string selectedServiceCode = GetServiceCode(selectedItem);
if (selectedServiceCode != currentService)
{
serviceChanged = true;
}
else
{
serviceChanged = false;
}
}
}
private static string GetServiceCode(string? service)
{
return service switch
{
"USA" => "usa",
"JPN" => "jpn",
"CHN" => "chn",
"USA_BETA" => "usa_beta",
"JPN_BETA" => "jpn_beta",
"CHN_BETA" => "chn_beta",
_ => "jpn",
};
}
private static string GetServiceName(string service)
{
return service switch
{
"usa" => "USA",
"jpn" => "JPN",
"chn" => "CHN",
"usa_beta" => "USA_BETA",
"jpn_beta" => "JPN_BETA",
"chn_beta" => "CHN_BETA",
_ => "JPN",
};
}
private void UpdateServiceDatFile(string serviceCode)
{
if (string.IsNullOrEmpty(installDirectory))
return;
try
{
// Compute MD5 hash
byte[] inputBytes = Encoding.UTF8.GetBytes(serviceCode);
byte[] hashBytes = System.Security.Cryptography.MD5.HashData(inputBytes);
StringBuilder sb = new();
foreach (byte b in hashBytes)
{
sb.Append(b.ToString("x2")); // Lowercase hex
}
string hashString = sb.ToString();
string fileContent = $"{hashString}\r\n\r\nSTAIRWAY GAMES";
// Write to Service.dat
string filePath = Path.Combine(installDirectory, "Service.dat");
File.WriteAllText(filePath, fileContent);
}
catch (Exception ex)
{
MessageBox.Show($"Failed to update Service.dat: {ex.Message}", LocalizedStrings.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
#endregion
#region Button Click Events
private void OkButton_Click(object sender, EventArgs e)
{
try
{
if (languageChanged || serviceChanged)
{
string? selectedService = cbLauncherService.SelectedItem?.ToString();
string serviceCode = GetServiceCode(selectedService);
if (serviceCode != null)
{
// Update the service in the INI file
Configuration.Default.Service = serviceCode;
Configuration.Default.iniFile.WriteValue("Info", "Service", serviceCode);
UpdateServiceDatFile(serviceCode);
}
string? selectedLanguage = cbLauncherLanguage.SelectedItem?.ToString();
string languageCode = GetLanguageCode(selectedLanguage);
if (languageCode != null)
{
// Update the language in the INI file
Configuration.Default.Lang = languageCode;
Configuration.Default.iniFile.WriteValue("Launcher", "Lang", languageCode);
DialogResult result = MsgBoxForm.ShowYN(LocalizedStrings.ChangeLanguageMessage, LocalizedStrings.Confirmation);
if (result == DialogResult.Yes)
{
Invoke((MethodInvoker)(() => Close()));
Task.Delay(1000).ContinueWith(_ =>
{
Application.Restart();
});
}
}
}
else
{
Close();
}
}
catch (Exception ex)
{
MessageBox.Show($"{LocalizedStrings.Error}: {ex.Message}", LocalizedStrings.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void VersionLabel_Click(object sender, EventArgs e)
{
Process.Start(new ProcessStartInfo { FileName = Url, UseShellExecute = true });
}
private void CloseButton_Click(object sender, EventArgs e)
{
Close();
}
#endregion
#region Button Events
private void Button_MouseHover(object sender, EventArgs e)
{
if (sender is Button button)
{
button.ImageIndex = 1;
}
}
private void Button_MouseLeave(object sender, EventArgs e)
{
if (sender is Button button)
{
button.ImageIndex = 0;
}
}
private void Button_MouseDown(object sender, MouseEventArgs e)
{
if (sender is Button button)
{
button.ImageIndex = 2;
}
}
#endregion
}
}

File diff suppressed because it is too large Load diff

View file

@ -48,8 +48,8 @@
PercentLabel = new Label();
DownloadingLabel = new Label();
FileNameLabel = new Label();
progressBar1 = new ProgressBar();
webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
progressBar = new ProgressBar();
webView2 = new Microsoft.Web.WebView2.WinForms.WebView2();
LabelNews = new Label();
imageListButton = new ImageList(components);
AccOptionsButton = new Button();
@ -64,13 +64,18 @@
OpenInstallDirButton = new Button();
ManageButton = new Button();
CheckUpdateButton = new Button();
InstallButton = new Button();
ChangeInstallLocationButton = new Button();
InstallPanel = new Panel();
UninstallButton = new Button();
notifyIcon = new NotifyIcon(components);
LabelInstalled = new Label();
LabelLocate = new Label();
SettingsButton = new Button();
imageListGear = new ImageList(components);
toolTip = new ToolTip(components);
((System.ComponentModel.ISupportInitialize)CharPictureBox).BeginInit();
getUpdatePanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)webView21).BeginInit();
((System.ComponentModel.ISupportInitialize)webView2).BeginInit();
AccPanel.SuspendLayout();
LaunchPanel.SuspendLayout();
InstallPanel.SuspendLayout();
@ -94,9 +99,9 @@
CloseButton.TabIndex = 9;
CloseButton.UseVisualStyleBackColor = false;
CloseButton.Click += CloseButton_Click;
CloseButton.MouseDown += CloseButton_OnMouseDown;
CloseButton.MouseLeave += CloseButton_MouseLeave;
CloseButton.MouseHover += CloseButton_MouseHover;
CloseButton.MouseDown += Button_MouseDown;
CloseButton.MouseLeave += Button_MouseLeave;
CloseButton.MouseHover += Button_MouseHover;
//
// imageListCloseBtn
//
@ -125,9 +130,9 @@
MinimizeButton.TabIndex = 8;
MinimizeButton.UseVisualStyleBackColor = false;
MinimizeButton.Click += MinimizeButton_Click;
MinimizeButton.MouseDown += MinimizeButton_OnMouseDown;
MinimizeButton.MouseLeave += MinimizeButton_MouseLeave;
MinimizeButton.MouseHover += MinimizeButton_MouseHover;
MinimizeButton.MouseDown += Button_MouseDown;
MinimizeButton.MouseLeave += Button_MouseLeave;
MinimizeButton.MouseHover += Button_MouseHover;
//
// imageListMinBtn
//
@ -156,9 +161,9 @@
LaunchButton.TabIndex = 10;
LaunchButton.Text = "Launch";
LaunchButton.UseVisualStyleBackColor = false;
LaunchButton.MouseDown += LaunchButton_OnMouseDown;
LaunchButton.MouseLeave += LaunchButton_MouseLeave;
LaunchButton.MouseHover += LaunchButton_MouseHover;
LaunchButton.MouseDown += Button_MouseDown;
LaunchButton.MouseLeave += Button_MouseLeave;
LaunchButton.MouseHover += Button_MouseHover;
//
// imageListLaunch
//
@ -185,7 +190,7 @@
// CharPictureBox
//
CharPictureBox.BackColor = Color.Transparent;
CharPictureBox.Image = Properties.Resources.character_select_cut_roselle;
CharPictureBox.Image = (Image)resources.GetObject("CharPictureBox.Image");
CharPictureBox.Location = new Point(23, 165);
CharPictureBox.Name = "CharPictureBox";
CharPictureBox.Size = new Size(367, 497);
@ -207,7 +212,7 @@
getUpdatePanel.Controls.Add(PercentLabel);
getUpdatePanel.Controls.Add(DownloadingLabel);
getUpdatePanel.Controls.Add(FileNameLabel);
getUpdatePanel.Controls.Add(progressBar1);
getUpdatePanel.Controls.Add(progressBar);
getUpdatePanel.Location = new Point(397, 570);
getUpdatePanel.Name = "getUpdatePanel";
getUpdatePanel.Size = new Size(594, 93);
@ -231,9 +236,9 @@
StopButton.TabIndex = 28;
StopButton.UseVisualStyleBackColor = false;
StopButton.Click += StopButton_Click;
StopButton.MouseDown += StopButton_OnMouseDown;
StopButton.MouseLeave += StopButton_MouseLeave;
StopButton.MouseHover += StopButton_MouseHover;
StopButton.MouseDown += Button_MouseDown;
StopButton.MouseLeave += Button_MouseLeave;
StopButton.MouseHover += Button_MouseHover;
//
// imageListStopBtn
//
@ -345,24 +350,24 @@
FileNameLabel.TabIndex = 1;
FileNameLabel.Text = "filename";
//
// progressBar1
// progressBar
//
progressBar1.Location = new Point(11, 38);
progressBar1.Name = "progressBar1";
progressBar1.Size = new Size(502, 23);
progressBar1.TabIndex = 0;
progressBar.Location = new Point(11, 38);
progressBar.Name = "progressBar";
progressBar.Size = new Size(502, 23);
progressBar.TabIndex = 0;
//
// webView21
// webView2
//
webView21.AllowExternalDrop = true;
webView21.BackColor = Color.RoyalBlue;
webView21.CreationProperties = null;
webView21.DefaultBackgroundColor = Color.White;
webView21.Location = new Point(412, 101);
webView21.Name = "webView21";
webView21.Size = new Size(475, 405);
webView21.TabIndex = 21;
webView21.ZoomFactor = 1D;
webView2.AllowExternalDrop = true;
webView2.BackColor = Color.RoyalBlue;
webView2.CreationProperties = null;
webView2.DefaultBackgroundColor = Color.White;
webView2.Location = new Point(412, 101);
webView2.Name = "webView2";
webView2.Size = new Size(475, 405);
webView2.TabIndex = 21;
webView2.ZoomFactor = 1D;
//
// LabelNews
//
@ -403,13 +408,13 @@
AccOptionsButton.TabIndex = 23;
AccOptionsButton.UseVisualStyleBackColor = false;
AccOptionsButton.Click += AccOptionsButton_Click;
AccOptionsButton.MouseLeave += AccOptionsButton_MouseLeave;
AccOptionsButton.MouseHover += AccOptionsButton_MouseHover;
AccOptionsButton.MouseLeave += Button_MouseLeave;
AccOptionsButton.MouseHover += Button_MouseHover;
//
// AccPanel
//
AccPanel.BackColor = Color.RoyalBlue;
AccPanel.BackgroundImage = Properties.Resources.help_panel_bkg;
AccPanel.BackgroundImage = (Image)resources.GetObject("AccPanel.BackgroundImage");
AccPanel.Controls.Add(LogoutButton);
AccPanel.Controls.Add(ChangePwdButton);
AccPanel.Location = new Point(969, 52);
@ -437,9 +442,9 @@
LogoutButton.Text = "Logout";
LogoutButton.UseVisualStyleBackColor = false;
LogoutButton.Click += LogoutButton_Click;
LogoutButton.MouseDown += MenuButton_MouseDown;
LogoutButton.MouseLeave += MenuButton_MouseLeave;
LogoutButton.MouseHover += MenuButton_MouseHover;
LogoutButton.MouseDown += Button_MouseDown;
LogoutButton.MouseLeave += Button_MouseLeave;
LogoutButton.MouseHover += Button_MouseHover;
//
// imageListMenuButton
//
@ -469,9 +474,9 @@
ChangePwdButton.Text = "Change Password";
ChangePwdButton.UseVisualStyleBackColor = false;
ChangePwdButton.Click += ChangePwdButton_Click;
ChangePwdButton.MouseDown += MenuButton_MouseDown;
ChangePwdButton.MouseLeave += MenuButton_MouseLeave;
ChangePwdButton.MouseHover += MenuButton_MouseHover;
ChangePwdButton.MouseDown += Button_MouseDown;
ChangePwdButton.MouseLeave += Button_MouseLeave;
ChangePwdButton.MouseHover += Button_MouseHover;
//
// LaunchOptionsButton
//
@ -491,9 +496,9 @@
LaunchOptionsButton.TabIndex = 25;
LaunchOptionsButton.UseVisualStyleBackColor = false;
LaunchOptionsButton.Click += LaunchOptionsButton_Click;
LaunchOptionsButton.MouseDown += LaunchOptionsButton_OnMouseDown;
LaunchOptionsButton.MouseLeave += LaunchOptionsButton_MouseLeave;
LaunchOptionsButton.MouseHover += LaunchOptionsButton_MouseHover;
LaunchOptionsButton.MouseDown += Button_MouseDown;
LaunchOptionsButton.MouseLeave += Button_MouseLeave;
LaunchOptionsButton.MouseHover += Button_MouseHover;
//
// imageListLaunchOpt
//
@ -507,7 +512,7 @@
// LaunchPanel
//
LaunchPanel.BackColor = Color.RoyalBlue;
LaunchPanel.BackgroundImage = Properties.Resources.help_panel_bkg;
LaunchPanel.BackgroundImage = (Image)resources.GetObject("LaunchPanel.BackgroundImage");
LaunchPanel.Controls.Add(OpenSettingsButton);
LaunchPanel.Controls.Add(OpenInstallDirButton);
LaunchPanel.Controls.Add(ManageButton);
@ -525,7 +530,7 @@
OpenSettingsButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
OpenSettingsButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
OpenSettingsButton.FlatStyle = FlatStyle.Flat;
OpenSettingsButton.Font = new Font("Segoe UI", 8F, FontStyle.Bold, GraphicsUnit.Point);
OpenSettingsButton.Font = new Font("Segoe UI", 7F, FontStyle.Bold, GraphicsUnit.Point);
OpenSettingsButton.ForeColor = Color.White;
OpenSettingsButton.ImageIndex = 0;
OpenSettingsButton.ImageList = imageListMenuButton;
@ -537,9 +542,9 @@
OpenSettingsButton.Text = "Game Settings";
OpenSettingsButton.UseVisualStyleBackColor = false;
OpenSettingsButton.Click += OpenSettingsButton_Click;
OpenSettingsButton.MouseDown += MenuButton_MouseDown;
OpenSettingsButton.MouseLeave += MenuButton_MouseLeave;
OpenSettingsButton.MouseHover += MenuButton_MouseHover;
OpenSettingsButton.MouseDown += Button_MouseDown;
OpenSettingsButton.MouseLeave += Button_MouseLeave;
OpenSettingsButton.MouseHover += Button_MouseHover;
//
// OpenInstallDirButton
//
@ -548,7 +553,7 @@
OpenInstallDirButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
OpenInstallDirButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
OpenInstallDirButton.FlatStyle = FlatStyle.Flat;
OpenInstallDirButton.Font = new Font("Segoe UI", 8F, FontStyle.Bold, GraphicsUnit.Point);
OpenInstallDirButton.Font = new Font("Segoe UI", 7F, FontStyle.Bold, GraphicsUnit.Point);
OpenInstallDirButton.ForeColor = Color.White;
OpenInstallDirButton.ImageIndex = 0;
OpenInstallDirButton.ImageList = imageListMenuButton;
@ -557,12 +562,12 @@
OpenInstallDirButton.Name = "OpenInstallDirButton";
OpenInstallDirButton.Size = new Size(118, 28);
OpenInstallDirButton.TabIndex = 28;
OpenInstallDirButton.Text = "Open Install Dir";
OpenInstallDirButton.Text = "Open Install Directory";
OpenInstallDirButton.UseVisualStyleBackColor = false;
OpenInstallDirButton.Click += OpenInstallDirButton_Click;
OpenInstallDirButton.MouseDown += MenuButton_MouseDown;
OpenInstallDirButton.MouseLeave += MenuButton_MouseLeave;
OpenInstallDirButton.MouseHover += MenuButton_MouseHover;
OpenInstallDirButton.MouseDown += Button_MouseDown;
OpenInstallDirButton.MouseLeave += Button_MouseLeave;
OpenInstallDirButton.MouseHover += Button_MouseHover;
//
// ManageButton
//
@ -571,7 +576,7 @@
ManageButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
ManageButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
ManageButton.FlatStyle = FlatStyle.Flat;
ManageButton.Font = new Font("Segoe UI", 8F, FontStyle.Bold, GraphicsUnit.Point);
ManageButton.Font = new Font("Segoe UI", 7F, FontStyle.Bold, GraphicsUnit.Point);
ManageButton.ForeColor = Color.White;
ManageButton.ImageIndex = 0;
ManageButton.ImageList = imageListMenuButton;
@ -583,9 +588,9 @@
ManageButton.Text = "< Manage";
ManageButton.UseVisualStyleBackColor = false;
ManageButton.Click += ManageButton_Click;
ManageButton.MouseDown += MenuButton_MouseDown;
ManageButton.MouseLeave += MenuButton_MouseLeave;
ManageButton.MouseHover += MenuButton_MouseHover;
ManageButton.MouseDown += Button_MouseDown;
ManageButton.MouseLeave += Button_MouseLeave;
ManageButton.MouseHover += Button_MouseHover;
//
// CheckUpdateButton
//
@ -594,7 +599,7 @@
CheckUpdateButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
CheckUpdateButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
CheckUpdateButton.FlatStyle = FlatStyle.Flat;
CheckUpdateButton.Font = new Font("Segoe UI", 8F, FontStyle.Bold, GraphicsUnit.Point);
CheckUpdateButton.Font = new Font("Segoe UI", 7F, FontStyle.Bold, GraphicsUnit.Point);
CheckUpdateButton.ForeColor = Color.White;
CheckUpdateButton.ImageIndex = 0;
CheckUpdateButton.ImageList = imageListMenuButton;
@ -603,42 +608,42 @@
CheckUpdateButton.Name = "CheckUpdateButton";
CheckUpdateButton.Size = new Size(118, 28);
CheckUpdateButton.TabIndex = 27;
CheckUpdateButton.Text = "Check Update";
CheckUpdateButton.Text = "Check for Updates";
CheckUpdateButton.UseVisualStyleBackColor = false;
CheckUpdateButton.Click += UpdateCheckButton_Click;
CheckUpdateButton.MouseDown += MenuButton_MouseDown;
CheckUpdateButton.MouseLeave += MenuButton_MouseLeave;
CheckUpdateButton.MouseHover += MenuButton_MouseHover;
CheckUpdateButton.MouseDown += Button_MouseDown;
CheckUpdateButton.MouseLeave += Button_MouseLeave;
CheckUpdateButton.MouseHover += Button_MouseHover;
//
// InstallButton
// ChangeInstallLocationButton
//
InstallButton.BackColor = Color.Transparent;
InstallButton.FlatAppearance.BorderSize = 0;
InstallButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
InstallButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
InstallButton.FlatStyle = FlatStyle.Flat;
InstallButton.Font = new Font("Microsoft Sans Serif", 8F, FontStyle.Bold, GraphicsUnit.Point);
InstallButton.ForeColor = Color.White;
InstallButton.ImageIndex = 0;
InstallButton.ImageList = imageListMenuButton;
InstallButton.ImeMode = ImeMode.NoControl;
InstallButton.Location = new Point(3, 2);
InstallButton.Name = "InstallButton";
InstallButton.Size = new Size(118, 28);
InstallButton.TabIndex = 28;
InstallButton.Text = "Install Location";
InstallButton.UseVisualStyleBackColor = false;
InstallButton.Click += InstallButton_Click;
InstallButton.MouseDown += MenuButton_MouseDown;
InstallButton.MouseLeave += MenuButton_MouseLeave;
InstallButton.MouseHover += MenuButton_MouseHover;
ChangeInstallLocationButton.BackColor = Color.Transparent;
ChangeInstallLocationButton.FlatAppearance.BorderSize = 0;
ChangeInstallLocationButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
ChangeInstallLocationButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
ChangeInstallLocationButton.FlatStyle = FlatStyle.Flat;
ChangeInstallLocationButton.Font = new Font("Microsoft Sans Serif", 7F, FontStyle.Bold, GraphicsUnit.Point);
ChangeInstallLocationButton.ForeColor = Color.White;
ChangeInstallLocationButton.ImageIndex = 0;
ChangeInstallLocationButton.ImageList = imageListMenuButton;
ChangeInstallLocationButton.ImeMode = ImeMode.NoControl;
ChangeInstallLocationButton.Location = new Point(3, 2);
ChangeInstallLocationButton.Name = "ChangeInstallLocationButton";
ChangeInstallLocationButton.Size = new Size(118, 28);
ChangeInstallLocationButton.TabIndex = 28;
ChangeInstallLocationButton.Text = "Install Location";
ChangeInstallLocationButton.UseVisualStyleBackColor = false;
ChangeInstallLocationButton.Click += ChangeInstallLocationButton_Click;
ChangeInstallLocationButton.MouseDown += Button_MouseDown;
ChangeInstallLocationButton.MouseLeave += Button_MouseLeave;
ChangeInstallLocationButton.MouseHover += Button_MouseHover;
//
// InstallPanel
//
InstallPanel.BackColor = Color.RoyalBlue;
InstallPanel.BackgroundImage = Properties.Resources.help_panel_bkg;
InstallPanel.BackgroundImage = (Image)resources.GetObject("InstallPanel.BackgroundImage");
InstallPanel.Controls.Add(UninstallButton);
InstallPanel.Controls.Add(InstallButton);
InstallPanel.Controls.Add(ChangeInstallLocationButton);
InstallPanel.Location = new Point(941, 469);
InstallPanel.Name = "InstallPanel";
InstallPanel.Size = new Size(124, 62);
@ -652,7 +657,7 @@
UninstallButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
UninstallButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
UninstallButton.FlatStyle = FlatStyle.Flat;
UninstallButton.Font = new Font("Microsoft Sans Serif", 8F, FontStyle.Bold, GraphicsUnit.Point);
UninstallButton.Font = new Font("Microsoft Sans Serif", 7F, FontStyle.Bold, GraphicsUnit.Point);
UninstallButton.ForeColor = Color.Red;
UninstallButton.ImageIndex = 0;
UninstallButton.ImageList = imageListMenuButton;
@ -664,32 +669,99 @@
UninstallButton.Text = "Uninstall";
UninstallButton.UseVisualStyleBackColor = false;
UninstallButton.Click += UninstallButton_Click;
UninstallButton.MouseDown += MenuButton_MouseDown;
UninstallButton.MouseLeave += MenuButton_MouseLeave;
UninstallButton.MouseHover += MenuButton_MouseHover;
UninstallButton.MouseDown += Button_MouseDown;
UninstallButton.MouseLeave += Button_MouseLeave;
UninstallButton.MouseHover += Button_MouseHover;
//
// notifyIcon
//
notifyIcon.Icon = (Icon)resources.GetObject("notifyIcon.Icon");
notifyIcon.Text = "Rusty Hearts";
notifyIcon.Visible = true;
notifyIcon.MouseClick += notifyIcon_MouseClick;
notifyIcon.MouseClick += NotifyIcon_MouseClick;
//
// LabelInstalled
//
LabelInstalled.AutoSize = true;
LabelInstalled.BackColor = Color.Transparent;
LabelInstalled.FlatStyle = FlatStyle.Flat;
LabelInstalled.Font = new Font("Segoe UI", 9F, FontStyle.Bold | FontStyle.Underline, GraphicsUnit.Point);
LabelInstalled.ForeColor = Color.FromArgb(246, 239, 247);
LabelInstalled.Location = new Point(998, 647);
LabelInstalled.MaximumSize = new Size(85, 0);
LabelInstalled.Name = "LabelInstalled";
LabelInstalled.Size = new Size(59, 15);
LabelInstalled.TabIndex = 28;
LabelInstalled.Text = "Installed?";
LabelInstalled.Visible = false;
//
// LabelLocate
//
LabelLocate.AutoSize = true;
LabelLocate.BackColor = Color.Transparent;
LabelLocate.Cursor = Cursors.Hand;
LabelLocate.FlatStyle = FlatStyle.Flat;
LabelLocate.Font = new Font("Segoe UI", 9F, FontStyle.Bold | FontStyle.Underline, GraphicsUnit.Point);
LabelLocate.ForeColor = Color.Gold;
LabelLocate.Location = new Point(1078, 647);
LabelLocate.MaximumSize = new Size(90, 0);
LabelLocate.Name = "LabelLocate";
LabelLocate.Size = new Size(80, 15);
LabelLocate.TabIndex = 29;
LabelLocate.Text = "Locate Game";
LabelLocate.Visible = false;
LabelLocate.Click += LbLocate_Click;
LabelLocate.MouseLeave += LabelLocate_MouseLeave;
LabelLocate.MouseHover += LabelLocate_MouseHover;
//
// SettingsButton
//
SettingsButton.BackColor = Color.Transparent;
SettingsButton.FlatAppearance.BorderColor = Color.Black;
SettingsButton.FlatAppearance.BorderSize = 0;
SettingsButton.FlatAppearance.MouseDownBackColor = Color.Transparent;
SettingsButton.FlatAppearance.MouseOverBackColor = Color.Transparent;
SettingsButton.FlatStyle = FlatStyle.Flat;
SettingsButton.Font = new Font("Segoe UI", 9F, FontStyle.Regular, GraphicsUnit.Point);
SettingsButton.ForeColor = Color.Transparent;
SettingsButton.ImageIndex = 0;
SettingsButton.ImageList = imageListGear;
SettingsButton.ImeMode = ImeMode.NoControl;
SettingsButton.Location = new Point(1130, 32);
SettingsButton.Name = "SettingsButton";
SettingsButton.Size = new Size(25, 26);
SettingsButton.TabIndex = 30;
SettingsButton.UseVisualStyleBackColor = false;
SettingsButton.Click += SettingsButton_Click;
SettingsButton.MouseLeave += Button_MouseLeave;
SettingsButton.MouseHover += Button_MouseHover;
//
// imageListGear
//
imageListGear.ColorDepth = ColorDepth.Depth32Bit;
imageListGear.ImageStream = (ImageListStreamer)resources.GetObject("imageListGear.ImageStream");
imageListGear.TransparentColor = Color.Transparent;
imageListGear.Images.SetKeyName(0, "gear.png");
imageListGear.Images.SetKeyName(1, "gear_hover.png");
//
// LauncherForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = Color.Magenta;
BackgroundImage = Properties.Resources.launcher_bg;
BackgroundImage = (Image)resources.GetObject("$this.BackgroundImage");
BackgroundImageLayout = ImageLayout.None;
ClientSize = new Size(1239, 700);
Controls.Add(SettingsButton);
Controls.Add(LabelLocate);
Controls.Add(LabelInstalled);
Controls.Add(InstallPanel);
Controls.Add(LaunchPanel);
Controls.Add(LaunchOptionsButton);
Controls.Add(AccPanel);
Controls.Add(AccOptionsButton);
Controls.Add(LabelNews);
Controls.Add(webView21);
Controls.Add(webView2);
Controls.Add(getUpdatePanel);
Controls.Add(CharPictureBox);
Controls.Add(NameLabel);
@ -704,13 +776,14 @@
Text = "Rusty Hearts Launcher";
TransparencyKey = Color.Magenta;
FormClosing += LauncherForm_FormClosing;
FormClosed += LauncherForm_FormClosed;
Load += LauncherForm_Load;
MouseDown += OnMouseDown;
Resize += LauncherForm_Resize;
((System.ComponentModel.ISupportInitialize)CharPictureBox).EndInit();
getUpdatePanel.ResumeLayout(false);
getUpdatePanel.PerformLayout();
((System.ComponentModel.ISupportInitialize)webView21).EndInit();
((System.ComponentModel.ISupportInitialize)webView2).EndInit();
AccPanel.ResumeLayout(false);
LaunchPanel.ResumeLayout(false);
InstallPanel.ResumeLayout(false);
@ -728,7 +801,7 @@
private Label NameLabel;
private PictureBox CharPictureBox;
private Panel getUpdatePanel;
private ProgressBar progressBar1;
private ProgressBar progressBar;
private Label FileSizeLabel;
private Label SpeedLabel;
private Label TimeLabel;
@ -737,7 +810,7 @@
private Label FileNameLabel;
private Button LaunchButton;
private Label FileCountLabel;
private Microsoft.Web.WebView2.WinForms.WebView2 webView21;
private Microsoft.Web.WebView2.WinForms.WebView2 webView2;
private Label LabelNews;
private ImageList imageListButton;
private Button AccOptionsButton;
@ -749,7 +822,7 @@
private ImageList imageListMenuButton;
private Button LogoutButton;
private Button ChangePwdButton;
private Button InstallButton;
private Button ChangeInstallLocationButton;
private Button ManageButton;
private Panel InstallPanel;
private Button UninstallButton;
@ -758,5 +831,10 @@
private ImageList imageListStopBtn;
private Button StopButton;
private NotifyIcon notifyIcon;
private Label LabelInstalled;
private Label LabelLocate;
private Button SettingsButton;
private ImageList imageListGear;
private ToolTip toolTip;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -44,7 +44,7 @@
imageListRegister = new ImageList(components);
CheckBoxAutoLogin = new CheckBox();
CheckBoxSaveUser = new CheckBox();
timer1 = new System.Windows.Forms.Timer(components);
timer = new System.Windows.Forms.Timer(components);
progressBarLogin = new ProgressBar();
ForgotPwdLabel = new Label();
VersionLabel = new Label();
@ -82,18 +82,18 @@
// UsernameTextBox
//
UsernameTextBox.Font = new Font("Microsoft Sans Serif", 9F, FontStyle.Regular, GraphicsUnit.Point);
UsernameTextBox.Location = new Point(612, 222);
UsernameTextBox.Location = new Point(614, 222);
UsernameTextBox.Name = "UsernameTextBox";
UsernameTextBox.Size = new Size(210, 21);
UsernameTextBox.Size = new Size(206, 21);
UsernameTextBox.TabIndex = 2;
//
// PasswordTextBox
//
PasswordTextBox.Font = new Font("Microsoft Sans Serif", 9F, FontStyle.Regular, GraphicsUnit.Point);
PasswordTextBox.Location = new Point(613, 271);
PasswordTextBox.Location = new Point(614, 271);
PasswordTextBox.Name = "PasswordTextBox";
PasswordTextBox.PasswordChar = '*';
PasswordTextBox.Size = new Size(210, 21);
PasswordTextBox.Size = new Size(206, 21);
PasswordTextBox.TabIndex = 3;
//
// MinimizeButton
@ -113,9 +113,9 @@
MinimizeButton.TabIndex = 5;
MinimizeButton.UseVisualStyleBackColor = false;
MinimizeButton.Click += MinimizeButton_Click;
MinimizeButton.MouseDown += MinimizeButton_OnMouseDown;
MinimizeButton.MouseLeave += MinimizeButton_MouseLeave;
MinimizeButton.MouseHover += MinimizeButton_MouseHover;
MinimizeButton.MouseDown += Button_MouseDown;
MinimizeButton.MouseLeave += Button_MouseLeave;
MinimizeButton.MouseHover += Button_MouseHover;
//
// imageListMinBtn
//
@ -152,9 +152,9 @@
CloseButton.TabIndex = 7;
CloseButton.UseVisualStyleBackColor = false;
CloseButton.Click += CloseButton_Click;
CloseButton.MouseDown += CloseButton_OnMouseDown;
CloseButton.MouseLeave += CloseButton_MouseLeave;
CloseButton.MouseHover += CloseButton_MouseHover;
CloseButton.MouseDown += Button_MouseDown;
CloseButton.MouseLeave += Button_MouseLeave;
CloseButton.MouseHover += Button_MouseHover;
//
// imageListLogin
//
@ -180,9 +180,9 @@
LoginButton.TabIndex = 8;
LoginButton.UseVisualStyleBackColor = false;
LoginButton.Click += LoginButton_Click;
LoginButton.MouseDown += LoginButton_OnMouseDown;
LoginButton.MouseLeave += LoginButton_MouseLeave;
LoginButton.MouseHover += LoginButton_MouseHover;
LoginButton.MouseDown += Button_MouseDown;
LoginButton.MouseLeave += Button_MouseLeave;
LoginButton.MouseHover += Button_MouseHover;
//
// RegisterButton
//
@ -199,9 +199,9 @@
RegisterButton.TabIndex = 9;
RegisterButton.UseVisualStyleBackColor = false;
RegisterButton.Click += RegisterButton_Click;
RegisterButton.MouseDown += RegisterButton_OnMouseDown;
RegisterButton.MouseLeave += RegisterButton_MouseLeave;
RegisterButton.MouseHover += RegisterButton_MouseHover;
RegisterButton.MouseDown += Button_MouseDown;
RegisterButton.MouseLeave += Button_MouseLeave;
RegisterButton.MouseHover += Button_MouseHover;
//
// imageListRegister
//
@ -241,15 +241,15 @@
CheckBoxSaveUser.UseVisualStyleBackColor = false;
CheckBoxSaveUser.CheckedChanged += CheckBoxSaveUser_CheckedChanged;
//
// timer1
// timer
//
timer1.Enabled = true;
timer.Enabled = true;
//
// progressBarLogin
//
progressBarLogin.BackColor = SystemColors.ControlDark;
progressBarLogin.ForeColor = Color.Transparent;
progressBarLogin.Location = new Point(788, 369);
progressBarLogin.Location = new Point(787, 369);
progressBarLogin.Name = "progressBarLogin";
progressBarLogin.Size = new Size(24, 23);
progressBarLogin.Style = ProgressBarStyle.Continuous;
@ -260,6 +260,7 @@
//
ForgotPwdLabel.AutoSize = true;
ForgotPwdLabel.BackColor = Color.Transparent;
ForgotPwdLabel.Cursor = Cursors.Hand;
ForgotPwdLabel.Font = new Font("Segoe UI", 11F, FontStyle.Bold, GraphicsUnit.Point);
ForgotPwdLabel.ForeColor = Color.White;
ForgotPwdLabel.Location = new Point(652, 410);
@ -315,7 +316,7 @@
notifyIcon.Icon = (Icon)resources.GetObject("notifyIcon.Icon");
notifyIcon.Text = "Rusty Hearts";
notifyIcon.Visible = true;
notifyIcon.MouseClick += notifyIcon_MouseClick;
notifyIcon.MouseClick += NotifyIcon_MouseClick;
//
// LoginForm
//
@ -323,7 +324,7 @@
AutoScaleMode = AutoScaleMode.Font;
AutoSize = true;
BackColor = Color.Magenta;
BackgroundImage = Properties.Resources.login_bg;
BackgroundImage = (Image)resources.GetObject("$this.BackgroundImage");
BackgroundImageLayout = ImageLayout.Stretch;
ClientSize = new Size(874, 497);
Controls.Add(VersionLabel);
@ -370,7 +371,7 @@
private ImageList imageListRegister;
private CheckBox CheckBoxAutoLogin;
private CheckBox CheckBoxSaveUser;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Timer timer;
private ProgressBar progressBarLogin;
private Label ForgotPwdLabel;
private Label VersionLabel;

View file

@ -1,8 +1,7 @@
using Newtonsoft.Json;
using RHLauncher.Helper;
using RHLauncher.RHLauncher;
using RHLauncher.RHLauncher.Helper;
using System.Diagnostics;
using RHLauncher.RHLauncher.Http;
using RHLauncher.RHLauncher.i8n;
using System.Text.RegularExpressions;
namespace RHLauncher
@ -11,10 +10,10 @@ namespace RHLauncher
{
private RegistryHandler registryHandler = new();
public string windyCode = string.Empty;
public string password = string.Empty;
public string LoginUrl = Configuration.Default.LoginUrl;
public string Lang = Configuration.Default.Lang;
private string windyCode = string.Empty;
private string password = string.Empty;
private readonly string LoginUrl = Configuration.Default.LoginUrl;
private readonly string Lang = Configuration.Default.Lang;
private List<Button>? buttons;
private List<ImageList>? imageLists;
private Dictionary<string, List<ImageList>>? languageImageLists;
@ -43,8 +42,8 @@ namespace RHLauncher
private void LoadLocalizedStrings()
{
// Initialize buttons and image lists
buttons = new List<Button> { LoginButton, RegisterButton };
imageLists = new List<ImageList> { imageListLogin, imageListRegister };
buttons = [LoginButton, RegisterButton];
imageLists = [imageListLogin, imageListRegister];
// Initialize language-specific image lists
languageImageLists = new Dictionary<string, List<ImageList>>
@ -58,11 +57,11 @@ namespace RHLauncher
LocalizationHelper.LoadLocalizedStrings(Lang, buttons, imageLists, languageImageLists);
}
#region Methods
#region Form Events
private async void LoginForm_Load(object sender, EventArgs e)
{
string currentVersion = GetLauncherVersion();
string currentVersion = GetLauncherVersion.GetVersion();
VersionLabel.Text = $"{LocalizedStrings.Version}: {currentVersion}";
registryHandler = new RegistryHandler();
@ -85,38 +84,40 @@ namespace RHLauncher
}
private static async Task CheckForLauncherUpdate()
private void LoginForm_FormClosing(object sender, FormClosingEventArgs e)
{
try
notifyIcon.Visible = false;
notifyIcon?.Dispose();
if (e.CloseReason == CloseReason.UserClosing)
{
LauncherUpdater launcherUpdater = new();
await launcherUpdater.CheckForLauncherUpdateAsync();
}
catch (Exception ex)
{
HandleException(ex);
Application.Exit();
}
}
public static string GetLauncherVersion()
private void LoginForm_Resize(object sender, EventArgs e)
{
// Get the version information of the application
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(Application.ExecutablePath);
// Extract the version number
string version = $"{versionInfo.FileMajorPart}.{versionInfo.FileMinorPart}.{versionInfo.FileBuildPart}";
return version;
if (WindowState == FormWindowState.Minimized)
{
notifyIcon.Visible = true;
}
else
{
notifyIcon.Visible = false;
}
}
#endregion
#region Login Methods
private async Task Login()
{
Regex usernameRegex = RegexPatterns.UsernameRegex();
if (string.IsNullOrEmpty(UsernameTextBox.Text))
{
MsgBoxForm.Show(LocalizedStrings.LoginInsertUsername, LocalizedStrings.LoginWindowTitle);
return;
}
if (!UsernameRegex().IsMatch(UsernameTextBox.Text))
if (!usernameRegex.IsMatch(UsernameTextBox.Text))
{
MsgBoxForm.Show(LocalizedStrings.LoginInvalidUsernameFormat, LocalizedStrings.LoginWindowTitle);
return;
@ -149,9 +150,6 @@ namespace RHLauncher
}
}
[GeneratedRegex("^[a-z0-9]{6,50}$|^[\\w\\d._%+-]+@[\\w\\d.-]+\\.[\\w]{2,}$")]
private static partial Regex UsernameRegex();
private async void AutoLogin()
{
if (CheckBoxAutoLogin.Checked)
@ -173,12 +171,12 @@ namespace RHLauncher
private async Task<string> SendLoginRequestAsync()
{
using HttpClient client = new();
using HttpResponseMessage response = await client.PostAsync(LoginUrl, new FormUrlEncodedContent(new[]
{
using HttpResponseMessage response = await client.PostAsync(LoginUrl, new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("account", UsernameTextBox.Text),
new KeyValuePair<string, string>("password", PasswordTextBox.Text)
}));
]));
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
@ -186,37 +184,63 @@ namespace RHLauncher
{
try
{
Dictionary<string, string>? loginResponse = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
var loginResponse = JsonConvert.DeserializeObject<LoginResponse>(response);
switch (loginResponse["Result"])
if (loginResponse == null)
{
MsgBoxForm.Show(LocalizedStrings.Error + $": {LocalizedStrings.HttpResponseNull}", LocalizedStrings.Error);
return;
}
switch (loginResponse.Result)
{
case "LoginSuccess":
windyCode = loginResponse["WindyCode"];
password = loginResponse["Token"];
Hide();
notifyIcon.Visible = false;
LauncherForm launcherForm = new(windyCode, password);
launcherForm.ShowDialog();
if (!string.IsNullOrEmpty(loginResponse.WindyCode) && !string.IsNullOrEmpty(loginResponse.Token))
{
windyCode = loginResponse.WindyCode;
password = loginResponse.Token;
progressBarLogin.Visible = false;
Hide();
notifyIcon.Visible = false;
LauncherForm launcherForm = new(windyCode, password);
launcherForm.ShowDialog();
}
else
{
MsgBoxForm.Show(LocalizedStrings.Error + " Missing token or windyCode.", LocalizedStrings.Error);
}
break;
case "InvalidCredentials":
MsgBoxForm.Show(LocalizedStrings.LoginInvalidCredentials, LocalizedStrings.LoginInfoTitle);
break;
case "InvalidUsernameFormat":
MsgBoxForm.Show(LocalizedStrings.LoginInvalidUsernameFormat, LocalizedStrings.LoginInfoTitle);
break;
case "AccountNotFound":
MsgBoxForm.Show(LocalizedStrings.LoginInvalidCredentials, LocalizedStrings.LoginInfoTitle);
break;
case "Locked":
MsgBoxForm.Show(LocalizedStrings.LoginLocked, LocalizedStrings.LoginInfoTitle);
break;
case "TooManyAttempts":
MsgBoxForm.Show(LocalizedStrings.LoginTooManyAttempts, LocalizedStrings.LoginInfoTitle);
break;
case "InvalidRequest":
case "ServerError":
if (!string.IsNullOrEmpty(loginResponse.Message))
{
MsgBoxForm.Show(loginResponse.Message, LocalizedStrings.Error);
}
else
{
MsgBoxForm.Show(LocalizedStrings.Error + ": " + loginResponse.Result, LocalizedStrings.Error);
}
break;
default:
MsgBoxForm.Show(LocalizedStrings.Error + loginResponse["Result"], LocalizedStrings.Error);
MsgBoxForm.Show(LocalizedStrings.Error + ": " + loginResponse.Result, LocalizedStrings.Error);
break;
}
}
catch (Exception ex)
{
@ -224,15 +248,6 @@ namespace RHLauncher
}
}
private static void HandleException(Exception ex)
{
string errorMessage = ex.Message;
string errorLog = ex.Message + ex.StackTrace;
Exception newEx = new(errorMessage, ex);
Exception newLogEx = new(errorLog, ex);
ExceptionHandler.HandleException(newEx, newLogEx);
}
private void CheckBoxAutoLogin_CheckedChanged(object sender, EventArgs e)
{
if (CheckBoxAutoLogin.Checked)
@ -262,37 +277,72 @@ namespace RHLauncher
registryHandler.SaveUser("", false);
}
}
#endregion
#region Methods
private static async Task CheckForLauncherUpdate()
{
try
{
LauncherUpdater launcherUpdater = new();
await launcherUpdater.CheckForLauncherUpdateAsync();
}
catch (Exception ex)
{
HandleException(ex);
}
}
private static void HandleException(Exception ex)
{
string errorMessage = ex.Message;
string errorLog = ex.Message + ex.StackTrace;
Exception newEx = new(errorMessage, ex);
Exception newLogEx = new(errorLog, ex);
ExceptionHandler.HandleException(newEx, newLogEx);
}
#endregion
#region Button Click Events
private async void LoginButton_Click(object sender, EventArgs e)
{
await Login();
}
private void OnMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
try
{
FormUtils.MoveForm(Handle);
await Login();
}
catch (Exception ex)
{
HandleException(ex);
}
}
private void RegisterButton_Click(object sender, EventArgs e)
{
using RegForm RegisterForm = new();
RegisterForm.ShowDialog();
try
{
using RegisterForm RegisterForm = new();
RegisterForm.ShowDialog();
}
catch (Exception ex)
{
HandleException(ex);
}
}
private void ForgotPwdLabel_Click(object sender, EventArgs e)
{
using ChangePwd ChangePwd = new();
ChangePwd.ShowDialog();
try
{
using ChangePwdForm ChangePwd = new();
ChangePwd.ShowDialog();
}
catch (Exception ex)
{
HandleException(ex);
}
}
private void CloseButton_Click(object sender, EventArgs e)
{
Close();
@ -303,31 +353,17 @@ namespace RHLauncher
WindowState = FormWindowState.Minimized;
}
private void OnMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
FormUtils.MoveForm(Handle);
}
}
#endregion
#region Button Events
private void LoginForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
Application.Exit();
}
}
private void LoginForm_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
notifyIcon.Visible = true;
}
else
{
notifyIcon.Visible = false;
}
}
private void notifyIcon_MouseClick(object sender, MouseEventArgs e)
private void NotifyIcon_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
@ -337,61 +373,28 @@ namespace RHLauncher
}
}
private void MinimizeButton_MouseHover(object sender, EventArgs e)
private void Button_MouseHover(object sender, EventArgs e)
{
MinimizeButton.ImageIndex = 1;
if (sender is Button button)
{
button.ImageIndex = 1;
}
}
private void MinimizeButton_MouseLeave(object sender, EventArgs e)
private void Button_MouseLeave(object sender, EventArgs e)
{
MinimizeButton.ImageIndex = 0;
}
private void MinimizeButton_OnMouseDown(object sender, MouseEventArgs e)
{
MinimizeButton.ImageIndex = 2;
if (sender is Button button)
{
button.ImageIndex = 0;
}
}
private void CloseButton_MouseHover(object sender, EventArgs e)
private void Button_MouseDown(object sender, MouseEventArgs e)
{
CloseButton.ImageIndex = 1;
}
private void CloseButton_MouseLeave(object sender, EventArgs e)
{
CloseButton.ImageIndex = 0;
}
private void CloseButton_OnMouseDown(object sender, MouseEventArgs e)
{
CloseButton.ImageIndex = 2;
}
private void LoginButton_MouseHover(object sender, EventArgs e)
{
LoginButton.ImageIndex = 1;
}
private void LoginButton_MouseLeave(object sender, EventArgs e)
{
LoginButton.ImageIndex = 0;
}
private void LoginButton_OnMouseDown(object sender, MouseEventArgs e)
{
LoginButton.ImageIndex = 2;
}
private void RegisterButton_MouseHover(object sender, EventArgs e)
{
RegisterButton.ImageIndex = 1;
}
private void RegisterButton_MouseLeave(object sender, EventArgs e)
{
RegisterButton.ImageIndex = 0;
}
private void RegisterButton_OnMouseDown(object sender, MouseEventArgs e)
{
RegisterButton.ImageIndex = 2;
if (sender is Button button)
{
button.ImageIndex = 2;
}
}
private void ForgotPwdLabel_MouseHover(object sender, EventArgs e)
@ -406,6 +409,5 @@ namespace RHLauncher
#endregion
}
}

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@
imageListOKBtn = new ImageList(components);
TitleLabel = new Label();
TextLabel = new Label();
textBox1 = new TextBox();
tbMessage = new TextBox();
YesButton = new Button();
imageListBtn = new ImageList(components);
NoButton = new Button();
@ -54,15 +54,15 @@
CloseButton.ImageIndex = 0;
CloseButton.ImageList = imageListCloseBtn;
CloseButton.ImeMode = ImeMode.NoControl;
CloseButton.Location = new Point(613, 16);
CloseButton.Location = new Point(607, 9);
CloseButton.Name = "CloseButton";
CloseButton.Size = new Size(32, 29);
CloseButton.TabIndex = 8;
CloseButton.UseVisualStyleBackColor = false;
CloseButton.Click += CloseButton_Click;
CloseButton.MouseDown += CloseButton_OnMouseDown;
CloseButton.MouseLeave += CloseButton_MouseLeave;
CloseButton.MouseHover += CloseButton_MouseHover;
CloseButton.MouseDown += Button_MouseDown;
CloseButton.MouseLeave += Button_MouseLeave;
CloseButton.MouseHover += Button_MouseHover;
//
// imageListCloseBtn
//
@ -83,15 +83,15 @@
OkButton.ImageIndex = 0;
OkButton.ImageList = imageListOKBtn;
OkButton.ImeMode = ImeMode.NoControl;
OkButton.Location = new Point(268, 234);
OkButton.Location = new Point(268, 224);
OkButton.Name = "OkButton";
OkButton.Size = new Size(110, 44);
OkButton.TabIndex = 9;
OkButton.UseVisualStyleBackColor = false;
OkButton.Click += OkButton_Click;
OkButton.MouseDown += OkButton_OnMouseDown;
OkButton.MouseLeave += OkButton_MouseLeave;
OkButton.MouseHover += OkButton_MouseHover;
OkButton.MouseDown += Button_MouseDown;
OkButton.MouseLeave += Button_MouseLeave;
OkButton.MouseHover += Button_MouseHover;
//
// imageListOKBtn
//
@ -112,7 +112,7 @@
TitleLabel.ForeColor = Color.White;
TitleLabel.ImageAlign = ContentAlignment.TopRight;
TitleLabel.ImeMode = ImeMode.NoControl;
TitleLabel.Location = new Point(295, 30);
TitleLabel.Location = new Point(285, 20);
TitleLabel.Name = "TitleLabel";
TitleLabel.Size = new Size(40, 20);
TitleLabel.TabIndex = 10;
@ -128,7 +128,7 @@
TextLabel.Font = new Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point);
TextLabel.ForeColor = Color.White;
TextLabel.ImeMode = ImeMode.NoControl;
TextLabel.Location = new Point(39, 72);
TextLabel.Location = new Point(39, 62);
TextLabel.MaximumSize = new Size(550, 0);
TextLabel.MinimumSize = new Size(50, 0);
TextLabel.Name = "TextLabel";
@ -136,16 +136,16 @@
TextLabel.TabIndex = 11;
TextLabel.Text = "Text";
//
// textBox1
// tbMessage
//
textBox1.Location = new Point(106, 99);
textBox1.Multiline = true;
textBox1.Name = "textBox1";
textBox1.ReadOnly = true;
textBox1.ScrollBars = ScrollBars.Vertical;
textBox1.Size = new Size(441, 129);
textBox1.TabIndex = 12;
textBox1.WordWrap = false;
tbMessage.Location = new Point(106, 88);
tbMessage.Multiline = true;
tbMessage.Name = "tbMessage";
tbMessage.ReadOnly = true;
tbMessage.ScrollBars = ScrollBars.Vertical;
tbMessage.Size = new Size(441, 129);
tbMessage.TabIndex = 12;
tbMessage.WordWrap = false;
//
// YesButton
//
@ -159,16 +159,16 @@
YesButton.ImageIndex = 0;
YesButton.ImageList = imageListBtn;
YesButton.ImeMode = ImeMode.NoControl;
YesButton.Location = new Point(164, 234);
YesButton.Location = new Point(164, 224);
YesButton.Name = "YesButton";
YesButton.Size = new Size(110, 44);
YesButton.TabIndex = 13;
YesButton.Text = "Yes";
YesButton.UseVisualStyleBackColor = false;
YesButton.Click += YesButton_Click;
YesButton.MouseDown += YesButton_OnMouseDown;
YesButton.MouseLeave += YesButton_MouseLeave;
YesButton.MouseHover += YesButton_MouseHover;
YesButton.MouseDown += Button_MouseDown;
YesButton.MouseLeave += Button_MouseLeave;
YesButton.MouseHover += Button_MouseHover;
//
// imageListBtn
//
@ -191,28 +191,28 @@
NoButton.ImageIndex = 0;
NoButton.ImageList = imageListBtn;
NoButton.ImeMode = ImeMode.NoControl;
NoButton.Location = new Point(373, 234);
NoButton.Location = new Point(373, 224);
NoButton.Name = "NoButton";
NoButton.Size = new Size(110, 44);
NoButton.TabIndex = 14;
NoButton.Text = "No";
NoButton.UseVisualStyleBackColor = false;
NoButton.Click += NoButton_Click;
NoButton.MouseDown += NoButton_OnMouseDown;
NoButton.MouseLeave += NoButton_MouseLeave;
NoButton.MouseHover += NoButton_MouseHover;
NoButton.MouseDown += Button_MouseDown;
NoButton.MouseLeave += Button_MouseLeave;
NoButton.MouseHover += Button_MouseHover;
//
// MsgBoxForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = Color.Black;
BackgroundImage = Properties.Resources.message_bkg;
BackColor = Color.Magenta;
BackgroundImage = (Image)resources.GetObject("$this.BackgroundImage");
BackgroundImageLayout = ImageLayout.Center;
ClientSize = new Size(666, 292);
ClientSize = new Size(646, 272);
Controls.Add(NoButton);
Controls.Add(YesButton);
Controls.Add(textBox1);
Controls.Add(tbMessage);
Controls.Add(TextLabel);
Controls.Add(TitleLabel);
Controls.Add(OkButton);
@ -223,7 +223,7 @@
Name = "MsgBoxForm";
StartPosition = FormStartPosition.CenterScreen;
Text = "Message";
TransparencyKey = Color.Black;
TransparencyKey = Color.Magenta;
FormClosing += MsgBoxForm_FormClosing;
Load += MsgBoxForm_Load;
ResumeLayout(false);
@ -238,7 +238,7 @@
private ImageList imageListOKBtn;
private Label TitleLabel;
private Label TextLabel;
private TextBox textBox1;
private TextBox tbMessage;
private Button YesButton;
private ImageList imageListBtn;
private Button NoButton;

View file

@ -1,9 +1,11 @@
using RHLauncher.RHLauncher;
using RHLauncher.RHLauncher.i8n;
using System.ComponentModel;
namespace RHLauncher
{
public partial class MsgBoxForm : Form
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new DialogResult DialogResult { get; private set; }
public MsgBoxForm()
@ -15,6 +17,20 @@ namespace RHLauncher
NoButton.Text = LocalizedStrings.No;
}
#region Form Events
private void MsgBoxForm_Load(object sender, EventArgs e)
{
TitleLabel.Left = (ClientSize.Width - TitleLabel.Width) / 2;
OkButton.Left = (ClientSize.Width - OkButton.Width) / 2;
}
private void MsgBoxForm_FormClosing(object sender, FormClosingEventArgs e)
{
Dispose();
}
#endregion
#region Button Click Events
private void YesButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Yes;
@ -27,10 +43,22 @@ namespace RHLauncher
Close();
}
private void CloseButton_Click(object sender, EventArgs e)
{
Close();
}
private void OkButton_Click(object sender, EventArgs e)
{
Close();
}
#endregion
#region Methods
public static void Show(string message, string title)
{
MsgBoxForm msgBox = new();
msgBox.textBox1.Visible = false;
msgBox.tbMessage.Visible = false;
msgBox.YesButton.Visible = false;
msgBox.NoButton.Visible = false;
msgBox.TextLabel.Text = message;
@ -41,11 +69,11 @@ namespace RHLauncher
public static void ShowST(string message, string title, string stacktrace)
{
MsgBoxForm msgBox = new();
msgBox.textBox1.Visible = true;
msgBox.tbMessage.Visible = true;
msgBox.YesButton.Visible = false;
msgBox.NoButton.Visible = false;
msgBox.TextLabel.Text = message;
msgBox.textBox1.Text = stacktrace;
msgBox.tbMessage.Text = stacktrace;
msgBox.TitleLabel.Text = title;
msgBox.ShowDialog();
}
@ -53,7 +81,7 @@ namespace RHLauncher
public static DialogResult ShowYN(string message, string title)
{
MsgBoxForm msgBox = new();
msgBox.textBox1.Visible = false;
msgBox.tbMessage.Visible = false;
msgBox.OkButton.Visible = false;
msgBox.YesButton.Visible = true;
msgBox.NoButton.Visible = true;
@ -63,83 +91,32 @@ namespace RHLauncher
return msgBox.DialogResult;
}
#endregion
private void CloseButton_Click(object sender, EventArgs e)
#region Button Events
private void Button_MouseHover(object sender, EventArgs e)
{
Close();
if (sender is Button button)
{
button.ImageIndex = 1;
}
}
private void OkButton_Click(object sender, EventArgs e)
private void Button_MouseLeave(object sender, EventArgs e)
{
Close();
if (sender is Button button)
{
button.ImageIndex = 0;
}
}
private void CloseButton_MouseHover(object sender, EventArgs e)
private void Button_MouseDown(object sender, MouseEventArgs e)
{
CloseButton.ImageIndex = 1;
}
private void CloseButton_MouseLeave(object sender, EventArgs e)
{
CloseButton.ImageIndex = 0;
}
private void CloseButton_OnMouseDown(object sender, MouseEventArgs e)
{
CloseButton.ImageIndex = 2;
}
private void OkButton_MouseHover(object sender, EventArgs e)
{
OkButton.ImageIndex = 1;
}
private void OkButton_MouseLeave(object sender, EventArgs e)
{
OkButton.ImageIndex = 0;
}
private void OkButton_OnMouseDown(object sender, MouseEventArgs e)
{
OkButton.ImageIndex = 2;
}
private void YesButton_MouseHover(object sender, EventArgs e)
{
YesButton.ImageIndex = 1;
}
private void YesButton_MouseLeave(object sender, EventArgs e)
{
YesButton.ImageIndex = 0;
}
private void YesButton_OnMouseDown(object sender, MouseEventArgs e)
{
YesButton.ImageIndex = 2;
}
private void NoButton_MouseHover(object sender, EventArgs e)
{
NoButton.ImageIndex = 1;
}
private void NoButton_MouseLeave(object sender, EventArgs e)
{
NoButton.ImageIndex = 0;
}
private void NoButton_OnMouseDown(object sender, MouseEventArgs e)
{
NoButton.ImageIndex = 2;
}
private void MsgBoxForm_Load(object sender, EventArgs e)
{
TitleLabel.Left = (ClientSize.Width - TitleLabel.Width) / 2;
OkButton.Left = (ClientSize.Width - OkButton.Width) / 2;
}
private void MsgBoxForm_FormClosing(object sender, FormClosingEventArgs e)
{
Dispose();
if (sender is Button button)
{
button.ImageIndex = 2;
}
}
#endregion
}
}

View file

@ -1,6 +1,6 @@
namespace RHLauncher
{
partial class RegForm
partial class RegisterForm
{
/// <summary>
/// Required designer variable.
@ -29,7 +29,7 @@
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RegForm));
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RegisterForm));
CloseButton = new Button();
imageListCloseBtn = new ImageList(components);
MinimizeButton = new Button();
@ -57,7 +57,7 @@
AgreementLabel = new Label();
AgreeCheckBox = new CheckBox();
NamePictureBox = new PictureBox();
NameTextBox = new TextBox();
UsernameTextBox = new TextBox();
NameDescLabel = new Label();
NameLabel = new Label();
PwdConfirmPictureBox = new PictureBox();
@ -102,9 +102,9 @@
CloseButton.TabIndex = 9;
CloseButton.UseVisualStyleBackColor = false;
CloseButton.Click += CloseButton_Click;
CloseButton.MouseDown += CloseButton_OnMouseDown;
CloseButton.MouseLeave += CloseButton_MouseLeave;
CloseButton.MouseHover += CloseButton_MouseHover;
CloseButton.MouseDown += Button_MouseDown;
CloseButton.MouseLeave += Button_MouseLeave;
CloseButton.MouseHover += Button_MouseHover;
//
// imageListCloseBtn
//
@ -132,9 +132,9 @@
MinimizeButton.TabIndex = 8;
MinimizeButton.UseVisualStyleBackColor = false;
MinimizeButton.Click += MinimizeButton_Click;
MinimizeButton.MouseDown += MinimizeButton_OnMouseDown;
MinimizeButton.MouseLeave += MinimizeButton_MouseLeave;
MinimizeButton.MouseHover += MinimizeButton_MouseHover;
MinimizeButton.MouseDown += Button_MouseDown;
MinimizeButton.MouseLeave += Button_MouseLeave;
MinimizeButton.MouseHover += Button_MouseHover;
//
// imageListMinBtn
//
@ -186,9 +186,9 @@
ContinueButtonS1.TabIndex = 16;
ContinueButtonS1.UseVisualStyleBackColor = false;
ContinueButtonS1.Click += ContinueButtonS1_Click;
ContinueButtonS1.MouseDown += ContinueButtonS1_OnMouseDown;
ContinueButtonS1.MouseLeave += ContinueButtonS1_MouseLeave;
ContinueButtonS1.MouseHover += ContinueButtonS1_MouseHover;
ContinueButtonS1.MouseDown += Button_MouseDown;
ContinueButtonS1.MouseLeave += Button_MouseLeave;
ContinueButtonS1.MouseHover += Button_MouseHover;
//
// PasswordLabel
//
@ -238,9 +238,9 @@
SendEmailButton.TabIndex = 21;
SendEmailButton.UseVisualStyleBackColor = false;
SendEmailButton.Click += SendEmailButton_Click;
SendEmailButton.MouseDown += SendEmailButton_OnMouseDown;
SendEmailButton.MouseLeave += SendEmailButton_MouseLeave;
SendEmailButton.MouseHover += SendEmailButton_MouseHover;
SendEmailButton.MouseDown += Button_MouseDown;
SendEmailButton.MouseLeave += Button_MouseLeave;
SendEmailButton.MouseHover += Button_MouseHover;
//
// imageListSendEmailBtn
//
@ -403,7 +403,7 @@
Stage2Panel.Controls.Add(AgreementLabel);
Stage2Panel.Controls.Add(AgreeCheckBox);
Stage2Panel.Controls.Add(NamePictureBox);
Stage2Panel.Controls.Add(NameTextBox);
Stage2Panel.Controls.Add(UsernameTextBox);
Stage2Panel.Controls.Add(NameDescLabel);
Stage2Panel.Controls.Add(NameLabel);
Stage2Panel.Controls.Add(PwdConfirmPictureBox);
@ -444,6 +444,7 @@
AgreementLabel.AutoEllipsis = true;
AgreementLabel.AutoSize = true;
AgreementLabel.BackColor = Color.Transparent;
AgreementLabel.Cursor = Cursors.Hand;
AgreementLabel.Font = new Font("Segoe UI", 10F, FontStyle.Bold, GraphicsUnit.Point);
AgreementLabel.ForeColor = Color.Gainsboro;
AgreementLabel.ImeMode = ImeMode.NoControl;
@ -454,8 +455,8 @@
AgreementLabel.Text = "\"User Agreement\"";
AgreementLabel.TextAlign = ContentAlignment.TopCenter;
AgreementLabel.Click += AgreementLabel_Click;
AgreementLabel.MouseLeave += AgreementLabel_MouseLeave;
AgreementLabel.MouseHover += AgreementLabel_MouseHover;
AgreementLabel.MouseLeave += Label_MouseLeave;
AgreementLabel.MouseHover += Label_MouseHover;
//
// AgreeCheckBox
//
@ -480,13 +481,13 @@
NamePictureBox.TabIndex = 39;
NamePictureBox.TabStop = false;
//
// NameTextBox
// UsernameTextBox
//
NameTextBox.Location = new Point(93, 147);
NameTextBox.Name = "NameTextBox";
NameTextBox.Size = new Size(279, 23);
NameTextBox.TabIndex = 38;
NameTextBox.TextChanged += NameTextBox_TextChanged;
UsernameTextBox.Location = new Point(93, 147);
UsernameTextBox.Name = "UsernameTextBox";
UsernameTextBox.Size = new Size(279, 23);
UsernameTextBox.TabIndex = 38;
UsernameTextBox.TextChanged += NameTextBox_TextChanged;
//
// NameDescLabel
//
@ -587,6 +588,7 @@
ReturnLabelS2.AutoEllipsis = true;
ReturnLabelS2.AutoSize = true;
ReturnLabelS2.BackColor = Color.Transparent;
ReturnLabelS2.Cursor = Cursors.Hand;
ReturnLabelS2.Font = new Font("Segoe UI", 10F, FontStyle.Bold, GraphicsUnit.Point);
ReturnLabelS2.ForeColor = Color.Gainsboro;
ReturnLabelS2.ImeMode = ImeMode.NoControl;
@ -597,8 +599,8 @@
ReturnLabelS2.Text = "< Return";
ReturnLabelS2.TextAlign = ContentAlignment.TopCenter;
ReturnLabelS2.Click += ReturnLabel_Click;
ReturnLabelS2.MouseLeave += ReturnLabelS2_MouseLeave;
ReturnLabelS2.MouseHover += ReturnLabelS2_MouseHover;
ReturnLabelS2.MouseLeave += Label_MouseLeave;
ReturnLabelS2.MouseHover += Label_MouseHover;
//
// ContinueButtonS2
//
@ -610,14 +612,15 @@
ContinueButtonS2.ImageIndex = 0;
ContinueButtonS2.ImageList = imageListContinueBtn;
ContinueButtonS2.ImeMode = ImeMode.NoControl;
ContinueButtonS2.Location = new Point(95, 351);
ContinueButtonS2.Location = new Point(94, 351);
ContinueButtonS2.Name = "ContinueButtonS2";
ContinueButtonS2.Size = new Size(110, 44);
ContinueButtonS2.TabIndex = 26;
ContinueButtonS2.UseVisualStyleBackColor = false;
ContinueButtonS2.Click += ContinueButtonS2_Click;
ContinueButtonS2.MouseLeave += ContinueButtonS2_MouseLeave;
ContinueButtonS2.MouseHover += ContinueButtonS2_MouseHover;
ContinueButtonS2.MouseDown += Button_MouseDown;
ContinueButtonS2.MouseLeave += Button_MouseLeave;
ContinueButtonS2.MouseHover += Button_MouseHover;
//
// PasswordTextBox
//
@ -713,12 +716,12 @@
imageListContinueBtn_ko.Images.SetKeyName(1, "Registerwnd_button_continue_active_ko.png");
imageListContinueBtn_ko.Images.SetKeyName(2, "Registerwnd_button_continue_down_ko.png");
//
// RegForm
// RegisterForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = Color.Black;
BackgroundImage = Properties.Resources.bg;
BackgroundImage = (Image)resources.GetObject("$this.BackgroundImage");
BackgroundImageLayout = ImageLayout.Center;
ClientSize = new Size(800, 571);
Controls.Add(CloseButton);
@ -728,7 +731,7 @@
DoubleBuffered = true;
FormBorderStyle = FormBorderStyle.None;
Icon = (Icon)resources.GetObject("$this.Icon");
Name = "RegForm";
Name = "RegisterForm";
StartPosition = FormStartPosition.CenterScreen;
Text = "Register Account";
FormClosing += RegForm_FormClosing;
@ -784,7 +787,7 @@
private Label EmailLabel;
private ImageList imageListOkBtn;
private PictureBox NamePictureBox;
private TextBox NameTextBox;
private TextBox UsernameTextBox;
private Label NameDescLabel;
private Label NameLabel;
private CheckBox AgreeCheckBox;

View file

@ -1,17 +1,18 @@
using RHLauncher.RHLauncher;
using Newtonsoft.Json;
using RHLauncher.RHLauncher.Helper;
using RHLauncher.RHLauncher.i8n;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace RHLauncher
{
public partial class RegForm : Form
public partial class RegisterForm : Form
{
public string SendCodeUrl = Configuration.Default.SendCodeUrl;
public string AgreementUrl = Configuration.Default.AgreementUrl;
public string VerifyCodeUrl = Configuration.Default.VerifyCodeUrl;
public string RegisterUrl = Configuration.Default.RegisterUrl;
public string Lang = Configuration.Default.Lang;
private readonly string SendCodeUrl = Configuration.Default.SendCodeUrl;
private readonly string AgreementUrl = Configuration.Default.AgreementUrl;
private readonly string VerifyCodeUrl = Configuration.Default.VerifyCodeUrl;
private readonly string RegisterUrl = Configuration.Default.RegisterUrl;
private readonly string Lang = Configuration.Default.Lang;
private List<Button>? buttons;
private List<ImageList>? imageLists;
private Dictionary<string, List<ImageList>>? languageImageLists;
@ -19,7 +20,7 @@ namespace RHLauncher
private readonly System.Windows.Forms.Timer resendTimer = new();
private int secondsLeft = 60;
public RegForm()
public RegisterForm()
{
InitializeComponent();
@ -55,45 +56,67 @@ namespace RHLauncher
private void LoadLocalizedStrings()
{
// Initialize buttons and image lists
buttons = new List<Button> { ContinueButtonS1, SendEmailButton, ContinueButtonS2 };
imageLists = new List<ImageList> { imageListContinueBtn, imageListSendEmailBtn, imageListContinueBtn };
buttons = [ContinueButtonS1, SendEmailButton, ContinueButtonS2];
imageLists = [imageListContinueBtn, imageListSendEmailBtn, imageListContinueBtn];
// Initialize language-specific image lists
languageImageLists = new Dictionary<string, List<ImageList>>
{
{ "en", new List<ImageList> { imageListContinueBtn, imageListSendEmailBtn, imageListContinueBtn } }, // English image lists
{ "ko", new List<ImageList> { imageListContinueBtn_ko, imageListSendEmailBtn_ko, imageListContinueBtn_ko } }, // Korean image lists
// Add other languages and their respective image lists here
};
{
{ "en", new List<ImageList> { imageListContinueBtn, imageListSendEmailBtn, imageListContinueBtn } }, // English image lists
{ "ko", new List<ImageList> { imageListContinueBtn_ko, imageListSendEmailBtn_ko, imageListContinueBtn_ko } }, // Korean image lists
// Add other languages and their respective image lists here
};
// Load the appropriate resource file based on the selected language
LocalizationHelper.LoadLocalizedStrings(Lang, buttons, imageLists, languageImageLists);
}
#region Form Events
private void RegForm_Load(object sender, EventArgs e)
{
ContinueButtonS1.Enabled = false;
}
private void RegForm_FormClosing(object sender, FormClosingEventArgs e)
{
resendTimer.Dispose();
Dispose();
}
#endregion
#region Methods
private async Task<string> SendEmailRequestAsync()
{
using HttpClient client = new();
using HttpResponseMessage response = await client.PostAsync(SendCodeUrl, new FormUrlEncodedContent(new[]
{
using HttpResponseMessage response = await client.PostAsync(SendCodeUrl, new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("email", EmailTextBox.Text),
}));
]));
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
private void HandleSendEmailResponse(string response)
{
switch (response)
HttpResponse? httpResponse = JsonConvert.DeserializeObject<HttpResponse>(response);
if (httpResponse == null)
{
MsgBoxForm.Show(LocalizedStrings.Error + $": {LocalizedStrings.HttpResponseNull}", LocalizedStrings.Error);
return;
}
switch (httpResponse.Result)
{
case "EmailSent":
SendEmailButton.Enabled = false;
resendTimer.Start();
break;
case "AccountExists":
MsgBoxForm.Show("A account with this email already exists.", "Info");
MsgBoxForm.Show(LocalizedStrings.AccountEmailExists, LocalizedStrings.Info);
ResetSendEmailButton();
break;
case "ValidVerificationCode":
// Hide the first panel and show the second panel
@ -104,17 +127,17 @@ namespace RHLauncher
CodePictureBox.Image = imageListTips.Images[1];
break;
case "InvalidVerificationCode":
CodeDescLabel.Text = "Invalid Verification Code";
CodeDescLabel.Text = LocalizedStrings.InvalidVerificationCode;
CodeDescLabel.ForeColor = Color.Red;
CodePictureBox.Image = imageListTips.Images[0];
return;
case "ExpiredVerificationCode":
CodeDescLabel.Text = "This verification code has expired, please request a new one.";
CodeDescLabel.Text = LocalizedStrings.ExpiredVerificationCode;
CodeDescLabel.ForeColor = Color.Red;
CodePictureBox.Image = imageListTips.Images[0];
return;
default:
MsgBoxForm.Show("An error occurred:" + response, "Error");
MsgBoxForm.Show($"{LocalizedStrings.Error}: {response}", LocalizedStrings.Error);
break;
}
}
@ -128,61 +151,75 @@ namespace RHLauncher
// If the timer has finished counting down, stop the timer and enable the ResendEmailButton
if (secondsLeft == 0)
{
resendTimer.Stop();
SendEmailButton.Enabled = true;
TimerLabel.Text = "";
ResetSendEmailButton();
}
}
private void ResetSendEmailButton()
{
resendTimer.Stop();
SendEmailButton.Enabled = true;
TimerLabel.Text = "";
}
private async Task<string> VerifyCodeSendRequestAsync()
{
using HttpClient client = new();
using HttpResponseMessage response = await client.PostAsync(VerifyCodeUrl, new FormUrlEncodedContent(new[]
{
using HttpResponseMessage response = await client.PostAsync(VerifyCodeUrl, new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("email", EmailTextBox.Text),
new KeyValuePair<string, string>("verification_code", CodeTextBox.Text),
new KeyValuePair<string, string>("verification_code_type", "Account"),
}));
new KeyValuePair<string, string>("verificationCode", CodeTextBox.Text),
new KeyValuePair<string, string>("verificationCodeType", "Account"),
]));
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
private async Task<string> SendRequestAsync()
{
using HttpClient client = new();
using HttpResponseMessage response = await client.PostAsync(RegisterUrl, new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("windyCode", NameTextBox.Text),
using HttpResponseMessage response = await client.PostAsync(RegisterUrl, new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("username", UsernameTextBox.Text),
new KeyValuePair<string, string>("email", EmailTextBox.Text),
new KeyValuePair<string, string>("password", PasswordTextBox.Text)
}));
new KeyValuePair<string, string>("password", PasswordTextBox.Text),
new KeyValuePair<string, string>("verificationCode", CodeTextBox.Text)
]));
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
private void HandleResponse(string response)
{
switch (response)
HttpResponse? accounResponse = JsonConvert.DeserializeObject<HttpResponse>(response);
if (accounResponse == null)
{
case "Success":
MsgBoxForm.Show("Account created successfully.", "Register Window");
MsgBoxForm.Show(LocalizedStrings.Error + $": {LocalizedStrings.HttpResponseNull}", LocalizedStrings.Error);
return;
}
switch (accounResponse.Result)
{
case "AccountCreated":
MsgBoxForm.Show(LocalizedStrings.AccountCreateSuccess, LocalizedStrings.RegisterWindow);
Close();
break;
case "AccountExists":
MsgBoxForm.Show("A account with this username already exists.", "Info");
case "EmailExists":
MsgBoxForm.Show(LocalizedStrings.AccountEmailExists, LocalizedStrings.Info);
break;
case "WindyCodeExists":
MsgBoxForm.Show("A game account with this username already exists.", "Error");
case "UsernameExists":
MsgBoxForm.Show(LocalizedStrings.WindyCodeExists, LocalizedStrings.Error);
break;
case "InvalidUserNameFormat":
MsgBoxForm.Show("Invalid username format", "Error");
MsgBoxForm.Show(LocalizedStrings.InvalidUserNameFormat, LocalizedStrings.Error);
break;
case "InvalidEmailFormat":
MsgBoxForm.Show("Invalid email format", "Error");
MsgBoxForm.Show(LocalizedStrings.InvalidEmailFormat, LocalizedStrings.Error);
break;
default:
MsgBoxForm.Show("An error occurred:" + response, "Error");
MsgBoxForm.Show($"{LocalizedStrings.Error}: " + accounResponse.Message, LocalizedStrings.Error);
break;
}
@ -222,9 +259,9 @@ namespace RHLauncher
try
{
string email = EmailTextBox.Text;
string pattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
if (Regex.IsMatch(email, pattern))
Regex emailRegex = RegexPatterns.EmailRegex();
if (emailRegex.IsMatch(EmailTextBox.Text))
{
// email is valid
EmailPictureBox.Image = imageListTips.Images[1];
@ -309,32 +346,32 @@ namespace RHLauncher
private bool NameTextBoxValid = false;
private void NameTextBox_TextChanged(object sender, EventArgs e)
{
Regex nameregex = new("^(?=.*[a-z])[a-z0-9]+$");
Regex usernameRegex = RegexPatterns.UsernameRegex();
if (string.IsNullOrEmpty(NameTextBox.Text) || NameTextBox.Text.Length < 6 || NameTextBox.Text.Length > 16 || !nameregex.IsMatch(NameTextBox.Text) || HasUppercase(NameTextBox.Text))
if (string.IsNullOrEmpty(UsernameTextBox.Text) || UsernameTextBox.Text.Length < 6 || UsernameTextBox.Text.Length > 16 || !usernameRegex.IsMatch(UsernameTextBox.Text) || HasUppercase(UsernameTextBox.Text))
{
if (string.IsNullOrEmpty(NameTextBox.Text))
if (string.IsNullOrEmpty(UsernameTextBox.Text))
{
NameDescLabel.Text = LocalizedStrings.UsernameDescLabelEmpty;
NameDescLabel.ForeColor = Color.Red;
NamePictureBox.Image = imageListTips.Images[0];
NameTextBoxValid = false;
}
else if (NameTextBox.Text.Length < 6 || NameTextBox.Text.Length > 16)
else if (UsernameTextBox.Text.Length < 6 || UsernameTextBox.Text.Length > 16)
{
NameDescLabel.Text = LocalizedStrings.UsernameDescLabelSize;
NameDescLabel.ForeColor = Color.Red;
NamePictureBox.Image = imageListTips.Images[0];
NameTextBoxValid = false;
}
else if (HasUppercase(NameTextBox.Text))
else if (HasUppercase(UsernameTextBox.Text))
{
NameDescLabel.Text = LocalizedStrings.UsernameDescLabelUppercase;
NameDescLabel.ForeColor = Color.Red;
NamePictureBox.Image = imageListTips.Images[0];
NameTextBoxValid = false;
}
else if (!nameregex.IsMatch(NameTextBox.Text))
else if (!usernameRegex.IsMatch(UsernameTextBox.Text))
{
NameDescLabel.Text = LocalizedStrings.UsernameDescLabelInvalid;
NameDescLabel.ForeColor = Color.Red;
@ -362,7 +399,7 @@ namespace RHLauncher
string password = PasswordTextBox.Text;
// Check for minimum length and maximum length
if (password.Length < 6 || password.Length > 16)
if (password.Length < 8 || password.Length > 16)
{
PwdDescLabel.Text = LocalizedStrings.PwdDescLabelSize;
PwdDescLabel.ForeColor = Color.Red;
@ -374,8 +411,8 @@ namespace RHLauncher
}
// Check for at least one uppercase, one lowercase letter, and one number
Regex regex = new(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$");
if (!regex.IsMatch(password))
Regex pwRegex = RegexPatterns.PWRegex();
if (!pwRegex.IsMatch(password))
{
PwdDescLabel.Text = LocalizedStrings.PwdDescLabelCriteria;
PwdDescLabel.ForeColor = Color.Red;
@ -389,8 +426,8 @@ namespace RHLauncher
}
// Check for additional character types such as symbols
regex = new Regex(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).+$");
if (regex.IsMatch(password))
Regex strongPWRegex = RegexPatterns.StrongPWRegex();
if (strongPWRegex.IsMatch(password))
{
PwdDescLabel.Text = "";
PwdPictureBox.Image = imageListTips.Images[1];
@ -449,9 +486,9 @@ namespace RHLauncher
}
try
{
string email = EmailTextBox.Text;
string pattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
if (Regex.IsMatch(email, pattern))
Regex emailRegex = RegexPatterns.EmailRegex();
if (emailRegex.IsMatch(EmailTextBox.Text))
{
// email is valid
EmailPictureBox.Image = imageListTips.Images[1];
@ -543,10 +580,6 @@ namespace RHLauncher
}
}
#endregion
#region Button Events
private void CloseButton_Click(object sender, EventArgs e)
{
Close();
@ -556,108 +589,51 @@ namespace RHLauncher
{
WindowState = FormWindowState.Minimized;
}
private void RegForm_FormClosing(object sender, FormClosingEventArgs e)
{
resendTimer.Dispose();
Dispose();
}
private void ContinueButtonS1_MouseHover(object sender, EventArgs e)
{
ContinueButtonS1.ImageIndex = 1;
}
private void ContinueButtonS1_MouseLeave(object sender, EventArgs e)
{
ContinueButtonS1.ImageIndex = 0;
}
private void ContinueButtonS1_OnMouseDown(object sender, MouseEventArgs e)
{
ContinueButtonS1.ImageIndex = 2;
}
private void ContinueButtonS2_MouseHover(object sender, EventArgs e)
{
ContinueButtonS2.ImageIndex = 1;
}
private void ContinueButtonS2_MouseLeave(object sender, EventArgs e)
{
ContinueButtonS2.ImageIndex = 0;
}
private void ContinueButtonS2_OnMouseDown(object sender, MouseEventArgs e)
{
ContinueButtonS2.ImageIndex = 2;
}
private void SendEmailButton_MouseHover(object sender, EventArgs e)
{
SendEmailButton.ImageIndex = 1;
}
private void SendEmailButton_MouseLeave(object sender, EventArgs e)
{
SendEmailButton.ImageIndex = 0;
}
private void SendEmailButton_OnMouseDown(object sender, MouseEventArgs e)
{
SendEmailButton.ImageIndex = 2;
}
private void RegForm_Load(object sender, EventArgs e)
{
ContinueButtonS1.Enabled = false;
}
private void MinimizeButton_MouseHover(object sender, EventArgs e)
{
MinimizeButton.ImageIndex = 1;
}
private void MinimizeButton_MouseLeave(object sender, EventArgs e)
{
MinimizeButton.ImageIndex = 0;
}
private void MinimizeButton_OnMouseDown(object sender, MouseEventArgs e)
{
MinimizeButton.ImageIndex = 2;
}
private void CloseButton_MouseHover(object sender, EventArgs e)
{
CloseButton.ImageIndex = 1;
}
private void CloseButton_MouseLeave(object sender, EventArgs e)
{
CloseButton.ImageIndex = 0;
}
private void CloseButton_OnMouseDown(object sender, MouseEventArgs e)
{
CloseButton.ImageIndex = 2;
}
private void ReturnLabelS2_MouseHover(object sender, EventArgs e)
{
ReturnLabelS2.ForeColor = Color.White;
}
private void ReturnLabelS2_MouseLeave(object sender, EventArgs e)
{
ReturnLabelS2.ForeColor = Color.Gainsboro;
}
private void AgreementLabel_MouseHover(object sender, EventArgs e)
{
AgreementLabel.ForeColor = Color.White;
}
private void AgreementLabel_MouseLeave(object sender, EventArgs e)
{
AgreementLabel.ForeColor = Color.Gainsboro;
}
#endregion
#region Button Events
private void Button_MouseHover(object sender, EventArgs e)
{
if (sender is Button button)
{
button.ImageIndex = 1;
}
}
private void Button_MouseLeave(object sender, EventArgs e)
{
if (sender is Button button)
{
button.ImageIndex = 0;
}
}
private void Button_MouseDown(object sender, MouseEventArgs e)
{
if (sender is Button button)
{
button.ImageIndex = 2;
}
}
private void Label_MouseHover(object sender, EventArgs e)
{
if (sender is Label label)
{
label.ForeColor = Color.White;
}
}
private void Label_MouseLeave(object sender, EventArgs e)
{
if (sender is Label label)
{
label.ForeColor = Color.Gainsboro;
}
}
#endregion
}
}

File diff suppressed because it is too large Load diff

View file

@ -6,38 +6,42 @@ public class Configuration
public static readonly Configuration Default = new();
private readonly IniFile iniFile = new(DefaultIniFilePath);
public readonly IniFile iniFile = new(DefaultIniFilePath);
public Configuration()
{
string apiUrl = iniFile.ReadValue("Info", "LoginURL");
string apiUrl = iniFile.ReadValue("Info", "ServerURL");
//Client endpoints
GateXMLUrl = $"{apiUrl}/serverApi/gateway";
GateInfoUrl = $"{apiUrl}/serverApi/gateway/info";
GateStatusUrl = $"{apiUrl}/serverApi/gateway/status";
GateXMLUrl = $"{apiUrl}/launcher/GetGatewayAction";
GateInfoUrl = $"{apiUrl}/launcher/GetGatewayAction/info";
GateStatusUrl = $"{apiUrl}/launcher/GetGatewayAction/status";
//Launcher endpoints
LoginUrl = $"{apiUrl}/accountApi/login";
RegisterUrl = $"{apiUrl}/accountApi/register";
SendCodeUrl = $"{apiUrl}/accountApi/sendVerificationEmail";
VerifyCodeUrl = $"{apiUrl}/accountApi/codeVerification";
SendPasswordCodeUrl = $"{apiUrl}/accountApi/sendPasswordResetEmail";
ChangePasswordUrl = $"{apiUrl}/accountApi/changePassword";
LoginUrl = $"{apiUrl}/launcher/LoginAction";
RegisterUrl = $"{apiUrl}/launcher/SignupAction";
SendCodeUrl = $"{apiUrl}/launcher/SendVerificationEmailAction";
VerifyCodeUrl = $"{apiUrl}/launcher/VerifyCodeAction";
SendPasswordCodeUrl = $"{apiUrl}/launcher/SendPasswordResetEmailAction";
ChangePasswordUrl = $"{apiUrl}/launcher/ResetPasswordAction";
LauncherNewsUrl = $"{apiUrl}/launcher/news";
AgreementUrl = $"{apiUrl}/launcher/agreement";
//Client download endpoints
ClientPartsListUrl = $"{apiUrl}/launcher/client/download/filelist.txt";
DownloadClientPartUrl = $"{apiUrl}/launcher/client/download";
//Client update endpoints
FileListUrl = $"{apiUrl}/launcher/patch/filelist.txt";
DownloadUpdateFileUrl = $"{apiUrl}/launcher/patch";
//Launcher update endpoints
GetLauncherVersion = $"{apiUrl}/launcherApi/launcherUpdater/getLauncherVersion";
UpdateLauncherVersion = $"{apiUrl}/launcherApi/launcherUpdater/updateLauncherVersion";
GetLauncherVersion = $"{apiUrl}/launcherAction/getLauncherVersion";
UpdateLauncherVersion = $"{apiUrl}/launcherAction/updateLauncherVersion";
//Launcher settings
string lang = iniFile.ReadValue("Launcher", "Lang");
Lang = lang;
Lang = iniFile.ReadValue("Launcher", "Lang");
Service = iniFile.ReadValue("Info", "Service");
}
public string GateXMLUrl { get; set; }
@ -55,6 +59,9 @@ public class Configuration
public string GetLauncherVersion { get; set; }
public string UpdateLauncherVersion { get; set; }
public string DownloadUpdateFileUrl { get; set; }
public string ClientPartsListUrl { get; set; }
public string DownloadClientPartUrl { get; set; }
public string Lang { get; set; }
public string Service { get; set; }
}

View file

@ -0,0 +1,49 @@
namespace RHLauncher.RHLauncher.Helper;
public static class Crc32
{
private static readonly uint[] Crc32Table = new uint[]
{
0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
public static string GetFileHash(string filePath)
{
uint crc = 0xFFFFFFFF;
using (FileStream stream = File.OpenRead(filePath))
{
int bytesRead;
byte[] buffer = new byte[4096];
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
for (int i = 0; i < bytesRead; i++)
{
byte b = buffer[i];
crc = (crc >> 8) ^ Crc32Table[(crc ^ b) & 0xFF];
}
}
}
crc ^= 0x00000000;
return crc.ToString("X8");
}
}

View file

@ -1,4 +1,4 @@
using RHLauncher.Helper;
using RHLauncher.RHLauncher.i8n;
namespace RHLauncher.RHLauncher.Helper
{
@ -6,8 +6,8 @@ namespace RHLauncher.RHLauncher.Helper
{
public static void HandleException(Exception ex, Exception exlog)
{
string errorMessage = $"Error: {ex.Message}";
string errorLog = $"Error:{ex.Message} {Environment.NewLine} {exlog.Message}";
string errorMessage = $"{LocalizedStrings.Error}: {ex.Message}";
string errorLog = $"{LocalizedStrings.Error}: {ex.Message} {Environment.NewLine} {exlog.Message}";
Logger.WriteLog(errorLog);
MsgBoxForm.Show(errorMessage, LocalizedStrings.Error);
}

View file

@ -1,6 +1,6 @@
using System.Runtime.InteropServices;
namespace RHLauncher.Helper
namespace RHLauncher.RHLauncher.Helper
{
public class FormUtils
{

View file

@ -0,0 +1,18 @@
using System.Diagnostics;
namespace RHLauncher.RHLauncher.Helper
{
public class GetLauncherVersion
{
public static string GetVersion()
{
// Get the version information of the application
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(Application.ExecutablePath);
// Extract the version number
string version = $"{versionInfo.FileMajorPart}.{versionInfo.FileMinorPart}.{versionInfo.FileBuildPart}";
return version;
}
}
}

View file

@ -0,0 +1,36 @@
using Newtonsoft.Json;
namespace RHLauncher.RHLauncher.Helper;
public class HttpResponse
{
[JsonProperty("success")]
public string? Success { get; set; }
[JsonProperty("result")]
public string? Result { get; set; }
[JsonProperty("message")]
public string? Message { get; set; }
}
public class LoginResponse
{
[JsonProperty("result")]
public string? Result { get; set; }
[JsonProperty("token")]
public string? Token { get; set; }
[JsonProperty("windyCode")]
public string? WindyCode { get; set; }
[JsonProperty("message")]
public string? Message { get; set; }
}
public class ServerStatusResponse
{
[JsonProperty("status")]
public string? Status { get; set; }
}

View file

@ -21,9 +21,9 @@ namespace RHLauncher.RHLauncher.Helper
if (!File.Exists(_iniFilePath))
{
//Default api url
WritePrivateProfileString("Info", "LoginURL", "http://localhost:3000", _iniFilePath);
WritePrivateProfileString("Info", "ServerURL", "http://127.0.0.1", _iniFilePath);
//Default client service
WritePrivateProfileString("Info", "Service", "usa", _iniFilePath);
WritePrivateProfileString("Info", "Service", "jpn", _iniFilePath);
//Default launcher language
WritePrivateProfileString("Launcher", "Lang", "en", _iniFilePath);
}

View file

@ -1,4 +1,4 @@
namespace RHLauncher.Helper;
namespace RHLauncher.RHLauncher.Helper;
public class Logger
{
@ -13,10 +13,14 @@ public class Logger
// Create log file with today's date
logFilePath = Path.Combine(logFilePath, "Log-" + DateTime.Today.ToString("MM-dd-yyyy") + ".txt");
FileInfo logFileInfo = new(logFilePath);
DirectoryInfo logDirInfo = new(logFileInfo.DirectoryName);
if (!logDirInfo.Exists)
if (logFileInfo.DirectoryName != null)
{
logDirInfo.Create();
DirectoryInfo logDirInfo = new(logFileInfo.DirectoryName);
if (!logDirInfo.Exists)
{
logDirInfo.Create();
}
}
// Write log entry to file
@ -28,4 +32,5 @@ public class Logger
streamWriter.WriteLine("Message: {0}", message);
streamWriter.WriteLine("---------------------------");
}
}

View file

@ -1,25 +1,26 @@
namespace RHLauncher.RHLauncher
namespace RHLauncher.RHLauncher.Helper
{
public class ProgressReport
{
public string? Label { get; set; }
public string? Button { get; set; }
public int PercentComplete { get; set; }
public string? FileName { get; set; }
public string? ErrorMessage { get; set; }
public long BytesDownloaded { get; set; }
public long TotalBytesToDownload { get; set; }
public long Current { get; set; }
public long Total { get; set; }
public double TotalSpeed { get; set; }
public long TimeLeft { get; set; }
public int NumFilesDownloaded { get; set; }
public int NumFiles { get; set; }
public int TotalNumFiles { get; set; }
public int NumFilesPacked { get; set; }
public int NumFilesUnpacked { get; set; }
public bool Panel { get; set; }
public CancellationToken CancellationToken { get; set; }
public bool CancellButton { get; set; }
public bool ShowFileNameLabel { get; set; }
public bool ShowSpeedLabel { get; set; }
public bool ShowTimeLabel { get; set; }
public bool ShowFileSizeLabel { get; set; }
public bool ShowFileCountLabel { get; set; }
public bool IsCheckingFilelist { get; set; }
public CancellationToken CancellationToken { get; set; }
}
}

View file

@ -0,0 +1,152 @@
using RHLauncher.RHLauncher.i8n;
using System.Diagnostics;
namespace RHLauncher.RHLauncher.Helper
{
public class ProgressReporter
{
public static void ReportFileListCheckProgress(IProgress<ProgressReport> progress, int checkedFilesCount, int totalFiles, CancellationToken cancellationToken)
{
int percentComplete = totalFiles > 0 ? (int)Math.Round(checkedFilesCount * 100.0 / totalFiles) : 0;
ProgressReport report = new()
{
Panel = true,
CancellButton = true,
ShowFileCountLabel = true,
IsCheckingFilelist = true,
Button = LocalizedStrings.Checking,
Label = LocalizedStrings.CheckingFiles,
Current = checkedFilesCount,
Total = totalFiles,
PercentComplete = percentComplete,
NumFiles = checkedFilesCount,
TotalNumFiles = totalFiles,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportDownloadProgress(IProgress<ProgressReport> progress, string fileName, long downloadedSize, long totalBytesToDownload, int downloadedFileCount, int totalFilesToDownload, Stopwatch sw, CancellationToken cancellationToken)
{
int percentComplete = totalBytesToDownload > 0 ? (int)Math.Round(downloadedSize * 100.0 / totalBytesToDownload) : 0;
double totalSpeed = downloadedSize / sw.Elapsed.TotalSeconds;
long timeLeft = totalBytesToDownload > 0 ? (long)((totalBytesToDownload - downloadedSize) / (downloadedSize / sw.Elapsed.TotalSeconds)) : 0;
ProgressReport report = new()
{
Panel = true,
CancellButton = true,
ShowFileNameLabel = true,
ShowSpeedLabel = true,
ShowTimeLabel = true,
ShowFileSizeLabel = true,
ShowFileCountLabel = true,
Button = LocalizedStrings.Downloading,
Label = LocalizedStrings.Downloading,
PercentComplete = percentComplete,
FileName = fileName,
Current = downloadedSize,
Total = totalBytesToDownload,
TotalSpeed = totalSpeed,
TimeLeft = timeLeft,
NumFiles = downloadedFileCount,
TotalNumFiles = totalFilesToDownload,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportClientDownloadProgress(IProgress<ProgressReport> progress, long downloadedSize, long totalBytesToDownload, Stopwatch sw, CancellationToken cancellationToken)
{
int percentComplete = totalBytesToDownload > 0 ? (int)Math.Round(downloadedSize * 100.0 / totalBytesToDownload) : 0;
double totalSpeed = downloadedSize / sw.Elapsed.TotalSeconds;
long timeLeft = totalBytesToDownload > 0 ? (long)((totalBytesToDownload - downloadedSize) / (downloadedSize / sw.Elapsed.TotalSeconds)) : 0;
ProgressReport report = new()
{
Panel = true,
CancellButton = true,
ShowSpeedLabel = true,
ShowTimeLabel = true,
ShowFileSizeLabel = true,
Button = LocalizedStrings.Downloading,
Label = LocalizedStrings.Downloading,
PercentComplete = percentComplete,
Current = downloadedSize,
Total = totalBytesToDownload,
TotalSpeed = totalSpeed,
TimeLeft = timeLeft,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportFileCheckingProgress(IProgress<ProgressReport> progress, int checkedFiles, int totalFiles, CancellationToken cancellationToken)
{
int percentComplete = totalFiles > 0 ? (int)Math.Round(checkedFiles * 100.0 / totalFiles) : 0;
ProgressReport report = new()
{
Panel = true,
IsCheckingFilelist = true,
Button = LocalizedStrings.Checking,
Label = LocalizedStrings.CheckingFiles,
PercentComplete = percentComplete,
Current = checkedFiles,
Total = totalFiles,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportUnzipProgress(IProgress<ProgressReport> progress, long extractedSize, long totalUncompressedSize, CancellationToken cancellationToken)
{
int percentComplete = totalUncompressedSize > 0 ? (int)(extractedSize * 100 / totalUncompressedSize) : 0;
ProgressReport report = new()
{
Panel = true,
CancellButton = true,
Button = LocalizedStrings.Installing,
Label = LocalizedStrings.Installing,
PercentComplete = percentComplete,
Current = extractedSize,
Total = totalUncompressedSize,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportErrorProgress(IProgress<ProgressReport> progress, string message, CancellationToken cancellationToken)
{
ProgressReport report = new()
{
Panel = true,
Button = LocalizedStrings.Error,
Label = LocalizedStrings.Error,
ErrorMessage = message,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportFinishedProgress(IProgress<ProgressReport> progress, CancellationToken cancellationToken)
{
ProgressReport report = new()
{
Panel = false,
Button = LocalizedStrings.Launch,
CancellationToken = cancellationToken
};
progress.Report(report);
}
}
}

View file

@ -1,4 +1,4 @@
namespace RHLauncher.RHLauncher
namespace RHLauncher.RHLauncher.Helper
{
public class ProgressThrottler : IProgress<ProgressReport>
{

View file

@ -0,0 +1,19 @@
using System.Text.RegularExpressions;
namespace RHLauncher.RHLauncher.Helper
{
public static partial class RegexPatterns
{
[GeneratedRegex(@"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")]
public static partial Regex EmailRegex();
[GeneratedRegex("^(?=.*[a-z])[a-z0-9]+$")]
public static partial Regex UsernameRegex();
[GeneratedRegex("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).+$")]
public static partial Regex PWRegex();
[GeneratedRegex("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[^\\da-zA-Z]).+$")]
public static partial Regex StrongPWRegex();
}
}

View file

@ -2,12 +2,13 @@
using System.Security.Cryptography;
using System.Text;
namespace RHLauncher.Helper
namespace RHLauncher.RHLauncher.Helper
{
public class RegistryHandler
{
private const string KEY_NAME = "RustyHearts\\UserInfo";
private const string INSTALL_DIR_KEY = "InstallDirectory";
private const string TEMP_INSTALL_DIR_KEY = "TempInstallDirectory";
private readonly RegistryKey key;
public RegistryHandler()
@ -56,6 +57,11 @@ namespace RHLauncher.Helper
key.SetValue(INSTALL_DIR_KEY, directory ?? string.Empty);
}
public void SaveTempInstallDirectory(string directory)
{
key.SetValue(TEMP_INSTALL_DIR_KEY, directory ?? string.Empty);
}
public string GetInstallDirectory()
{
return key.GetValue(INSTALL_DIR_KEY)?.ToString() ?? string.Empty;
@ -70,6 +76,20 @@ namespace RHLauncher.Helper
}
}
public string GetTempInstallDirectory()
{
return key.GetValue(TEMP_INSTALL_DIR_KEY)?.ToString() ?? string.Empty;
}
public void ClearTempInstallDirectory()
{
var value = key.GetValue(TEMP_INSTALL_DIR_KEY)?.ToString();
if (!string.IsNullOrEmpty(value))
{
key.DeleteValue(TEMP_INSTALL_DIR_KEY);
}
}
public void DeleteValues(string KEY_NAME)
{
var value = key.GetValue(KEY_NAME) as string ?? "";

View file

@ -1,4 +1,5 @@
using System.Security.Cryptography;
using RHLauncher.RHLauncher.i8n;
using System.Security.Cryptography;
namespace RHLauncher.RHLauncher.Helper
{
@ -37,13 +38,13 @@ namespace RHLauncher.RHLauncher.Helper
}
else
{
MsgBoxForm.Show("Service.dat file does not exist. Please check if the Install Directory is correct.", LocalizedStrings.Error);
MsgBoxForm.Show(LocalizedStrings.ServiceDatFileMissing, LocalizedStrings.Error);
return;
}
}
catch (Exception ex)
{
MsgBoxForm.Show("An error occurred while updating service: " + ex.Message, LocalizedStrings.Error);
MsgBoxForm.Show(LocalizedStrings.ServiceUpdateError + ": " + ex.Message, LocalizedStrings.Error);
}
}

View file

@ -0,0 +1,225 @@
using RHLauncher.RHLauncher.Helper;
using RHLauncher.RHLauncher.i8n;
using System.Diagnostics;
using System.Globalization;
using System.IO.Compression;
using System.Net;
namespace RHLauncher.RHLauncher.Http
{
public class ClientDownloader
{
public enum DownloadClientResultStatus
{
Success,
Failed,
Cancelled
}
public class DownloadClientResult
{
public DownloadClientResultStatus Status { get; set; }
public string? InstallDirectoryPath { get; set; }
}
private const int BufferSize = 8192;
private const int TimeoutSeconds = 30;
public static async Task<DownloadClientResult> DownloadClientAsync(string installDirectory, IProgress<ProgressReport> progress, CancellationToken cancellationToken)
{
using HttpClientHandler handler = new() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
using HttpClient client = new(handler, true) { Timeout = TimeSpan.FromSeconds(TimeoutSeconds) };
try
{
string filelistUrl = Configuration.Default.ClientPartsListUrl;
using HttpResponseMessage filelistResponse = await client.GetAsync(filelistUrl, cancellationToken);
if (!filelistResponse.IsSuccessStatusCode)
{
// Handle the case where the filelist URL is not found
string errorMessage = $"{LocalizedStrings.ClientDownloadErrorMessage}:\n\n{LocalizedStrings.ClientDownloadFilelistError}: {filelistUrl}.\n\n {LocalizedStrings.Error}: {filelistResponse.ReasonPhrase}";
MsgBoxForm.Show($" {LocalizedStrings.Error}: {errorMessage}", LocalizedStrings.Error);
Logger.WriteLog(errorMessage);
return new DownloadClientResult { Status = DownloadClientResultStatus.Failed };
}
string filelistText = await client.GetStringAsync(filelistUrl, cancellationToken).ConfigureAwait(false);
string downloadDir = Path.Combine(installDirectory, "rhclient_download");
if (!Directory.Exists(downloadDir))
{
Directory.CreateDirectory(downloadDir);
}
List<string> filesToBeDownloaded = [];
long totalBytesToDownload = 0L;
List<string> lines = [.. filelistText.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries)];
int totalLines = lines.Count;
int checkedFiles = 0;
foreach (string line in lines)
{
cancellationToken.ThrowIfCancellationRequested();
string[] parts = line.Split(' ');
if (parts.Length != 3)
{
continue;
}
string fileName = parts[0];
long fileSize = long.Parse(parts[1]);
ulong fileHashFromServer = ulong.Parse(parts[2], NumberStyles.HexNumber, CultureInfo.InvariantCulture);
string filePath = Path.Combine(downloadDir, fileName);
if (File.Exists(filePath))
{
string existingFileHash = Crc32.GetFileHash(filePath);
if (existingFileHash.Equals(fileHashFromServer.ToString("X8"), StringComparison.OrdinalIgnoreCase))
{
checkedFiles++;
ProgressReporter.ReportFileCheckingProgress(progress, checkedFiles, totalLines, cancellationToken);
continue; // Skip this file as it already exists and the hash matches
}
}
filesToBeDownloaded.Add(fileName);
totalBytesToDownload += fileSize;
checkedFiles++;
ProgressReporter.ReportFileCheckingProgress(progress, checkedFiles, totalLines, cancellationToken);
}
Stopwatch sw = Stopwatch.StartNew();
long downloadedBytes = 0L;
foreach (string fileName in filesToBeDownloaded)
{
cancellationToken.ThrowIfCancellationRequested();
string fileUrl = $"{Configuration.Default.DownloadClientPartUrl}/{fileName}";
string filePath = Path.Combine(downloadDir, fileName);
using HttpResponseMessage response = await client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
await using Stream contentStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
await using FileStream fileStream = new(filePath, FileMode.Create, FileAccess.Write, FileShare.None, BufferSize, true);
byte[] buffer = new byte[BufferSize];
int bytesRead;
while ((bytesRead = await contentStream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) > 0)
{
cancellationToken.ThrowIfCancellationRequested();
await fileStream.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false);
downloadedBytes += bytesRead;
ProgressReporter.ReportClientDownloadProgress(progress, downloadedBytes, totalBytesToDownload, sw, cancellationToken);
}
}
ProgressReporter.ReportFinishedProgress(progress, cancellationToken);
string rhExePath = await UnzipFilesAsync(downloadDir, installDirectory, progress, cancellationToken);
ProgressReporter.ReportFinishedProgress(progress, cancellationToken);
return new DownloadClientResult
{
Status = DownloadClientResultStatus.Success,
InstallDirectoryPath = rhExePath
};
}
catch (OperationCanceledException ex)
{
Logger.WriteLog($"Download cancelled: {ex.Message}");
return new DownloadClientResult { Status = DownloadClientResultStatus.Cancelled };
}
catch (Exception ex)
{
ProgressReporter.ReportErrorProgress(progress, ex.Message, cancellationToken);
string errorMessage = LocalizedStrings.ClientDownloadError + "\n" + ex.Message;
string errorLog = LocalizedStrings.ClientDownloadError + ex.Message + ex.StackTrace;
Exception newEx = new(errorMessage, ex);
Exception newLogEx = new(errorLog, ex);
ExceptionHandler.HandleException(newEx, newLogEx);
return new DownloadClientResult { Status = DownloadClientResultStatus.Failed };
}
}
private static async Task<string> UnzipFilesAsync(string sourceDirectory, string destinationDirectory, IProgress<ProgressReport> progress, CancellationToken cancellationToken)
{
string[] fileEntries = [.. Directory.GetFiles(sourceDirectory, "*.zip.*").OrderBy(f => f)];
string rhExeDirectoryPath = "";
// Calculate total uncompressed size of all files in all zip archives
long totalUncompressedSize = fileEntries.Sum(file =>
{
using FileStream fs = new(file, FileMode.Open, FileAccess.Read);
using ZipArchive zip = new(fs, ZipArchiveMode.Read);
static long entryLength(ZipArchiveEntry entry) => entry.Length;
return zip.Entries.Sum(entryLength);
});
long totalExtracted = 0;
try
{
foreach (string file in fileEntries)
{
await Task.Run(() =>
{
using FileStream fs = new(file, FileMode.Open, FileAccess.Read);
using ZipArchive zip = new(fs, ZipArchiveMode.Read);
foreach (var entry in zip.Entries)
{
cancellationToken.ThrowIfCancellationRequested();
string destinationPath = Path.Combine(destinationDirectory, entry.FullName);
string? directoryPath = Path.GetDirectoryName(destinationPath);
if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
entry.ExtractToFile(destinationPath, overwrite: true);
totalExtracted += entry.Length;
cancellationToken.ThrowIfCancellationRequested();
ProgressReporter.ReportUnzipProgress(progress, totalExtracted, totalUncompressedSize, cancellationToken);
// Check if the current entry is "rustyhearts.exe" and store its directory path
if (entry.FullName.EndsWith("rustyhearts.exe", StringComparison.OrdinalIgnoreCase))
{
rhExeDirectoryPath = Path.GetDirectoryName(destinationPath) ?? "";
}
}
}, cancellationToken);
}
}
catch (OperationCanceledException)
{
throw;
}
try
{
if (Directory.Exists(sourceDirectory))
{
Directory.Delete(sourceDirectory, true);
}
}
catch (Exception ex)
{
throw new InvalidOperationException($"{LocalizedStrings.ClientFolderErrorMessage}", ex);
}
// Check if 'rustyhearts.exe' directory exists
if (!string.IsNullOrWhiteSpace(rhExeDirectoryPath) && Directory.Exists(rhExeDirectoryPath))
{
return rhExeDirectoryPath;
}
else
{
throw new FileNotFoundException($"{LocalizedStrings.ClientFolderExeErrorMessage}");
}
}
}
}

View file

@ -0,0 +1,69 @@
using RHLauncher.RHLauncher.Helper;
using System.Net;
namespace RHLauncher.RHLauncher.Http
{
public class DownloadHelper
{
public static async Task<long> GetFileSizeAsync(HttpClient client, string fileUrl, CancellationToken cancellationToken)
{
using HttpRequestMessage request = new(HttpMethod.Get, fileUrl);
try
{
using HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
return response.Content.Headers.ContentLength ?? throw new Exception("Content-Length header not found in response headers.");
}
else if (response.StatusCode == HttpStatusCode.NotFound)
{
Logger.WriteLog($"File not found: {fileUrl}");
return 0;
}
else
{
Logger.WriteLog($"Error getting file size for {fileUrl}: {response.StatusCode}");
return 0;
}
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
Logger.WriteLog($"File not found: {fileUrl}");
return 0;
}
catch (Exception ex)
{
Logger.WriteLog($"Error getting file size for {fileUrl}: {ex.Message}");
return 0;
}
}
public static string FormatDownloadSpeed(double totalDownloadSpeed)
{
string[] sizes = { "B/s", "KB/s", "MB/s", "GB/s" };
int order = 0;
while (totalDownloadSpeed >= 1024 && order < sizes.Length - 1)
{
order++;
totalDownloadSpeed /= 1024;
}
return $"{totalDownloadSpeed:0.#} {sizes[order]}";
}
public static string FormatFileSize(long bytes)
{
string[] sizes = { "B", "KB", "MB", "GB" };
int order = 0;
while (bytes >= 1024 && order < sizes.Length - 1)
{
order++;
bytes /= 1024;
}
return $"{bytes:0.#} {sizes[order]}";
}
}
}

View file

@ -0,0 +1,118 @@
using Newtonsoft.Json;
using RHLauncher.RHLauncher.Helper;
using RHLauncher.RHLauncher.i8n;
using System.IO.Compression;
using System.Text;
namespace RHLauncher.RHLauncher.Http
{
public class LauncherUpdater
{
private readonly string LauncherVersionUrl = Configuration.Default.GetLauncherVersion;
private readonly string LauncherUpdateUrl = Configuration.Default.UpdateLauncherVersion;
public class LauncherVersion
{
public string? Version { get; set; }
}
public async Task CheckForLauncherUpdateAsync()
{
try
{
using HttpClient client = new();
using HttpResponseMessage response = await client.GetAsync(LauncherVersionUrl);
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<LauncherVersion>(json);
if (result != null)
{
string? newVersion = result.Version;
if (!string.IsNullOrEmpty(newVersion))
{
string currentVersion = GetLauncherVersion.GetVersion();
if (!string.IsNullOrEmpty(currentVersion) && !currentVersion.Equals(newVersion, StringComparison.OrdinalIgnoreCase))
{
string updateMessage = $"{LocalizedStrings.LauncherUpdateText}\n\n" +
$"{LocalizedStrings.Version}: {newVersion}";
MsgBoxForm.Show(updateMessage, LocalizedStrings.Info);
await DownloadLauncherUpdateAsync(json);
}
await Task.Delay(1000);
}
}
}
catch (Exception ex)
{
HandleLauncherUpdateException(ex);
}
}
private async Task DownloadLauncherUpdateAsync(string version)
{
try
{
using HttpClient client = new();
using StringContent content = new(version, Encoding.UTF8, "application/json");
var result = JsonConvert.DeserializeObject<LauncherVersion>(version);
if (result != null)
{
string? v = result.Version;
if (!string.IsNullOrEmpty(version))
{
using HttpResponseMessage response = await client.PostAsync(LauncherUpdateUrl, content);
response.EnsureSuccessStatusCode();
byte[] updateBytes = await response.Content.ReadAsByteArrayAsync();
string tempFilePath = Path.Combine(Path.GetTempPath(), $"launcher_update.zip");
File.WriteAllBytes(tempFilePath, updateBytes);
string executablePath = AppDomain.CurrentDomain.BaseDirectory;
string backupFilePath = Path.Combine(executablePath, $"Launcher_old.exe");
string launcherExePath = Path.Combine(executablePath, "Launcher.exe");
if (File.Exists(backupFilePath))
{
File.Delete(backupFilePath);
}
// Move existing launcher.exe to temporary location
File.Move(launcherExePath, backupFilePath);
// Extract new update files
ZipFile.ExtractToDirectory(tempFilePath, executablePath, true);
// Delete temporary zip file
File.Delete(tempFilePath);
MsgBoxForm.Show(LocalizedStrings.LauncherUpdateSuccess + v, LocalizedStrings.Info);
await Task.Delay(500).ContinueWith(_ =>
{
Application.Restart();
});
}
}
}
catch (Exception ex)
{
HandleLauncherUpdateException(ex);
}
}
private static void HandleLauncherUpdateException(Exception ex)
{
string errorMessage = LocalizedStrings.LauncherUpdateFailed + ex.Message;
string errorLog = LocalizedStrings.LauncherUpdateFailed + ex.Message + ex.StackTrace;
Exception newEx = new(errorMessage, ex);
Exception newLogEx = new(errorLog, ex);
ExceptionHandler.HandleException(newEx, newLogEx);
}
}
}

View file

@ -1,14 +1,21 @@
using RHLauncher.Helper;
using RHLauncher.PCK;
using RHLauncher.RHLauncher.Helper;
using RHLauncher.RHLauncher.Helper;
using RHLauncher.RHLauncher.i8n;
using RHLauncher.RHLauncher.PCK;
using System.Diagnostics;
using System.Globalization;
using System.Net;
namespace RHLauncher.RHLauncher
namespace RHLauncher.RHLauncher.Http
{
public class UpdateDownloader
{
public enum UpdateState
{
UpdateAvailable,
NoUpdateAvailable,
Error
}
private const int BufferSize = 8192;
private const int TimeoutSeconds = 30;
@ -16,8 +23,18 @@ namespace RHLauncher.RHLauncher
{
try
{
string fileListUrl = Configuration.Default.FileListUrl;
using var client = new HttpClient();
string fileListUrl = Configuration.Default.FileListUrl;
using HttpResponseMessage filelistResponse = await client.GetAsync(fileListUrl);
if (!filelistResponse.IsSuccessStatusCode)
{
// Handle the case where the filelist URL is not found
return UpdateState.Error;
}
using var response = await client.GetAsync(fileListUrl);
using var content = await response.Content.ReadAsStreamAsync();
using var reader = new StreamReader(content);
@ -69,13 +86,6 @@ namespace RHLauncher.RHLauncher
}
}
public enum UpdateState
{
UpdateAvailable,
NoUpdateAvailable,
Error
}
public static async Task DownloadUpdatesAsync(string installDirectory, IProgress<ProgressReport> progress, CancellationToken cancellationToken)
{
using HttpClientHandler handler = new() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
@ -83,6 +93,12 @@ namespace RHLauncher.RHLauncher
try
{
string archiveDir = Path.Combine(installDirectory, "archive");
if (!Directory.Exists(archiveDir))
{
Directory.CreateDirectory(archiveDir);
}
string filelistUrl = Configuration.Default.FileListUrl;
string filelistText = await client.GetStringAsync(filelistUrl, cancellationToken).ConfigureAwait(false);
@ -94,8 +110,13 @@ namespace RHLauncher.RHLauncher
List<string> filesToBeDownloaded = new();
long totalBytesToDownload = 0L;
int totalFilesToDownload = 0;
foreach (string line in filelistText.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
List<string> lines = filelistText.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
int totalLines = lines.Count;
for (int i = 0; i < totalLines; i++)
{
string line = lines[i];
cancellationToken.ThrowIfCancellationRequested();
string[] parts = line.Split(' ');
@ -118,16 +139,12 @@ namespace RHLauncher.RHLauncher
if (!fileHashes.TryGetValue(fileName, out uint fileHash) || fileHash != fileHashFromServer)
{
filesToBeDownloaded.Add(fileName);
long fileSize = await GetFileSizeAsync(client, $"{Configuration.Default.DownloadUpdateFileUrl}/{fileName}.mip", cancellationToken).ConfigureAwait(false);
long fileSize = await DownloadHelper.GetFileSizeAsync(client, $"{Configuration.Default.DownloadUpdateFileUrl}/{fileName}.mip", cancellationToken).ConfigureAwait(false);
totalBytesToDownload += fileSize;
totalFilesToDownload++;
}
}
string archiveDir = Path.Combine(installDirectory, "archive");
if (!Directory.Exists(archiveDir))
{
Directory.CreateDirectory(archiveDir);
ProgressReporter.ReportFileListCheckProgress(progress, i + 1, totalLines, cancellationToken);
}
Stopwatch sw = Stopwatch.StartNew();
@ -147,9 +164,12 @@ namespace RHLauncher.RHLauncher
response.EnsureSuccessStatusCode();
await using Stream contentStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
if (!Directory.Exists(Path.GetDirectoryName(filePath)))
string? directoryPath = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
{
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
Directory.CreateDirectory(directoryPath);
}
await using FileStream fileStream = new(filePath, FileMode.Create, FileAccess.Write, FileShare.None, BufferSize, true);
@ -166,7 +186,6 @@ namespace RHLauncher.RHLauncher
}
ProgressReporter.ReportDownloadProgress(progress, finalfileName, downloadedSize, totalBytesToDownload, downloadedFileCount, totalFilesToDownload, sw, cancellationToken);
await Task.Yield();
downloadedFileCount++;
}
fileHashes.Clear();
@ -175,7 +194,7 @@ namespace RHLauncher.RHLauncher
}
catch (OperationCanceledException ex)
{
Logger.WriteLog($"Download update cancelled: {ex.Message}");
Logger.WriteLog($"Update download cancelled: {ex.Message}");
}
catch (Exception ex)
{
@ -189,38 +208,5 @@ namespace RHLauncher.RHLauncher
}
}
private static async Task<long> GetFileSizeAsync(HttpClient client, string fileUrl, CancellationToken cancellationToken)
{
using HttpRequestMessage request = new(HttpMethod.Get, fileUrl);
using HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
return response.Content.Headers.ContentLength ?? throw new Exception("Content-Length header not found in response headers.");
}
public static string FormatDownloadSpeed(double totalDownloadSpeed)
{
string[] sizes = { "B/s", "KB/s", "MB/s", "GB/s" };
int order = 0;
while (totalDownloadSpeed >= 1024 && order < sizes.Length - 1)
{
order++;
totalDownloadSpeed /= 1024;
}
return $"{totalDownloadSpeed:0.#} {sizes[order]}";
}
public static string FormatFileSize(long bytes)
{
string[] sizes = { "B", "KB", "MB", "GB" };
int order = 0;
while (bytes >= 1024 && order < sizes.Length - 1)
{
order++;
bytes /= 1024;
}
return $"{bytes:0.#} {sizes[order]}";
}
}
}

View file

@ -1,739 +0,0 @@
using Newtonsoft.Json;
using RHLauncher.Helper;
using RHLauncher.RHLauncher;
using RHLauncher.RHLauncher.Helper;
using System.Diagnostics;
using static RHLauncher.RHLauncher.UpdateDownloader;
using static RHLauncher.RHLauncher.UpdateInstaller;
using static RHLauncher.RHLauncher.UpdateUnpacker;
/*
Rusty Hearts Launcher - Windows Forms Implementation in C#
Author: JuniorDark
GitHub Repository: https://github.com/JuniorDark/RustyHearts-Launcher
This code serves as a starting point for creating your own launcher.
However, it requires further development to improve functionality and
ensure stability. Please check the GitHub repository for updates.
*/
namespace RHLauncher
{
public partial class LauncherForm : Form
{
private RegistryHandler registryHandler = new();
public string? installDirectory;
private static readonly string DefaultIniFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.ini");
private readonly IniFile _iniFile = new(DefaultIniFilePath);
private readonly string _windyCode;
private readonly string _password;
private readonly Image[] images = {
Properties.Resources.character_select_cut_angela,
Properties.Resources.character_select_cut_edgar,
Properties.Resources.character_select_cut_frantz,
Properties.Resources.character_select_cut_ian,
Properties.Resources.character_select_cut_leila,
Properties.Resources.character_select_cut_meilinchen,
Properties.Resources.character_select_cut_natasha,
Properties.Resources.character_select_cut_roselle,
Properties.Resources.character_select_cut_tude
};
public LauncherForm(string windyCode, string password)
{
InitializeComponent();
notifyIcon.Text = LocalizedStrings.RustyHearts;
Text = LocalizedStrings.LauncherFormTitle;
LabelNews.Text = LocalizedStrings.LabelNews;
InstallButton.Text = LocalizedStrings.InstallLocation;
UninstallButton.Text = LocalizedStrings.Uninstall;
OpenSettingsButton.Text = LocalizedStrings.GameSettings;
CheckUpdateButton.Text = LocalizedStrings.CheckUpdate;
OpenInstallDirButton.Text = LocalizedStrings.OpenInstallDir;
ManageButton.Text = LocalizedStrings.Manage;
ChangePwdButton.Text = LocalizedStrings.ChangePassword;
LogoutButton.Text = LocalizedStrings.Logout;
_windyCode = windyCode;
_password = password;
installDirectory = registryHandler.GetInstallDirectory();
}
#region Methods
private async void LauncherForm_Load(object sender, EventArgs e)
{
NameLabel.Text = LocalizedStrings.Welcome + ", " + _windyCode;
ChangeCharPictureBox();
getUpdatePanel.Hide();
if (string.IsNullOrEmpty(installDirectory))
{
LaunchOptionsButton.Enabled = false;
LaunchButton.Text = LocalizedStrings.Install;
LaunchButton.Click += (s, e) =>
{
Install();
};
}
else
{
ServiceFileHandler updater = new("Config.ini", installDirectory);
updater.UpdateService();
await CheckForUpdates();
}
await WebView2Async();
}
private async Task WebView2Async()
{
await webView21.EnsureCoreWebView2Async();
webView21.Source = new Uri(Configuration.Default.LauncherNewsUrl);
webView21.CoreWebView2.NavigationStarting += (sender, args) =>
{
// Check if the URL being navigated to is an external link
if (!args.Uri.ToString().StartsWith(Configuration.Default.LauncherNewsUrl))
{
// Cancel the navigation
args.Cancel = true;
// Launch the URL in the user's default browser
Process.Start(new ProcessStartInfo(args.Uri) { UseShellExecute = true });
}
};
}
private async void Install()
{
try
{
if (string.IsNullOrEmpty(installDirectory))
{
OpenFileDialog openFileDialog1 = new()
{
InitialDirectory = AppDomain.CurrentDomain.BaseDirectory,
Filter = "RustyHearts.exe|RustyHearts.exe",
Title = "Select RustyHearts.exe"
};
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
installDirectory = Path.GetDirectoryName(openFileDialog1.FileName);
registryHandler.SaveInstallDirectory(installDirectory);
await CheckForUpdates();
}
}
}
catch (Exception ex)
{
HandleException(ex);
}
}
private async Task CheckForUpdates()
{
try
{
LaunchButton.Enabled = false;
LaunchButton.Text = LocalizedStrings.Checking;
LaunchOptionsButton.Enabled = false;
switch (await CheckForUpdatesAsync())
{
case UpdateState.UpdateAvailable:
LaunchButton.Text = LocalizedStrings.Update;
LaunchButton.Enabled = true;
LaunchButton.Click -= LaunchGameButton_Click;
LaunchButton.Click += InstallUpdateButton_Click;
break;
case UpdateState.NoUpdateAvailable:
LaunchButton.Text = LocalizedStrings.Launch;
LaunchButton.Click -= LaunchGameButton_Click;
LaunchButton.Click += LaunchGameButton_Click;
break;
case UpdateState.Error:
LaunchButton.Text = LocalizedStrings.Launch;
LaunchButton.Click -= LaunchGameButton_Click;
LaunchButton.Click += LaunchGameButton_Click;
break;
}
}
catch (Exception ex)
{
HandleException(ex);
}
finally
{
LaunchButton.Enabled = true;
LaunchOptionsButton.Enabled = true;
AccOptionsButton.Enabled = true;
}
}
private readonly SemaphoreSlim _semaphore = new(1);
public async Task InstallUpdate()
{
await _semaphore.WaitAsync();
_cancellationTokenSource = new CancellationTokenSource();
try
{
Progress<ProgressReport> progress = new(ReportProgress);
ProgressThrottler progressThrottler = new(progress, 200);
Progress<ProgressReport> packProgress = new(ReportInstallProgress);
ProgressThrottler packProgressThrottler = new(packProgress, 200);
await DownloadUpdatesAsync(installDirectory, progressThrottler, _cancellationTokenSource.Token);
await UnpackDownloadedFilesAsync(installDirectory, packProgressThrottler, _cancellationTokenSource.Token);
await PackDownloadedFilesAsync(installDirectory, packProgressThrottler, _cancellationTokenSource.Token);
}
catch (OperationCanceledException ex)
{
Logger.WriteLog($"Update installation canceled: {ex.Message}");
}
catch (Exception ex)
{
HandleException(ex);
}
finally
{
_semaphore.Release();
LaunchButton.Enabled = true;
LaunchOptionsButton.Enabled = true;
LaunchButton.Text = LocalizedStrings.Launch;
LaunchButton.Click -= InstallUpdateButton_Click;
LaunchButton.Click += LaunchGameButton_Click;
if (_cancellationTokenSource.IsCancellationRequested)
{
await CheckForUpdates();
}
}
}
private static void HandleException(Exception ex)
{
string errorMessage = ex.Message;
string errorLog = ex.Message + ex.StackTrace;
Exception newEx = new(errorMessage, ex);
Exception newLogEx = new(errorLog, ex);
ExceptionHandler.HandleException(newEx, newLogEx);
}
private void ReportProgress(ProgressReport progressReport)
{
if (InvokeRequired)
{
Invoke(new Action<ProgressReport>(ReportProgress), progressReport);
return;
}
FileNameLabel.Visible = progressReport.ShowFileNameLabel;
SpeedLabel.Visible = progressReport.ShowSpeedLabel;
TimeLabel.Visible = progressReport.ShowTimeLabel;
FileSizeLabel.Visible = progressReport.ShowFileSizeLabel;
FileCountLabel.Visible = progressReport.ShowFileCountLabel;
DownloadingLabel.Text = progressReport.Label;
PercentLabel.Text = $"{progressReport.PercentComplete}%";
progressBar1.Maximum = (int)progressReport.TotalBytesToDownload;
progressBar1.Value = (int)Math.Min(progressReport.BytesDownloaded, progressReport.TotalBytesToDownload);
FileNameLabel.Text = progressReport.FileName;
SpeedLabel.Text = FormatDownloadSpeed(progressReport.TotalSpeed);
TimeSpan t = TimeSpan.FromSeconds(progressReport.TimeLeft);
TimeLabel.Text = $"{t.Hours:00}:{t.Minutes:00}:{t.Seconds:00}";
FileSizeLabel.Text = $"({FormatFileSize(progressReport.BytesDownloaded)} / {FormatFileSize(progressReport.TotalBytesToDownload)})";
FileCountLabel.Text = $"({progressReport.NumFilesDownloaded}/{progressReport.TotalNumFiles})";
if (!string.IsNullOrEmpty(progressReport.FileName))
{
FileNameLabel.Refresh();
}
getUpdatePanel.Visible = progressReport.Panel;
}
private void ReportInstallProgress(ProgressReport progressReport)
{
if (InvokeRequired)
{
Invoke(new Action<ProgressReport>(ReportInstallProgress), progressReport);
return;
}
FileNameLabel.Visible = progressReport.ShowFileNameLabel;
SpeedLabel.Visible = progressReport.ShowSpeedLabel;
TimeLabel.Visible = progressReport.ShowTimeLabel;
FileSizeLabel.Visible = progressReport.ShowFileSizeLabel;
FileCountLabel.Visible = progressReport.ShowFileCountLabel;
DownloadingLabel.Text = progressReport.Label;
PercentLabel.Text = $"{progressReport.PercentComplete}%";
progressBar1.Maximum = progressReport.TotalNumFiles;
progressBar1.Value = progressReport.NumFilesPacked;
FileNameLabel.Text = progressReport.FileName;
FileCountLabel.Text = $"({progressReport.NumFilesPacked}/{progressReport.TotalNumFiles})";
if (!string.IsNullOrEmpty(progressReport.FileName))
{
FileNameLabel.Refresh();
}
getUpdatePanel.Visible = progressReport.Panel;
}
public void ChangeCharPictureBox()
{
Random rnd = new();
int index = rnd.Next(images.Length);
CharPictureBox.Image = images[index];
}
private static async Task<bool> CheckServerStatusAsync()
{
try
{
using HttpClient client = new();
using HttpResponseMessage response = await client.GetAsync(Configuration.Default.GateStatusUrl);
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
dynamic result = JsonConvert.DeserializeObject(json);
string status = result.status;
return (status == "online");
}
catch
{
return false;
}
}
private void CharPictureBox_Click(object sender, EventArgs e)
{
ChangeCharPictureBox();
}
private static void HidePanel(Panel panel)
{
if (panel.Visible)
{
panel.Visible = false;
}
}
private void HidePanels()
{
HidePanel(AccPanel);
HidePanel(LaunchPanel);
HidePanel(InstallPanel);
}
#endregion
#region Button Click Events
private CancellationTokenSource? _cancellationTokenSource;
private void StopButton_Click(object sender, EventArgs e)
{
_cancellationTokenSource?.Cancel();
getUpdatePanel.Visible = false;
LaunchButton.Text = LocalizedStrings.Cancelling;
LaunchButton.Click -= InstallUpdateButton_Click;
}
private async void InstallUpdateButton_Click(object? sender, EventArgs e)
{
try
{
LaunchButton.Text = LocalizedStrings.Updating;
LaunchButton.Enabled = false;
LaunchOptionsButton.Enabled = false;
await InstallUpdate();
}
catch (Exception ex)
{
HandleException(ex);
}
}
private async void LaunchGameButton_Click(object? sender, EventArgs e)
{
try
{
HidePanels();
LaunchButton.Text = LocalizedStrings.Launching;
LaunchButton.Enabled = false;
LaunchOptionsButton.Enabled = false;
AccOptionsButton.Enabled = false;
// Check if RustyHearts.exe is already running
if (Process.GetProcessesByName("RustyHearts").Length > 0)
{
MsgBoxForm.Show(LocalizedStrings.AlreadyExecute, LocalizedStrings.Error);
await CheckForUpdates();
return;
}
// Check if server is online
bool serverOnline = await CheckServerStatusAsync();
if (!serverOnline)
{
MsgBoxForm.Show(LocalizedStrings.ServerOffline, LocalizedStrings.Error);
await CheckForUpdates();
return;
}
LaunchButton.Text = LocalizedStrings.Running;
LaunchButton.Enabled = false;
LaunchOptionsButton.Enabled = false;
AccOptionsButton.Enabled = false;
string service = _iniFile.ReadValue("Info", "Service");
string arguments = string.Empty;
switch (service.ToLower())
{
case "usa":
arguments = "server=" + Configuration.Default.GateXMLUrl;
break;
case "chn":
arguments = $"-serverurl{Configuration.Default.GateInfoUrl} id={_windyCode} password={_password}";
break;
default:
// handle unsupported service
MsgBoxForm.Show(LocalizedStrings.UnsupportedService, LocalizedStrings.Error);
await CheckForUpdates();
return;
}
ProcessStartInfo startInfo = new()
{
FileName = Path.Combine(installDirectory, "RustyHearts.exe"),
Arguments = arguments,
WorkingDirectory = installDirectory
};
Process? process = Process.Start(startInfo);
WindowState = FormWindowState.Minimized;
if (WindowState == FormWindowState.Minimized)
{
Hide();
notifyIcon.Visible = true;
}
await process.WaitForExitAsync();
Show();
WindowState = FormWindowState.Normal;
notifyIcon.Visible = false;
await CheckForUpdates();
}
catch (Exception ex)
{
HandleException(ex);
}
}
private void OnMouseDown(object sender, MouseEventArgs e)
{
HidePanels();
if (e.Button == MouseButtons.Left)
{
FormUtils.MoveForm(Handle);
}
}
private void CloseButton_Click(object sender, EventArgs e)
{
Close();
}
private void MinimizeButton_Click(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
}
private void LauncherForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
Application.Exit();
}
}
private void LogoutButton_Click(object sender, EventArgs e)
{
HidePanels();
DialogResult result = MsgBoxForm.ShowYN(LocalizedStrings.LogoutText, LocalizedStrings.Confirmation);
if (result == DialogResult.Yes)
{
registryHandler = new RegistryHandler();
registryHandler.SaveValues(_windyCode, "", false, false);
Logout();
}
}
public void Logout()
{
LoginForm loginForm = Application.OpenForms.OfType<LoginForm>().FirstOrDefault();
if (loginForm != null)
{
// Close the current form before restarting
Close();
// Restart the application
Application.Restart();
}
else
{
LoginForm newLoginForm = new();
newLoginForm.Show();
Close();
}
}
private async void UpdateCheckButton_Click(object sender, EventArgs e)
{
HidePanels();
await CheckForUpdates();
}
private async void InstallButton_Click(object? sender, EventArgs e)
{
HidePanels();
OpenFileDialog openFileDialog1 = new()
{
InitialDirectory = AppDomain.CurrentDomain.BaseDirectory,
Filter = "RustyHearts.exe|RustyHearts.exe",
Title = "Select RustyHearts.exe"
};
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
installDirectory = Path.GetDirectoryName(openFileDialog1.FileName);
registryHandler.SaveInstallDirectory(installDirectory);
await CheckForUpdates();
}
}
private void ManageButton_Click(object sender, EventArgs e)
{
InstallPanel.Visible = !InstallPanel.Visible;
}
private void OpenInstallDirButton_Click(object sender, EventArgs e)
{
HidePanels();
if (!string.IsNullOrEmpty(installDirectory))
{
Process.Start("explorer.exe", installDirectory);
}
}
private void OpenSettingsButton_Click(object sender, EventArgs e)
{
HidePanels();
if (!string.IsNullOrEmpty(installDirectory))
{
string rustyHeartsConfigPath = Path.Combine(installDirectory, "rustyheartsconfig.exe");
if (File.Exists(rustyHeartsConfigPath))
{
ProcessStartInfo startInfo = new()
{
FileName = rustyHeartsConfigPath,
WorkingDirectory = installDirectory
};
Process.Start(startInfo);
}
else
{
MsgBoxForm.Show(LocalizedStrings.rustyheartsconfig, LocalizedStrings.Error);
}
}
}
private void UninstallButton_Click(object sender, EventArgs e)
{
HidePanels();
if (!string.IsNullOrEmpty(installDirectory))
{
DialogResult result = MsgBoxForm.ShowYN(LocalizedStrings.ConfirmUninstallText, LocalizedStrings.ConfirmUninstall);
if (result == DialogResult.Yes)
{
try
{
LaunchButton.Enabled = false;
LaunchOptionsButton.Enabled = false;
LaunchButton.Text = LocalizedStrings.Uninstalling;
Directory.Delete(installDirectory, true);
MsgBoxForm.Show(LocalizedStrings.UninstallText, LocalizedStrings.Uninstall);
registryHandler.ClearInstallDirectory();
LaunchButton.Enabled = true;
LaunchButton.Text = LocalizedStrings.Install;
LaunchButton.Click -= LaunchGameButton_Click;
LaunchButton.Click += InstallButton_Click;
}
catch (Exception ex)
{
HandleException(ex);
}
}
}
}
private void ChangePwdButton_Click(object sender, EventArgs e)
{
HidePanels();
ChangePwd changePwd = new(true);
changePwd.FormClosing += ChangePwd_FormClosing;
changePwd.ShowDialog();
}
private void ChangePwd_FormClosing(object sender, FormClosingEventArgs e)
{
if (sender is ChangePwd changePwd)
{
changePwd.Dispose();
}
}
private void LaunchOptionsButton_Click(object sender, EventArgs e)
{
LaunchPanel.Visible = !LaunchPanel.Visible;
if (InstallPanel.Visible)
{
InstallPanel.Visible = false;
}
}
#endregion
#region Button Events
private void LauncherForm_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
notifyIcon.Visible = true;
}
}
private void notifyIcon_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// Restore the form and hide the NotifyIcon when clicked
Show();
WindowState = FormWindowState.Normal;
notifyIcon.Visible = false;
}
}
private void MenuButton_MouseHover(object sender, EventArgs e)
{
Button button = (Button)sender;
button.ImageIndex = 1;
}
private void MenuButton_MouseLeave(object sender, EventArgs e)
{
Button button = (Button)sender;
button.ImageIndex = 0;
}
private void MenuButton_MouseDown(object sender, MouseEventArgs e)
{
Button button = (Button)sender;
button.ImageIndex = 2;
}
private void AccOptionsButton_Click(object sender, EventArgs e)
{
AccPanel.Visible = !AccPanel.Visible;
}
private void MinimizeButton_MouseHover(object sender, EventArgs e)
{
MinimizeButton.ImageIndex = 1;
}
private void MinimizeButton_MouseLeave(object sender, EventArgs e)
{
MinimizeButton.ImageIndex = 0;
}
private void MinimizeButton_OnMouseDown(object sender, MouseEventArgs e)
{
MinimizeButton.ImageIndex = 2;
}
private void CloseButton_MouseHover(object sender, EventArgs e)
{
CloseButton.ImageIndex = 1;
}
private void CloseButton_MouseLeave(object sender, EventArgs e)
{
CloseButton.ImageIndex = 0;
}
private void CloseButton_OnMouseDown(object sender, MouseEventArgs e)
{
CloseButton.ImageIndex = 2;
}
private void LaunchButton_MouseHover(object sender, EventArgs e)
{
LaunchButton.ImageIndex = 1;
}
private void LaunchButton_MouseLeave(object sender, EventArgs e)
{
LaunchButton.ImageIndex = 0;
}
private void LaunchButton_OnMouseDown(object sender, MouseEventArgs e)
{
LaunchButton.ImageIndex = 2;
}
private void AccOptionsButton_MouseHover(object sender, EventArgs e)
{
AccOptionsButton.ImageIndex = 1;
}
private void AccOptionsButton_MouseLeave(object sender, EventArgs e)
{
AccOptionsButton.ImageIndex = 0;
}
private void LaunchOptionsButton_MouseHover(object sender, EventArgs e)
{
LaunchOptionsButton.ImageIndex = 1;
}
private void LaunchOptionsButton_MouseLeave(object sender, EventArgs e)
{
LaunchOptionsButton.ImageIndex = 0;
}
private void LaunchOptionsButton_OnMouseDown(object sender, MouseEventArgs e)
{
LaunchOptionsButton.ImageIndex = 2;
}
private void StopButton_MouseHover(object sender, EventArgs e)
{
StopButton.ImageIndex = 1;
}
private void StopButton_MouseLeave(object sender, EventArgs e)
{
StopButton.ImageIndex = 0;
}
private void StopButton_OnMouseDown(object sender, MouseEventArgs e)
{
StopButton.ImageIndex = 2;
}
#endregion
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,71 +0,0 @@
using System.IO.Compression;
using RHLauncher.DynamicLib;
namespace RHLauncher
{
internal class MIPDecoder
{
private static readonly byte[] codeMip = new byte[] {
0x30, 0x22, 0x41, 0xa8, 0x5b, 0xa6, 0x6a, 0x49, 0xbf, 0x53, 0x35, 0xe5, 0x9e, 14, 0xec, 0xb8,
0x5e, 0x15, 0x1f, 0xc1, 0x4f, 0xec, 0x77, 0xe8, 0xb7, 0x4e, 0x87, 230, 0xf5, 60, 0xb3, 0x43,
0xcc, 0x53, 0x36, 0xac, 90, 0x77, 0xb8, 0xdd, 0x30, 0x74, 140, 0x4a, 0x9a, 0x9b, 0xbc, 10,
0xa4, 0xad, 0xbb, 0x13, 0x4b, 140, 0xd4, 0x80, 0xce, 0x65, 0x1d, 8, 90, 0x6a, 0x6f, 0x25,
0xf9, 0x3f, 0xef, 0x1b, 0xa4, 0x72, 20, 0xed, 0x97, 0x22, 0x4a, 0x2e, 0xb8, 150, 0x4b, 0x8e,
150, 0x93, 0xf1, 40, 0xb2, 11, 60, 0xf8, 0x5d, 170, 0xa9, 130, 0x13, 110, 0xc1, 0xa9,
0x20, 0x57, 0xb2, 0x5b, 0x16, 0xcf, 0x9e, 0x5f, 0xd4, 0xcc, 0x2e, 0xf5, 0xc9, 0x4c, 0x1c, 0xee,
0xe3, 0x3f, 0x29, 0xb3, 6, 0x70, 0x43, 0x3d, 0xf5, 0x90, 0xa2, 0x42, 2, 0x98, 80, 0xfd,
0x5d, 0x4e, 0x92, 0xad, 0xad, 0x7f, 0xab, 0x60, 0x2c, 0xb8, 0x43, 0x76, 0x8f, 0x5f, 230, 0xa7,
0x19, 0xe0, 0xb9, 0xb5, 0x62, 0x6b, 0xd4, 0x47, 0x69, 0x34, 14, 0x6d, 0xa4, 0x52, 0xe3, 100,
0x4a, 0x65, 0x47, 0xf5, 0x3f, 0x53, 0x5e, 0x8b, 0x1b, 0xfd, 0x21, 0xf7, 0xba, 0x68, 0xf9, 0xdf,
0x68, 0xa8, 150, 15, 0x8b, 1, 0x97, 0x58, 140, 30, 0xef, 0xb3, 0x41, 0x44, 0x21, 0xda,
0xe0, 0xf4, 0xe0, 0x2d, 0xcd, 11, 240, 0x5c, 0x59, 0xd6, 0x99, 0xe7, 1, 0x15, 0x67, 50,
0xe0, 0x12, 0x2f, 0xcd, 0xa2, 0xde, 0x52, 0xce, 0xec, 0xef, 0x77, 14, 0xbc, 0x38, 100, 0x8d,
180, 0xdb, 0x67, 0xff, 200, 0x66, 12, 0x8a, 0x60, 0xe1, 0x2e, 0, 0x43, 0xa9, 0x37, 0x9c,
0x11, 170, 0xb9, 0x98, 0xed, 0x21, 0x35, 0xd4, 0xc3, 0xde, 0x65, 0x54, 0x9d, 0x1c, 0xb0, 0xa9
};
private static void BytesWithCodeMip(byte[] toBytes)
{
for (int i = 0; i < toBytes.Length; i++)
{
toBytes[i] = (byte)(toBytes[i] ^ codeMip[i & 0xff]);
}
}
public static async Task DecompressFileAsync(string filePath, string outputPath, CancellationToken cancellationToken)
{
byte[] buffer;
using (FileStream fileStream = new(filePath, FileMode.Open, FileAccess.Read))
{
buffer = new byte[fileStream.Length];
await fileStream.ReadAsync(buffer, 0, (int)fileStream.Length, cancellationToken);
}
BytesWithCodeMip(buffer);
buffer = DecompressBytes(buffer);
using FileStream outputFileStream = new(outputPath, FileMode.Create, FileAccess.Write);
await outputFileStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken);
}
private static byte[] DecompressBytes(byte[] toBytes)
{
using MemoryStream inputStream = new(toBytes);
using DeflateStream deflateStream = new(inputStream, CompressionMode.Decompress);
using MemoryStream outputStream = new();
deflateStream.CopyTo(outputStream);
return outputStream.ToArray();
}
//Zlib have issues with some files
private static byte[] DecompressBytes1(byte[] toBytes)
{
int num = (toBytes.Length << 4) - toBytes.Length;
byte[] buffer = new byte[num];
int err = ZLibDll.Decompress(toBytes, toBytes.Length, buffer, ref num);
if (err != 0) throw new Exception(string.Format("Decompress returned error code {0}.", err));
toBytes = new byte[num];
Buffer.BlockCopy(buffer, 0, toBytes, 0, num);
return toBytes;
}
}
}

View file

@ -1,4 +1,4 @@
namespace RHLauncher.PCK
namespace RHLauncher.RHLauncher.PCK
{
public class PCKFile
{
@ -12,10 +12,6 @@
public long Offset { get; private set; }
public bool IsChecked { get; set; }
public string[] PathElements { get { return Name.Split(new char[] { '\\' }); } }
public PCKFile(string name, byte archive, int size, uint hash, long offset)
{
Name = name;

View file

@ -1,22 +1,9 @@
namespace RHLauncher.PCK
namespace RHLauncher.RHLauncher.PCK
{
public class PCKFileNode
{
public string Name { get; private set; }
public PCKFile PCKFile { get; set; }
public bool IsDir { get { return PCKFile == null; } }
public SortedDictionary<string, PCKFileNode> Nodes { get; set; }
private bool isChecked;
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
if (PCKFile != null) PCKFile.IsChecked = isChecked;
}
}
public PCKFileNode(string name, PCKFile file)
{

View file

@ -1,13 +1,11 @@
using RHLauncher.DynamicLib;
using RHLauncher.Helper;
using System.IO.Compression;
using RHLauncher.RHLauncher.Helper;
using System.Text;
namespace RHLauncher.PCK
namespace RHLauncher.RHLauncher.PCK
{
public static class PCKReader
{
public static readonly byte[] BufferTable = new byte[]
{
0x30, 0x22, 0x41, 0xA8, 0x5B, 0xA6, 0x6A, 0x49, 0xBF, 0x53, 0x35, 0xE5, 0x9E, 0x0E, 0xEC, 0xB8, 0x5E, 0x15, 0x1F, 0xC1, 0x4F, 0xEC, 0x77, 0xE8, 0xB7, 0x4E, 0x87, 0xE6, 0xF5, 0x3C, 0xB3, 0x43
@ -31,19 +29,20 @@ namespace RHLauncher.PCK
compressedBytes = compressedBytes.Select((b, i) => (byte)(b ^ BufferTable[i & 0xFF])).ToArray();
int decompressedSize = (compressedBytes.Length << 4) - compressedBytes.Length;
byte[] decompressedBytes = new byte[decompressedSize];
int result = ZLibDll.Decompress(compressedBytes, compressedBytes.Length, decompressedBytes, ref decompressedSize);
if (result != 0) throw new Exception("Error decoding f00x.dat");
List<PCKFile> pckFileList = new(100000);
using (MemoryStream memoryStream = new(decompressedBytes, 0, decompressedSize, false))
string fileName = string.Empty;
try
{
using BinaryReader binaryReader = new(memoryStream);
using MemoryStream compressedStream = new(compressedBytes);
using ZLibStream deflateStream = new(compressedStream, CompressionMode.Decompress);
using MemoryStream decompressedStream = new();
deflateStream.CopyTo(decompressedStream);
decompressedStream.Seek(0, SeekOrigin.Begin);
using BinaryReader binaryReader = new(decompressedStream);
while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length)
{
string fileName = string.Empty;
try
{
ushort nameLength = binaryReader.ReadUInt16();
@ -75,11 +74,17 @@ namespace RHLauncher.PCK
}
}
}
catch (Exception ex)
{
string errorMessage = $"Error decompressing PCK file: {ex.Message}";
string errorLog = $"Error decompressing PCK file: {ex.Message}|{ex.StackTrace}";
Exception newEx = new(errorMessage, ex);
Exception newLogEx = new(errorLog, ex);
ExceptionHandler.HandleException(newEx, newLogEx);
}
return pckFileList;
}
}
}

View file

@ -1,263 +0,0 @@
using Newtonsoft.Json;
using RHLauncher.DynamicLib;
using RHLauncher.Helper;
using System.Text;
namespace RHLauncher.PCK
{
public static class PCKWriter
{
private static readonly byte[] BufferTable = new byte[] {
0x30, 0x22, 0x41, 0xa8, 0x5b, 0xa6, 0x6a, 0x49, 0xbf, 0x53, 0x35, 0xe5, 0x9e, 14, 0xec, 0xb8,
0x5e, 0x15, 0x1f, 0xc1, 0x4f, 0xec, 0x77, 0xe8, 0xb7, 0x4e, 0x87, 230, 0xf5, 60, 0xb3, 0x43,
0xcc, 0x53, 0x36, 0xac, 90, 0x77, 0xb8, 0xdd, 0x30, 0x74, 140, 0x4a, 0x9a, 0x9b, 0xbc, 10,
0xa4, 0xad, 0xbb, 0x13, 0x4b, 140, 0xd4, 0x80, 0xce, 0x65, 0x1d, 8, 90, 0x6a, 0x6f, 0x25,
0xf9, 0x3f, 0xef, 0x1b, 0xa4, 0x72, 20, 0xed, 0x97, 0x22, 0x4a, 0x2e, 0xb8, 150, 0x4b, 0x8e,
150, 0x93, 0xf1, 40, 0xb2, 11, 60, 0xf8, 0x5d, 170, 0xa9, 130, 0x13, 110, 0xc1, 0xa9,
0x20, 0x57, 0xb2, 0x5b, 0x16, 0xcf, 0x9e, 0x5f, 0xd4, 0xcc, 0x2e, 0xf5, 0xc9, 0x4c, 0x1c, 0xee,
0xe3, 0x3f, 0x29, 0xb3, 6, 0x70, 0x43, 0x3d, 0xf5, 0x90, 0xa2, 0x42, 2, 0x98, 80, 0xfd,
0x5d, 0x4e, 0x92, 0xad, 0xad, 0x7f, 0xab, 0x60, 0x2c, 0xb8, 0x43, 0x76, 0x8f, 0x5f, 230, 0xa7,
0x19, 0xe0, 0xb9, 0xb5, 0x62, 0x6b, 0xd4, 0x47, 0x69, 0x34, 14, 0x6d, 0xa4, 0x52, 0xe3, 100,
0x4a, 0x65, 0x47, 0xf5, 0x3f, 0x53, 0x5e, 0x8b, 0x1b, 0xfd, 0x21, 0xf7, 0xba, 0x68, 0xf9, 0xdf,
0x68, 0xa8, 150, 15, 0x8b, 1, 0x97, 0x58, 140, 30, 0xef, 0xb3, 0x41, 0x44, 0x21, 0xda,
0xe0, 0xf4, 0xe0, 0x2d, 0xcd, 11, 240, 0x5c, 0x59, 0xd6, 0x99, 0xe7, 1, 0x15, 0x67, 50,
0xe0, 0x12, 0x2f, 0xcd, 0xa2, 0xde, 0x52, 0xce, 0xec, 0xef, 0x77, 14, 0xbc, 0x38, 100, 0x8d,
180, 0xdb, 0x67, 0xff, 200, 0x66, 12, 0x8a, 0x60, 0xe1, 0x2e, 0, 0x43, 0xa9, 0x37, 0x9c,
0x11, 170, 0xb9, 0x98, 0xed, 0x21, 0x35, 0xd4, 0xc3, 0xde, 0x65, 0x54, 0x9d, 0x1c, 0xb0, 0xa9
};
private static readonly uint[] CodeHash = new uint[]
{
0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
public static uint BytesWithCodeHash(byte[] toBytes)
{
int num = -1;
for (int i = 0; i < toBytes.Length; i++)
{
num = (int)CodeHash[num & 0xff ^ toBytes[i]] ^ num >> 8 & 0xffffff;
}
return (uint)num;
}
public delegate void GetFilesDelegate(string path, bool isComplete);
public static List<string> GetFiles(string dir, GetFilesDelegate gfDelegate)
{
List<string> listFile = new();
foreach (string file in Directory.EnumerateFiles(dir, "*", SearchOption.AllDirectories))
{
if (File.GetAttributes(file).HasFlag(FileAttributes.Directory))
{
continue;
}
listFile.Add(file);
gfDelegate(file, false);
}
return listFile;
}
public delegate void PackingDelegate(string fileName, int pos, int count);
public static async Task Packing(string rootDir, List<string> listFile, List<PCKFile> listPckFile, bool replace, PackingDelegate pDelegate, CancellationToken cancellationToken)
{
RegistryHandler registryHandler = new();
string installDirectory = registryHandler.GetInstallDirectory();
SortedDictionary<string, PCKFile> dicPckFile = new();
foreach (PCKFile file in listPckFile)
{
dicPckFile.Add(file.Name, file);
}
SortedDictionary<string, string> dicInputFile = new();
string s = rootDir.Substring(rootDir.Length - 1, 1);
if (s != "\\") rootDir += "\\";
foreach (string file in listFile)
{
dicInputFile.Add(file.Replace(rootDir, ""), file);
}
Dictionary<int, FileStream> archives = new(10);
Dictionary<int, BinaryWriter> writers = new(10);
try
{
for (int i = 0; i < 10; i++)
{
string pathPCK = Path.Combine(installDirectory, string.Format("{0:000}.pck", i));
FileMode mode = File.Exists(pathPCK) ? FileMode.Open : FileMode.Create;
FileStream ofs = new(pathPCK, mode, FileAccess.Write);
ofs.Position = ofs.Length;
BinaryWriter obr = new(ofs);
archives.Add(i, ofs);
writers.Add(i, obr);
}
// Read the f00x.dat file to get the archive numbers
Dictionary<string, int> dicArchive = new();
string pathF00X = Path.Combine(installDirectory, "f00x.dat");
if (File.Exists(pathF00X))
{
byte[] buffer = await File.ReadAllBytesAsync(pathF00X, cancellationToken);
int numDecompressed = buffer.Length << 4;
byte[] decompressed = new byte[numDecompressed];
int result = ZLibDll.Decompress(buffer, buffer.Length, decompressed, ref numDecompressed);
if (result == 0)
{
string json = Encoding.UTF8.GetString(decompressed);
dicArchive = JsonConvert.DeserializeObject<Dictionary<string, int>>(json);
}
}
int pos = 0;
int count = dicInputFile.Count;
foreach (KeyValuePair<string, string> file in dicInputFile)
{
if (cancellationToken.IsCancellationRequested)
{
WriteF00XDAT(dicPckFile);
throw new OperationCanceledException();
}
pos++;
pDelegate(file.Key, pos, count);
PCKFile? pckFile = null;
if (dicPckFile.ContainsKey(file.Key))
{
if (!replace) continue;
pckFile = dicPckFile[file.Key];
}
if (!File.Exists(file.Value)) continue;
byte[] fileBytes;
using (FileStream fileStream = File.OpenRead(file.Value))
{
fileStream.Seek(0, SeekOrigin.Begin);
fileBytes = new byte[fileStream.Length];
await fileStream.ReadAsync(fileBytes, 0, fileBytes.Length);
}
uint fileHash = BytesWithCodeHash(fileBytes);
int arc = 0;
if (pckFile != null)
{
if (pckFile.Hash == fileHash) continue;
arc = pckFile.Archive;
dicPckFile.Remove(file.Key);
}
else
{
if (dicArchive.ContainsKey(file.Key)) arc = dicArchive[file.Key];
else
{
long pckLen = archives[0].Length;
for (byte i = 1; i < 10; i++)
{
long x = archives[i].Length;
if (x < pckLen)
{
pckLen = x;
arc = i;
}
}
}
}
pckFile = new PCKFile(file.Key, (byte)arc, fileBytes.Length, fileHash, archives[arc].Length);
dicPckFile.Add(file.Key, pckFile);
BinaryWriter bw = writers[pckFile.Archive];
bw.Write(fileBytes);
bw.Flush();
}
WriteF00XDAT(dicPckFile);
}
catch (Exception)
{
throw;
}
finally
{
foreach (KeyValuePair<int, FileStream> kvp in archives)
{
kvp.Value.Close();
kvp.Value.Dispose();
}
listFile.Clear();
listPckFile.Clear();
}
}
public static void WriteF00XDAT(SortedDictionary<string, PCKFile> dicPckFile)
{
try
{
RegistryHandler registryHandler = new();
string installDirectory = registryHandler.GetInstallDirectory();
byte[]? bufferF00XDAT = null;
using (MemoryStream streamF00X = new())
{
using BinaryWriter writerF00X = new(streamF00X);
foreach (KeyValuePair<string, PCKFile> kvFile in dicPckFile)
{
PCKFile pckFile = kvFile.Value;
byte[] bytes = Encoding.Unicode.GetBytes(pckFile.Name);
int numNameLen = Convert.ToInt32(bytes.Length / 2);
writerF00X.Write((ushort)numNameLen);
writerF00X.Write(bytes);
writerF00X.Write(pckFile.Archive);
writerF00X.Write((uint)pckFile.FileSize);
writerF00X.Write(pckFile.Hash);
writerF00X.Write((ulong)pckFile.Offset);
}
writerF00X.Flush();
bufferF00XDAT = streamF00X.ToArray();
}
int numCompress = (bufferF00XDAT.Length >> 4) + bufferF00XDAT.Length;
byte[] bufferCompress = new byte[numCompress];
if (ZLibDll.Compress(bufferF00XDAT, bufferF00XDAT.Length, bufferCompress, ref numCompress) == 0)
{
for (int i = 0; i < numCompress; i++)
{
bufferCompress[i] = (byte)(bufferCompress[i] ^ BufferTable[i & 0xff]);
}
string pathF00XDAT = Path.Combine(installDirectory, "f00X.dat");
File.Delete(pathF00XDAT + ".old");
File.Move(pathF00XDAT, pathF00XDAT + ".old");
using FileStream streamF00XDAT = new(pathF00XDAT, FileMode.Create, FileAccess.Write);
using BinaryWriter writerF00XDAT = new(streamF00XDAT);
writerF00XDAT.Write(bufferCompress, 0, numCompress);
writerF00XDAT.Flush();
}
}
catch (Exception)
{
throw;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows7.0</TargetFramework>
<TargetFramework>net9.0-windows</TargetFramework>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
@ -18,9 +18,9 @@
<Product>Rusty Hearts Launcher</Product>
<AssemblyName>Launcher</AssemblyName>
<Description>Rusty Hearts Launcher</Description>
<PlatformTarget>x86</PlatformTarget>
<AssemblyVersion>1.1.0</AssemblyVersion>
<FileVersion>1.1.0</FileVersion>
<PlatformTarget>x64</PlatformTarget>
<AssemblyVersion>1.4.0</AssemblyVersion>
<FileVersion>1.4.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -36,25 +36,18 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2045.28" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3179.45" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="WindowsAPICodePack" Version="8.0.6" />
</ItemGroup>
<ItemGroup>
<Compile Update="RegForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Update="RHLauncher\LocalizedStrings.Designer.cs">
<Compile Update="RHLauncher.i8n\LocalizedStrings.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>LocalizedStrings.resx</DependentUpon>
@ -66,22 +59,15 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="RHLauncher\LocalizedStrings.ko.resx">
<EmbeddedResource Update="RHLauncher.i8n\LocalizedStrings.ko.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="RHLauncher\LocalizedStrings.resx">
<EmbeddedResource Update="RHLauncher.i8n\LocalizedStrings.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>LocalizedStrings.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<PropertyGroup>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<Authors>Rusty Hearts Launcher</Authors>

View file

@ -1,7 +1,7 @@
using System.Globalization;
using System.Resources;
namespace RHLauncher.RHLauncher
namespace RHLauncher.RHLauncher.i8n
{
public class LocalizationHelper
{
@ -12,10 +12,10 @@ namespace RHLauncher.RHLauncher
Dictionary<string, List<ImageList>> languageImageLists)
{
CultureInfo cultureInfo;
if (languageImageLists.ContainsKey(lang))
if (languageImageLists.TryGetValue(lang, out List<ImageList>? value))
{
// If the language is supported, get the corresponding image lists
List<ImageList> langSpecificImageLists = languageImageLists[lang];
List<ImageList> langSpecificImageLists = value;
for (int i = 0; i < buttons.Count && i < langSpecificImageLists.Count; i++)
{
buttons[i].ImageList = langSpecificImageLists[i];

View file

@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace RHLauncher.RHLauncher {
namespace RHLauncher.RHLauncher.i8n {
using System;
@ -39,7 +39,7 @@ namespace RHLauncher.RHLauncher {
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RHLauncher.RHLauncher.LocalizedStrings", typeof(LocalizedStrings).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RHLauncher.RHLauncher.i8n.LocalizedStrings", typeof(LocalizedStrings).Assembly);
resourceMan = temp;
}
return resourceMan;
@ -69,6 +69,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Account created successfully..
/// </summary>
public static string AccountCreateSuccess {
get {
return ResourceManager.GetString("AccountCreateSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Account Details.
/// </summary>
@ -87,6 +96,24 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to A account with this email already exists..
/// </summary>
public static string AccountEmailExists {
get {
return ResourceManager.GetString("AccountEmailExists", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A account with this username already exists..
/// </summary>
public static string AccountExists {
get {
return ResourceManager.GetString("AccountExists", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Account Name.
/// </summary>
@ -123,6 +150,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Installed?.
/// </summary>
public static string AlreadyInstalled {
get {
return ResourceManager.GetString("AlreadyInstalled", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cancelling.
/// </summary>
@ -132,6 +168,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to The launcher needs to be restarted to change the language. Restart now?.
/// </summary>
public static string ChangeLanguageMessage {
get {
return ResourceManager.GetString("ChangeLanguageMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Change Password.
/// </summary>
@ -178,7 +223,16 @@ namespace RHLauncher.RHLauncher {
}
/// <summary>
/// Looks up a localized string similar to Check Update.
/// Looks up a localized string similar to Checking files....
/// </summary>
public static string CheckingFiles {
get {
return ResourceManager.GetString("CheckingFiles", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Check for Updates.
/// </summary>
public static string CheckUpdate {
get {
@ -186,6 +240,51 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to An error occurred while downloading client..
/// </summary>
public static string ClientDownloadError {
get {
return ResourceManager.GetString("ClientDownloadError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error downloading game client..
/// </summary>
public static string ClientDownloadErrorMessage {
get {
return ResourceManager.GetString("ClientDownloadErrorMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Could not retrieve file list from.
/// </summary>
public static string ClientDownloadFilelistError {
get {
return ResourceManager.GetString("ClientDownloadFilelistError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Failed to delete download directory..
/// </summary>
public static string ClientFolderErrorMessage {
get {
return ResourceManager.GetString("ClientFolderErrorMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The directory containing &apos;rustyhearts.exe&apos; was not found after extraction..
/// </summary>
public static string ClientFolderExeErrorMessage {
get {
return ResourceManager.GetString("ClientFolderExeErrorMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Insert the verification code.
/// </summary>
@ -204,6 +303,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Launcher Settings.
/// </summary>
public static string ConfigFormTitle {
get {
return ResourceManager.GetString("ConfigFormTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Confirmation.
/// </summary>
@ -330,6 +438,24 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Failed to process server response..
/// </summary>
public static string HttpResponseNull {
get {
return ResourceManager.GetString("HttpResponseNull", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Failed to parse server response..
/// </summary>
public static string HttpResponseParseError {
get {
return ResourceManager.GetString("HttpResponseParseError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Info.
/// </summary>
@ -348,6 +474,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Installing.
/// </summary>
public static string Installing {
get {
return ResourceManager.GetString("Installing", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Install Location.
/// </summary>
@ -357,6 +492,33 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Invalid Install Directory.
/// </summary>
public static string InvalidDirectory {
get {
return ResourceManager.GetString("InvalidDirectory", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid email format.
/// </summary>
public static string InvalidEmailFormat {
get {
return ResourceManager.GetString("InvalidEmailFormat", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid username format.
/// </summary>
public static string InvalidUserNameFormat {
get {
return ResourceManager.GetString("InvalidUserNameFormat", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid Verification Code.
/// </summary>
@ -384,6 +546,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Only one instance of the launcher can run at a time..
/// </summary>
public static string LauncherAlreadyRunning {
get {
return ResourceManager.GetString("LauncherAlreadyRunning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Rusty Hearts Launcher.
/// </summary>
@ -393,6 +564,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Launcher Language.
/// </summary>
public static string LauncherLanguage {
get {
return ResourceManager.GetString("LauncherLanguage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error checking for launcher update: .
/// </summary>
@ -438,6 +618,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Locate Game.
/// </summary>
public static string LocateGame {
get {
return ResourceManager.GetString("LocateGame", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Login Info.
/// </summary>
@ -537,6 +726,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Error installing update. Could not find MPatcher.exe.
/// </summary>
public static string MPatcher {
get {
return ResourceManager.GetString("MPatcher", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Message.
/// </summary>
@ -556,7 +754,7 @@ namespace RHLauncher.RHLauncher {
}
/// <summary>
/// Looks up a localized string similar to 6-16 characters.
/// Looks up a localized string similar to 8-16 characters.
/// </summary>
public static string NewPasswordDesc {
get {
@ -574,7 +772,7 @@ namespace RHLauncher.RHLauncher {
}
/// <summary>
/// Looks up a localized string similar to Open Install Dir.
/// Looks up a localized string similar to Open Install Directory.
/// </summary>
public static string OpenInstallDir {
get {
@ -646,7 +844,7 @@ namespace RHLauncher.RHLauncher {
}
/// <summary>
/// Looks up a localized string similar to Password must be between 6-16 characters!.
/// Looks up a localized string similar to Password must be between 8-16 characters!.
/// </summary>
public static string PwdDescLabelSize {
get {
@ -699,6 +897,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Register Window.
/// </summary>
public static string RegisterWindow {
get {
return ResourceManager.GetString("RegisterWindow", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Repeat the new password.
/// </summary>
@ -762,6 +969,24 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Select RustyHearts.exe.
/// </summary>
public static string SelectExe {
get {
return ResourceManager.GetString("SelectExe", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select Install Location.
/// </summary>
public static string SelectInstallLocation {
get {
return ResourceManager.GetString("SelectInstallLocation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot connect to the game server..
/// </summary>
@ -771,6 +996,42 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to Service.
/// </summary>
public static string Service {
get {
return ResourceManager.GetString("Service", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Could not find Service.dat. Please check if the Install Directory is correct..
/// </summary>
public static string ServiceDatFileMissing {
get {
return ResourceManager.GetString("ServiceDatFileMissing", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An error occurred while updating service.
/// </summary>
public static string ServiceUpdateError {
get {
return ResourceManager.GetString("ServiceUpdateError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Settings.
/// </summary>
public static string Settings {
get {
return ResourceManager.GetString("Settings", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Success.
/// </summary>
@ -960,6 +1221,15 @@ namespace RHLauncher.RHLauncher {
}
}
/// <summary>
/// Looks up a localized string similar to A game account with this username already exists..
/// </summary>
public static string WindyCodeExists {
get {
return ResourceManager.GetString("WindyCodeExists", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Yes.
/// </summary>

View file

@ -120,12 +120,21 @@
<data name="Account" xml:space="preserve">
<value>계정</value>
</data>
<data name="AccountCreateSuccess" xml:space="preserve">
<value>계정이 성공적으로 생성되었습니다.</value>
</data>
<data name="AccountDetails" xml:space="preserve">
<value>계정 정보</value>
</data>
<data name="AccountEmail" xml:space="preserve">
<value>계정 이메일</value>
</data>
<data name="AccountEmailExists" xml:space="preserve">
<value>이 이메일을 사용하는 계정이 이미 존재합니다.</value>
</data>
<data name="AccountExists" xml:space="preserve">
<value>이 사용자 이름을 사용하는 계정이 이미 존재합니다.</value>
</data>
<data name="AccountName" xml:space="preserve">
<value>계정 이름</value>
</data>
@ -136,11 +145,17 @@
<value>나는 에 동의하고 수락합니다</value>
</data>
<data name="AlreadyExecute" xml:space="preserve">
<value>Rustyhearts.exe가 이미 실행 중입니다.</value>
<value>RustyHearts.exe가 이미 실행 중입니다.</value>
</data>
<data name="AlreadyInstalled" xml:space="preserve">
<value>설치되었나요?</value>
</data>
<data name="Cancelling" xml:space="preserve">
<value>취소 중</value>
</data>
<data name="ChangeLanguageMessage" xml:space="preserve">
<value>언어를 변경하려면 런처를 다시 시작해야 합니다. 지금 다시 시작하시겠습니까?</value>
</data>
<data name="ChangePassword" xml:space="preserve">
<value>비밀번호 변경</value>
</data>
@ -156,15 +171,36 @@
<data name="Checking" xml:space="preserve">
<value>확인 중</value>
</data>
<data name="CheckingFiles" xml:space="preserve">
<value>파일을 확인하는 중...</value>
</data>
<data name="CheckUpdate" xml:space="preserve">
<value>업데이트 확인</value>
</data>
<data name="ClientDownloadError" xml:space="preserve">
<value>클라이언트를 다운로드하는 동안 오류가 발생했습니다.</value>
</data>
<data name="ClientDownloadErrorMessage" xml:space="preserve">
<value>게임 클라이언트 다운로드 중 오류가 발생했습니다.</value>
</data>
<data name="ClientDownloadFilelistError" xml:space="preserve">
<value>에서 파일 목록을 검색할 수 없습니다</value>
</data>
<data name="ClientFolderErrorMessage" xml:space="preserve">
<value>다운로드 디렉터리를 삭제하지 못했습니다.</value>
</data>
<data name="ClientFolderExeErrorMessage" xml:space="preserve">
<value>추출 후 'rustyhearts.exe'가 포함된 디렉터리를 찾을 수 없습니다.</value>
</data>
<data name="CodeDescLabel" xml:space="preserve">
<value>인증코드를 입력하세요</value>
</data>
<data name="CodeDescLabelInvalid" xml:space="preserve">
<value>잘못된 인증 코드 형식</value>
</data>
<data name="ConfigFormTitle" xml:space="preserve">
<value>런처 설정</value>
</data>
<data name="Confirmation" xml:space="preserve">
<value>확증</value>
</data>
@ -207,15 +243,33 @@
<data name="GameSettings" xml:space="preserve">
<value>게임 설정</value>
</data>
<data name="HttpResponseNull" xml:space="preserve">
<value>서버 응답을 처리하지 못했습니다.</value>
</data>
<data name="HttpResponseParseError" xml:space="preserve">
<value>서버 응답을 구문 분석하는 데 실패했습니다.</value>
</data>
<data name="Info" xml:space="preserve">
<value>정보</value>
</data>
<data name="Install" xml:space="preserve">
<value>설치하다</value>
</data>
<data name="Installing" xml:space="preserve">
<value>설치 중</value>
</data>
<data name="InstallLocation" xml:space="preserve">
<value>설치 위치</value>
</data>
<data name="InvalidDirectory" xml:space="preserve">
<value>잘못된 설치 디렉터리</value>
</data>
<data name="InvalidEmailFormat" xml:space="preserve">
<value>잘못된 이메일 형식</value>
</data>
<data name="InvalidUserNameFormat" xml:space="preserve">
<value>잘못된 사용자 이름 형식</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>잘못된 인증 코드</value>
</data>
@ -225,9 +279,15 @@
<data name="Launch" xml:space="preserve">
<value>시작하다</value>
</data>
<data name="LauncherAlreadyRunning" xml:space="preserve">
<value>한 번에 하나의 런처 인스턴스만 실행할 수 있습니다.</value>
</data>
<data name="LauncherFormTitle" xml:space="preserve">
<value>러스티하츠 런처</value>
</data>
<data name="LauncherLanguage" xml:space="preserve">
<value>런처 언어</value>
</data>
<data name="LauncherUpdateCheckFailed" xml:space="preserve">
<value>런처 업데이트 확인 중 오류가 발생했습니다:</value>
</data>
@ -243,6 +303,9 @@
<data name="Launching" xml:space="preserve">
<value>진수</value>
</data>
<data name="LocateGame" xml:space="preserve">
<value>게임 위치</value>
</data>
<data name="LoginInfoTitle" xml:space="preserve">
<value>로그인 정보</value>
</data>
@ -276,6 +339,9 @@
<data name="Manage" xml:space="preserve">
<value>&lt; 관리</value>
</data>
<data name="MPatcher" xml:space="preserve">
<value>업데이트 설치 중 오류가 발생했습니다. MPatcher.exe를 찾을 수 없습니다.</value>
</data>
<data name="MsgBoxFormTitle" xml:space="preserve">
<value>메시지</value>
</data>
@ -283,7 +349,7 @@
<value>새 비밀번호를 입력하세요</value>
</data>
<data name="NewPasswordDesc" xml:space="preserve">
<value>6~16자</value>
<value>8~16자</value>
</data>
<data name="No" xml:space="preserve">
<value>아니요</value>
@ -313,7 +379,7 @@
<value>비밀번호는 비워둘 수 없습니다!</value>
</data>
<data name="PwdDescLabelSize" xml:space="preserve">
<value>비밀번호는 6~16자 사이여야 합니다!</value>
<value>비밀번호는 8~16자 사이여야 합니다!</value>
</data>
<data name="PwdStrengthLabelMedium" xml:space="preserve">
<value>매질</value>
@ -330,6 +396,9 @@
<data name="RegisterAccount" xml:space="preserve">
<value>계좌등록</value>
</data>
<data name="RegisterWindow" xml:space="preserve">
<value>등록 창</value>
</data>
<data name="RepeatPassword" xml:space="preserve">
<value>새 비밀번호를 다시 입력하세요.</value>
</data>
@ -351,9 +420,27 @@
<data name="SamePassword" xml:space="preserve">
<value>동일한 비밀번호. 다른 비밀번호를 사용해 주세요.</value>
</data>
<data name="SelectExe" xml:space="preserve">
<value>RustyHearts.exe를 선택하세요.</value>
</data>
<data name="SelectInstallLocation" xml:space="preserve">
<value>설치 위치 선택</value>
</data>
<data name="ServerOffline" xml:space="preserve">
<value>게임 서버에 연결할 수 없습니다.</value>
</data>
<data name="Service" xml:space="preserve">
<value>서비스</value>
</data>
<data name="ServiceDatFileMissing" xml:space="preserve">
<value>Service.dat를 찾을 수 없습니다. 설치 디렉터리가 올바른지 확인하세요.</value>
</data>
<data name="ServiceUpdateError" xml:space="preserve">
<value>서비스를 업데이트하는 중 오류가 발생했습니다.</value>
</data>
<data name="Settings" xml:space="preserve">
<value>설정</value>
</data>
<data name="Success" xml:space="preserve">
<value>성공</value>
</data>
@ -403,7 +490,7 @@
<value>사용자 이름에는 대문자가 포함될 수 없습니다. 소문자와 숫자만 사용해주세요.</value>
</data>
<data name="UsernameLabel" xml:space="preserve">
<value>사용자 이름/이메일</value>
<value>아이디 또는 이메일</value>
</data>
<data name="VerificationCode" xml:space="preserve">
<value>확인 코드</value>
@ -412,11 +499,14 @@
<value>확인 이메일이 다음으로 전송되었습니다</value>
</data>
<data name="Version" xml:space="preserve">
<value>Version</value>
<value>런처 버전</value>
</data>
<data name="Welcome" xml:space="preserve">
<value>환영하다</value>
</data>
<data name="WindyCodeExists" xml:space="preserve">
<value>이 사용자 이름을 가진 게임 계정이 이미 존재합니다.</value>
</data>
<data name="Yes" xml:space="preserve">
<value>예</value>
</data>

View file

@ -120,12 +120,21 @@
<data name="Account" xml:space="preserve">
<value>Account</value>
</data>
<data name="AccountCreateSuccess" xml:space="preserve">
<value>Account created successfully.</value>
</data>
<data name="AccountDetails" xml:space="preserve">
<value>Account Details</value>
</data>
<data name="AccountEmail" xml:space="preserve">
<value>Account Email</value>
</data>
<data name="AccountEmailExists" xml:space="preserve">
<value>A account with this email already exists.</value>
</data>
<data name="AccountExists" xml:space="preserve">
<value>A account with this username already exists.</value>
</data>
<data name="AccountName" xml:space="preserve">
<value>Account Name</value>
</data>
@ -138,9 +147,15 @@
<data name="AlreadyExecute" xml:space="preserve">
<value>rustyhearts.exe is already running.</value>
</data>
<data name="AlreadyInstalled" xml:space="preserve">
<value>Installed?</value>
</data>
<data name="Cancelling" xml:space="preserve">
<value>Cancelling</value>
</data>
<data name="ChangeLanguageMessage" xml:space="preserve">
<value>The launcher needs to be restarted to change the language. Restart now?</value>
</data>
<data name="ChangePassword" xml:space="preserve">
<value>Change Password</value>
</data>
@ -156,8 +171,26 @@
<data name="Checking" xml:space="preserve">
<value>Checking</value>
</data>
<data name="CheckingFiles" xml:space="preserve">
<value>Checking files...</value>
</data>
<data name="CheckUpdate" xml:space="preserve">
<value>Check Update</value>
<value>Check for Updates</value>
</data>
<data name="ClientDownloadError" xml:space="preserve">
<value>An error occurred while downloading client.</value>
</data>
<data name="ClientDownloadErrorMessage" xml:space="preserve">
<value>Error downloading game client.</value>
</data>
<data name="ClientDownloadFilelistError" xml:space="preserve">
<value>Could not retrieve file list from</value>
</data>
<data name="ClientFolderErrorMessage" xml:space="preserve">
<value>Failed to delete download directory.</value>
</data>
<data name="ClientFolderExeErrorMessage" xml:space="preserve">
<value>The directory containing 'rustyhearts.exe' was not found after extraction.</value>
</data>
<data name="CodeDescLabel" xml:space="preserve">
<value>Insert the verification code</value>
@ -165,6 +198,9 @@
<data name="CodeDescLabelInvalid" xml:space="preserve">
<value>Invalid Verification Code format</value>
</data>
<data name="ConfigFormTitle" xml:space="preserve">
<value>Launcher Settings</value>
</data>
<data name="Confirmation" xml:space="preserve">
<value>Confirmation</value>
</data>
@ -207,15 +243,33 @@
<data name="GameSettings" xml:space="preserve">
<value>Game Settings</value>
</data>
<data name="HttpResponseNull" xml:space="preserve">
<value>Failed to process server response.</value>
</data>
<data name="HttpResponseParseError" xml:space="preserve">
<value>Failed to parse server response.</value>
</data>
<data name="Info" xml:space="preserve">
<value>Info</value>
</data>
<data name="Install" xml:space="preserve">
<value>Install</value>
</data>
<data name="Installing" xml:space="preserve">
<value>Installing</value>
</data>
<data name="InstallLocation" xml:space="preserve">
<value>Install Location</value>
</data>
<data name="InvalidDirectory" xml:space="preserve">
<value>Invalid Install Directory</value>
</data>
<data name="InvalidEmailFormat" xml:space="preserve">
<value>Invalid email format</value>
</data>
<data name="InvalidUserNameFormat" xml:space="preserve">
<value>Invalid username format</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Invalid Verification Code</value>
</data>
@ -225,9 +279,15 @@
<data name="Launch" xml:space="preserve">
<value>Launch</value>
</data>
<data name="LauncherAlreadyRunning" xml:space="preserve">
<value>Only one instance of the launcher can run at a time.</value>
</data>
<data name="LauncherFormTitle" xml:space="preserve">
<value>Rusty Hearts Launcher</value>
</data>
<data name="LauncherLanguage" xml:space="preserve">
<value>Launcher Language</value>
</data>
<data name="LauncherUpdateCheckFailed" xml:space="preserve">
<value>Error checking for launcher update: </value>
</data>
@ -243,6 +303,9 @@
<data name="Launching" xml:space="preserve">
<value>Launching</value>
</data>
<data name="LocateGame" xml:space="preserve">
<value>Locate Game</value>
</data>
<data name="LoginInfoTitle" xml:space="preserve">
<value>Login Info</value>
</data>
@ -276,6 +339,9 @@
<data name="Manage" xml:space="preserve">
<value>&lt; Manage</value>
</data>
<data name="MPatcher" xml:space="preserve">
<value>Error installing update. Could not find MPatcher.exe</value>
</data>
<data name="MsgBoxFormTitle" xml:space="preserve">
<value>Message</value>
</data>
@ -283,13 +349,13 @@
<value>Enter the new password</value>
</data>
<data name="NewPasswordDesc" xml:space="preserve">
<value>6-16 characters</value>
<value>8-16 characters</value>
</data>
<data name="No" xml:space="preserve">
<value>No</value>
</data>
<data name="OpenInstallDir" xml:space="preserve">
<value>Open Install Dir</value>
<value>Open Install Directory</value>
</data>
<data name="Packing" xml:space="preserve">
<value>Packing</value>
@ -313,7 +379,7 @@
<value>Password cannot be empty!</value>
</data>
<data name="PwdDescLabelSize" xml:space="preserve">
<value>Password must be between 6-16 characters!</value>
<value>Password must be between 8-16 characters!</value>
</data>
<data name="PwdStrengthLabelMedium" xml:space="preserve">
<value>Medium</value>
@ -330,6 +396,9 @@
<data name="RegisterAccount" xml:space="preserve">
<value>Register Account</value>
</data>
<data name="RegisterWindow" xml:space="preserve">
<value>Register Window</value>
</data>
<data name="RepeatPassword" xml:space="preserve">
<value>Repeat the new password</value>
</data>
@ -351,9 +420,27 @@
<data name="SamePassword" xml:space="preserve">
<value>Same password. Please use another password.</value>
</data>
<data name="SelectExe" xml:space="preserve">
<value>Select RustyHearts.exe</value>
</data>
<data name="SelectInstallLocation" xml:space="preserve">
<value>Select Install Location</value>
</data>
<data name="ServerOffline" xml:space="preserve">
<value>Cannot connect to the game server.</value>
</data>
<data name="Service" xml:space="preserve">
<value>Service</value>
</data>
<data name="ServiceDatFileMissing" xml:space="preserve">
<value>Could not find Service.dat. Please check if the Install Directory is correct.</value>
</data>
<data name="ServiceUpdateError" xml:space="preserve">
<value>An error occurred while updating service</value>
</data>
<data name="Settings" xml:space="preserve">
<value>Settings</value>
</data>
<data name="Success" xml:space="preserve">
<value>Success</value>
</data>
@ -417,6 +504,9 @@
<data name="Welcome" xml:space="preserve">
<value>Welcome</value>
</data>
<data name="WindyCodeExists" xml:space="preserve">
<value>A game account with this username already exists.</value>
</data>
<data name="Yes" xml:space="preserve">
<value>Yes</value>
</data>

View file

@ -1,104 +0,0 @@
using Newtonsoft.Json;
using RHLauncher.RHLauncher;
using RHLauncher.RHLauncher.Helper;
using System.Diagnostics;
using System.IO.Compression;
using System.Text;
namespace RHLauncher
{
public class LauncherUpdater
{
private readonly string LauncherVersionUrl = Configuration.Default.GetLauncherVersion;
private readonly string LauncherUpdateUrl = Configuration.Default.UpdateLauncherVersion;
public async Task CheckForLauncherUpdateAsync()
{
try
{
using HttpClient client = new();
using HttpResponseMessage response = await client.GetAsync(LauncherVersionUrl);
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
dynamic result = JsonConvert.DeserializeObject(json);
string version = result.version;
if (!string.IsNullOrEmpty(version))
{
string currentVersion = GetLauncherVersion();
if (!string.IsNullOrEmpty(currentVersion) && !currentVersion.Equals(version, StringComparison.OrdinalIgnoreCase))
{
MsgBoxForm.Show(LocalizedStrings.LauncherUpdateText, LocalizedStrings.Info);
await DownloadLauncherUpdateAsync(json);
}
await Task.Delay(1000);
}
}
catch (Exception ex)
{
string errorMessage = LocalizedStrings.LauncherUpdateCheckFailed + ex.Message;
string errorLog = LocalizedStrings.LauncherUpdateCheckFailed + ex.Message + ex.StackTrace;
Exception newEx = new(errorMessage, ex);
Exception newLogEx = new(errorLog, ex);
ExceptionHandler.HandleException(newEx, newLogEx);
}
}
private async Task DownloadLauncherUpdateAsync(string version)
{
try
{
using HttpClient client = new();
using StringContent content = new(version, Encoding.UTF8, "application/json");
dynamic result = JsonConvert.DeserializeObject(version);
string v = result.version;
using HttpResponseMessage response = await client.PostAsync(LauncherUpdateUrl, content);
response.EnsureSuccessStatusCode();
byte[] updateBytes = await response.Content.ReadAsByteArrayAsync();
string tempFilePath = Path.Combine(Path.GetTempPath(), $"launcher_update.zip");
File.WriteAllBytes(tempFilePath, updateBytes);
string executablePath = AppDomain.CurrentDomain.BaseDirectory;
string backupFilePath = Path.Combine(executablePath, $"Launcher_old.exe");
string launcherExePath = Path.Combine(executablePath, "Launcher.exe");
if (File.Exists(backupFilePath))
{
File.Delete(backupFilePath);
}
// Move existing launcher.exe to temporary location
File.Move(launcherExePath, backupFilePath);
// Extract new update files
ZipFile.ExtractToDirectory(tempFilePath, executablePath, true);
// Delete temporary zip file
File.Delete(tempFilePath);
MsgBoxForm.Show(LocalizedStrings.LauncherUpdateSuccess + v, LocalizedStrings.Info);
Application.Restart();
}
catch (Exception ex)
{
string errorMessage = LocalizedStrings.LauncherUpdateFailed + ex.Message;
string errorLog = LocalizedStrings.LauncherUpdateFailed + ex.Message + ex.StackTrace;
Exception newEx = new(errorMessage, ex);
Exception newLogEx = new(errorLog, ex);
ExceptionHandler.HandleException(newEx, newLogEx);
}
}
public static string GetLauncherVersion()
{
// Get the version information of the application
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(Application.ExecutablePath);
// Extract the version number
string version = $"{versionInfo.FileMajorPart}.{versionInfo.FileMinorPart}.{versionInfo.FileBuildPart}";
return version;
}
}
}

View file

@ -1,86 +0,0 @@
using System.Diagnostics;
namespace RHLauncher.RHLauncher
{
internal class ProgressReporter
{
public static void ReportInstallProgress(IProgress<ProgressReport> progress, string label, string file, int pos, int count, CancellationToken cancellationToken)
{
ProgressReport report = new()
{
Panel = true,
ShowFileNameLabel = true,
ShowSpeedLabel = false,
ShowTimeLabel = false,
ShowFileSizeLabel = false,
ShowFileCountLabel = true,
Label = label,
FileName = Path.GetFileName(file),
PercentComplete = (int)Math.Round(pos * 100.0 / count),
NumFilesPacked = pos,
TotalNumFiles = count,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportDownloadProgress(IProgress<ProgressReport> progress, string fileName, long downloadedSize, long totalBytesToDownload, int downloadedFileCount, int totalFilesToDownload, Stopwatch sw, CancellationToken cancellationToken)
{
int percentComplete = totalBytesToDownload > 0 ? (int)Math.Round(downloadedSize * 100.0 / totalBytesToDownload) : 0;
double totalSpeed = downloadedSize / sw.Elapsed.TotalSeconds;
long timeLeft = totalBytesToDownload > 0 ? (long)((totalBytesToDownload - downloadedSize) / (downloadedSize / sw.Elapsed.TotalSeconds)) : 0;
ProgressReport report = new()
{
Panel = true,
ShowFileNameLabel = true,
ShowSpeedLabel = true,
ShowTimeLabel = true,
ShowFileSizeLabel = true,
ShowFileCountLabel = true,
Label = LocalizedStrings.Downloading,
PercentComplete = percentComplete,
FileName = fileName,
BytesDownloaded = downloadedSize,
TotalBytesToDownload = totalBytesToDownload,
TotalSpeed = totalSpeed,
TimeLeft = timeLeft,
NumFilesDownloaded = downloadedFileCount,
TotalNumFiles = totalFilesToDownload,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportErrorProgress(IProgress<ProgressReport> progress, string message, CancellationToken cancellationToken)
{
ProgressReport report = new()
{
Panel = true,
ShowFileNameLabel = false,
ShowSpeedLabel = false,
ShowTimeLabel = false,
ShowFileSizeLabel = false,
ShowFileCountLabel = false,
Label = LocalizedStrings.Error,
ErrorMessage = message,
CancellationToken = cancellationToken
};
progress.Report(report);
}
public static void ReportFinishedProgress(IProgress<ProgressReport> progress, CancellationToken cancellationToken)
{
ProgressReport report = new()
{
Panel = false,
CancellationToken = cancellationToken
};
progress.Report(report);
}
}
}

View file

@ -1,86 +0,0 @@
using RHLauncher.Helper;
using RHLauncher.PCK;
namespace RHLauncher.RHLauncher
{
public class UpdateInstaller
{
public static async Task PackDownloadedFilesAsync(string installDir, IProgress<ProgressReport> progress, CancellationToken cancellationToken)
{
string archiveDir = Path.Combine(installDir, "archive");
string updateRootFolder = Path.Combine(installDir, "Update");
if (!Directory.Exists(updateRootFolder))
{
return;
}
List<string> fileList = Directory.EnumerateFiles(updateRootFolder, "*", SearchOption.AllDirectories).ToList();
List<PCKFile> existingFiles = PCKReader.GetPCKFileList();
int count = fileList.Count;
int pos = 0;
try
{
await PCKWriter.Packing(updateRootFolder, fileList, existingFiles, true,
(string fileName, int curPos, int totalCount) =>
{
cancellationToken.ThrowIfCancellationRequested();
pos++;
ProgressReporter.ReportInstallProgress(progress, LocalizedStrings.Packing, fileName, pos, count, cancellationToken);
},
cancellationToken
).ConfigureAwait(false);
}
catch (OperationCanceledException ex)
{
if (Directory.Exists(archiveDir))
{
Directory.Delete(archiveDir, true);
Directory.CreateDirectory(archiveDir);
}
if (Directory.Exists(updateRootFolder))
{
GC.Collect();
GC.WaitForPendingFinalizers();
Directory.Delete(updateRootFolder, true);
}
Logger.WriteLog($"Update installation canceled: {ex.Message}");
}
catch (Exception ex)
{
Logger.WriteLog($"An error occurred while packing: {ex.Message}");
ProgressReporter.ReportErrorProgress(progress, ex.Message, cancellationToken);
throw;
}
finally
{
fileList.Clear();
existingFiles.Clear();
}
ProgressReporter.ReportFinishedProgress(progress, cancellationToken);
// Pause for a short time to allow other tasks to run
await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
if (Directory.Exists(archiveDir))
{
Directory.Delete(archiveDir, true);
Directory.CreateDirectory(archiveDir);
}
if (Directory.Exists(updateRootFolder))
{
GC.Collect();
GC.WaitForPendingFinalizers();
Directory.Delete(updateRootFolder, true);
}
}
}
}

View file

@ -1,74 +0,0 @@
using RHLauncher.Helper;
namespace RHLauncher.RHLauncher
{
public class UpdateUnpacker
{
public static async Task UnpackDownloadedFilesAsync(string installDir, IProgress<ProgressReport> progress, CancellationToken cancellationToken)
{
if (installDir == null)
throw new ArgumentNullException(nameof(installDir));
if (progress == null)
throw new ArgumentNullException(nameof(progress));
string archiveDir = Path.Combine(installDir, "archive");
string updateRootFolder = Path.Combine(installDir, "Update");
if (!Directory.Exists(archiveDir))
{
return;
}
if (!Directory.Exists(updateRootFolder))
{
Directory.CreateDirectory(updateRootFolder);
}
List<string> files = Directory.EnumerateFiles(archiveDir, "*.mip", SearchOption.AllDirectories)
.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)
.ToList();
int count = files.Count;
int pos = 0;
await Task.Run(async () =>
{
foreach (string file in files)
{
cancellationToken.ThrowIfCancellationRequested();
string relativePath = Path.GetRelativePath(archiveDir, file);
string outputPath = Path.Combine(updateRootFolder, relativePath.Substring(0, relativePath.Length - 4)); // Remove the ".mip" extension
try
{
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
await MIPDecoder.DecompressFileAsync(file, outputPath, cancellationToken);
pos++;
ProgressReporter.ReportInstallProgress(progress, LocalizedStrings.Unpacking, file, pos, count, cancellationToken);
}
catch (OperationCanceledException ex)
{
Logger.WriteLog($"Update unpack canceled: {ex.Message}");
}
catch (ArgumentException ex)
{
Logger.WriteLog($"An error occurred while unpacking: {file} {ex}");
ProgressReporter.ReportErrorProgress(progress, ex.Message, cancellationToken);
}
catch (Exception ex)
{
Logger.WriteLog($"Error: {ex.Message} {ex.StackTrace} ");
throw;
}
}
ProgressReporter.ReportFinishedProgress(progress, cancellationToken);
}, cancellationToken);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 427 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 373 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 979 KiB

After

Width:  |  Height:  |  Size: 336 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 667 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Before After
Before After

BIN
Resources/icons/gear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B