rft: 小游戏界面重构,添加分类并优化选择逻辑,添加日志显示 (#16499)

* rft: 小游戏界面重构,添加分类并优化选择逻辑,添加日志显示

* chore: 修复格式化问题和误删注释

* chore: 重命名小游戏

* fix: 不再硬编码日志内容

* i18n: EN

* i18n: zh-tw

---------

Co-authored-by: Constrat <56174894+Constrat@users.noreply.github.com>
Co-authored-by: momomochi987 <45387477+momomochi987@users.noreply.github.com>
This commit is contained in:
SherkeyXD
2026-05-13 19:18:32 +08:00
committed by GitHub
parent 5e78b23157
commit a105eccd05
7 changed files with 264 additions and 59 deletions

View File

@@ -718,7 +718,9 @@ If the game is launched in portrait mode and then switched to landscape, it may
<system:String x:Key="Roguelike">{key=AutoRoguelike}</system:String>
<system:String x:Key="Reclamation">Reclamation Algorithm</system:String>
<system:String x:Key="UserDataUpdate">Update Doctor Data</system:String>
<system:String x:Key="MiniGame">Mini-Games</system:String>
<system:String x:Key="MiniGame">Useful Tasks</system:String>
<system:String x:Key="MiniGameCategoryPermanent">Permanent</system:String>
<system:String x:Key="MiniGameCategoryCurrentEvent">Current Events</system:String>
<system:String x:Key="Custom">Custom Task</system:String>
<system:String x:Key="SingleStep">Single-Step Task</system:String>
<system:String x:Key="ReclamationTheme">Reclamation Algorithm Theme</system:String>

View File

@@ -719,7 +719,9 @@ C:\\leidian\\LDPlayer9
<system:String x:Key="Roguelike">{key=AutoRoguelike}</system:String>
<system:String x:Key="Reclamation">生息演算</system:String>
<system:String x:Key="UserDataUpdate">ユーザーデータ更新</system:String>
<system:String x:Key="MiniGame">ミニゲーム</system:String>
<system:String x:Key="MiniGame">便利機能</system:String>
<system:String x:Key="MiniGameCategoryPermanent">常設</system:String>
<system:String x:Key="MiniGameCategoryCurrentEvent">現在のイベント</system:String>
<system:String x:Key="Custom">カスタムタスク</system:String>
<system:String x:Key="SingleStep">単一ステップタスク</system:String>
<system:String x:Key="ReclamationTheme">主題</system:String>

View File

@@ -720,7 +720,9 @@ C:\\leidian\\LDPlayer9
<system:String x:Key="Roguelike">{key=AutoRoguelike}</system:String>
<system:String x:Key="Reclamation">생존 연산</system:String>
<system:String x:Key="UserDataUpdate">사용자 데이터 업데이트</system:String>
<system:String x:Key="MiniGame">미니게임</system:String>
<system:String x:Key="MiniGame">편의 기능</system:String>
<system:String x:Key="MiniGameCategoryPermanent">상시</system:String>
<system:String x:Key="MiniGameCategoryCurrentEvent">현재 이벤트</system:String>
<system:String x:Key="Custom">커스텀 작업</system:String>
<system:String x:Key="SingleStep">단일 단계 작업</system:String>
<system:String x:Key="ReclamationTheme">생존 연산 테마</system:String>

View File

@@ -719,7 +719,9 @@ C:\\leidian\\LDPlayer9。\n
<system:String x:Key="Roguelike">{key=AutoRoguelike}</system:String>
<system:String x:Key="Reclamation">生息演算</system:String>
<system:String x:Key="UserDataUpdate">更新数据</system:String>
<system:String x:Key="MiniGame">小游戏</system:String>
<system:String x:Key="MiniGame">便捷功能</system:String>
<system:String x:Key="MiniGameCategoryPermanent">常驻活动</system:String>
<system:String x:Key="MiniGameCategoryCurrentEvent">当期活动</system:String>
<system:String x:Key="Custom">自定任务</system:String>
<system:String x:Key="SingleStep">单步任务</system:String>
<system:String x:Key="ReclamationTheme">生息演算主题</system:String>

View File

@@ -719,7 +719,9 @@ C:\\leidian\\LDPlayer9\n
<system:String x:Key="Roguelike">{key=AutoRoguelike}</system:String>
<system:String x:Key="Reclamation">生息演算</system:String>
<system:String x:Key="UserDataUpdate">更新使用者資料</system:String>
<system:String x:Key="MiniGame">小遊戲</system:String>
<system:String x:Key="MiniGame">快捷功能</system:String>
<system:String x:Key="MiniGameCategoryPermanent">常駐</system:String>
<system:String x:Key="MiniGameCategoryCurrentEvent">目前活動</system:String>
<system:String x:Key="Custom">自定義任務</system:String>
<system:String x:Key="SingleStep">單步任務</system:String>
<system:String x:Key="ReclamationTheme">生息演算主題</system:String>

View File

@@ -2079,20 +2079,74 @@ public class ToolboxViewModel : Screen
#region MiniGame
public static ObservableCollection<MiniGameEntry> MiniGameTaskList { get; } = [];
public class MiniGameCategoryItem : PropertyChangedBase
{
public string Display { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
public string Category { get; set; } = string.Empty;
public bool IsSecretFront => Value == "MiniGame@SecretFront";
}
public ObservableCollection<MiniGameCategoryItem> MiniGameCategoryItems { get; } = [];
private MiniGameCategoryItem? _selectedMiniGameItem;
public MiniGameCategoryItem? SelectedMiniGameItem
{
get => _selectedMiniGameItem;
set {
if (!SetAndNotify(ref _selectedMiniGameItem, value) || value == null)
{
return;
}
MiniGameTaskName = value.Value;
ClearMiniGameLogs();
}
}
public static void UpdateMiniGameTaskList()
{
var tasks = Instances.StageManager.MiniGameEntries
.Select(t => new MiniGameEntry { Display = t.Display, DisplayKey = t.DisplayKey, Value = t.Value, Tip = t.Tip, TipKey = t.TipKey })
var categorizedItems = Instances.StageManager.MiniGameEntries
.Select(t =>
{
var isCurrentEvent = t.UtcStartTime != DateTime.MinValue || t.UtcExpireTime != DateTime.MinValue;
var category = LocalizationHelper.GetString(isCurrentEvent
? "MiniGameCategoryCurrentEvent"
: "MiniGameCategoryPermanent");
return new MiniGameCategoryItem
{
Display = string.IsNullOrEmpty(t.DisplayKey)
? t.Display
: (LocalizationHelper.TryGetString(t.DisplayKey, out var loc) ? loc : t.Display),
Value = t.Value,
Category = category,
};
})
.ToList();
Execute.OnUIThread(() => {
MiniGameTaskList.Clear();
foreach (var task in tasks)
Execute.OnUIThread(() =>
{
var toolbox = Instances.ToolboxViewModel;
if (toolbox == null)
{
MiniGameTaskList.Add(task);
return;
}
var prevSelected = toolbox.SelectedMiniGameItem?.Value;
toolbox.MiniGameCategoryItems.Clear();
foreach (var item in categorizedItems)
{
toolbox.MiniGameCategoryItems.Add(item);
}
toolbox.SelectedMiniGameItem = toolbox.MiniGameCategoryItems
.FirstOrDefault(i => i.Value == prevSelected)
?? toolbox.MiniGameCategoryItems.FirstOrDefault();
});
}
@@ -2110,7 +2164,8 @@ public class ToolboxViewModel : Screen
public string GetMiniGameTask()
{
return MiniGameTaskName switch {
return MiniGameTaskName switch
{
"MiniGame@SecretFront" => $"{MiniGameTaskName}@Begin@Ending{SecretFrontEnding}{(string.IsNullOrEmpty(SecretFrontEvent) ? string.Empty : $"@{SecretFrontEvent}")}",
_ => MiniGameTaskName,
};
@@ -2189,7 +2244,8 @@ public class ToolboxViewModel : Screen
}
}
public List<GenericCombinedData<string>> SecretFrontEventList { get; set; } = [
public List<GenericCombinedData<string>> SecretFrontEventList { get; set; } =
[
new GenericCombinedData<string> { Display = LocalizationHelper.GetString("NotSelected"), Value = string.Empty },
new GenericCombinedData<string> { Display = LocalizationHelper.GetString("MiniGame@SecretFront@Event1"), Value = "支援作战平台" },
new GenericCombinedData<string> { Display = LocalizationHelper.GetString("MiniGame@SecretFront@Event2"), Value = "游侠" },
@@ -2207,6 +2263,35 @@ public class ToolboxViewModel : Screen
}
}
public class MiniGameLogItem : PropertyChangedBase
{
public string Time { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public string Color { get; set; } = UiLogColor.Info;
}
public ObservableCollection<MiniGameLogItem> MiniGameLogs { get; } = [];
public void AddMiniGameLog(string content, string color = UiLogColor.Info)
{
Execute.OnUIThread(() =>
{
MiniGameLogs.Add(new MiniGameLogItem
{
Time = DateTime.Now.ToString("HH:mm:ss"),
Content = content,
Color = color,
});
});
}
public void ClearMiniGameLogs()
{
Execute.OnUIThread(() => MiniGameLogs.Clear());
}
public void StartMiniGame()
{
_ = StartMiniGameAsync();
@@ -2221,10 +2306,14 @@ public class ToolboxViewModel : Screen
}
_runningState.SetIdle(false);
ClearMiniGameLogs();
AddMiniGameLog(LocalizationHelper.GetString("ConnectingToEmulator"), UiLogColor.Message);
string errMsg = string.Empty;
bool caught = await Task.Run(() => Instances.AsstProxy.AsstConnect(ref errMsg));
if (!caught)
{
AddMiniGameLog(errMsg, UiLogColor.Error);
_runningState.SetIdle(true);
return;
}

View File

@@ -8,6 +8,7 @@
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:helper="clr-namespace:MaaWpfGui.Helper"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:properties="clr-namespace:MaaWpfGui.Styles.Properties"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:uiBehaviors="clr-namespace:MaaWpfGui.Extensions.UIBehaviors"
xmlns:ui_vms="clr-namespace:MaaWpfGui.ViewModels.UI"
@@ -828,52 +829,157 @@
</Grid>
</TabItem>
<TabItem Header="{DynamicResource MiniGame}">
<Grid Margin="20,0,20,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<ComboBox
Margin="10,0"
hc:TitleElement.Title="{DynamicResource MiniGameName}"
DisplayMemberPath="Display"
IsEnabled="{Binding Idle}"
ItemsSource="{Binding MiniGameTaskList}"
SelectedValue="{Binding MiniGameTaskName}"
SelectedValuePath="Value" />
<Grid Grid.Row="1" IsEnabled="{Binding Idle}">
<Grid Visibility="{c:Binding 'MiniGameTaskName == &quot;MiniGame@SecretFront&quot;'}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ComboBox
Margin="10,10,10,0"
hc:TitleElement.Title="{DynamicResource MiniGame@SecretFront@Ending}"
ItemsSource="{Binding SecretFrontEndingList}"
SelectedValue="{Binding SecretFrontEnding}" />
<ComboBox
Grid.Row="1"
Margin="10,10,10,0"
hc:TitleElement.Title="{DynamicResource MiniGame@SecretFront@Event}"
DisplayMemberPath="Display"
ItemsSource="{Binding SecretFrontEventList}"
SelectedValue="{Binding SecretFrontEvent}"
SelectedValuePath="Value" />
</Grid>
<Grid Margin="20,0,20,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.Resources>
<CollectionViewSource x:Key="CategorizedMiniGames" Source="{Binding MiniGameCategoryItems}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Category" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Grid.Resources>
<Border
Grid.Row="0"
Background="{DynamicResource RegionBrushOpacity25}"
BorderBrush="{DynamicResource BorderBrush}"
BorderThickness="1"
CornerRadius="4">
<ListBox
Margin="0"
Background="Transparent"
BorderThickness="0"
IsEnabled="{Binding Idle}"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Source={StaticResource CategorizedMiniGames}}"
SelectedItem="{Binding SelectedMiniGameItem}"
Style="{StaticResource MaaListBoxDefaultStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock
Margin="5,0"
Text="{Binding Display}"
TextTrimming="CharacterEllipsis" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Border
Padding="8,4"
Background="{DynamicResource RegionBrushOpacity50}"
BorderBrush="{DynamicResource BorderBrush}"
BorderThickness="0,0,0,1">
<controls:TextBlock FontWeight="Bold" Text="{Binding Name}" />
</Border>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
</ListBox>
</Border>
<Button
Grid.Row="1"
Width="160"
Height="60"
Margin="0,20,0,0"
HorizontalAlignment="Center"
Command="{s:Action StartMiniGame}"
Content="{c:Binding 'Idle ? &quot;Link Start!&quot; : &quot;Stop!&quot;'}"
IsEnabled="{c:Binding 'Inited and !Stopping'}" />
</Grid>
<Grid Grid.Column="1" Margin="50,50,30,10" IsEnabled="{Binding Idle}" VerticalAlignment="Top">
<Grid Visibility="{c:Binding 'SelectedMiniGameItem != null'}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Visibility="{c:Binding 'SelectedMiniGameItem.IsSecretFront'}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ComboBox
Margin="10,0,10,0"
hc:TitleElement.Title="{DynamicResource MiniGame@SecretFront@Ending}"
ItemsSource="{Binding SecretFrontEndingList}"
SelectedValue="{Binding SecretFrontEnding}" />
<ComboBox
Grid.Row="1"
Margin="10,10,10,10"
hc:TitleElement.Title="{DynamicResource MiniGame@SecretFront@Event}"
DisplayMemberPath="Display"
ItemsSource="{Binding SecretFrontEventList}"
SelectedValue="{Binding SecretFrontEvent}"
SelectedValuePath="Value" />
</Grid>
<controls:TextBlock
Grid.Row="1"
Margin="10,0,10,10"
Text="{Binding MiniGameTip}"
TextWrapping="Wrap" />
</Grid>
</Grid>
<Grid
Grid.Column="2"
Margin="10,10,0,10"
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<hc:ScrollViewer
Grid.Row="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
properties:AutoScroll.AutoScroll="True"
HorizontalScrollBarVisibility="Disabled"
IsInertiaEnabled="True"
PanningMode="Both">
<Grid>
<ItemsControl
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding MiniGameLogs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<controls:TextBlock
Grid.Column="0"
Margin="0,5,10,5"
VerticalAlignment="Top"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding Time}" />
<Grid
Grid.Column="1"
Margin="0,5"
HorizontalAlignment="Left">
<controls:TextBlock
ForegroundKey="{Binding Color}"
Text="{Binding Content}"
TextWrapping="Wrap" />
</Grid>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</hc:ScrollViewer>
</Grid>
<controls:TextBlock Grid.Row="2" Text="{Binding MiniGameTip}" />
<Button
Grid.Row="3"
Width="100"
Height="50"
Margin="10"
Command="{s:Action StartMiniGame}"
Content="{c:Binding 'Idle ? &quot;Link Start!&quot; : &quot;Stop!&quot;'}"
IsEnabled="{c:Binding 'Inited and !Stopping'}" />
</Grid>
</TabItem>
</TabControl>