Files
NebulaLauncher/Nebula.Launcher/ViewModels/ServerEntryModelView.cs

289 lines
8.6 KiB
C#
Raw Normal View History

2024-12-27 19:15:33 +03:00
using System;
using System.Collections.Generic;
2025-01-17 16:23:50 +03:00
using System.Collections.ObjectModel;
using System.Linq;
2025-01-08 18:00:06 +03:00
using System.Threading.Tasks;
2025-01-27 15:55:30 +03:00
using System.Windows.Input;
using Avalonia.Controls;
2025-01-17 16:23:50 +03:00
using CommunityToolkit.Mvvm.ComponentModel;
2025-06-17 21:07:32 +03:00
using Nebula.Launcher.ProcessHelper;
using Nebula.Launcher.ServerListProviders;
2025-01-14 22:10:16 +03:00
using Nebula.Launcher.Services;
using Nebula.Launcher.ViewModels.Pages;
2025-01-14 22:10:16 +03:00
using Nebula.Launcher.ViewModels.Popup;
2025-01-16 21:07:50 +03:00
using Nebula.Launcher.Views;
2025-01-05 17:05:23 +03:00
using Nebula.Shared.Models;
2025-01-07 17:01:00 +03:00
using Nebula.Shared.Services;
using Nebula.Shared.Services.Logging;
2025-01-17 16:23:50 +03:00
using Nebula.Shared.Utils;
2024-12-27 19:15:33 +03:00
namespace Nebula.Launcher.ViewModels;
[ViewModelRegister(typeof(ServerEntryView), false)]
2025-01-14 22:10:16 +03:00
[ConstructGenerator]
public partial class ServerEntryModelView : ViewModelBase, IFilterConsumer
2024-12-27 19:15:33 +03:00
{
[ObservableProperty] private string _description = "Fetching info...";
[ObservableProperty] private bool _expandInfo;
[ObservableProperty] private bool _isFavorite;
[ObservableProperty] private bool _isVisible;
2025-06-17 21:07:32 +03:00
[ObservableProperty] private bool _runVisible = true;
private ILogger _logger;
2025-06-17 21:07:32 +03:00
private bool _isStatusFromHub;
private ServerInfo? _serverInfo;
2025-06-17 21:07:32 +03:00
private ContentLogConsumer _currentContentLogConsumer;
private ProcessRunHandler<GameProcessStartInfoProvider>? _currentInstance;
[ObservableProperty] private bool _tagDataVisible;
2025-01-14 22:10:16 +03:00
public LogPopupModelView CurrLog;
public RobustUrl Address { get; private set; }
[GenerateProperty] private ConfigurationService ConfigurationService { get; } = default!;
2025-01-14 22:10:16 +03:00
[GenerateProperty] private CancellationService CancellationService { get; } = default!;
[GenerateProperty] private DebugService DebugService { get; } = default!;
[GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!;
[GenerateProperty] private ViewHelperService ViewHelperService { get; } = default!;
2025-01-17 16:23:50 +03:00
[GenerateProperty] private RestService RestService { get; } = default!;
[GenerateProperty] private MainViewModel MainViewModel { get; } = default!;
[GenerateProperty] private FavoriteServerListProvider FavoriteServerListProvider { get; } = default!;
2025-06-17 21:07:32 +03:00
[GenerateProperty] private GameRunnerPreparer GameRunnerPreparer { get; } = default!;
public ServerStatus Status { get; private set; } =
new(
"Fetching data...",
"Loading...", [],
"",
-1,
-1,
-1,
2025-02-01 13:13:49 +03:00
false,
DateTime.Now,
-1
);
2025-01-28 19:59:35 +03:00
public ObservableCollection<ServerLink> Links { get; } = new();
public ObservableCollection<string> Tags { get; } = [];
public ICommand OnLinkGo { get; } = new LinkGoCommand();
2025-01-17 16:23:50 +03:00
public async Task<ServerInfo?> GetServerInfo()
{
if (_serverInfo == null)
2025-01-29 12:32:42 +03:00
try
{
2025-01-30 20:18:40 +03:00
_serverInfo = await RestService.GetAsync<ServerInfo>(Address.InfoUri, CancellationService.Token);
2025-01-29 12:32:42 +03:00
}
catch (Exception e)
{
Description = e.Message;
_logger.Error(e);
2025-01-29 12:32:42 +03:00
}
2025-01-17 16:23:50 +03:00
return _serverInfo;
}
2025-01-14 22:10:16 +03:00
protected override void InitialiseInDesignMode()
2025-01-05 17:05:23 +03:00
{
2025-01-17 16:23:50 +03:00
Description = "Server of meow girls! Nya~ \nNyaMeow\nOOOINK!!";
Links.Add(new ServerLink("Discord", "discord", "https://cinka.ru"));
2025-01-28 19:59:35 +03:00
Status = new ServerStatus("Ameba",
"Locala meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow meow ",
["rp:hrp", "18+"],
"Antag", 15, 5, 1, false
, DateTime.Now, 100);
Address = "ss14://localhost".ToRobustUrl();
2025-01-05 17:05:23 +03:00
}
2024-12-27 19:15:33 +03:00
2025-01-14 22:10:16 +03:00
protected override void Initialise()
2025-01-05 17:05:23 +03:00
{
_logger = DebugService.GetLogger(this);
2025-01-14 22:10:16 +03:00
CurrLog = ViewHelperService.GetViewModel<LogPopupModelView>();
2025-06-17 21:07:32 +03:00
_currentContentLogConsumer = new(CurrLog, PopupMessageService);
2025-01-07 19:14:42 +03:00
}
2025-01-07 17:01:00 +03:00
public void ProcessFilter(ServerFilter? serverFilter)
{
if (serverFilter == null)
{
IsVisible = true;
return;
}
IsVisible = serverFilter.IsMatch(Status.Name, Tags);
}
2025-02-01 13:13:49 +03:00
public void SetStatus(ServerStatus serverStatus)
2025-01-28 19:59:35 +03:00
{
Status = serverStatus;
Tags.Clear();
foreach (var tag in Status.Tags) Tags.Add(tag);
2025-02-01 13:13:49 +03:00
OnPropertyChanged(nameof(Status));
}
2025-06-17 21:07:32 +03:00
public void UpdateStatusIfNecessary()
{
if(_isStatusFromHub) return;
FetchStatus();
}
2025-02-01 13:13:49 +03:00
public ServerEntryModelView WithData(RobustUrl url, ServerStatus? serverStatus)
{
Address = url;
2025-06-17 21:07:32 +03:00
_isStatusFromHub = serverStatus is not null;
if (_isStatusFromHub)
SetStatus(serverStatus!);
2025-02-01 13:13:49 +03:00
else
FetchStatus();
IsFavorite = GetFavoriteEntries().Contains(Address.ToString());
2025-01-28 19:59:35 +03:00
return this;
}
private List<string> GetFavoriteEntries()
{
return ConfigurationService.GetConfigValue(LauncherConVar.Favorites)?.ToList() ?? [];
}
2025-02-01 13:13:49 +03:00
private async void FetchStatus()
{
try
{
SetStatus(await RestService.GetAsync<ServerStatus>(Address.StatusUri, CancellationService.Token));
}
catch (Exception e)
{
_logger.Error(e);
2025-02-01 13:13:49 +03:00
Status = new ServerStatus("ErrorLand", $"ERROR: {e.Message}", [], "", -1, -1, -1, false,
DateTime.Now,
-1);
}
}
public void OpenContentViewer()
{
MainViewModel.RequirePage<ContentBrowserViewModel>().Go(Address, ContentPath.Empty);
}
2025-01-28 19:59:35 +03:00
public void ToggleFavorites()
{
IsFavorite = !IsFavorite;
if(IsFavorite)
FavoriteServerListProvider.AddFavorite(this);
else
FavoriteServerListProvider.RemoveFavorite(this);
2025-01-28 19:59:35 +03:00
}
2025-01-08 18:00:06 +03:00
public void RunInstance()
2025-06-17 21:07:32 +03:00
{
CurrLog.Clear();
Task.Run(RunInstanceAsync);
2025-01-08 18:00:06 +03:00
}
2025-01-07 17:01:00 +03:00
2025-06-17 21:07:32 +03:00
private async void RunInstanceAsync()
2025-01-08 18:00:06 +03:00
{
2025-06-17 21:07:32 +03:00
using var loadingContext = ViewHelperService.GetViewModel<LoadingContextViewModel>();
loadingContext.LoadingName = "Loading instance...";
((ILoadingHandler)loadingContext).AppendJob();
2025-01-14 22:10:16 +03:00
2025-06-17 21:07:32 +03:00
PopupMessageService.Popup(loadingContext);
_currentInstance =
await GameRunnerPreparer.GetGameProcessStartInfoProvider(Address, loadingContext, CancellationService.Token);
2025-06-17 21:07:32 +03:00
_currentInstance.RegisterLogger(_currentContentLogConsumer);
_currentInstance.RegisterLogger(new DebugLoggerBridge(DebugService.GetLogger($"PROCESS_{Random.Shared.Next(65535)}")));
_currentInstance.OnProcessExited += OnProcessExited;
RunVisible = false;
_currentInstance.Start();
2025-01-05 17:05:23 +03:00
}
2025-01-07 17:01:00 +03:00
2025-06-17 21:07:32 +03:00
private void OnProcessExited(ProcessRunHandler<GameProcessStartInfoProvider> obj)
2025-01-07 17:01:00 +03:00
{
2025-06-17 21:07:32 +03:00
RunVisible = true;
if (_currentInstance == null) return;
2025-06-17 21:07:32 +03:00
_currentInstance.OnProcessExited -= OnProcessExited;
_currentInstance.Dispose();
_currentInstance = null;
2025-01-07 17:01:00 +03:00
}
2025-06-17 21:07:32 +03:00
public void StopInstance()
2025-01-07 17:01:00 +03:00
{
2025-06-17 21:07:32 +03:00
_currentInstance?.Stop();
2025-01-07 17:01:00 +03:00
}
2025-06-17 21:07:32 +03:00
2025-01-05 17:05:23 +03:00
public void ReadLog()
2024-12-27 19:15:33 +03:00
{
2025-01-14 22:10:16 +03:00
PopupMessageService.Popup(CurrLog);
2024-12-27 19:15:33 +03:00
}
2025-01-17 16:23:50 +03:00
public async void ExpandInfoRequired()
{
ExpandInfo = !ExpandInfo;
if (Design.IsDesignMode) return;
2025-01-17 16:23:50 +03:00
var info = await GetServerInfo();
if (info == null) return;
2025-01-27 15:55:30 +03:00
Description = info.Desc;
Links.Clear();
if (info.Links is null) return;
foreach (var link in info.Links) Links.Add(link);
2025-01-17 16:23:50 +03:00
}
2025-01-07 19:14:42 +03:00
}
2025-06-17 21:07:32 +03:00
public sealed class ContentLogConsumer : IProcessLogConsumer
2025-01-07 19:14:42 +03:00
{
2025-06-17 21:07:32 +03:00
private readonly LogPopupModelView _currLog;
private readonly PopupMessageService _popupMessageService;
2025-01-07 19:14:42 +03:00
2025-06-17 21:07:32 +03:00
public ContentLogConsumer(LogPopupModelView currLog, PopupMessageService popupMessageService)
2025-01-07 19:14:42 +03:00
{
2025-06-17 21:07:32 +03:00
_currLog = currLog;
_popupMessageService = popupMessageService;
}
2025-01-07 19:14:42 +03:00
2025-06-17 21:07:32 +03:00
public void Out(string text)
{
_currLog.Append(text);
}
2025-01-07 19:14:42 +03:00
2025-06-17 21:07:32 +03:00
public void Error(string text)
{
_currLog.Append(text);
}
2025-01-14 22:10:16 +03:00
2025-06-17 21:07:32 +03:00
public void Fatal(string text)
{
_popupMessageService.Popup("Fatal error while stop instance:" + text);
2025-01-07 19:14:42 +03:00
}
2025-01-27 15:55:30 +03:00
}
2025-06-17 21:07:32 +03:00
2025-01-27 15:55:30 +03:00
public class LinkGoCommand : ICommand
{
public LinkGoCommand()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
2025-01-27 15:55:30 +03:00
public bool CanExecute(object? parameter)
{
return true;
}
public void Execute(object? parameter)
{
if (parameter is not string str) return;
2025-01-27 15:55:30 +03:00
Helper.SafeOpenBrowser(str);
}
public event EventHandler? CanExecuteChanged;
}
public interface IFilterConsumer
{
public void ProcessFilter(ServerFilter? serverFilter);
2024-12-27 19:15:33 +03:00
}