Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
 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();
         }
     }
 }
Beispiel #6
0
        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;
                }
            }
        }
Beispiel #7
0
        private bool CheckAssetsIndex(KMCCC.Launcher.Version kver)
        {
            var result = CoreMCL.CheckAssets(kver);

            return(result.hasValidIndex);
        }
Beispiel #8
0
        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);
            }
        }