Skip to content

Commit 368dfb0

Browse files
authored
Merge pull request #128 from ModShardTeam/BetterErrors
Better errors
2 parents 044bcf5 + 5225364 commit 368dfb0

38 files changed

Lines changed: 987 additions & 986 deletions

Controls/ModInfos.xaml.cs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using System.Threading.Tasks;
77
using System.Windows;
88
using System.Windows.Controls;
9+
using ModShardLauncher.Core.Errors;
10+
using ModShardLauncher.Core.UI;
911
using ModShardLauncher.Mods;
1012
using Serilog;
1113

@@ -36,38 +38,33 @@ private async void Save_Click(object sender, EventArgs e)
3638
return;
3739
}
3840

39-
bool patchSucess = false;
41+
MSLDiagnostic? diag = ModLoader.PatchFile();
4042

41-
Stopwatch watch = Stopwatch.StartNew();
42-
try
43+
if (diag is null)
4344
{
44-
ModLoader.PatchFile();
45-
long elapsedMs = watch.ElapsedMilliseconds;
4645
Main.Instance.LogModListStatus();
47-
Log.Information("Patching lasts {{{0}}} ms", elapsedMs);
4846
Log.Information("Successfully patch vanilla");
49-
patchSucess = true;
47+
48+
Task<bool> save = DataLoader.DoSaveDialog();
49+
await save;
50+
if (save.Result)
51+
{
52+
LootUtils.SaveLootTables(Msl.ThrowIfNull(Path.GetDirectoryName(DataLoader.savedDataPath)));
53+
}
54+
else
55+
{
56+
Log.Information("Saved cancelled.");
57+
}
5058
}
51-
catch (Exception ex)
59+
else
5260
{
5361
Main.Instance.LogModListStatus();
54-
Log.Error(ex, "Something went wrong");
5562
Log.Information("Failed patching vanilla");
56-
MessageBox.Show(ex.ToString(), Application.Current.FindResource("SaveDataWarning").ToString());
57-
}
58-
59-
// attempt to save the patched data
60-
if (patchSucess)
61-
{
62-
Task<bool> save = DataLoader.DoSaveDialog();
63-
await save;
64-
if (!save.Result) Log.Information("Saved cancelled.");
65-
// copy the dataloot.json in the stoneshard directory
66-
LootUtils.SaveLootTables(Msl.ThrowIfNull(Path.GetDirectoryName(DataLoader.savedDataPath)));
63+
ErrorMessageDialog.Show(diag.Title(), diag.MessageDialog(), Main.Instance.logPath);
6764
}
6865

6966
// reload the data
70-
await DataLoader.LoadFile(DataLoader.dataPath, true);
67+
await DataLoader.LoadFile(DataLoader.dataPath);
7168
Main.Instance.Refresh();
7269
}
7370

Controls/SourceBar.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ private void CompileButton_Click(object sender, RoutedEventArgs e)
3838
Log.Error(ex, "Something went wrong");
3939
}
4040

41-
Msl.ThrowIfNull(Main.Instance.Viewer.Content as UserControl).UpdateLayout();
41+
Msl.ThrowIfNull((UserControl)Main.Instance.Viewer.Content).UpdateLayout();
4242
Main.Instance.Refresh();
4343
}
4444

Core/Errors/MSLDiagnostic.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System;
2+
using System.Drawing;
3+
using System.Windows.Forms;
4+
using Serilog;
5+
6+
namespace ModShardLauncher.Core.Errors
7+
{
8+
public class MSLDiagnostic
9+
{
10+
public string ModName;
11+
public string? FileName;
12+
public string? PatchingMethod;
13+
public Exception exception;
14+
public MSLDiagnostic(Exception ex, ModFile modFile)
15+
{
16+
if (ex.Data.Contains("fileName"))
17+
{
18+
object? fileName = ex.Data["fileName"];
19+
FileName = $"{fileName}";
20+
}
21+
if (ex.Data.Contains("patchingWay"))
22+
{
23+
object? patchingWay = ex.Data["patchingWay"];
24+
PatchingMethod = $"{patchingWay}";
25+
}
26+
ModName = modFile.Name;
27+
exception = ex;
28+
}
29+
public void ToLog()
30+
{
31+
string extraInformation = " for {{{0}}}";
32+
if (FileName is not null)
33+
{
34+
extraInformation += " in file {{{1}}}";
35+
}
36+
if (PatchingMethod is not null)
37+
{
38+
extraInformation += " while patching by {{{2}}}";
39+
}
40+
Log.Error(exception, "Something went wrong" + extraInformation, ModName, FileName, PatchingMethod);
41+
}
42+
public string Title()
43+
{
44+
return $"Patching {ModName} failed";
45+
}
46+
public string MessageDialog()
47+
{
48+
RichTextBox message = new();
49+
50+
message.SelectionColor = Color.Black;
51+
message.AppendText("An error was encountered while patching the mod ");
52+
message.SelectionColor = Color.Blue;
53+
message.AppendText(ModName);
54+
message.SelectionColor = Color.Black;
55+
message.AppendText(":\n");
56+
57+
if (FileName is not null)
58+
{
59+
message.SelectionColor = Color.Black;
60+
message.AppendText("In file ");
61+
message.SelectionColor = Color.Blue;
62+
message.AppendText(FileName);
63+
}
64+
if (PatchingMethod is not null)
65+
{
66+
message.SelectionColor = Color.Black;
67+
message.AppendText(" by ");
68+
message.SelectionColor = Color.Blue;
69+
message.AppendText(PatchingMethod);
70+
message.SelectionColor = Color.Black;
71+
message.AppendText(":\n");
72+
}
73+
74+
message.SelectionColor = Color.Black;
75+
message.AppendText("\n");
76+
message.SelectionFont = new Font(message.Font, FontStyle.Bold);
77+
message.AppendText(exception.ToString());
78+
return message.Rtf;
79+
}
80+
}
81+
}

Core/UI/ErrorMessageDialog.cs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
using System;
2+
using System.Drawing;
3+
using System.Windows.Forms;
4+
using Serilog;
5+
6+
namespace ModShardLauncher.Core.UI
7+
{
8+
public class ErrorMessageDialog : Form
9+
{
10+
private readonly RichTextBox messageTextBox;
11+
public DialogResult Result { get; private set; }
12+
private readonly TableLayoutPanel panel;
13+
private readonly Button okButton;
14+
private readonly Button cpyButton;
15+
private readonly Button logButton;
16+
public ErrorMessageDialog(string title, string message, string? logPath = null)
17+
{
18+
panel = new();
19+
messageTextBox = new RichTextBox();
20+
okButton = new Button();
21+
cpyButton = new Button();
22+
logButton = new Button();
23+
24+
InitializeComponent();
25+
SetupDialog(title, message, logPath);
26+
}
27+
private void InitializeComponent()
28+
{
29+
SuspendLayout();
30+
31+
Text = string.Empty;
32+
Size = new Size(450, 200);
33+
StartPosition = FormStartPosition.CenterParent;
34+
FormBorderStyle = FormBorderStyle.FixedDialog;
35+
MaximizeBox = false;
36+
MinimizeBox = false;
37+
ShowIcon = false;
38+
ShowInTaskbar = false;
39+
Dock = DockStyle.Fill;
40+
41+
// panel
42+
panel.Anchor = AnchorStyles.Top;
43+
panel.Size = new Size(300, 150);
44+
panel.BorderStyle = BorderStyle.None;
45+
panel.ColumnCount = 3;
46+
panel.RowCount = 2;
47+
panel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
48+
panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 44));
49+
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
50+
panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
51+
panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
52+
panel.Dock = DockStyle.Fill;
53+
54+
// Message TextBox
55+
messageTextBox.ReadOnly = true;
56+
messageTextBox.BorderStyle = BorderStyle.None;
57+
messageTextBox.BackColor = BackColor;
58+
messageTextBox.ScrollBars = RichTextBoxScrollBars.Vertical;
59+
messageTextBox.TabStop = false;
60+
61+
// ok button
62+
okButton.Text = "OK";
63+
okButton.Size = new Size(75, 23);
64+
okButton.DialogResult = DialogResult.OK;
65+
okButton.Click += (s, e) => { Result = DialogResult.OK; Close(); };
66+
67+
// copy button
68+
cpyButton.Text = "Copy error";
69+
cpyButton.Size = new Size(100, 23);
70+
cpyButton.Click += CopyButton_Click;
71+
72+
// log button
73+
logButton.Text = "Open Log Folder";
74+
logButton.Size = new Size(120, 23);
75+
logButton.Click += LogButton_Click;
76+
77+
panel.Controls.Add(messageTextBox, 0, 0);
78+
panel.SetColumnSpan(messageTextBox, 3);
79+
panel.Controls.Add(okButton, 0, 1);
80+
panel.Controls.Add(cpyButton, 1, 1);
81+
panel.Controls.Add(logButton, 2, 1);
82+
83+
Controls.Add(panel);
84+
85+
// Set default button and cancel button
86+
AcceptButton = okButton;
87+
CancelButton = okButton;
88+
89+
ResumeLayout();
90+
}
91+
private void SetupDialog(string title, string message, string? logPath = null)
92+
{
93+
Text = title;
94+
messageTextBox.Rtf = message;
95+
messageTextBox.AutoSize = true;
96+
97+
Size size = messageTextBox.GetPreferredSize(new Size(800, 0)) + new Size(0, 50);
98+
int newHeight = size.Height + 100;
99+
int newWidth = Math.Max(450, size.Width + 50);
100+
101+
messageTextBox.Size = new Size(size.Width, size.Height);
102+
Size = new Size(newWidth, newHeight);
103+
104+
// Hide log button if no path provided
105+
if (string.IsNullOrEmpty(logPath))
106+
{
107+
logButton.Visible = false;
108+
okButton.Location = new Point(340, 125); // Center the OK button
109+
}
110+
else
111+
{
112+
logButton.Tag = logPath; // Store the log path
113+
}
114+
}
115+
private void LogButton_Click(object? sender, EventArgs e)
116+
{
117+
try
118+
{
119+
string? logPath = logButton.Tag?.ToString();
120+
if (!string.IsNullOrEmpty(logPath))
121+
{
122+
System.Diagnostics.Process.Start("explorer.exe", logPath);
123+
}
124+
}
125+
catch (Exception ex)
126+
{
127+
MessageBox.Show($"Could not open log folder: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
128+
}
129+
130+
// nifty trick: use Retry to indicate log button was clicked
131+
Result = DialogResult.Retry;
132+
Close();
133+
}
134+
private void CopyButton_Click(object? sender, EventArgs e)
135+
{
136+
Clipboard.SetText(messageTextBox.Text);
137+
}
138+
public static DialogResult Show(string title, string message, string? logPath = null)
139+
{
140+
using var dialog = new ErrorMessageDialog(title, message, logPath);
141+
dialog.ShowDialog();
142+
return dialog.Result;
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)