Skip to content

Commit

Permalink
Improve data integrity checks (#720)
Browse files Browse the repository at this point in the history
Resolves #719.
  • Loading branch information
lahm86 authored Jun 29, 2024
1 parent 362ca6b commit 5361dad
Show file tree
Hide file tree
Showing 14 changed files with 130 additions and 61 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## [Unreleased](https://github.com/LostArtefacts/TR-Rando/compare/V1.9.1...master) - xxxx-xx-xx
- improved data integrity checks when opening a folder and prior to randomization (#719)

## [V1.9.1](https://github.com/LostArtefacts/TR-Rando/compare/V1.9.0...V1.9.1) - 2024-06-23
- fixed a missing reference related to Willard, which would cause enemy randomization to fail if he was selected (#712)
Expand Down
Binary file modified Deps/TRGE.Coord.dll
Binary file not shown.
Binary file modified Deps/TRGE.Core.dll
Binary file not shown.
1 change: 1 addition & 0 deletions TRRandomizerCore/Helpers/ChecksumTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public bool Test(string file)
"1e7d0d88ff9d569e22982af761bb006b", // FLOATING.TR2 (Multipatch/EPC)
"fd8c45efc3f5e690edd0796d350a28ba", // XIAN.TR2
"b56c04ea52227eb7fdebd0665b45357a", // HOUSE.TR2
"2241125203a4af81fc4889ed844d5b22", // HOUSE.TR2 (rando-generated for texture optimisation)
"04ad2f33e48081a6b27a7f0ebf90968d", // LEVEL1.TR2
"d9b53b88dd70eec1e4b31182f3286bf5", // LEVEL2.TR2
"ca4294e3bd8835ebf06e114b479a22c2", // LEVEL3.TR2
Expand Down
7 changes: 4 additions & 3 deletions TRRandomizerCore/TRRandomizerController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ public class TRRandomizerController
internal AbstractTRScriptEditor ScriptEditor => _editor.ScriptEditor;
internal RandomizerSettings LevelRandomizer => (_editor.LevelEditor as ISettingsProvider).Settings;

internal TRRandomizerController(string directoryPath, bool performChecksumTest)
internal TRRandomizerController(string directoryPath)
{
// If there is a checksum mismatch, we will just ignore the previous backup and open the folder afresh
_editor = TRCoord.Instance.Open(directoryPath, TRScriptOpenOption.DiscardBackup, performChecksumTest ? TRBackupChecksumOption.PerformCheck : TRBackupChecksumOption.IgnoreIssues);
// If there is a script checksum mismatch, we will just ignore the previous backup and open the folder afresh. If the
// data files fail the checksum test, the folder cannot be opened.
_editor = TRCoord.Instance.Open(directoryPath, TRScriptOpenOption.DiscardBackup, TRBackupChecksumOption.PerformCheck);
_editor.SaveProgressChanged += Editor_SaveProgressChanged;
_editor.RestoreProgressChanged += Editor_RestoreProgressChanged;
StoreExternalOrganisations();
Expand Down
9 changes: 7 additions & 2 deletions TRRandomizerCore/TRRandomizerCoord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,22 @@ public void Initialise(string applicationID, string version, string taggedVersio
TRCoord.Instance.BackupProgressChanged += TRCoord_BackupProgressChanged;
}

public TRRandomizerController Open(string directoryPath, bool performChecksumTest)
public TRRandomizerController Open(string directoryPath)
{
_openEventArgs = new();
return new(directoryPath, performChecksumTest);
return new(directoryPath);
}

public static void ClearHistory()
{
TRCoord.Instance.ClearHistory();
}

public static void CheckBackupIntegrity()
{
TRCoord.Instance.CheckBackupIntegrity();
}

public static void ClearCurrentBackup()
{
TRCoord.Instance.ClearCurrentBackup();
Expand Down
54 changes: 38 additions & 16 deletions TRRandomizerView/Controls/EditorControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using TRGE.Core;
using TRRandomizerCore;
using TRRandomizerView.Events;
using TRRandomizerView.Model;
Expand Down Expand Up @@ -88,6 +89,7 @@ private void FireEditorStateChanged()
{
EditorStateChanged?.Invoke(this, new EditorEventArgs
{
IsLoaded = Controller != null,
IsDirty = _dirty,
CanExport = Controller != null && Controller.IsExportPossible,
ReloadRequested = _reloadRequested
Expand Down Expand Up @@ -158,6 +160,23 @@ public bool Randomize()
return false;
}

try
{
TRRandomizerCoord.CheckBackupIntegrity();
}
catch (ChecksumMismatchException)
{
MessageWindow.ShowError("Game backup data integrity check failed. Randomization cannot be performed as the game data files in the backup directory are not original." +
"\n\nPlease uninstall the game and remove any external mods you may have applied.\n\nOnce complete, reinstall the game afresh, and open the data folder again in the randomizer to proceed.",
"https://github.com/LostArtefacts/TR-Rando/blob/master/USING.md#troubleshooting");

if (DeleteBackupImpl())
{
Unload();
}
return false;
}

if (_options.DevelopmentMode)
{
if (!MessageWindow.ShowConfirm("Development mode is switched on and so the generated level files will not be playable.\n\nDo you wish to continue?"))
Expand Down Expand Up @@ -284,23 +303,26 @@ public void RestoreDefaults()

public bool DeleteBackup()
{
if (MessageWindow.ShowConfirm("The files that were backed up when this folder was first opened will be deleted and the editor will be closed.\n\nDo you wish to proceed?"))
return MessageWindow.ShowConfirm("The files that were backed up when this folder was first opened will be deleted and the editor will be closed.\n\nDo you wish to proceed?")
&& DeleteBackupImpl();
}

private bool DeleteBackupImpl()
{
try
{
try
{
_showExternalModPrompt = false;
TRRandomizerCoord.ClearCurrentBackup();
_dirty = false;
return true;
}
catch (Exception e)
{
MessageWindow.ShowException(e);
}
finally
{
_showExternalModPrompt = true;
}
_showExternalModPrompt = false;
TRRandomizerCoord.ClearCurrentBackup();
_dirty = false;
return true;
}
catch (Exception e)
{
MessageWindow.ShowException(e);
}
finally
{
_showExternalModPrompt = true;
}

return false;
Expand Down
13 changes: 5 additions & 8 deletions TRRandomizerView/Controls/FolderLoadControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ public void OpenDataFolder(RecentFolder folder)
OpenDataFolder(folder.FolderPath);
}

public void OpenDataFolder(string folderPath, bool performChecksumTest = true)
public void OpenDataFolder(string folderPath)
{
OpenProgressWindow opw = new(folderPath, performChecksumTest);
OpenProgressWindow opw = new(folderPath);
try
{
if (opw.ShowDialog() ?? false)
Expand All @@ -109,12 +109,9 @@ public void OpenDataFolder(string folderPath, bool performChecksumTest = true)
}
catch (ChecksumMismatchException)
{
if (!MessageWindow.ShowConfirm(folderPath + "\n\nGame data integrity check failed. Randomization may not perform as expected as the game data files in the chosen directory are not original." +
"\n\nThe recommended action is for you to re-install the game. Once complete, open the data folder again in the randomizer to proceed." +
"\n\nDo you want to cancel the current operation and take the recommended action?"))
{
OpenDataFolder(folderPath, false);
}
MessageWindow.ShowError(folderPath + "\n\nGame data integrity check failed. Randomization cannot be performed as the game data files in the chosen directory are not original." +
"\n\nPlease uninstall the game and remove any external mods you may have applied.\n\nOnce complete, reinstall the game afresh, and open the data folder again in the randomizer to proceed.",
"https://github.com/LostArtefacts/TR-Rando/blob/master/USING.md#troubleshooting");
}
catch (Exception e)
{
Expand Down
1 change: 1 addition & 0 deletions TRRandomizerView/Events/EditorEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace TRRandomizerView.Events;

public class EditorEventArgs : EventArgs
{
public bool IsLoaded { get; set; }
public bool IsDirty { get; set; }
public bool CanExport { get; set; }
public bool ReloadRequested { get; set; }
Expand Down
6 changes: 5 additions & 1 deletion TRRandomizerView/Windows/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,11 @@ private void EditorControl_EditorStateChanged(object sender, EditorEventArgs e)
IsEditorDirty = e.IsDirty;
EditorCanExport = e.CanExport;
_developmentModeMenuItem.IsChecked = _editorControl.DevelopmentMode;
if (e.ReloadRequested)
if (!e.IsLoaded)
{
IsEditorActive = false;
}
else if (e.ReloadRequested)
{
_editorControl.Unload();
IsEditorActive = false;
Expand Down
20 changes: 14 additions & 6 deletions TRRandomizerView/Windows/MessageWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,20 @@
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

<Button Grid.Row="1"
Grid.Column="1"
Style="{StaticResource LinkButtonStyle}"
Content="Show Error Folder"
Click="ErrorButton_Click"
Visibility="{Binding ErrorLinkVisibility}"/>
<Button
Style="{StaticResource LinkButtonStyle}"
Content="Show Error Folder"
Click="ErrorButton_Click"
Visibility="{Binding ErrorLinkVisibility}"/>

<TextBlock
VerticalAlignment="Center"
Visibility="{Binding HelpLinkVisibility}">
<Hyperlink
NavigateUri="{Binding HelpURL}"
ToolTip="{Binding HelpURL}"
RequestNavigate="HelpLink_RequestNavigate">Help</Hyperlink>
</TextBlock>

<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right"
Expand Down
64 changes: 47 additions & 17 deletions TRRandomizerView/Windows/MessageWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using TRRandomizerView.Commands;
using TRRandomizerView.Utilities;

Expand All @@ -21,6 +22,11 @@ public partial class MessageWindow : Window
nameof(Details), typeof(string), typeof(MessageWindow)
);

public static readonly DependencyProperty HelpURLProperty = DependencyProperty.Register
(
nameof(HelpURL), typeof(string), typeof(MessageWindow)
);

public static readonly DependencyProperty ImageIconProperty = DependencyProperty.Register
(
nameof(ImageIcon), typeof(BitmapSource), typeof(MessageWindow)
Expand All @@ -41,6 +47,11 @@ public partial class MessageWindow : Window
nameof(ErrorLinkVisibility), typeof(Visibility), typeof(MessageWindow)
);

public static readonly DependencyProperty HelpLinkVisibilityProperty = DependencyProperty.Register
(
nameof(HelpLinkVisibility), typeof(Visibility), typeof(MessageWindow)
);

public static readonly DependencyProperty YesNoButtonVisibilityProperty = DependencyProperty.Register
(
nameof(YesNoButtonVisibility), typeof(Visibility), typeof(MessageWindow)
Expand All @@ -63,6 +74,12 @@ public string Details
set => SetValue(DetailsProperty, value);
}

public string HelpURL
{
get => (string)GetValue(HelpURLProperty);
set => SetValue(HelpURLProperty, value);
}

public BitmapSource ImageIcon
{
get => (BitmapSource)GetValue(ImageIconProperty);
Expand All @@ -87,6 +104,12 @@ public Visibility ErrorLinkVisibility
set => SetValue(ErrorLinkVisibilityProperty, value);
}

public Visibility HelpLinkVisibility
{
get => (Visibility)GetValue(HelpLinkVisibilityProperty);
set => SetValue(HelpLinkVisibilityProperty, value);
}

public Visibility YesNoButtonVisibility
{
get => (Visibility)GetValue(YesNoButtonVisibilityProperty);
Expand All @@ -102,7 +125,7 @@ public Visibility CancelButtonVisibility

private MessageBoxResult _result;

private MessageWindow(string message, Icon icon, MessageBoxButton buttons, string details = null)
private MessageWindow(string message, Icon icon, MessageBoxButton buttons, string details = null, string helpURL = null)
{
InitializeComponent();
Owner = WindowUtils.GetActiveWindow(this);
Expand All @@ -111,11 +134,13 @@ private MessageWindow(string message, Icon icon, MessageBoxButton buttons, strin

Message = message;
Details = details;
HelpURL = helpURL ?? string.Empty;
ImageIcon = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

OkButtonVisibility = (buttons == MessageBoxButton.OK || buttons == MessageBoxButton.OKCancel) ? Visibility.Visible : Visibility.Collapsed;
DetailsButtonVisibility = details == null ? Visibility.Collapsed : Visibility.Visible;
ErrorLinkVisibility = details != null && WindowCommands.ShowErrors.CanExecute(null, Application.Current.MainWindow) ? Visibility.Visible : Visibility.Collapsed;
HelpLinkVisibility = helpURL == null ? Visibility.Collapsed : Visibility.Visible;
YesNoButtonVisibility = (buttons == MessageBoxButton.YesNo || buttons == MessageBoxButton.YesNoCancel) ? Visibility.Visible : Visibility.Collapsed;
CancelButtonVisibility = (buttons == MessageBoxButton.OKCancel || buttons == MessageBoxButton.YesNoCancel) ? Visibility.Visible : Visibility.Collapsed;

Expand All @@ -134,49 +159,49 @@ private MessageWindow(string message, Icon icon, MessageBoxButton buttons, strin
}
}

public static void ShowMessage(string message)
public static void ShowMessage(string message, string helpURL = null)
{
Show(message, SystemIcons.Information, MessageBoxButton.OK);
Show(message, SystemIcons.Information, MessageBoxButton.OK, helpURL: helpURL);
}

public static bool ShowMessageWithCancel(string message)
public static bool ShowMessageWithCancel(string message, string helpURL = null)
{
return Show(message, SystemIcons.Information, MessageBoxButton.OKCancel) == MessageBoxResult.OK;
return Show(message, SystemIcons.Information, MessageBoxButton.OKCancel, helpURL: helpURL) == MessageBoxResult.OK;
}

public static void ShowWarning(string message)
public static void ShowWarning(string message, string helpURL = null)
{
Show(message, SystemIcons.Warning, MessageBoxButton.OK);
Show(message, SystemIcons.Warning, MessageBoxButton.OK, helpURL: helpURL);
}

public static bool ShowWarningWithCancel(string message)
public static bool ShowWarningWithCancel(string message, string helpURL = null)
{
return Show(message, SystemIcons.Warning, MessageBoxButton.OKCancel) == MessageBoxResult.OK;
return Show(message, SystemIcons.Warning, MessageBoxButton.OKCancel, helpURL: helpURL) == MessageBoxResult.OK;
}

public static void ShowError(string message)
public static void ShowError(string message, string helpURL = null)
{
Show(message, SystemIcons.Error, MessageBoxButton.OK);
Show(message, SystemIcons.Error, MessageBoxButton.OK, helpURL: helpURL);
}

public static void ShowException(Exception e)
{
Show(e.Message, SystemIcons.Error, MessageBoxButton.OK, e.ToString());
}

public static bool ShowConfirm(string message)
public static bool ShowConfirm(string message, string helpURL = null)
{
return Show(message, SystemIcons.Question, MessageBoxButton.YesNo) == MessageBoxResult.Yes;
return Show(message, SystemIcons.Question, MessageBoxButton.YesNo, helpURL: helpURL) == MessageBoxResult.Yes;
}

public static MessageBoxResult ShowConfirmCancel(string message)
public static MessageBoxResult ShowConfirmCancel(string message, string helpURL = null)
{
return Show(message, SystemIcons.Question, MessageBoxButton.YesNoCancel);
return Show(message, SystemIcons.Question, MessageBoxButton.YesNoCancel, helpURL: helpURL);
}

private static MessageBoxResult Show(string message, Icon icon, MessageBoxButton buttons, string details = null)
private static MessageBoxResult Show(string message, Icon icon, MessageBoxButton buttons, string details = null, string helpURL = null)
{
MessageWindow mw = new(message, icon, buttons, details);
MessageWindow mw = new(message, icon, buttons, details, helpURL);
mw.ShowDialog();
return mw._result;
}
Expand Down Expand Up @@ -225,4 +250,9 @@ private void ErrorButton_Click(object sender, RoutedEventArgs e)
{
WindowCommands.ShowErrors.Execute(null, Application.Current.MainWindow);
}

private void HelpLink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
ProcessUtils.OpenURL(HelpURL);
}
}
6 changes: 2 additions & 4 deletions TRRandomizerView/Windows/OpenProgressWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,17 @@ public string ProgressDescription

private volatile bool _complete;
private readonly string _folderPath;
private readonly bool _performChecksumTest;

public Exception OpenException { get; private set; }
public TRRandomizerController OpenedController { get; private set; }

public OpenProgressWindow(string folderPath, bool performChecksumTest)
public OpenProgressWindow(string folderPath)
{
InitializeComponent();
Owner = WindowUtils.GetActiveWindow(this);
DataContext = this;
_complete = false;
_folderPath = folderPath;
_performChecksumTest = performChecksumTest;
}

private void Window_Loaded(object sender, RoutedEventArgs e)
Expand All @@ -75,7 +73,7 @@ private void Open()

try
{
OpenedController = TRRandomizerCoord.Instance.Open(_folderPath, _performChecksumTest);
OpenedController = TRRandomizerCoord.Instance.Open(_folderPath);
}
catch (Exception e)
{
Expand Down
Loading

0 comments on commit 5361dad

Please sign in to comment.