Compare commits

..
47 Commits
Author SHA1 Message Date
amacocianandGitHub 09fdbb6f95 Release 0.9.9.13 (#560) 2024-02-01 14:52:15 +00:00
amacocianandGitHub 8ee7ed23e4 Release 0.9.9.12 (#558)
* Release 0.9.9.12

* Move injection to injector executable (#554)

* Fix logview missing history (#556)

Closes #526

* Detect unresponsive Guild Wars instance (#557)

Closes #534
Closes #422
2024-01-31 22:02:14 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>amacocian
8d8a78cf88 Bump microsoft/setup-msbuild from 1.3.1 to 1.3.2 (#552)
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Changelog](https://github.com/microsoft/setup-msbuild/blob/main/building-release.md)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v1.3.1...v1.3.2)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Macocian Alexandru Victor <amacocian@yahoo.com>
2024-01-29 17:06:36 +01:00
amacocianandGitHub f0652231cb Fix minimap mouse interaction (#553)
* Rework minimap renderer

* Fix dragging

* Fix mouse over detection
2024-01-29 15:50:32 +00:00
amacocianandGitHub d9aa760256 Release 0.9.9.10 (#550)
* Release 0.9.9.10
Option to rotate minimap with the camera
Fix launch button not disabling properly when launching
Remove minimap id overlay
Closes #549
Closes #533
Closes #532

* Increment version

* Increment Daybreak.GWCA version
2024-01-28 14:56:51 +00:00
amacocianandGitHub a65f375255 Release 0.9.9.9 (#548)
Closes #547
Closes #546
Closes #536
2024-01-27 19:34:47 +00:00
amacocianandGitHub 3ee58e2711 Release 0.9.9.8 (#545)
* Synchronize browser history

* Intercept mouse button navigation
Closes #535
Closes #544
2024-01-26 14:24:32 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>amacocian
9b3b083aec Bump MSTest.TestAdapter from 3.1.1 to 3.2.0 (#542)
Bumps [MSTest.TestAdapter](https://github.com/microsoft/testfx) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/microsoft/testfx/releases)
- [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md)
- [Commits](https://github.com/microsoft/testfx/compare/v3.1.1...v.3.2.0)

---
updated-dependencies:
- dependency-name: MSTest.TestAdapter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Macocian Alexandru Victor <amacocian@yahoo.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Macocian Alexandru Victor <amacocian@yahoo.com>
2024-01-26 13:09:38 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ecb9b8f172 Bump MSTest.TestFramework from 3.1.1 to 3.2.0 (#543)
Bumps [MSTest.TestFramework](https://github.com/microsoft/testfx) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/microsoft/testfx/releases)
- [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md)
- [Commits](https://github.com/microsoft/testfx/compare/v3.1.1...v.3.2.0)

---
updated-dependencies:
- dependency-name: MSTest.TestFramework
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-26 13:08:22 +01:00
amacocianandGitHub 5765c27240 Release 0.9.9.7 (#541)
* Introduce support for browser extensions

* Setup ublock origin

* Release 0.9.9.7 branch

* Automatically backup settings
Closes #539

* Compare settings with remote
2024-01-23 18:25:31 +00:00
amacocianandGitHub c53456112a Update GWCA (#538)
Fix inventory bug
2024-01-20 10:19:46 +00:00
amacocianandGitHub ccea21886e Release 0.9.9.5 (#531)
* Remove character name from credentials
Update vulnerable packages

* Update SharpCompress
2024-01-17 20:00:12 +00:00
amacocianandGitHub 37be8de5ac Update httplib (#529)
Fix missing data when player has no titles
Fix http requests stalling
2024-01-15 19:20:55 +00:00
amacocianandGitHub 107e43a15f Update GWCA (#528) 2024-01-15 13:34:41 +00:00
amacocianandGitHub 17b3ed34db Disable wintersday mode (#527) 2024-01-09 14:06:05 +02:00
amacocianandGitHub cce9cd34af Update README.md (#524)
Signed-off-by: Macocian Alexandru Victor <amacocian@yahoo.com>
2023-12-22 07:58:23 +02:00
amacocianandGitHub 6a80f8ee5d Escape parameters passed to Guild Wars on launch (#522) 2023-12-20 14:54:34 +00:00
amacocianandGitHub edb7f0d0bd Beta release 0.9 (#521)
Closes #453
2023-12-20 00:27:29 +00:00
amacocianandGitHub 8e69375338 Fix application updater start message (#520)
Closes #519
2023-12-19 23:59:39 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>amacocian
d24ae98fb0 Bump github/codeql-action from 2 to 3 (#516)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Macocian Alexandru Victor <amacocian@yahoo.com>
2023-12-19 23:22:27 +00:00
amacocianandGitHub 111b3ea632 Setup setting synchronization functionality (#518)
* Setup setting synchronization functionality
Update dependencies
Closes #515

* Disable mainwindow periodic check
2023-12-19 23:05:53 +00:00
amacocian cc1e759972 Improve updater responsiveness
Closes #514
2023-12-15 16:18:03 +01:00
amacocianandGitHub ad0527ed73 Notifications improvements (#513)
Add checkbox for unopened notifications
Added sort options for notifications
Closes #511
Closes #510
2023-12-15 15:13:48 +00:00
amacocianandGitHub 8ffbb918ea Add frequency checking option for trader quote alerts (#512)
Hide sell trade quotes since they don't populate
Closes #509
Closes #508
2023-12-15 13:08:51 +00:00
amacocianandGitHub c27a0dba65 Setup alerts for quotes (#507) 2023-12-12 15:22:40 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ad8305c66d Bump actions/setup-dotnet from 3 to 4 (#505)
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3 to 4.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 12:41:35 +01:00
amacocianandGitHub 29fe12f094 Revert injector extraction (#504)
* Revert "Extract injector to its own process (#503)"

This reverts commit 9dbe4c5eaf.

* Revert injector extraction
2023-12-04 14:54:34 +01:00
amacocianandGitHub 9dbe4c5eaf Extract injector to its own process (#503) 2023-12-04 14:12:18 +01:00
amacocianandGitHub 1e9aca3807 Onboard SharpNav for pathfinding (#502) 2023-11-29 23:05:41 +00:00
amacocianandGitHub 895da23f7d Re-enable beta update by default (#500)
Extra pictures
2023-11-23 18:39:44 +00:00
amacocianandGitHub f788a10879 Implement file version checking for updater (#499)
* Implement file version checking for updater

* Increment version
2023-11-23 17:17:58 +00:00
amacocianandGitHub 9fe4be0467 Remove privilege mode for updater (#497) 2023-11-22 20:51:54 +00:00
amacocianandGitHub b1a7d3a111 Improve update procedure (#496)
* Improve update procedure

* Change release procedure

* Fix gh release

* Fix release tag

* Change release structure to support folders

* Revert zip file changes to make them backwards compatible

* Change path

* Make launcher not contain the entire dependencies

* Add downtime after API rate limit

* Add rate limit checking before create release

* Enumerate through rates

* Adjust rate limit call

* Change to create release as draft

* Add update logic based on azure blobs

* Fix publish

* Create zip

* Disable CD pipeline for prs

* Increment version

* Fix tests
2023-11-22 21:13:01 +01:00
amacocianandGitHub 8b9fdaaa30 Release v152 (#493)
Improve LaunchView responsiveness
Show current uMod version
Make services and models internal
Closes #491
Closes #490
Closes #381
2023-11-21 16:25:32 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
60d5947535 Bump SharpCompress from 0.34.1 to 0.34.2 (#489)
Bumps [SharpCompress](https://github.com/adamhathcock/sharpcompress) from 0.34.1 to 0.34.2.
- [Release notes](https://github.com/adamhathcock/sharpcompress/releases)
- [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.34.1...0.34.2)

---
updated-dependencies:
- dependency-name: SharpCompress
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-21 15:25:31 +01:00
amacocianandGitHub 0ba0e64a2a Small fixes (#488)
Fix copy folder picker
Fix metrics
Closes #487
Closes #474
2023-11-19 00:17:26 +00:00
amacocianandGitHub e1dfd1f0d0 Update to .net8.0 (#486)
Fix uMod installation steps
ReShade monitor config changes
2023-11-18 23:40:09 +00:00
amacocianandGitHub cd2a529381 Catch exceptions on startup (#485)
Extend process injection timeout (mainly due to uMod)
2023-11-17 15:50:08 +00:00
amacocianandGitHub 6ba8dcac49 Upgrade GWCA (#480) 2023-11-14 13:09:32 +00:00
amacocianandGitHub f2e76b5459 Show winter related background for Wintersday (#479)
* Show winter related background for Wintersday
Closes #449
Contributes to #453

* Increment version
2023-11-13 22:40:41 +00:00
amacocianandGitHub cfbf6ed021 Update toolbox and uMod links to gwdevhub (#477) 2023-11-12 15:30:06 +00:00
amacocianandGitHub a372eb5125 Replace uMod with gMod (#476) 2023-11-10 17:09:54 +00:00
amacocianandGitHub 76b89ca0e8 Make Daybreak create a modlist.txt for uMod (#475) 2023-11-10 11:06:30 +00:00
amacocianandGitHub 2c1721d52c Bugfixes (#473)
Fix NRE in minimap
Add a fallback routine to figure out if an elevated guildwars executable is running
2023-11-10 00:11:24 +00:00
amacocianandGitHub 324a77a625 Update UMod startup action (#472)
Minor mod fixes
2023-11-09 22:09:47 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
88e59b8ec9 Bump Microsoft.NET.Test.Sdk from 17.8.0-release-23468-02 to 17.8.0 (#471)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.8.0-release-23468-02 to 17.8.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.8.0-release-23468-02...v17.8.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 23:00:54 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>amacocian
df71a17d9f Bump Microsoft.Web.WebView2 from 1.0.2088.41 to 1.0.2151.40 (#469)
* Bump Microsoft.Web.WebView2 from 1.0.2088.41 to 1.0.2151.40

Bumps Microsoft.Web.WebView2 from 1.0.2088.41 to 1.0.2151.40.

---
updated-dependencies:
- dependency-name: Microsoft.Web.WebView2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix version

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Alex Macocian <amacocian@yahoo.com>
2023-11-08 19:08:20 +00:00
271 changed files with 13403 additions and 10598 deletions
+20 -6
View File
@@ -50,12 +50,12 @@ jobs:
LatestReleaseTag: ${{steps.getLatestTag.outputs.tag}}
- name: Install .NET Core
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v4
with:
dotnet-version: '7.x'
dotnet-version: '8.x'
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.3.1
uses: microsoft/setup-msbuild@v1.3.2
- name: Fetch submodules
run: |
@@ -83,7 +83,7 @@ jobs:
echo "::set-env name=Version::$version"
- name: Create publish launcher files
run: dotnet publish .\Daybreak\Daybreak.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -o .\Publish
run: dotnet publish .\Daybreak\Daybreak.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=false --self-contained true -o .\Publish
env:
RuntimeIdentifier: win-${{ matrix.targetplatform }}
@@ -93,7 +93,7 @@ jobs:
RuntimeIdentifier: win-${{ matrix.targetplatform }}
- name: Create publish extractor files
run: dotnet publish .\Daybreak.7ZipExtractor\Daybreak.7ZipExtractor.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -o .\Publish
run: dotnet publish .\Daybreak.7ZipExtractor\Daybreak.7ZipExtractor.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=false --self-contained true -o .\Publish
env:
RuntimeIdentifier: win-${{ matrix.targetplatform }}
@@ -103,7 +103,13 @@ jobs:
.\Scripts\BuildRelease.ps1 -version $env:Version
shell: pwsh
- name: Publish release
- name: Publish blob files
run: |
Write-Host $env
.\Scripts\PushFilesToBlobStorage.ps1 -version $env:Version -sourcePath .\Publish\ -connectionString "${{ secrets.BLOBSTORAGE_CONNECTIONSTRING }}"
shell: pwsh
- name: Create release draft
uses: Xotl/cool-github-releases@v1.1.8
with:
mode: update
@@ -113,6 +119,14 @@ jobs:
github_token: ${{ env.GITHUB_TOKEN }}
replace_assets: true
body_mrkdwn: ${{ env.Changelog }}
isDraft: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish release
run: |
gh release edit v${{ env.Version }} --draft=false
shell: powershell
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+3 -3
View File
@@ -36,12 +36,12 @@ jobs:
fetch-depth: 0
- name: Install .NET Core
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v4
with:
dotnet-version: '7.x'
dotnet-version: '8.x'
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.3.1
uses: microsoft/setup-msbuild@v1.3.2
- name: Fetch submodules
run: |
+4 -4
View File
@@ -55,7 +55,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -70,9 +70,9 @@ jobs:
# If this step fails, then you should remove it and run the build manually (see below)
- name: Install .NET Core
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v4
with:
dotnet-version: '7.x'
dotnet-version: '8.x'
#- name: Autobuild
# uses: github/codeql-action/autobuild@v2
@@ -91,4 +91,4 @@ jobs:
run: dotnet build Daybreak -c $env:Configuration --property:SolutionDir=$env:GITHUB_WORKSPACE
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
+6 -1
View File
@@ -28,7 +28,12 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'
- name: Get Latest Tag
id: getLatestTag
uses: WyriHaximus/github-action-get-previous-tag@v1
+1 -1
View File
@@ -1,3 +1,3 @@
[submodule "GWCA"]
path = GWCA
url = https://github.com/GregLando113/GWCA
url = https://github.com/gwdevhub/GWCA
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>Daybreak._7ZipExtractor</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
@@ -10,7 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SharpCompress" Version="0.34.1" />
<PackageReference Include="SharpCompress" Version="0.36.0" />
</ItemGroup>
</Project>
+17 -4
View File
@@ -2,17 +2,28 @@
# project specific logic here.
#
project(Daybreak.GWCA)
project(Daybreak.GWCA VERSION 1.0.0)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
message(FATAL_ERROR "You are configuring a 64bit build, this is not supported. Run cmake with `-A Win32`")
endif()
set(VERSION_MAJOR 0)
set(VERSION_MINOR 9)
set(VERSION_PATCH 9)
set(VERSION_TWEAK 10)
set(VERSION_RC "${CMAKE_CURRENT_BINARY_DIR}/version.rc")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in" "${VERSION_RC}" @ONLY)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(Daybreak.GWCA_FOLDER "${CMAKE_CURRENT_LIST_DIR}/")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/bin/install)
add_compile_options(/MP /permissive-)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/")
add_library(Daybreak.GWCA SHARED)
@@ -23,11 +34,13 @@ file(GLOB SOURCES
"header/*.h*"
"header/*/*.h")
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${SOURCES})
target_sources(Daybreak.GWCA PRIVATE ${SOURCES})
source_group("Generated Files" FILES ${VERSION_RC})
target_sources(Daybreak.GWCA PRIVATE ${SOURCES} ${VERSION_RC})
target_compile_features(Daybreak.GWCA PUBLIC cxx_std_17)
target_compile_definitions(Daybreak.GWCA PRIVATE
$<$<CONFIG:Debug>:BUILD_TYPE_DEBUG>
$<$<CONFIG:Release>:BUILD_TYPE_RELEASE>
NOMINMAX
)
target_precompile_headers(Daybreak.GWCA PRIVATE "header/pch.h")
File diff suppressed because it is too large Load Diff
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <cstdint>
#include <json.hpp>
using json = nlohmann::json;
namespace Daybreak {
struct Camera {
float Yaw;
float Pitch;
};
void to_json(json& j, const Camera& p);
}
@@ -2,11 +2,13 @@
#include <cstdint>
#include <json.hpp>
#include <payloads/StatePayload.h>
#include <payloads/Camera.h>
using json = nlohmann::json;
namespace Daybreak {
struct GameStatePayload {
Camera Camera;
std::list<StatePayload> States;
};
+5 -6
View File
@@ -287,6 +287,11 @@ namespace Daybreak::Modules::GameModule {
auto name = Daybreak::Utils::WStringToString(nameString);
player.Name = name;
if (titles.empty() ||
titleTiers.empty()) {
return;
}
for (const auto &t : titles) {
if (t.current_title_tier_index == gwPlayer->active_title_tier) {
gwTitle = t;
@@ -360,14 +365,8 @@ namespace Daybreak::Modules::GameModule {
}
auto titles = GetTitles();
if (titles.empty()) {
return gamePayload;
}
auto titleTiers = GetTitleTiers();
if (titleTiers.empty()) {
return gamePayload;
}
auto players = GetPlayers();
if (players.empty()) {
+8
View File
@@ -2,7 +2,9 @@
#include "GameStateModule.h"
#include <GWCA/Managers/GameThreadMgr.h>
#include <GWCA/Managers/AgentMgr.h>
#include <GWCA/Managers/CameraMgr.h>
#include <GWCA/GameEntities/Agent.h>
#include <GWCA/GameEntities/Camera.h>
#include <GWCA/Managers/MapMgr.h>
#include <future>
#include <payloads/GameStatePayload.h>
@@ -64,6 +66,12 @@ namespace Daybreak::Modules::GameStateModule {
auto states = GetStates(agents);
gamePayload.States = states;
auto camera = GW::CameraMgr::GetCamera();
Daybreak::Camera cameraPayload{};
cameraPayload.Pitch = camera->pitch;
cameraPayload.Yaw = camera->yaw;
gamePayload.Camera = cameraPayload;
return gamePayload;
}
+5 -6
View File
@@ -287,6 +287,11 @@ namespace Daybreak::Modules::MainPlayerModule {
auto name = Daybreak::Utils::WStringToString(gwPlayerName);
player.Name = name;
if (titles.empty() ||
titleTiers.empty()) {
return;
}
for (const auto &t : titles) {
if (t.current_title_tier_index == gwPlayer->active_title_tier) {
gwTitle = t;
@@ -358,14 +363,8 @@ namespace Daybreak::Modules::MainPlayerModule {
}
auto titles = GetTitles();
if (titles.empty()) {
return gamePayload;
}
auto titleTiers = GetTitleTiers();
if (titleTiers.empty()) {
return gamePayload;
}
auto players = GetPlayers();
if (players.empty()) {
+2 -2
View File
@@ -22,8 +22,8 @@ namespace Daybreak::Modules::MapModule {
auto region = GW::Map::GetRegion();
auto mapId = GW::Map::GetMapID();
MapPayload mapPayload;
mapPayload.Campaign = mapInfo->campaign;
mapPayload.Continent = mapInfo->continent;
mapPayload.Campaign = static_cast<uint32_t>(mapInfo->campaign);
mapPayload.Continent = static_cast<uint32_t>(mapInfo->continent);
mapPayload.Region = mapInfo->region;
mapPayload.InstanceType = (uint32_t)instanceType;
mapPayload.IsLoaded = isLoaded;
+3
View File
@@ -62,6 +62,9 @@ namespace http {
int port = FindPort();
if (port > 0) {
std::cout << "Initializing server on port " << port << std::endl;
server.set_read_timeout(1, 0);
server.set_write_timeout(1, 0);
server.set_idle_interval(0, 100000);
server.listen("0.0.0.0", port);
return true;
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <payloads/Camera.h>
#include <cstdint>
#include <json.hpp>
using json = nlohmann::json;
namespace Daybreak {
void to_json(json& j, const Camera& p) {
j = json
{
{"Yaw", p.Yaw},
{"Pitch", p.Pitch}
};
}
}
@@ -8,6 +8,7 @@ namespace Daybreak {
void to_json(json& j, const GameStatePayload& p) {
j = json
{
{"Camera", p.Camera},
{"States", p.States},
};
}
+34
View File
@@ -0,0 +1,34 @@
#include <winver.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_TWEAK@
PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_TWEAK@
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "gwdevhub"
VALUE "FileDescription", "Daybreak.GWCA"
VALUE "FileVersion", "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@.@VERSION_TWEAK@"
VALUE "InternalName", "Daybreak.GWCA"
VALUE "LegalCopyright", ""
VALUE "OriginalFilename", "Daybreak.GWCA.dll"
VALUE "ProductName", "Daybreak.GWCA"
VALUE "ProductVersion", "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@.@VERSION_TWEAK@"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 0x4B0
END
END
+6 -2
View File
@@ -2,10 +2,14 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU;x86;x64</Platforms>
<Platforms>AnyCPU;x86</Platforms>
<PublishSingleFile>True</PublishSingleFile>
<Self-Contained>True</Self-Contained>
<PublishReadyToRun>True</PublishReadyToRun>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>
</Project>
+93 -36
View File
@@ -1,59 +1,116 @@
// See https://aka.ms/new-console-template for more information
using System.Diagnostics;
using System.IO.Compression;
using System.Text;
static void RenderProgressBar(int currentStep, int totalSteps, int barSize)
{
Console.CursorLeft = 0; // Reset cursor position to the start of the line
Console.Write("["); // Start of the progress bar
double pctComplete = (double)currentStep / totalSteps;
int chars = (int)Math.Round(pctComplete * barSize);
Console.Write(new string('=', chars)); // The 'completed' part of the bar
Console.Write(new string(' ', barSize - chars)); // The 'remaining' part of the bar
Console.Write("] ");
Console.Write($"{pctComplete:P0}"); // Display the percentage completed
}
const string tempFile = "tempfile.zip";
const string updatePkg = "update.pkg";
const string executableName = "Daybreak.exe";
Console.Title = "Daybreak Installer";
Console.WriteLine("Starting installation...");
if (File.Exists(tempFile) is false)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Unable to find launcher package. Aborting installation");
Console.ReadKey();
return;
}
while (Process.GetProcesses().Where(p => p.ProcessName == "Daybreak").FirstOrDefault()?.HasExited is false)
{
Console.WriteLine($"Detected Daybreak process is still running. Waiting 5s and retrying");
await Task.Delay(5000);
}
Console.WriteLine("Unpacking files...");
try
{
ZipFile.ExtractToDirectory(tempFile, AppContext.BaseDirectory, true);
}
catch
if (File.Exists(updatePkg))
{
Console.WriteLine("Unpacking files...");
}
using var fileStream = new FileStream(updatePkg, FileMode.Open);
var sizeBuffer = new byte[4];
var copyBuffer = new byte[1024];
while (fileStream.Position < fileStream.Length - 1)
{
/*
* For each file downloaded, we write to the package the following:
* Size of the name string
* UTF-8 encoded name string
* Size of the relative path string
* UTF-8 encoded relative path string
* Size of the binary
* Binary data
*/
Console.WriteLine("Deleting browser caches");
try
{
Directory.Delete("BrowserData", true);
}
catch(Exception)
{
}
try
{
Directory.Delete("Daybreak.exe.WebView2", true);
}
catch(Exception)
{
}
await fileStream.ReadAsync(sizeBuffer, 0, 4);
var fileNameSize = BitConverter.ToInt32(sizeBuffer, 0);
var fileNameBuffer = new byte[fileNameSize];
await fileStream.ReadAsync(fileNameBuffer, 0, fileNameSize);
var fileName = Encoding.UTF8.GetString(fileNameBuffer);
Console.WriteLine("Deleting package");
try
{
File.Delete(tempFile);
RenderProgressBar((int)fileStream.Position, (int)fileStream.Length, 40);
await fileStream.ReadAsync(sizeBuffer, 0, 4);
var relativePathSize = BitConverter.ToInt32(sizeBuffer, 0);
var relativePathBuffer = new byte[relativePathSize];
await fileStream.ReadAsync(relativePathBuffer, 0, relativePathSize);
var relativePath = Encoding.UTF8.GetString(relativePathBuffer);
RenderProgressBar((int)fileStream.Position, (int)fileStream.Length, 40);
await fileStream.ReadAsync(sizeBuffer, 0, 4);
var binarySize = BitConverter.ToInt32(sizeBuffer, 0);
var fileInfo = new FileInfo(relativePath);
fileInfo.Directory!.Create();
using var destinationStream = new FileStream(relativePath, FileMode.Create);
while(binarySize > 0)
{
var toRead = Math.Min(binarySize, copyBuffer.Length);
await fileStream.ReadAsync(copyBuffer, 0, toRead);
await destinationStream.WriteAsync(copyBuffer, 0, toRead);
binarySize -= toRead;
RenderProgressBar((int)fileStream.Position, (int)fileStream.Length, 40);
}
}
fileStream.Close();
fileStream.Dispose();
File.Delete(updatePkg);
}
catch (Exception e)
else if (File.Exists(tempFile))
{
Console.WriteLine($"Failed to delete {tempFile}.\n{e}");
Console.WriteLine("Unpacking files...");
try
{
ZipFile.ExtractToDirectory(tempFile, AppContext.BaseDirectory, true);
}
catch
{
}
Console.WriteLine("Deleting package");
try
{
File.Delete(tempFile);
}
catch (Exception e)
{
Console.WriteLine($"Failed to delete {tempFile}.\n{e}");
}
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Unable to find launcher package. Aborting installation");
Console.ReadKey();
return;
}
Console.WriteLine("Launching application");
+5 -4
View File
@@ -1,16 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<TargetFramework>net8.0-windows</TargetFramework>
<IsPackable>false</IsPackable>
<Platforms>AnyCPU;x86;x64</Platforms>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0-release-23468-02" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.2.0" />
<PackageReference Include="MSTest.TestFramework" Version="3.2.0" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -5,7 +5,6 @@ using FluentAssertions;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute;
using System.Collections.Generic;
namespace Daybreak.Tests.Services;
@@ -54,8 +53,8 @@ public class BuildTemplateManagerTests
{
Primary = Profession.Assassin,
Secondary = Profession.None,
Attributes = new List<AttributeEntry>
{
Attributes =
[
new AttributeEntry
{
Attribute = Attribute.DaggerMastery,
@@ -76,9 +75,9 @@ public class BuildTemplateManagerTests
Attribute = Attribute.CriticalStrikes,
Points = 11
}
},
Skills = new List<Skill>
{
],
Skills =
[
Skill.UnsuspectingStrike,
Skill.WildStrike,
Skill.CriticalStrike,
@@ -87,7 +86,7 @@ public class BuildTemplateManagerTests
Skill.CriticalEye,
Skill.CriticalAgility,
Skill.CriticalDefenses
}
]
};
var encoded = this.buildTemplateManager.EncodeTemplate(build);
+6 -5
View File
@@ -23,6 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{41AE
Scripts\BuildRelease.ps1 = Scripts\BuildRelease.ps1
Scripts\CompareVersions.ps1 = Scripts\CompareVersions.ps1
Scripts\GetBuildVersion.ps1 = Scripts\GetBuildVersion.ps1
Scripts\PushFilesToBlobStorage.ps1 = Scripts\PushFilesToBlobStorage.ps1
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0E30DDA0-2111-4E6C-851E-01DC34124FC2}"
@@ -31,7 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.github\CODEOWNERS = .github\CODEOWNERS
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Daybreak.7ZipExtractor", "Daybreak.7ZipExtractor\Daybreak.7ZipExtractor.csproj", "{CA60F9AC-A496-4DB6-970E-ECE73B051C05}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daybreak.7ZipExtractor", "Daybreak.7ZipExtractor\Daybreak.7ZipExtractor.csproj", "{CA60F9AC-A496-4DB6-970E-ECE73B051C05}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -69,8 +70,8 @@ Global
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x86.Build.0 = Release|x86
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x64.ActiveCfg = Debug|x64
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x64.Build.0 = Debug|x64
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x64.ActiveCfg = Debug|x86
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x64.Build.0 = Debug|x86
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x86.ActiveCfg = Debug|x86
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x86.Build.0 = Debug|x86
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -81,8 +82,8 @@ Global
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x86.Build.0 = Release|x86
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x64.ActiveCfg = Debug|Any CPU
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x64.Build.0 = Debug|Any CPU
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x64.ActiveCfg = Debug|x64
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x64.Build.0 = Debug|x64
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x86.ActiveCfg = Debug|x64
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Debug|x86.Build.0 = Debug|x64
{CA60F9AC-A496-4DB6-970E-ECE73B051C05}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -0,0 +1,8 @@
using System;
namespace Daybreak.Attributes;
[AttributeUsage(AttributeTargets.Property)]
public sealed class OptionSynchronizationIgnoreAttribute : Attribute
{
}
@@ -0,0 +1,8 @@
using System;
namespace Daybreak.Attributes;
[AttributeUsage(AttributeTargets.Class)]
public sealed class OptionsSynchronizationIgnoreAttribute : Attribute
{
}
@@ -4,6 +4,7 @@ namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Ascalon Trade Chat")]
[OptionsIgnore]
[OptionsSynchronizationIgnore]
public sealed class AscalonTradeChatOptions : ITradeChatOptions
{
public string HttpsUri { get; set; } = "https://ascalon.gwtoolbox.com/";
@@ -4,7 +4,7 @@ using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Background Provider")]
public sealed class BackgroundProviderOptions
internal sealed class BackgroundProviderOptions
{
[OptionName(Name = "Bloogum Client Enabled", Description = "When enabled, Background Provider will make use of Bloogum to get background images")]
[JsonProperty(nameof(BloogumEnabled))]
@@ -3,9 +3,10 @@ using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Build Synchronization")]
[OptionsName(Name = "Synchronization")]
[OptionsIgnore]
public sealed class BuildSynchronizationOptions
[OptionsSynchronizationIgnore]
internal sealed class SynchronizationOptions
{
[JsonProperty(nameof(ProtectedGraphAccessToken))]
public string? ProtectedGraphAccessToken { get; set; }
@@ -6,8 +6,9 @@ using System.Collections.Generic;
namespace Daybreak.Configuration.Options;
[OptionsIgnore]
public sealed class CredentialManagerOptions
[OptionsSynchronizationIgnore]
internal sealed class CredentialManagerOptions
{
[JsonProperty(nameof(ProtectedLoginCredentials))]
public List<ProtectedLoginCredentials> ProtectedLoginCredentials { get; set; } = new();
public List<ProtectedLoginCredentials> ProtectedLoginCredentials { get; set; } = [];
}
@@ -3,10 +3,11 @@ using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "DSOAL")]
public sealed class DSOALOptions
internal sealed class DSOALOptions
{
[JsonProperty(nameof(Path))]
[OptionName(Name = "Path", Description = "The path to the DSOAL installation")]
[OptionSynchronizationIgnore]
public string? Path { get; set; }
[JsonProperty(nameof(Enabled))]
@@ -4,10 +4,11 @@ using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "DirectSong")]
public sealed class DirectSongOptions
internal sealed class DirectSongOptions
{
[JsonProperty(nameof(Path))]
[OptionName(Name = "Path", Description = "Folder that contains the DirectSong files")]
[OptionSynchronizationIgnore]
public string Path { get; set; } = string.Empty;
[JsonProperty(nameof(Enabled))]
@@ -3,7 +3,7 @@
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Event Notifier")]
public sealed class EventNotifierOptions
internal sealed class EventNotifierOptions
{
[OptionName(Name = "Enabled", Description = "If set to true, Daybreak will notify the user of any event on startup")]
public bool Enabled { get; set; } = true;
@@ -1,5 +1,6 @@
using Daybreak.Attributes;
using Daybreak.Configuration.FocusView;
using Daybreak.Models.Browser;
using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
@@ -49,7 +50,11 @@ public sealed class FocusViewOptions
[OptionName(Name = "Energy Display Mode", Description = "Sets how should the energy display show the information")]
public PointsDisplay EnergyDisplay { get; set; }
[JsonProperty(nameof(BrowserUrl))]
[JsonProperty(nameof(MinimapRotationEnabled))]
[OptionName(Name = "Minimap Rotation", Description = "When enabled, the minimap will rotate according to the player camera")]
public bool MinimapRotationEnabled { get; set; } = true;
[JsonProperty(nameof(BrowserHistory))]
[OptionIgnore]
public string? BrowserUrl { get; set; } = "https://wiki.guildwars.com/wiki/Main_Page";
public BrowserHistory BrowserHistory { get; set; } = new();
}
@@ -4,8 +4,9 @@ using System.Collections.Generic;
namespace Daybreak.Configuration.Options;
[OptionsIgnore]
public sealed class GuildwarsExecutableOptions
[OptionsSynchronizationIgnore]
internal sealed class GuildwarsExecutableOptions
{
[JsonProperty(nameof(ExecutablePaths))]
public List<string> ExecutablePaths { get; set; } = new();
public List<string> ExecutablePaths { get; set; } = [];
}
@@ -3,7 +3,7 @@
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Memory Cache")]
public sealed class ImageCacheOptions
internal sealed class ImageCacheOptions
{
[OptionName(Name = "Image Cache Limit", Description = "The maximum number of MBs that will be used to cache images in memory")]
[OptionRange<double>(MinValue = 0d, MaxValue = 1000d)]
@@ -4,6 +4,7 @@ namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Kamadan Trade Chat")]
[OptionsIgnore]
[OptionsSynchronizationIgnore]
public sealed class KamadanTradeChatOptions : ITradeChatOptions
{
public string HttpsUri { get; set; } = "https://kamadan.gwtoolbox.com/";
@@ -6,8 +6,9 @@ using System.Collections.Generic;
namespace Daybreak.Configuration.Options;
[OptionsIgnore]
public sealed class LaunchConfigurationServiceOptions
[OptionsSynchronizationIgnore]
internal sealed class LaunchConfigurationServiceOptions
{
[JsonProperty(nameof(LaunchConfigurations))]
public List<LaunchConfiguration> LaunchConfigurations { get; set; } = new();
public List<LaunchConfiguration> LaunchConfigurations { get; set; } = [];
}
@@ -2,7 +2,6 @@
using Daybreak.Views;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
namespace Daybreak.Configuration.Options;
@@ -11,11 +10,13 @@ public sealed class LauncherOptions
{
[JsonProperty(nameof(SetGuildwarsWindowSizeOnLaunch))]
[OptionName(Name = "Set GuildWars Window Size On Launch", Description = "Sets the GuildWars window size and position on launch")]
[OptionSynchronizationIgnore]
public bool SetGuildwarsWindowSizeOnLaunch { get; set; }
[JsonProperty(nameof(DesiredGuildwarsScreen))]
[OptionName(Name = "Desired GuildWars Screen", Description = "Sets the screen on which the GuildWars window will be placed")]
[OptionSetterView<ScreenChoiceView>(Action = "Screen Selector")]
[OptionSynchronizationIgnore]
public int DesiredGuildwarsScreen { get; set; }
[JsonProperty(nameof(LaunchGuildwarsAsCurrentUser))]
@@ -24,6 +25,7 @@ public sealed class LauncherOptions
[JsonProperty(nameof(ShortcutLocation))]
[OptionName(Name = "Shortcut Location", Description = "Location where the shortcut will be placed")]
[OptionSynchronizationIgnore]
public string? ShortcutLocation { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
[JsonProperty(nameof(PlaceShortcut))]
@@ -50,4 +52,12 @@ public sealed class LauncherOptions
[JsonProperty(nameof(PersistentLogging))]
[OptionName(Name = "Persistent Logging", Description = "If true, the launcher will save logs in the local database. Otherwise, the launcher will only keep logs in a memory cache")]
public bool PersistentLogging { get; set; } = false;
[JsonProperty(nameof(BetaUpdate))]
[OptionName(Name = "Beta Update", Description = "If true, the launcher will use the new update procedure")]
public bool BetaUpdate { get; set; } = true;
[JsonProperty(nameof(AutoBackupSettings))]
[OptionName(Name = "Auto Backup Settings", Description = "If true, the launcher will attempt to backup settings periodically")]
public bool AutoBackupSettings { get; set; } = false;
}
@@ -4,7 +4,8 @@ namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Logging Options")]
[OptionsIgnore]
public sealed class LoggingOptions : ILiteCollectionOptions<Models.Log>
[OptionsSynchronizationIgnore]
internal sealed class LoggingOptions : ILiteCollectionOptions<Models.Log>
{
public string CollectionName => "logs";
}
@@ -4,7 +4,7 @@ using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Memory Reader")]
public sealed class MemoryReaderOptions
internal sealed class MemoryReaderOptions
{
[JsonProperty(nameof(MemoryReaderFrequency))]
[OptionRange<double>(MinValue = 0, MaxValue = 1000)]
@@ -4,6 +4,7 @@ using Daybreak.Services.Notifications.Models;
namespace Daybreak.Configuration.Options;
[OptionsIgnore]
[OptionsSynchronizationIgnore]
internal sealed class NotificationStorageOptions : ILiteCollectionOptions<NotificationDTO>
{
public string CollectionName => "notifications";
@@ -4,21 +4,13 @@ using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Pathfinding")]
public sealed class PathfindingOptions
internal sealed class PathfindingOptions
{
[JsonProperty(nameof(EnablePathfinding))]
[OptionName(Name = "Enable Pathfinding", Description = "If true, the pathfinder will attempt to produce paths from the player position to objectives")]
public bool EnablePathfinding { get; set; } = true;
[JsonProperty(nameof(ImprovedPathfinding))]
[OptionName(Name = "Distance-Based Pathfinding", Description = "If true, the pathfinder will attempt use an improved algorithm to find paths. Slower but generally more precise")]
public bool ImprovedPathfinding { get; set; } = false;
[JsonProperty(nameof(OptimizePaths))]
[OptionName(Name = "Path Optimization", Description = "If true, the pathfinder will attempt to optimize paths. Slower but generally more precise")]
public bool OptimizePaths { get; set; } = true;
[JsonProperty(nameof(UseCaching))]
[OptionName(Name = "Use Caching", Description = "If true, the pathfinder will use more memory to cache parts of the pathfinding algorithm")]
public bool UseCaching { get; set; } = true;
[JsonProperty(nameof(HighSensitivity))]
[OptionName(Name = "High Sensitivity", Description = "If true, the pathfinder generate much more accurate paths. This will greatly increase memory usage and map load times")]
public bool HighSensitivity { get; set; } = false;
}
@@ -5,7 +5,8 @@ using System.Collections.Generic;
namespace Daybreak.Configuration.Options;
[OptionsIgnore]
public sealed class PluginsServiceOptions
[OptionsSynchronizationIgnore]
internal sealed class PluginsServiceOptions
{
public List<PluginEntry> EnabledPlugins { get; set; } = new();
public List<PluginEntry> EnabledPlugins { get; set; } = [];
}
@@ -7,7 +7,8 @@ namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Price History")]
[OptionsIgnore]
public sealed class PriceHistoryOptions : ILiteCollectionOptions<TraderQuoteDTO>
[OptionsSynchronizationIgnore]
internal sealed class PriceHistoryOptions : ILiteCollectionOptions<TraderQuoteDTO>
{
public string HttpsUri { get; set; } = "https://kamadan.gwtoolbox.com/";
@@ -15,5 +16,5 @@ public sealed class PriceHistoryOptions : ILiteCollectionOptions<TraderQuoteDTO>
public TimeSpan UpdateInterval { get; set; } = TimeSpan.FromHours(1);
public Dictionary<string, DateTime> ItemHistoryMetadata { get; set; } = new();
public Dictionary<string, DateTime> ItemHistoryMetadata { get; set; } = [];
}
@@ -4,7 +4,7 @@ using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "ReShade")]
public sealed class ReShadeOptions
internal sealed class ReShadeOptions
{
[JsonProperty(nameof(Enabled))]
[OptionName(Name = "Enabled", Description = "If true, Daybreak will attempt to inject ReShade into the starting Guild Wars executable")]
@@ -4,7 +4,8 @@ namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Screen Manager")]
[OptionsIgnore]
public sealed class ScreenManagerOptions
[OptionsSynchronizationIgnore]
internal sealed class ScreenManagerOptions
{
public double X { get; set; }
public double Y { get; set; }
@@ -3,7 +3,7 @@
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Sounds")]
public sealed class SoundOptions
internal sealed class SoundOptions
{
[OptionName(Name = "Sounds Enabled", Description = "If enabled, the client will play sounds.")]
public bool Enabled { get; set; }
@@ -21,6 +21,7 @@ public sealed class ThemeOptions
[OptionName(Name = "Blur Background", Description = "If true, the background image will be blurred")]
public bool BackgroundBlur { get; set; } = false;
[OptionIgnore]
[OptionName(Name = "Wintersday Mode", Description = "If true, Daybreak will apply a Wintersday theme")]
public bool WintersdayMode { get; set; } = false;
public bool WintersdayMode => false;
}
@@ -4,10 +4,11 @@ using Newtonsoft.Json;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "GWToolbox")]
public sealed class ToolboxOptions
internal sealed class ToolboxOptions
{
[JsonProperty(nameof(DllPath))]
[OptionName(Name = "DllPath", Description = "The path to GWToolboxdll.dll")]
[OptionSynchronizationIgnore]
public string? DllPath { get; set; }
[JsonProperty(nameof(Enabled))]
@@ -5,10 +5,21 @@ using System.Collections.Generic;
namespace Daybreak.Configuration.Options;
[OptionsIgnore]
public sealed class TradeAlertingOptions
[OptionsName(Name = "Trade Alerts")]
internal sealed class TradeAlertingOptions
{
[OptionIgnore]
[OptionSynchronizationIgnore]
public TimeSpan MaxLookbackPeriod { get; set; } = TimeSpan.FromDays(31);
[OptionIgnore]
[OptionSynchronizationIgnore]
public DateTime LastCheckTime { get; set; } = DateTime.MinValue;
public List<TradeAlert> Alerts { get; set; } = new();
[OptionIgnore]
public List<ITradeAlert> Alerts { get; set; } = [];
[OptionName(Name = "Quote Alerts Interval", Description = "The amount of seconds in between checking for alerts based on trade quotes")]
[OptionRange<double>(MinValue = 30d, MaxValue = 1440d)]
public double QuoteAlertsInterval { get; set; } = 30;
}
@@ -4,7 +4,8 @@ using Daybreak.Services.TradeChat.Models;
namespace Daybreak.Configuration.Options;
[OptionsIgnore]
public sealed class TraderMessagesOptions : ILiteCollectionOptions<TraderMessageDTO>
[OptionsSynchronizationIgnore]
internal sealed class TraderMessagesOptions : ILiteCollectionOptions<TraderMessageDTO>
{
public string CollectionName => "trader_messages";
}
@@ -4,15 +4,16 @@ using System;
namespace Daybreak.Configuration.Options;
[OptionsName(Name = "Trader Quotes")]
public sealed class TraderQuotesOptions
[OptionsSynchronizationIgnore]
internal sealed class TraderQuotesOptions
{
[OptionIgnore]
public string HttpsUri { get; set; } = "https://kamadan.gwtoolbox.com/";
[OptionIgnore]
public DateTime LastCheckTime { get; set;} = DateTime.MinValue;
[OptionName(Name = "Cache Update Interval", Description = "The amount of minutes in between cache updates")]
[OptionName(Name = "Cache Update Interval", Description = "The amount of minutes in between cache updates")]
[OptionRange<double>(MinValue = 30d, MaxValue = 1440d)]
public double CacheUpdateInterval { get; set; } = 60;
}
@@ -8,10 +8,6 @@ namespace Daybreak.Configuration.Options;
[OptionsName(Name = "uMod")]
public sealed class UModOptions
{
[JsonProperty(nameof(DllPath))]
[OptionName(Name = "Dll Path", Description = "The path to the uMod dll")]
public string? DllPath { get; set; }
[JsonProperty(nameof(Enabled))]
[OptionName(Name = "Enabled", Description = "If true, Daybreak will also launch uMod when launching GuildWars")]
public bool Enabled { get; set; }
@@ -22,5 +18,6 @@ public sealed class UModOptions
[JsonProperty(nameof(Mods))]
[OptionIgnore]
public List<UModEntry> Mods { get; set; } = new();
[OptionSynchronizationIgnore]
public List<UModEntry> Mods { get; set; } = [];
}
+30 -16
View File
@@ -70,7 +70,6 @@ using Daybreak.Services.Events;
using Daybreak.Controls;
using Daybreak.Models.Plugins;
using Daybreak.Services.Plugins;
using Daybreak.Services.UMod.Utilities;
using Daybreak.Services.Toolbox.Utilities;
using Daybreak.Services.Injection;
using Daybreak.Services.ReShade;
@@ -81,8 +80,10 @@ using Daybreak.Views.Launch;
using Daybreak.Services.GWCA;
using Daybreak.Services.DirectSong;
using Daybreak.Views.Onboarding.DirectSong;
using System.Xml.Linq;
using Daybreak.Services.SevenZip;
using Daybreak.Services.ReShade.Notifications;
using Daybreak.Services.UBlockOrigin;
using Daybreak.Services.Browser;
namespace Daybreak.Configuration;
@@ -157,10 +158,9 @@ public class ProjectConfiguration : PluginConfigurationBase
.WithMessageHandler(this.SetupLoggingAndMetrics<UModService>)
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
.Build()
.RegisterHttpClient<UModClient>()
.WithMessageHandler(this.SetupLoggingAndMetrics<UModClient>)
.RegisterHttpClient<UBlockOriginService>()
.WithMessageHandler(this.SetupLoggingAndMetrics<UBlockOriginService>)
.WithDefaultRequestHeadersSetup(this.SetupDaybreakUserAgent)
.WithTimeout(TimeSpan.FromSeconds(30))
.Build();
}
@@ -196,19 +196,19 @@ public class ProjectConfiguration : PluginConfigurationBase
services.AddSingleton<IPostUpdateActionProducer>(sp => sp.GetRequiredService<PostUpdateActionManager>());
services.AddSingleton<IPostUpdateActionProvider>(sp => sp.GetRequiredService<PostUpdateActionManager>());
services.AddSingleton<IMenuService, MenuService>();
services.AddSingleton<IMenuServiceInitializer, MenuService>(sp => sp.GetRequiredService<IMenuService>().As<MenuService>()!);
services.AddSingleton<IMenuServiceInitializer, MenuService>(sp => sp.GetRequiredService<IMenuService>().Cast<MenuService>());
services.AddSingleton<ILiteDatabase, LiteDatabase>(sp => new LiteDatabase("Daybreak.db"));
services.AddSingleton<IMutexHandler, MutexHandler>();
services.AddSingleton<IShortcutManager, ShortcutManager>();
services.AddSingleton<IMetricsService, MetricsService>();
services.AddSingleton<IStartupActionProducer, StartupActionManager>();
services.AddSingleton<IOptionsProducer, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().As<OptionsManager>()!);
services.AddSingleton<IOptionsUpdateHook, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().As<OptionsManager>()!);
services.AddSingleton<IOptionsProvider, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().As<OptionsManager>()!);
services.AddSingleton<IOptionsProducer, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().Cast<OptionsManager>());
services.AddSingleton<IOptionsUpdateHook, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().Cast<OptionsManager>());
services.AddSingleton<IOptionsProvider, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().Cast<OptionsManager>());
services.AddSingleton<IThemeManager, ThemeManager>();
services.AddSingleton<INotificationService, NotificationService>();
services.AddSingleton<INotificationProducer, NotificationService>(sp => sp.GetRequiredService<INotificationService>().As<NotificationService>()!);
services.AddSingleton<INotificationHandlerProducer, NotificationService>(sp => sp.GetRequiredService<INotificationService>().As<NotificationService>()!);
services.AddSingleton<INotificationProducer, NotificationService>(sp => sp.GetRequiredService<INotificationService>().Cast<NotificationService>());
services.AddSingleton<INotificationHandlerProducer, NotificationService>(sp => sp.GetRequiredService<INotificationService>().Cast<NotificationService>());
services.AddSingleton<ILiveChartInitializer, LiveChartInitializer>();
services.AddSingleton<IImageCache, ImageCache>();
services.AddSingleton<ISoundService, SoundService>();
@@ -224,6 +224,10 @@ public class ProjectConfiguration : PluginConfigurationBase
services.AddSingleton<IGWCAClient, GWCAClient>();
services.AddSingleton<IGuildwarsMemoryReader, GWCAMemoryReader>();
services.AddSingleton<ISevenZipExtractor, SevenZipExtractor>();
services.AddSingleton<IGraphClient, GraphClient>();
services.AddSingleton<IOptionsSynchronizationService, OptionsSynchronizationService>();
services.AddScoped<IBrowserExtensionsManager, BrowserExtensionsManager>();
services.AddScoped<IBrowserExtensionsProducer, BrowserExtensionsManager>(sp => sp.GetRequiredService<IBrowserExtensionsManager>().Cast<BrowserExtensionsManager>());
services.AddScoped<ICredentialManager, CredentialManager>();
services.AddScoped<IApplicationLauncher, ApplicationLauncher>();
services.AddScoped<IScreenshotProvider, ScreenshotProvider>();
@@ -233,14 +237,13 @@ public class ProjectConfiguration : PluginConfigurationBase
services.AddScoped<IIconCache, IconCache>();
services.AddScoped<IPrivilegeManager, PrivilegeManager>();
services.AddScoped<IScreenManager, ScreenManager>();
services.AddScoped<IGraphClient, GraphClient>();
services.AddScoped<IPathfinder, SharpNavPathfinder>();
services.AddScoped<IOnboardingService, OnboardingService>();
services.AddScoped<IExperienceCalculator, ExperienceCalculator>();
services.AddScoped<IAttributePointCalculator, AttributePointCalculator>();
services.AddScoped<IDownloadService, DownloadService>();
services.AddScoped<IGuildwarsInstaller, GuildwarsInstaller>();
services.AddScoped<IExceptionHandler, ExceptionHandler>();
services.AddScoped<IPathfinder, StupidPathfinder>();
services.AddScoped<IDrawingService, DrawingService>();
services.AddScoped<IDrawingModuleProducer, DrawingService>(sp => sp.GetRequiredService<IDrawingService>().As<DrawingService>()!);
services.AddScoped<ITradeChatService<KamadanTradeChatOptions>, TradeChatService<KamadanTradeChatOptions>>();
@@ -255,10 +258,10 @@ public class ProjectConfiguration : PluginConfigurationBase
services.AddScoped<IRegistryService, RegistryService>();
services.AddScoped<IEventNotifierService, EventNotifierService>();
services.AddScoped<IBackgroundProvider, BackgroundProvider>();
services.AddScoped<IUModClient, UModClient>();
services.AddScoped<IToolboxClient, ToolboxClient>();
services.AddScoped<IProcessInjector, ProcessInjector>();
services.AddScoped<ILaunchConfigurationService, LaunchConfigurationService>();
services.AddScoped<IBrowserHistoryManager, BrowserHistoryManager>();
}
public override void RegisterViews(IViewProducer viewProducer)
@@ -301,6 +304,8 @@ public class ProjectConfiguration : PluginConfigurationBase
viewProducer.RegisterView<TradeAlertsView>();
viewProducer.RegisterView<TradeAlertSetupView>();
viewProducer.RegisterView<TradeNotificationView>();
viewProducer.RegisterView<TradeAlertsChoiceView>();
viewProducer.RegisterView<QuoteAlertSetupView>();
viewProducer.RegisterView<GuildwarsCopySelectionView>();
viewProducer.RegisterView<GuildwarsCopyView>();
viewProducer.RegisterView<DSOALInstallingView>();
@@ -324,6 +329,7 @@ public class ProjectConfiguration : PluginConfigurationBase
viewProducer.RegisterView<DirectSongInstallationChoiceView>();
viewProducer.RegisterView<DirectSongOnboardingEntryView>();
viewProducer.RegisterView<DirectSongSwitchView>();
viewProducer.RegisterView<SettingsSynchronizationView>();
}
public override void RegisterStartupActions(IStartupActionProducer startupActionProducer)
@@ -332,6 +338,7 @@ public class ProjectConfiguration : PluginConfigurationBase
startupActionProducer.RegisterAction<RenameInstallerAction>();
startupActionProducer.RegisterAction<FixSymbolicLinkStartupAction>();
startupActionProducer.RegisterAction<UpdateUModAction>();
}
public override void RegisterPostUpdateActions(IPostUpdateActionProducer postUpdateActionProducer)
@@ -396,7 +403,7 @@ public class ProjectConfiguration : PluginConfigurationBase
optionsProducer.RegisterOptions<ThemeOptions>();
optionsProducer.RegisterOptions<BrowserOptions>();
optionsProducer.RegisterOptions<BuildSynchronizationOptions>();
optionsProducer.RegisterOptions<SynchronizationOptions>();
optionsProducer.RegisterOptions<FocusViewOptions>();
optionsProducer.RegisterOptions<MemoryReaderOptions>();
@@ -434,19 +441,26 @@ public class ProjectConfiguration : PluginConfigurationBase
notificationHandlerProducer.RegisterNotificationHandler<TradeMessageNotificationHandler>();
notificationHandlerProducer.RegisterNotificationHandler<FixSymbolicLinkNotificationHandler>();
notificationHandlerProducer.RegisterNotificationHandler<UpdateNotificationHandler>();
notificationHandlerProducer.RegisterNotificationHandler<ReShadeConfigChangedHandler>();
}
public override void RegisterMods(IModsManager modsManager)
{
modsManager.RegisterMod<IReShadeService, ReShadeService>();
modsManager.RegisterMod<IUModService, UModService>();
modsManager.RegisterMod<IToolboxService, ToolboxService>();
modsManager.RegisterMod<IDSOALService, DSOALService>();
modsManager.RegisterMod<IGuildwarsScreenPlacer, GuildwarsScreenPlacer>();
modsManager.RegisterMod<IReShadeService, ReShadeService>();
modsManager.RegisterMod<IGWCAInjector, GWCAInjector>();
modsManager.RegisterMod<IDirectSongService, DirectSongService>(singleton: true);
}
public override void RegisterBrowserExtensions(IBrowserExtensionsProducer browserExtensionsProducer)
{
browserExtensionsProducer.ThrowIfNull();
browserExtensionsProducer.RegisterExtension<UBlockOriginService>();
}
private void RegisterLiteCollections(IServiceCollection services)
{
this.RegisterLiteCollection<Models.Log, LoggingOptions>(services);
+2 -4
View File
@@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Controls.Buttons"
xmlns:glyphs="clr-namespace:Daybreak.Controls.Glyphs"
mc:Ignorable="d"
x:Name="_this"
Cursor="Hand"
@@ -14,10 +15,7 @@
Clicked="HighlightButton_Clicked">
<local:CircularButton.Content>
<Viewbox Stretch="Fill" Width="60" Height="60">
<Grid Width="30" Height="30" Margin="-2, 0, 0 ,0">
<Path Fill="{DynamicResource MahApps.Brushes.ThemeForeground}" VerticalAlignment="Top" HorizontalAlignment="Left"
Data="m18.87,9.41l-5.58,5.59l5.58,5.59a1,1 0 0 1 0,1.41l0,0a1,1 0 0 1 -1.41,0l-6.36,-6.36a0.91,0.91 0 0 1 0,-1.28l6.36,-6.36a1,1 0 0 1 1.41,0l0,0a1,1 0 0 1 0,1.41z"></Path>
</Grid>
<glyphs:ArrowGlyph />
</Viewbox>
</local:CircularButton.Content>
</local:CircularButton>
@@ -10,6 +10,7 @@
mc:Ignorable="d"
Loaded="UserControl_Loaded"
Unloaded="UserControl_Unloaded"
PreviewMouseDown="Browser_PreviewMouseDown"
x:Name="_this"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
@@ -51,11 +52,11 @@
<WrapPanel>
<buttons:BackButton Height="30" Width="30"
Clicked="BackButton_Clicked" Margin="5" Cursor="Hand"
IsEnabled="{Binding ElementName=WebBrowser, Path=CanGoBack, Mode=OneWay}"
IsEnabled="{Binding ElementName=_this, Path=BrowserHistoryManager.CanGoBack, Mode=OneWay}"
ToolTip="Go back"/>
<buttons:BackButton Height="30" Width="30"
Clicked="ForwardButton_Clicked" Margin="5" Cursor="Hand"
IsEnabled="{Binding ElementName=WebBrowser, Path=CanGoForward, Mode=OneWay}"
IsEnabled="{Binding ElementName=_this, Path=BrowserHistoryManager.CanGoForward, Mode=OneWay}"
ToolTip="Go forward">
<buttons:BackButton.RenderTransform>
<RotateTransform Angle="180" CenterX="15" CenterY="15"></RotateTransform>
@@ -3,12 +3,14 @@ using Daybreak.Configuration.Options;
using Daybreak.Models;
using Daybreak.Models.Browser;
using Daybreak.Models.Guildwars;
using Daybreak.Services.Browser;
using Daybreak.Services.BuildTemplates;
using Daybreak.Utils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Web.WebView2.Core;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Core.Extensions;
using System.Diagnostics;
@@ -21,6 +23,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Extensions;
using System.Windows.Input;
namespace Daybreak.Controls;
@@ -39,10 +42,10 @@ public partial class ChromiumBrowserWrapper : UserControl
private const string BrowserSearchLink = $"https://www.google.com/search?q={BrowserSearchPlaceholder}";
private const string BrowserDownloadLink = "https://developer.microsoft.com/en-us/microsoft-edge/webview2/";
private static readonly Regex WebAddressRegex = new("^((http|ftp|https)://)?([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?", RegexOptions.Compiled);
private static readonly object Lock = new();
private static readonly Regex WebAddressRegex = BuildWebAddressRegex();
private static readonly SemaphoreSlim SemaphoreSlim = new(1, 1);
private static CoreWebView2Environment? CoreWebView2Environment;
private static CoreWebView2Environment? CoreWebView2Environment;
public event EventHandler<string>? FavoriteUriChanged;
public event EventHandler? MaximizeClicked;
@@ -50,12 +53,16 @@ public partial class ChromiumBrowserWrapper : UserControl
public event EventHandler<DownloadPayload>? DownloadingFile;
public event EventHandler<string>? DownloadedFile;
private readonly HashSet<ulong> domNavigationIds = [];
private readonly Task initializationTask;
private readonly IHttpClient<ChromiumBrowserWrapper> httpClient;
private readonly ILiveOptions<BrowserOptions> liveOptions;
private readonly ILogger<ChromiumBrowserWrapper> logger;
private readonly IBuildTemplateManager buildTemplateManager;
private readonly IBrowserHistoryManager historyManager;
private readonly IBrowserExtensionsManager browserExtensionsManager;
[GenerateDependencyProperty(InitialValue = true)]
private bool canDownloadBuild;
[GenerateDependencyProperty(InitialValue = true)]
@@ -95,8 +102,13 @@ public partial class ChromiumBrowserWrapper : UserControl
set => this.SetValue(AddressProperty, value);
}
public IBrowserHistoryManager BrowserHistoryManager => this.historyManager;
public ChromiumBrowserWrapper()
: this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IHttpClient<ChromiumBrowserWrapper>>(),
: this(
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBrowserHistoryManager>(),
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBrowserExtensionsManager>(),
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IHttpClient<ChromiumBrowserWrapper>>(),
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<BrowserOptions>>(),
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBuildTemplateManager>(),
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILogger<ChromiumBrowserWrapper>>())
@@ -104,18 +116,22 @@ public partial class ChromiumBrowserWrapper : UserControl
}
public ChromiumBrowserWrapper(
IBrowserHistoryManager historyManager,
IBrowserExtensionsManager browserExtensionsManager,
IHttpClient<ChromiumBrowserWrapper> httpClient,
ILiveOptions<BrowserOptions> liveOptions,
IBuildTemplateManager buildTemplateManager,
ILogger<ChromiumBrowserWrapper> logger)
{
this.historyManager = historyManager.ThrowIfNull();
this.browserExtensionsManager = browserExtensionsManager.ThrowIfNull();
this.httpClient = httpClient.ThrowIfNull();
this.liveOptions = liveOptions.ThrowIfNull();
this.buildTemplateManager = buildTemplateManager.ThrowIfNull();
this.logger = logger.ThrowIfNull();
this.InitializeEnvironment();
this.InitializeComponent();
this.historyManager.InitializeHistoryManager(this);
this.initializationTask = Task.Run(this.InitializeBrowserSafe);
}
@@ -149,24 +165,22 @@ public partial class ChromiumBrowserWrapper : UserControl
{
try
{
lock (Lock)
if (CoreWebView2Environment is not null)
{
if (CoreWebView2Environment is not null)
{
this.BrowserSupported = true;
return;
}
CoreWebView2Environment ??= System.Extensions.TaskExtensions.RunSync(() => CoreWebView2Environment.CreateAsync(null, "BrowserData", new CoreWebView2EnvironmentOptions
{
EnableTrackingPrevention = true,
AllowSingleSignOnUsingOSPrimaryAccount = true
}));
this.BrowserSupported = true;
return;
}
CoreWebView2Environment ??= System.Extensions.TaskExtensions.RunSync(() => CoreWebView2Environment.CreateAsync(null, "BrowserData", new CoreWebView2EnvironmentOptions
{
EnableTrackingPrevention = true,
AllowSingleSignOnUsingOSPrimaryAccount = true,
AreBrowserExtensionsEnabled = true,
}));
this.BrowserSupported = true;
}
catch(Exception e)
catch (Exception e)
{
this.logger!.LogWarning($"Browser initialization failed. Details: {e}");
this.BrowserSupported = false;
@@ -177,10 +191,7 @@ public partial class ChromiumBrowserWrapper : UserControl
{
await this.Dispatcher.InvokeAsync(async () =>
{
while (!Monitor.TryEnter(Lock))
{
await Task.Delay(100);
}
await SemaphoreSlim.WaitAsync();
try
{
@@ -189,7 +200,7 @@ public partial class ChromiumBrowserWrapper : UserControl
}
finally
{
Monitor.Exit(Lock);
SemaphoreSlim.Release();
}
});
}
@@ -201,12 +212,18 @@ public partial class ChromiumBrowserWrapper : UserControl
if (!this.BrowserSupported ||
!this.BrowserEnabled)
{
return;
}
if (this.WebBrowser.CoreWebView2 is not null)
{
return;
}
this.ShowBrowserDisabledMessage = false;
await this.WebBrowser.EnsureCoreWebView2Async(CoreWebView2Environment);
await this.WebBrowser.EnsureCoreWebView2Async(CoreWebView2Environment).ConfigureAwait(true);
await this.browserExtensionsManager.InitializeBrowserEnvironment(this.WebBrowser.CoreWebView2!.Profile, CoreWebView2Environment!.BrowserVersionString).ConfigureAwait(true);
if (this.Address is not null &&
Uri.TryCreate(this.Address, UriKind.RelativeOrAbsolute, out var uri))
{
@@ -217,6 +234,21 @@ public partial class ChromiumBrowserWrapper : UserControl
this.AddressBarReadonly = this.liveOptions!.Value.AddressBarReadonly;
this.CanDownloadBuild = this.liveOptions.Value.DynamicBuildLoading;
this.WebBrowser.CoreWebView2.NewWindowRequested += (browser, args) => args.Handled = true;
this.WebBrowser.KeyDown += (sender, e) =>
{
if ((e.Key == Key.Left && Keyboard.Modifiers == ModifierKeys.Alt) ||
(e.Key == Key.BrowserBack))
{
this.BrowserHistoryManager.GoBack();
e.Handled = true; // Prevent default behavior
}
else if ((e.Key == Key.Right && Keyboard.Modifiers == ModifierKeys.Alt) ||
(e.Key == Key.BrowserForward))
{
this.BrowserHistoryManager.GoForward();
e.Handled = true; // Prevent default behavior
}
};
this.WebBrowser.NavigationStarting += (browser, args) =>
{
if (this.CanNavigate is false && args.Uri != this.Address)
@@ -271,6 +303,13 @@ public partial class ChromiumBrowserWrapper : UserControl
};
this.WebBrowser.CoreWebView2.DOMContentLoaded += async (browser, args) =>
{
if (this.domNavigationIds.Contains(args.NavigationId))
{
return;
}
this.domNavigationIds.Add(args.NavigationId);
await this.WebBrowser.CoreWebView2.ExecuteScriptAsync(Scripts.CaptureNavigationButtons);
if (this.CanDownloadBuild)
{
await this.WebBrowser.CoreWebView2.ExecuteScriptAsync(Scripts.SendSelectionOnContextMenu);
@@ -376,12 +415,12 @@ public partial class ChromiumBrowserWrapper : UserControl
{
payload = args.WebMessageAsJson.Deserialize<BrowserPayload>();
}
catch(Exception e)
catch (Exception e)
{
this.logger!.LogError(e, $"Exception encountered when deserializing {nameof(BrowserPayload)}");
}
if (payload?.Key == BrowserPayload.PayloadKeys.ContextMenu)
if (payload?.Key is BrowserPayload.PayloadKeys.ContextMenu)
{
var contextMenuPayload = args.WebMessageAsJson.Deserialize<BrowserPayload<OnContextMenuPayload>>();
var maybeTemplate = contextMenuPayload?.Value?.Selection?.Trim();
@@ -411,12 +450,20 @@ public partial class ChromiumBrowserWrapper : UserControl
this.ContextMenu.IsOpen = true;
});
}
catch(Exception e)
catch (Exception e)
{
this.logger!.LogWarning($"Exception when decoding template {maybeTemplate}. Details {e}");
}
});
}
else if (payload?.Key is BrowserPayload.PayloadKeys.XButton1Pressed)
{
this.BrowserHistoryManager.GoBack();
}
else if (payload?.Key is BrowserPayload.PayloadKeys.XButton2Pressed)
{
this.BrowserHistoryManager.GoForward();
}
}
private void DownloadOperation_StateChanged(object? sender, object? e)
@@ -461,26 +508,24 @@ public partial class ChromiumBrowserWrapper : UserControl
return;
}
this.historyManager.UnInitializeHistoryManager();
this.WebBrowser?.Dispose();
this.browserInitialized = false;
}
private void BackButton_Clicked(object sender, EventArgs e)
{
this.WebBrowser.GoBack();
this.Address = this.WebBrowser.Source.ToString();
this.historyManager.GoBack();
}
private void ForwardButton_Clicked(object sender, EventArgs e)
{
this.WebBrowser.GoForward();
this.Address = this.WebBrowser.Source.ToString();
this.historyManager.GoForward();
}
private void RefreshGlyph_Clicked(object sender, EventArgs e)
{
this.WebBrowser.Reload();
this.Address = this.WebBrowser.Source.ToString();
this.BrowserHistoryManager.Reload();
}
private void CancelGlyph_Clicked(object sender, EventArgs e)
@@ -504,6 +549,11 @@ public partial class ChromiumBrowserWrapper : UserControl
this.MaximizeClicked?.Invoke(this, e);
}
private void Browser_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
}
private void CheckFavoriteAddress()
{
if (this.Address == this.FavoriteAddress)
@@ -541,4 +591,7 @@ public partial class ChromiumBrowserWrapper : UserControl
Uri.TryCreate(address, UriKind.Absolute, out var uri);
return uri?.ToString() ?? string.Empty;
}
[GeneratedRegex("^((http|ftp|https)://)?([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?", RegexOptions.Compiled)]
private static partial Regex BuildWebAddressRegex();
}
+76
View File
@@ -0,0 +1,76 @@
<UserControl x:Class="Daybreak.Controls.DropDownButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Controls"
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
xmlns:glyphs="clr-namespace:Daybreak.Controls.Glyphs"
xmlns:converters="clr-namespace:Daybreak.Converters"
mc:Ignorable="d"
x:Name="_this"
Tag="{Binding RelativeSource={RelativeSource Self}}"
MouseRightButtonDown="IgnoreRightMouseButton"
MouseRightButtonUp="IgnoreRightMouseButton"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<converters:BooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" TriggerValue="True"/>
</UserControl.Resources>
<UserControl.ContextMenu>
<ContextMenu Placement="Bottom">
<ContextMenu.Template>
<ControlTemplate>
<local:DropDownButtonContextMenu
Items="{Binding PlacementTarget.Tag.Items, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
ItemTemplate="{Binding PlacementTarget.Tag.ItemTemplate, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
Background="{Binding PlacementTarget.Tag.Background, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
Width="{Binding PlacementTarget.Tag.ActualWidth, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
ItemClicked="DropDownButtonContextMenu_ItemClicked"/>
</ControlTemplate>
</ContextMenu.Template>
</ContextMenu>
</UserControl.ContextMenu>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<buttons:HighlightButton Grid.Column="0"
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center"
Clicked="MainButton_Clicked">
<buttons:HighlightButton.ButtonContent>
<ContentControl ContentTemplate="{Binding ItemTemplate, RelativeSource={RelativeSource AncestorType={x:Type local:DropDownButton}}}"
Content="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={x:Type local:DropDownButton}}}" />
</buttons:HighlightButton.ButtonContent>
</buttons:HighlightButton>
<buttons:HighlightButton Grid.Column="1"
Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Clicked="ArrowButton_Clicked">
<buttons:HighlightButton.ButtonContent>
<glyphs:ArrowGlyph Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
Height="30"
Width="30"
VerticalAlignment="Center"
HorizontalAlignment="Center"
RenderTransformOrigin="0.5 0.5">
<glyphs:ArrowGlyph.RenderTransform>
<RotateTransform Angle="270"/>
</glyphs:ArrowGlyph.RenderTransform>
</glyphs:ArrowGlyph>
</buttons:HighlightButton.ButtonContent>
</buttons:HighlightButton>
<Rectangle Opacity="0.2"
Fill="Black"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Visibility="{Binding ElementName=_this, Path=ClickEnabled, Mode=OneWay, Converter={StaticResource InverseBooleanToVisibilityConverter}}"/>
</Grid>
</UserControl>
+60
View File
@@ -0,0 +1,60 @@
using System;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Extensions;
using System.Windows.Input;
namespace Daybreak.Controls;
/// <summary>
/// Interaction logic for DropdownButton.xaml
/// </summary>
public partial class DropDownButton : UserControl
{
[GenerateDependencyProperty]
private DataTemplate itemTemplate = default!;
[GenerateDependencyProperty]
private object selectedItem = default!;
[GenerateDependencyProperty]
private IEnumerable items = default!;
[GenerateDependencyProperty(InitialValue = true)]
private bool clickEnabled = true;
public event EventHandler<object> Clicked = default!;
public event EventHandler<object> SelectionChanged = default!;
public DropDownButton()
{
this.InitializeComponent();
}
private void MainButton_Clicked(object sender, EventArgs e)
{
this.Clicked?.Invoke(this, this.SelectedItem);
}
private void ArrowButton_Clicked(object sender, EventArgs e)
{
var contextMenu = this.ContextMenu;
contextMenu.PlacementTarget = this;
contextMenu.IsOpen = true;
}
private void DropDownButtonContextMenu_ItemClicked(object _, object e)
{
this.SelectedItem = e;
this.ContextMenu.IsOpen = false;
this.SelectionChanged?.Invoke(this, e);
}
private void IgnoreRightMouseButton(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton is MouseButton.Right)
{
e.Handled = true;
}
}
}
@@ -0,0 +1,29 @@
<UserControl x:Class="Daybreak.Controls.DropDownButtonContextMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Controls"
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
mc:Ignorable="d"
x:Name="_this"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ItemsControl ItemsSource="{Binding ElementName=_this, Path=Items, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<buttons:HighlightButton HighlightColor="{DynamicResource MahApps.Brushes.Accent}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Tag="{Binding Mode=OneWay}"
Clicked="HighlightButton_Clicked">
<buttons:HighlightButton.ButtonContent>
<ContentControl DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type buttons:HighlightButton}}}"
ContentTemplate="{Binding ItemTemplate, RelativeSource={RelativeSource AncestorType={x:Type local:DropDownButtonContextMenu}}}"/>
</buttons:HighlightButton.ButtonContent>
</buttons:HighlightButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
@@ -0,0 +1,32 @@
using Daybreak.Controls.Buttons;
using System;
using System.Collections;
using System.Extensions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Extensions;
namespace Daybreak.Controls;
/// <summary>
/// Interaction logic for DropDownButtonContextMenu.xaml
/// </summary>
public partial class DropDownButtonContextMenu : UserControl
{
[GenerateDependencyProperty]
private DataTemplate itemTemplate = default!;
[GenerateDependencyProperty]
private IEnumerable items = default!;
public event EventHandler<object> ItemClicked = default!;
public DropDownButtonContextMenu()
{
this.InitializeComponent();
}
private void HighlightButton_Clicked(object sender, EventArgs e)
{
this.ItemClicked?.Invoke(this, sender.Cast<HighlightButton>().DataContext);
}
}
@@ -20,7 +20,7 @@ public partial class ExpandableMenuSection : UserControl
[GenerateDependencyProperty(InitialValue = false)]
private bool expanded = false;
public ObservableCollection<FrameworkElement> Children { get; } = new ObservableCollection<FrameworkElement>();
public ObservableCollection<FrameworkElement> Children { get; } = [];
public ExpandableMenuSection()
{
+15
View File
@@ -0,0 +1,15 @@
<UserControl x:Class="Daybreak.Controls.Glyphs.ArrowGlyph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Controls.Glyphs"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Viewbox>
<Grid Width="30" Height="30" Margin="-2, 0, 0 ,0">
<Path Fill="{DynamicResource MahApps.Brushes.ThemeForeground}" VerticalAlignment="Top" HorizontalAlignment="Left"
Data="m18.87,9.41l-5.58,5.59l5.58,5.59a1,1 0 0 1 0,1.41l0,0a1,1 0 0 1 -1.41,0l-6.36,-6.36a0.91,0.91 0 0 1 0,-1.28l6.36,-6.36a1,1 0 0 1 1.41,0l0,0a1,1 0 0 1 0,1.41z"></Path>
</Grid>
</Viewbox>
</UserControl>
@@ -0,0 +1,13 @@
using System.Windows.Controls;
namespace Daybreak.Controls.Glyphs;
/// <summary>
/// Interaction logic for ArrowGlyph.xaml
/// </summary>
public partial class ArrowGlyph : UserControl
{
public ArrowGlyph()
{
this.InitializeComponent();
}
}
@@ -58,7 +58,7 @@ public partial class LivingEntityContextMenu : UserControl
this.PrimaryProfessionVisible = false;
}
await this.guildwarsMemoryReader.EnsureInitialized(context.GuildWarsApplicationLaunchContext!.GuildWarsProcess, CancellationToken.None);
await this.guildwarsMemoryReader.EnsureInitialized(context.GuildWarsApplicationLaunchContext!.ProcessId, CancellationToken.None);
this.EntityName = await this.guildwarsMemoryReader.GetEntityName(context.LivingEntity!, CancellationToken.None).ConfigureAwait(true);
}
@@ -68,8 +68,13 @@
</ContextMenu>
</UserControl.Resources>
<Grid>
<Image x:Name="MapDrawingHost" VerticalAlignment="Top" HorizontalAlignment="Left" Stretch="Fill"/>
<Image x:Name="EntitiesDrawingHost" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
<Grid RenderTransformOrigin="0.5 0.5">
<Grid.RenderTransform>
<RotateTransform x:Name="RotateTransform" Angle="{Binding ElementName=_this, Path=Angle, Mode=OneWay}"/>
</Grid.RenderTransform>
<Image x:Name="MapDrawingHost" VerticalAlignment="Top" HorizontalAlignment="Left" Stretch="Fill" />
<Image x:Name="EntitiesDrawingHost" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</Grid>
<Grid Background="{DynamicResource Daybreak.Brushes.Background}"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
@@ -79,15 +84,5 @@
Clicked="MaximizeButton_Clicked"
ToolTip="Maximize"/>
</Grid>
<WrapPanel Background="{DynamicResource Daybreak.Brushes.Background}"
VerticalAlignment="Top"
HorizontalAlignment="Right" >
<TextBlock Text="{Binding ElementName=_this, Path=TargetEntityId, Mode=OneWay}" Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
FontSize="16" Padding="5" />
<TextBlock Text=" - " Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
FontSize="16" Padding="5" />
<TextBlock Text="{Binding ElementName=_this, Path=TargetEntityModelId, Mode=OneWay}" Foreground="{DynamicResource MahApps.Brushes.ThemeForeground}"
FontSize="16" Padding="5" />
</WrapPanel>
</Grid>
</UserControl>
@@ -24,6 +24,8 @@ using System.Diagnostics.Metrics;
using System.Diagnostics;
using Daybreak.Models.FocusView;
using Daybreak.Models.LaunchConfigurations;
using System.Configuration;
using System.Runtime.CompilerServices;
namespace Daybreak.Controls.Minimap;
@@ -42,7 +44,7 @@ public partial class GuildwarsMinimap : UserControl
private readonly Histogram<double> drawingLatency;
private readonly DispatcherTimer dispatcherTimer = new(DispatcherPriority.Render);
private readonly List<Position> mainPlayerPositionHistory = new();
private readonly List<Position> mainPlayerPositionHistory = [];
private readonly IPathfinder pathfinder;
private readonly IDrawingService drawingService;
private readonly IThemeManager themeManager;
@@ -78,6 +80,10 @@ public partial class GuildwarsMinimap : UserControl
[GenerateDependencyProperty]
private bool controlsVisible;
[GenerateDependencyProperty]
private bool canRotate;
[GenerateDependencyProperty]
private double angle;
[GenerateDependencyProperty]
private int targetEntityId;
[GenerateDependencyProperty]
private int targetEntityModelId;
@@ -187,6 +193,8 @@ public partial class GuildwarsMinimap : UserControl
entity.Health = state?.Health ?? 0;
entity.Energy = state?.Energy ?? 0;
}
this.Angle = this.CanRotate ? (this.GameState.Camera.Yaw - (Math.PI / 2)) * (180 / Math.PI) : 0;
}
private void UpdateGameData()
@@ -357,8 +365,8 @@ public partial class GuildwarsMinimap : UserControl
this.drawingService.DrawEngagementArea(bitmap, this.GameData);
this.drawingService.DrawMainPlayerPositionHistory(bitmap, this.mainPlayerPositionHistory);
this.drawingService.DrawPaths(bitmap, this.pathfindingCache);
this.drawingService.DrawQuestObjectives(bitmap, this.GameData.MainPlayer?.QuestLog ?? new List<QuestMetadata>());
this.drawingService.DrawMapIcons(bitmap, this.GameData.MapIcons ?? new List<MapIcon>());
this.drawingService.DrawQuestObjectives(bitmap, this.GameData.MainPlayer?.QuestLog ?? []);
this.drawingService.DrawMapIcons(bitmap, this.GameData.MapIcons ?? []);
this.drawingService.DrawEntities(bitmap, this.GameData, this.TargetEntityId);
bitmap.Unlock();
this.drawingLatency.Record(sw.ElapsedMilliseconds);
@@ -368,8 +376,10 @@ public partial class GuildwarsMinimap : UserControl
{
var x = (int)((entity.Position!.Value.X - this.originPoint.X) * this.Zoom);
var y = 0 - (int)((entity.Position!.Value.Y - this.originPoint.Y) * this.Zoom);
return Math.Pow(mousePosition.X - x, 2) + Math.Pow(mousePosition.Y - y, 2) < Math.Pow(EntitySize * this.Zoom, 2);
var entityPoint = new Point(x, y);
var centerPoint = new Point(this.ActualWidth / 2, this.ActualHeight / 2);
var finalEntityPoint = RotatePointAroundPivot(entityPoint, centerPoint, this.Angle);
return Math.Pow(mousePosition.X - finalEntityPoint.X, 2) + Math.Pow(mousePosition.Y - finalEntityPoint.Y, 2) < Math.Pow(EntitySize * this.Zoom, 2);
}
private void DragMinimap()
@@ -379,9 +389,14 @@ public partial class GuildwarsMinimap : UserControl
return;
}
var rad = -this.Angle * Math.PI / 180;
var mousePosition = Mouse.GetPosition(this);
var offset = mousePosition - this.initialClickPoint;
var transformedOffset = new Vector((offset.X * Math.Cos(rad)) - (offset.Y * Math.Sin(rad)),
(offset.X * Math.Sin(rad)) + (offset.Y * Math.Cos(rad)));
this.initialClickPoint = mousePosition;
this.offsetRevert = 0;
this.originOffset = mousePosition - this.initialClickPoint;
this.originOffset += transformedOffset;
this.offsetRevertTime = DateTime.Now + this.offsetRevertDelay;
this.UpdateGameData();
}
@@ -518,7 +533,7 @@ public partial class GuildwarsMinimap : UserControl
private void GuildwarsMinimap_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.initialClickPoint = Mouse.GetPosition(this) - this.originOffset;
this.initialClickPoint = Mouse.GetPosition(this);
this.offsetRevert = 0;
this.offsetRevertTime = DateTime.Now + this.offsetRevertDelay;
this.dragging = true;
@@ -629,7 +644,8 @@ public partial class GuildwarsMinimap : UserControl
private void GuildwarsMinimap_MouseMove(object sender, MouseEventArgs e)
{
if (this.GameData.Valid is false ||
if (this.GameData is null ||
this.GameData.Valid is false ||
this.GameData.MainPlayer is null ||
this.GameData.Party is null ||
this.GameData.WorldPlayers is null)
@@ -653,24 +669,24 @@ public partial class GuildwarsMinimap : UserControl
return;
}
if (this.CheckMouseOverEntity(this.GameData.LivingEntities!.OfType<IEntity>()) is not null)
if (this.CheckMouseOverEntity(this.GameData.LivingEntities?.OfType<IEntity>()) is not null)
{
return;
}
if (this.CheckMouseOverEntity(this.GameData.MapIcons!.OfType<IPositionalEntity>()) is not null)
if (this.CheckMouseOverEntity(this.GameData.MapIcons?.OfType<IPositionalEntity>()) is not null)
{
return;
}
if (this.CheckMouseOverEntity(this.GameData.MainPlayer.QuestLog!
if (this.CheckMouseOverEntity(this.GameData.MainPlayer.QuestLog?
.Where(entity => this.drawingService.IsEntityOnScreen(entity.Position, out _, out _))
.OfType<IPositionalEntity>()) is not null)
{
return;
}
if (this.CheckMouseOverEntity(this.GameData.MainPlayer.QuestLog!
if (this.CheckMouseOverEntity(this.GameData.MainPlayer.QuestLog?
.Where(entity => !this.drawingService.IsEntityOnScreen(entity.Position, out _, out _))
.Select(oldQuestMetadata =>
{
@@ -693,7 +709,7 @@ public partial class GuildwarsMinimap : UserControl
{
var delta = e.Delta > 0 ? 0.1 : -0.1;
var previousZoom = this.Zoom;
var newZoom = this.Zoom + this.Zoom * delta;
var newZoom = this.Zoom + (this.Zoom * delta);
this.originOffset *= newZoom / previousZoom;
this.initialClickPoint = new Point(
this.initialClickPoint.X * newZoom / previousZoom,
@@ -784,6 +800,26 @@ public partial class GuildwarsMinimap : UserControl
}
}
private static Point RotatePointAroundPivot(Point point, Point pivot, double angle)
{
// Translate the point to the pivot point
point = new Point(point.X - pivot.X, point.Y - pivot.Y);
// Convert angle to radians for the rotation
double radians = Math.PI / 180 * angle;
// Rotate the point around the pivot
double rotatedX = (point.X * Math.Cos(radians)) - (point.Y * Math.Sin(radians));
double rotatedY = (point.X * Math.Sin(radians)) + (point.Y * Math.Cos(radians));
// Translate the point back
rotatedX += pivot.X;
rotatedY += pivot.Y;
return new Point(rotatedX, rotatedY);
}
private static bool PositionsCollide(Position position1, Position position2)
{
var a = PositionRadius + PositionRadius;
@@ -24,7 +24,7 @@ public partial class NotificationStackpanel : UserControl
private readonly DispatcherTimer dispatcherTimer = new();
private CancellationTokenSource? cancellationToken;
public ObservableCollection<NotificationWrapper> Notifications { get; } = new();
public ObservableCollection<NotificationWrapper> Notifications { get; } = [];
public NotificationStackpanel() :
this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<INotificationProducer>(),
@@ -15,7 +15,7 @@ public partial class EnumOptionTemplate : UserControl
{
private OptionProperty optionProperty = default!;
public ObservableCollection<object> PossibleEnumValues { get; } = new ObservableCollection<object>();
public ObservableCollection<object> PossibleEnumValues { get; } = [];
[GenerateDependencyProperty]
private object value = default!;
@@ -23,7 +23,7 @@ public partial class OptionsSection : UserControl
private readonly IOptionsProvider optionsProvider;
private readonly IViewManager viewManager;
public ObservableCollection<OptionSection> Options { get; } = new ObservableCollection<OptionSection>();
public ObservableCollection<OptionSection> Options { get; } = [];
public OptionsSection(
IOptionsProvider optionsProvider,
+1 -1
View File
@@ -43,7 +43,7 @@ public partial class PlayerContextMenu : UserControl
return;
}
await this.guildwarsMemoryReader.EnsureInitialized(context.GuildWarsApplicationLaunchContext!.GuildWarsProcess, CancellationToken.None);
await this.guildwarsMemoryReader.EnsureInitialized(context.GuildWarsApplicationLaunchContext!.ProcessId, CancellationToken.None);
this.PlayerName = await this.guildwarsMemoryReader.GetEntityName(context.Player!, CancellationToken.None).ConfigureAwait(true);
}
+24 -6
View File
@@ -5,11 +5,19 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Controls"
xmlns:effects="clr-namespace:System.Windows.Media.Extensions.Effects;assembly=WpfExtended"
xmlns:converters="clr-namespace:Daybreak.Converters"
mc:Ignorable="d"
Loaded="UserControl_Loaded"
Unloaded="UserControl_Unloaded"
x:Name="_this"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<converters:DoubleMultiplierConverter x:Key="FallMultiplier1" Multiplier="0.2"/>
<converters:DoubleMultiplierConverter x:Key="FallMultiplier2" Multiplier="0.18"/>
<converters:DoubleMultiplierConverter x:Key="FallMultiplier3" Multiplier="0.15"/>
<converters:DoubleMultiplierConverter x:Key="FallMultiplier4" Multiplier="0.13"/>
<converters:DoubleMultiplierConverter x:Key="FallMultiplier5" Multiplier="0.1"/>
</UserControl.Resources>
<UserControl.Effect>
<BlurEffect
KernelType="Box"
@@ -22,7 +30,7 @@
<DoubleAnimation Storyboard.TargetName="_this"
Storyboard.TargetProperty="Time"
From="0"
To="200"
To="1000"
Duration="0:30:0"
RepeatBehavior="Forever"/>
</Storyboard>
@@ -39,7 +47,9 @@
<ImageBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="{Binding ElementName=_this, Path=FlakeSize1, Mode=OneWay}" ScaleY="{Binding ElementName=_this, Path=FlakeSize1, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform1" X="0" Y="{Binding ElementName=_this, Path=Time, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform1"
X="0"
Y="{Binding ElementName=_this, Path=Time, Mode=OneWay, Converter={StaticResource FallMultiplier1}}" />
</TransformGroup>
</ImageBrush.RelativeTransform>
</ImageBrush>
@@ -54,7 +64,9 @@
<ImageBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="{Binding ElementName=_this, Path=FlakeSize2, Mode=OneWay}" ScaleY="{Binding ElementName=_this, Path=FlakeSize2, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform2" X="0" Y="{Binding ElementName=_this, Path=Time, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform2"
X="0"
Y="{Binding ElementName=_this, Path=Time, Mode=OneWay, Converter={StaticResource FallMultiplier2}}" />
</TransformGroup>
</ImageBrush.RelativeTransform>
</ImageBrush>
@@ -69,7 +81,9 @@
<ImageBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="{Binding ElementName=_this, Path=FlakeSize3, Mode=OneWay}" ScaleY="{Binding ElementName=_this, Path=FlakeSize3, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform3" X="0" Y="{Binding ElementName=_this, Path=Time, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform3"
X="0"
Y="{Binding ElementName=_this, Path=Time, Mode=OneWay, Converter={StaticResource FallMultiplier3}}" />
</TransformGroup>
</ImageBrush.RelativeTransform>
</ImageBrush>
@@ -84,7 +98,9 @@
<ImageBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="{Binding ElementName=_this, Path=FlakeSize4, Mode=OneWay}" ScaleY="{Binding ElementName=_this, Path=FlakeSize4, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform4" X="0" Y="{Binding ElementName=_this, Path=Time, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform4"
X="0"
Y="{Binding ElementName=_this, Path=Time, Mode=OneWay, Converter={StaticResource FallMultiplier4}}" />
</TransformGroup>
</ImageBrush.RelativeTransform>
</ImageBrush>
@@ -99,7 +115,9 @@
<ImageBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="{Binding ElementName=_this, Path=FlakeSize5, Mode=OneWay}" ScaleY="{Binding ElementName=_this, Path=FlakeSize5, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform5" X="0" Y="{Binding ElementName=_this, Path=Time, Mode=OneWay}" />
<TranslateTransform x:Name="SnowfallTransform5"
X="0"
Y="{Binding ElementName=_this, Path=Time, Mode=OneWay, Converter={StaticResource FallMultiplier5}}" />
</TransformGroup>
</ImageBrush.RelativeTransform>
</ImageBrush>
+2 -1
View File
@@ -27,6 +27,7 @@ public partial class SnowfallOverlay : UserControl
private double flakeSize4;
[GenerateDependencyProperty]
private double flakeSize5;
[GenerateDependencyProperty]
private double time;
@@ -111,7 +112,7 @@ public partial class SnowfallOverlay : UserControl
{
var f = Frequencies[i];
var a = Amplitudes[i];
returnValue += a * Math.Sin(f * source * Math.PI * 2);
returnValue += a * Math.Sin(f * source * Math.PI);
}
return returnValue / Divisor;
@@ -23,7 +23,6 @@
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
@@ -31,7 +30,6 @@
</Grid.ColumnDefinitions>
<TextBlock FontSize="16" Text="Username:" Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" Margin="5" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center"></TextBlock>
<TextBlock FontSize="16" Text="Password:" Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" Margin="5" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center"></TextBlock>
<TextBlock FontSize="16" Text="Character name:" Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" Margin="5" Grid.Row="2" HorizontalAlignment="Right" VerticalAlignment="Center"></TextBlock>
<TextBox Text="{Binding ElementName=_this, Path=Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" Background="Transparent"
BorderThickness="1" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1"
FontSize="16" TextChanged="UsernameTextbox_TextChanged" Margin="5"
@@ -40,10 +38,6 @@
BorderThickness="1" HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="1"
FontSize="16" PasswordChanged="Passwordbox_PasswordChanged" Margin="5"
ToolTip="Password" />
<TextBox Text="{Binding ElementName=_this, Path=CharacterName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" Background="Transparent"
BorderThickness="1" HorizontalAlignment="Stretch" Grid.Row="2" Grid.Column="1"
FontSize="16" TextChanged="CharacterNameTextbox_TextChanged" Margin="5"
ToolTip="Character name" />
</Grid>
<buttons:BinButton Grid.Column="2" Height="30" Width="30" Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" VerticalAlignment="Center" Margin="5, 5, 5, 5"
Clicked="BinButton_Clicked"
@@ -21,8 +21,6 @@ public partial class AccountTemplate : UserControl
private string username = string.Empty;
[GenerateDependencyProperty]
private string password = string.Empty;
[GenerateDependencyProperty]
private string characterName = string.Empty;
public AccountTemplate()
{
@@ -36,7 +34,6 @@ public partial class AccountTemplate : UserControl
{
this.PasswordBox.Password = loginCredentials.Password;
this.Username = loginCredentials.Username;
this.CharacterName = loginCredentials.CharacterName;
}
}
@@ -50,11 +47,6 @@ public partial class AccountTemplate : UserControl
this.DataContext.As<LoginCredentials>()!.Username = this.Username;
}
private void CharacterNameTextbox_TextChanged(object sender, EventArgs e)
{
this.DataContext.As<LoginCredentials>()!.CharacterName = this.CharacterName;
}
private void Passwordbox_PasswordChanged(object sender, EventArgs e)
{
this.Password = sender.As<PasswordBox>()?.Password;
@@ -56,11 +56,11 @@ public partial class BuildTemplate : UserControl
private int attributePoints;
[GenerateDependencyProperty]
private List<Skill> availableSkills = new();
private List<Skill> availableSkills = [];
public event EventHandler? BuildChanged;
public ObservableCollection<Profession> PrimaryProfessions { get; } = new();
public ObservableCollection<Profession> SecondaryProfessions { get; } = new();
public ObservableCollection<Profession> PrimaryProfessions { get; } = [];
public ObservableCollection<Profession> SecondaryProfessions { get; } = [];
public BuildTemplate()
: this(Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBuildTemplateManager>(),
@@ -8,6 +8,7 @@
xmlns:configs="clr-namespace:Daybreak.Models.LaunchConfigurations"
xmlns:converters="clr-namespace:Daybreak.Converters"
mc:Ignorable="d"
DataContextChanged="UserControl_DataContextChanged"
Loaded="UserControl_Loaded"
Unloaded="UserControl_Unloaded"
x:Name="_this"
@@ -18,47 +19,56 @@
</UserControl.Resources>
<Grid>
<StackPanel
Visibility="{Binding ElementName=_this, Path=CanShowFocusView, Mode=OneWay, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
Visibility="{Binding ElementName=_this, Path=CanLaunch, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
<WrapPanel VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBlock Text="Launch "
FontSize="22"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
Visibility="{Binding ElementName=_this, Path=GameRunning, Mode=OneWay, Converter={StaticResource InverseBooleanToVisibilityConverter}}"/>
<TextBlock Text="{Binding Credentials.Username}"
<TextBlock Text="{Binding Configuration.Credentials.Username}"
FontSize="22"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"/>
<TextBlock Text=" running"
FontSize="22"
Foreground="{StaticResource MahApps.Brushes.Accent}"
Visibility="{Binding ElementName=_this, Path=GameRunning, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</WrapPanel>
<TextBlock Text="{Binding Credentials.CharacterName}"
FontSize="16"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"/>
<TextBlock Text="{Binding ExecutablePath}"
<TextBlock Text="{Binding Configuration.ExecutablePath}"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
FontSize="12"
TextWrapping="Wrap"/>
TextWrapping="Wrap"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Visibility="{Binding ElementName=_this, Path=CanShowFocusView, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
Visibility="{Binding ElementName=_this, Path=CanAttach, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
<WrapPanel VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBlock Text="Attach "
FontSize="22"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" />
<TextBlock Text="{Binding Credentials.Username}"
<TextBlock Text="{Binding Configuration.Credentials.Username}"
FontSize="22"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"/>
</WrapPanel>
<TextBlock Text="{Binding Credentials.CharacterName}"
FontSize="16"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"/>
<TextBlock Text="{Binding ExecutablePath}"
<TextBlock Text="{Binding Configuration.ExecutablePath}"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
FontSize="12"
TextWrapping="Wrap"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Visibility="{Binding ElementName=_this, Path=CanKill, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
<WrapPanel VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBlock Text="Kill "
FontSize="22"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}" />
<TextBlock Text="{Binding Configuration.Credentials.Username}"
FontSize="22"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"/>
</WrapPanel>
<TextBlock Text="{Binding Configuration.ExecutablePath}"
Foreground="{StaticResource MahApps.Brushes.ThemeForeground}"
FontSize="12"
TextWrapping="Wrap"/>
TextWrapping="Wrap"
HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
</UserControl>
@@ -1,7 +1,12 @@
using Daybreak.Configuration.Options;
using Daybreak.Controls.Buttons;
using Daybreak.Models;
using Daybreak.Models.LaunchConfigurations;
using Daybreak.Services.ApplicationLauncher;
using Daybreak.Services.GWCA;
using Daybreak.Services.LaunchConfigurations;
using Daybreak.Services.Scanner;
using Daybreak.Utils;
using Microsoft.Extensions.DependencyInjection;
using Slim.Attributes;
using System;
@@ -9,6 +14,7 @@ using System.Configuration;
using System.Core.Extensions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Extensions;
@@ -20,12 +26,19 @@ public partial class LaunchButtonTemplate : UserControl
{
private static readonly TimeSpan CheckGameDelay = TimeSpan.FromSeconds(1);
private readonly IGuildwarsMemoryReader guildwarsMemoryReader;
private readonly ILaunchConfigurationService launchConfigurationService;
private readonly IApplicationLauncher applicationLauncher;
private readonly ILiveOptions<FocusViewOptions> liveOptions;
[GenerateDependencyProperty(InitialValue = true)]
private bool canLaunch;
[GenerateDependencyProperty]
private bool canShowFocusView;
private bool canKill;
[GenerateDependencyProperty]
private bool canAttach;
[GenerateDependencyProperty]
private bool gameRunning;
@@ -33,10 +46,12 @@ public partial class LaunchButtonTemplate : UserControl
private CancellationTokenSource? tokenSource;
public LaunchButtonTemplate(
IGuildwarsMemoryReader guildwarsMemoryReader,
ILaunchConfigurationService launchConfigurationService,
IApplicationLauncher applicationLauncher,
ILiveOptions<FocusViewOptions> liveOptions)
{
this.guildwarsMemoryReader = guildwarsMemoryReader.ThrowIfNull();
this.launchConfigurationService = launchConfigurationService.ThrowIfNull();
this.applicationLauncher = applicationLauncher.ThrowIfNull();
this.liveOptions = liveOptions.ThrowIfNull();
@@ -46,47 +61,101 @@ public partial class LaunchButtonTemplate : UserControl
[DoNotInject]
public LaunchButtonTemplate()
:this(
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IGuildwarsMemoryReader>(),
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILaunchConfigurationService>(),
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IApplicationLauncher>(),
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<FocusViewOptions>>())
{
}
private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
this.tokenSource?.Dispose();
this.tokenSource = new CancellationTokenSource();
this.CheckGameState(this.tokenSource.Token);
this.PeriodicallyCheckGameState(this.tokenSource.Token);
}
private void UserControl_Unloaded(object sender, System.Windows.RoutedEventArgs e)
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
{
this.tokenSource?.Dispose();
this.tokenSource = default;
}
private async void CheckGameState(CancellationToken cancellationToken)
private async void UserControl_DataContextChanged(object _, DependencyPropertyChangedEventArgs e)
{
await this.CheckGameState(this.tokenSource?.Token ?? CancellationToken.None);
}
private async void PeriodicallyCheckGameState(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
if (this.DataContext is not LaunchConfigurationWithCredentials config)
// The following if case is needed due to a fault in the ContentPresenter not passing the DataContext to the content it presents
if (this.FindParent<HighlightButton>()?.DataContext is LauncherViewContext parentContext &&
this.DataContext != parentContext)
{
await Task.Delay(CheckGameDelay, cancellationToken);
continue;
}
if (this.applicationLauncher.GetGuildwarsProcess(config) is null)
{
this.GameRunning = false;
}
else
{
this.GameRunning = true;
this.DataContext = parentContext;
}
this.CanShowFocusView = this.liveOptions.Value.Enabled && this.GameRunning;
await this.CheckGameState(cancellationToken);
await Task.Delay(CheckGameDelay, cancellationToken);
}
}
private async Task CheckGameState(CancellationToken cancellationToken)
{
if (this.DataContext is not LauncherViewContext launcherViewContext ||
launcherViewContext.Configuration is null)
{
this.CanLaunch = false;
this.CanAttach = false;
this.CanKill = false;
return;
}
if (this.applicationLauncher.GetGuildwarsProcess(launcherViewContext.Configuration) is not GuildWarsApplicationLaunchContext context)
{
this.GameRunning = false;
this.CanLaunch = true;
this.CanAttach = this.liveOptions.Value.Enabled && this.GameRunning;
this.CanKill = false;
launcherViewContext.CanLaunch = true;
launcherViewContext.CanKill = false;
return;
}
try
{
await this.guildwarsMemoryReader.EnsureInitialized(context.ProcessId, cancellationToken);
}
catch
{
this.GameRunning = false;
this.CanLaunch = false;
this.CanAttach = this.liveOptions.Value.Enabled && this.GameRunning;
this.CanKill = this.CanAttach ? false : true;
launcherViewContext.CanLaunch = false;
launcherViewContext.CanKill = true;
return;
}
var loginInfo = await this.guildwarsMemoryReader.ReadLoginData(cancellationToken);
if (loginInfo?.Email != context.LaunchConfiguration.Credentials?.Username)
{
this.GameRunning = false;
this.CanAttach = this.liveOptions.Value.Enabled && this.GameRunning;
this.CanLaunch = true;
this.CanKill = false;
launcherViewContext.CanLaunch = false;
launcherViewContext.CanKill = false;
return;
}
this.GameRunning = true;
this.CanKill = false;
this.CanLaunch = false;
launcherViewContext.CanLaunch = true;
launcherViewContext.CanKill = false;
this.CanAttach = this.liveOptions.Value.Enabled && this.GameRunning;
}
}
@@ -29,7 +29,7 @@ public partial class QuestLogTemplate : UserControl
public QuestLogTemplate()
{
this.quests = new List<QuestMetadata>();
this.quests = [];
this.InitializeComponent();
}
@@ -49,7 +49,7 @@ public partial class TradeChatTemplate : UserControl
[GenerateDependencyProperty]
private TraderMessage selectedTraderMessage = default!;
public ObservableCollection<TraderMessageViewWrapper> TraderMessages { get; } = new();
public ObservableCollection<TraderMessageViewWrapper> TraderMessages { get; } = [];
public TradeChatTemplate()
: this(Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IWordHighlightingService>())
@@ -0,0 +1,24 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace Daybreak.Converters;
public sealed class DoubleMultiplierConverter : IValueConverter
{
public double Multiplier { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not double d)
{
return value;
}
return d * this.Multiplier;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
@@ -0,0 +1,44 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace Daybreak.Converters;
public sealed class IntToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType == typeof(string) &&
value is int i)
{
return i.ToString();
}
else if(targetType == typeof(int) &&
value is string s)
{
return int.Parse(s);
}
else
{
throw new InvalidOperationException($"Unable to convert from {value.GetType().Name} to {targetType.Name}");
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType == typeof(string) &&
value is int i)
{
return i.ToString();
}
else if (targetType == typeof(int) &&
value is string s)
{
return int.Parse(s);
}
else
{
throw new InvalidOperationException($"Unable to convert from {value.GetType().Name} to {targetType.Name}");
}
}
}
@@ -0,0 +1,36 @@
using Daybreak.Models.Guildwars;
using System;
using System.Globalization;
using System.Windows.Data;
namespace Daybreak.Converters;
public sealed class ItemBaseToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is int i)
{
return ItemBase.Parse(i, modifiers: null);
}
else if(value is ItemBase itemBase)
{
return itemBase.Id;
}
throw new InvalidOperationException($"Unable to convert value of type {value.GetType().Name}");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is int i)
{
return ItemBase.Parse(i, modifiers: null);
}
else if (value is ItemBase itemBase)
{
return itemBase.Id;
}
throw new InvalidOperationException($"Unable to convert value of type {value.GetType().Name}");
}
}
@@ -0,0 +1,36 @@
using Daybreak.Models.Guildwars;
using System;
using System.Globalization;
using System.Windows.Data;
namespace Daybreak.Converters;
public sealed class ItemBaseToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string s)
{
return ItemBase.Parse(s);
}
else if(value is ItemBase itemBase)
{
return itemBase.Name ?? string.Empty;
}
throw new InvalidOperationException($"Unable to convert value of type {value.GetType().Name}");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string s)
{
return ItemBase.Parse(s);
}
else if (value is ItemBase itemBase)
{
return itemBase.Name ?? string.Empty;
}
throw new InvalidOperationException($"Unable to convert value of type {value.GetType().Name}");
}
}
@@ -0,0 +1,78 @@
using Daybreak.Models.Trade;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Reflection.Emit;
namespace Daybreak.Converters;
public sealed class TradeAlertConverter : JsonConverter<ITradeAlert>
{
public override ITradeAlert? ReadJson(JsonReader reader, Type objectType, ITradeAlert? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader).ToObject<dynamic>();
if (jObject is null)
{
throw new InvalidOperationException($"Unable to deserialize {nameof(ITradeAlert)}");
}
if (jObject[nameof(TradeAlert.MessageCheck)] is null)
{
return new QuoteAlert
{
Name = jObject[nameof(QuoteAlert.Name)],
Id = jObject[nameof(QuoteAlert.Id)],
Enabled = jObject[nameof(QuoteAlert.Enabled)],
UpperPriceTarget = jObject[nameof(QuoteAlert.UpperPriceTarget)],
LowerPriceTarget = jObject[nameof(QuoteAlert.LowerPriceTarget)],
UpperPriceTargetEnabled = jObject[nameof(QuoteAlert.UpperPriceTargetEnabled)],
LowerPriceTargetEnabled = jObject[nameof(QuoteAlert.LowerPriceTargetEnabled)],
ItemId = jObject[nameof(QuoteAlert.ItemId)]
};
}
else
{
return new TradeAlert
{
Name = jObject[nameof(TradeAlert.Name)],
Id = jObject[nameof(TradeAlert.Id)],
Enabled = jObject[nameof(TradeAlert.Enabled)],
MessageCheck = jObject[nameof(TradeAlert.MessageCheck)],
MessageRegexCheck = jObject[nameof(TradeAlert.MessageRegexCheck)],
SenderCheck = jObject[nameof(TradeAlert.SenderCheck)],
SenderRegexCheck = jObject[nameof(TradeAlert.SenderRegexCheck)]
};
}
}
public override void WriteJson(JsonWriter writer, ITradeAlert? value, JsonSerializer serializer)
{
if (value is null)
{
serializer.Serialize(writer, null);
return;
}
var jObject = new JObject();
jObject[nameof(ITradeAlert.Name)] = value.Name;
jObject[nameof(ITradeAlert.Enabled)] = value.Enabled;
jObject[nameof(ITradeAlert.Id)] = value.Id;
if (value is TradeAlert tradeAlert)
{
jObject[nameof(TradeAlert.MessageCheck)] = tradeAlert.MessageCheck;
jObject[nameof(TradeAlert.MessageRegexCheck)] = tradeAlert.MessageRegexCheck;
jObject[nameof(TradeAlert.SenderCheck)] = tradeAlert.SenderCheck;
jObject[nameof(TradeAlert.SenderRegexCheck)] = tradeAlert.SenderRegexCheck;
}
else if (value is QuoteAlert quoteAlert)
{
jObject[nameof(QuoteAlert.TraderQuoteType)] = quoteAlert.TraderQuoteType.ToString();
jObject[nameof(QuoteAlert.ItemId)] = quoteAlert.ItemId;
jObject[nameof(QuoteAlert.UpperPriceTarget)] = quoteAlert.UpperPriceTarget;
jObject[nameof(QuoteAlert.UpperPriceTargetEnabled)] = quoteAlert.UpperPriceTargetEnabled;
jObject[nameof(QuoteAlert.LowerPriceTarget)] = quoteAlert.LowerPriceTarget;
jObject[nameof(QuoteAlert.LowerPriceTargetEnabled)] = quoteAlert.LowerPriceTargetEnabled;
}
serializer.Serialize(writer, jObject);
}
}
@@ -0,0 +1,33 @@
using Daybreak.Services.TradeChat.Models;
using System;
using System.Globalization;
using System.Windows.Data;
namespace Daybreak.Converters;
public sealed class TraderQuoteTypeToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(string))
{
throw new InvalidOperationException($"Unable to convert from {nameof(TraderQuoteType)} to {targetType.Name}");
}
return value?.ToString() ?? string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not string s)
{
throw new InvalidOperationException($"Unable to convert to {targetType.Name}");
}
if (!Enum.TryParse<TraderQuoteType>(s, out var enumValue))
{
throw new InvalidOperationException($"Invalid string value provided {s}");
}
return enumValue;
}
}
+16 -14
View File
@@ -3,17 +3,15 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<RootNamespace>Daybreak</RootNamespace>
<!--Unable to migrate to .net 7 due to issues with font families not being found #140-->
<TargetFramework>net6.0-windows</TargetFramework>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<Platforms>AnyCPU;x86;x64</Platforms>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<LangVersion>preview</LangVersion>
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
<Version>0.9.8.140</Version>
<Version>0.9.9.13</Version>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
<UserSecretsId>cfb2a489-db80-448d-a969-80270f314c46</UserSecretsId>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
@@ -68,7 +66,7 @@
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
<None Include="..\build\Daybreak.GWCA\$(Configuration)\Daybreak.GWCA.dll" Link="GWCA\Daybreak.GWCA.dll">
<None Include="..\Daybreak.GWCA\bin\$(Configuration)\Daybreak.GWCA.dll" Link="GWCA\Daybreak.GWCA.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
@@ -89,27 +87,31 @@
<ItemGroup>
<PackageReference Include="AvalonEdit" Version="6.3.0.90" />
<PackageReference Include="DiffPlex" Version="1.7.2" />
<PackageReference Include="DotNetZip" Version="1.16.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.54" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.57" />
<PackageReference Include="ini-parser-netstandard" Version="2.5.2" />
<PackageReference Include="LiteDB" Version="5.0.17" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc1.2" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc2" />
<PackageReference Include="MahApps.Metro" Version="2.4.10" />
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2088.41" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2210.55" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
<PackageReference Include="NAudio" Version="2.2.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Plumsy" Version="1.1.0" />
<PackageReference Include="securifybv.ShellLink" Version="0.1.0" />
<PackageReference Include="SharpNav" Version="0.9.2" />
<PackageReference Include="Slim" Version="1.9.2" />
<PackageReference Include="Svg" Version="3.4.5" />
<PackageReference Include="Svg" Version="3.4.6" />
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
<PackageReference Include="System.Reflection.Metadata" Version="7.0.2" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Reflection.Metadata" Version="8.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageReference Include="SystemExtensions.NetCore" Version="1.0.1" />
<PackageReference Include="SystemExtensions.NetStandard" Version="1.6.2" />
<PackageReference Include="SystemExtensions.NetStandard.DependencyInjection" Version="1.3.1" />
+11 -8
View File
@@ -1,33 +1,32 @@
using Daybreak.Configuration;
using Daybreak.Models.Progress;
using Daybreak.Services.Browser;
using Daybreak.Services.Drawing;
using Daybreak.Services.ExceptionHandling;
using Daybreak.Services.GWCA;
using Daybreak.Services.Injection;
using Daybreak.Services.Mods;
using Daybreak.Services.Navigation;
using Daybreak.Services.Notifications;
using Daybreak.Services.Options;
using Daybreak.Services.Plugins;
using Daybreak.Services.ReShade;
using Daybreak.Services.Screens;
using Daybreak.Services.Startup;
using Daybreak.Services.Themes;
using Daybreak.Services.UMod.Utilities;
using Daybreak.Services.Updater.PostUpdate;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Slim;
using Slim.Integration.ServiceCollection;
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Extensions;
using System.Windows.Media;
//The following lines are needed to expose internal objects to the test project
[assembly: InternalsVisibleTo("Daybreak.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
namespace Daybreak.Launch;
public sealed class Launcher : ExtendedApplication<MainWindow>
@@ -97,6 +96,7 @@ public sealed class Launcher : ExtendedApplication<MainWindow>
var drawingModuleProducer = this.ServiceProvider.GetRequiredService<IDrawingModuleProducer>();
var notificationHandlerProducer = this.ServiceProvider.GetRequiredService<INotificationHandlerProducer>();
var modsManager = this.ServiceProvider.GetRequiredService<IModsManager>();
var browserExtensionsProducer = this.ServiceProvider.GetRequiredService<IBrowserExtensionsProducer>();
startupStatus.CurrentStep = StartupStatus.Custom("Loading views");
this.projectConfiguration.RegisterViews(viewProducer);
@@ -110,6 +110,8 @@ public sealed class Launcher : ExtendedApplication<MainWindow>
this.projectConfiguration.RegisterNotificationHandlers(notificationHandlerProducer);
startupStatus.CurrentStep = StartupStatus.Custom("Loading mods");
this.projectConfiguration.RegisterMods(modsManager);
startupStatus.CurrentStep = StartupStatus.Custom("Loading browser extensions");
this.projectConfiguration.RegisterBrowserExtensions(browserExtensionsProducer);
this.logger = this.ServiceProvider.GetRequiredService<ILogger<Launcher>>();
this.exceptionHandler = this.ServiceProvider.GetRequiredService<IExceptionHandler>();
@@ -125,7 +127,8 @@ public sealed class Launcher : ExtendedApplication<MainWindow>
startupActionProducer,
drawingModuleProducer,
notificationHandlerProducer,
modsManager);
modsManager,
browserExtensionsProducer);
}
catch(Exception e)
{
+34 -15
View File
@@ -22,7 +22,7 @@
d:DesignHeight="450" d:DesignWidth="800">
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<BooleanToVisibilityConverter x:Key="BaseBooleanToVisibilityConverter" />
<converters:BooleanToEffectConverter x:Key="BooleanToEffectConverter" />
<effects:Kuwahara x:Key="PaintifyEffect" TexelWidth="200" TexelHeight="50" />
<BlurEffect x:Key="BlurEffect" Radius="3" RenderingBias="Performance" KernelType="Box" />
@@ -79,18 +79,18 @@
</Border>
</Border>
<controls:SnowfallOverlay
Visibility="{Binding ElementName=_this, Path=WintersdayMode, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
Visibility="{Binding ElementName=_this, Path=WintersdayMode, Mode=OneWay, Converter={StaticResource BaseBooleanToVisibilityConverter}}"
Opacity="0.4"
BaseWind1="0.00247"
BaseWind2="0.000427"
BaseWind3="0.000443"
BaseWind4="0.000405"
BaseWind5="0.000362"
WindStrength1="0.06"
WindStrength2="0.01"
WindStrength3="0.0096"
WindStrength4="0.0098"
WindStrength5="0.009"
BaseWind1="0.0247"
BaseWind2="0.00427"
BaseWind3="0.00443"
BaseWind4="0.00405"
BaseWind5="0.00362"
WindStrength1="0.006"
WindStrength2="0.001"
WindStrength3="0.00096"
WindStrength4="0.00098"
WindStrength5="0.0009"
FlakeSize1="14"
FlakeSize2="6"
FlakeSize3="4.6"
@@ -102,7 +102,7 @@
<Rectangle Fill="Transparent"
MouseDown="Window_MouseLeftButtonDown"
Grid.RowSpan="2"
Grid.ColumnSpan="2"></Rectangle>
Grid.ColumnSpan="2" />
<buttons:MenuButton Grid.Row="1"
Grid.Column="1"
Background="Transparent"
@@ -129,11 +129,11 @@
ToolTip="Version Management"/>
<buttons:MenuButton Grid.Row="1" Background="Transparent" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Opacity="0.6" Title=" - " FontSize="10" BorderBrush="Transparent" BorderThickness="0"
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BaseBooleanToVisibilityConverter}}"
ToolTip="Running with Administrator Rights"/>
<buttons:MenuButton Grid.Row="1" Background="Transparent" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Opacity="0.6" Title="[Admin]" FontSize="10" BorderBrush="Transparent" BorderThickness="0"
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BaseBooleanToVisibilityConverter}}"
Clicked="AdminText_Clicked"
ToolTip="Running with Administrator Rights"/>
</WrapPanel>
@@ -174,6 +174,25 @@
Visibility="{Binding ElementName=_this, Path=IsShowingDropdown, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
Click="SettingsButton_Clicked"
ToolTip="Close Settings"/>
<buttons:HighlightButton Height="30"
Width="47"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Grid.Column="1"
Margin="0, 0, 140, 0"
Cursor="Arrow"
Opacity="0.8"
HighlightColor="White"
ToolTip="Synchronize Settings"
Clicked="SynchronizeButton_Click">
<buttons:HighlightButton.ButtonContent>
<Grid Height="30"
Width="30">
<glyphs:DownloadGlyph Height="20"
Width="20" />
</Grid>
</buttons:HighlightButton.ButtonContent>
</buttons:HighlightButton>
<notifications:NotificationStackpanel
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
+69 -48
View File
@@ -8,12 +8,15 @@ using Daybreak.Services.Screenshots;
using Daybreak.Services.Updater;
using Daybreak.Views;
using MahApps.Metro.Controls;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Configuration;
using System.Core.Extensions;
using System.Diagnostics;
using System.Extensions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Extensions;
@@ -31,6 +34,7 @@ namespace Daybreak.Launch;
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Used by source generators")]
public partial class MainWindow : MetroWindow
{
private readonly IOptionsSynchronizationService optionsSynchronizationService;
private readonly ISplashScreenService splashScreenService;
private readonly IMenuServiceInitializer menuServiceInitializer;
private readonly IViewManager viewManager;
@@ -55,10 +59,13 @@ public partial class MainWindow : MetroWindow
private bool blurBackground;
[GenerateDependencyProperty]
private bool wintersdayMode;
[GenerateDependencyProperty]
private bool settingsSynchronized;
public event EventHandler<MainWindow>? WindowParametersChanged;
public MainWindow(
IOptionsSynchronizationService optionsSynchronizationService,
ISplashScreenService splashScreenService,
IMenuServiceInitializer menuServiceInitializer,
IViewManager viewManager,
@@ -69,6 +76,7 @@ public partial class MainWindow : MetroWindow
ILiveOptions<LauncherOptions> launcherOptions,
ILiveOptions<ThemeOptions> themeOptions)
{
this.optionsSynchronizationService = optionsSynchronizationService.ThrowIfNull();
this.splashScreenService = splashScreenService.ThrowIfNull();
this.menuServiceInitializer = menuServiceInitializer.ThrowIfNull();
this.viewManager = viewManager.ThrowIfNull();
@@ -83,7 +91,6 @@ public partial class MainWindow : MetroWindow
this.IsRunningAsAdmin = this.privilegeManager.AdminPrivileges;
this.ThemeOptionsChanged();
this.SetupMenuService();
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
@@ -105,9 +112,14 @@ public partial class MainWindow : MetroWindow
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.splashScreenService.HideSplashScreen();
this.SetupImageCycle();
this.viewManager.ShowView<LauncherView>();
this.splashScreenService.HideSplashScreen();
}
private void SynchronizeButton_Click(object sender, EventArgs e)
{
this.viewManager.ShowView<SettingsSynchronizationView>();
}
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
@@ -130,7 +142,7 @@ public partial class MainWindow : MetroWindow
private void SetupImageCycle()
{
TaskExtensions.RunPeriodicAsync(() => this.Dispatcher.Invoke(() => this.UpdateRandomImage()), TimeSpan.Zero, TimeSpan.FromSeconds(15), this.cancellationToken.Token);
System.Extensions.TaskExtensions.RunPeriodicAsync(() => this.Dispatcher.Invoke(() => this.UpdateRandomImage()), TimeSpan.Zero, TimeSpan.FromSeconds(15), this.cancellationToken.Token);
}
private async void UpdateRandomImage()
@@ -153,69 +165,78 @@ public partial class MainWindow : MetroWindow
private void OpenDropdownMenu()
{
if (this.IsShowingDropdown)
this.Dispatcher.Invoke(() =>
{
return;
}
if (this.IsShowingDropdown)
{
return;
}
this.ToggleDropdownMenu();
this.ToggleDropdownMenu();
});
}
private void CloseDropdownMenu()
{
if (!this.IsShowingDropdown)
this.Dispatcher.Invoke(() =>
{
return;
}
if (!this.IsShowingDropdown)
{
return;
}
this.ToggleDropdownMenu();
this.ToggleDropdownMenu();
});
}
private void ToggleDropdownMenu()
{
var button = this.IsShowingDropdown ?
this.Dispatcher.Invoke(() =>
{
var button = this.IsShowingDropdown ?
this.ClosingSettingsButton :
this.OpeningSettingsButton;
button.IsEnabled = false;
var widthAnimation = new DoubleAnimation
{
From = this.IsShowingDropdown ?
this.MenuContainer.ActualWidth :
0,
To = this.IsShowingDropdown ?
0 :
300,
Duration = new Duration(TimeSpan.FromMilliseconds(200)),
DecelerationRatio = 0.7
};
button.IsEnabled = false;
var widthAnimation = new DoubleAnimation
{
From = this.IsShowingDropdown ?
this.MenuContainer.ActualWidth :
0,
To = this.IsShowingDropdown ?
0 :
300,
Duration = new Duration(TimeSpan.FromMilliseconds(200)),
DecelerationRatio = 0.7
};
var opacityAnimation = new DoubleAnimation
{
From = this.IsShowingDropdown ?
this.MenuContainer.Opacity :
0,
To = this.IsShowingDropdown ?
0 :
1,
Duration = new Duration(TimeSpan.FromMilliseconds(100)),
DecelerationRatio = 0.7
};
var opacityAnimation = new DoubleAnimation
{
From = this.IsShowingDropdown ?
this.MenuContainer.Opacity :
0,
To = this.IsShowingDropdown ?
0 :
1,
Duration = new Duration(TimeSpan.FromMilliseconds(100)),
DecelerationRatio = 0.7
};
var storyBoard = new Storyboard();
storyBoard.Children.Add(widthAnimation);
Storyboard.SetTarget(widthAnimation, this.MenuContainer);
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(Grid.WidthProperty));
storyBoard.Children.Add(opacityAnimation);
Storyboard.SetTarget(opacityAnimation, this.MenuContainer);
Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(Grid.OpacityProperty));
var storyBoard = new Storyboard();
storyBoard.Children.Add(widthAnimation);
Storyboard.SetTarget(widthAnimation, this.MenuContainer);
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(Grid.WidthProperty));
storyBoard.Children.Add(opacityAnimation);
Storyboard.SetTarget(opacityAnimation, this.MenuContainer);
Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(Grid.OpacityProperty));
storyBoard.Completed += (_, _) =>
{
button.IsEnabled = true;
this.IsShowingDropdown = !this.IsShowingDropdown;
};
storyBoard.Completed += (_, _) =>
{
button.IsEnabled = true;
this.IsShowingDropdown = !this.IsShowingDropdown;
};
storyBoard.Begin();
storyBoard.Begin();
});
}
private void CreditTextBox_MouseLeftButtonDown(object sender, EventArgs e)
@@ -0,0 +1,9 @@
using System.Diagnostics;
namespace Daybreak.Models;
public readonly struct ApplicationLauncherContext
{
public string ExecutablePath { get; init; }
public Process Process { get; init; }
public uint ProcessId { get; init; }
}
@@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Daybreak.Models.Browser;
public sealed class BrowserHistory
{
public List<string> History { get; set; } = [];
public int CurrentPosition { get; set; } = -1;
}
+3 -1
View File
@@ -9,7 +9,9 @@ public class BrowserPayload
public enum PayloadKeys
{
None,
ContextMenu
ContextMenu,
XButton1Pressed,
XButton2Pressed
}
[JsonProperty(nameof(Key))]
+3 -3
View File
@@ -24,8 +24,8 @@ public static class ColorPalette
public readonly static Color BlueGrey = Color.FromArgb(255, 96, 125, 139);
public readonly static Color Grey = Color.FromArgb(255, 158, 158, 158);
public readonly static List<Color> Colors = new()
{
public readonly static List<Color> Colors =
[
Pink,
Amber,
Purple,
@@ -45,5 +45,5 @@ public static class ColorPalette
Gold,
BlueGrey,
Grey
};
];
}
+3 -1
View File
@@ -3,9 +3,11 @@
public readonly struct ConnectionContext
{
public readonly int Port;
public readonly uint ProcessId;
public ConnectionContext(int port)
public ConnectionContext(int port, uint processId)
{
this.Port = port;
this.ProcessId = processId;
}
}
+2 -2
View File
@@ -8,7 +8,7 @@ public sealed class Build
public BuildMetadata? BuildMetadata { get; set; }
public Profession Primary { get; set; } = Profession.None;
public Profession Secondary { get; set; } = Profession.None;
public List<AttributeEntry> Attributes { get; set; } = new();
public List<Skill> Skills { get; set; } = new() { Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill };
public List<AttributeEntry> Attributes { get; set; } = [];
public List<Skill> Skills { get; set; } = [Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill, Skill.NoSkill];
public string? SourceUrl { get; set; }
}
+3 -3
View File
@@ -16,7 +16,7 @@ public sealed class BuildMetadata
public int SkillsLength { get; set; }
public bool TailPresent { get; set; }
public bool NewTemplate { get; set; }
public List<int> SkillIds { get; set; } = new();
public List<int> AttributesIds { get; set; } = new();
public List<int> AttributePoints { get; set; } = new();
public List<int> SkillIds { get; set; } = [];
public List<int> AttributesIds { get; set; } = [];
public List<int> AttributePoints { get; set; } = [];
}
+7
View File
@@ -0,0 +1,7 @@
namespace Daybreak.Models.Guildwars;
public sealed class Camera
{
public float Yaw { get; set; }
public float Pitch { get; set; }
}
+1
View File
@@ -3,5 +3,6 @@
namespace Daybreak.Models.Guildwars;
public sealed class GameState
{
public Camera Camera { get; init; }
public List<EntityGameState>? States { get; init; }
}
+3 -3
View File
@@ -21,8 +21,8 @@ public sealed class GuildwarsIcon : IWikiEntity
public static readonly GuildwarsIcon DungeonBoss = new() { Id = 302779, Name = "Dungeon Boss" };
public static readonly GuildwarsIcon DungeonKey = new() { Id = 302777, Name = "Dungeon Key" };
public static readonly List<GuildwarsIcon> Icons = new()
{
public static readonly List<GuildwarsIcon> Icons =
[
ResurrectionShrine,
Collector,
AreaMap,
@@ -34,7 +34,7 @@ public sealed class GuildwarsIcon : IWikiEntity
DungeonKey,
Flag,
Person
};
];
public static bool TryParse(int id, out GuildwarsIcon icon)
{

Some files were not shown because too many files have changed in this diff Show More