Files
Mitria_Minecraft_Project/Mitria_Minecraft_Launcher/Updater/GameUpdateManager.cs
crudelis ff52d49800 - Update 시작점
업데이트 해야 될점 TODO 작성 및 MK2 버전 제작 시작
2025-04-07 16:28:50 +09:00

419 lines
21 KiB
C#

using CommonLibrary;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Mitria_Minecraft_Launcher.Updater
{
public class GameUpdateManager
{
public delegate void GameUpdateManagerMessageHandler(object sender, GameUpdateManagerMessageEventArgs downloaderProgressChangedEventArgs);
public event GameUpdateManagerMessageHandler GameUpdateManagerMessage;
public GameUpdateManager()
{
}
public GameUpdateStatus Start()
{
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.Message, 0, 0, "[0/9] GameUpdatStart"));
CommonLibrary.Log.INFO("Game Update Start");
// Downloader 선언
var downloader = new Downloader();
downloader.DownloaderProgressChangedEvent += Downloader_DownloaderProgressChangedEvent;
// Version File Download
CommonLibrary.Log.INFO("download version file.");
var verionData = downloader.DownloadString(CommonLibrary.Extensions.PathCombineL(Settings.ServerBaseUrl,"Servers", Settings.NowProfile.ServerName, Settings.ServerDataPatchInformationFile));
// Versoin File 받기에 실패하였을때 업데이트 전체 실패처리
if (verionData == string.Empty)
{
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.Message, 0, 0, "★★ Update Fail ★★"));
CommonLibrary.Log.FATAL("Failed to download version file");
return GameUpdateStatus.Fail;
}
// Version File Xml 형태로 변환
var dataPatchInformation = CommonLibrary.XmlSystem.LoadFromData<DataPatchInformation>(verionData);
// 임시 폴더 생성
var tempDirectory = System.IO.Path.GetFullPath("temp");
if (!System.IO.Directory.Exists(tempDirectory))
{
System.IO.Directory.CreateDirectory(tempDirectory);
Log.INFO("[GameUpdateManager] +[F] " + tempDirectory);
}
// 런타임 업데이트
#region Runtime Update
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 1, 9, "[1/9] Runtime Version Check"));
Log.INFO("[Runtime] Version Check");
// 버전 비교
var thisVersion = Version.Parse(Settings.NowProfile.RuntimeVersion);
var remoteVersion = Version.Parse(dataPatchInformation.RuntimeVersion);
CommonLibrary.Log.INFO("[Runtime] LocalVersion : " + thisVersion);
CommonLibrary.Log.INFO("[Runtime] RemoteVersion : " + remoteVersion);
var result = remoteVersion.CompareTo(thisVersion);
// 1 : 리모트가 큼, 0 : 같음, -1 리모트가 적음
if (result == 0)
{
CommonLibrary.Log.INFO("[Runtime] Version Same");
}
else
{
CommonLibrary.Log
.INFO(string.Format("{0}", result == 1 ? "remote is the upper version" : "remote is the lower version"));
CommonLibrary.Log.INFO("Runtime delete it for update.");
// 런타임 폴더 경로 가져오기
var rootDirectoryInfo = new System.IO.DirectoryInfo(System.IO.Path.GetFullPath(CommonLibrary.Extensions.PathCombineW(Settings.RuntimeLocation,Settings.NowProfile.ServerName)));
// 런타임 폴더 삭제후 새로만들기
if (!rootDirectoryInfo.Exists)
{
rootDirectoryInfo.Create();
Log.INFO("[Runtime] +[D] " + rootDirectoryInfo.FullName);
}
else
{
rootDirectoryInfo.Delete(true);
Log.INFO("[Runtime] -[D] " + rootDirectoryInfo.FullName);
rootDirectoryInfo.Create();
Log.INFO("[Runtime] +[D] " + rootDirectoryInfo.FullName);
}
// 런타임 다운로드 시작
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 2, 9, "[2/9] Runtime Download"));
Log.INFO("[Runtime] Data Download Start");
var downloadUrl = CommonLibrary.Extensions.PathCombineL(Settings.ServerBaseUrl, "Servers", Settings.NowProfile.ServerName, dataPatchInformation.RuntimeUrl, dataPatchInformation.RuntimeFileName);
var targetPath = System.IO.Path.Combine(tempDirectory, dataPatchInformation.RuntimeFileName); // 임시폴더에 다운로드
downloader.DownloadFile(downloadUrl, targetPath);
Log.INFO("[Runtime] Data Download End");
// 런타임 다운로드 완료
// 런타임 언패킹 작업
var progressPacker = new ProgressPacker();
var unpackPath = rootDirectoryInfo.FullName;
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 3, 9, "[3/9] Runtime Unpack"));
Log.INFO("[Runtime] Unpack Start");
progressPacker.UnPack(targetPath, unpackPath, new BasicProgress<double>(p => Change(p)));
Settings.NowProfile.RuntimeVersion = remoteVersion.ToString();
//임시폴더 삭제
System.IO.File.Delete(targetPath);
Log.INFO("[Runtime] -[F] " + targetPath);
Log.INFO("[Runtime] Unpack End");
}
#endregion Runtime Update
#region Package Update
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 4, 9, "[4/9] Package Version Check"));
Log.INFO("[Package] Version Check");
thisVersion = Version.Parse(Settings.UserClientVersion.PackageVersion);
remoteVersion = Version.Parse(dataPatchInformation.PackageVersion);
CommonLibrary.Log.INFO("[Package] LocalVersion : " + thisVersion);
CommonLibrary.Log.INFO("[Package] RemoteVersion : " + remoteVersion);
result = remoteVersion.CompareTo(thisVersion);
//TODO: 만약 Major 버전이 바뀌면 전부삭제, 아니면 있는 폴더면 선별후 삭제
// 1 : 리모트가 큼, 0 : 같음, -1 리모트가 적음
if (result == 0)
{
CommonLibrary.Log.INFO("[Package] Version Same");
}
else
{
CommonLibrary.Log
.INFO(string.Format("{0}", result == 1 ? "remote is the upper version" : "remote is the lower version"));
CommonLibrary.Log.INFO("[Package] delete it for update.");
var rootDirectoryInfo = new System.IO.DirectoryInfo(System.IO.Path.GetFullPath(CommonLibrary.Extensions.PathCombineW(Settings.UserLauncherConfig.GameDirectory,Settings.NowProfile.ServerName)));
if (!rootDirectoryInfo.Exists)
{
rootDirectoryInfo.Create();
Log.INFO("[Package] +[D] " + rootDirectoryInfo.FullName);
}
else
{
// 비우기 전에 스크린샷폴더 보존 /screenshots
string oldScreenshotsDirectory = CommonLibrary.Extensions.PathCombineW(Settings.UserLauncherConfig.GameDirectory, Settings.NowProfile.ServerName, "screenshots");
string newScreenshotsDirectory = System.IO.Path.GetFullPath("screenshots_" + DateTime.Now.ToString("yyyyMMddHHmmss"));
if (System.IO.Directory.Exists(oldScreenshotsDirectory) && System.IO.Directory.GetFiles(oldScreenshotsDirectory, "*", System.IO.SearchOption.AllDirectories).Length > 0)
{
Log.INFO("[Package] Screenshots Directory Backup : " + newScreenshotsDirectory);
DirectoryInfo oldScreenshotsDirectoryInfo = new DirectoryInfo(oldScreenshotsDirectory);
DirectoryInfo newScreenshotsDirectoryInfo = new DirectoryInfo(newScreenshotsDirectory);
oldScreenshotsDirectoryInfo.DeepMove(newScreenshotsDirectoryInfo);
}
Extensions.EmptyDirectory(rootDirectoryInfo.FullName);
Log.INFO("[Package] Empty GameDirectory");
}
var downloadUrl = CommonLibrary.Extensions.PathCombineL(Settings.ServerBaseUrl, "Servers", Settings.NowProfile.ServerName, dataPatchInformation.PackageUrl, dataPatchInformation.PackageFileName);
var targetPath = System.IO.Path.Combine(tempDirectory, dataPatchInformation.PackageFileName);
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 5, 9, "[5/9] Package Download"));
Log.INFO("[Package] Download Start");
downloader.DownloadFile(downloadUrl, targetPath);
Log.INFO("[Package] Download End");
if (Settings.UserClientVersion.PackageDirectorys != null)
{
foreach (var item in Settings.UserClientVersion.PackageDirectorys)
{
var directoryInfo = new System.IO.DirectoryInfo(System.IO.Path.GetFullPath(item));
if (directoryInfo.Exists)
{
directoryInfo.Delete(true);
Log.INFO("[Package] -[D] " + directoryInfo.FullName);
}
}
}
if (dataPatchInformation.PackageDirectorys != null)
{
foreach (var item in dataPatchInformation.PackageDirectorys)
{
var directoryInfo = new System.IO.DirectoryInfo(System.IO.Path.GetFullPath(item));
if (directoryInfo.Exists)
{
directoryInfo.Delete(true);
Log.INFO("[Package] -[D] " + directoryInfo.FullName);
}
}
}
// 패키지 언팩
var progressPacker = new ProgressPacker();
var unpackPath = System.IO.Path.GetFullPath(rootDirectoryInfo.FullName);
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 6, 9, "[6/9] Package Unpack"));
Log.INFO("[Package] Unpack Start");
progressPacker.UnPack(targetPath, unpackPath, new BasicProgress<double>(p => Change(p)));
Settings.UserClientVersion.PackageVersion = remoteVersion.ToString();
//임시파일 삭제
System.IO.File.Delete(targetPath);
Log.INFO("[Package] -[F] " + targetPath);
Log.INFO("[Package] Unpack End");
Settings.UserClientVersion.ComponentVersion = "0.0.0.0";
}
#endregion Package Update
#region Coomponent Update
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 7, 9, "[7/9] Component Version Check"));
Log.INFO("[Component] Version Check");
thisVersion = Version.Parse(Settings.UserClientVersion.ComponentVersion);
remoteVersion = Version.Parse(dataPatchInformation.ComponentVersion);
CommonLibrary.Log.INFO("[Component] LocalVersion : " + thisVersion);
CommonLibrary.Log.INFO("[Component] RemoteVersion : " + remoteVersion);
result = remoteVersion.CompareTo(thisVersion);
if (result == 0)
{
CommonLibrary.Log.INFO("[Component] Version Same");
}
else
{
// 제거된 폴더 삭제
var resultDirectorys = new List<string>();
foreach (var directory in Settings.UserClientVersion.ComponentDirectorys)
{
if (!dataPatchInformation.ComponentDirectorys.Contains(directory))
{
resultDirectorys.Add(directory);
}
}
foreach (var directory in resultDirectorys)
{
var directoryPath = System.IO.Path.GetFullPath(CommonLibrary.Extensions.PathCombineW(Settings.UserLauncherConfig.GameDirectory,Settings.NowProfile.ServerName, directory));
if (System.IO.Directory.Exists(directoryPath))
{
System.IO.Directory.Delete(directoryPath, true);
Log.INFO("[Component] -[D] " + directoryPath);
}
}
var reverseDirectorys = dataPatchInformation.ComponentDirectorys;
reverseDirectorys.Reverse();
string gameDirectory = CommonLibrary.Extensions.PathCombineW(Settings.UserLauncherConfig.GameDirectory, Settings.NowProfile.ServerName) + "\\";
foreach (var directory in reverseDirectorys)
{
var directoryPath = System.IO.Path.GetFullPath(CommonLibrary.Extensions.PathCombineW(Settings.UserLauncherConfig.GameDirectory, Settings.NowProfile.ServerName, directory));
if (System.IO.Directory.Exists(directoryPath))
{
var lowDirectorys = System.IO.Directory.GetDirectories(directoryPath);
foreach (var lowDirectory in lowDirectorys)
{
var directoryName = lowDirectory.Replace(gameDirectory, string.Empty);
directoryName = directoryName.Replace("\\", "/");
if (!dataPatchInformation.ComponentDirectorys.Contains(directoryName))
{
System.IO.Directory.Delete(lowDirectory, true);
Log.INFO("[Component] -[D] " + directoryPath);
}
}
}
}
foreach (var directory in dataPatchInformation.ComponentDirectorys)
{
var directoryPath = System.IO.Path.GetFullPath(CommonLibrary.Extensions.PathCombineW(Settings.UserLauncherConfig.GameDirectory, Settings.NowProfile.ServerName, directory));
if (!System.IO.Directory.Exists(directoryPath))
{
System.IO.Directory.CreateDirectory(directoryPath);
Log.INFO("[Component] +[D] " + directoryPath);
}
}
var auditFile = new AuditFile();
var localFiles = auditFile.GetLocalFileList(dataPatchInformation.ComponentDirectorys);
var removeFiles = auditFile.GetRemoveFiles(localFiles, dataPatchInformation.ComponentList);
var needFiles = auditFile.GetNeedFiles(localFiles, dataPatchInformation.ComponentList);
//var customFiles =
foreach (var fileDetail in removeFiles)
{
var filePath = CommonLibrary.Extensions.PathCombineW(Settings.UserLauncherConfig.GameDirectory,Settings.NowProfile.ServerName, fileDetail.Directory, fileDetail.FileName);
FileInfo fileInfo= new FileInfo(filePath);
fileInfo.IsReadOnly = false;
if (fileInfo.Exists)
{
Log.INFO("[Component] -[F] " + filePath);
fileInfo.Delete();
}
}
// 디렉토리 삭제
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 8, 9, "[8/9] Component Download"));
Log.INFO("[Component] Download Start");
for (int i = 0; i < needFiles.Count; i++)
{
var url = CommonLibrary.Extensions.PathCombineL(Settings.ServerBaseUrl, "Servers", Settings.NowProfile.ServerName, dataPatchInformation.ComponentUrl, needFiles[i].Directory, needFiles[i].FileName);
var path = CommonLibrary.Extensions.PathCombineW(Settings.UserLauncherConfig.GameDirectory,Settings.NowProfile.ServerName, needFiles[i].Directory, needFiles[i].FileName);
downloader.DownloadFile(url, path);
Log.INFO("[Component] +[F] " + path);
}
Log.INFO("[Component] Download End");
Settings.UserClientVersion.ComponentVersion = remoteVersion.ToString();
Settings.UserClientVersion.ComponentDirectorys = dataPatchInformation.ComponentDirectorys;
#endregion Coomponent Update
}
// 커스텀 폴더, Config
#region CustomData
// 삭제된 파일 찾기
string rootCustomPath = System.IO.Path.GetFullPath(CommonLibrary.Extensions.PathCombineW(Settings.CustomDataDirectory, Settings.NowProfile.ServerName));
if(!System.IO.Directory.Exists(CommonLibrary.Extensions.PathCombineW(rootCustomPath, "config")))
{
System.IO.Directory.CreateDirectory(CommonLibrary.Extensions.PathCombineW(rootCustomPath, "config"));
}
if (!System.IO.Directory.Exists(CommonLibrary.Extensions.PathCombineW(rootCustomPath, "mods")))
{
System.IO.Directory.CreateDirectory(CommonLibrary.Extensions.PathCombineW(rootCustomPath, "mods"));
}
List<string> files = new List<string>();
files.AddRange(System.IO.Directory.GetFiles(CommonLibrary.Extensions.PathCombineW(rootCustomPath, "config")));
files.AddRange(System.IO.Directory.GetFiles(CommonLibrary.Extensions.PathCombineW(rootCustomPath, "mods")));
for (int i = 0; i < files.Count; i++)
{
files[i] = files[i].Replace(rootCustomPath + '\\', string.Empty);
}
foreach (var file in files)
{
string sourcePath = CommonLibrary.Extensions.PathCombineW(rootCustomPath, file);
string targetPath = CommonLibrary.Extensions.PathCombineW( Settings.UserLauncherConfig.GameDirectory, Settings.NowProfile.ServerName,file);
if (System.IO.File.Exists(targetPath))
{
System.IO.FileInfo sourceFile = new System.IO.FileInfo(sourcePath);
System.IO.FileInfo targetFile = new System.IO.FileInfo(targetPath);
if (sourceFile.GetFileHashCode() != targetFile.GetFileHashCode())
{
System.IO.File.Copy(sourcePath, targetPath,true);
Log.INFO("[CustomData] +[F] " + targetPath);
}
}
else
{
System.IO.File.Copy(sourcePath, targetPath);
Log.INFO("[CustomData] +[F] " + targetPath);
}
//Settings.UserLauncherConfig.CustomData = files;
Settings.SaveUserLauncherConfig();
}
#endregion CustomData
GameUpdateManagerMessage(this, new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.First, 9, 9, "[9/9] Update Complete"));
Log.INFO("GameUpdate All Success");
return GameUpdateStatus.Success;
}
private void Change(double value)
{
var e = new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.Second, (long)(value * 100), 100, string.Empty);
GameUpdateManagerMessage?.Invoke(this, e);
}
private void Downloader_DownloaderProgressChangedEvent(object sender, DownloaderProgressChangedEventArgs downloaderProgressChangedEventArgs)
{
var e = new GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType.Second, downloaderProgressChangedEventArgs.ProcessedByte, downloaderProgressChangedEventArgs.FileSize, string.Empty);
GameUpdateManagerMessage?.Invoke(this, e);
}
}
public enum GameUpdateStatus
{
Success,
Fail
}
public enum GameUpdateManagerMessageType
{
First,
Second,
Message
}
public class GameUpdateManagerMessageEventArgs : EventArgs
{
public GameUpdateManagerMessageType MessageType { get; set; }
public long MinValue { get; set; }
public long MaxValue { get; set; }
public string Message { get; set; }
public GameUpdateManagerMessageEventArgs(GameUpdateManagerMessageType messageType, long minValue, long maxValue, string message)
{
MessageType = messageType;
MinValue = minValue;
MaxValue = maxValue;
Message = message;
}
}
}