~ruther/NosTale-PacketLogger

088a47056fb85ff7330ec09dc90241e7016c9cd8 — Rutherther 2 years ago ecad72b
feat: add client closed indicator
M src/PacketLogger/Models/NostaleProcess.cs => src/PacketLogger/Models/NostaleProcess.cs +11 -0
@@ 56,12 56,23 @@ public class NostaleProcess : ObservableObject
    public NosBrowserManager BrowserManager { get; init; }

    /// <summary>
    /// Gets whether the process has been closed.
    /// </summary>
    public bool Closed { get; private set; }

    /// <summary>
    /// Look for changes in the process, fire property changed.
    /// </summary>
    internal void ObserveChanges()
    {
        try
        {
            if (Process.HasExited)
            {
                Closed = true;
                return;
            }

            if (BrowserManager.IsInGame.Get() != _wasInGame)
            {
                OnPropertyChanging(nameof(BrowserManager));

M src/PacketLogger/Models/NostaleProcesses.cs => src/PacketLogger/Models/NostaleProcesses.cs +20 -2
@@ 14,6 14,7 @@ using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
using NosSmooth.Comms.Local;
using NosSmooth.Core.Extensions;


@@ 31,6 32,7 @@ namespace PacketLogger.Models;
public class NostaleProcesses : IDisposable
{
    private readonly IDisposable? _cleanUp;
    private readonly SemaphoreSlim _semaphore;
    private readonly ManagementEventWatcher? _processStartWatcher;
    private readonly ManagementEventWatcher? _processStopWatcher;



@@ 39,6 41,7 @@ public class NostaleProcesses : IDisposable
    /// </summary>
    public NostaleProcesses()
    {
        _semaphore = new SemaphoreSlim(1, 1);
        Processes = new ObservableCollection<NostaleProcess>();

        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))


@@ 123,7 126,13 @@ public class NostaleProcesses : IDisposable
        if (nosBrowserManager.IsModuleLoaded<PlayerManager>())
        {
            RxApp.MainThreadScheduler.Schedule
                (() => Processes.Add(new NostaleProcess(process, nosBrowserManager)));
                (() =>
                    {
                        _semaphore.Wait();
                        Processes.Add(new NostaleProcess(process, nosBrowserManager));
                        _semaphore.Release();
                    }
                );
        }
        else
        {


@@ 143,7 152,14 @@ public class NostaleProcesses : IDisposable
            if (process is not null)
            {
                RxApp.MainThreadScheduler.Schedule
                    (() => Processes.Remove(process));
                    (() =>
                        {
                            process.ObserveChanges();
                            _semaphore.Wait();
                            Processes.Remove(process);
                            _semaphore.Release();
                        }
                    );
            }
        }
    }


@@ 175,9 191,11 @@ public class NostaleProcesses : IDisposable

    private void UpdateNames()
    {
        _semaphore.Wait();
        foreach (var process in Processes)
        {
            process.ObserveChanges();
        }
        _semaphore.Release();
    }
}
\ No newline at end of file

M src/PacketLogger/Models/Packets/ClientPacketProvider.cs => src/PacketLogger/Models/Packets/ClientPacketProvider.cs +13 -1
@@ 6,6 6,8 @@

using System;
using System.ComponentModel;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using DynamicData;


@@ 42,11 44,16 @@ public abstract class ClientPacketProvider : ReactiveObject, IPacketProvider
        _process = process;
        _client = client;
        Packets = new SourceList<PacketInfo>();
        _cleanUp = process.WhenPropertyChanged(x => x.CharacterString)
        var cleanUp1 = process.WhenPropertyChanged(x => x.CharacterString)
            .Subscribe
            (
                _ => this.RaisePropertyChanged(nameof(Name))
            );

        var cleanUp2 = process.WhenAnyValue(x => x.Closed)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => this.RaisePropertyChanged(nameof(Closed)));
        _cleanUp = new CompositeDisposable(cleanUp1, cleanUp2);
    }

    /// <inheritdoc />


@@ 55,6 62,11 @@ public abstract class ClientPacketProvider : ReactiveObject, IPacketProvider
        : null) ?? $"Not in game ({_process.Process.Id})";

    /// <summary>
    /// Gets whether the process has been closed.
    /// </summary>
    public bool Closed => _process.Closed;

    /// <summary>
    /// Gets or sets title of document.
    /// </summary>
    public string DocumentTitle { get; set; } = string.Empty;

M src/PacketLogger/ViewModels/DocumentViewModel.cs => src/PacketLogger/ViewModels/DocumentViewModel.cs +23 -7
@@ 85,7 85,9 @@ public class DocumentViewModel : Document, INotifyPropertyChanged, IDisposable
        );

        _cleanUp = this.WhenAnyValue(x => x.Title)
            .Subscribe(title =>
            .Subscribe
            (
                title =>
                {
                    if (_packetProvider is not null)
                    {


@@ 207,7 209,8 @@ public class DocumentViewModel : Document, INotifyPropertyChanged, IDisposable
                    if (!runClientContractResult.IsDefined(out var runClientResponse))
                    {
                        repository.Remove(connection.Client);
                        Error = "An error has occurred upon sending run client: " + runClientContractResult.ToFullString();
                        Error = "An error has occurred upon sending run client: "
                            + runClientContractResult.ToFullString();
                        Loading = false;
                        return;
                    }


@@ 220,7 223,8 @@ public class DocumentViewModel : Document, INotifyPropertyChanged, IDisposable
                        return;
                    }

                    if (runClientResponse.BindingManagerResult is not null && !runClientResponse.BindingManagerResult.Value.IsSuccess)
                    if (runClientResponse.BindingManagerResult is not null
                        && !runClientResponse.BindingManagerResult.Value.IsSuccess)
                    {
                        Console.WriteLine("There was an error in binding initialization.");
                        Console.WriteLine(runClientResponse.BindingManagerResult.Value.ToFullString());


@@ 229,7 233,8 @@ public class DocumentViewModel : Document, INotifyPropertyChanged, IDisposable
                    if (!runClientResponse.InitializationResult.Value.IsSuccess)
                    {
                        repository.Remove(connection.Client);
                        Error = "An error has occurred during starting client: " + runClientResponse.InitializationResult.ToFullString();
                        Error = "An error has occurred during starting client: "
                            + runClientResponse.InitializationResult.ToFullString();
                        Loading = false;
                        return;
                    }


@@ 239,7 244,14 @@ public class DocumentViewModel : Document, INotifyPropertyChanged, IDisposable
                _titleHandle = titleGenerator.AddTitle
                (
                    title => Title = title,
                    provider.WhenAnyValue(x => x.Name).ObserveOn(RxApp.MainThreadScheduler),
                    provider
                        .WhenAnyValue(x => x.Name, x => x.Closed)
                        .ObserveOn(RxApp.MainThreadScheduler)
                        .Select
                        (
                            (x) => (x.Item2 ? "Closed (" : string.Empty) + x.Item1
                                + (x.Item2 ? ")" : string.Empty)
                        ),
                    provider.Name
                );



@@ 276,9 288,13 @@ public class DocumentViewModel : Document, INotifyPropertyChanged, IDisposable
                (
                    title => Title = title,
                    provider
                        .WhenAnyValue(x => x.Name)
                        .WhenAnyValue(x => x.Name, x => x.Closed)
                        .ObserveOn(RxApp.MainThreadScheduler)
                        .Select(x => x + " - sniff"),
                        .Select
                        (
                            (x) => (x.Item2 ? "Closed (" : string.Empty) + (x.Item1 + " - sniff")
                                + (x.Item2 ? ")" : string.Empty)
                        ),
                    provider.Name
                );
                await provider.Open();

Do not follow this link