Added a lot
- Self contained runtime - Translated french to english - Fixed java path and url
This commit is contained in:
parent
8444698e2a
commit
b33779e77d
@ -8,6 +8,13 @@
|
|||||||
<AssemblyName>LentiaLauncher</AssemblyName>
|
<AssemblyName>LentiaLauncher</AssemblyName>
|
||||||
<ApplicationIcon>./src/resources/icon.ico</ApplicationIcon>
|
<ApplicationIcon>./src/resources/icon.ico</ApplicationIcon>
|
||||||
<PublishTrimmed>false</PublishTrimmed>
|
<PublishTrimmed>false</PublishTrimmed>
|
||||||
|
<RollForward>Major</RollForward>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<PublishTrimmed>false</PublishTrimmed>
|
||||||
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
|
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Target Name="PackRenderer" BeforeTargets="DispatchToInnerBuild;BeforeBuild">
|
<Target Name="PackRenderer" BeforeTargets="DispatchToInnerBuild;BeforeBuild">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@ -29,6 +29,7 @@ class Program {
|
|||||||
BrikPackage bpkg = new BrikPackage(Path.Combine(__dirname, "root.dat"), 66);
|
BrikPackage bpkg = new BrikPackage(Path.Combine(__dirname, "root.dat"), 66);
|
||||||
List<string> entries = bpkg.ListEntries();
|
List<string> entries = bpkg.ListEntries();
|
||||||
var window = new PhotinoWindow()
|
var window = new PhotinoWindow()
|
||||||
|
.SetTitle("Lentia")
|
||||||
.SetUseOsDefaultLocation(false)
|
.SetUseOsDefaultLocation(false)
|
||||||
.SetUseOsDefaultSize(false)
|
.SetUseOsDefaultSize(false)
|
||||||
.SetContextMenuEnabled(false)
|
.SetContextMenuEnabled(false)
|
||||||
@ -232,6 +233,15 @@ class Program {
|
|||||||
case "launcher::game":
|
case "launcher::game":
|
||||||
try {
|
try {
|
||||||
await GenericFilesService.FetchAndSyncGenericFiles(gameRoot);
|
await GenericFilesService.FetchAndSyncGenericFiles(gameRoot);
|
||||||
|
|
||||||
|
MinecraftVersion version = await GameHelper.PrepareGame(new LaunchOptions {
|
||||||
|
Version = new LaunchOptions.VersionOptions { Number = "1.12.2", Type = "release" },
|
||||||
|
ModLoader = LaunchOptions.ModLoaderType.Forge
|
||||||
|
}, gameRoot);
|
||||||
|
|
||||||
|
string javaPath = await JavaHelper.GetJavaExecutablePath(version, gameRoot);
|
||||||
|
SettingsManager.Set("JavaPath", javaPath);
|
||||||
|
|
||||||
var options = new LaunchOptions {
|
var options = new LaunchOptions {
|
||||||
Version = new LaunchOptions.VersionOptions {
|
Version = new LaunchOptions.VersionOptions {
|
||||||
Number = "1.12.2",
|
Number = "1.12.2",
|
||||||
@ -241,13 +251,13 @@ class Program {
|
|||||||
Max = $"{SettingsManager.ReadSettings().Ram.Max}M",
|
Max = $"{SettingsManager.ReadSettings().Ram.Max}M",
|
||||||
Min = "512M"
|
Min = "512M"
|
||||||
},
|
},
|
||||||
|
JavaPath = javaPath,
|
||||||
ModLoader = LaunchOptions.ModLoaderType.Forge,
|
ModLoader = LaunchOptions.ModLoaderType.Forge,
|
||||||
CustomArgs = new List<string> {
|
CustomArgs = new List<string> {
|
||||||
$"-javaagent:{Path.Combine(gameRoot, LauncherConstants.AgentsPath.AuthlibInjector)}={LauncherConstants.Urls.YggdrasilServer}"
|
$"-javaagent:{Path.Combine(gameRoot, LauncherConstants.AgentsPath.AuthlibInjector)}={LauncherConstants.Urls.YggdrasilServer}"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MinecraftVersion version = await GameHelper.PrepareGame(options, gameRoot);
|
|
||||||
await JavaHelper.GetJavaExecutablePath(version, gameRoot);
|
|
||||||
GameHelper.Launch(version, _authenticatedPlayer!, gameRoot, options, (logLine) => {
|
GameHelper.Launch(version, _authenticatedPlayer!, gameRoot, options, (logLine) => {
|
||||||
var logMessage = new {
|
var logMessage = new {
|
||||||
requestId = "game::log",
|
requestId = "game::log",
|
||||||
|
|||||||
@ -7,8 +7,8 @@ namespace Lentia.Core.Constants {
|
|||||||
public const string MojangManifest = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json";
|
public const string MojangManifest = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json";
|
||||||
public const string YggdrasilServer = "https://yggdrasil.azures.fr/";
|
public const string YggdrasilServer = "https://yggdrasil.azures.fr/";
|
||||||
public const string MojangAuthServer = YggdrasilServer + "authserver";
|
public const string MojangAuthServer = YggdrasilServer + "authserver";
|
||||||
|
|
||||||
public const string ApiUrl = "https://lentia-api.azures.fr";
|
public const string ApiUrl = "https://lentia-api.azures.fr";
|
||||||
|
public const string AllJavaRuntime = "https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AgentsPath {
|
public static class AgentsPath {
|
||||||
|
|||||||
@ -90,9 +90,9 @@ public class Authenticator {
|
|||||||
var data = await response.Content.ReadFromJsonAsync<AuthenticateResponse>();
|
var data = await response.Content.ReadFromJsonAsync<AuthenticateResponse>();
|
||||||
return data != null ? AuthResult.Ok(data) : AuthResult.Fail("Erreur de lecture des données.");
|
return data != null ? AuthResult.Ok(data) : AuthResult.Fail("Erreur de lecture des données.");
|
||||||
} catch (HttpRequestException ex) {
|
} catch (HttpRequestException ex) {
|
||||||
return AuthResult.Fail($"Erreur réseau : {ex.Message}", "NETWORK_ERROR");
|
return AuthResult.Fail($"Network error : {ex.Message}", "NETWORK_ERROR");
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return AuthResult.Fail($"Erreur interne : {ex.Message}", "INTERNAL_ERROR");
|
return AuthResult.Fail($"Internal error : {ex.Message}", "INTERNAL_ERROR");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,12 +40,12 @@ public class Discord {
|
|||||||
var response = await HttpHelper.FetchAsync(url, HttpMethod.Get);
|
var response = await HttpHelper.FetchAsync(url, HttpMethod.Get);
|
||||||
if (response.IsSuccessStatusCode) {
|
if (response.IsSuccessStatusCode) {
|
||||||
var data = await response.Content.ReadFromJsonAsync<AuthenticateResponse>();
|
var data = await response.Content.ReadFromJsonAsync<AuthenticateResponse>();
|
||||||
return data != null ? AuthResult.Ok(data) : AuthResult.Fail("Erreur de lecture des données.");
|
return data != null ? AuthResult.Ok(data) : AuthResult.Fail("Data reading error.");
|
||||||
} else {
|
} else {
|
||||||
var errorData = await response.Content.ReadFromJsonAsync<YggdrasilError>();
|
var errorData = await response.Content.ReadFromJsonAsync<YggdrasilError>();
|
||||||
Console.WriteLine(await response.Content.ReadAsStringAsync());
|
Console.WriteLine(await response.Content.ReadAsStringAsync());
|
||||||
return AuthResult.Fail(
|
return AuthResult.Fail(
|
||||||
errorData?.errorMessage ?? "Identifiants invalides.",
|
errorData?.errorMessage ?? "Invalid credentials.",
|
||||||
errorData?.error,
|
errorData?.error,
|
||||||
errorData?.cause
|
errorData?.cause
|
||||||
);
|
);
|
||||||
|
|||||||
@ -31,10 +31,10 @@ public class AssetsHelper {
|
|||||||
string json = await response.Content.ReadAsStringAsync();
|
string json = await response.Content.ReadAsStringAsync();
|
||||||
var index = JsonSerializer.Deserialize<AssetsIndex>(json, LauncherConstants._jsonOptions);
|
var index = JsonSerializer.Deserialize<AssetsIndex>(json, LauncherConstants._jsonOptions);
|
||||||
|
|
||||||
return index ?? throw new Exception("L'index des assets est vide ou invalide.");
|
return index ?? throw new Exception("The assets index is empty or invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception($"Impossible de récupérer l'index des assets : {response.StatusCode}");
|
throw new Exception($"Assets index unavailable : {response.StatusCode}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task DownloadAssets(AssetsIndex index, string rootDir) {
|
public static async Task DownloadAssets(AssetsIndex index, string rootDir) {
|
||||||
@ -87,7 +87,7 @@ public class AssetsHelper {
|
|||||||
await FileHelper.DownloadFileAsync(url, localPath);
|
await FileHelper.DownloadFileAsync(url, localPath);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Console.WriteLine(url);
|
Console.WriteLine(url);
|
||||||
Console.WriteLine($"Échec : {hash} - {ex.Message}");
|
Console.WriteLine($"Fail : {hash} - {ex.Message}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,15 +69,13 @@ public static class JavaHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static async Task DownloadJavaRuntime(string root, string platform, string component) {
|
private static async Task DownloadJavaRuntime(string root, string platform, string component) {
|
||||||
string allJsonUrl = "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc6c0dba9f635e09f3900331038590632291/all.json";
|
var allRuntimesResponse = await HttpHelper.FetchAsync(LauncherConstants.Urls.AllJavaRuntime);
|
||||||
|
|
||||||
var allRuntimesResponse = await HttpHelper.FetchAsync(allJsonUrl);
|
|
||||||
allRuntimesResponse.EnsureSuccessStatusCode();
|
allRuntimesResponse.EnsureSuccessStatusCode();
|
||||||
var allRuntimes = await allRuntimesResponse.Content.ReadFromJsonAsync<JsonElement>(LauncherConstants._jsonOptions);
|
var allRuntimes = await allRuntimesResponse.Content.ReadFromJsonAsync<JsonElement>(LauncherConstants._jsonOptions);
|
||||||
|
|
||||||
if (!allRuntimes.TryGetProperty(platform, out var platformData) ||
|
if (!allRuntimes.TryGetProperty(platform, out var platformData) ||
|
||||||
!platformData.TryGetProperty(component, out var componentVersions)) {
|
!platformData.TryGetProperty(component, out var componentVersions)) {
|
||||||
throw new Exception($"Le runtime {component} n'est pas disponible pour {platform}");
|
throw new Exception($"There is no {component} runtime for {platform}");
|
||||||
}
|
}
|
||||||
|
|
||||||
string manifestUrl = componentVersions[0].GetProperty("manifest").GetProperty("url").GetString()!;
|
string manifestUrl = componentVersions[0].GetProperty("manifest").GetProperty("url").GetString()!;
|
||||||
|
|||||||
@ -212,9 +212,9 @@ public static class VersionsHelper {
|
|||||||
string jsonResponse = await response.Content.ReadAsStringAsync();
|
string jsonResponse = await response.Content.ReadAsStringAsync();
|
||||||
var version = JsonSerializer.Deserialize<MinecraftVersion>(jsonResponse, LauncherConstants._jsonOptions);
|
var version = JsonSerializer.Deserialize<MinecraftVersion>(jsonResponse, LauncherConstants._jsonOptions);
|
||||||
|
|
||||||
return version ?? throw new Exception("Impossible de lire les détails de la version.");
|
return version ?? throw new Exception("Version details data are unreadable.");
|
||||||
} else {
|
} else {
|
||||||
throw new Exception($"Erreur lors de la récupération des détails : {response.StatusCode}");
|
throw new Exception($"Error when getting version details: {response.StatusCode}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ public static class ForgeHelper {
|
|||||||
string promoKey = $"{mcVersion}-{(recommended ? "recommended" : "latest")}";
|
string promoKey = $"{mcVersion}-{(recommended ? "recommended" : "latest")}";
|
||||||
|
|
||||||
if (promoData?.Promos == null || !promoData.Promos.TryGetValue(promoKey, out string? buildVersion)) {
|
if (promoData?.Promos == null || !promoData.Promos.TryGetValue(promoKey, out string? buildVersion)) {
|
||||||
throw new Exception($"Version Forge introuvable pour {promoKey}");
|
throw new Exception($"No forge version found for : {promoKey}");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isModern = IsVersionModern(mcVersion);
|
bool isModern = IsVersionModern(mcVersion);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ namespace Lentia.Core.Utils;
|
|||||||
|
|
||||||
public static class FileHelper {
|
public static class FileHelper {
|
||||||
public static async Task DownloadFileAsync(string url, string destinationPath) {
|
public static async Task DownloadFileAsync(string url, string destinationPath) {
|
||||||
|
Console.WriteLine($"Downloading file from {url} to {destinationPath}");
|
||||||
string? directory = Path.GetDirectoryName(destinationPath);
|
string? directory = Path.GetDirectoryName(destinationPath);
|
||||||
if (!string.IsNullOrEmpty(directory)) {
|
if (!string.IsNullOrEmpty(directory)) {
|
||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directory);
|
||||||
|
|||||||
@ -8,6 +8,7 @@ public static class HttpHelper {
|
|||||||
private static readonly HttpClient Http = new HttpClient();
|
private static readonly HttpClient Http = new HttpClient();
|
||||||
|
|
||||||
public static async Task<HttpResponseMessage> FetchAsync(string url, HttpMethod? method = null, object? body = null, Dictionary<string, string>? headers = null) {
|
public static async Task<HttpResponseMessage> FetchAsync(string url, HttpMethod? method = null, object? body = null, Dictionary<string, string>? headers = null) {
|
||||||
|
Console.WriteLine($"Fetching {url} using {method} method");
|
||||||
var request = new HttpRequestMessage(method ?? HttpMethod.Get, url);
|
var request = new HttpRequestMessage(method ?? HttpMethod.Get, url);
|
||||||
|
|
||||||
if (headers != null) {
|
if (headers != null) {
|
||||||
|
|||||||
@ -64,7 +64,7 @@ public static class SettingsManager {
|
|||||||
|
|
||||||
foreach (var k in keys) {
|
foreach (var k in keys) {
|
||||||
var property = current.GetType().GetProperty(k);
|
var property = current.GetType().GetProperty(k);
|
||||||
if (property == null) throw new Exception($"Clé {k} introuvable.");
|
if (property == null) throw new Exception($"Key {k} not found.");
|
||||||
current = property.GetValue(current)!;
|
current = property.GetValue(current)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ public static class SettingsManager {
|
|||||||
var prop = current.GetType().GetProperty(properties[i],
|
var prop = current.GetType().GetProperty(properties[i],
|
||||||
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.IgnoreCase);
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.IgnoreCase);
|
||||||
|
|
||||||
if (prop == null) throw new Exception($"Niveau '{properties[i]}' introuvable.");
|
if (prop == null) throw new Exception($"Level '{properties[i]}' not found.");
|
||||||
|
|
||||||
var next = prop.GetValue(current);
|
var next = prop.GetValue(current);
|
||||||
if (next == null) {
|
if (next == null) {
|
||||||
@ -99,14 +99,14 @@ public static class SettingsManager {
|
|||||||
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.IgnoreCase);
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.IgnoreCase);
|
||||||
|
|
||||||
if (lastProp == null || !lastProp.CanWrite)
|
if (lastProp == null || !lastProp.CanWrite)
|
||||||
throw new Exception($"Propriété '{properties[^1]}' introuvable ou verrouillée.");
|
throw new Exception($"Property '{properties[^1]}' not found or locked.");
|
||||||
|
|
||||||
object? convertedValue = Convert.ChangeType(value.ToString(), lastProp.PropertyType);
|
object? convertedValue = Convert.ChangeType(value.ToString(), lastProp.PropertyType);
|
||||||
lastProp.SetValue(current, convertedValue);
|
lastProp.SetValue(current, convertedValue);
|
||||||
|
|
||||||
WriteSettings(settings);
|
WriteSettings(settings);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Console.WriteLine($"[SettingsManager] Erreur Set sur '{path}': {ex.Message}");
|
Console.WriteLine($"[SettingsManager] \"set\" Error on '{path}': {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +69,6 @@ public static class WindowHelper {
|
|||||||
|
|
||||||
Size loginSize = GetScaledSize(window, 310, 420);
|
Size loginSize = GetScaledSize(window, 310, 420);
|
||||||
window
|
window
|
||||||
.SetTitle("Lentia")
|
|
||||||
.SetIconFile(iconPath)
|
.SetIconFile(iconPath)
|
||||||
.SetResizable(false)
|
.SetResizable(false)
|
||||||
.SetSize(loginSize)
|
.SetSize(loginSize)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user