CTZLauncher/CTZLauncher/Launcher/LauncherCoreInternal.cs

226 lines
8.5 KiB
C#

namespace KMCCC.Launcher
{
#region
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Tools;
#endregion
partial class LauncherCore
{
internal object Locker = new object();
private LaunchResult GenerateArguments(LaunchOptions options, ref MinecraftLaunchArguments args)
{
try
{
var authentication = options.Authenticator.Do();
if (!string.IsNullOrWhiteSpace(authentication.Error))
return new LaunchResult
{
Success = false,
ErrorType = ErrorType.AuthenticationFailed,
ErrorMessage = "验证错误: " + authentication.Error
};
args.CGCEnabled = true;
args.MainClass = options.Version.MainClass;
args.MaxMemory = options.MaxMemory;
args.MinMemory = options.MinMemory;
args.NativePath = GameRootPath + @"\versions\" + options.Version.Id + @"\" + options.Version.Id + @"-natives";
foreach (var native in options.Version.Natives)
{
var exp = ZipTools.UnzipFile(this.GetNativePath(native), args.NativePath, native.Options);
if (exp == null)
{
continue;
}
return new LaunchResult
{
Success = false,
ErrorType = ErrorType.UncompressingFailed,
ErrorMessage = string.Format("解压错误: {0}:{1}:{2}", native.NS, native.Name, native.Version),
Exception = exp
};
}
args.Server = options.Server;
args.Size = options.Size;
args.Libraries = options.Version.Libraries.Select(this.GetLibPath).ToList();
args.Libraries.Add(this.GetVersionJarPath(options.Version.JarId));
args.MinecraftArguments = options.Version.MinecraftArguments;
args.Tokens.Add("auth_access_token", authentication.AccessToken.GoString());
args.Tokens.Add("auth_session", authentication.AccessToken.GoString());
args.Tokens.Add("auth_player_name", authentication.DisplayName);
args.Tokens.Add("version_name", options.Version.Id);
args.Tokens.Add("game_directory", GameRootPath + @"\versions\" + options.Version.Id + @"\");
args.Tokens.Add("game_assets", "assets");
args.Tokens.Add("assets_root", "assets");
args.Tokens.Add("assets_index_name", options.Version.Assets);
args.Tokens.Add("auth_uuid", authentication.UUID.GoString());
args.Tokens.Add("user_properties", authentication.Properties);
args.Tokens.Add("user_type", authentication.UserType);
args.AdvencedArguments = new List<string> { "-Dfml.ignoreInvalidMinecraftCertificates=true", "-Dfml.ignorePatchDiscrepancies=true" };
args.Authentication = authentication;
args.Version = options.Version;
if (options.Mode != null)
{
options.Mode.Operate(this, args);
}
return null;
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
Console.WriteLine(exp.Source);
Console.WriteLine(exp.StackTrace);
return new LaunchResult { Success = false, ErrorType = ErrorType.Unknown, ErrorMessage = "在生成参数时发生了意外的错误", Exception = exp };
}
}
internal LaunchResult LaunchInternal(LaunchOptions options, params Action<MinecraftLaunchArguments>[] argumentsOperators)
{
lock (Locker)
{
if (!File.Exists(JavaPath))
{
return new LaunchResult { Success = false, ErrorType = ErrorType.NoJAVA, ErrorMessage = "指定的JAVA位置不存在" };
}
CurrentCode = Random.Next();
var args = new MinecraftLaunchArguments();
var result = GenerateArguments(options, ref args);
if (result != null)
{
return result;
}
if (argumentsOperators == null) return LaunchGame(args);
foreach (var opt in argumentsOperators)
{
try
{
if (opt != null)
{
opt(args);
}
}
catch (Exception exp)
{
return new LaunchResult { Success = false, ErrorType = ErrorType.OperatorException, ErrorMessage = "指定的操作器引发了异常", Exception = exp };
}
}
return LaunchGame(args);
}
}
private LaunchResult LaunchGame(MinecraftLaunchArguments args)
{
Console.WriteLine(args.ToArguments());
try
{
var handle = new LaunchHandle(args.Authentication)
{
Code = CurrentCode,
Core = this,
Arguments = args,
Process = Process.Start(new ProcessStartInfo(JavaPath)
{
Arguments = args.ToArguments(),
UseShellExecute = false,
WorkingDirectory = GameRootPath,
RedirectStandardError = true,
RedirectStandardOutput = true
})
};
handle.Work();
Start(handle, handle.GetTile());
Task.Factory.StartNew(handle.Process.WaitForExit).ContinueWith(t => Exit(handle, handle.Process.ExitCode));
return new LaunchResult { Success = true, Handle = handle };
}
catch (Exception exp)
{
return new LaunchResult { Success = false, ErrorType = ErrorType.Unknown, ErrorMessage = "启动时出现了异常", Exception = exp };
}
}
#region 复制文件夹
public void CopyVersionDirectory(string directoryName, string versionId)
{
CopyDirectory(string.Format(@"{0}\versions\{2}\{1}", GameRootPath, directoryName, versionId),
string.Format(@"{0}\{1}", GameRootPath, directoryName));
}
public void CopyDirectory(string source, string target)
{
var code = CurrentCode;
if (!Directory.Exists(source)) return;
if (Directory.Exists(target))
{
Directory.Delete(target, true);
}
UsefulTools.Dircopy(source, target);
Action<LaunchHandle, int> handler = null;
handler = (handle, c) =>
{
if (handle.Code == code)
{
Directory.Delete(source, true);
UsefulTools.Dircopy(target, source);
Directory.Delete(target, true);
}
GameExit -= handler;
};
GameExit += handler;
}
public void CopyVersionDirectories(string ver)
{
var root = string.Format(@"{0}\versions\{1}\moddir", GameRootPath, ver);
if (!Directory.Exists(root))
{
return;
}
foreach (var dir in new DirectoryInfo(root).EnumerateDirectories())
{
CopyDirectory(dir.FullName, string.Format(@"{0}\{1}", GameRootPath, dir.Name));
}
}
#endregion
#region 事件
internal void Log(LaunchHandle handle, string line)
{
if (GameLog != null)
{
GameLog(handle, line);
}
}
internal void Exit(LaunchHandle handle, int code)
{
if (GameExit != null)
{
GameExit(handle, code);
}
}
internal void Start(LaunchHandle handle, string title)
{
if (GameStart != null)
{
GameStart(handle, title);
}
}
#endregion
}
}