Skip to content

Commit

Permalink
feat: 更新汉化文本, 新增对加密压缩包的支持
Browse files Browse the repository at this point in the history
  • Loading branch information
Moonholder committed Oct 16, 2024
1 parent e003308 commit b3ea563
Show file tree
Hide file tree
Showing 78 changed files with 722 additions and 497 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -665,5 +665,6 @@ Testing/
Testing_honkai/
Testing_wuwa/
Testing_ZZZ/

output/
*.7z
# End of https://www.toptal.com/developers/gitignore/api/visualstudio,csharp,rider
2 changes: 1 addition & 1 deletion Build/Release.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def checkSuccessfulExitCode(exitCode: int) -> None:
exit(exitCode)

def extractVersionNumber() -> str:
with open(JASM_CSPROJ, "r") as jasmCSPROJ:
with open(JASM_CSPROJ, "r", encoding="utf-8") as jasmCSPROJ:
for line in jasmCSPROJ:
line = line.strip()
if line.startswith("<VersionPrefix>"):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GIMI_ModManager.Core.Contracts.Entities;
using GIMI_ModManager.Core.Helpers;
using System.Text.RegularExpressions;

namespace GIMI_ModManager.Core.Entities.Mods.Helpers;

Expand Down Expand Up @@ -31,8 +32,9 @@ public static class SkinModHelpers
if (string.IsNullOrWhiteSpace(modName))
modName = mod.Name;

var relativePath = relativeUri.OriginalString.Replace($"{modName}/", "");

// var relativePath = relativeUri.OriginalString.Replace($"{modName}/", "");
var regex = new Regex(Regex.Escape($"{modName}/"));
var relativePath = regex.Replace(relativeUri.OriginalString, "", 1);
return relativePath;
}

Expand Down
30 changes: 26 additions & 4 deletions src/GIMI-ModManager.Core/Entities/Mods/SkinMod/SkinMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,30 @@ public bool ContainsOnlyJasmFiles()

private static string? HasMergedInIFile(DirectoryInfo modDirectory)
{
var mergedIniPath = modDirectory.EnumerateFiles("*.ini", SearchOption.TopDirectoryOnly)
.FirstOrDefault(iniFiles =>
// var mergedIniPath = modDirectory.EnumerateFiles("*.ini", SearchOption.TopDirectoryOnly)
// .FirstOrDefault(iniFiles =>
// Constants.ScriptIniNames.Any(iniNames =>
// iniNames.Equals(iniFiles.Name, StringComparison.OrdinalIgnoreCase)))
// ?.FullName;

// 获取目录及其子目录中的所有 INI 文件
var iniFiles = modDirectory.EnumerateFiles("*.ini", SearchOption.AllDirectories).ToList();

// 如果只有一个 INI 文件,直接返回该文件的路径
if (iniFiles.Count == 1)
{
return iniFiles.First().FullName;
}

// 否则,继续执行原有的逻辑
var mergedIniPath = iniFiles
.Where(iniFile =>
Constants.ScriptIniNames.Any(iniNames =>
iniNames.Equals(iniFiles.Name, StringComparison.OrdinalIgnoreCase)))
?.FullName;
iniNames.Equals(iniFile.Name, StringComparison.OrdinalIgnoreCase)) ||
Constants.ScriptIniPrefixes.Any(prefix =>
iniFile.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
.FirstOrDefault()?.FullName;


return mergedIniPath;
}
Expand Down Expand Up @@ -141,6 +160,9 @@ public override ISkinMod CopyTo(string absPath)
modIniPath = iniPath;
}

// 将路径中的转义字符还原
modIniPath = Uri.UnescapeDataString(modIniPath);

if (!File.Exists(modIniPath))
{
settings.MergedIniPath = null;
Expand Down
9 changes: 6 additions & 3 deletions src/GIMI-ModManager.Core/GamesService/GameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,14 @@ public async Task InitializeAsync(InitializationOptions options)
}


public static async Task<GameInfo?> GetGameInfoAsync(SupportedGames game)
public async Task<GameInfo?> GetGameInfoAsync(SupportedGames game)
{
var gameAssetDir = Path.Combine(AppContext.BaseDirectory, "Assets", "Games", game.ToString());
var currentLanguage = _localizer.CurrentLanguage;
string gameAssetDir = Path.Combine(AppContext.BaseDirectory, "Assets", "Games", game.ToString()), assetDir = gameAssetDir;
if (currentLanguage.LanguageCode == "zh-cn")
assetDir = Path.Combine(AppContext.BaseDirectory, "Assets", "Games", game.ToString(), "Languages", "zh-cn");

var gameFilePath = Path.Combine(gameAssetDir, "game.json");
var gameFilePath = Path.Combine(assetDir, "game.json");

if (!File.Exists(gameFilePath))
return null;
Expand Down
2 changes: 2 additions & 0 deletions src/GIMI-ModManager.Core/GamesService/IGameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public List<T> GetAllModdableObjectsAsCategory<T>(GetOnly getOnlyStatus = GetOnl
public string OtherCharacterInternalName { get; }
public string GlidersCharacterInternalName { get; }
public string WeaponsCharacterInternalName { get; }

public Task<GameInfo?> GetGameInfoAsync(SupportedGames game);
}

public class InitializationOptions
Expand Down
2 changes: 1 addition & 1 deletion src/GIMI-ModManager.Core/GamesService/Models/Category.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ internal static ICategory CreateForCharacter()
{
var internalName = new InternalName("Character");

return new Category(internalName, ModCategory.Character, "Character", "Characters", typeof(ICharacter));
return new Category(internalName, ModCategory.Character, "角色", "角色", typeof(ICharacter));
}

internal static ICategory CreateForNpc()
Expand Down
2 changes: 1 addition & 1 deletion src/GIMI-ModManager.Core/GamesService/Models/Character.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private static ICharacterSkin CreateDefaultSkin(Character character) =>
{
InternalName = new InternalName("Default_" + character.InternalName),
ModFilesName = character.ModFilesName,
DisplayName = "Default",
DisplayName = "默认",
Rarity = character.Rarity,
ReleaseDate = character.ReleaseDate,
Character = character,
Expand Down
1 change: 1 addition & 0 deletions src/GIMI-ModManager.Core/Helpers/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public static class Constants
public static readonly string ModConfigFileName = ".JASM_ModConfig.json";
public static readonly string ShaderFixesFolderName = "ShaderFixes";
public static readonly string[] ScriptIniNames = ["Script.ini", "merged.ini"];
public static readonly string[] ScriptIniPrefixes = ["Master"];
public static readonly string UserIniFileName = "d3dx_user.ini";
}
11 changes: 9 additions & 2 deletions src/GIMI-ModManager.Core/Helpers/IniConfigHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GIMI_ModManager.Core.Entities.Mods.FileModels;
using System.Text.RegularExpressions;

namespace GIMI_ModManager.Core.Helpers;

Expand All @@ -23,8 +24,14 @@ public static class IniConfigHelpers
else if (IsIniKey(line, IniKeySwapSection.TypeIniKey))
skinModKeySwap.Type = GetIniValue(line);

else if (IsIniKey(line, IniKeySwapSection.SwapVarIniKey))
skinModKeySwap.SwapVar = GetIniValue(line)?.Split(',');
else if (Regex.IsMatch(line, @"^\s*\$\w+\s*=\s*\d+(,\d+)+"))
{
var value = GetIniValue(line);
if (!string.IsNullOrEmpty(value))
{
skinModKeySwap.SwapVar = value.Split(',');
}
}

else if (IsSection(line))
break;
Expand Down
82 changes: 62 additions & 20 deletions src/GIMI-ModManager.Core/Services/DragAndDropScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,24 @@ public DragAndDropScanner()
_extractTool = GetExtractTool();
}

public DragAndDropScanResult ScanAndGetContents(string path)
public DragAndDropScanResult ScanAndGetContents(string path, string? password = null)
{
PrepareWorkFolder();

_workFolder = Path.Combine(_workFolder, Path.GetFileName(path));

int exitCode = 0;

if (IsArchive(path))
{
var copiedArchive = new FileInfo(path);
copiedArchive = copiedArchive.CopyTo(Path.Combine(_tmpFolder, Path.GetFileName(path)), true);

var result = Extractor(copiedArchive.FullName);

result?.Invoke(copiedArchive.FullName);
if (password is not null) {
exitCode = Extract7Z(copiedArchive.FullName, password);
} else {
var result = Extractor(copiedArchive.FullName);
exitCode = result?.Invoke(copiedArchive.FullName)?? 0;
}
}
else if (Directory.Exists(path)) // ModDragAndDropService handles loose folders, but this added just in case
{
Expand All @@ -56,7 +60,8 @@ public DragAndDropScanResult ScanAndGetContents(string path)

return new DragAndDropScanResult()
{
ExtractedFolder = new Mod(new DirectoryInfo(_workFolder).Parent!)
ExtractedFolder = new Mod(new DirectoryInfo(_workFolder).Parent!),
exitedCode = exitCode
};
}

Expand All @@ -77,20 +82,22 @@ private bool IsArchive(string path)
};
}

private Action<string>? Extractor(string path)
private Func<string, int>? Extractor(string path, string? password = null)
{
Action<string>? action = null;
Func<string, int>? action = null;

if (_extractTool == ExtractTool.Bundled7Zip)
action = Extract7Z;
else if (_extractTool == ExtractTool.SharpCompress)
action = Path.GetExtension(path) switch
{
".zip" => SharpExtractZip,
".rar" => SharpExtractRar,
".7z" => SharpExtract7z,
_ => null
action = (path) => {
return Extract7Z(path);
};
// else if (_extractTool == ExtractTool.SharpCompress)
// action = Path.GetExtension(path) switch
// {
// ".zip" => SharpExtractZip,
// ".rar" => SharpExtractRar,
// ".7z" => SharpExtract7z,
// _ => null
// };
else if (_extractTool == ExtractTool.System7Zip) throw new NotImplementedException();

return action;
Expand Down Expand Up @@ -154,29 +161,64 @@ private ExtractTool GetExtractTool()
return ExtractTool.SharpCompress;
}


private void Extract7Z(string path)
private int Extract7Z(string path, string? password = null)
{
var sevenZipPath = Path.Combine(AppContext.BaseDirectory, @"Assets\7z\7z.exe");
var args = $"x \"{path}\" -o\"{_workFolder}\" -y";
args += password is not null ? $" -p\"{password}\"" : " -p-";
// 先尝试无密码解压
var process = new Process
{
StartInfo =
{
FileName = sevenZipPath,
Arguments = $"x \"{path}\" -o\"{_workFolder}\" -y",
Arguments = args,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = true
}
};

_logger.Information("Extracting 7z archive with command: {Command}", process.StartInfo.Arguments);
process.Start();

// 读取标准输出
var output = new System.Text.StringBuilder();
bool passwordRequired = false;
bool passwordProvided = password != null;

process.OutputDataReceived += (sender, e) =>
{
if (e.Data != null)
{
output.AppendLine(e.Data);
if (e.Data.Contains("Can't open as archive"))
{
passwordRequired = true;
if (!passwordProvided)
{
// 密码为空,直接返回 exitcode = 1
_logger.Warning("Password is required but not provided");
process.Kill();
}
}
}
};
process.BeginOutputReadLine();
process.WaitForExit();
_logger.Information("7z extraction finished with exit code {ExitCode}", process.ExitCode);

// 如果密码为空且密码被要求,返回1
int exitCode = (passwordRequired && !passwordProvided) ? 1 : process.ExitCode;
_logger.Information("7z extraction finished with exit code {ExitCode}", exitCode);
return exitCode;
}

}

public class DragAndDropScanResult
{
public IMod ExtractedFolder { get; init; } = null!;
public string[] IgnoredMods { get; init; } = Array.Empty<string>();
public int exitedCode { get; init; } = 0;
}
18 changes: 9 additions & 9 deletions src/GIMI-ModManager.Core/Services/SkinManagerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ public void ExportMods(ICollection<ICharacterModList> characterModLists, string
exportFolder.Create();

if (exportFolder.EnumerateFileSystemInfos().Any())
throw new InvalidOperationException("Export folder is not empty");
throw new InvalidOperationException("导出文件夹不是空的");


var modsToExport = new List<CharacterSkinEntry>();
Expand Down Expand Up @@ -443,15 +443,15 @@ public void ExportMods(ICollection<ICharacterModList> characterModLists, string
}

ModExportProgress?.Invoke(this,
new ExportProgress(modsProgress += modsProgressIncrement, null, "Removing JASM settings..."));
new ExportProgress(modsProgress += modsProgressIncrement, null, "删除JASM设置..."));
RemoveJASMSettings(removeLocalJasmSettings, exportedMods);

ModExportProgress?.Invoke(this,
new ExportProgress(modsProgress += modsProgressIncrement, null, "Setting Mod Status..."));
new ExportProgress(modsProgress += modsProgressIncrement, null, "设置Mod状态..."));
SetModsStatus(setModStatus, exportedMods);

ModExportProgress?.Invoke(this,
new ExportProgress(100, null, "Finished"));
new ExportProgress(100, null, "导出完成"));
return;
}

Expand All @@ -477,7 +477,7 @@ public void ExportMods(ICollection<ICharacterModList> characterModLists, string

if (characterToFolder.Count != _gameService.GetAllModdableObjects().Count - emptyFoldersCount)
throw new InvalidOperationException(
"Failed to create character folders in export folder, character mismatch");
"在导出文件夹中创建角色文件夹失败,角色不匹配");

var exportedMods = new List<IMod>();
foreach (var characterSkinEntry in modsToExport)
Expand Down Expand Up @@ -511,15 +511,15 @@ public void ExportMods(ICollection<ICharacterModList> characterModLists, string
}

ModExportProgress?.Invoke(this,
new ExportProgress(modsProgress += modsProgressIncrement, null, "Removing JASM settings..."));
new ExportProgress(modsProgress += modsProgressIncrement, null, "删除JASM设置......"));
RemoveJASMSettings(removeLocalJasmSettings, exportedMods);

ModExportProgress?.Invoke(this,
new ExportProgress(modsProgress += modsProgressIncrement, null, "Setting Mod Status..."));
new ExportProgress(modsProgress += modsProgressIncrement, null, "设置Mod状态......"));
SetModsStatus(setModStatus, exportedMods);

ModExportProgress?.Invoke(this,
new ExportProgress(100, null, "Finished"));
new ExportProgress(100, null, "导出完成"));


return;
Expand Down Expand Up @@ -623,7 +623,7 @@ public async Task InitializeAsync(string activeModsFolderPath, string? unloadedM
_threeMigotoFolder = new DirectoryInfo(threeMigotoRootfolder);
_threeMigotoFolder.Refresh();
if (!_threeMigotoFolder.Exists)
throw new InvalidOperationException("3DMigoto folder does not exist");
throw new InvalidOperationException("加载器文件夹不存在");

//_userIniWatcher = new FileSystemWatcher(_threeMigotoFolder.FullName, D3DX_USER_INI);
//_userIniWatcher.Changed += OnUserIniChanged;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"GameName": "原神",
"GameShortName": "Genshin",
"RarityName": "Quality",
"GameIcon": "Start_Game.png",
"GameBananaUrl": "https://gamebanana.com/games/8552",
"GameModelImporterUrl": "https://github.com/SilentNightSound/GI-Model-Importer",
"GameModelImporterName": "Genshin-Impact-Model-Importer",
"GameModelImporterShortName": "GIMI",
"GameModelImporterExeName": ["3DMigoto Loader.exe"]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"GameName": "Honkai: Star Rail",
"GameName": "崩坏: 星穹铁道",
"GameShortName": "Honkai",
"RarityName": "Rarity",
"GameIcon": "Start_Game.webp",
Expand Down
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
"InternalName": "Weapons",
"DisplayName": "武器"
},
{
"InternalName": "Gliders",
"DisplayName": "滑翔翼"
},
{
"Keys": [
"rover"
Expand Down
Loading

0 comments on commit b3ea563

Please sign in to comment.