Skip to content

Commit 75aa79e

Browse files
committed
v1.0.0
1 parent 9401706 commit 75aa79e

11 files changed

Lines changed: 955 additions & 0 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
/bin/
33
/obj/
44
/*.DotSettings.user
5+
/*.otf

Config.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.Text.Json;
2+
using Il2CppSystem.IO;
3+
using Il2CppSystem.Text;
4+
5+
namespace IMYSHook;
6+
7+
public class IMYSConfig
8+
{
9+
public static double Speed;
10+
public static int FPS;
11+
public static bool TranslationEnabled;
12+
13+
public static void Read()
14+
{
15+
if (File.Exists("./BepInEx/plugins/config.json"))
16+
{
17+
var content = File.InternalReadAllText("./BepInEx/plugins/config.json", Encoding.UTF8);
18+
var doc = JsonDocument.Parse(content);
19+
var config = doc.RootElement;
20+
21+
var needWrite = false;
22+
23+
if (config.TryGetProperty("speed", out var sValue))
24+
{
25+
Speed = sValue.GetDouble();
26+
}
27+
else
28+
{
29+
Speed = 0.5;
30+
needWrite = true;
31+
}
32+
33+
if (config.TryGetProperty("fps", out var fValue))
34+
{
35+
FPS = fValue.GetInt32();
36+
}
37+
else
38+
{
39+
FPS = 60;
40+
needWrite = true;
41+
}
42+
43+
if (config.TryGetProperty("translation", out var tValue))
44+
{
45+
TranslationEnabled = tValue.GetBoolean();
46+
}
47+
else
48+
{
49+
TranslationEnabled = true;
50+
needWrite = true;
51+
}
52+
53+
if (needWrite) WriteJsonFile(Speed, FPS, TranslationEnabled);
54+
55+
Plugin.Global.Log.LogInfo("Current setting:");
56+
Plugin.Global.Log.LogInfo("Game speed(each step): " + Speed);
57+
Plugin.Global.Log.LogInfo("FPS: " + FPS);
58+
Plugin.Global.Log.LogInfo("Translation: " + (TranslationEnabled ? "Enabled" : "Disabled"));
59+
}
60+
else
61+
{
62+
Plugin.Global.Log.LogWarning("config.json not found!!!");
63+
Plugin.Global.Log.LogWarning("Using default config.");
64+
Speed = 0.5;
65+
FPS = 60;
66+
TranslationEnabled = true;
67+
68+
// Create default JSON file
69+
WriteJsonFile(0.5, 60, true);
70+
}
71+
}
72+
73+
public static void WriteJsonFile(double speed, int fps, bool enabled)
74+
{
75+
var config = new config
76+
{
77+
speed = speed,
78+
fps = fps,
79+
translation = enabled
80+
};
81+
82+
var json = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
83+
File.WriteAllText("./BepInEx/plugins/config.json", json);
84+
}
85+
86+
public class config
87+
{
88+
public double speed { get; set; }
89+
public int fps { get; set; }
90+
public bool translation { get; set; }
91+
}
92+
}

IMYSHook.csproj

Lines changed: 377 additions & 0 deletions
Large diffs are not rendered by default.

IMYSHook.sln

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.7.34031.279
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IMYSHook", "IMYSHook.csproj", "{ECCA29DF-52F0-47C8-B3EF-2E9072DC696B}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{ECCA29DF-52F0-47C8-B3EF-2E9072DC696B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{ECCA29DF-52F0-47C8-B3EF-2E9072DC696B}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{ECCA29DF-52F0-47C8-B3EF-2E9072DC696B}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{ECCA29DF-52F0-47C8-B3EF-2E9072DC696B}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {FFF19899-6EE7-4266-9123-87E30E6015B7}
24+
EndGlobalSection
25+
EndGlobal

Notification.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Diagnostics;
2+
3+
namespace IMYSHook;
4+
5+
public class Notification
6+
{
7+
public static void Popup(string title, string text)
8+
{
9+
var script = string.Format("$headlineText = '{0}';", title) +
10+
string.Format("$bodyText = '{0}';", text) +
11+
"$ToastText02 = [Windows.UI.Notifications.ToastTemplateType, Windows.UI.Notifications, ContentType = WindowsRuntime]::ToastText02;" +
12+
"$TemplateContent = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]::GetTemplateContent($ToastText02);" +
13+
"$TemplateContent.SelectSingleNode('//text[@id=\"1\"]').InnerText = $headlineText;" +
14+
"$TemplateContent.SelectSingleNode('//text[@id=\"2\"]').InnerText = $bodyText;" +
15+
"$AppId = 'Iris Mysteria';" +
16+
"[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($AppId).Show($TemplateContent);";
17+
18+
var start = new ProcessStartInfo("powershell.exe")
19+
{
20+
UseShellExecute = false,
21+
Arguments = script
22+
};
23+
Process.Start(start);
24+
}
25+
26+
public static void SsPopup(string location)
27+
{
28+
var scriptArgs = "-F ./BepInEx/plugins/SS_Notification.ps1 " + location + "";
29+
30+
var start = new ProcessStartInfo("powershell.exe")
31+
{
32+
UseShellExecute = false,
33+
Arguments = scriptArgs
34+
};
35+
Process.Start(start);
36+
}
37+
}

Patch.cs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
using System.Text.RegularExpressions;
2+
using BepInEx;
3+
using Hachiroku.Novel;
4+
using Hachiroku.Novel.UI;
5+
using HarmonyLib;
6+
using Il2CppSystem.IO;
7+
using TMPro;
8+
using UnityEngine;
9+
10+
namespace IMYSHook;
11+
12+
public class Patch
13+
{
14+
private static string currentAdvId;
15+
public static string fontName = "notosanscjktc";
16+
public static TMP_FontAsset TMPTranslateFont;
17+
18+
public static void Initialize()
19+
{
20+
Harmony.CreateAndPatchAll(typeof(Patch));
21+
}
22+
23+
[HarmonyPostfix]
24+
[HarmonyPatch(typeof(NovelRoot), "Start")]
25+
public static void NovelStart(ref NovelRoot __instance)
26+
{
27+
if (!IMYSConfig.TranslationEnabled) return;
28+
29+
if (TMPTranslateFont == null && File.Exists($"{Paths.PluginPath}/font/{fontName}"))
30+
{
31+
var ab = AssetBundle.LoadFromFile($"{Paths.PluginPath}/font/{fontName}");
32+
TMPTranslateFont = ab.LoadAsset<TMP_FontAsset>(fontName + " SDF");
33+
ab.Unload(false);
34+
}
35+
36+
currentAdvId = __instance.Linker.ScenarioId;
37+
38+
if (!Translation.chapterDicts.ContainsKey(currentAdvId)) Translation.FetchChapterTranslation(currentAdvId);
39+
Plugin.Global.Log.LogInfo(currentAdvId);
40+
}
41+
42+
// Message
43+
[HarmonyPrefix]
44+
[HarmonyPatch(typeof(BurikoParseScript), "_SetMssageCommand")]
45+
public static void Novel_SetMssageCommand(ref int lineNum, ref string line, ref bool isSelectedCaseArea,
46+
ref int caseCount)
47+
{
48+
if (!IMYSConfig.TranslationEnabled) return;
49+
50+
if (Translation.chapterDicts.ContainsKey(currentAdvId) && line.Contains("「"))
51+
{
52+
var idx = line.IndexOf('「');
53+
var name = line.Substring(0, idx);
54+
var text = line.Substring(idx);
55+
56+
var full = "";
57+
58+
string name_replace;
59+
if (Translation.nameDicts.TryGetValue(name, out name_replace))
60+
full = name_replace.IsNullOrWhiteSpace() ? text : name_replace;
61+
62+
string text_replace;
63+
if (Translation.chapterDicts[currentAdvId].TryGetValue(text, out text_replace))
64+
full += text_replace.IsNullOrWhiteSpace() ? text : text_replace;
65+
66+
line = full;
67+
}
68+
else
69+
{
70+
string text_replace;
71+
if (Translation.chapterDicts.ContainsKey(currentAdvId) &&
72+
Translation.chapterDicts[currentAdvId].TryGetValue(line, out text_replace))
73+
line = text_replace.IsNullOrWhiteSpace() ? line : text_replace;
74+
}
75+
}
76+
77+
// Option
78+
[HarmonyPrefix]
79+
[HarmonyPatch(typeof(BurikoParseScript), "_ToParamList")]
80+
public static void Novel_ToParamList(ref string param)
81+
{
82+
if (!IMYSConfig.TranslationEnabled) return;
83+
84+
var re = new Regex(@"{(.*)}");
85+
var match = re.Match(param);
86+
if (match.Success)
87+
for (var i = 0; i < match.Groups.Count; i++)
88+
{
89+
var options = match.Groups[i].Value.Split(",");
90+
91+
for (var i2 = 0; i2 < options.Length; i2++)
92+
{
93+
string text_replace;
94+
if (Translation.chapterDicts.ContainsKey(currentAdvId) && Translation.chapterDicts[currentAdvId]
95+
.TryGetValue(options[i2], out text_replace))
96+
{
97+
var option_tr = text_replace.IsNullOrWhiteSpace() ? options[i2] : text_replace;
98+
param = param.Replace(options[i2], option_tr);
99+
}
100+
}
101+
}
102+
}
103+
104+
[HarmonyPrefix]
105+
[HarmonyPatch(typeof(MessageScrollView), "CreateItem")]
106+
public static void CreateItem(ref MessageScrollViewItem item)
107+
{
108+
if (!IMYSConfig.TranslationEnabled) return;
109+
110+
if (TMPTranslateFont != null)
111+
{
112+
item._name.font = TMPTranslateFont;
113+
item._message.font = TMPTranslateFont;
114+
}
115+
}
116+
117+
[HarmonyPostfix]
118+
[HarmonyPatch(typeof(ChoicesContent), "SetChoiceButtonText")]
119+
public static void SetChoiceButtonText(ref ChoicesContent __instance)
120+
{
121+
if (!IMYSConfig.TranslationEnabled) return;
122+
123+
if (TMPTranslateFont != null)
124+
for (var i = 0; i < __instance.choiceTextList.Length; i++)
125+
__instance.choiceTextList[i].font = TMPTranslateFont;
126+
}
127+
128+
[HarmonyPostfix]
129+
[HarmonyPatch(typeof(TextRoot), "DeleteRuby")]
130+
public static void DeleteRuby(ref TextRoot __instance)
131+
{
132+
if (!IMYSConfig.TranslationEnabled) return;
133+
134+
if (TMPTranslateFont != null)
135+
{
136+
if (__instance.CharaName) __instance.CharaName.font = TMPTranslateFont;
137+
if (__instance.Message) __instance.Message.font = TMPTranslateFont;
138+
}
139+
}
140+
}

Plugin.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Text;
4+
using BepInEx;
5+
using BepInEx.Logging;
6+
using BepInEx.Unity.IL2CPP;
7+
using Il2CppSystem.IO;
8+
9+
namespace IMYSHook;
10+
11+
[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]
12+
public class Plugin : BasePlugin
13+
{
14+
public override void Load()
15+
{
16+
Console.OutputEncoding = Encoding.UTF8;
17+
18+
if (File.Exists("IMYSProxy.exe"))
19+
{
20+
if (Process.GetProcessesByName("IMYSProxy").Length == 0)
21+
{
22+
var start = new ProcessStartInfo("IMYSProxy.exe")
23+
{
24+
UseShellExecute = true,
25+
CreateNoWindow = false,
26+
WindowStyle = ProcessWindowStyle.Normal
27+
};
28+
Process.Start(start);
29+
}
30+
31+
Environment.SetEnvironmentVariable("http_proxy", "http://127.0.0.1:8765",
32+
EnvironmentVariableTarget.Process);
33+
Environment.SetEnvironmentVariable("https_proxy", "http://127.0.0.1:8765",
34+
EnvironmentVariableTarget.Process);
35+
}
36+
else
37+
{
38+
Environment.SetEnvironmentVariable("http_proxy", "http://127.0.0.1:5678",
39+
EnvironmentVariableTarget.Process);
40+
Environment.SetEnvironmentVariable("https_proxy", "http://127.0.0.1:5678",
41+
EnvironmentVariableTarget.Process);
42+
}
43+
44+
45+
var log = Log;
46+
Global.Log = log;
47+
Log.LogInfo($"Plugin {MyPluginInfo.PLUGIN_GUID} is loaded!");
48+
49+
IMYSConfig.Read();
50+
Translation.Init();
51+
Patch.Initialize();
52+
53+
AddComponent<PluginBehavior>();
54+
}
55+
56+
public class Global
57+
{
58+
public static ManualLogSource Log { get; set; }
59+
}
60+
}

0 commit comments

Comments
 (0)