修了一堆东西
This commit is contained in:
parent
1f5f1c8e6c
commit
6fd0bf0046
20
Debug.xaml
20
Debug.xaml
@ -6,8 +6,20 @@
|
|||||||
xmlns:local="clr-namespace:AnotherReplayReader"
|
xmlns:local="clr-namespace:AnotherReplayReader"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Debug" Height="450" Width="800">
|
Title="Debug" Height="450" Width="800">
|
||||||
<Grid>
|
<DockPanel Margin="10,10,10,10">
|
||||||
<TextBox x:Name="_textBox" Margin="10,34,10,10" TextWrapping="Wrap" Text="{Binding Path=DebugMessage, Mode=TwoWay}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
<StackPanel DockPanel.Dock="Top"
|
||||||
<Button x:Name="_export" Content="导出日志" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="OnExport_Click"/>
|
Orientation="Horizontal"
|
||||||
</Grid>
|
Margin="0,0,0,10">
|
||||||
|
<Button Padding="8,2"
|
||||||
|
Margin="0,0,10,0"
|
||||||
|
Content="导出日志"
|
||||||
|
Click="OnExport_Click" />
|
||||||
|
<Button Padding="8,2"
|
||||||
|
Content="清空日志"
|
||||||
|
Click="OnClear_Click" />
|
||||||
|
</StackPanel>
|
||||||
|
<TextBox x:Name="_textBox"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Auto" />
|
||||||
|
</DockPanel>
|
||||||
</Window>
|
</Window>
|
||||||
|
@ -1,37 +1,31 @@
|
|||||||
using System;
|
using Microsoft.Win32;
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
|
|
||||||
namespace AnotherReplayReader
|
namespace AnotherReplayReader
|
||||||
{
|
{
|
||||||
public sealed class DebugMessageWrapper : INotifyPropertyChanged
|
public sealed class DebugMessageWrapper
|
||||||
{
|
{
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public readonly struct Proxy
|
||||||
public string DebugMessage
|
|
||||||
{
|
{
|
||||||
get => _debugMessage;
|
public readonly string Payload;
|
||||||
set
|
public Proxy(string text)
|
||||||
{
|
{
|
||||||
_debugMessage = value;
|
Payload = text;
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("DebugMessage"));
|
}
|
||||||
|
public static Proxy operator +(Proxy p, string text)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(p.Payload) ? new Proxy(text) : new Proxy(p.Payload + text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _debugMessage;
|
public event Action<string> NewText;
|
||||||
|
public Proxy DebugMessage
|
||||||
|
{
|
||||||
|
get => new Proxy();
|
||||||
|
set => NewText?.Invoke(value.Payload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Debug.xaml 的交互逻辑
|
/// Debug.xaml 的交互逻辑
|
||||||
@ -42,8 +36,8 @@ namespace AnotherReplayReader
|
|||||||
|
|
||||||
public Debug()
|
public Debug()
|
||||||
{
|
{
|
||||||
DataContext = Instance;
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
Instance.NewText += t => Dispatcher.Invoke(() => _textBox.AppendText(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExport_Click(object sender, RoutedEventArgs e)
|
private void OnExport_Click(object sender, RoutedEventArgs e)
|
||||||
@ -64,5 +58,10 @@ namespace AnotherReplayReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnClear_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_textBox.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,35 @@
|
|||||||
<ColumnDefinition Width="145"/>
|
<ColumnDefinition Width="145"/>
|
||||||
<ColumnDefinition Width="472*"/>
|
<ColumnDefinition Width="472*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBox x:Name="_replayFilterBox" Grid.Row="0" Grid.Column="2" Margin="120,10,10,0" TextWrapping="Wrap" Height="20" VerticalAlignment="Top" />
|
<Grid Grid.Row="0"
|
||||||
|
Grid.Column="2"
|
||||||
|
Margin="120,10,10,0"
|
||||||
|
Height="20"
|
||||||
|
VerticalAlignment="Top">
|
||||||
|
<TextBox x:Name="_replayFilterBox"
|
||||||
|
TextChanged="ReplayFilterBox_TextChanged" />
|
||||||
|
<TextBlock IsHitTestVisible="False"
|
||||||
|
Text="输入录像名称或玩家名称可以筛选录像"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Foreground="DarkGray">
|
||||||
|
<TextBlock.Style>
|
||||||
|
<Style TargetType="{x:Type TextBlock}">
|
||||||
|
<Setter Property="Visibility"
|
||||||
|
Value="Collapsed" />
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Text, ElementName=_replayFilterBox}"
|
||||||
|
Value="">
|
||||||
|
<Setter Property="Visibility"
|
||||||
|
Value="Visible" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Button x:Name="_refreshButton" Content="刷新" Grid.Column="2" HorizontalAlignment="Left" Margin="0,11,0,0" VerticalAlignment="Top" Width="80" Click="OnReplayFolderPathBoxTextChanged"/>
|
<Button x:Name="_refreshButton" Content="刷新" Grid.Column="2" HorizontalAlignment="Left" Margin="0,11,0,0" VerticalAlignment="Top" Width="80" Click="OnReplayFolderPathBoxTextChanged"/>
|
||||||
<DataGrid x:Name="_dataGrid" Grid.Row="0" Grid.Column="2" Grid.RowSpan="2" Margin="0,30,10,16" SelectionMode="Single" SelectionChanged="OnReplaySelectionChanged">
|
<DataGrid x:Name="_dataGrid" Grid.Row="0" Grid.Column="2" Grid.RowSpan="2" Margin="0,30,10,16" SelectionMode="Single" SelectionChanged="OnReplaySelectionChanged">
|
||||||
<DataGrid.Columns>
|
<DataGrid.Columns>
|
||||||
|
@ -9,6 +9,7 @@ using System.Runtime.CompilerServices;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
namespace AnotherReplayReader
|
namespace AnotherReplayReader
|
||||||
{
|
{
|
||||||
@ -18,12 +19,19 @@ namespace AnotherReplayReader
|
|||||||
{
|
{
|
||||||
string userDataLeafName = null;
|
string userDataLeafName = null;
|
||||||
string replayFolderName = null;
|
string replayFolderName = null;
|
||||||
using (var view32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
|
try
|
||||||
using (var ra3Key = view32.OpenSubKey(@"Software\Electronic Arts\Electronic Arts\Red Alert 3", false))
|
|
||||||
{
|
{
|
||||||
RA3Directory = ra3Key?.GetValue("Install Dir") as string;
|
using (var view32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
|
||||||
userDataLeafName = ra3Key?.GetValue("UserDataLeafName") as string;
|
using (var ra3Key = view32.OpenSubKey(@"Software\Electronic Arts\Electronic Arts\Red Alert 3", false))
|
||||||
replayFolderName = ra3Key?.GetValue("ReplayFolderName") as string;
|
{
|
||||||
|
RA3Directory = ra3Key?.GetValue("Install Dir") as string;
|
||||||
|
userDataLeafName = ra3Key?.GetValue("UserDataLeafName") as string;
|
||||||
|
replayFolderName = ra3Key?.GetValue("ReplayFolderName") as string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Instance.DebugMessage += $"获取注册表项时出现错误:{e}\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(userDataLeafName))
|
if (string.IsNullOrWhiteSpace(userDataLeafName))
|
||||||
@ -64,12 +72,6 @@ namespace AnotherReplayReader
|
|||||||
set { _replayFolderPath = value; NotifyPropertyChanged(_replayFolderPath); }
|
set { _replayFolderPath = value; NotifyPropertyChanged(_replayFolderPath); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ReplayFilterString
|
|
||||||
{
|
|
||||||
get { return _replayFilterString; }
|
|
||||||
set { _replayFilterString = value; NotifyPropertyChanged(_replayFilterString); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ReplayDetails
|
public string ReplayDetails
|
||||||
{
|
{
|
||||||
get { return _replayDetails; }
|
get { return _replayDetails; }
|
||||||
@ -84,22 +86,21 @@ namespace AnotherReplayReader
|
|||||||
|
|
||||||
public Replay CurrentReplay
|
public Replay CurrentReplay
|
||||||
{
|
{
|
||||||
get { return _currentReplay; }
|
get => _currentReplay;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_currentReplay = value;
|
_currentReplay = value;
|
||||||
NotifyPropertyChanged(_currentReplay);
|
NotifyPropertyChanged(_currentReplay);
|
||||||
ReplayDetails = "";
|
ReplayDetails = "";
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ReplayPlayable"));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ReplayPlayable)));
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ReplaySelected"));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ReplaySelected)));
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ReplayDamaged"));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ReplayDamaged)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private volatile string _replayFolderPath;
|
private string _replayFolderPath;
|
||||||
private volatile string _replayDetails;
|
private string _replayDetails;
|
||||||
private volatile string _replayFilterString;
|
private Replay _currentReplay;
|
||||||
private volatile Replay _currentReplay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -107,12 +108,12 @@ namespace AnotherReplayReader
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
private MainWindowProperties _properties = new MainWindowProperties();
|
private readonly MainWindowProperties _properties = new MainWindowProperties();
|
||||||
private volatile List<Replay> _replayList;
|
private readonly List<Replay> _replayList = new List<Replay>();
|
||||||
private Cache _cache = new Cache();
|
private readonly Cache _cache = new Cache();
|
||||||
private PlayerIdentity _playerIdentity;
|
private readonly PlayerIdentity _playerIdentity;
|
||||||
private BigMinimapCache _minimapCache;
|
private readonly BigMinimapCache _minimapCache;
|
||||||
private MinimapReader _minimapReader;
|
private readonly MinimapReader _minimapReader;
|
||||||
private CancellationTokenSource _loadReplaysToken;
|
private CancellationTokenSource _loadReplaysToken;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
@ -124,7 +125,7 @@ namespace AnotherReplayReader
|
|||||||
var handling = new bool[1] { false };
|
var handling = new bool[1] { false };
|
||||||
Application.Current.Dispatcher.UnhandledException += (sender, eventArgs) =>
|
Application.Current.Dispatcher.UnhandledException += (sender, eventArgs) =>
|
||||||
{
|
{
|
||||||
if (handling == null || handling[0] == true)
|
if (handling == null || handling[0])
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -132,17 +133,17 @@ namespace AnotherReplayReader
|
|||||||
Dispatcher.Invoke(() => MessageBox.Show($"错误:\r\n{eventArgs.Exception}"));
|
Dispatcher.Invoke(() => MessageBox.Show($"错误:\r\n{eventArgs.Exception}"));
|
||||||
};
|
};
|
||||||
|
|
||||||
Closing += ((sender, eventArgs) => _cache.Save());
|
Closing += (sender, eventArgs) => _cache.Save();
|
||||||
|
|
||||||
_playerIdentity = new PlayerIdentity(_cache);
|
_playerIdentity = new PlayerIdentity(_cache);
|
||||||
_minimapCache = new BigMinimapCache(_cache, _properties.RA3Directory);
|
_minimapCache = new BigMinimapCache(_cache, _properties.RA3Directory);
|
||||||
_minimapReader = new MinimapReader(_minimapCache, _properties.RA3Directory, _properties.CustomMapsDirectory, _properties.ModsDirectory);
|
_minimapReader = new MinimapReader(_minimapCache, _properties.RA3Directory, _properties.CustomMapsDirectory, _properties.ModsDirectory);
|
||||||
|
|
||||||
LoadReplays();
|
LoadReplays();
|
||||||
_ = AutoSaveReplays();
|
Task.Run(() => AutoSaveReplays(Dispatcher, _properties.RA3ReplayFolderPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AutoSaveReplays()
|
private static async Task AutoSaveReplays(Dispatcher dispatcher, string replayFolderPath)
|
||||||
{
|
{
|
||||||
const string ourPrefix = "自动保存";
|
const string ourPrefix = "自动保存";
|
||||||
var errorMessageCount = 0;
|
var errorMessageCount = 0;
|
||||||
@ -155,7 +156,7 @@ namespace AnotherReplayReader
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var changed = (from fileName in Directory.GetFiles(_properties.RA3ReplayFolderPath, "*.RA3Replay")
|
var changed = (from fileName in Directory.GetFiles(replayFolderPath, "*.RA3Replay")
|
||||||
let info = new FileInfo(fileName)
|
let info = new FileInfo(fileName)
|
||||||
where !info.Name.StartsWith(ourPrefix)
|
where !info.Name.StartsWith(ourPrefix)
|
||||||
where !previousFiles.ContainsKey(info.FullName) || previousFiles[info.FullName] != info.LastWriteTimeUtc
|
where !previousFiles.ContainsKey(info.FullName) || previousFiles[info.FullName] != info.LastWriteTimeUtc
|
||||||
@ -238,7 +239,7 @@ namespace AnotherReplayReader
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dateString = $"{date.Year}{date.Month:D2}{date.Day:D2}_{date.Hour:D2}{date.Minute:D2}{date.Second:D2}";
|
var dateString = $"{date.Year}{date.Month:D2}{date.Day:D2}_{date.Hour:D2}{date.Minute:D2}{date.Second:D2}";
|
||||||
var destinationPath = Path.Combine(_properties.RA3ReplayFolderPath, $"{ourPrefix}-{playerString}{dateString}.RA3Replay");
|
var destinationPath = Path.Combine(replayFolderPath, $"{ourPrefix}-{playerString}{dateString}.RA3Replay");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.Copy(replay.Path, destinationPath, true);
|
File.Copy(replay.Path, destinationPath, true);
|
||||||
@ -253,20 +254,20 @@ namespace AnotherReplayReader
|
|||||||
{
|
{
|
||||||
var errorString = $"自动保存录像时出现错误:\r\n{e}\r\n";
|
var errorString = $"自动保存录像时出现错误:\r\n{e}\r\n";
|
||||||
Debug.Instance.DebugMessage += errorString;
|
Debug.Instance.DebugMessage += errorString;
|
||||||
_ = Dispatcher.InvokeAsync(() =>
|
if (Interlocked.Increment(ref errorMessageCount) == 1)
|
||||||
{
|
{
|
||||||
try
|
_ = dispatcher.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
if (Interlocked.Increment(ref errorMessageCount) == 1)
|
try
|
||||||
{
|
{
|
||||||
MessageBox.Show(errorString);
|
MessageBox.Show(errorString);
|
||||||
}
|
}
|
||||||
}
|
finally
|
||||||
finally
|
{
|
||||||
{
|
Interlocked.Decrement(ref errorMessageCount);
|
||||||
Interlocked.Decrement(ref errorMessageCount);
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(10 * 1000);
|
await Task.Delay(10 * 1000);
|
||||||
@ -275,66 +276,59 @@ namespace AnotherReplayReader
|
|||||||
|
|
||||||
private async void LoadReplays(string nextSelected = null)
|
private async void LoadReplays(string nextSelected = null)
|
||||||
{
|
{
|
||||||
const string loadingString = "正在加载录像列表,请稍候";
|
const string loadingString = "正在加载录像列表,请稍候… 已加载 {0} 个录像";
|
||||||
|
|
||||||
Dispatcher.Invoke(() =>
|
|
||||||
{
|
|
||||||
if (_image != null)
|
|
||||||
{
|
|
||||||
_image.Source = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_dataGrid != null)
|
|
||||||
{
|
|
||||||
_dataGrid.Items.Clear();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_loadReplaysToken?.Cancel();
|
|
||||||
_loadReplaysToken = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var cancelToken = _loadReplaysToken.Token;
|
|
||||||
var path = _properties.ReplayFolderPath;
|
|
||||||
var task = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var messages = "";
|
|
||||||
var replayList = new List<Replay>();
|
|
||||||
|
|
||||||
if (!Directory.Exists(path))
|
|
||||||
{
|
|
||||||
messages = "这个文件夹并不存在。";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var replays = Directory.EnumerateFiles(path, "*.RA3Replay");
|
|
||||||
foreach (var replayPath in replays)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var replay = await Task.Run(() => new Replay(replayPath));
|
|
||||||
replayList.Add(replay);
|
|
||||||
_properties.ReplayDetails = loadingString + $"\n已加载 {replayList.Count} 个录像";
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
Debug.Instance.DebugMessage += $"Uncaught exception when loading replay list: \r\n{exception}\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelToken.ThrowIfCancellationRequested();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new { Replays = replayList, Messages = messages };
|
|
||||||
});
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await task;
|
_loadReplaysToken?.Cancel();
|
||||||
_replayList = result.Replays;
|
|
||||||
cancelToken.ThrowIfCancellationRequested();
|
|
||||||
DisplayReplays(result.Messages, nextSelected);
|
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException) { }
|
catch (AggregateException e)
|
||||||
|
{
|
||||||
|
Debug.Instance.DebugMessage += $"Cancellation failed: {e}";
|
||||||
|
}
|
||||||
|
_loadReplaysToken?.Dispose();
|
||||||
|
_loadReplaysToken = new CancellationTokenSource();
|
||||||
|
var cancelToken = _loadReplaysToken.Token;
|
||||||
|
var path = _properties.ReplayFolderPath;
|
||||||
|
|
||||||
|
if (_image != null)
|
||||||
|
{
|
||||||
|
_image.Source = null;
|
||||||
|
}
|
||||||
|
_dataGrid?.Items.Clear();
|
||||||
|
_replayList.Clear();
|
||||||
|
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
{
|
||||||
|
DisplayReplays("这个文件夹并不存在。", nextSelected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newList = await Task.Run(() =>
|
||||||
|
{
|
||||||
|
var list = new List<Replay>();
|
||||||
|
foreach (var replayPath in Directory.EnumerateFiles(path, "*.RA3Replay"))
|
||||||
|
{
|
||||||
|
if (cancelToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
list.Add(new Replay(replayPath));
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Debug.Instance.DebugMessage += $"Uncaught exception when loading replay list: \r\n{exception}\r\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ = Dispatcher.Invoke(() => _properties.ReplayDetails = string.Format(loadingString, _replayList.Count));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
|
||||||
|
_replayList.AddRange(newList);
|
||||||
|
DisplayReplays(string.Empty, nextSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisplayReplays(string message = null, string nextSelected = null)
|
private void DisplayReplays(string message = null, string nextSelected = null)
|
||||||
@ -351,13 +345,7 @@ namespace AnotherReplayReader
|
|||||||
{
|
{
|
||||||
for (var i = 0; i < _dataGrid.Items.Count; ++i)
|
for (var i = 0; i < _dataGrid.Items.Count; ++i)
|
||||||
{
|
{
|
||||||
var replay = _dataGrid.Items[i] as Replay;
|
if (_dataGrid.Items[i] is Replay replay && replay.Path.Equals(nextSelected, StringComparison.OrdinalIgnoreCase))
|
||||||
if (replay == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (replay.Path.Equals(nextSelected, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
_dataGrid.SelectedIndex = i;
|
_dataGrid.SelectedIndex = i;
|
||||||
OnReplaySelectionChanged(null, null);
|
OnReplaySelectionChanged(null, null);
|
||||||
@ -533,5 +521,10 @@ namespace AnotherReplayReader
|
|||||||
|
|
||||||
LoadReplays();
|
LoadReplays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ReplayFilterBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
95
autosave.txt
95
autosave.txt
@ -1,95 +0,0 @@
|
|||||||
private async Task AutoSaveReplays()
|
|
||||||
{
|
|
||||||
const string ourPrefix = "自动保存";
|
|
||||||
|
|
||||||
// filename and last write time
|
|
||||||
Dictionary<string, DateTime> previousFiles = new Dictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
// filename and file size
|
|
||||||
Dictionary<string, long> lastReplays = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var changed = from fileName in Directory.GetFiles(_properties.ReplayFolderPath, "*.RA3Replay")
|
|
||||||
let info = new FileInfo(fileName)
|
|
||||||
where !info.Name.StartsWith(ourPrefix)
|
|
||||||
where !previousFiles.ContainsKey(info.FullName) || previousFiles[info.FullName] != info.LastWriteTimeUtc
|
|
||||||
select info;
|
|
||||||
|
|
||||||
foreach (var info in changed)
|
|
||||||
{
|
|
||||||
previousFiles[info.FullName] = info.LastWriteTimeUtc;
|
|
||||||
}
|
|
||||||
|
|
||||||
var replays = changed.Select(info =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return new Replay(info.FullName);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}).Where(replay => replay != null);
|
|
||||||
|
|
||||||
var newLastReplays = from replay in replays
|
|
||||||
let threshold = Math.Abs((DateTime.UtcNow - replay.Date).TotalSeconds)
|
|
||||||
where threshold < 20
|
|
||||||
select replay;
|
|
||||||
|
|
||||||
var toBeChecked = newLastReplays.ToDictionary(replay => replay.FileName, StringComparer.OrdinalIgnoreCase);
|
|
||||||
foreach (var savedLastReplay in lastReplays)
|
|
||||||
{
|
|
||||||
if (!toBeChecked.ContainsKey(savedLastReplay.Key))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
toBeChecked.Add(savedLastReplay.Key, new Replay(savedLastReplay.Key));
|
|
||||||
}
|
|
||||||
catch(Exception)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var kv in toBeChecked)
|
|
||||||
{
|
|
||||||
var replay = kv.Value;
|
|
||||||
if (lastReplays.TryGetValue(kv.Key, out var fileSize))
|
|
||||||
{
|
|
||||||
if (fileSize == replay.Size)
|
|
||||||
{
|
|
||||||
// skip if size is not changed
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastReplays[kv.Key] = replay.Size;
|
|
||||||
|
|
||||||
var date = replay.Date;
|
|
||||||
var numberOfPlayers = replay.NumberOfPlayingPlayers;
|
|
||||||
var playerString = $"{numberOfPlayers}名玩家";
|
|
||||||
if (replay.NumberOfPlayingPlayers <= 2)
|
|
||||||
{
|
|
||||||
var playingPlayers = from player in replay.Players
|
|
||||||
let faction = ModData.GetFaction(replay.Mod, player.FactionID)
|
|
||||||
where faction.Kind != FactionKind.Observer
|
|
||||||
select $"{player}({faction.Name})";
|
|
||||||
playerString = playingPlayers.Aggregate((x, y) => x + y);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dateString = $"{date.Year}-{date.Month}-{date.Day}_{date.Hour}:{date.Minute}";
|
|
||||||
|
|
||||||
File.Copy(replay.FileName, $"{_properties.ReplayFolderPath}/{ourPrefix}-{playerString}{dateString}.RA3Replay");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
_ = Dispatcher.InvokeAsync(() => MessageBox.Show($"自动保存录像时出现错误:\r\n{e}"));
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(10 * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user