/// <summary> /// Check minecraft assets before launch /// </summary> /// <returns> /// hasValidIndex: Indicates whether a valid index file exists /// missingAssets: List of missing assets, will be null if 'hasValidIndex' is false. /// </returns> public (bool hasValidIndex, List <MinecraftAsset> missingAssets) CheckAssets(KMCCC.Launcher.Version version) { string indexPath = string.Format(@"{0}\assets\indexes\{1}.json", Core.GameRootPath, version.Assets); bool hasIndex = Core.CheckFileHash(indexPath, version.AssetsIndex.SHA1, new SHA1CryptoServiceProvider()); if (!hasIndex) { return(false, null); } //Read and parse asset index string json = File.ReadAllText(indexPath); JObject rootObj = null; try { rootObj = JObject.Parse(json)["objects"]?.ToObject <JObject>(); } catch (JsonException) { return(false, null); } List <MinecraftAsset> ret = new List <MinecraftAsset>(); if (rootObj == null) { //Some specific versions may not contain assets files return(true, ret); } var sha1 = new SHA1CryptoServiceProvider(); foreach (KeyValuePair <string, JToken> prop in rootObj) { string _hash = prop.Value["hash"].ToString(); if (string.IsNullOrWhiteSpace(_hash)) { continue; } int _size; int.TryParse(prop.Value["size"].ToString(), out _size); MinecraftAsset asset = new MinecraftAsset { Hash = _hash, Size = _size }; if (!Core.CheckFileHash(string.Format(@"{0}\{1}", Core.GameRootPath, asset.GetPath()), asset.Hash, sha1)) { ret.Add(asset); } } return(true, ret); }
public override ValueSet OnRequest(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) { string versionID = args.Request.Message["version"].ToString(); if (string.IsNullOrWhiteSpace(versionID)) { return(null); } Logger.Info("Scanning libraries and natives"); KMCCC.Launcher.Version ver = Program.Launcher.Core.GetVersion(versionID); List <MinecraftAssembly> missing = new List <MinecraftAssembly>(); List <MinecraftAssembly> missingLib = Program.Launcher.CheckLibraries(ver); List <MinecraftAssembly> missingNative = Program.Launcher.CheckNatives(ver); Logger.Info("Found " + missingLib?.Count + " missing libraries"); foreach (MinecraftAssembly lib in missingLib) { Logger.Warn(" # " + lib.Name); } Logger.Info("Found " + missingNative?.Count + " missing natives"); foreach (MinecraftAssembly nav in missingNative) { Logger.Warn(" # " + nav.Name); } missing.AddRange(missingLib); missing.AddRange(missingNative); Logger.Info("Serializing list to json"); string json = null; try { json = JsonConvert.SerializeObject(missing); } catch (JsonException) { return(null); } ValueSet ret = new ValueSet(); ret["value"] = json; Logger.Info("Sending list to app"); return(ret); }
public List <MinecraftAssembly> CheckNatives(KMCCC.Launcher.Version version) { List <MinecraftAssembly> missing = new List <MinecraftAssembly>(); List <Native> missingNav = Core.CheckNatives(version); foreach (Native nav in missingNav) { string dName = nav.Url.Substring(nav.Url.LastIndexOf('/') + 1); missing.Add(new MinecraftAssembly { Name = dName, Path = Core.GetNativePath(nav), Url = nav.Url }); } return(missing); }
public List <MinecraftAssembly> CheckLibraries(KMCCC.Launcher.Version version) { List <MinecraftAssembly> missing = new List <MinecraftAssembly>(); List <Library> missingLib = Core.CheckLibraries(version); foreach (Library lib in missingLib) { string dName = lib.Url.Substring(lib.Url.LastIndexOf('/') + 1); missing.Add(new MinecraftAssembly { Name = dName, Path = Core.GetLibPath(lib), Url = lib.Url }); } return(missing); }
private void Btn_launch_Click(object sender, RoutedEventArgs e) { KMCCC.Launcher.Version selectedItem = (KMCCC.Launcher.Version) this.ListVersions.SelectedItem; if (selectedItem == null) { MessageBox.Show("检测到没有游戏文件!"); } else { Config.LastVersion = selectedItem.Id; LaunchOptions options = new LaunchOptions { Version = selectedItem, MaxMemory = Config.MaxMemory, Authenticator = (Config.Authenticator == "Yggdrasil") ? ((IAuthenticator) new YggdrasilLogin(Config.UserName, Config.Password, true, null, null)) : ((IAuthenticator) new OfflineAuthenticator(Config.UserName)), Server = (Config.Server != null) ? new ServerInfo() : null, Mode = (Config.LaunchMode == "BMCL") ? ((LaunchMode)LaunchMode.BmclMode) : ((Config.LaunchMode == "MCLauncher") ? ((LaunchMode)LaunchMode.MCLauncher) : null) }; Action <MinecraftLaunchArguments>[] argumentsOperators = new Action <MinecraftLaunchArguments>[] { args => args.AdvencedArguments.Add(Config.AdvancedArguments) }; LaunchResult result = App.Core.Launch(options, argumentsOperators); if (!result.Success) { MessageBox.Show(result.ErrorMessage, result.ErrorType.ToString(), MessageBoxButton.OK, MessageBoxImage.Hand); switch (result.ErrorType) { case ErrorType.NoJAVA: case ErrorType.AuthenticationFailed: new ConfigWindow { Owner = this }.ShowDialog(); break; } } else { base.Hide(); } } }
private async void Btn_启动_Click(object sender, RoutedEventArgs e) { if (设置框.IsVisible) { Nosave(); return; } Btn_启动.IsEnabled = false; runts.Text = "正在启动中"; runts.Visibility = Visibility.Visible; if (ListVersions.Items.Count == 0) { await this.ShowMessageAsync("无法启动游戏", "没有读取到游戏版本", MessageDialogStyle.Affirmative, new MetroDialogSettings() { AffirmativeButtonText = "确定" }); Btn_启动.IsEnabled = true; runts.Text = null; load.Visibility = Visibility.Hidden; return; } if (DownWindow.bgWorker.IsBusy) { //bgWorker.IsBusy await this.ShowMessageAsync("正在下载", "正在下载资源文件", MessageDialogStyle.Affirmative, new MetroDialogSettings() { AffirmativeButtonText = "确定" }); // new downWindow { Owner = this }.ShowDialog(); //downWindow.Showdown(); downw.ShowDialog(); //this.Hide(); //down.Show(); } else { runts.Text = "检查支持库"; lostFlie.Clear();//清空列表,防止重新启动后,列表重复 ver = (Version)ListVersions.SelectedItem; core = LauncherCore.Create(); var version = ver;//设置读取的版本配置为当前选择的项 var jarid = ver.JarId; // MessageBox.Show(core.GetVersionJsonPath(jarid)); if (!File.Exists(core.GetVersionJsonPath(jarid))) { Ts("无法启动游戏", "游戏核心不存在,请确认已选择正确的核心版本!"); runts.Visibility = Visibility.Hidden; Btn_启动.Content = "启动游戏"; load.Visibility = Visibility.Hidden; return; } try { var libs = version.Libraries.Select(lib => core.GetLibPath(lib)); var natives = version.Natives.Select(native => core.GetNativePath(native)); foreach (string libflie in libs) { if (!File.Exists(libflie)) { lostFlie.Add(libflie); // MessageBox.Show("当前缺少的Libraries文件有:" + file); } } foreach (string libflie in natives) { if (!File.Exists(libflie)) { lostFlie.Add(libflie); //MessageBox.Show("当前缺少的Libraries-natives文件有:" + file); } } if (lostFlie.Count != 0) { //返回一个值,中止继续执行后面的代码 new DownWindow { Owner = this }.ShowDialog(); } } catch { Ts("无法启动游戏", "版本信息获取失败,无法读取所需的支持库,请确认已选择正确的核心版本!"); runts.Visibility = Visibility.Hidden; Btn_启动.Content = "启动游戏"; load.Visibility = Visibility.Hidden; return; } lostFlie.Clear(); lostasset.Clear(); lostlegacyasset.Clear(); runts.Text = "检查资源文件"; if (!Directory.Exists(rundir + ".minecraft/assets/indexes")) { Directory.CreateDirectory(rundir + ".minecraft/assets/indexes");//创建文件夹 } if (!Directory.Exists(rundir + ".minecraft/assets/objects")) { Directory.CreateDirectory(rundir + ".minecraft/assets/objects");//创建文件夹 } var jsondir = core.GetVersionJsonPath(jarid); string json = File.ReadAllText(jsondir); // MessageBox.Show(core.VersionLocator); JsonData data = JsonMapper.ToObject(json); string type; string url; try { type = data["assetIndex"]["id"].ToString(); url = data["assetIndex"]["url"].ToString().Replace("https://launchermeta.mojang.com", "http://download.mcbbs.net"); if (type != "legacy") { string jsonindex; if (File.Exists(rundir + @".minecraft\assets\indexes\" + type + ".json")) { jsonindex = File.ReadAllText(rundir + @".minecraft\assets\indexes\" + type + ".json"); } else { jsonindex = Beelogin.GetGeneralContent(url); File.WriteAllText(rundir + @".minecraft\assets\indexes\" + type + ".json", jsonindex, Encoding.Default); } JsonData jdata = JsonMapper.ToObject(jsonindex); jdata = jdata["objects"]; string hash; string two; string lj; for (int i = 0; i < jdata.Count; i++) { hash = jdata[i]["hash"].ToString(); two = hash.Substring(0, 2); lj = two + "\\" + hash; if (!File.Exists(rundir + @".minecraft\assets\objects\" + lj)) { lostasset.Add(hash); } } } else if (type == "legacy") { string jsonindex; if (File.Exists(rundir + @".minecraft\assets\indexes\legacy.json")) { jsonindex = File.ReadAllText(rundir + ".minecraft/assets/indexes/legacy.json"); } else { jsonindex = Beelogin.GetGeneralContent(url); } File.WriteAllText(rundir + @".minecraft\assets\indexes\legacy.json", jsonindex, Encoding.Default); JObject jdata = (JObject)JsonConvert.DeserializeObject(jsonindex); jdata = (JObject)jdata["objects"]; // jdata = jdata["objects"]; foreach (var name in jdata) { //MessageBox.Show(rundir + @".minecraft\assets\" + name.Key); if (!File.Exists(rundir + @".minecraft\assets\" + name.Key)) { lostlegacyasset.Add(name.Key.Replace("/", "\\")); } } } } catch { type = data["assets"].ToString(); url = "null"; if (type != "legacy") { string jsonindex; if (File.Exists(rundir + @".minecraft\assets\indexes\" + type + ".json")) { jsonindex = File.ReadAllText(rundir + @".minecraft\assets\indexes\" + type + ".json"); JsonData jdata = JsonMapper.ToObject(jsonindex); jdata = jdata["objects"]; string hash; string two; string lj; for (int i = 0; i < jdata.Count; i++) { hash = jdata[i]["hash"].ToString(); two = hash.Substring(0, 2); lj = two + "\\" + hash; if (!File.Exists(rundir + @".minecraft\assets\objects\" + lj)) { lostasset.Add(hash); } } lostassets = false; } else { lostassets = true; } } else if (type == "legacy") { string jsonindex; if (File.Exists(rundir + @".minecraft\assets\indexes\legacy.json")) { jsonindex = File.ReadAllText(rundir + ".minecraft/assets/indexes/legacy.json"); File.WriteAllText(rundir + @".minecraft\assets\indexes\legacy.json", jsonindex, Encoding.Default); JObject jdata = (JObject)JsonConvert.DeserializeObject(jsonindex); jdata = (JObject)jdata["objects"]; // jdata = jdata["objects"]; foreach (var name in jdata) { //MessageBox.Show(rundir + @".minecraft\assets\" + name.Key); if (!File.Exists(rundir + @".minecraft\assets\" + name.Key)) { lostlegacyasset.Add(name.Key.Replace("/", "\\")); } } lostassets = false; } else { lostassets = true; } } } try { if (lostasset.Count != 0 || lostlegacyasset.Count != 0) { if (url == "null") { await this.ShowMessageAsync("资源文件缺失", "发现缺少了" + (lostasset.Count != 0 ? lostasset.Count.ToString() : lostlegacyasset.Count != 0 ? lostlegacyasset.Count.ToString() : null) + "个资源文件,这可能导致游戏声音丢失\n但您的游戏核心版本较旧,不能自动补全.\n建议前往下载游戏窗口下载新版本客户端!", MessageDialogStyle.Affirmative, new MetroDialogSettings() { AffirmativeButtonText = "确定" }); // Ts("资源文件缺失", "发现缺少了" + (lostasset.Count != 0 ? lostasset.Count.ToString() : lostlegacyasset.Count != 0 ? lostlegacyasset.Count.ToString() : null) + "个资源文件,但您的游戏核心版本较旧,不能自动补全.\n建议前往下载游戏窗口下载新版本客户端!"); } else { // new downWindow { Owner = this }.ShowDialog(); downw.Owner = this; downw.ShowDialog(); } } } catch { //ts("错误", "尝试检查资源文件时失败,建议前往下载游戏窗口下载新版本客户端!"); lostassets = true; // await this.ShowMessageAsync("错误", "尝试检查资源文件时失败,建议前往下载游戏窗口下载新版本客户端!", MessageDialogStyle.Affirmative, new MetroDialogSettings() { AffirmativeButtonText = "确定" }); } } if (!bgWorker.IsBusy) { //MessageBox.Show("1"); // bgWorker.CancelAsync(); //bgWorker.Dispose(); if (islaunch) { bgWorker.RunWorkerAsync(); } else { bgWorker.WorkerReportsProgress = true; bgWorker.ProgressChanged += new ProgressChangedEventHandler(Bw_ProgressChanged); bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bw_RunWorkerCompleted); bgWorker.DoWork += new DoWorkEventHandler(Bw_DoWork1); bgWorker.RunWorkerAsync(); islaunch = true; } } }
private bool CheckAssetsIndex(KMCCC.Launcher.Version kver) { var result = CoreMCL.CheckAssets(kver); return(result.hasValidIndex); }
private async Task launch() { Config.INSTANCE.User = ViewModel.User; Config.SaveConfigToFileAsync(); KMCCC.Launcher.Version kver = ViewModel.SelectedVersion; if (kver == null) { await MainWindow.Current.ShowMessageAsync("启动失败", "版本未指定,请选择一个要启动的Minecraft版本"); return; } if (CoreMCL.UserAuthenticator == null) { await MainWindow.Current.ShowMessageAsync("启动失败", "未指定用户,请前往账户设置选择要登入Minecraft的用户"); return; } Option.versionId = kver.Id; Option.javaExt = Config.INSTANCE.JavaExt; Option.javaArgs = Config.INSTANCE.JavaArgs; if (Config.INSTANCE.MaxMemory > 0) { Option.javaArgs = string.Format("-Xmx{0}M {1}", Config.INSTANCE.MaxMemory, Option.javaArgs); } #region Check libraries and natives ViewModel.LaunchButtonContent = "正在检查核心文件..."; List <MinecraftAssembly> missing = null; await Task.Run(() => { missing = CoreMCL.CheckLibraries(kver); missing?.AddRange(CoreMCL.CheckNatives(kver)); }); if (missing?.Count > 0) { ViewModel.LaunchButtonContent = "正在下载核心文件..."; DownloadDialog dialog = new DownloadDialog("正在下载运行Minecraft所需的文件..."); missing.ForEach(lib => { if (Uri.TryCreate(lib.Url, UriKind.Absolute, out Uri uri)) { DownloadItem item = new DownloadItem(lib.Name, lib.Path, uri); dialog.DownloadQuene.Add(item); } }); dialog.StartDownload(); if (await ShowDownloadDialog(dialog)) { return; } } #endregion // Check Assets ViewModel.LaunchButtonContent = "正在检查资源文件"; if (!CheckAssetsIndex(kver)) { ViewModel.LaunchButtonContent = "正在获取资源元数据"; try { await Task.Run(async() => { using (HttpClient client = new HttpClient()) { string json = await client.GetStringAsync(kver.AssetsIndex.Url); string path = string.Format(@"{0}\assets\indexes\{1}.json", CoreMCL.Core.GameRootPath, kver.Assets); FileInfo fileInfo = new FileInfo(path); if (!fileInfo.Directory.Exists) { fileInfo.Directory.Create(); } fileInfo.Create().Dispose(); File.WriteAllText(path, json); } }); } catch (HttpRequestException ex) { await MainWindow.Current.ShowMessageAsync("获取资源元数据失败", ex.Message + ex.StackTrace, MessageDialogStyle.Affirmative, DefaultDialogSettings); return; } catch (IOException ex) { await MainWindow.Current.ShowMessageAsync("获取资源元数据失败", ex.Message + ex.StackTrace, MessageDialogStyle.Affirmative, DefaultDialogSettings); return; } } ViewModel.LaunchButtonContent = "正在检查资源文件..."; (bool hasValidIndex, List <MinecraftAsset> missingAssets)assetsResult = (false, null); await Task.Run(() => { assetsResult = CoreMCL.CheckAssets(kver); }); if (!assetsResult.hasValidIndex) { await MainWindow.Current.ShowMessageAsync("获取资源元数据失败", "发生未知错误,无法获取有效的资源元数据,我们将为您继续启动游戏,但这可能会导致游戏中出现无翻译和无声音等问题"); } else { if (assetsResult.missingAssets.Count > 0) { DownloadDialog dialog = new DownloadDialog("正在下载资源文件..."); assetsResult.missingAssets.ForEach(ass => { if (Uri.TryCreate(ass.GetDownloadUrl(), UriKind.Absolute, out Uri uri)) { DownloadItem item = new DownloadItem("资源: " + ass.Hash, CoreMCL.Core.GameRootPath + "\\" + ass.GetPath(), uri); dialog.DownloadQuene.Add(item); } }); if (await ShowDownloadDialog(dialog)) { return; } } } ViewModel.LaunchButtonContent = "正在启动..."; LaunchResult result = CoreMCL.Launch(Option); if (!result.Success) { await MainWindow.Current.ShowMessageAsync("启动失败", result.ErrorMessage + "\r\n" + result.Exception); } }