minecraft吧 关注:2,568,784贴子:32,084,089

回复:我的世界启动器制作教程

只看楼主收藏回复

可以


IP属地:广东来自Android客户端175楼2016-06-30 20:01
收起回复
    于是修改我们的Launch方法为函数如下:


    176楼2016-07-01 14:28
    回复
      2026-01-14 06:58:17
      广告
      不感兴趣
      开通SVIP免广告
      /// <summary>
      /// 启动主方法
      /// </summary>
      /// <param name="MaxMem">最大内存</param>
      /// <param name="JavaPath">Javaw.exe路径</param>
      /// <param name="UserName">用户名</param>
      /// <param name="VerName">版本名</param>
      /// <param name="returnvalue">返回值的指定。0为不返回,直接执行;1为返回库的完整字符串;2为返回完整的启动命令。默认为0。</param>
      public string Launch(string MaxMem,string JavaPath,string UserName,string VerName,int returnvalue=0)
      {
      string rtxt = "";//声明
      int tmp = 0;//声明
      rtxt = File.ReadAllText(Application.StartupPath + "\\.minecraft\\versions\\" + VerName + "\\" + VerName + ".json").Replace(" ", "").Replace("\n","");//读取内容
      tmp = rtxt.IndexOf("mainClass") + "mainClass".Length + 3;//取名称起始位置并赋值到tmp
      String mainClass = rtxt.Substring(tmp, rtxt.IndexOf("\"", tmp) - tmp);//截取值
      tmp = rtxt.IndexOf("minecraftArguments") + "minecraftArguments".Length + 3;//json读取部分,同上
      String minecraftArguments = rtxt.Substring(tmp, rtxt.IndexOf("\"", tmp) - tmp).Replace("${", " ${").Replace("}", "} ").Replace("cpw", " cpw");//json读取部分,同上
      tmp = rtxt.IndexOf("libraries") + "libraries".Length + 3;//json读取部分,同上
      String libraries = rtxt.Substring(tmp + 1, rtxt.LastIndexOf("]") - tmp);//json读取部分,同上
      String natives = Application.StartupPath + "\\.minecraft\\versions\\" + VerName + "\\" + VerName + "-natives";//设置natives路径
      if (!Directory.Exists(natives))//目录不存在
      {
      Directory.CreateDirectory(natives);//创建
      }
      String[] libs = libraries.Replace("${arch}","32").Replace("},{", "^").Split("^".ToCharArray());//将},{替换为^然后以^进行分割,顺便决定32位系统
      String libp="";//声明libp
      for (int i = 0; i < libs.Length; i++)//为数组内容循环,也可以考虑foreach
      {
      if (libs[i].IndexOf("name") == -1)//如果没有name值
      {
      continue;//跳过
      }
      String tml = libs[i];//声明临时字符串变量tml
      if (tml.IndexOf("{") != -1)//如果含有子json对象,则去掉子项
      {
      do//循环
      {
      try//捕获错误
      {
      tml = tml.Replace(tml.Substring(tml.LastIndexOf("{") - 1, tml.IndexOf("}", tml.LastIndexOf("{")) - tml.LastIndexOf("{") + 1), "");//去掉子项
      }
      catch (ArgumentOutOfRangeException ex)//如果是干扰的
      {
      tml = tml + "," + libs[i + 1];//追加
      tml = tml.Replace(tml.Substring(tml.LastIndexOf("{") - 1, tml.IndexOf("}", tml.LastIndexOf("{")) - tml.LastIndexOf("{") + 1), "");//再去掉子项
      }
      } while (tml.IndexOf("{") != -1);//有子项则仍然循环
      tml = tml.Replace("{", "").Replace("}", "");//去掉干扰的{}
      }
      tmp = tml.IndexOf("name") + "name".Length + 3;//json读取部分,同上
      String libn = tml.Substring(tmp, tml.IndexOf("\"", tmp) - tmp);//json读取部分,同上
      if (libn.IndexOf(":") == -1)//如果name的值不合法
      {
      continue;//跳过
      }
      String[] tlib = new String[] { libn.Substring(0, libn.IndexOf(":")).Replace(":", ""), libn.Substring(libn.IndexOf(":") + 1, libn.IndexOf(":", libn.IndexOf(":") + 1) - libn.IndexOf(":")).Replace(":", ""), libn.Substring(libn.IndexOf(":", libn.IndexOf(":") +1)).Replace(":", "") };//将读取的name值转成路径
      String tpath = Application.StartupPath + "\\.minecraft\\libraries\\" + tlib[0].Replace(".", "\\") + "\\" + tlib[1] + "\\" + tlib[2] + "\\" + tlib[1] + "-" + tlib[2] + ".jar";//同上
      if (libs[i].IndexOf("natives")!= -1 && libs[i].IndexOf("windows") != -1)//如果有natives指定
      {
      tmp = libs[i].IndexOf("windows") + "windows".Length + 3;//json读取部分,同上
      tpath = tpath.Replace(".jar", "") + "-" + libs[i].Substring(tmp, libs[i].IndexOf("\"", tmp) - tmp) + ".jar";//json读取部分,同上
      }
      if (File.Exists(tpath))//检查文件是否存在
      {
      libp = libp + tpath + ";";//存在就加录
      }
      if (libs[i].IndexOf("extract") != -1)//如果要提取natives
      {
      decompress(tpath, natives);//提取
      }
      }
      if (returnvalue == 1)//如果要返回库路径
      {
      return libp;//返回并退出方法
      }
      if (rtxt.IndexOf("inheritsFrom\":") != -1)//如果是继承的json数据
      {
      tmp = rtxt.IndexOf("inheritsFrom\":") + "inheritsFrom".Length + 3;//json读取部分,同上
      String newVerName = rtxt.Substring(tmp, rtxt.IndexOf("\"", tmp) - tmp);//json读取部分,同上
      libp += Launch("", "", "", newVerName, 1);//读入父json数据生成的库,解压父json数据要求的natives
      tmp = rtxt.IndexOf("jar\":") + "jar".Length + 3;//json读取部分,同上
      VerName = rtxt.Substring(tmp, rtxt.IndexOf("\"", tmp) - tmp);//json读取部分,同上
      natives = Application.StartupPath + "\\.minecraft\\versions\\" + newVerName + "\\" + newVerName + "-natives";//重新指定natives文件夹
      }
      libp = libp + Application.StartupPath + "\\.minecraft\\versions\\" + VerName + "\\" + VerName + ".jar";//整合字符串
      String assets = Application.StartupPath + "\\.minecraft\\assets";//设置资源文件夹路径
      tmp = rtxt.IndexOf("assets\":") + "assets".Length + 3;//json读取部分,同上
      String assetIndex = rtxt.Substring(tmp, rtxt.IndexOf("\"", tmp) - tmp);//json读取部分,同上
      if (!File.Exists(assets + "\\indexes\\" + assetIndex + ".json"))//如果不存在
      {
      if (File.Exists(assets + "\\virtual\\legacy\\indexes\\" + assetIndex + ".json"))//如果virtual目录有效
      {
      assets = assets + "\\virtual\\legacy";//修改资源文件夹
      }
      }
      String gameDir=Application.StartupPath + "\\.minecraft";//设置游戏路径
      if (Application.StartupPath.IndexOf(" ") != -1)//如果路径有空格
      {
      natives = "\"" + natives + "\"";//加上引号
      libp = "\"" + libp + "\"";//加上引号
      assets = "\"" + assets + "\"";//加上引号
      gameDir = "\"" + gameDir + "\"";//加上引号
      }
      minecraftArguments = minecraftArguments.Replace("${auth_player_name}", UserName).Replace("${version_name}", "JuicyLauncher_1.0").Replace("${game_directory}", gameDir).Replace("${game_assets}", assets).Replace("${assets_root}",assets).Replace("${assets_index_name}",assetIndex).Replace("${user_properties}","{}").Replace("${user_type}","Legacy");//读取额外参数
      //启动参数拼接
      String RunComm = "";//声明RunComm
      RunComm = "-Xmx" + MaxMem + "m -Djava.library.path=" + natives + " -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -cp " + libp + " " + mainClass + " " + minecraftArguments;//拼接参数
      if (returnvalue == 2)//如果要返回完整的启动命令
      {
      return RunComm;//返回并退出
      }
      Process mjp=new Process();//运行部分
      ProcessStartInfo psi = new ProcessStartInfo(JavaPath, RunComm);//运行部分
      psi.UseShellExecute = false;//运行部分
      mjp.StartInfo = psi;//运行部分
      mjp.Start();//运行部分
      Application.Exit();//退出
      return null;//最终返回空值
      }


      177楼2016-07-01 14:29
      回复
        实测可以启动成功。


        178楼2016-07-01 14:30
        回复
          进阶四:纯净版库的补全


          179楼2016-07-01 14:30
          回复
            请大家看一下第153楼的这段json数据:
            {
            "name":"com.mojang:netty:1.6",
            "downloads":{
            "artifact":{
            "size":7877,
            "sha1":"4b75825a06139752bd800d9e29c5fd55b8b1b1e4",
            "path":"com/mojang/netty/1.6/netty-1.6.jar",
            "url":"https://libraries.minecraft.net/com/mojang/netty/1.6/netty-1.6.jar"
            }
            }
            },


            180楼2016-07-01 14:33
            回复
              首先您要知道,您的用户的客户端也许并不完整。这样的客户端是无法启动的。这时,就需要我们的启动器来自动下载所缺少的库了。那么,我们怎么知道要下载的库的URL的存放路径呢?


              181楼2016-07-01 14:35
              回复
                上面的json数据派上了用场。


                182楼2016-07-01 14:36
                回复
                  2026-01-14 06:52:17
                  广告
                  不感兴趣
                  开通SVIP免广告
                  183楼2016-07-01 14:36
                  回复
                    但如果您看一看1.7.2.json的话,


                    来自Android客户端186楼2016-07-02 16:16
                    回复
                      您会发现它并没有提供下载地址。


                      来自Android客户端187楼2016-07-02 16:16
                      回复
                        我们可以通过加上https://libraries.minecraft.net/的前缀和路径(替换\为/以后的)拼接在一起得到下载地址。


                        来自Android客户端188楼2016-07-03 17:53
                        回复
                          然后,我们只要在库文件不存在的情况下下载即可。


                          来自Android客户端189楼2016-07-03 18:22
                          回复
                            但是,我们可不能犯HHS Minecraft启动器的错误,一下载就卡在那了,直到下载好了才行。


                            来自Android客户端190楼2016-07-03 18:23
                            回复
                              2026-01-14 06:46:17
                              广告
                              不感兴趣
                              开通SVIP免广告
                              所以,我们要创建一个向用户显示下载进度的窗口,并尽力不用死循环。(VB语言的注意了,在VB非.net中只要来个死循环,运行一下,你的项目如果没保存基本上就废了)


                              来自Android客户端192楼2016-07-04 17:33
                              收起回复