Add support for known outdated mods, unpatching on game exit

This commit is contained in:
Norbi Peti 2022-02-14 00:10:30 +01:00
parent 4ddab53b6d
commit ae89291c55
5 changed files with 76 additions and 30 deletions

View file

@ -128,7 +128,9 @@ You may also want to verify the game's files in the launcher.
{ {
if (mod.Updatable) if (mod.Updatable)
addText("New version available! " + mod.UpdateDetails, Color.Aqua); addText("New version available! " + mod.UpdateDetails, Color.Aqua);
if (mod.LastUpdated != default && mod.LastUpdated < lastGameUpdateTime) if (mod.Broken)
addText("Outdated mod! It has been confirmed that the mod is broken on the current version of the game.", Color.Red);
else if (mod.LastUpdated != default && mod.LastUpdated < lastGameUpdateTime)
addText("Outdated mod! It may not work properly on the current version of the game.", Color.DarkOrange); addText("Outdated mod! It may not work properly on the current version of the game.", Color.DarkOrange);
if (mod.Description != null) if (mod.Description != null)
modinfobox.AppendText(mod.Description.Replace("\n", Environment.NewLine)); modinfobox.AppendText(mod.Description.Replace("\n", Environment.NewLine));

View file

@ -66,11 +66,22 @@ namespace TBMM
{ {
var sp = line.Split('\t'); var sp = line.Split('\t');
if (sp.Length < 2) continue; if (sp.Length < 2) continue;
DateTime updated = default;
bool broken = false;
if (sp.Length > 2)
{
if (DateTime.TryParse(sp[2].Trim(), out var updatedAt))
updated = updatedAt;
else if (sp[2].Trim().ToLower() == "broken")
broken = true;
}
var mod = new ModInfo var mod = new ModInfo
{ {
Author = sp[0].Trim(), Author = sp[0].Trim(),
Name = sp[1].Trim(), Name = sp[1].Trim(),
LastUpdated = sp.Length > 2 ? DateTime.Parse(sp[2].Trim()) : default LastUpdated = updated,
Broken = broken
}; };
if (await FetchModInfo(mod, preview, true)) //If it's actually a mod if (await FetchModInfo(mod, preview, true)) //If it's actually a mod
AddUpdateModInList(mod); AddUpdateModInList(mod);
@ -191,6 +202,8 @@ namespace TBMM
} }
if (mod.LatestVersion != null && mod.Version != null && mod.Version < mod.LatestVersion) if (mod.LatestVersion != null && mod.Version != null && mod.Version < mod.LatestVersion)
item.ForeColor = Color.Blue; item.ForeColor = Color.Blue;
else if(mod.Broken)
item.ForeColor = Color.Red;
else if (mod.LastUpdated != default && mod.LastUpdated < lastGameUpdateTime) else if (mod.LastUpdated != default && mod.LastUpdated < lastGameUpdateTime)
item.ForeColor = Color.OrangeRed; item.ForeColor = Color.OrangeRed;
else else

View file

@ -18,7 +18,7 @@ namespace TBMM
status.Text = "Status: Game not found"; status.Text = "Status: Game not found";
return GameState.NotFound; return GameState.NotFound;
} }
string pnp = "Patch && Play"; string pnp = "Play modded";
if (!File.Exists(GamePath(@"\IPA.exe"))) if (!File.Exists(GamePath(@"\IPA.exe")))
{ {
status.Text = "Status: Patcher missing\nClicking Play will install it"; status.Text = "Status: Patcher missing\nClicking Play will install it";
@ -31,8 +31,8 @@ namespace TBMM
playbtn.Text = pnp; playbtn.Text = pnp;
return GameState.OldPatcher; return GameState.OldPatcher;
} }
string nopatch = "Status: Unpatched\nClicking Play patches it"; string nopatch = "Status: Unpatched";
string gc = GetExe().Replace(".exe", ""); string gc = GetExe(withExtension: false);
string backups = GamePath(@"\IPA\Backups\" + gc); string backups = GamePath(@"\IPA\Backups\" + gc);
if (!Directory.Exists(backups)) if (!Directory.Exists(backups))
{ {
@ -129,26 +129,8 @@ namespace TBMM
case GameState.Unpatched: case GameState.Unpatched:
{ //TODO: Wine { //TODO: Wine
EnsureShown(false); EnsureShown(false);
var psi = new ProcessStartInfo(GamePath(@"\IPA.exe"), GetExe() + " --nowait")
{
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = Configuration.GamePath,
CreateNoWindow = true
};
var process = Process.Start(psi);
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.EnableRaisingEvents = true;
modinfobox.Text = "";
DataReceivedEventHandler onoutput = (sender, e) =>
{
Invoke((Action)(() => modinfobox.Text += e.Data + Environment.NewLine));
};
process.OutputDataReceived += onoutput;
process.ErrorDataReceived += onoutput;
var (handler, task) = CheckStartGame(command); var (handler, task) = CheckStartGame(command);
var process = ExecutePatcher(true);
process.Exited += handler; process.Exited += handler;
await task; await task;
} }
@ -165,6 +147,30 @@ namespace TBMM
return retOpenedWindowShouldStay; return retOpenedWindowShouldStay;
} }
private Process ExecutePatcher(bool patch)
{
var psi = new ProcessStartInfo(GamePath(@"\IPA.exe"), $"{GetExe()} --nowait {(patch ? "" : "--revert")}")
{
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = Configuration.GamePath,
CreateNoWindow = true
};
var process = Process.Start(psi);
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.EnableRaisingEvents = true;
modinfobox.Text = "";
DataReceivedEventHandler onoutput = (sender, e) =>
{
Invoke((Action)(() => modinfobox.Text += e.Data + Environment.NewLine));
};
process.OutputDataReceived += onoutput;
process.ErrorDataReceived += onoutput;
return process;
}
public enum GameState public enum GameState
{ {
NotFound, NotFound,

View file

@ -73,18 +73,28 @@ namespace TBMM
return; return;
} }
if (CheckIfPatched() == GameState.Patched || unpatched.Checked) if (CheckIfPatched() == GameState.Patched || unpatched.Checked)
{
Process process = null;
if (command != null) if (command != null)
{ {
if (sender is Process) //Patched just now if (sender is Process) //Patched just now
CheckCompatibilityAndDisableMods(); CheckCompatibilityAndDisableMods();
await CheckModUpdatesAsync(); await CheckModUpdatesAsync();
Process.Start(command); process = Process.Start(command);
} }
else if (Environment.OSVersion.Platform == PlatformID.Win32NT) else if (Environment.OSVersion.Platform == PlatformID.Win32NT)
Process.Start(new ProcessStartInfo(GamePath("\\" + GetExe())) {
process = Process.Start(new ProcessStartInfo(GamePath("\\" + GetExe()))
{ {
WorkingDirectory = GamePath("\\") //Mods are only loaded if the working directory is correct WorkingDirectory = GamePath("\\") //Mods are only loaded if the working directory is correct
}); });
}
if (process is null)
throw new NullReferenceException("Game process is null");
process.EnableRaisingEvents = true;
process.Exited += HandleGameExit;
}
EndWork(false); EndWork(false);
tcs.SetResult(null); tcs.SetResult(null);
}; };
@ -95,6 +105,20 @@ namespace TBMM
}, tcs.Task); }, tcs.Task);
} }
private void HandleGameExit(object sender, EventArgs e)
{
ExecutePatcher(false).Exited += (o, args) =>
{
if (CheckIfPatched() == GameState.Patched)
{
MessageBox.Show("Failed to unpatch game, launching through the launcher will fail because of anticheat. " +
"Check the output in the panel on the right.\n\n" +
"Please try starting the game again by clicking Play.", "Patcher error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
};
}
private void CheckCompatibilityAndDisableMods() private void CheckCompatibilityAndDisableMods()
{ {
if (!unpatched.Checked && MessageBox.Show("If the game updated just now, some mods may be incompatible or they may work just fine." + if (!unpatched.Checked && MessageBox.Show("If the game updated just now, some mods may be incompatible or they may work just fine." +
@ -168,12 +192,12 @@ namespace TBMM
return ((gamepath ?? Configuration.GamePath) + path).Replace('\\', Path.DirectorySeparatorChar); return ((gamepath ?? Configuration.GamePath) + path).Replace('\\', Path.DirectorySeparatorChar);
} }
public string GetExe(string path = null) public string GetExe(string path = null, bool withExtension = true)
{ {
if (File.Exists(GamePath("\\Techblox.exe", path))) if (File.Exists(GamePath("\\Techblox.exe", path)))
return "Techblox.exe"; return "Techblox" + (withExtension ? ".exe" : "");
if (File.Exists(GamePath("\\TechbloxPreview.exe", path))) if (File.Exists(GamePath("\\TechbloxPreview.exe", path)))
return "TechbloxPreview.exe"; return "TechbloxPreview.exe" + (withExtension ? ".exe" : "");
return null; return null;
} }
@ -196,7 +220,7 @@ namespace TBMM
public DateTime GetGameVersionAsDate() public DateTime GetGameVersionAsDate()
{ {
if (Configuration.GamePath == null) return default; if (Configuration.GamePath == null) return default;
using var fs = File.OpenRead(GamePath("\\TechbloxPreview_Data\\globalgamemanagers")); using var fs = File.OpenRead(GamePath($"\\{GetExe(withExtension: false)}_Data\\globalgamemanagers"));
using var sr = new StreamReader(fs); using var sr = new StreamReader(fs);
char[] data = new char[512]; char[] data = new char[512];
while(!sr.EndOfStream) while(!sr.EndOfStream)

View file

@ -31,5 +31,6 @@ namespace TBMM
public HashSet<string> ModFiles { get; set; } public HashSet<string> ModFiles { get; set; }
public string UpdateDetails { get; set; } public string UpdateDetails { get; set; }
public bool Updatable => Version != null && LatestVersion != null && Version < LatestVersion; public bool Updatable => Version != null && LatestVersion != null && Version < LatestVersion;
public bool Broken { get; set; }
} }
} }