mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-20 07:15:16 +00:00
Compare commits
245
Commits
v0.9.8.127
...
v0.9.9.65
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0799dd100 | ||
|
|
24f4607899 | ||
|
|
7aee0dfc16 | ||
|
|
5fcb2314bc | ||
|
|
f218b89f6c | ||
|
|
cc607b37c9 | ||
|
|
f80ea8cf0c | ||
|
|
39f6707d23 | ||
|
|
eb11029ece | ||
|
|
4583b5b2d3 | ||
|
|
8c01377667 | ||
|
|
9a130d71dd | ||
|
|
018ed6c5b5 | ||
|
|
cb48248c82 | ||
|
|
e1284375e2 | ||
|
|
d38d620a84 | ||
|
|
ce810dafab | ||
|
|
aabc98e4fc | ||
|
|
7eb0b7cc4f | ||
|
|
f1eb829ac4 | ||
|
|
4b03a5a16f | ||
|
|
71c90100be | ||
|
|
ee512d130d | ||
|
|
03d0759e57 | ||
|
|
0db7628d66 | ||
|
|
d1d1ba6c08 | ||
|
|
d16a88a9bc | ||
|
|
a9d93f4162 | ||
|
|
632b5a55ac | ||
|
|
6424505631 | ||
|
|
dfc1d3ba0a | ||
|
|
5bee88016d | ||
|
|
5a37250680 | ||
|
|
1c4ccb9fa3 | ||
|
|
8403dadca7 | ||
|
|
4ac4cb0886 | ||
|
|
74f13d2447 | ||
|
|
bf53793729 | ||
|
|
e69dbf6791 | ||
|
|
a0eafa8a13 | ||
|
|
b0a236beb4 | ||
|
|
c10b81f3a1 | ||
|
|
6cd51d6584 | ||
|
|
a283117cc8 | ||
|
|
329e64232c | ||
|
|
feb3c9042e | ||
|
|
71f15f56a4 | ||
|
|
d37951b832 | ||
|
|
908a149df4 | ||
|
|
38cf140dfa | ||
|
|
d13e1a2d08 | ||
|
|
a0c7842b84 | ||
|
|
de13b68633 | ||
|
|
f289602068 | ||
|
|
15f4ee8979 | ||
|
|
d826dea457 | ||
|
|
b89a6666a3 | ||
|
|
1dc69fd0c2 | ||
|
|
5005b07f09 | ||
|
|
0b692165e0 | ||
|
|
ffee0fdf4c | ||
|
|
72b4cd5470 | ||
|
|
dc9be53ace | ||
|
|
3a8a6b0f7f | ||
|
|
7cdd0534f6 | ||
|
|
4b14ab9312 | ||
|
|
57e1ddb8da | ||
|
|
c7609c0f7e | ||
|
|
1eca8021d2 | ||
|
|
0077f35c4d | ||
|
|
28b0a0a138 | ||
|
|
cc7ce92013 | ||
|
|
5bd02e56ee | ||
|
|
8c7cd0a562 | ||
|
|
3ab3f72366 | ||
|
|
733883a6c2 | ||
|
|
d1ed8aeaf6 | ||
|
|
66ad44b8ce | ||
|
|
18e51ae408 | ||
|
|
06940dbf38 | ||
|
|
875b29f8ba | ||
|
|
a953c3a0d3 | ||
|
|
ce198fcfc9 | ||
|
|
3d84648af2 | ||
|
|
38bb43bba3 | ||
|
|
cc00709016 | ||
|
|
ee02b3b49a | ||
|
|
d1d6b7d757 | ||
|
|
4e1c0c4f50 | ||
|
|
2a7e2c90fc | ||
|
|
0dc957a99d | ||
|
|
f3f0aeb97e | ||
|
|
d6dbe6f2cd | ||
|
|
79da1801bc | ||
|
|
2b692b2d88 | ||
|
|
a7a98f7288 | ||
|
|
5d27d9c380 | ||
|
|
fb4185b541 | ||
|
|
d2d6e87e12 | ||
|
|
354cdda109 | ||
|
|
83429e264a | ||
|
|
ffdf374cdd | ||
|
|
aed34608ee | ||
|
|
18981e131d | ||
|
|
fe0a77d89d | ||
|
|
dbfd555f0d | ||
|
|
85d4ac3a29 | ||
|
|
dcb983d3de | ||
|
|
ba1e4348ad | ||
|
|
04bc7cffc6 | ||
|
|
01b74a936b | ||
|
|
654b6bc10f | ||
|
|
c9e6b9f626 | ||
|
|
554f1aea9b | ||
|
|
6fb817855c | ||
|
|
b3f5fadfe3 | ||
|
|
9275b7a7f8 | ||
|
|
2d06ff85b8 | ||
|
|
07d06313d9 | ||
|
|
546409130c | ||
|
|
82436872f8 | ||
|
|
ad6f76af0c | ||
|
|
8f0ad91a22 | ||
|
|
6a70c5b7cc | ||
|
|
5f5d67fdf2 | ||
|
|
150b41647a | ||
|
|
66e52e7324 | ||
|
|
23328240a9 | ||
|
|
3f06e9486d | ||
|
|
52a8e912e9 | ||
|
|
641aa8250e | ||
|
|
faa47f32c7 | ||
|
|
e3dac780df | ||
|
|
dfc0f12150 | ||
|
|
638fb38fa0 | ||
|
|
4d6a06ccdf | ||
|
|
3228604876 | ||
|
|
44879924d6 | ||
|
|
6b7478f6ae | ||
|
|
f54d95c1e7 | ||
|
|
5315a45a98 | ||
|
|
8575d970a3 | ||
|
|
5c611eca4f | ||
|
|
71aa37b965 | ||
|
|
0f1b1cc83d | ||
|
|
198c1e6eb3 | ||
|
|
e7c9111a1f | ||
|
|
1191e996db | ||
|
|
19de3c99f9 | ||
|
|
d857b6dc26 | ||
|
|
68b5b79035 | ||
|
|
318032d998 | ||
|
|
483860532f | ||
|
|
694dbe82a9 | ||
|
|
a936f24e32 | ||
|
|
a2ec87ced2 | ||
|
|
48955a7dd7 | ||
|
|
9d7c6c29b0 | ||
|
|
902d210dfd | ||
|
|
57867851a9 | ||
|
|
ca82cc92bf | ||
|
|
569ce1e656 | ||
|
|
a96c6c3f66 | ||
|
|
28c3b2f8c1 | ||
|
|
deeccd81b4 | ||
|
|
6a27245ae8 | ||
|
|
6f4063abb7 | ||
|
|
f307bcd665 | ||
|
|
02ca41ba6d | ||
|
|
a0ebc87b7c | ||
|
|
d21c55deb0 | ||
|
|
50a8131ec2 | ||
|
|
e70cfa3d99 | ||
|
|
4c0c45f1c7 | ||
|
|
a9e819a83a | ||
|
|
65830f9125 | ||
|
|
3d9106addf | ||
|
|
2863032d9a | ||
|
|
aada189b1b | ||
|
|
22ea4de66e | ||
|
|
9859617a74 | ||
|
|
0629c1929d | ||
|
|
6ec45396c3 | ||
|
|
b76a9b80fb | ||
|
|
f4bc58bbf7 | ||
|
|
09fdbb6f95 | ||
|
|
8ee7ed23e4 | ||
|
|
8d8a78cf88 | ||
|
|
f0652231cb | ||
|
|
d9aa760256 | ||
|
|
a65f375255 | ||
|
|
3ee58e2711 | ||
|
|
9b3b083aec | ||
|
|
ecb9b8f172 | ||
|
|
5765c27240 | ||
|
|
c53456112a | ||
|
|
ccea21886e | ||
|
|
37be8de5ac | ||
|
|
107e43a15f | ||
|
|
17b3ed34db | ||
|
|
cce9cd34af | ||
|
|
6a80f8ee5d | ||
|
|
edb7f0d0bd | ||
|
|
8e69375338 | ||
|
|
d24ae98fb0 | ||
|
|
111b3ea632 | ||
|
|
cc1e759972 | ||
|
|
ad0527ed73 | ||
|
|
8ffbb918ea | ||
|
|
c27a0dba65 | ||
|
|
ad8305c66d | ||
|
|
29fe12f094 | ||
|
|
9dbe4c5eaf | ||
|
|
1e9aca3807 | ||
|
|
895da23f7d | ||
|
|
f788a10879 | ||
|
|
9fe4be0467 | ||
|
|
b1a7d3a111 | ||
|
|
8b9fdaaa30 | ||
|
|
60d5947535 | ||
|
|
0ba0e64a2a | ||
|
|
e1dfd1f0d0 | ||
|
|
cd2a529381 | ||
|
|
6ba8dcac49 | ||
|
|
f2e76b5459 | ||
|
|
cfbf6ed021 | ||
|
|
a372eb5125 | ||
|
|
76b89ca0e8 | ||
|
|
2c1721d52c | ||
|
|
324a77a625 | ||
|
|
88e59b8ec9 | ||
|
|
df71a17d9f | ||
|
|
8451f53e19 | ||
|
|
e795af5c11 | ||
|
|
efa3c5175c | ||
|
|
32efe42a61 | ||
|
|
97d2d09cdc | ||
|
|
ed90d567a4 | ||
|
|
51d6fb0f42 | ||
|
|
c10525708c | ||
|
|
0a69d795aa | ||
|
|
3b1d6831a5 | ||
|
|
b4c1dbcddb | ||
|
|
db5d62d7c0 | ||
|
|
ed5ccf38c6 |
+66
-15
@@ -46,23 +46,18 @@ jobs:
|
||||
run: |
|
||||
$changeLog = git log --no-merges --pretty="%h - %s (%an)<br />" ${{ env.LatestReleaseTag }}..HEAD
|
||||
echo "::set-env name=Changelog::$changeLog"
|
||||
mkdir Publish
|
||||
echo $changeLog > .\Publish\changelog.txt
|
||||
env:
|
||||
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: '9.x'
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.3.1
|
||||
|
||||
- name: Fetch submodules
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Build CMake Files
|
||||
run: cmake -S . -B build -A Win32
|
||||
uses: microsoft/setup-msbuild@v2.0.0
|
||||
|
||||
- name: Setup project secrets
|
||||
run: |
|
||||
@@ -83,7 +78,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 }}
|
||||
|
||||
@@ -92,22 +87,78 @@ jobs:
|
||||
env:
|
||||
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=false --self-contained true -o .\Publish
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
- name: Pack publish files
|
||||
run: |
|
||||
Write-Host $env
|
||||
.\Scripts\BuildRelease.ps1 -version $env:Version
|
||||
shell: pwsh
|
||||
|
||||
- name: Publish release
|
||||
uses: Xotl/cool-github-releases@v1.1.8
|
||||
- name: Submit virustotal scan
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd Publish
|
||||
$apiKey = "${{ secrets.VIRUSTOTAL_APIKEY }}"
|
||||
$archiveName = "daybreakv${{ env.Version }}.zip"
|
||||
$uploadUrlResponse = curl https://www.virustotal.com/api/v3/files/upload_url -H x-apikey:"$apiKey"
|
||||
$uploadUrlResponse
|
||||
$uploadUrlJson = $uploadUrlResponse | ConvertFrom-Json
|
||||
$uploadUrl = $uploadUrlJson.data
|
||||
$uploadResponse = curl --request POST --header x-apikey:"$apiKey" --header 'content-type: multipart/form-data' --form file="@$archiveName" --url $uploadUrl
|
||||
$uploadResponse
|
||||
$uploadResponseJson = $uploadResponse | ConvertFrom-Json
|
||||
$resultsUrl = "https://www.virustotal.com/api/v3/analyses/$($uploadResponseJson.data.id)"
|
||||
$resultsUrl
|
||||
# Poll the results until the status is "completed"
|
||||
$status = ""
|
||||
while ($status -ne "completed") {
|
||||
Start-Sleep -Seconds 10 # Wait for 10 seconds between checks
|
||||
$results = curl --header x-apikey:"$apiKey" --url $resultsUrl
|
||||
$results
|
||||
$resultsJson = $results | ConvertFrom-Json
|
||||
$status = $resultsJson.data.attributes.status
|
||||
Write-Host "Current status: $status"
|
||||
}
|
||||
|
||||
$resultsJson.data.attributes.results | ConvertTo-Json | Out-File -FilePath "VirusTotal.Results.json" -Encoding UTF8
|
||||
$resultsJson.data.attributes.stats | ConvertTo-Json | Out-File -FilePath "VirusTotal.Stats.json" -Encoding UTF8
|
||||
$stats = $resultsJson.data.attributes.stats
|
||||
echo "::set-env name=VirusTotalStats::$stats"
|
||||
|
||||
- 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.10
|
||||
with:
|
||||
mode: update
|
||||
tag_name: v${{ env.Version }}
|
||||
release_name: Daybreak v${{ env.Version }}
|
||||
assets: .\Publish\daybreakv${{ env.Version }}.zip
|
||||
assets: .\Publish\daybreakv${{ env.Version }}.zip;.\Publish\VirusTotal.Results.json;.\Publish\VirusTotal.Stats.json
|
||||
github_token: ${{ env.GITHUB_TOKEN }}
|
||||
replace_assets: true
|
||||
body_mrkdwn: ${{ env.Changelog }}
|
||||
body_mrkdwn: |
|
||||
${{ env.Changelog }}
|
||||
|
||||
** VirustTotal Stats: **
|
||||
```
|
||||
${{ env.VirusTotalStats }}
|
||||
```
|
||||
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 }}
|
||||
|
||||
@@ -36,22 +36,15 @@ 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: '9.x'
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.3.1
|
||||
|
||||
- name: Fetch submodules
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Build CMake Files
|
||||
run: cmake -S . -B build -A Win32
|
||||
uses: microsoft/setup-msbuild@v2.0.0
|
||||
|
||||
- name: Execute Unit Tests
|
||||
run: dotnet test $env:Test_Project_Path --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
run: dotnet test $env:Test_Project_Path --property:SolutionDir=$env:GITHUB_WORKSPACE -p:ParallelizeTestCollections=false
|
||||
|
||||
- name: Restore the Wpf application to populate the obj folder
|
||||
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
|
||||
@@ -49,13 +49,9 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch submodules
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
|
||||
# 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 +66,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: '9.x'
|
||||
|
||||
#- name: Autobuild
|
||||
# uses: github/codeql-action/autobuild@v2
|
||||
@@ -91,4 +87,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
|
||||
|
||||
@@ -28,18 +28,16 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '9.x'
|
||||
|
||||
- name: Get Latest Tag
|
||||
id: getLatestTag
|
||||
uses: WyriHaximus/github-action-get-previous-tag@v1
|
||||
|
||||
- name: Fetch submodules
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Build CMake Files
|
||||
run: cmake -S . -B build -A Win32
|
||||
|
||||
- name: Build Daybreak project
|
||||
run: dotnet build Daybreak -c $env:Configuration --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
|
||||
|
||||
+3
-1
@@ -362,4 +362,6 @@ MigrationBackup/
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
FodyWeavers.xsd
|
||||
|
||||
.idea
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[submodule "GWCA"]
|
||||
path = GWCA
|
||||
url = https://github.com/GregLando113/GWCA
|
||||
@@ -1,16 +0,0 @@
|
||||
# CMakeList.txt : Top-level CMake project file, do global configuration
|
||||
# and include sub-projects here.
|
||||
#
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
# Enable Hot Reload for MSVC compilers if supported.
|
||||
if (POLICY CMP0141)
|
||||
cmake_policy(SET CMP0141 NEW)
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
|
||||
endif()
|
||||
|
||||
project ("Daybreak")
|
||||
|
||||
# Include sub-projects.
|
||||
add_subdirectory ("Daybreak.GWCA")
|
||||
add_subdirectory ("GWCA")
|
||||
@@ -1,61 +0,0 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "windows-base",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"installDir": "${sourceDir}/install/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "cl.exe",
|
||||
"CMAKE_CXX_COMPILER": "cl.exe"
|
||||
},
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-debug",
|
||||
"displayName": "x64 Debug",
|
||||
"inherits": "windows-base",
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-release",
|
||||
"displayName": "x64 Release",
|
||||
"inherits": "x64-debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x86-debug",
|
||||
"displayName": "x86 Debug",
|
||||
"inherits": "windows-base",
|
||||
"architecture": {
|
||||
"value": "x86",
|
||||
"strategy": "external"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x86-release",
|
||||
"displayName": "x86 Release",
|
||||
"inherits": "x86-debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<RootNamespace>Daybreak._7ZipExtractor</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpCompress" Version="0.39.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Extractor is in a different executable because of memory limitations. Daybreak needs to be compiled for x86 and as such has a memory limit of 2GB.
|
||||
* 7Zip algorithm may require more than 2GB memory to unpack large zip files.
|
||||
* As such, Daybreak.7ZipExtractor is x64.
|
||||
*/
|
||||
using SharpCompress.Archives;
|
||||
|
||||
if (args.Length != 2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var archivePath = args[0];
|
||||
var destinationDirectory = args[1];
|
||||
|
||||
using var fileStream = new FileStream(archivePath, FileMode.Open);
|
||||
using var archive = ArchiveFactory.Open(fileStream);
|
||||
var progress = 0d;
|
||||
var count = archive.Entries.Count();
|
||||
var reader = archive.ExtractAllEntries();
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
var entry = reader.Entry;
|
||||
if (entry.IsDirectory)
|
||||
{
|
||||
var directoryName = Path.Combine(Path.GetFullPath(destinationDirectory), entry.Key);
|
||||
Directory.CreateDirectory(directoryName);
|
||||
continue;
|
||||
}
|
||||
|
||||
var fileName = Path.Combine(Path.GetFullPath(destinationDirectory), entry.Key);
|
||||
using var entryStream = new FileStream(fileName, FileMode.Create);
|
||||
using (var stream = reader.OpenEntryStream())
|
||||
{
|
||||
stream.CopyTo(entryStream);
|
||||
}
|
||||
|
||||
progress += 1d / count;
|
||||
Console.WriteLine($"{progress} {fileName}");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,39 +0,0 @@
|
||||
# CMakeList.txt : CMake project for Daybreak.GWCA, include source and define
|
||||
# project specific logic here.
|
||||
#
|
||||
|
||||
project(Daybreak.GWCA)
|
||||
|
||||
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_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(Daybreak.GWCA_FOLDER "${CMAKE_CURRENT_LIST_DIR}/")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/")
|
||||
|
||||
add_library(Daybreak.GWCA SHARED)
|
||||
file(GLOB SOURCES
|
||||
"source/pch.h"
|
||||
"source/*.cpp"
|
||||
"source/*/*.cpp"
|
||||
"header/*.h*"
|
||||
"header/*/*.h")
|
||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${SOURCES})
|
||||
target_sources(Daybreak.GWCA PRIVATE ${SOURCES})
|
||||
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>
|
||||
)
|
||||
|
||||
target_precompile_headers(Daybreak.GWCA PRIVATE "header/pch.h")
|
||||
target_include_directories(Daybreak.GWCA PUBLIC "header")
|
||||
|
||||
target_link_libraries(Daybreak.GWCA PUBLIC
|
||||
gwca
|
||||
directx
|
||||
minhook)
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace http {
|
||||
namespace modules {
|
||||
void HandleAlive(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::GameModule {
|
||||
void GetGameInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace http {
|
||||
void ConsoleLogger(const httplib::Request req, httplib::Response res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::InventoryModule {
|
||||
void GetInventoryInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::LoginModule {
|
||||
void GetLoginInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::MainPlayerModule {
|
||||
void GetMainPlayer(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::MapModule {
|
||||
void GetMapInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::PathingMetadataModule {
|
||||
void GetPathingMetadata(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::PathingModule {
|
||||
void GetPathingData(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::PreGameModule {
|
||||
void GetPreGameInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace http {
|
||||
namespace modules {
|
||||
void HandleProcessId(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
#include "pch.h"
|
||||
|
||||
namespace http {
|
||||
namespace server {
|
||||
bool StartServer();
|
||||
void SetLogger(httplib::Logger logger);
|
||||
void Get(const std::string& pattern, httplib::Server::Handler handler);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::SessionModule {
|
||||
void GetSessionInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::UserModule {
|
||||
void GetUserInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files
|
||||
#include <windows.h>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct Attribute {
|
||||
uint32_t Id;
|
||||
uint32_t BaseLevel;
|
||||
uint32_t ActualLevel;
|
||||
uint32_t DecrementPoints;
|
||||
uint32_t IncrementPoints;
|
||||
};
|
||||
|
||||
void to_json(json& j, const Attribute& p);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <payloads/BagContent.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct Bag {
|
||||
std::list<BagContent> Items;
|
||||
};
|
||||
|
||||
void to_json(json& j, const Bag& p);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct BagContent {
|
||||
uint32_t Id = 0;
|
||||
uint32_t Slot = 0;
|
||||
uint32_t Count = 0;
|
||||
std::list<uint32_t> Modifiers;
|
||||
};
|
||||
|
||||
void to_json(json& j, const BagContent& p);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/Attribute.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct Build {
|
||||
uint32_t Primary = 0;
|
||||
uint32_t Secondary = 0;
|
||||
std::list<Attribute> Attributes;
|
||||
std::list<uint32_t> Skills;
|
||||
};
|
||||
|
||||
void to_json(json& j, const Build& p);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/MainPlayer.h>
|
||||
#include <payloads/MapIcon.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct GamePayload {
|
||||
MainPlayer MainPlayer;
|
||||
std::list<Player> Party;
|
||||
std::list<WorldPlayer> WorldPlayers;
|
||||
std::list<LivingEntity> LivingEntities;
|
||||
std::list<MapIcon> MapIcons;
|
||||
uint32_t TargetId = 0;
|
||||
};
|
||||
|
||||
void to_json(json& j, const GamePayload& p);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/Bag.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct InventoryPayload {
|
||||
uint32_t GoldInStorage;
|
||||
uint32_t GoldOnCharacter;
|
||||
Bag Backpack;
|
||||
Bag BeltPouch;
|
||||
Bag EquipmentPack;
|
||||
Bag MaterialStorage;
|
||||
Bag UnclaimedItems;
|
||||
Bag EquippedItems;
|
||||
std::list<Bag> Bags;
|
||||
std::list<Bag> StoragePanes;
|
||||
};
|
||||
|
||||
void to_json(json& j, const InventoryPayload& p);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct LivingEntity {
|
||||
uint32_t Id = 0;
|
||||
uint32_t Timer = 0;
|
||||
float PosX = 0;
|
||||
float PosY = 0;
|
||||
uint32_t NpcDefinition = 0;
|
||||
uint32_t PrimaryProfessionId = 0;
|
||||
uint32_t SecondaryProfessionId = 0;
|
||||
uint32_t Level = 0;
|
||||
uint32_t EntityState = 0;
|
||||
uint32_t EntityAllegiance = 0;
|
||||
};
|
||||
|
||||
void to_json(json& j, const LivingEntity& p);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct LoginPayload {
|
||||
std::string Email;
|
||||
std::string PlayerName;
|
||||
};
|
||||
|
||||
void to_json(json& j, const LoginPayload& p);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/WorldPlayer.h>
|
||||
#include <payloads/QuestMetadata.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct MainPlayer : public WorldPlayer {
|
||||
uint32_t CurrentQuest = 0;
|
||||
std::list<QuestMetadata> QuestLog;
|
||||
bool HardModeUnlocked = false;
|
||||
uint32_t Experience = 0;
|
||||
uint32_t Morale = 0;
|
||||
float CurrentHp = 0;
|
||||
uint32_t MaxHp = 0;
|
||||
float CurrentEnergy = 0;
|
||||
uint32_t MaxEnergy = 0;
|
||||
};
|
||||
|
||||
void to_json(json& j, const MainPlayer& p);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct MapIcon {
|
||||
uint32_t Id;
|
||||
float PosX;
|
||||
float PosY;
|
||||
uint32_t Affiliation;
|
||||
};
|
||||
|
||||
void to_json(json& j, const MapIcon& p);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct MapPayload {
|
||||
bool IsLoaded;
|
||||
uint32_t Id;
|
||||
uint32_t InstanceType;
|
||||
uint32_t Timer;
|
||||
uint32_t Campaign;
|
||||
uint32_t Continent;
|
||||
uint32_t Region;
|
||||
uint32_t Type;
|
||||
};
|
||||
|
||||
void to_json(json& j, const MapPayload& p);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct PathingMetadataPayload {
|
||||
uint32_t TrapezoidCount;
|
||||
};
|
||||
|
||||
void to_json(json& j, const PathingMetadataPayload& p);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <payloads/PathingTrapezoid.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct PathingPayload {
|
||||
std::list<PathingTrapezoid> Trapezoids;
|
||||
std::list<std::list<int>> AdjacencyList;
|
||||
};
|
||||
|
||||
void to_json(json& j, const PathingPayload& p);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct PathingTrapezoid {
|
||||
uint32_t Id;
|
||||
uint32_t PathingMapId;
|
||||
float XTL;
|
||||
float XTR;
|
||||
float XBL;
|
||||
float XBR;
|
||||
float YT;
|
||||
float YB;
|
||||
};
|
||||
|
||||
void to_json(json& j, const PathingTrapezoid& p);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/LivingEntity.h>
|
||||
#include <payloads/Build.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct Player : public LivingEntity {
|
||||
std::list<uint32_t> UnlockedProfession;
|
||||
uint32_t NpcDefinition = 0;
|
||||
Build Build;
|
||||
};
|
||||
|
||||
void to_json(json& j, const Player& p);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct PreGamePayload {
|
||||
int ChosenCharacterIndex;
|
||||
std::list<std::string> Characters;
|
||||
};
|
||||
|
||||
void to_json(json& j, const PreGamePayload& p);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct QuestMetadata {
|
||||
uint32_t Id;
|
||||
float PosX;
|
||||
float PosY;
|
||||
uint32_t FromId;
|
||||
uint32_t ToId;
|
||||
};
|
||||
|
||||
void to_json(json& j, const QuestMetadata& p);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct SessionPayload {
|
||||
uint32_t FoesKilled = 0;
|
||||
uint32_t FoesToKill = 0;
|
||||
uint32_t MapId = 0;
|
||||
uint32_t InstanceTimer = 0;
|
||||
uint32_t InstanceType = 0;
|
||||
};
|
||||
|
||||
void to_json(json& j, const SessionPayload& p);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct Title {
|
||||
uint32_t Id = 0;
|
||||
uint32_t CurrentPoints = 0;
|
||||
uint32_t PointsForCurrentRank = 0;
|
||||
uint32_t PointsForNextRank = 0;
|
||||
uint32_t TierNumber = 0;
|
||||
uint32_t MaxTierNumber = 0;
|
||||
bool IsPercentage = false;
|
||||
};
|
||||
|
||||
void to_json(json& j, const Title& p);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct UserPayload {
|
||||
std::string Email;
|
||||
uint32_t CurrentKurzickPoints;
|
||||
uint32_t TotalKurzickPoints;
|
||||
uint32_t CurrentLuxonPoints;
|
||||
uint32_t TotalLuxonPoints;
|
||||
uint32_t CurrentImperialPoints;
|
||||
uint32_t TotalImperialPoints;
|
||||
uint32_t CurrentBalthazarPoints;
|
||||
uint32_t TotalBalthazarPoints;
|
||||
uint32_t CurrentSkillPoints;
|
||||
uint32_t TotalSkillPoints;
|
||||
uint32_t MaxKurzickPoints;
|
||||
uint32_t MaxLuxonPoints;
|
||||
uint32_t MaxImperialPoints;
|
||||
uint32_t MaxBalthazarPoints;
|
||||
};
|
||||
|
||||
void to_json(json& j, const UserPayload& p);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/Player.h>
|
||||
#include <payloads/Title.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct WorldPlayer : public Player {
|
||||
std::string Name = "";
|
||||
Title Title;
|
||||
};
|
||||
|
||||
void to_json(json& j, const WorldPlayer& p);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for future builds.
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
// add headers that you want to pre-compile here
|
||||
#include "framework.h"
|
||||
|
||||
#endif //PCH_H
|
||||
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace PipeServer {
|
||||
void StartServer();
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#pragma warning(disable: 4619) // there is no warning number 'number'
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4061) // enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label
|
||||
#pragma warning(disable: 4365) // 'action' : conversion from 'type_1' to 'type_2', signed/unsigned mismatch
|
||||
#pragma warning(disable: 4514) // 'function' : unreferenced inline function has been removed
|
||||
#pragma warning(disable: 4530) // C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
|
||||
#pragma warning(disable: 4577) // 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
|
||||
#pragma warning(disable: 4623) // 'derived class' : default constructor was implicitly defined as deleted because a base class default constructor is inaccessible or deleted
|
||||
#pragma warning(disable: 4625) // 'derived class' : copy constructor was implicitly defined as deleted because a base class copy constructor is inaccessible or deleted
|
||||
#pragma warning(disable: 4626) // 'derived class' : assignment operator was implicitly defined as deleted because a base class assignment operator is inaccessible or deleted
|
||||
#pragma warning(disable: 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
|
||||
#pragma warning(disable: 4710) // 'function' : function not inlined
|
||||
#pragma warning(disable: 4711) // function 'function' selected for inline expansion
|
||||
#pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
|
||||
#pragma warning(disable: 4917) // 'declarator' : a GUID can only be associated with a class, interface or namespace
|
||||
#pragma warning(disable: 5026) // 'type': move constructor was implicitly defined as deleted
|
||||
#pragma warning(disable: 5027) // 'type': move assignment operator was implicitly defined as deleted
|
||||
#pragma warning(disable: 5039) // 'function': pointer or reference to potentially throwing function passed to extern C function under -EHc. Undefined behavior may occur if this function throws an exception.
|
||||
#pragma warning(disable: 5045) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
|
||||
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS 1
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <Windows.h>
|
||||
#include <ShellApi.h>
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
|
||||
#pragma warning(disable: 4061) // enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label
|
||||
#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union
|
||||
#pragma warning(disable: 4514) // 'function' : unreferenced inline function has been removed
|
||||
#pragma warning(disable: 4505) // 'function' : unreferenced local function has been removed
|
||||
#pragma warning(disable: 4530) // C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
|
||||
#pragma warning(disable: 4577) // 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
|
||||
#pragma warning(disable: 4623) // 'derived class' : default constructor was implicitly defined as deleted because a base class default constructor is inaccessible or deleted
|
||||
#pragma warning(disable: 4625) // 'derived class' : copy constructor was implicitly defined as deleted because a base class copy constructor is inaccessible or deleted
|
||||
#pragma warning(disable: 4626) // 'derived class' : assignment operator was implicitly defined as deleted because a base class assignment operator is inaccessible or deleted
|
||||
#pragma warning(disable: 4710) // 'function' : function not inlined
|
||||
#pragma warning(disable: 4711) // function 'function' selected for inline expansion
|
||||
#pragma warning(disable: 4774) // 'swprintf' : format string expected in argument 3 is not a string literal
|
||||
#pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
|
||||
#pragma warning(disable: 5026) // 'type': move constructor was implicitly defined as deleted
|
||||
#pragma warning(disable: 5027) // 'type': move assignment operator was implicitly defined as deleted
|
||||
#pragma warning(disable: 5045) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
|
||||
#pragma warning(disable: 28159) // Consider using 'GetTickCount64' instead of 'GetTickCount'.
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/LivingEntity.h>
|
||||
#include <payloads/Build.h>
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak::Temp {
|
||||
struct GWPlayer { // total: 0x4C/76
|
||||
/* +h0000 */ uint32_t agent_id;
|
||||
/* +h0004 */ uint32_t h0004[3];
|
||||
/* +h0010 */ uint32_t appearance_bitmap;
|
||||
/* +h0014 */ uint32_t flags; // Bitwise field
|
||||
/* +h0018 */ uint32_t primary;
|
||||
/* +h001C */ uint32_t secondary;
|
||||
/* +h0020 */ uint32_t h0020;
|
||||
/* +h0024 */ wchar_t* name_enc;
|
||||
/* +h0028 */ wchar_t* name;
|
||||
/* +h002C */ uint32_t party_leader_player_number;
|
||||
/* +h0030 */ uint32_t active_title_tier;
|
||||
/* +h0034 */ uint32_t player_number;
|
||||
/* +h0038 */ uint32_t party_size;
|
||||
/* +h003C */ uint32_t m_buffer; // +h0000
|
||||
/* +h0040 */ uint32_t m_capacity; // +h0004
|
||||
/* +h0044 */ uint32_t m_size; // +h0008
|
||||
/* +h0048 */ uint32_t m_param;
|
||||
|
||||
inline bool IsPvP() {
|
||||
return (flags & 0x800) != 0;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "AliveModule.h"
|
||||
|
||||
namespace http {
|
||||
namespace modules {
|
||||
void HandleAlive(const httplib::Request&, httplib::Response& res) {
|
||||
res.set_content("Yes!", "text/plain");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,607 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "GameModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <GWCA/Managers/AgentMgr.h>
|
||||
#include <GWCA/Managers/PartyMgr.h>
|
||||
#include <GWCA/Managers/PlayerMgr.h>
|
||||
#include <GWCA/Managers/SkillbarMgr.h>
|
||||
#include <GWCA/Managers/QuestMgr.h>
|
||||
#include <GWCA/Context/WorldContext.h>
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/GameEntities/Skill.h>
|
||||
#include <GWCA/GameEntities/Quest.h>
|
||||
#include <GWCA/GameEntities/Agent.h>
|
||||
#include <GWCA/GameEntities/Title.h>
|
||||
#include <GWCA/GameEntities/Party.h>
|
||||
#include <GWCA/GameEntities/Attribute.h>
|
||||
#include <GWCA/GameEntities/Player.h>
|
||||
#include <GWCA/GameEntities/NPC.h>
|
||||
#include <GWCA/Constants/Constants.h>
|
||||
#include <temp/GWPlayer.h>
|
||||
#include <future>
|
||||
#include <payloads/GamePayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Daybreak::Modules::GameModule {
|
||||
std::queue<std::promise<GamePayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
std::string GetString(wchar_t* chars) {
|
||||
if (!chars) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string str(64, '\0');
|
||||
auto length = std::wcstombs(&str[0], chars, 64);
|
||||
str.resize(length);
|
||||
return str;
|
||||
}
|
||||
|
||||
std::list<QuestMetadata> GetQuestLog() {
|
||||
std::list<QuestMetadata> questMetadatas;
|
||||
auto questLog = GW::QuestMgr::GetQuestLog();
|
||||
if (!questLog) {
|
||||
return questMetadatas;
|
||||
}
|
||||
|
||||
for (auto& quest : *questLog) {
|
||||
QuestMetadata metadata;
|
||||
metadata.FromId = (uint32_t)quest.map_from;
|
||||
metadata.ToId = (uint32_t)quest.map_to;
|
||||
metadata.Id = (uint32_t)quest.quest_id;
|
||||
metadata.PosX = (uint32_t)quest.marker.x;
|
||||
metadata.PosY = (uint32_t)quest.marker.y;
|
||||
questMetadatas.push_back(metadata);
|
||||
}
|
||||
|
||||
return questMetadatas;
|
||||
}
|
||||
|
||||
std::vector<GW::MapAgent> GetMapEntities() {
|
||||
std::vector<GW::MapAgent> entities;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& agent : worldContext->map_agents) {
|
||||
entities.push_back(agent);
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
std::list<GW::PartyAttribute> GetPartyAttributes() {
|
||||
std::list<GW::PartyAttribute> attributes;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& attribute : worldContext->attributes) {
|
||||
attributes.push_back(attribute);
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
std::list<GW::ProfessionState> GetProfessions() {
|
||||
std::list<GW::ProfessionState> professions;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& profession : worldContext->party_profession_states) {
|
||||
professions.push_back(profession);
|
||||
}
|
||||
|
||||
return professions;
|
||||
}
|
||||
|
||||
std::list<GW::AgentLiving> GetLivingAgents() {
|
||||
std::list<GW::AgentLiving> agentList;
|
||||
const GW::AgentArray* agents_ptr = GW::Agents::GetAgentArray();
|
||||
GW::AgentArray* agents = GW::Agents::GetAgentArray();
|
||||
if (!agents) {
|
||||
return agentList;
|
||||
}
|
||||
|
||||
for (auto* a : *agents) {
|
||||
const GW::AgentLiving* agent = a ? a->GetAsAgentLiving() : nullptr;
|
||||
if (agent) {
|
||||
agentList.push_back(*agent);
|
||||
}
|
||||
}
|
||||
|
||||
return agentList;
|
||||
}
|
||||
|
||||
std::list<GW::NPC> GetNpcs() {
|
||||
std::list<GW::NPC> npcs;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& npc : worldContext->npcs) {
|
||||
npcs.push_back(npc);
|
||||
}
|
||||
|
||||
return npcs;
|
||||
}
|
||||
|
||||
std::vector<GW::TitleTier> GetTitleTiers() {
|
||||
std::vector<GW::TitleTier> titles;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& title : worldContext->title_tiers) {
|
||||
titles.push_back(title);
|
||||
}
|
||||
|
||||
return titles;
|
||||
}
|
||||
|
||||
std::list<GW::Title> GetTitles() {
|
||||
std::list<GW::Title> titles;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& title : worldContext->titles) {
|
||||
titles.push_back(title);
|
||||
}
|
||||
|
||||
return titles;
|
||||
}
|
||||
|
||||
std::list<Temp::GWPlayer> GetPlayers() {
|
||||
std::list<Temp::GWPlayer> players;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
Temp::GWPlayer *tempPlayerArray = (Temp::GWPlayer*)worldContext->players.m_buffer;
|
||||
if (!tempPlayerArray) {
|
||||
return players;
|
||||
}
|
||||
|
||||
for (auto i = 0; i < worldContext->players.m_size; i++) {
|
||||
if (tempPlayerArray->agent_id != 0) {
|
||||
players.push_back(*tempPlayerArray);
|
||||
}
|
||||
tempPlayerArray++;
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
std::map<uint32_t, std::list<uint32_t>> GetSkillbars() {
|
||||
std::map<uint32_t, std::list<uint32_t>> skillbarMap;
|
||||
auto skillbars = GW::SkillbarMgr::GetSkillbarArray();
|
||||
if (!skillbars) {
|
||||
return skillbarMap;
|
||||
}
|
||||
|
||||
for (auto& skillbar : *skillbars) {
|
||||
std::list<uint32_t> skillList;
|
||||
skillList.push_back((uint32_t)skillbar.skills[0].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[1].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[2].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[3].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[4].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[5].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[6].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[7].skill_id);
|
||||
skillbarMap[skillbar.agent_id] = skillList;
|
||||
}
|
||||
|
||||
return skillbarMap;
|
||||
}
|
||||
|
||||
std::list<LivingEntity> GetLivingEntities(
|
||||
std::list<GW::AgentLiving> agents) {
|
||||
std::list<LivingEntity> entities;
|
||||
for (auto& agent : agents) {
|
||||
LivingEntity entity;
|
||||
entity.PrimaryProfessionId = agent.primary;
|
||||
entity.SecondaryProfessionId = agent.secondary;
|
||||
entity.EntityState = agent.type_map;
|
||||
entity.EntityAllegiance = (uint32_t)agent.allegiance;
|
||||
entity.NpcDefinition = agent.player_number;
|
||||
entity.Id = agent.agent_id;
|
||||
entity.Timer = agent.timer;
|
||||
entity.Level = agent.level;
|
||||
entity.PosX = agent.pos.x;
|
||||
entity.PosY = agent.pos.y;
|
||||
entities.push_back(entity);
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
void PopulatePlayer(
|
||||
Player& player,
|
||||
int playerId,
|
||||
GW::ProfessionState* professionState,
|
||||
std::list<uint32_t> skillbar,
|
||||
GW::PartyAttribute* partyAttribute,
|
||||
GW::AgentLiving* agent) {
|
||||
|
||||
std::list<uint32_t> unlockedProfessions;
|
||||
if (professionState) {
|
||||
for (auto i = 0; i < 11; i++) {
|
||||
auto prof = (GW::Constants::Profession)i;
|
||||
if (professionState->IsProfessionUnlocked(prof)) {
|
||||
unlockedProfessions.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
unlockedProfessions.push_back((uint32_t)professionState->primary);
|
||||
}
|
||||
|
||||
Build build;
|
||||
std::list<Attribute> attributes;
|
||||
if (partyAttribute) {
|
||||
for (const auto& partyAttr : partyAttribute->attribute) {
|
||||
if (((uint32_t)partyAttr.id < 0) ||
|
||||
((uint32_t)partyAttr.id > 44) ||
|
||||
partyAttr.level <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Attribute attribute;
|
||||
attribute.Id = (uint32_t)partyAttr.id;
|
||||
attribute.BaseLevel = partyAttr.level_base;
|
||||
attribute.ActualLevel = partyAttr.level;
|
||||
attribute.DecrementPoints = partyAttr.decrement_points;
|
||||
attribute.IncrementPoints = partyAttr.increment_points;
|
||||
attributes.push_back(attribute);
|
||||
}
|
||||
|
||||
build.Attributes = attributes;
|
||||
if (agent) {
|
||||
build.Primary = (uint32_t)agent->primary;
|
||||
build.Secondary = (uint32_t)agent->secondary;
|
||||
}
|
||||
else if (professionState) {
|
||||
build.Primary = (uint32_t)professionState->primary;
|
||||
build.Secondary = (uint32_t)professionState->secondary;
|
||||
}
|
||||
|
||||
build.Skills = skillbar;
|
||||
player.Build = build;
|
||||
}
|
||||
|
||||
player.UnlockedProfession = unlockedProfessions;
|
||||
player.Id = playerId;
|
||||
if (agent) {
|
||||
player.PosX = agent->pos.x;
|
||||
player.PosY = agent->pos.y;
|
||||
player.Timer = agent->timer;
|
||||
player.Level = agent->level;
|
||||
player.NpcDefinition = agent->player_number;
|
||||
player.PrimaryProfessionId = (uint32_t)agent->primary;
|
||||
player.SecondaryProfessionId = (uint32_t)agent->secondary;
|
||||
}
|
||||
else if (professionState) {
|
||||
player.PrimaryProfessionId = (uint32_t)professionState->primary;
|
||||
player.SecondaryProfessionId = (uint32_t)professionState->secondary;
|
||||
}
|
||||
}
|
||||
|
||||
void PopulateWorldPlayer(
|
||||
std::list<GW::Title> titles,
|
||||
std::vector<GW::TitleTier> titleTiers,
|
||||
WorldPlayer& player,
|
||||
int playerId,
|
||||
Temp::GWPlayer gwPlayer,
|
||||
GW::ProfessionState* professionState,
|
||||
std::list<uint32_t> skillbar,
|
||||
GW::PartyAttribute* partyAttribute,
|
||||
GW::AgentLiving* agent) {
|
||||
|
||||
PopulatePlayer(player, playerId, professionState, skillbar, partyAttribute, agent);
|
||||
GW::Title gwTitle;
|
||||
Title title;
|
||||
int titleId = 0;
|
||||
auto name = GetString(gwPlayer.name);
|
||||
player.Name = name;
|
||||
|
||||
for (const auto &t : titles) {
|
||||
if (t.current_title_tier_index == gwPlayer.active_title_tier) {
|
||||
gwTitle = t;
|
||||
break;
|
||||
}
|
||||
|
||||
titleId++;
|
||||
}
|
||||
|
||||
if (gwTitle.current_title_tier_index >= titleTiers.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto titleTier = titleTiers[gwTitle.current_title_tier_index];
|
||||
title.CurrentPoints = gwTitle.current_points;
|
||||
title.IsPercentage = gwTitle.is_percentage_based();
|
||||
title.PointsForCurrentRank = gwTitle.points_needed_current_rank;
|
||||
title.PointsForNextRank = titleTier.tier_number == gwTitle.max_title_rank ? gwTitle.current_points : gwTitle.points_needed_next_rank;
|
||||
title.TierNumber = titleTier.tier_number;
|
||||
title.MaxTierNumber = gwTitle.max_title_rank;
|
||||
title.Id = titleId;
|
||||
|
||||
player.Title = title;
|
||||
}
|
||||
|
||||
void PopulateMainPlayer(
|
||||
MainPlayer& player,
|
||||
int activeQuestId,
|
||||
std::list<QuestMetadata> questLog,
|
||||
std::list<GW::Title> titles,
|
||||
std::vector<GW::TitleTier> titleTiers,
|
||||
int playerId,
|
||||
Temp::GWPlayer gwPlayer,
|
||||
GW::ProfessionState* professionState,
|
||||
std::list<uint32_t> skillbar,
|
||||
GW::PartyAttribute* partyAttribute,
|
||||
GW::AgentLiving* agent) {
|
||||
PopulateWorldPlayer(titles, titleTiers, player, playerId, gwPlayer, professionState, skillbar, partyAttribute, agent);
|
||||
player.CurrentQuest = activeQuestId;
|
||||
player.QuestLog = questLog;
|
||||
player.HardModeUnlocked = GW::GetWorldContext()->is_hard_mode_unlocked == 1;
|
||||
player.Experience = GW::GetWorldContext()->experience;
|
||||
player.Morale = GW::GetWorldContext()->morale;
|
||||
if (agent) {
|
||||
player.CurrentEnergy = agent->max_energy * agent->energy;
|
||||
player.CurrentHp = agent->max_hp * agent->hp;
|
||||
player.MaxEnergy = agent->max_energy;
|
||||
player.MaxHp = agent->max_hp;
|
||||
}
|
||||
}
|
||||
|
||||
GamePayload GetPayload() {
|
||||
GamePayload gamePayload;
|
||||
gamePayload.TargetId = 0;
|
||||
if (!GW::Map::GetIsMapLoaded()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
gamePayload.TargetId = GW::Agents::GetTargetId();
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
auto activeQuestId = GW::QuestMgr::GetActiveQuestId();
|
||||
auto questLog = GetQuestLog();
|
||||
auto skillbars = GetSkillbars();
|
||||
if (skillbars.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto agents = GetLivingAgents();
|
||||
if (agents.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto titles = GetTitles();
|
||||
if (titles.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto titleTiers = GetTitleTiers();
|
||||
if (titleTiers.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto players = GetPlayers();
|
||||
if (players.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto npcs = GetNpcs();
|
||||
if (npcs.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto attributes = GetPartyAttributes();
|
||||
if (attributes.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto professions = GetProfessions();
|
||||
if (professions.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto mapAgents = GetMapEntities();
|
||||
if (mapAgents.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto playerAgentId = GW::Agents::GetPlayerId();
|
||||
|
||||
std::list<MapIcon> mapIcons;
|
||||
for (const auto &icon : worldContext->mission_map_icons) {
|
||||
MapIcon mapIcon;
|
||||
mapIcon.Id = icon.model_id;
|
||||
mapIcon.Affiliation = icon.option;
|
||||
mapIcon.PosX = icon.X;
|
||||
mapIcon.PosY = icon.Y;
|
||||
mapIcons.push_back(mapIcon);
|
||||
}
|
||||
|
||||
gamePayload.MapIcons = mapIcons;
|
||||
|
||||
std::list<Player> partyMembers;
|
||||
for (auto &prof : professions) {
|
||||
if (prof.agent_id == playerAgentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Player player;
|
||||
auto foundAttr = std::find_if(attributes.begin(), attributes.end(), [&](GW::PartyAttribute attribute) {
|
||||
return prof.agent_id == attribute.agent_id;
|
||||
});
|
||||
|
||||
auto foundAgent = std::find_if(agents.begin(), agents.end(), [&](GW::AgentLiving agentLiving) {
|
||||
return prof.agent_id == agentLiving.agent_id;
|
||||
});
|
||||
|
||||
GW::AgentLiving* agentPtr;
|
||||
if (foundAgent == agents.end()) {
|
||||
agentPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
agentPtr = &*foundAgent;
|
||||
}
|
||||
|
||||
GW::PartyAttribute* attrPtr;
|
||||
if (foundAttr == attributes.end()) {
|
||||
attrPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
attrPtr = &*foundAttr;
|
||||
}
|
||||
|
||||
PopulatePlayer(player, prof.agent_id, &prof, skillbars[prof.agent_id], attrPtr, agentPtr);
|
||||
partyMembers.push_back(player);
|
||||
}
|
||||
gamePayload.Party = partyMembers;
|
||||
|
||||
MainPlayer mainPlayer;
|
||||
auto foundMainAttr = std::find_if(attributes.begin(), attributes.end(), [&](GW::PartyAttribute attribute) {
|
||||
return playerAgentId == attribute.agent_id;
|
||||
});
|
||||
auto foundMainAgent = std::find_if(agents.begin(), agents.end(), [&](GW::AgentLiving agentLiving) {
|
||||
return playerAgentId == agentLiving.agent_id;
|
||||
});
|
||||
auto foundMainProfessionsState = std::find_if(professions.begin(), professions.end(), [&](GW::ProfessionState professionState) {
|
||||
return playerAgentId == professionState.agent_id;
|
||||
});
|
||||
auto foundMainGwPlayer = std::find_if(players.begin(), players.end(), [&](Temp::GWPlayer gwPlayer) {
|
||||
return playerAgentId == gwPlayer.agent_id;
|
||||
});
|
||||
GW::AgentLiving* mainAgentPtr;
|
||||
if (foundMainAgent == agents.end()) {
|
||||
mainAgentPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
mainAgentPtr = &*foundMainAgent;
|
||||
}
|
||||
|
||||
GW::PartyAttribute* mainAttrPtr;
|
||||
if (foundMainAttr == attributes.end()) {
|
||||
mainAttrPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
mainAttrPtr = &*foundMainAttr;
|
||||
}
|
||||
|
||||
GW::ProfessionState* mainProfPtr;
|
||||
if (foundMainProfessionsState == professions.end()) {
|
||||
mainProfPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
mainProfPtr = &*foundMainProfessionsState;
|
||||
}
|
||||
|
||||
PopulateMainPlayer(mainPlayer, (uint32_t)activeQuestId, questLog, titles, titleTiers, playerAgentId, *foundMainGwPlayer, mainProfPtr, skillbars[playerAgentId], mainAttrPtr, mainAgentPtr);
|
||||
gamePayload.MainPlayer = mainPlayer;
|
||||
|
||||
std::list<WorldPlayer> worldPlayers;
|
||||
for (const auto& gwPlayer : players) {
|
||||
if (gwPlayer.agent_id == 0 ||
|
||||
gwPlayer.agent_id == playerAgentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WorldPlayer worldPlayer;
|
||||
auto foundWorldProfessionsState = std::find_if(professions.begin(), professions.end(), [&](GW::ProfessionState professionState) {
|
||||
return gwPlayer.agent_id == professionState.agent_id;
|
||||
});
|
||||
auto foundWorldAttr = std::find_if(attributes.begin(), attributes.end(), [&](GW::PartyAttribute attribute) {
|
||||
return gwPlayer.agent_id == attribute.agent_id;
|
||||
});
|
||||
auto foundWorldAgent = std::find_if(agents.begin(), agents.end(), [&](GW::AgentLiving agentLiving) {
|
||||
return gwPlayer.agent_id == agentLiving.agent_id;
|
||||
});
|
||||
|
||||
std::list<uint32_t> skills;
|
||||
auto foundSkillbar = skillbars.find(gwPlayer.agent_id);
|
||||
if (foundSkillbar != skillbars.end()){
|
||||
skills = foundSkillbar->second;
|
||||
}
|
||||
|
||||
GW::AgentLiving* worldAgentPtr;
|
||||
if (foundWorldAgent == agents.end()) {
|
||||
worldAgentPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
worldAgentPtr = &*foundWorldAgent;
|
||||
}
|
||||
|
||||
GW::PartyAttribute* worldAttrPtr;
|
||||
if (foundWorldAttr == attributes.end()) {
|
||||
worldAttrPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
worldAttrPtr = &*foundWorldAttr;
|
||||
}
|
||||
|
||||
GW::ProfessionState* worldProfPtr;
|
||||
if (foundWorldProfessionsState == professions.end()) {
|
||||
worldProfPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
worldProfPtr = &*foundWorldProfessionsState;
|
||||
}
|
||||
|
||||
PopulateWorldPlayer(titles, titleTiers, worldPlayer, gwPlayer.agent_id, gwPlayer, worldProfPtr, skills, worldAttrPtr, worldAgentPtr);
|
||||
worldPlayers.push_back(worldPlayer);
|
||||
}
|
||||
|
||||
gamePayload.WorldPlayers = worldPlayers;
|
||||
std::list<GW::AgentLiving> livingEntities;
|
||||
for (const auto& agentLiving : agents) {
|
||||
/*
|
||||
* Get all living entities that are not the main player, a world player or a party member.
|
||||
*/
|
||||
if (!agentLiving.GetIsLivingType() ||
|
||||
agentLiving.agent_id == playerAgentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto foundPartyMember = std::find_if(partyMembers.begin(), partyMembers.end(), [&](Daybreak::Player player) { return player.Id == agentLiving.agent_id; });
|
||||
if (foundPartyMember != partyMembers.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto foundWorldPlayer = std::find_if(worldPlayers.begin(), worldPlayers.end(), [&](Daybreak::WorldPlayer player) { return player.Id == agentLiving.agent_id; });
|
||||
if (foundWorldPlayer != worldPlayers.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
livingEntities.push_back(agentLiving);
|
||||
}
|
||||
|
||||
auto livingEntityList = GetLivingEntities(livingEntities);
|
||||
gamePayload.LivingEntities = livingEntityList;
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
GamePayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetGameInfo(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<GamePayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "HttpLogger.h"
|
||||
|
||||
namespace http {
|
||||
void ConsoleLogger(const httplib::Request req, httplib::Response res) {
|
||||
std::cout << req.method << " " << req.path << std::endl << res.status << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "InventoryModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <GWCA/Context/ItemContext.h>
|
||||
#include <GWCA/Managers/ItemMgr.h>
|
||||
#include <GWCA/GameEntities/Item.h>
|
||||
#include <future>
|
||||
#include <payloads/InventoryPayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
|
||||
namespace Daybreak::Modules::InventoryModule {
|
||||
std::queue<std::promise<InventoryPayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
Daybreak::Bag GetBag(GW::Bag* bag) {
|
||||
Bag retBag;
|
||||
if (!bag) {
|
||||
return retBag;
|
||||
}
|
||||
|
||||
for (const auto &item : bag->items) {
|
||||
BagContent bagContent;
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bagContent.Id = item->item_id;
|
||||
bagContent.Slot = item->slot;
|
||||
bagContent.Count = item->quantity;
|
||||
auto modifier = item->mod_struct;
|
||||
for (auto i = 0; i < item->mod_struct_size; i++) {
|
||||
bagContent.Modifiers.push_back((uint32_t)modifier);
|
||||
modifier++;
|
||||
}
|
||||
|
||||
retBag.Items.push_back(bagContent);
|
||||
}
|
||||
|
||||
return retBag;
|
||||
}
|
||||
|
||||
InventoryPayload GetPayload() {
|
||||
InventoryPayload inventoryPayload;
|
||||
if (!GW::Map::GetIsMapLoaded()) {
|
||||
return inventoryPayload;
|
||||
}
|
||||
|
||||
inventoryPayload.GoldInStorage = GW::Items::GetGoldAmountInStorage();
|
||||
inventoryPayload.GoldOnCharacter = GW::Items::GetGoldAmountOnCharacter();
|
||||
auto inventory = GW::GetItemContext()->inventory;
|
||||
inventoryPayload.Backpack = GetBag(inventory->backpack);
|
||||
inventoryPayload.BeltPouch = (GetBag(inventory->belt_pouch));
|
||||
inventoryPayload.Bags.push_back(GetBag(inventory->bag1));
|
||||
inventoryPayload.Bags.push_back(GetBag(inventory->bag2));
|
||||
inventoryPayload.EquipmentPack = (GetBag(inventory->equipment_pack));
|
||||
inventoryPayload.MaterialStorage = (GetBag(inventory->material_storage));
|
||||
inventoryPayload.UnclaimedItems = (GetBag(inventory->unclaimed_items));
|
||||
inventoryPayload.EquippedItems = (GetBag(inventory->equipped_items));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage1));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage2));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage3));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage4));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage5));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage6));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage7));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage8));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage9));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage10));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage11));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage12));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage13));
|
||||
inventoryPayload.StoragePanes.push_back(GetBag(inventory->storage14));
|
||||
return inventoryPayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch(...){
|
||||
InventoryPayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetInventoryInfo(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<InventoryPayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "LoginModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <GWCA/Context/CharContext.h>
|
||||
#include <future>
|
||||
#include <payloads/LoginPayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
|
||||
namespace Daybreak::Modules::LoginModule {
|
||||
std::queue<std::promise<LoginPayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
LoginPayload GetPayload() {
|
||||
auto context = GW::GetCharContext();
|
||||
LoginPayload loginPayload;
|
||||
std::string emailstr(64, '\0');
|
||||
auto length = std::wcstombs(&emailstr[0], context->player_email, 64);
|
||||
emailstr.resize(length);
|
||||
loginPayload.Email = emailstr;
|
||||
|
||||
std::string playerstr(20, '\0');
|
||||
length = std::wcstombs(&playerstr[0], context->player_name, 20);
|
||||
playerstr.resize(length);
|
||||
loginPayload.PlayerName = playerstr;
|
||||
|
||||
return loginPayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
LoginPayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetLoginInfo(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<LoginPayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,477 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "MainPlayerModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <GWCA/Managers/AgentMgr.h>
|
||||
#include <GWCA/Managers/PartyMgr.h>
|
||||
#include <GWCA/Managers/PlayerMgr.h>
|
||||
#include <GWCA/Managers/SkillbarMgr.h>
|
||||
#include <GWCA/Managers/QuestMgr.h>
|
||||
#include <GWCA/Context/WorldContext.h>
|
||||
#include <GWCA/GameContainers/Array.h>
|
||||
#include <GWCA/GameEntities/Skill.h>
|
||||
#include <GWCA/GameEntities/Quest.h>
|
||||
#include <GWCA/GameEntities/Agent.h>
|
||||
#include <GWCA/GameEntities/Title.h>
|
||||
#include <GWCA/GameEntities/Party.h>
|
||||
#include <GWCA/GameEntities/Attribute.h>
|
||||
#include <GWCA/GameEntities/Player.h>
|
||||
#include <GWCA/GameEntities/NPC.h>
|
||||
#include <GWCA/Constants/Constants.h>
|
||||
#include <temp/GWPlayer.h>
|
||||
#include <future>
|
||||
#include <payloads/MainPlayer.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Daybreak::Modules::MainPlayerModule {
|
||||
std::queue<std::promise<MainPlayer>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
std::string GetString(wchar_t* chars) {
|
||||
if (!chars) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string str(64, '\0');
|
||||
auto length = std::wcstombs(&str[0], chars, 64);
|
||||
str.resize(length);
|
||||
return str;
|
||||
}
|
||||
|
||||
std::list<QuestMetadata> GetQuestLog() {
|
||||
std::list<QuestMetadata> questMetadatas;
|
||||
auto questLog = GW::QuestMgr::GetQuestLog();
|
||||
if (!questLog) {
|
||||
return questMetadatas;
|
||||
}
|
||||
|
||||
for (auto& quest : *questLog) {
|
||||
QuestMetadata metadata;
|
||||
metadata.FromId = (uint32_t)quest.map_from;
|
||||
metadata.ToId = (uint32_t)quest.map_to;
|
||||
metadata.Id = (uint32_t)quest.quest_id;
|
||||
metadata.PosX = (uint32_t)quest.marker.x;
|
||||
metadata.PosY = (uint32_t)quest.marker.y;
|
||||
questMetadatas.push_back(metadata);
|
||||
}
|
||||
|
||||
return questMetadatas;
|
||||
}
|
||||
|
||||
std::vector<GW::MapAgent> GetMapEntities() {
|
||||
std::vector<GW::MapAgent> entities;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& agent : worldContext->map_agents) {
|
||||
entities.push_back(agent);
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
std::list<GW::PartyAttribute> GetPartyAttributes() {
|
||||
std::list<GW::PartyAttribute> attributes;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& attribute : worldContext->attributes) {
|
||||
attributes.push_back(attribute);
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
std::list<GW::ProfessionState> GetProfessions() {
|
||||
std::list<GW::ProfessionState> professions;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& profession : worldContext->party_profession_states) {
|
||||
professions.push_back(profession);
|
||||
}
|
||||
|
||||
return professions;
|
||||
}
|
||||
|
||||
std::list<GW::AgentLiving> GetLivingAgents() {
|
||||
std::list<GW::AgentLiving> agentList;
|
||||
const GW::AgentArray* agents_ptr = GW::Agents::GetAgentArray();
|
||||
GW::AgentArray* agents = GW::Agents::GetAgentArray();
|
||||
if (!agents) {
|
||||
return agentList;
|
||||
}
|
||||
|
||||
for (auto* a : *agents) {
|
||||
const GW::AgentLiving* agent = a ? a->GetAsAgentLiving() : nullptr;
|
||||
if (agent) {
|
||||
agentList.push_back(*agent);
|
||||
}
|
||||
}
|
||||
|
||||
return agentList;
|
||||
}
|
||||
|
||||
std::list<GW::NPC> GetNpcs() {
|
||||
std::list<GW::NPC> npcs;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& npc : worldContext->npcs) {
|
||||
npcs.push_back(npc);
|
||||
}
|
||||
|
||||
return npcs;
|
||||
}
|
||||
|
||||
std::vector<GW::TitleTier> GetTitleTiers() {
|
||||
std::vector<GW::TitleTier> titles;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& title : worldContext->title_tiers) {
|
||||
titles.push_back(title);
|
||||
}
|
||||
|
||||
return titles;
|
||||
}
|
||||
|
||||
std::list<GW::Title> GetTitles() {
|
||||
std::list<GW::Title> titles;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
for (auto& title : worldContext->titles) {
|
||||
titles.push_back(title);
|
||||
}
|
||||
|
||||
return titles;
|
||||
}
|
||||
|
||||
std::list<Temp::GWPlayer> GetPlayers() {
|
||||
std::list<Temp::GWPlayer> players;
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
Temp::GWPlayer *tempPlayerArray = (Temp::GWPlayer*)worldContext->players.m_buffer;
|
||||
if (!tempPlayerArray) {
|
||||
return players;
|
||||
}
|
||||
|
||||
for (auto i = 0; i < worldContext->players.m_size; i++) {
|
||||
if (tempPlayerArray->agent_id != 0) {
|
||||
players.push_back(*tempPlayerArray);
|
||||
}
|
||||
tempPlayerArray++;
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
std::map<uint32_t, std::list<uint32_t>> GetSkillbars() {
|
||||
std::map<uint32_t, std::list<uint32_t>> skillbarMap;
|
||||
auto skillbars = GW::SkillbarMgr::GetSkillbarArray();
|
||||
if (!skillbars) {
|
||||
return skillbarMap;
|
||||
}
|
||||
|
||||
for (auto& skillbar : *skillbars) {
|
||||
std::list<uint32_t> skillList;
|
||||
skillList.push_back((uint32_t)skillbar.skills[0].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[1].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[2].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[3].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[4].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[5].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[6].skill_id);
|
||||
skillList.push_back((uint32_t)skillbar.skills[7].skill_id);
|
||||
skillbarMap[skillbar.agent_id] = skillList;
|
||||
}
|
||||
|
||||
return skillbarMap;
|
||||
}
|
||||
|
||||
std::list<LivingEntity> GetLivingEntities(
|
||||
std::list<GW::AgentLiving> agents) {
|
||||
std::list<LivingEntity> entities;
|
||||
for (auto& agent : agents) {
|
||||
LivingEntity entity;
|
||||
entity.PrimaryProfessionId = agent.primary;
|
||||
entity.SecondaryProfessionId = agent.secondary;
|
||||
entity.EntityState = agent.type_map;
|
||||
entity.EntityAllegiance = (uint32_t)agent.allegiance;
|
||||
entity.NpcDefinition = agent.player_number;
|
||||
entity.Id = agent.agent_id;
|
||||
entity.Timer = agent.timer;
|
||||
entity.Level = agent.level;
|
||||
entity.PosX = agent.pos.x;
|
||||
entity.PosY = agent.pos.y;
|
||||
entities.push_back(entity);
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
void PopulatePlayer(
|
||||
Player& player,
|
||||
int playerId,
|
||||
GW::ProfessionState* professionState,
|
||||
std::list<uint32_t> skillbar,
|
||||
GW::PartyAttribute* partyAttribute,
|
||||
GW::AgentLiving* agent) {
|
||||
|
||||
std::list<uint32_t> unlockedProfessions;
|
||||
if (professionState) {
|
||||
for (auto i = 0; i < 11; i++) {
|
||||
auto prof = (GW::Constants::Profession)i;
|
||||
if (professionState->IsProfessionUnlocked(prof)) {
|
||||
unlockedProfessions.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
unlockedProfessions.push_back((uint32_t)professionState->primary);
|
||||
}
|
||||
|
||||
Build build;
|
||||
std::list<Attribute> attributes;
|
||||
if (partyAttribute) {
|
||||
for (const auto& partyAttr : partyAttribute->attribute) {
|
||||
if (((uint32_t)partyAttr.id < 0) ||
|
||||
((uint32_t)partyAttr.id > 44) ||
|
||||
partyAttr.level <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Attribute attribute;
|
||||
attribute.Id = (uint32_t)partyAttr.id;
|
||||
attribute.BaseLevel = partyAttr.level_base;
|
||||
attribute.ActualLevel = partyAttr.level;
|
||||
attribute.DecrementPoints = partyAttr.decrement_points;
|
||||
attribute.IncrementPoints = partyAttr.increment_points;
|
||||
attributes.push_back(attribute);
|
||||
}
|
||||
|
||||
build.Attributes = attributes;
|
||||
if (agent) {
|
||||
build.Primary = (uint32_t)agent->primary;
|
||||
build.Secondary = (uint32_t)agent->secondary;
|
||||
}
|
||||
else if (professionState) {
|
||||
build.Primary = (uint32_t)professionState->primary;
|
||||
build.Secondary = (uint32_t)professionState->secondary;
|
||||
}
|
||||
|
||||
build.Skills = skillbar;
|
||||
player.Build = build;
|
||||
}
|
||||
|
||||
player.UnlockedProfession = unlockedProfessions;
|
||||
player.Id = playerId;
|
||||
if (agent) {
|
||||
player.PosX = agent->pos.x;
|
||||
player.PosY = agent->pos.y;
|
||||
player.Timer = agent->timer;
|
||||
player.Level = agent->level;
|
||||
player.NpcDefinition = agent->player_number;
|
||||
player.PrimaryProfessionId = (uint32_t)agent->primary;
|
||||
player.SecondaryProfessionId = (uint32_t)agent->secondary;
|
||||
}
|
||||
else if (professionState) {
|
||||
player.PrimaryProfessionId = (uint32_t)professionState->primary;
|
||||
player.SecondaryProfessionId = (uint32_t)professionState->secondary;
|
||||
}
|
||||
}
|
||||
|
||||
void PopulateWorldPlayer(
|
||||
std::list<GW::Title> titles,
|
||||
std::vector<GW::TitleTier> titleTiers,
|
||||
WorldPlayer& player,
|
||||
int playerId,
|
||||
Temp::GWPlayer gwPlayer,
|
||||
GW::ProfessionState* professionState,
|
||||
std::list<uint32_t> skillbar,
|
||||
GW::PartyAttribute* partyAttribute,
|
||||
GW::AgentLiving* agent) {
|
||||
|
||||
PopulatePlayer(player, playerId, professionState, skillbar, partyAttribute, agent);
|
||||
GW::Title gwTitle;
|
||||
Title title;
|
||||
int titleId = 0;
|
||||
auto name = GetString(gwPlayer.name);
|
||||
player.Name = name;
|
||||
|
||||
for (const auto &t : titles) {
|
||||
if (t.current_title_tier_index == gwPlayer.active_title_tier) {
|
||||
gwTitle = t;
|
||||
break;
|
||||
}
|
||||
|
||||
titleId++;
|
||||
}
|
||||
|
||||
if (gwTitle.current_title_tier_index >= titleTiers.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto titleTier = titleTiers[gwTitle.current_title_tier_index];
|
||||
title.CurrentPoints = gwTitle.current_points;
|
||||
title.IsPercentage = gwTitle.is_percentage_based();
|
||||
title.PointsForCurrentRank = gwTitle.points_needed_current_rank;
|
||||
title.PointsForNextRank = titleTier.tier_number == gwTitle.max_title_rank ? gwTitle.current_points : gwTitle.points_needed_next_rank;
|
||||
title.TierNumber = titleTier.tier_number;
|
||||
title.MaxTierNumber = gwTitle.max_title_rank;
|
||||
title.Id = titleId;
|
||||
|
||||
player.Title = title;
|
||||
}
|
||||
|
||||
void PopulateMainPlayer(
|
||||
MainPlayer& player,
|
||||
int activeQuestId,
|
||||
std::list<QuestMetadata> questLog,
|
||||
std::list<GW::Title> titles,
|
||||
std::vector<GW::TitleTier> titleTiers,
|
||||
int playerId,
|
||||
Temp::GWPlayer gwPlayer,
|
||||
GW::ProfessionState* professionState,
|
||||
std::list<uint32_t> skillbar,
|
||||
GW::PartyAttribute* partyAttribute,
|
||||
GW::AgentLiving* agent) {
|
||||
PopulateWorldPlayer(titles, titleTiers, player, playerId, gwPlayer, professionState, skillbar, partyAttribute, agent);
|
||||
player.CurrentQuest = activeQuestId;
|
||||
player.QuestLog = questLog;
|
||||
player.HardModeUnlocked = GW::GetWorldContext()->is_hard_mode_unlocked == 1;
|
||||
player.Experience = GW::GetWorldContext()->experience;
|
||||
player.Morale = GW::GetWorldContext()->morale;
|
||||
if (agent) {
|
||||
player.CurrentEnergy = agent->max_energy * agent->energy;
|
||||
player.CurrentHp = agent->max_hp * agent->hp;
|
||||
player.MaxEnergy = agent->max_energy;
|
||||
player.MaxHp = agent->max_hp;
|
||||
}
|
||||
}
|
||||
|
||||
MainPlayer GetPayload() {
|
||||
MainPlayer gamePayload;
|
||||
if (!GW::Map::GetIsMapLoaded()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
auto activeQuestId = GW::QuestMgr::GetActiveQuestId();
|
||||
auto questLog = GetQuestLog();
|
||||
auto skillbars = GetSkillbars();
|
||||
if (skillbars.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto agents = GetLivingAgents();
|
||||
if (agents.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto titles = GetTitles();
|
||||
if (titles.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto titleTiers = GetTitleTiers();
|
||||
if (titleTiers.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto players = GetPlayers();
|
||||
if (players.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto npcs = GetNpcs();
|
||||
if (npcs.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto attributes = GetPartyAttributes();
|
||||
if (attributes.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto professions = GetProfessions();
|
||||
if (professions.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
|
||||
auto mapAgents = GetMapEntities();
|
||||
if (mapAgents.empty()) {
|
||||
return gamePayload;
|
||||
}
|
||||
auto playerAgentId = GW::Agents::GetPlayerId();
|
||||
|
||||
|
||||
MainPlayer mainPlayer;
|
||||
auto foundMainAttr = std::find_if(attributes.begin(), attributes.end(), [&](GW::PartyAttribute attribute) {
|
||||
return playerAgentId == attribute.agent_id;
|
||||
});
|
||||
auto foundMainAgent = std::find_if(agents.begin(), agents.end(), [&](GW::AgentLiving agentLiving) {
|
||||
return playerAgentId == agentLiving.agent_id;
|
||||
});
|
||||
auto foundMainProfessionsState = std::find_if(professions.begin(), professions.end(), [&](GW::ProfessionState professionState) {
|
||||
return playerAgentId == professionState.agent_id;
|
||||
});
|
||||
auto foundMainGwPlayer = std::find_if(players.begin(), players.end(), [&](Temp::GWPlayer gwPlayer) {
|
||||
return playerAgentId == gwPlayer.agent_id;
|
||||
});
|
||||
GW::AgentLiving* mainAgentPtr;
|
||||
if (foundMainAgent == agents.end()) {
|
||||
mainAgentPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
mainAgentPtr = &*foundMainAgent;
|
||||
}
|
||||
|
||||
GW::PartyAttribute* mainAttrPtr;
|
||||
if (foundMainAttr == attributes.end()) {
|
||||
mainAttrPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
mainAttrPtr = &*foundMainAttr;
|
||||
}
|
||||
|
||||
GW::ProfessionState* mainProfPtr;
|
||||
if (foundMainProfessionsState == professions.end()) {
|
||||
mainProfPtr = nullptr;
|
||||
}
|
||||
else {
|
||||
mainProfPtr = &*foundMainProfessionsState;
|
||||
}
|
||||
|
||||
PopulateMainPlayer(mainPlayer, (uint32_t)activeQuestId, questLog, titles, titleTiers, playerAgentId, *foundMainGwPlayer, mainProfPtr, skillbars[playerAgentId], mainAttrPtr, mainAgentPtr);
|
||||
return mainPlayer;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
MainPlayer payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetMainPlayer(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<MainPlayer>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "MapModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <future>
|
||||
#include <payloads/MapPayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
|
||||
namespace Daybreak::Modules::MapModule {
|
||||
std::queue<std::promise<MapPayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
MapPayload GetPayload() {
|
||||
auto isLoaded = GW::Map::GetIsMapLoaded();
|
||||
auto instanceType = GW::Map::GetInstanceType();
|
||||
auto instanceTime = GW::Map::GetInstanceTime();
|
||||
auto mapInfo = GW::Map::GetCurrentMapInfo();
|
||||
auto isInCinematic = GW::Map::GetIsInCinematic();
|
||||
auto region = GW::Map::GetRegion();
|
||||
auto mapId = GW::Map::GetMapID();
|
||||
MapPayload mapPayload;
|
||||
mapPayload.Campaign = mapInfo->campaign;
|
||||
mapPayload.Continent = mapInfo->continent;
|
||||
mapPayload.Region = mapInfo->region;
|
||||
mapPayload.InstanceType = (uint32_t)instanceType;
|
||||
mapPayload.IsLoaded = isLoaded;
|
||||
mapPayload.Timer = instanceTime;
|
||||
mapPayload.Id = (uint32_t)mapId;
|
||||
|
||||
return mapPayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
MapPayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetMapInfo(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<MapPayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "PathingMetadataModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <future>
|
||||
#include <payloads/PathingMetadataPayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
#include <GWCA/GameEntities/Pathing.h>
|
||||
|
||||
namespace Daybreak::Modules::PathingMetadataModule {
|
||||
std::queue<std::promise<PathingMetadataPayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
PathingMetadataPayload GetPayload() {
|
||||
PathingMetadataPayload pathingPayload;
|
||||
pathingPayload.TrapezoidCount = 0;
|
||||
if (!GW::Map::GetIsMapLoaded()) {
|
||||
return pathingPayload;
|
||||
}
|
||||
|
||||
auto pathingMap = GW::Map::GetPathingMap();
|
||||
int count = 0;
|
||||
for (int i = 0; i < pathingMap->size(); i++) {
|
||||
auto gwPathingMap = pathingMap->at(i);
|
||||
count += gwPathingMap.trapezoid_count;
|
||||
}
|
||||
|
||||
pathingPayload.TrapezoidCount = count;
|
||||
return pathingPayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
PathingMetadataPayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetPathingMetadata(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<PathingMetadataPayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "PathingModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <future>
|
||||
#include <payloads/PathingPayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
#include <GWCA/GameEntities/Pathing.h>
|
||||
|
||||
namespace Daybreak::Modules::PathingModule {
|
||||
std::queue<std::promise<PathingPayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
PathingPayload GetPayload() {
|
||||
PathingPayload pathingPayload;
|
||||
pathingPayload.Trapezoids.clear();
|
||||
pathingPayload.AdjacencyList.clear();
|
||||
if (!GW::Map::GetIsMapLoaded()) {
|
||||
return pathingPayload;
|
||||
}
|
||||
|
||||
auto pathingMap = GW::Map::GetPathingMap();
|
||||
std::list<PathingTrapezoid> trapezoids;
|
||||
std::map<int, std::list<int>> adjacencyMap;
|
||||
for (int i = 0; i < pathingMap->size(); i++) {
|
||||
auto gwPathingMap = pathingMap->at(i);
|
||||
for (int j = 0; j < gwPathingMap.trapezoid_count; j++) {
|
||||
auto gwTrapezoid = gwPathingMap.trapezoids[j];
|
||||
PathingTrapezoid trapezoid;
|
||||
trapezoid.Id = gwTrapezoid.id;
|
||||
trapezoid.PathingMapId = i;
|
||||
trapezoid.XTL = gwTrapezoid.XTL;
|
||||
trapezoid.XBL = gwTrapezoid.XBL;
|
||||
trapezoid.XTR = gwTrapezoid.XTR;
|
||||
trapezoid.XBR = gwTrapezoid.XBR;
|
||||
trapezoid.YT = gwTrapezoid.YT;
|
||||
trapezoid.YB = gwTrapezoid.YB;
|
||||
|
||||
trapezoids.push_back(trapezoid);
|
||||
for (int k = 0; k < 4; k++) {
|
||||
auto adjacentTrapezoid = gwTrapezoid.adjacent[k];
|
||||
if (adjacentTrapezoid) {
|
||||
adjacencyMap[trapezoid.Id].push_back(adjacentTrapezoid->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::list<std::list<int>> adjacencyList;
|
||||
for (const auto& pair : adjacencyMap) {
|
||||
adjacencyList.push_back(pair.second);
|
||||
}
|
||||
|
||||
pathingPayload.Trapezoids = trapezoids;
|
||||
pathingPayload.AdjacencyList = adjacencyList;
|
||||
return pathingPayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
PathingPayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetPathingData(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<PathingPayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "MapModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <future>
|
||||
#include <payloads/PreGamePayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
#include <GWCA/GWCA.h>
|
||||
#include <GWCA/Context/PreGameContext.h>
|
||||
|
||||
namespace Daybreak::Modules::PreGameModule {
|
||||
std::queue<std::promise<PreGamePayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
PreGamePayload GetPayload() {
|
||||
PreGamePayload preGamePayload;
|
||||
if (GW::Map::GetIsMapLoaded()) {
|
||||
preGamePayload.Characters.clear();
|
||||
preGamePayload.ChosenCharacterIndex = 0;
|
||||
return preGamePayload;
|
||||
}
|
||||
|
||||
auto context = GW::GetPreGameContext();
|
||||
for (const auto& loginChar : context->chars) {
|
||||
std::string charName(20, '\0');
|
||||
auto length = std::wcstombs(&charName[0], loginChar.character_name, 20);
|
||||
charName.resize(length);
|
||||
preGamePayload.Characters.push_back(charName);
|
||||
}
|
||||
|
||||
preGamePayload.ChosenCharacterIndex = context->index_1;
|
||||
return preGamePayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
PreGamePayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetPreGameInfo(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<PreGamePayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "ProcessIdModule.h"
|
||||
|
||||
namespace http {
|
||||
namespace modules {
|
||||
static DWORD processId = 0;
|
||||
|
||||
int GetProcessId() {
|
||||
if (processId > 0) {
|
||||
return processId;
|
||||
}
|
||||
|
||||
processId = GetCurrentProcessId();
|
||||
return processId;
|
||||
}
|
||||
|
||||
void HandleProcessId(const httplib::Request&, httplib::Response& res) {
|
||||
res.set_content(std::to_string(GetProcessId()), "text/plain");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "Server.h"
|
||||
|
||||
namespace http {
|
||||
namespace server {
|
||||
static httplib::Server server;
|
||||
|
||||
static int FindPort() {
|
||||
// Initialize Winsock
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
std::cout << "Failed to initialize Winsock." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create a socket
|
||||
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverSocket == INVALID_SOCKET) {
|
||||
std::cout << "Failed to create socket." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sockaddr_in serverAddr;
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
// Start from a specific port number and find an available port
|
||||
int port = 48557;
|
||||
while (true) {
|
||||
serverAddr.sin_port = htons(port);
|
||||
|
||||
if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == 0) {
|
||||
std::cout << "Successfully bound to port " << port << std::endl;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
port++; // Try the next port
|
||||
}
|
||||
|
||||
if (port > 65534) {
|
||||
std::cout << "Failed to find a port. Cannot initialize server" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
closesocket(serverSocket);
|
||||
WSACleanup();
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
void Get(const std::string& pattern, httplib::Server::Handler handler) {
|
||||
server.Get(pattern, handler);
|
||||
}
|
||||
|
||||
void SetLogger(httplib::Logger logger) {
|
||||
server.set_logger(logger);
|
||||
}
|
||||
|
||||
bool StartServer() {
|
||||
int port = FindPort();
|
||||
if (port > 0) {
|
||||
std::cout << "Initializing server on port " << port << std::endl;
|
||||
server.listen("0.0.0.0", port);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "SessionModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <future>
|
||||
#include <payloads/SessionPayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
#include <GWCA/Context/AgentContext.h>
|
||||
#include <GWCA/Context/WorldContext.h>
|
||||
|
||||
namespace Daybreak::Modules::SessionModule {
|
||||
std::queue<std::promise<SessionPayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
SessionPayload GetPayload() {
|
||||
SessionPayload sessionPayload;
|
||||
sessionPayload.MapId = (uint32_t)GW::Map::GetMapID();
|
||||
sessionPayload.InstanceType = (uint32_t)GW::Map::GetInstanceType();
|
||||
|
||||
const auto worldContext = GW::GetWorldContext();
|
||||
if (!worldContext) {
|
||||
return sessionPayload;
|
||||
}
|
||||
|
||||
sessionPayload.FoesKilled = worldContext->foes_killed;
|
||||
sessionPayload.FoesToKill = worldContext->foes_to_kill;
|
||||
|
||||
const auto agentContext = GW::GetAgentContext();
|
||||
if (!agentContext) {
|
||||
return sessionPayload;
|
||||
}
|
||||
|
||||
sessionPayload.InstanceTimer = agentContext->instance_timer;
|
||||
return sessionPayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
SessionPayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetSessionInfo(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<SessionPayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "UserModule.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <future>
|
||||
#include <payloads/UserPayload.h>
|
||||
#include <json.hpp>
|
||||
#include <queue>
|
||||
#include <GWCA/Context/CharContext.h>
|
||||
#include <GWCA/Context/WorldContext.h>
|
||||
|
||||
namespace Daybreak::Modules::UserModule {
|
||||
std::queue<std::promise<UserPayload>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
UserPayload GetPayload() {
|
||||
UserPayload userPayload;
|
||||
auto charContext = GW::GetCharContext();
|
||||
auto worldContext = GW::GetWorldContext();
|
||||
std::string emailstr(64, '\0');
|
||||
auto length = std::wcstombs(&emailstr[0], charContext->player_email, 64);
|
||||
emailstr.resize(length);
|
||||
userPayload.Email = emailstr;
|
||||
userPayload.CurrentKurzickPoints = worldContext->current_kurzick;
|
||||
userPayload.CurrentLuxonPoints = worldContext->current_luxon;
|
||||
userPayload.CurrentImperialPoints = worldContext->current_imperial;
|
||||
userPayload.CurrentBalthazarPoints = worldContext->current_balth;
|
||||
userPayload.CurrentSkillPoints = worldContext->current_skill_points;
|
||||
userPayload.TotalKurzickPoints = worldContext->total_earned_kurzick;
|
||||
userPayload.TotalLuxonPoints = worldContext->total_earned_luxon;
|
||||
userPayload.TotalImperialPoints = worldContext->total_earned_imperial;
|
||||
userPayload.TotalBalthazarPoints = worldContext->total_earned_balth;
|
||||
userPayload.TotalSkillPoints = worldContext->total_earned_skill_points;
|
||||
userPayload.MaxKurzickPoints = worldContext->max_kurzick;
|
||||
userPayload.MaxLuxonPoints = worldContext->max_luxon;
|
||||
userPayload.MaxImperialPoints = worldContext->max_imperial;
|
||||
userPayload.MaxBalthazarPoints = worldContext->max_balth;
|
||||
|
||||
return userPayload;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promise = PromiseQueue.front();
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto payload = GetPayload();
|
||||
promise->set_value(GetPayload());
|
||||
}
|
||||
catch (...) {
|
||||
UserPayload payload;
|
||||
promise->set_value(payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetUserInfo(const httplib::Request&, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
auto response = new std::promise<UserPayload>;
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
json responsePayload = response->get_future().get();
|
||||
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
#include "httplib.h"
|
||||
#include <GWCA/GWCA.h>
|
||||
#include "AliveModule.h"
|
||||
#include "ProcessIdModule.h"
|
||||
#include "HttpLogger.h"
|
||||
#include "Server.h"
|
||||
#include "MapModule.h"
|
||||
#include "LoginModule.h"
|
||||
#include "PathingMetadataModule.h"
|
||||
#include "PathingModule.h"
|
||||
#include "PreGameModule.h"
|
||||
#include "InventoryModule.h"
|
||||
#include "UserModule.h"
|
||||
#include "GameModule.h"
|
||||
#include "MainPlayerModule.h"
|
||||
#include "SessionModule.h"
|
||||
|
||||
static FILE* stdout_proxy;
|
||||
static FILE* stderr_proxy;
|
||||
|
||||
|
||||
static DWORD WINAPI ThreadProc(LPVOID lpModule)
|
||||
{
|
||||
// This is a new thread so you should only initialize GWCA and setup the hook on the game thread.
|
||||
// When the game thread hook is setup (i.e. SetRenderCallback), you should do the next operations
|
||||
// on the game from within the game thread.
|
||||
|
||||
HMODULE hModule = static_cast<HMODULE>(lpModule);
|
||||
#ifdef BUILD_TYPE_DEBUG
|
||||
AllocConsole();
|
||||
SetConsoleTitleA("Daybreak.GWCA Console");
|
||||
freopen_s(&stdout_proxy, "CONOUT$", "w", stdout);
|
||||
freopen_s(&stderr_proxy, "CONOUT$", "w", stderr);
|
||||
#endif
|
||||
GW::Initialize();
|
||||
http::server::SetLogger(http::ConsoleLogger);
|
||||
http::server::Get("/alive", http::modules::HandleAlive);
|
||||
http::server::Get("/id", http::modules::HandleProcessId);
|
||||
http::server::Get("/map", Daybreak::Modules::MapModule::GetMapInfo);
|
||||
http::server::Get("/login", Daybreak::Modules::LoginModule::GetLoginInfo);
|
||||
http::server::Get("/pathing/metadata", Daybreak::Modules::PathingMetadataModule::GetPathingMetadata);
|
||||
http::server::Get("/pathing", Daybreak::Modules::PathingModule::GetPathingData);
|
||||
http::server::Get("/pregame", Daybreak::Modules::PreGameModule::GetPreGameInfo);
|
||||
http::server::Get("/user", Daybreak::Modules::UserModule::GetUserInfo);
|
||||
http::server::Get("/game", Daybreak::Modules::GameModule::GetGameInfo);
|
||||
http::server::Get("/inventory", Daybreak::Modules::InventoryModule::GetInventoryInfo);
|
||||
http::server::Get("/game/mainplayer", Daybreak::Modules::MainPlayerModule::GetMainPlayer);
|
||||
http::server::Get("/session", Daybreak::Modules::SessionModule::GetSessionInfo);
|
||||
http::server::StartServer();
|
||||
|
||||
#ifdef BUILD_TYPE_DEBUG
|
||||
if (stdout_proxy)
|
||||
fclose(stdout_proxy);
|
||||
if (stderr_proxy)
|
||||
fclose(stderr_proxy);
|
||||
FreeConsole();
|
||||
#endif
|
||||
|
||||
FreeLibraryAndExitThread(hModule, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
DisableThreadLibraryCalls(hModule);
|
||||
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
|
||||
HANDLE handle = CreateThread(0, 0, ThreadProc, hModule, 0, 0);
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <payloads/Attribute.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const Attribute& p) {
|
||||
j = json
|
||||
{
|
||||
{"Id", p.Id},
|
||||
{"BaseLevel", p.BaseLevel},
|
||||
{"ActualLevel", p.ActualLevel},
|
||||
{"DecrementPoints", p.DecrementPoints},
|
||||
{"IncrementPoints", p.IncrementPoints},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <payloads/BagContent.h>
|
||||
#include <payloads/Bag.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const Bag& p) {
|
||||
j = json
|
||||
{
|
||||
{"Items", p.Items},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <payloads/BagContent.h>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const BagContent& p) {
|
||||
j = json
|
||||
{
|
||||
{"Id", p.Id},
|
||||
{"Slot", p.Slot},
|
||||
{"Count", p.Count},
|
||||
{"Modifiers", p.Modifiers},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/Build.h>
|
||||
#include <payloads/Attribute.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const Build& p) {
|
||||
j = json
|
||||
{
|
||||
{"Primary", p.Primary},
|
||||
{"Secondary", p.Secondary},
|
||||
{"Attributes", p.Attributes},
|
||||
{"Skills", p.Skills}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/MainPlayer.h>
|
||||
#include <payloads/MapIcon.h>
|
||||
#include <payloads/GamePayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const GamePayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"MainPlayer", p.MainPlayer},
|
||||
{"Party", p.Party},
|
||||
{"WorldPlayers", p.WorldPlayers},
|
||||
{"LivingEntities", p.LivingEntities},
|
||||
{"MapIcons", p.MapIcons},
|
||||
{"TargetId", p.TargetId},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/Bag.h>
|
||||
#include <payloads/InventoryPayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const InventoryPayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"GoldInStorage", p.GoldInStorage},
|
||||
{"GoldOnCharacter", p.GoldOnCharacter},
|
||||
{"Backpack", p.Backpack},
|
||||
{"BeltPouch", p.BeltPouch},
|
||||
{"Bags", p.Bags},
|
||||
{"EquipmentPack", p.EquipmentPack},
|
||||
{"MaterialStorage", p.MaterialStorage},
|
||||
{"UnclaimedItems", p.UnclaimedItems},
|
||||
{"StoragePanes", p.StoragePanes},
|
||||
{"EquippedItems", p.EquippedItems},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/LivingEntity.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const LivingEntity& p) {
|
||||
j = json
|
||||
{
|
||||
{"Id", p.Id},
|
||||
{"Timer", p.Timer},
|
||||
{"PosX", p.PosX},
|
||||
{"PosY", p.PosY},
|
||||
{"NpcDefinition", p.NpcDefinition},
|
||||
{"PrimaryProfessionId", p.PrimaryProfessionId},
|
||||
{"SecondaryProfessionId", p.SecondaryProfessionId},
|
||||
{"Level", p.Level},
|
||||
{"EntityState", p.EntityState},
|
||||
{"EntityAllegiance", p.EntityAllegiance},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/LoginPayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const LoginPayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"Email", p.Email},
|
||||
{"PlayerName", p.PlayerName},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/WorldPlayer.h>
|
||||
#include <payloads/QuestMetadata.h>
|
||||
#include <payloads/MainPlayer.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const MainPlayer& p) {
|
||||
to_json(j, (WorldPlayer)p);
|
||||
j["CurrentQuest"] = p.CurrentQuest;
|
||||
j["QuestLog"] = p.QuestLog;
|
||||
j["HardModeUnlocked"] = p.HardModeUnlocked;
|
||||
j["Experience"] = p.Experience;
|
||||
j["Morale"] = p.Morale;
|
||||
j["CurrentHp"] = p.CurrentHp;
|
||||
j["MaxHp"] = p.MaxHp;
|
||||
j["CurrentEnergy"] = p.CurrentEnergy;
|
||||
j["MaxEnergy"] = p.MaxEnergy;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/MapIcon.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const MapIcon& p) {
|
||||
j = json
|
||||
{
|
||||
{"Id", p.Id},
|
||||
{"PosX", p.PosX},
|
||||
{"PosY", p.PosY},
|
||||
{"Affiliation", p.Affiliation},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/MapPayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const MapPayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"IsLoaded", p.IsLoaded},
|
||||
{"Id", p.Id},
|
||||
{"InstanceType", p.InstanceType},
|
||||
{"Timer", p.Timer},
|
||||
{"Campaign", p.Campaign},
|
||||
{"Continent", p.Continent},
|
||||
{"Region", p.Region},
|
||||
{"Type", p.Type},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/PathingMetadataPayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const PathingMetadataPayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"TrapezoidCount", p.TrapezoidCount},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <payloads/PathingTrapezoid.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/PathingPayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const PathingPayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"Trapezoids", p.Trapezoids},
|
||||
{"AdjacencyList", p.AdjacencyList}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/PathingTrapezoid.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const PathingTrapezoid& p) {
|
||||
j = json
|
||||
{
|
||||
{"Id", p.Id},
|
||||
{"PathingMapId", p.PathingMapId},
|
||||
{"XTL", p.XTL},
|
||||
{"XTR", p.XTR},
|
||||
{"XBL", p.XBL},
|
||||
{"XBR", p.XBR},
|
||||
{"YT", p.YT},
|
||||
{"YB", p.YB},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/LivingEntity.h>
|
||||
#include <payloads/Build.h>
|
||||
#include <payloads/Player.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const Player& p) {
|
||||
to_json(j, (LivingEntity)p);
|
||||
j["UnlockedProfession"] = p.UnlockedProfession;
|
||||
j["NpcDefinition"] = p.NpcDefinition;
|
||||
j["Build"] = p.Build;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <json.hpp>
|
||||
#include <payloads/PreGamePayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const PreGamePayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"ChosenCharacterIndex", p.ChosenCharacterIndex},
|
||||
{"Characters", p.Characters},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/QuestMetadata.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const QuestMetadata& p) {
|
||||
j = json
|
||||
{
|
||||
{"Id", p.Id},
|
||||
{"PosX", p.PosX},
|
||||
{"PosY", p.PosY},
|
||||
{"FromId", p.FromId},
|
||||
{"ToId", p.ToId},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <json.hpp>
|
||||
#include <payloads/SessionPayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const SessionPayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"FoedKilled", p.FoesKilled},
|
||||
{"FoesToKill", p.FoesToKill},
|
||||
{"MapId", p.MapId},
|
||||
{"InstanceTimer", p.InstanceTimer},
|
||||
{"InstanceType", p.InstanceType},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/Title.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const Title& p) {
|
||||
j = json
|
||||
{
|
||||
{"Id", p.Id},
|
||||
{"CurrentPoints", p.CurrentPoints},
|
||||
{"PointsForCurrentRank", p.PointsForCurrentRank},
|
||||
{"PointsForNextRank", p.PointsForNextRank},
|
||||
{"TierNumber", p.TierNumber},
|
||||
{"MaxTierNumber", p.MaxTierNumber},
|
||||
{"IsPercentage", p.IsPercentage},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <json.hpp>
|
||||
#include <payloads/UserPayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const UserPayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"Email", p.Email},
|
||||
{"CurrentKurzickPoints", p.CurrentKurzickPoints},
|
||||
{"CurrentLuxonPoints", p.CurrentLuxonPoints},
|
||||
{"CurrentImperialPoints", p.CurrentImperialPoints},
|
||||
{"CurrentBalthazarPoints", p.CurrentBalthazarPoints},
|
||||
{"CurrentSkillPoints", p.CurrentSkillPoints},
|
||||
{"TotalKurzickPoints", p.TotalKurzickPoints},
|
||||
{"TotalLuxonPoints", p.TotalLuxonPoints},
|
||||
{"TotalImperialPoints", p.TotalImperialPoints},
|
||||
{"TotalBalthazarPoints", p.TotalBalthazarPoints},
|
||||
{"TotalSkillPoints", p.TotalSkillPoints},
|
||||
{"MaxKurzickPoints", p.MaxKurzickPoints},
|
||||
{"MaxLuxonPoints", p.MaxLuxonPoints},
|
||||
{"MaxImperialPoints", p.MaxImperialPoints},
|
||||
{"MaxBalthazarPoints", p.MaxBalthazarPoints},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <GWCA/GameEntities/Map.h>
|
||||
#include <json.hpp>
|
||||
#include <payloads/Player.h>
|
||||
#include <payloads/Title.h>
|
||||
#include <payloads/WorldPlayer.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const WorldPlayer& p) {
|
||||
to_json(j, (Player)p);
|
||||
j["Title"] = p.Title;
|
||||
j["Name"] = p.Name;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
||||
@@ -1,106 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include <iostream>
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
namespace PipeServer {
|
||||
// Function to handle a single client connection
|
||||
void HandleClient(HANDLE hPipe)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
char buffer[1024];
|
||||
DWORD bytesRead;
|
||||
|
||||
if (!ReadFile(hPipe, buffer, sizeof(buffer), &bytesRead, NULL) || bytesRead == 0)
|
||||
{
|
||||
break; // Error or client closed the connection
|
||||
}
|
||||
|
||||
// Process data received from the client (e.g., display or manipulate it)
|
||||
std::cout << "Received from client: " << buffer << std::endl;
|
||||
|
||||
// Send a response back to the client (optional)
|
||||
const char* response = "Hello from server!";
|
||||
DWORD bytesWritten;
|
||||
WriteFile(hPipe, response, static_cast<DWORD>(strlen(response) + 1), &bytesWritten, NULL);
|
||||
}
|
||||
|
||||
// Close the pipe handle when the client disconnects
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
|
||||
void StartServer()
|
||||
{
|
||||
DWORD processId = GetCurrentProcessId();
|
||||
// Create a buffer to store the formatted process ID as a wide string
|
||||
wchar_t processIdStr[12]; // Assuming DWORD can be represented in 10 characters
|
||||
|
||||
// Format the process ID into the buffer as a wide string
|
||||
swprintf_s(processIdStr, L"%u", processId);
|
||||
std::wstring pipeName = L"\\\\.\\pipe\\Daybreak";
|
||||
pipeName += processIdStr;
|
||||
|
||||
HANDLE hPipe = CreateNamedPipeW(
|
||||
pipeName.c_str(), // Use the generated pipe name
|
||||
PIPE_ACCESS_DUPLEX,
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||
1,
|
||||
1024, 1024,
|
||||
1000,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (hPipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
std::cerr << "Error: CreateNamedPipe failed with error code " << GetLastError() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Created named pipe ";
|
||||
wprintf(L"%s\n", pipeName.c_str());
|
||||
std::cout << "Waiting for clients to connect..." << std::endl;
|
||||
// Wait for client connections and handle them in separate threads
|
||||
std::vector<std::thread> clientThreads;
|
||||
HANDLE io_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
OVERLAPPED overlapped;
|
||||
if (io_event == NULL) {
|
||||
std::cout << "Failed to create event" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
overlapped.hEvent = io_event;
|
||||
if (ConnectNamedPipe(hPipe, &overlapped))
|
||||
{
|
||||
// A client has connected, create a thread to handle it
|
||||
std::cout << "Client connected" << std::endl;
|
||||
clientThreads.emplace_back(HandleClient, hPipe);
|
||||
clientThreads.back().detach();
|
||||
}
|
||||
else {
|
||||
DWORD err = GetLastError();
|
||||
std::cout << "Failed to connect named pipe " << err << std::endl;
|
||||
if (err == ERROR_PIPE_CONNECTED) {
|
||||
std::cout << "Pipe connection was successful. Client connected" << std::endl;
|
||||
clientThreads.emplace_back(HandleClient, hPipe);
|
||||
clientThreads.back().detach();
|
||||
}
|
||||
|
||||
if (err == ERROR_IO_PENDING)
|
||||
{
|
||||
std::cout << "Error IO Pending" << std::endl;
|
||||
}
|
||||
if (err == ERROR_PIPE_LISTENING)
|
||||
{
|
||||
std::cout << "Error Pipe Listening" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hPipe); // Close the server pipe when done
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
@@ -2,10 +2,14 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net9.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>
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<TargetFramework>net9.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="coverlet.collector" Version="6.0.0">
|
||||
<PackageReference Include="FluentAssertions" Version="8.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.8.3" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.8.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NSubstitute" Version="5.1.0" />
|
||||
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.16">
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.17">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
<PackageReference Include="System.Private.Uri" Version="4.3.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -14,7 +14,7 @@ public abstract class ItemTestsBase<T>
|
||||
protected abstract IEnumerable<T> AllItems { get; }
|
||||
|
||||
[TestMethod]
|
||||
public void InscriptionList_Should_ContainOnlyUniqueItems()
|
||||
public void List_Should_ContainOnlyUniqueItems()
|
||||
{
|
||||
var itemMap = new Dictionary<T, int>();
|
||||
|
||||
@@ -45,7 +45,7 @@ public abstract class ItemTestsBase<T>
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InscriptionList_Should_ContainAllNpcs()
|
||||
public void List_Should_ContainAllItems()
|
||||
{
|
||||
var itemMap = new Dictionary<T, bool>();
|
||||
var definedItemFields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == typeof(T));
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using Daybreak.Services.ApplicationArguments;
|
||||
using Daybreak.Tests.Services.Models;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NSubstitute;
|
||||
using Slim;
|
||||
|
||||
namespace Daybreak.Tests.Services;
|
||||
|
||||
[TestClass]
|
||||
public class ApplicationArgumentServiceTests
|
||||
{
|
||||
private readonly ServiceManager serviceManager = new();
|
||||
private readonly ApplicationArgumentService applicationArgumentService;
|
||||
|
||||
public ApplicationArgumentServiceTests()
|
||||
{
|
||||
this.applicationArgumentService = new ApplicationArgumentService(this.serviceManager, Substitute.For<ILogger<ApplicationArgumentService>>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void HandleArguments_ExpectedArguments_HandlesCorrectly()
|
||||
{
|
||||
this.serviceManager.RegisterSingleton<TestArgumentHandler>();
|
||||
this.serviceManager.RegisterSingleton<TestArgumentHandler2>();
|
||||
|
||||
this.applicationArgumentService.HandleArguments("-r so me arg -c uments he re and there".Split(" "));
|
||||
|
||||
this.serviceManager.GetRequiredService<TestArgumentHandler>().Called.Should().BeTrue();
|
||||
this.serviceManager.GetRequiredService<TestArgumentHandler2>().Called.Should().BeTrue();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void HandleArguments_NotEnoughArguments_DoesNotCallHandlers()
|
||||
{
|
||||
this.serviceManager.RegisterScoped<TestArgumentHandler>();
|
||||
this.serviceManager.RegisterScoped<TestArgumentHandler2>();
|
||||
|
||||
this.applicationArgumentService.HandleArguments("-r so me arg -c uments he re".Split(" "));
|
||||
|
||||
this.serviceManager.GetRequiredService<TestArgumentHandler>().Called.Should().BeTrue();
|
||||
this.serviceManager.GetRequiredService<TestArgumentHandler2>().Called.Should().BeFalse();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RegisterHandler_RegistersHandler()
|
||||
{
|
||||
this.applicationArgumentService.RegisterArgumentHandler<TestArgumentHandler>();
|
||||
|
||||
var action = this.serviceManager.GetRequiredService<TestArgumentHandler>;
|
||||
|
||||
action.Should().NotThrow();
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,14 @@ using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NSubstitute;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Tests.Services;
|
||||
|
||||
[TestClass]
|
||||
public class BuildTemplateManagerTests
|
||||
{
|
||||
private const string EncodedTemplate = "OwBk0texXNu0Dj/z+TDzBj+TN4AE";
|
||||
private const string EncodedSingleTemplate = "OwBk0texXNu0Dj/z+TDzBj+TN4AE";
|
||||
private const string EncodedTeamTemplate = "OQJUAMxOEMLnw0nDXQGY6aw2B OQNCA8wDP9B8DyzmOUi1veC OggjYxXTIPWbp5krZfxEAAAoD OwUTM4HDn5gc9TJSh6xddmETA";
|
||||
private IBuildTemplateManager buildTemplateManager;
|
||||
|
||||
[TestInitialize]
|
||||
@@ -22,40 +22,263 @@ public class BuildTemplateManagerTests
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestDecode()
|
||||
public void TestSingleDecode()
|
||||
{
|
||||
var build = this.buildTemplateManager.DecodeTemplate(EncodedTemplate);
|
||||
build.Primary.Should().Be(Profession.Assassin);
|
||||
build.Secondary.Should().Be(Profession.None);
|
||||
build.Attributes.Count.Should().Be(4);
|
||||
build.Attributes[1].Attribute.Should().Be(Attribute.DaggerMastery);
|
||||
build.Attributes[1].Points.Should().Be(11);
|
||||
build.Attributes[2].Attribute.Should().Be(Attribute.DeadlyArts);
|
||||
build.Attributes[2].Points.Should().Be(1);
|
||||
build.Attributes[3].Attribute.Should().Be(Attribute.ShadowArts);
|
||||
build.Attributes[3].Points.Should().Be(5);
|
||||
build.Attributes[0].Attribute.Should().Be(Attribute.CriticalStrikes);
|
||||
build.Attributes[0].Points.Should().Be(11);
|
||||
build.Skills.Count.Should().Be(8);
|
||||
build.Skills[0].Should().Be(Skill.UnsuspectingStrike);
|
||||
build.Skills[1].Should().Be(Skill.WildStrike);
|
||||
build.Skills[2].Should().Be(Skill.CriticalStrike);
|
||||
build.Skills[3].Should().Be(Skill.MoebiusStrike);
|
||||
build.Skills[4].Should().Be(Skill.DeathBlossom);
|
||||
build.Skills[5].Should().Be(Skill.CriticalEye);
|
||||
build.Skills[6].Should().Be(Skill.CriticalAgility);
|
||||
build.Skills[7].Should().Be(Skill.CriticalDefenses);
|
||||
var build = this.buildTemplateManager.DecodeTemplate(EncodedSingleTemplate);
|
||||
var singleBuildEntry = build.As<SingleBuildEntry>();
|
||||
singleBuildEntry.Should().NotBeNull();
|
||||
singleBuildEntry.Primary.Should().Be(Profession.Assassin);
|
||||
singleBuildEntry.Secondary.Should().Be(Profession.None);
|
||||
singleBuildEntry.Attributes.Count.Should().Be(4);
|
||||
singleBuildEntry.Attributes[1].Attribute.Should().Be(Attribute.DaggerMastery);
|
||||
singleBuildEntry.Attributes[1].Points.Should().Be(11);
|
||||
singleBuildEntry.Attributes[2].Attribute.Should().Be(Attribute.DeadlyArts);
|
||||
singleBuildEntry.Attributes[2].Points.Should().Be(1);
|
||||
singleBuildEntry.Attributes[3].Attribute.Should().Be(Attribute.ShadowArts);
|
||||
singleBuildEntry.Attributes[3].Points.Should().Be(5);
|
||||
singleBuildEntry.Attributes[0].Attribute.Should().Be(Attribute.CriticalStrikes);
|
||||
singleBuildEntry.Attributes[0].Points.Should().Be(11);
|
||||
singleBuildEntry.Skills.Count.Should().Be(8);
|
||||
singleBuildEntry.Skills[0].Should().Be(Skill.UnsuspectingStrike);
|
||||
singleBuildEntry.Skills[1].Should().Be(Skill.WildStrike);
|
||||
singleBuildEntry.Skills[2].Should().Be(Skill.CriticalStrike);
|
||||
singleBuildEntry.Skills[3].Should().Be(Skill.MoebiusStrike);
|
||||
singleBuildEntry.Skills[4].Should().Be(Skill.DeathBlossom);
|
||||
singleBuildEntry.Skills[5].Should().Be(Skill.CriticalEye);
|
||||
singleBuildEntry.Skills[6].Should().Be(Skill.CriticalAgility);
|
||||
singleBuildEntry.Skills[7].Should().Be(Skill.CriticalDefenses);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestEncode()
|
||||
public void TestTeamDecode()
|
||||
{
|
||||
var build = new Build()
|
||||
var build = this.buildTemplateManager.DecodeTemplate(EncodedTeamTemplate);
|
||||
var teamBuildEntry = build.As<TeamBuildEntry>();
|
||||
teamBuildEntry.Should().NotBeNull();
|
||||
teamBuildEntry.Builds.Should().HaveCount(4);
|
||||
|
||||
var firstBuild = teamBuildEntry.Builds[0];
|
||||
firstBuild.Primary.Should().Be(Profession.Mesmer);
|
||||
firstBuild.Secondary.Should().Be(Profession.Ranger);
|
||||
firstBuild.Attributes.Should().BeEquivalentTo(
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.FastCasting,
|
||||
Points = 6
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 11
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 2
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.BeastMastery,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Marksmanship,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.WildernessSurvival,
|
||||
Points = 12
|
||||
},
|
||||
]);
|
||||
firstBuild.Skills.Should().BeEquivalentTo(
|
||||
[
|
||||
Skill.EnergySurge,
|
||||
Skill.Mistrust,
|
||||
Skill.CryofFrustration,
|
||||
Skill.PowerSpike,
|
||||
Skill.PowerDrain,
|
||||
Skill.UnnaturalSignet,
|
||||
Skill.Empathy,
|
||||
Skill.QuickeningZephyr
|
||||
]);
|
||||
|
||||
var secondBuild = teamBuildEntry.Builds[1];
|
||||
secondBuild.Primary.Should().Be(Profession.Mesmer);
|
||||
secondBuild.Secondary.Should().Be(Profession.Monk);
|
||||
secondBuild.Attributes.Should().BeEquivalentTo(
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.FastCasting,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.HealingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.SmitingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ProtectionPrayers,
|
||||
Points = 0
|
||||
},
|
||||
]);
|
||||
secondBuild.Skills.Should().BeEquivalentTo(
|
||||
[
|
||||
Skill.SymbolicCelerity,
|
||||
Skill.MantraofInscriptions,
|
||||
Skill.KeystoneSignet,
|
||||
Skill.SignetofClumsiness,
|
||||
Skill.UnnaturalSignet,
|
||||
Skill.BaneSignet,
|
||||
Skill.CastigationSignet,
|
||||
Skill.SignetofRage
|
||||
]);
|
||||
|
||||
var thirdBuild = teamBuildEntry.Builds[2];
|
||||
thirdBuild.Primary.Should().Be(Profession.Ranger);
|
||||
thirdBuild.Secondary.Should().Be(Profession.Ritualist);
|
||||
thirdBuild.Attributes.Should().BeEquivalentTo(
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Expertise,
|
||||
Points = 3
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.BeastMastery,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Marksmanship,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.WildernessSurvival,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ChannelingMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Communing,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.RestorationMagic,
|
||||
Points = 12
|
||||
},
|
||||
]);
|
||||
thirdBuild.Skills.Should().BeEquivalentTo(
|
||||
[
|
||||
Skill.XinraesWeapon,
|
||||
Skill.MendBodyandSoul,
|
||||
Skill.SpiritLight,
|
||||
Skill.GhostmirrorLight,
|
||||
Skill.FleshofMyFlesh,
|
||||
Skill.ResurrectionSignet,
|
||||
Skill.NoSkill,
|
||||
Skill.EdgeofExtinction
|
||||
]);
|
||||
|
||||
var fourthBuild = teamBuildEntry.Builds[3];
|
||||
fourthBuild.Primary.Should().Be(Profession.Monk);
|
||||
fourthBuild.Secondary.Should().Be(Profession.Mesmer);
|
||||
fourthBuild.Attributes.Should().BeEquivalentTo(
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DivineFavor,
|
||||
Points = 3
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.HealingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.SmitingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ProtectionPrayers,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 12
|
||||
},
|
||||
]);
|
||||
fourthBuild.Skills.Should().BeEquivalentTo(
|
||||
[
|
||||
Skill.ProtectiveBond,
|
||||
Skill.PurifyingVeil,
|
||||
Skill.BlessedSignet,
|
||||
Skill.MantraofRecall,
|
||||
Skill.ProtectiveSpirit,
|
||||
Skill.ShieldofAbsorption,
|
||||
Skill.ReversalofFortune,
|
||||
Skill.Resurrect
|
||||
]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSingleEncode()
|
||||
{
|
||||
var build = new SingleBuildEntry()
|
||||
{
|
||||
Primary = Profession.Assassin,
|
||||
Secondary = Profession.None,
|
||||
Attributes = new List<AttributeEntry>
|
||||
{
|
||||
Attributes =
|
||||
[
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DaggerMastery,
|
||||
@@ -76,9 +299,9 @@ public class BuildTemplateManagerTests
|
||||
Attribute = Attribute.CriticalStrikes,
|
||||
Points = 11
|
||||
}
|
||||
},
|
||||
Skills = new List<Skill>
|
||||
{
|
||||
],
|
||||
Skills =
|
||||
[
|
||||
Skill.UnsuspectingStrike,
|
||||
Skill.WildStrike,
|
||||
Skill.CriticalStrike,
|
||||
@@ -87,10 +310,231 @@ public class BuildTemplateManagerTests
|
||||
Skill.CriticalEye,
|
||||
Skill.CriticalAgility,
|
||||
Skill.CriticalDefenses
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var encoded = this.buildTemplateManager.EncodeTemplate(build);
|
||||
encoded.Should().Be(EncodedTemplate);
|
||||
encoded.Should().Be(EncodedSingleTemplate);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestTeamEncode()
|
||||
{
|
||||
var build = new TeamBuildEntry
|
||||
{
|
||||
Builds = [
|
||||
new SingleBuildEntry
|
||||
{
|
||||
Primary = Profession.Mesmer,
|
||||
Secondary = Profession.Ranger,
|
||||
Attributes = [
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.FastCasting,
|
||||
Points = 6
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 11
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 2
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.BeastMastery,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Marksmanship,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.WildernessSurvival,
|
||||
Points = 12
|
||||
},
|
||||
],
|
||||
Skills = [
|
||||
Skill.EnergySurge,
|
||||
Skill.Mistrust,
|
||||
Skill.CryofFrustration,
|
||||
Skill.PowerSpike,
|
||||
Skill.PowerDrain,
|
||||
Skill.UnnaturalSignet,
|
||||
Skill.Empathy,
|
||||
Skill.QuickeningZephyr
|
||||
]
|
||||
},
|
||||
new SingleBuildEntry
|
||||
{
|
||||
Primary = Profession.Mesmer,
|
||||
Secondary = Profession.Monk,
|
||||
Attributes = [
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.FastCasting,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.HealingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.SmitingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ProtectionPrayers,
|
||||
Points = 0
|
||||
},
|
||||
],
|
||||
Skills = [
|
||||
Skill.SymbolicCelerity,
|
||||
Skill.MantraofInscriptions,
|
||||
Skill.KeystoneSignet,
|
||||
Skill.SignetofClumsiness,
|
||||
Skill.UnnaturalSignet,
|
||||
Skill.BaneSignet,
|
||||
Skill.CastigationSignet,
|
||||
Skill.SignetofRage
|
||||
]
|
||||
},
|
||||
new SingleBuildEntry
|
||||
{
|
||||
Primary = Profession.Ranger,
|
||||
Secondary = Profession.Ritualist,
|
||||
Attributes = [
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Expertise,
|
||||
Points = 3
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.BeastMastery,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Marksmanship,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.WildernessSurvival,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ChannelingMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.Communing,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.RestorationMagic,
|
||||
Points = 12
|
||||
},
|
||||
],
|
||||
Skills = [
|
||||
Skill.XinraesWeapon,
|
||||
Skill.MendBodyandSoul,
|
||||
Skill.SpiritLight,
|
||||
Skill.GhostmirrorLight,
|
||||
Skill.FleshofMyFlesh,
|
||||
Skill.ResurrectionSignet,
|
||||
Skill.NoSkill,
|
||||
Skill.EdgeofExtinction
|
||||
]
|
||||
},
|
||||
new SingleBuildEntry
|
||||
{
|
||||
Primary = Profession.Monk,
|
||||
Secondary = Profession.Mesmer,
|
||||
Attributes = [
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DivineFavor,
|
||||
Points = 3
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.HealingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.SmitingPrayers,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.ProtectionPrayers,
|
||||
Points = 12
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.DominationMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.IllusionMagic,
|
||||
Points = 0
|
||||
},
|
||||
new AttributeEntry
|
||||
{
|
||||
Attribute = Attribute.InspirationMagic,
|
||||
Points = 12
|
||||
},
|
||||
],
|
||||
Skills = [
|
||||
Skill.ProtectiveBond,
|
||||
Skill.PurifyingVeil,
|
||||
Skill.BlessedSignet,
|
||||
Skill.MantraofRecall,
|
||||
Skill.ProtectiveSpirit,
|
||||
Skill.ShieldofAbsorption,
|
||||
Skill.ReversalofFortune,
|
||||
Skill.Resurrect
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var encoded = this.buildTemplateManager.EncodeTemplate(build);
|
||||
encoded.Should().Be(EncodedTeamTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
using Daybreak.Services.Logging;
|
||||
using FluentAssertions;
|
||||
using LiteDB;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Logging;
|
||||
|
||||
namespace Daybreak.Tests.Services;
|
||||
|
||||
[TestClass]
|
||||
public class JsonLoggerProviderTests
|
||||
{
|
||||
private ILogsManager logsManager;
|
||||
private ILoggerProvider loggerProvider;
|
||||
private ILiteDatabase liteDatabase;
|
||||
|
||||
[TestInitialize]
|
||||
public void InitializeProvider()
|
||||
{
|
||||
File.Delete("Daybreak.db");
|
||||
this.liteDatabase = new LiteDatabase("Daybreak.db");
|
||||
this.logsManager = new JsonLogsManager(this.liteDatabase.GetCollection<Daybreak.Models.Log>());
|
||||
this.loggerProvider = new CVLoggerProvider(this.logsManager);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
this.liteDatabase.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateLoggerReturnsLogger()
|
||||
{
|
||||
var logger = this.loggerProvider.CreateLogger("SomeCategory");
|
||||
logger.Should().NotBeNull();
|
||||
}
|
||||
[TestMethod]
|
||||
public void LoggerLogsAndReaderReadsFiltered()
|
||||
{
|
||||
var logger = this.loggerProvider.CreateLogger("SomeCategory");
|
||||
logger.LogTrace("Logging some trace");
|
||||
logger.LogInformation("Logging some stuff");
|
||||
logger.LogError("Logging some error");
|
||||
|
||||
this.logsManager.GetLogs(l => l.LogLevel < LogLevel.Information).Should().HaveCount(1);
|
||||
var log = this.logsManager.GetLogs(l => l.LogLevel < LogLevel.Information).First();
|
||||
log.LogLevel.Should().Be(LogLevel.Error);
|
||||
}
|
||||
[TestMethod]
|
||||
public void LoggerLogsAndReaderReads()
|
||||
{
|
||||
var logger = this.loggerProvider.CreateLogger("SomeCategory");
|
||||
logger.LogInformation("Logging some stuff");
|
||||
logger.LogError("Logging some error");
|
||||
|
||||
this.logsManager.GetLogs().Should().HaveCount(2);
|
||||
}
|
||||
[TestMethod]
|
||||
public void DeletingLogsShouldDeleteLogs()
|
||||
{
|
||||
var logger = this.loggerProvider.CreateLogger("SomeCategory");
|
||||
logger.LogInformation("Logging some stuff");
|
||||
logger.LogError("Logging some error");
|
||||
|
||||
this.logsManager.GetLogs().Should().HaveCount(2);
|
||||
|
||||
this.logsManager.DeleteLogs();
|
||||
this.logsManager.GetLogs().Should().HaveCount(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Services.ApplicationArguments.ArgumentHandling;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace Daybreak.Tests.Services.Models;
|
||||
public sealed class TestArgumentHandler : IArgumentHandler
|
||||
{
|
||||
public string Identifier => "-r";
|
||||
public int ExpectedArgumentCount => 3;
|
||||
public bool Called { get; private set; }
|
||||
|
||||
public void HandleArguments(string[] args)
|
||||
{
|
||||
args.Should().BeEquivalentTo(["so", "me", "arg"]);
|
||||
this.Called = true;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user