Files
Daybreak/Daybreak.API/Services/Interop/PartyContextService.cs
T
amacocian 794afa6c2c Blazor UI Migration (#1085)
* Migrate to Fluent UI

* Setup window events for Blazor WebView

* Setup basic FluentUI styling

* FluentUI links

* Setup views and viewmodel infra

* Remove old navigation logic

* Prepare an example of iframe embed

* Style window + navigation menu

* Setup page based navigation

* Add some UI error handling

* Introduce UI resiliency to exceptions

* Setup settings menu dropdown

* Basic setup for options views

* Setup reusable OptionBase

* Setup options views

* Basic styling

* Setup scoped css files.
Split App into components

* Hook option updates to OptionProvider

* Fix option dropdowns

* Setup multiple themes

* Make fonts scalable

* Move ViewModels under Views

* Launch view + styling

* Setup FocusView base

* Finish BuildListView implementation

* Base for build views

* Setup build routing

* Implement single build editor

* Implement skill description on hover

* Scrape skill information from the wiki and cache it locally

* Scrape and fix Guild Wars wiki info

* Improve mouse hover performance by querying position only when needed

* Skill snippet snaps to edges

* Setup accounts and executables view

* Launch configurations view

* Fix build skill icons
Attach skill types to skills
Scrape upkeep from wiki

* Fix skilltype overflow

* Adjust navigation menu

* Setup privilege elevation flow

* Setup MSAL

* Options synchronization view

* Telemetry view

* Version management and update view

* Setup plugins view

* Setup notifications panel

* Base for logs view

* Finish LogView

* Setup metrics view

* Setup UI logging interop

* GuildWarsPartySearch view implementation

* Setup gitlab mirror job

* Eventviewer base

* Remove gitlab mirror

* Remove mirror pipeline

* Fix metricsview crashes

* Extract progress component

* Setup trade chat views

* Setup Download view

* Extract progress styling

* Setup guild wars copy view

* Setup trade alerts

* Fix team template view skill selection

* Setup basic onboarding view

* Overhaul asynchronous progress operations and remove redundant versioning code

* Setup modsview base

* Setup modsview with mod states

* Setup mod installation process

* Cleanup more ui migration
Remove price history #1076

* Screen selector manage view

* Upgrade to .net 10
Closes #1078

* gMod management view

* Trader message notification

* ReShade management

* Update for toolbox

* Setup focusview fetching

* Setup CharacterComponent

* Setup vanquishing component

* Setup TitleInformationComponent

* Closes #1082
Fix API project for Guild Wars Reforged

* Small fixes + attempts to get new exe version

* FileId fixes

* Current Map and Player Resources widgets

* Quest log widget

* BuildComponent implementation

* Closes #1075
Embed wwwroot into the executable

* Cleanup

* Fixes to slnx

* Fix test project
2025-12-08 22:39:48 +01:00

102 lines
3.5 KiB
C#

using Daybreak.API.Interop;
using Daybreak.API.Models;
using System.Core.Extensions;
using System.Extensions;
using static Daybreak.API.Models.UIPackets;
namespace Daybreak.API.Services.Interop;
public sealed class PartyContextService
: IAddressHealthService
{
private const string SearchButtonFile = "\\Code\\Gw\\Ui\\Game\\Party\\PtSearch.cpp";
private const string SearchButtonAssertion = "m_activeList == LIST_HEROES";
private const string WindowButtonAssertion = "selection.agentId";
// Fastcall funcs do not work in .NET for x86 right now. https://github.com/dotnet/runtime/issues/113851
// This fastcall equivalent is <void*, uint, UIPacket::kMouseAction*, void>
private readonly GWFastCall<nint, uint, nint, GWFastCall.Void> searchButtonCallback;
// This fastcall equivalent is <void*, uint, UIPacket::kMouseAction*, void>
private readonly GWFastCall<nint, uint, nint, GWFastCall.Void> windowButtonCallback;
private readonly MemoryScanningService memoryScanningService;
private readonly ILogger<PartyContextService> logger;
public PartyContextService(
MemoryScanningService memoryScanningService,
ILogger<PartyContextService> logger)
{
this.memoryScanningService = memoryScanningService.ThrowIfNull();
this.logger = logger.ThrowIfNull();
this.searchButtonCallback = new(new GWAddressCache(() => this.memoryScanningService.ToFunctionStart(this.memoryScanningService.FindAssertion(SearchButtonFile, SearchButtonAssertion, 0, 0))));
this.windowButtonCallback = new(new GWAddressCache(() => this.memoryScanningService.ToFunctionStart(this.memoryScanningService.FindUseOfString(WindowButtonAssertion))));
}
public List<AddressState> GetAddressStates()
{
unsafe
{
return
[
new AddressState
{
Address = this.searchButtonCallback.Cache.GetAddress() ?? 0,
Name = nameof(this.searchButtonCallback)
},
new AddressState
{
Address = this.windowButtonCallback.Cache.GetAddress() ?? 0,
Name = nameof(this.windowButtonCallback)
}
];
}
}
public unsafe bool CallSearchButtonCallback(void* ctx, uint edx, MouseAction* wparam)
{
this.searchButtonCallback.Invoke((nint)ctx, edx, (nint)wparam);
return true;
}
public unsafe bool CallWindowButtonCallback(void* ctx, uint edx, MouseAction* wparam)
{
this.windowButtonCallback.Invoke((nint)ctx, edx, (nint)wparam);
return true;
}
public unsafe bool AddHero(uint heroId)
{
var action = new MouseAction(
frameId: 0,
childOffsetId: 0x1,
currentState: ActionState.MouseUp);
var ctx = stackalloc uint[13];
ctx[0xb] = 1;
ctx[0x9] = heroId;
return this.CallSearchButtonCallback(ctx, 2, &action);
}
public unsafe bool KickHero(uint heroId)
{
var action = new MouseAction(
frameId: 0,
childOffsetId: 0x6,
currentState: ActionState.MouseUp);
var ctx = stackalloc uint[13];
ctx[0xb] = 1;
ctx[0x9] = heroId;
return this.CallSearchButtonCallback(ctx, 0, &action);
}
public bool KickAllHeroes() => this.KickHero(0x26);
public unsafe bool LeaveParty()
{
var ctx = stackalloc uint[14];
ctx[0xd] = 1;
return this.CallWindowButtonCallback(ctx, 0, (MouseAction*)0);
}
}