- tweak: less memory tweak
This commit is contained in:
@@ -5,7 +5,7 @@ using Nebula.Launcher.ServerListProviders;
|
||||
namespace Nebula.Launcher.Models;
|
||||
|
||||
public record ListItemTemplate(Type ModelType, string IconKey, string Label);
|
||||
public record ServerListTabTemplate(IServerListProvider ServerListProvider, string TabName);
|
||||
public record ServerListTabTemplate(BaseServerListProvider ServerListProvider, string TabName);
|
||||
public record ServerHubRecord(
|
||||
[property:JsonPropertyName("name")] string Name,
|
||||
[property:JsonPropertyName("url")] string MainUrl);
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
@@ -17,47 +18,35 @@ using Nebula.Shared.Utils;
|
||||
namespace Nebula.Launcher.ServerListProviders;
|
||||
|
||||
[ServiceRegister, ConstructGenerator]
|
||||
public sealed partial class FavoriteServerListProvider : IServerListProvider, IServerListDirtyInvoker
|
||||
public sealed partial class FavoriteServerListProvider : BaseServerListProvider
|
||||
{
|
||||
[GenerateProperty] private ConfigurationService ConfigurationService { get; }
|
||||
[GenerateProperty] private IServiceProvider ServiceProvider { get; }
|
||||
[GenerateProperty] private ServerViewContainer ServerViewContainer { get; }
|
||||
|
||||
private List<IListEntryModelView> _serverLists = [];
|
||||
private string[] rawServerLists = [];
|
||||
//[GenerateProperty] private ServerOverviewModel ServerOverviewModel { get; }
|
||||
|
||||
public bool IsLoaded { get; private set; }
|
||||
public Action? OnLoaded { get; set; }
|
||||
public Action? OnDisposed { get; set; }
|
||||
public Action? Dirty { get; set; }
|
||||
public IEnumerable<IListEntryModelView> GetServers()
|
||||
{
|
||||
return _serverLists;
|
||||
}
|
||||
|
||||
public IEnumerable<Exception> GetErrors()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public void LoadServerList()
|
||||
{
|
||||
IsLoaded = false;
|
||||
_serverLists.Clear();
|
||||
var servers = GetFavoriteEntries();
|
||||
|
||||
var serverEntries = servers.Select(s =>
|
||||
ServerViewContainer.Get(s.ToRobustUrl())
|
||||
);
|
||||
|
||||
_serverLists.AddRange(serverEntries);
|
||||
|
||||
_serverLists.Add(new AddFavoriteButton(ServiceProvider));
|
||||
|
||||
IsLoaded = true;
|
||||
OnLoaded?.Invoke();
|
||||
}
|
||||
private string[] _rawServerLists = [];
|
||||
|
||||
public override void LoadServerList(
|
||||
ObservableCollection<IListEntryModelView> servers,
|
||||
ObservableCollection<Exception> exceptions)
|
||||
{
|
||||
base.LoadServerList(servers, exceptions);
|
||||
|
||||
foreach (var server in _rawServerLists)
|
||||
{
|
||||
var container = ServerViewContainer.Get(server.ToRobustUrl());
|
||||
servers.Add(container);
|
||||
}
|
||||
|
||||
servers.Add(new AddFavoriteButton(ServiceProvider));
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AddFavorite(ServerEntryModelView entryModelView)
|
||||
{
|
||||
AddFavorite(entryModelView.Address);
|
||||
@@ -87,7 +76,7 @@ public sealed partial class FavoriteServerListProvider : IServerListProvider, IS
|
||||
|
||||
private List<string> GetFavoriteEntries()
|
||||
{
|
||||
return rawServerLists.ToList();
|
||||
return _rawServerLists.ToList();
|
||||
}
|
||||
|
||||
private void Initialise()
|
||||
@@ -99,26 +88,20 @@ public sealed partial class FavoriteServerListProvider : IServerListProvider, IS
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
rawServerLists = [];
|
||||
Dirty?.Invoke();
|
||||
_rawServerLists = [];
|
||||
return;
|
||||
}
|
||||
|
||||
rawServerLists = value;
|
||||
Dirty?.Invoke();
|
||||
_rawServerLists = value;
|
||||
//ServerOverviewModel.UpdateRequired();
|
||||
}
|
||||
|
||||
private void InitialiseInDesignMode(){}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
OnDisposed?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AddFavoriteButton: Border, IListEntryModelView{
|
||||
|
||||
private Button _addFavoriteButton = new Button();
|
||||
private readonly Button _addFavoriteButton = new();
|
||||
public AddFavoriteButton(IServiceProvider serviceProvider)
|
||||
{
|
||||
Margin = new Thickness(5, 5, 5, 20);
|
||||
@@ -133,10 +116,5 @@ public sealed class AddFavoriteButton: Border, IListEntryModelView{
|
||||
_addFavoriteButton.Content = "Add Favorite";
|
||||
Child = _addFavoriteButton;
|
||||
}
|
||||
public bool IsFavorite { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
public void Dispose(){}
|
||||
}
|
||||
@@ -1,7 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
using Nebula.Launcher.Models;
|
||||
using Nebula.Launcher.Services;
|
||||
using Nebula.Launcher.ViewModels.Pages;
|
||||
using Nebula.Shared;
|
||||
using Nebula.Shared.Models;
|
||||
@@ -11,81 +16,118 @@ using Nebula.Shared.Utils;
|
||||
namespace Nebula.Launcher.ServerListProviders;
|
||||
|
||||
[ServiceRegister(null, false), ConstructGenerator]
|
||||
public sealed partial class HubServerListProvider : IServerListProvider
|
||||
public sealed partial class HubServerListProvider : BaseServerListProvider
|
||||
{
|
||||
private CancellationTokenSource? _cts;
|
||||
private readonly SemaphoreSlim _loadLock = new(1, 1);
|
||||
|
||||
[GenerateProperty] private RestService RestService { get; }
|
||||
[GenerateProperty] private ServerViewContainer ServerViewContainer { get; }
|
||||
|
||||
public string HubUrl { get; set; }
|
||||
|
||||
public bool IsLoaded { get; private set; }
|
||||
public Action? OnLoaded { get; set; }
|
||||
public Action? OnDisposed { get; set; }
|
||||
|
||||
private CancellationTokenSource? _cts;
|
||||
private readonly List<IListEntryModelView> _servers = [];
|
||||
private readonly List<Exception> _errors = [];
|
||||
private string _hubUrl;
|
||||
|
||||
public HubServerListProvider With(string hubUrl)
|
||||
{
|
||||
HubUrl = hubUrl;
|
||||
_hubUrl = hubUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IEnumerable<IListEntryModelView> GetServers()
|
||||
{
|
||||
return _servers;
|
||||
}
|
||||
|
||||
public IEnumerable<Exception> GetErrors()
|
||||
public override void LoadServerList(
|
||||
ObservableCollection<IListEntryModelView> servers,
|
||||
ObservableCollection<Exception> exceptions)
|
||||
{
|
||||
return _errors;
|
||||
}
|
||||
|
||||
public async void LoadServerList()
|
||||
{
|
||||
if (_cts != null)
|
||||
{
|
||||
await _cts.CancelAsync();
|
||||
_cts = null;
|
||||
}
|
||||
base.LoadServerList(servers, exceptions);
|
||||
|
||||
_servers.Clear();
|
||||
_errors.Clear();
|
||||
IsLoaded = false;
|
||||
_cts = new CancellationTokenSource();
|
||||
servers.Add(new LoadingServerEntry());
|
||||
Task.Run(() => LoadServerListAsync(servers, exceptions));
|
||||
}
|
||||
|
||||
private void SyncServers(List<IListEntryModelView> servers,
|
||||
ObservableCollection<IListEntryModelView> collection)
|
||||
{
|
||||
collection.Clear();
|
||||
foreach (var server in servers)
|
||||
{
|
||||
collection.Add(server);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadServerListAsync(
|
||||
ObservableCollection<IListEntryModelView> servers,
|
||||
ObservableCollection<Exception> exceptions)
|
||||
{
|
||||
CancellationTokenSource localCts;
|
||||
|
||||
var serverList = new List<IListEntryModelView>();
|
||||
|
||||
await _loadLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
_cts?.Cancel();
|
||||
_cts?.Dispose();
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
localCts = _cts;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_loadLock.Release();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var servers =
|
||||
await RestService.GetAsync<List<ServerHubInfo>>(new Uri(HubUrl), _cts.Token);
|
||||
|
||||
servers.Sort(new ServerComparer());
|
||||
|
||||
if(_cts.Token.IsCancellationRequested) return;
|
||||
|
||||
_servers.AddRange(
|
||||
servers.Select(h=>
|
||||
ServerViewContainer.Get(h.Address.ToRobustUrl(), h.StatusData)
|
||||
)
|
||||
var serversRaw = await RestService.GetAsync<List<ServerHubInfo>>(
|
||||
new Uri(_hubUrl),
|
||||
localCts.Token
|
||||
);
|
||||
|
||||
serversRaw.Sort(new ServerComparer());
|
||||
|
||||
localCts.Token.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (var info in serversRaw)
|
||||
{
|
||||
var viewContainer =
|
||||
ServerViewContainer.Get(info.Address.ToRobustUrl(), info.StatusData);
|
||||
|
||||
serverList.Add(viewContainer);
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
SyncServers(serverList, servers);
|
||||
});
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_errors.Add(new Exception($"Some error while loading server list from {HubUrl}. See inner exception", e));
|
||||
_errors.Add(e);
|
||||
exceptions.Add(
|
||||
new Exception(
|
||||
$"Some error while loading server list from {_hubUrl}. See inner exception",
|
||||
e
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
IsLoaded = true;
|
||||
OnLoaded?.Invoke();
|
||||
}
|
||||
|
||||
private void Initialise(){}
|
||||
private void InitialiseInDesignMode(){}
|
||||
|
||||
public void Dispose()
|
||||
public override void Dispose()
|
||||
{
|
||||
OnDisposed?.Invoke();
|
||||
_cts?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class LoadingServerEntry : Label, IListEntryModelView
|
||||
{
|
||||
public LoadingServerEntry()
|
||||
{
|
||||
Content = LocalizationService.GetString("server-list-loading");
|
||||
}
|
||||
public void Dispose()
|
||||
{}
|
||||
}
|
||||
@@ -1,23 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Nebula.Launcher.ViewModels.Pages;
|
||||
|
||||
namespace Nebula.Launcher.ServerListProviders;
|
||||
|
||||
public interface IServerListProvider : IDisposable
|
||||
public abstract class BaseServerListProvider : ObservableObject, IDisposable
|
||||
{
|
||||
public bool IsLoaded { get; }
|
||||
public Action? OnLoaded { get; set; }
|
||||
public Action? OnDisposed { get; set; }
|
||||
|
||||
public IEnumerable<IListEntryModelView> GetServers();
|
||||
public IEnumerable<Exception> GetErrors();
|
||||
|
||||
public void LoadServerList();
|
||||
}
|
||||
public virtual void LoadServerList(
|
||||
ObservableCollection<IListEntryModelView> servers,
|
||||
ObservableCollection<Exception> exceptions)
|
||||
{
|
||||
servers.Clear();
|
||||
exceptions.Clear();
|
||||
}
|
||||
|
||||
public interface IServerListDirtyInvoker
|
||||
{
|
||||
public Action? Dirty { get; set; }
|
||||
public abstract void Dispose();
|
||||
}
|
||||
@@ -1,33 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using Nebula.Launcher.ViewModels.Pages;
|
||||
|
||||
namespace Nebula.Launcher.ServerListProviders;
|
||||
|
||||
public sealed class TestServerList : IServerListProvider
|
||||
public sealed class TestServerList : BaseServerListProvider
|
||||
{
|
||||
public bool IsLoaded => true;
|
||||
public Action? OnLoaded { get; set; }
|
||||
public Action? OnDisposed { get; set; }
|
||||
|
||||
public IEnumerable<IListEntryModelView> GetServers()
|
||||
public override void LoadServerList(
|
||||
ObservableCollection<IListEntryModelView> servers,
|
||||
ObservableCollection<Exception> exceptions)
|
||||
{
|
||||
return [new ServerEntryModelView(),new ServerEntryModelView()];
|
||||
base.LoadServerList(servers, exceptions);
|
||||
|
||||
servers.Add(new ServerEntryModelView());
|
||||
servers.Add(new ServerEntryModelView());
|
||||
|
||||
exceptions.Add(new Exception("Oh no!"));
|
||||
}
|
||||
|
||||
public IEnumerable<Exception> GetErrors()
|
||||
{
|
||||
return [new Exception("On no!")];
|
||||
}
|
||||
|
||||
public void LoadServerList()
|
||||
public override void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
OnDisposed?.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -24,16 +24,17 @@ public partial class ServerOverviewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty] private string _searchText = string.Empty;
|
||||
[ObservableProperty] private bool _isFilterVisible;
|
||||
|
||||
public readonly ServerFilter CurrentFilter = new();
|
||||
[GenerateProperty] private IServiceProvider ServiceProvider { get; }
|
||||
[GenerateProperty] private ConfigurationService ConfigurationService { get; }
|
||||
[GenerateProperty] private FavoriteServerListProvider FavoriteServerListProvider { get; }
|
||||
public ObservableCollection<ServerListTabTemplate> Items { get; private set; }
|
||||
|
||||
[ObservableProperty] private ServerListTabTemplate _selectedItem;
|
||||
[GenerateProperty, DesignConstruct] private ServerViewContainer ServerViewContainer { get; }
|
||||
[GenerateProperty, DesignConstruct] public ServerListViewModel CurrentServerList { get; }
|
||||
|
||||
public ServerFilter CurrentFilter { get; } = new();
|
||||
public ObservableCollection<ServerListTabTemplate> Items { get; private set; }
|
||||
|
||||
|
||||
//Design think
|
||||
protected override void InitialiseInDesignMode()
|
||||
@@ -73,13 +74,9 @@ public partial class ServerOverviewModel : ViewModelBase
|
||||
ApplyFilter();
|
||||
}
|
||||
|
||||
public void ApplyFilter()
|
||||
private void ApplyFilter()
|
||||
{
|
||||
foreach (var entry in ServerViewContainer.Items)
|
||||
{
|
||||
if(entry is IFilterConsumer filterConsumer)
|
||||
filterConsumer.ProcessFilter(CurrentFilter);
|
||||
}
|
||||
ServerViewContainer.ApplyFilter(CurrentFilter);
|
||||
}
|
||||
|
||||
public void OnFilterChanged(FilterBoxChangedEventArgs args)
|
||||
@@ -100,15 +97,14 @@ public partial class ServerOverviewModel : ViewModelBase
|
||||
{
|
||||
ServerViewContainer.Clear();
|
||||
CurrentServerList.RefreshFromProvider();
|
||||
CurrentServerList.ApplyFilter(CurrentFilter);
|
||||
}
|
||||
|
||||
partial void OnSelectedItemChanged(ServerListTabTemplate value)
|
||||
{
|
||||
CurrentServerList.Provider = value.ServerListProvider;
|
||||
CurrentServerList.ClearProvider();
|
||||
CurrentServerList.SetProvider(value.ServerListProvider);
|
||||
ApplyFilter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[ServiceRegister]
|
||||
@@ -119,6 +115,7 @@ public sealed class ServerViewContainer
|
||||
private readonly Dictionary<string, string> _customNames = [];
|
||||
|
||||
private readonly Dictionary<string, WeakReference<IListEntryModelView>> _entries = new();
|
||||
private ServerFilter? _currentFilter;
|
||||
|
||||
public ICollection<IListEntryModelView> Items =>
|
||||
_entries.Values
|
||||
@@ -178,10 +175,14 @@ public sealed class ServerViewContainer
|
||||
.LoadServerEntry(url, customName, CancellationToken.None);
|
||||
}
|
||||
|
||||
if (_favorites.Contains(key)
|
||||
&& entry is IFavoriteEntryModelView fav)
|
||||
if (entry is IFavoriteEntryModelView fav)
|
||||
{
|
||||
fav.IsFavorite = true;
|
||||
fav.IsFavorite = _favorites.Contains(key);
|
||||
}
|
||||
|
||||
if (entry is IFilterConsumer filterConsumer)
|
||||
{
|
||||
filterConsumer.ProcessFilter(_currentFilter);
|
||||
}
|
||||
|
||||
_entries[key] = new WeakReference<IListEntryModelView>(entry);
|
||||
@@ -189,6 +190,17 @@ public sealed class ServerViewContainer
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void ApplyFilter(ServerFilter? filter)
|
||||
{
|
||||
_currentFilter = filter;
|
||||
|
||||
foreach (var serverView in Items)
|
||||
{
|
||||
if(serverView is IFilterConsumer filterConsumer)
|
||||
filterConsumer.ProcessFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFavoritesChange(string[]? value)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using Avalonia.Controls;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Nebula.Launcher.Models;
|
||||
using Nebula.Launcher.ServerListProviders;
|
||||
using Nebula.Launcher.ViewModels.Pages;
|
||||
using Nebula.Launcher.Views;
|
||||
@@ -13,133 +10,37 @@ namespace Nebula.Launcher.ViewModels;
|
||||
[ViewModelRegister(typeof(ServerListView), false)]
|
||||
public partial class ServerListViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty] private bool _isLoading;
|
||||
public ObservableCollection<IListEntryModelView> ServerList { get; private set; } = new();
|
||||
public ObservableCollection<Exception> ErrorList { get; private set; } = new();
|
||||
|
||||
public ServerListViewModel()
|
||||
private BaseServerListProvider? _provider;
|
||||
|
||||
public void ClearProvider()
|
||||
{
|
||||
if (Design.IsDesignMode)
|
||||
{
|
||||
Provider = new TestServerList();
|
||||
}
|
||||
}
|
||||
|
||||
private IServerListProvider? _provider;
|
||||
|
||||
public ObservableCollection<IListEntryModelView> ServerList { get; } = new();
|
||||
public ObservableCollection<Exception> ErrorList { get; } = new();
|
||||
|
||||
public IServerListProvider Provider
|
||||
{
|
||||
get => _provider ?? throw new Exception();
|
||||
|
||||
set
|
||||
{
|
||||
_provider = value;
|
||||
_provider.OnDisposed += OnProviderDisposed;
|
||||
if (_provider is IServerListDirtyInvoker invoker)
|
||||
{
|
||||
invoker.Dirty += OnDirty;
|
||||
}
|
||||
|
||||
if(!_provider.IsLoaded)
|
||||
RefreshFromProvider();
|
||||
else
|
||||
{
|
||||
Clear();
|
||||
PasteServersFromList();
|
||||
}
|
||||
}
|
||||
ServerList.Clear();
|
||||
ErrorList.Clear();
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
}
|
||||
|
||||
private void OnProviderDisposed()
|
||||
public void SetProvider(BaseServerListProvider provider)
|
||||
{
|
||||
Provider.OnLoaded -= RefreshRequired;
|
||||
Provider.OnDisposed -= OnProviderDisposed;
|
||||
if (Provider is IServerListDirtyInvoker invoker)
|
||||
{
|
||||
invoker.Dirty -= OnDirty;
|
||||
}
|
||||
_provider = provider;
|
||||
|
||||
_provider = null;
|
||||
}
|
||||
|
||||
private ServerFilter? _currentFilter;
|
||||
|
||||
public void RefreshFromProvider()
|
||||
{
|
||||
if (IsLoading)
|
||||
return;
|
||||
OnPropertyChanged(nameof(ServerList));
|
||||
OnPropertyChanged(nameof(ErrorList));
|
||||
|
||||
Clear();
|
||||
StartLoading();
|
||||
|
||||
Provider.LoadServerList();
|
||||
|
||||
if (Provider.IsLoaded) PasteServersFromList();
|
||||
else Provider.OnLoaded += RefreshRequired;
|
||||
}
|
||||
|
||||
public void ApplyFilter(ServerFilter? filter)
|
||||
{
|
||||
_currentFilter = filter;
|
||||
|
||||
if(IsLoading)
|
||||
return;
|
||||
|
||||
foreach (var serverView in ServerList)
|
||||
{
|
||||
if(serverView is IFilterConsumer filterConsumer)
|
||||
filterConsumer.ProcessFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDirty()
|
||||
{
|
||||
RefreshFromProvider();
|
||||
}
|
||||
|
||||
private void Clear()
|
||||
public void RefreshFromProvider()
|
||||
{
|
||||
ErrorList.Clear();
|
||||
ServerList.Clear();
|
||||
_provider?.LoadServerList(ServerList, ErrorList);
|
||||
}
|
||||
|
||||
private void PasteServersFromList()
|
||||
{
|
||||
foreach (var serverEntry in Provider.GetServers())
|
||||
{
|
||||
ServerList.Add(serverEntry);
|
||||
if(serverEntry is IFilterConsumer serverFilter)
|
||||
serverFilter.ProcessFilter(_currentFilter);
|
||||
}
|
||||
|
||||
foreach (var error in Provider.GetErrors())
|
||||
{
|
||||
ErrorList.Add(error);
|
||||
}
|
||||
|
||||
EndLoading();
|
||||
}
|
||||
|
||||
private void RefreshRequired()
|
||||
{
|
||||
PasteServersFromList();
|
||||
Provider.OnLoaded -= RefreshRequired;
|
||||
}
|
||||
|
||||
private void StartLoading()
|
||||
{
|
||||
Clear();
|
||||
IsLoading = true;
|
||||
}
|
||||
|
||||
private void EndLoading()
|
||||
{
|
||||
IsLoading = false;
|
||||
}
|
||||
|
||||
protected override void InitialiseInDesignMode()
|
||||
{
|
||||
SetProvider(new TestServerList());
|
||||
}
|
||||
|
||||
protected override void Initialise()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:services="clr-namespace:Nebula.Launcher.Services"
|
||||
xmlns:viewModels1="clr-namespace:Nebula.Launcher.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nebula.Launcher.Views.ServerListView"
|
||||
@@ -15,10 +14,6 @@
|
||||
Margin="5,0,0,10"
|
||||
Padding="0,0,10,0">
|
||||
<StackPanel Margin="0,0,0,30">
|
||||
<Label IsVisible="{Binding IsLoading}"
|
||||
x:Name="LoadingLabel"
|
||||
Margin="10" HorizontalAlignment="Center"
|
||||
Content="{services:LocaledText 'server-list-loading'}"/>
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding ErrorList}"
|
||||
Margin="10,0,10,0" />
|
||||
|
||||
@@ -29,20 +29,37 @@ public class HarmonyService(ReflectionService reflectionService)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Я помню пенис большой,Я помню пенис большой, Я помню пенис большой, я помню....
|
||||
/// Я не понимаю суть античитов в сосаке.
|
||||
/// Эту хуйню может обойти любой школьник!
|
||||
/// Нет.. я не хочу вводить читы, просто мне нужно поменять некоторые штучки :)
|
||||
/// </summary>
|
||||
private void UnShittyWizard()
|
||||
{
|
||||
var method = reflectionService.GetType("Robust.Client.GameController").TypeInitializer;
|
||||
_instance!.Harmony.Patch(method, new HarmonyMethod(Prefix));
|
||||
_instance!.Harmony.Patch(method, new HarmonyMethod(IgnorePrefix));
|
||||
|
||||
var method2 = typeof(Type).Method(nameof(Type.GetType), new[] { typeof(string) });
|
||||
_instance!.Harmony.Patch(method2, new HarmonyMethod(HidifyPrefix));
|
||||
}
|
||||
|
||||
static bool Prefix()
|
||||
static bool IgnorePrefix()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool HidifyPrefix(ref Type? __result, string typeName)
|
||||
{
|
||||
if (typeName.Contains("Harmony"))
|
||||
{
|
||||
__result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class HarmonyInstance
|
||||
{
|
||||
public readonly Harmony Harmony;
|
||||
|
||||
Reference in New Issue
Block a user