mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-15 21:09:22 +00:00
Compare commits
247
Commits
v0.7.2
...
v0.9.8.129
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db5d62d7c0 | ||
|
|
ed5ccf38c6 | ||
|
|
7671e0c04c | ||
|
|
f3b8221b29 | ||
|
|
8fdc9a67c0 | ||
|
|
bb2e739876 | ||
|
|
852cbff5f3 | ||
|
|
6e1c111876 | ||
|
|
9f60839e40 | ||
|
|
dd37db18b5 | ||
|
|
793d60f7b5 | ||
|
|
08674cd7a6 | ||
|
|
dca3e39a6d | ||
|
|
8a1033d4b6 | ||
|
|
e4ebe558d7 | ||
|
|
70728cc5ed | ||
|
|
b49a0a5ff4 | ||
|
|
b48d959ffb | ||
|
|
b8e1ad89af | ||
|
|
b2bfbfcd86 | ||
|
|
062e28a6d2 | ||
|
|
dc0f833291 | ||
|
|
e598237916 | ||
|
|
6b96d3d9e9 | ||
|
|
1dbb610846 | ||
|
|
5c649b0c15 | ||
|
|
527ab041d9 | ||
|
|
ff94e90259 | ||
|
|
51efbcce1e | ||
|
|
87b2345105 | ||
|
|
5022d33ca9 | ||
|
|
141f949a63 | ||
|
|
3913c71fd8 | ||
|
|
5706652c40 | ||
|
|
768b6b20f5 | ||
|
|
7066b7dbb6 | ||
|
|
17e01fc7b9 | ||
|
|
ee9fcf38b7 | ||
|
|
5abb24bdd4 | ||
|
|
53f17d3f22 | ||
|
|
b728c38dc1 | ||
|
|
5e57b6ecd0 | ||
|
|
e9ffcdf7c3 | ||
|
|
118657de7c | ||
|
|
34c332504b | ||
|
|
d7a29d68a1 | ||
|
|
eefa02837d | ||
|
|
5b2812fa61 | ||
|
|
e3ddfb88c1 | ||
|
|
664d94aeaa | ||
|
|
e2baf63099 | ||
|
|
c1b7000139 | ||
|
|
6e8333d76f | ||
|
|
c67eddc9d4 | ||
|
|
292cf6fd94 | ||
|
|
69038bca43 | ||
|
|
f05d15ce36 | ||
|
|
98cb349d67 | ||
|
|
a4314ee4d5 | ||
|
|
96097bd25a | ||
|
|
14029e6af2 | ||
|
|
365777141d | ||
|
|
aaa5da8d9b | ||
|
|
b898ab5679 | ||
|
|
b896fa5cc7 | ||
|
|
bca9f6d66b | ||
|
|
d6f71cb2eb | ||
|
|
986d09867c | ||
|
|
97cb2151f9 | ||
|
|
338ac100a1 | ||
|
|
01badcee6a | ||
|
|
302cf1114c | ||
|
|
613e03dc75 | ||
|
|
4267359cb2 | ||
|
|
daac8ec787 | ||
|
|
857adec459 | ||
|
|
b46e10a1a6 | ||
|
|
10799b7e9c | ||
|
|
6bbeaa1738 | ||
|
|
1a0f1cbf9a | ||
|
|
68e708fe96 | ||
|
|
a2166f2327 | ||
|
|
6d55366bdc | ||
|
|
28fcaa81cf | ||
|
|
c5efc2990e | ||
|
|
597010b9a1 | ||
|
|
1f71816256 | ||
|
|
7c3618d2b5 | ||
|
|
df9038039c | ||
|
|
9a4b23976a | ||
|
|
8732e0fe5e | ||
|
|
c23b84c4d5 | ||
|
|
345b6a792a | ||
|
|
d9ae52165d | ||
|
|
4f40e8328b | ||
|
|
ebdd828b06 | ||
|
|
711acb55db | ||
|
|
7dfc21bfe0 | ||
|
|
78644a6eec | ||
|
|
30b1d77575 | ||
|
|
a9626d03a4 | ||
|
|
be731bbffb | ||
|
|
8cd40e2de3 | ||
|
|
7745594bb6 | ||
|
|
e43bedf1c2 | ||
|
|
d6623a8646 | ||
|
|
403ba51a7d | ||
|
|
b185a606e6 | ||
|
|
342a9a4826 | ||
|
|
2df2e8a65e | ||
|
|
2d5e9231a9 | ||
|
|
818e2bf1d0 | ||
|
|
f0a876f7cc | ||
|
|
3fae8f91cb | ||
|
|
8b08056ca7 | ||
|
|
39eaf53deb | ||
|
|
4674d1d7e5 | ||
|
|
b8b5cc8b1d | ||
|
|
dc987233a7 | ||
|
|
266b400c22 | ||
|
|
a4ac083fd0 | ||
|
|
320dd16838 | ||
|
|
5c05c636bc | ||
|
|
7103a8a83a | ||
|
|
ad749d801a | ||
|
|
747e9a0490 | ||
|
|
836402bd0f | ||
|
|
a3d5e1ce1f | ||
|
|
f2cc59a4ab | ||
|
|
6ea77f7e05 | ||
|
|
5ea8df7cb9 | ||
|
|
c70e8ec90d | ||
|
|
210e3a8cb1 | ||
|
|
a0c3bb094c | ||
|
|
b4d932692a | ||
|
|
667534a07a | ||
|
|
159928f24b | ||
|
|
8a91ded610 | ||
|
|
4226b7eb32 | ||
|
|
b61c99dd1c | ||
|
|
1ccb0d5334 | ||
|
|
7fa01353dd | ||
|
|
4f849d880b | ||
|
|
4b60c96aad | ||
|
|
a4dc0d65cf | ||
|
|
85e017423f | ||
|
|
b38488937b | ||
|
|
d291d5825a | ||
|
|
9d6162f65f | ||
|
|
f54ab42a92 | ||
|
|
78c8ae3e8f | ||
|
|
c64830c5b6 | ||
|
|
561c7cf7b1 | ||
|
|
2c6862de41 | ||
|
|
69842cbadf | ||
|
|
c7327e7bb2 | ||
|
|
de33ed7fc4 | ||
|
|
c99bb8d074 | ||
|
|
a98e54ebc6 | ||
|
|
a832aa1925 | ||
|
|
c7eb5debcb | ||
|
|
91f0cb4e31 | ||
|
|
5e8407a6ab | ||
|
|
243c2c1536 | ||
|
|
930aca4ffe | ||
|
|
1639cabe8e | ||
|
|
5961a57c5b | ||
|
|
75d9bc6dec | ||
|
|
4ccca32881 | ||
|
|
a7f5d9dd96 | ||
|
|
c8ba125abc | ||
|
|
7d290031f1 | ||
|
|
5220a8c7ac | ||
|
|
33e221f60f | ||
|
|
7f77547c50 | ||
|
|
c5964e33ac | ||
|
|
1c6f3ec797 | ||
|
|
8601f61739 | ||
|
|
91bac0d50b | ||
|
|
0bf03e0fb5 | ||
|
|
81401178a5 | ||
|
|
882357a8e5 | ||
|
|
abf629c5c6 | ||
|
|
758f9004cd | ||
|
|
f174f8cbb3 | ||
|
|
f2f6bde25d | ||
|
|
85f378b303 | ||
|
|
71ab3fdefb | ||
|
|
2f83d6c860 | ||
|
|
3db4975b48 | ||
|
|
6a6eea5d02 | ||
|
|
8fe9eeb32f | ||
|
|
4c1025243b | ||
|
|
f24eb02ca1 | ||
|
|
b01c09491f | ||
|
|
54ae742899 | ||
|
|
4c862463d7 | ||
|
|
b455c89ddc | ||
|
|
782b76cd8e | ||
|
|
230c2d9457 | ||
|
|
63531e3b8c | ||
|
|
ac430305f4 | ||
|
|
3d830cfc16 | ||
|
|
b529aa8861 | ||
|
|
3798daa54e | ||
|
|
624380ed86 | ||
|
|
2b025e225b | ||
|
|
15a67ea28c | ||
|
|
c6b62fd5fd | ||
|
|
3c0877c1a0 | ||
|
|
967b57b9a8 | ||
|
|
f47cc319b5 | ||
|
|
26da84c4e7 | ||
|
|
a39e8dc5c6 | ||
|
|
1bb4669135 | ||
|
|
0203eef006 | ||
|
|
4ab50ee191 | ||
|
|
06c1ec1ac2 | ||
|
|
ef4befdc38 | ||
|
|
33f49ddffa | ||
|
|
49aa249b5b | ||
|
|
c387d44890 | ||
|
|
d4d09e7267 | ||
|
|
dd7bf02a97 | ||
|
|
6d0eeb478f | ||
|
|
d4e9de48b1 | ||
|
|
6bd9877925 | ||
|
|
d38df6596f | ||
|
|
b4e31e859c | ||
|
|
1acd07c1be | ||
|
|
b9b25bb098 | ||
|
|
5ea2981dc7 | ||
|
|
4fb96ca3a4 | ||
|
|
6de52f5585 | ||
|
|
6622e41f64 | ||
|
|
8405e4d1e5 | ||
|
|
0edc3f1560 | ||
|
|
c109fe7561 | ||
|
|
b5413dca5c | ||
|
|
6c2d4a1e70 | ||
|
|
be03f1a32d | ||
|
|
3ed1cc453a | ||
|
|
16030063ed | ||
|
|
458696ad8f | ||
|
|
6201702563 | ||
|
|
c5bea23a8f | ||
|
|
e5f38f77ef |
+137
@@ -0,0 +1,137 @@
|
||||
[*.cs]
|
||||
|
||||
# CA2254: Template should be a static expression
|
||||
dotnet_diagnostic.CA2254.severity = none
|
||||
csharp_indent_labels = one_less_than_current
|
||||
csharp_using_directive_placement = outside_namespace:error
|
||||
csharp_prefer_simple_using_statement = true:error
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_style_namespace_declarations = file_scoped:error
|
||||
csharp_style_prefer_method_group_conversion = true:suggestion
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_lambdas = true:silent
|
||||
csharp_style_expression_bodied_local_functions = false:silent
|
||||
csharp_indent_braces = false
|
||||
insert_final_newline = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_prefer_null_check_over_type_check = true:suggestion
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_prefer_local_over_anonymous_function = true:error
|
||||
csharp_style_prefer_index_operator = true:suggestion
|
||||
csharp_style_prefer_range_operator = true:suggestion
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
||||
csharp_style_prefer_tuple_swap = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_deconstructed_variable_declaration = true:error
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:error
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
|
||||
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
|
||||
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:suggestion
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
csharp_style_prefer_parameter_null_checking = true:suggestion
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
csharp_style_prefer_pattern_matching = true:silent
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_prefer_not_pattern = true:suggestion
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_prefer_extended_property_pattern = true:suggestion
|
||||
csharp_style_var_for_built_in_types = false:silent
|
||||
csharp_style_var_when_type_is_apparent = false:silent
|
||||
csharp_style_var_elsewhere = false:silent
|
||||
csharp_style_prefer_top_level_statements = true:suggestion
|
||||
csharp_style_prefer_utf8_string_literals = true:suggestion
|
||||
csharp_style_prefer_readonly_struct = true:suggestion
|
||||
|
||||
[*.{cs,vb}]
|
||||
#### Naming styles ####
|
||||
|
||||
# Naming rules
|
||||
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = error
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||
|
||||
dotnet_naming_rule.types_should_be_pascal_case.severity = error
|
||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = error
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||
|
||||
# Symbol specifications
|
||||
|
||||
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.interface.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.types.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||
dotnet_naming_style.begins_with_i.required_suffix =
|
||||
dotnet_naming_style.begins_with_i.word_separator =
|
||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
tab_width = 4
|
||||
indent_size = 4
|
||||
end_of_line = crlf
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error
|
||||
dotnet_style_prefer_auto_properties = true:error
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_compound_assignment = true:suggestion
|
||||
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||
dotnet_style_namespace_match_folder = true:suggestion
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||
dotnet_style_predefined_type_for_member_access = true:silent
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
|
||||
dotnet_style_allow_statement_immediately_after_block_experimental = false:suggestion
|
||||
dotnet_code_quality_unused_parameters = all:error
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
|
||||
dotnet_style_qualification_for_field = true:error
|
||||
dotnet_style_qualification_for_property = true:error
|
||||
dotnet_style_qualification_for_method = true:error
|
||||
dotnet_style_qualification_for_event = true:error
|
||||
dotnet_diagnostic.CA1000.severity = error
|
||||
|
||||
[*.vb]
|
||||
dotnet_diagnostic.CA1047.severity = error
|
||||
@@ -0,0 +1 @@
|
||||
* amacocian@yahoo.com
|
||||
@@ -0,0 +1,16 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "nuget"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
@@ -0,0 +1,113 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
|
||||
# This continuous integration pipeline is triggered anytime a user pushes code to the repo.
|
||||
# This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
|
||||
name: Daybreak CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- "Daybreak/**"
|
||||
- "Daybreak.Installer/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x86]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
env:
|
||||
Configuration: Release
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreak.csproj
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get Latest Tag
|
||||
id: getLatestTag
|
||||
uses: WyriHaximus/github-action-get-previous-tag@v1
|
||||
|
||||
- name: Generate changelog
|
||||
id: gen_changelog
|
||||
run: |
|
||||
$changeLog = git log --no-merges --pretty="%h - %s (%an)<br />" ${{ env.LatestReleaseTag }}..HEAD
|
||||
echo "::set-env name=Changelog::$changeLog"
|
||||
env:
|
||||
LatestReleaseTag: ${{steps.getLatestTag.outputs.tag}}
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.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
|
||||
|
||||
- name: Setup project secrets
|
||||
run: |
|
||||
dotnet user-secrets --project Daybreak\Daybreak.csproj set AadApplicationId "${{ secrets.AadApplicationId }}"
|
||||
dotnet user-secrets --project Daybreak\Daybreak.csproj set AadTenantId "${{ secrets.AadTenantId }}"
|
||||
|
||||
- name: Restore project
|
||||
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier --property:SolutionDir=$GITHUB_WORKSPACE
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
- name: Build Daybreak project
|
||||
run: dotnet build Daybreak -c $env:Configuration --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
|
||||
- name: Set version variable
|
||||
run: |
|
||||
$version = .\Scripts\GetBuildVersion.ps1
|
||||
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
|
||||
env:
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
|
||||
- name: Create publish installer files
|
||||
run: dotnet publish .\Daybreak.Installer\Daybreak.Installer.csproj -c $env:Configuration -r $env:RuntimeIdentifier --property:SolutionDir=$env:GITHUB_WORKSPACE -p:PublishReadyToRun=true -p:PublishSingleFile=true --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
|
||||
with:
|
||||
mode: update
|
||||
tag_name: v${{ env.Version }}
|
||||
release_name: Daybreak v${{ env.Version }}
|
||||
assets: .\Publish\daybreakv${{ env.Version }}.zip
|
||||
github_token: ${{ env.GITHUB_TOKEN }}
|
||||
replace_assets: true
|
||||
body_mrkdwn: ${{ env.Changelog }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT license.
|
||||
|
||||
# This continuous integration pipeline is triggered anytime a user pushes code to the repo.
|
||||
# This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
|
||||
name: Daybreak CI Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x86]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
env:
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreak.csproj
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.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
|
||||
|
||||
- name: Execute Unit Tests
|
||||
run: dotnet test $env:Test_Project_Path --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
|
||||
- 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
|
||||
env:
|
||||
Configuration: Debug
|
||||
RuntimeIdentifier: win-${{ matrix.targetplatform }}
|
||||
@@ -0,0 +1,94 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '41 12 * * 6'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'csharp' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
env:
|
||||
Configuration: Release
|
||||
Solution_Path: Daybreak.sln
|
||||
Test_Project_Path: Daybreak.Tests\Daybreak.Tests.csproj
|
||||
Wpf_Project_Path: Daybreak\Daybreak.csproj
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
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
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# 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
|
||||
with:
|
||||
dotnet-version: '7.x'
|
||||
|
||||
#- name: Autobuild
|
||||
# uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Build Daybreak project
|
||||
run: dotnet build Daybreak -c $env:Configuration --property:SolutionDir=$env:GITHUB_WORKSPACE
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
@@ -0,0 +1,55 @@
|
||||
name: Daybreak Version Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- "Daybreak/**"
|
||||
- "Daybreak.Installer/**"
|
||||
|
||||
jobs:
|
||||
|
||||
check_version:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x86]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
env:
|
||||
Configuration: Release
|
||||
Solution_Path: Daybreak.sln
|
||||
Actions_Allow_Unsecure_Commands: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- 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
|
||||
|
||||
- name: Set version variable
|
||||
run: |
|
||||
$version = .\Scripts\GetBuildVersion.ps1
|
||||
echo "::set-env name=Version::$version"
|
||||
|
||||
- name: Check version difference
|
||||
run: |
|
||||
.\Scripts\CompareVersions -currentVersion ${{ env.Version }} -lastVersion ${{ env.LatestReleaseTag }}
|
||||
env:
|
||||
LatestReleaseTag: ${{ steps.getLatestTag.outputs.tag }}
|
||||
@@ -9,6 +9,7 @@
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
*.version
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
@@ -27,6 +28,7 @@ x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "GWCA"]
|
||||
path = GWCA
|
||||
url = https://github.com/GregLando113/GWCA
|
||||
@@ -0,0 +1,16 @@
|
||||
# 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")
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"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",
|
||||
"CMAKE_CXX_FLAGS": "/EHa"
|
||||
},
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,39 @@
|
||||
# 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)
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace http {
|
||||
namespace modules {
|
||||
void HandleAlive(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::GameModule {
|
||||
void GetGameInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace http {
|
||||
void ConsoleLogger(const httplib::Request req, httplib::Response res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::InventoryModule {
|
||||
void GetInventoryInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::LoginModule {
|
||||
void GetLoginInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::MainPlayerModule {
|
||||
void GetMainPlayer(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::MapModule {
|
||||
void GetMapInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::NameModule {
|
||||
void GetName(const httplib::Request& req, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::PathingMetadataModule {
|
||||
void GetPathingMetadata(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::PathingModule {
|
||||
void GetPathingData(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::PreGameModule {
|
||||
void GetPreGameInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace http {
|
||||
namespace modules {
|
||||
void HandleProcessId(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::SessionModule {
|
||||
void GetSessionInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "httplib.h"
|
||||
|
||||
namespace Daybreak::Modules::UserModule {
|
||||
void GetUserInfo(const httplib::Request&, httplib::Response& res);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#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
@@ -0,0 +1,18 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
struct NamePayload {
|
||||
uint32_t Id = 0;
|
||||
std::string Name = "";
|
||||
};
|
||||
|
||||
void to_json(json& j, const NamePayload& p);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// 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
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace PipeServer {
|
||||
void StartServer();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#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'.
|
||||
@@ -0,0 +1,36 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "pch.h"
|
||||
#include "AliveModule.h"
|
||||
|
||||
namespace http {
|
||||
namespace modules {
|
||||
void HandleAlive(const httplib::Request&, httplib::Response& res) {
|
||||
res.set_content("Yes!", "text/plain");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,620 @@
|
||||
#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);
|
||||
if (!gwPlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Temp::GWPlayer* mainGwPlayer;
|
||||
if (foundMainGwPlayer == players.end()) {
|
||||
mainGwPlayer = nullptr;
|
||||
}
|
||||
else{
|
||||
mainGwPlayer = &*foundMainGwPlayer;
|
||||
}
|
||||
|
||||
PopulateMainPlayer(mainPlayer, (uint32_t)activeQuestId, questLog, titles, titleTiers, playerAgentId, mainGwPlayer, mainProfPtr, skillbars[playerAgentId], mainAttrPtr, mainAgentPtr);
|
||||
gamePayload.MainPlayer = mainPlayer;
|
||||
|
||||
std::list<WorldPlayer> worldPlayers;
|
||||
for (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;
|
||||
}
|
||||
|
||||
auto* tempGwPlayer = &gwPlayer;
|
||||
PopulateWorldPlayer(titles, titleTiers, worldPlayer, gwPlayer.agent_id, tempGwPlayer, 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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
#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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
#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);
|
||||
if (!gwPlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Temp::GWPlayer* mainGwPlayer;
|
||||
if (foundMainGwPlayer == players.end()) {
|
||||
mainGwPlayer = nullptr;
|
||||
}
|
||||
else {
|
||||
mainGwPlayer = &*foundMainGwPlayer;
|
||||
}
|
||||
|
||||
PopulateMainPlayer(mainPlayer, (uint32_t)activeQuestId, questLog, titles, titleTiers, playerAgentId, mainGwPlayer, 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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
#include "pch.h"
|
||||
#include "NameModule.h"
|
||||
#include "payloads/NamePayload.h"
|
||||
#include <GWCA/Managers/GameThreadMgr.h>
|
||||
#include <GWCA/Managers/MapMgr.h>
|
||||
#include <GWCA/GameEntities/Agent.h>
|
||||
#include <future>
|
||||
#include <json.hpp>
|
||||
#include <tuple>
|
||||
#include <queue>
|
||||
#include <GWCA/GWCA.h>
|
||||
#include <GWCA/Context/PreGameContext.h>
|
||||
#include <GWCA/Managers/AgentMgr.h>
|
||||
#include <Windows.h>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace Daybreak::Modules::NameModule {
|
||||
std::vector<std::tuple<uint32_t, std::promise<NamePayload>*, std::wstring*>> WaitingList;
|
||||
std::queue<std::tuple<uint32_t, std::promise<NamePayload>>*> PromiseQueue;
|
||||
std::mutex GameThreadMutex;
|
||||
GW::HookEntry GameThreadHook;
|
||||
volatile bool initialized = false;
|
||||
|
||||
std::string WStringToString(const std::wstring& wstr)
|
||||
{
|
||||
if (wstr.empty()) return std::string();
|
||||
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
|
||||
std::string strTo(size_needed, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
|
||||
|
||||
return strTo;
|
||||
}
|
||||
|
||||
std::wstring* GetAsyncName(uint32_t id) {
|
||||
NamePayload namePayload;
|
||||
auto agent = GW::Agents::GetAgentByID(id);
|
||||
if (!agent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto agentLiving = agent->GetAsAgentLiving();
|
||||
if (!agentLiving) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto name = new std::wstring();
|
||||
if (!GW::Agents::AsyncGetAgentName(agentLiving, *name)) {
|
||||
delete(name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void EnsureInitialized() {
|
||||
GameThreadMutex.lock();
|
||||
if (!initialized) {
|
||||
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
|
||||
while (!PromiseQueue.empty()) {
|
||||
auto promiseRequest = PromiseQueue.front();
|
||||
std::promise<NamePayload> &promise = std::get<1>(*promiseRequest);
|
||||
uint32_t id = std::get<0>(*promiseRequest);
|
||||
PromiseQueue.pop();
|
||||
try {
|
||||
auto name = GetAsyncName(id);
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WaitingList.emplace_back(id, &promise, name);
|
||||
}
|
||||
catch (...) {
|
||||
NamePayload payload;
|
||||
promise.set_value(payload);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = 0; i < WaitingList.size(); ) {
|
||||
auto item = &WaitingList[i];
|
||||
auto name = std::get<2>(*item);
|
||||
if (name->empty()) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto promise = std::get<1>(*item);
|
||||
auto id = std::get<0>(*item);
|
||||
WaitingList.erase(WaitingList.begin() + i);
|
||||
NamePayload payload;
|
||||
payload.Id = id;
|
||||
payload.Name = WStringToString(*name);
|
||||
delete(name);
|
||||
promise->set_value(payload);
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
GameThreadMutex.unlock();
|
||||
}
|
||||
|
||||
void GetName(const httplib::Request& req, httplib::Response& res) {
|
||||
auto callbackEntry = new GW::HookEntry;
|
||||
uint32_t id = 0;
|
||||
auto it = req.params.find("id");
|
||||
if (it == req.params.end()) {
|
||||
res.status = 400;
|
||||
res.set_content("Missing id parameter", "text/plain");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
auto idStr = it->second;
|
||||
size_t pos = 0;
|
||||
auto result = std::stoul(idStr, &pos);
|
||||
if (pos != idStr.size()) {
|
||||
res.status = 400;
|
||||
res.set_content("Invalid id parameter", "text/plain");
|
||||
return;
|
||||
}
|
||||
|
||||
id = static_cast<uint32_t>(result);
|
||||
}
|
||||
|
||||
auto response = new std::tuple<uint32_t, std::promise<NamePayload>>();
|
||||
std::get<0>(*response) = id;
|
||||
std::promise<NamePayload>& promise = std::get<1>(*response);
|
||||
|
||||
EnsureInitialized();
|
||||
PromiseQueue.emplace(response);
|
||||
|
||||
json responsePayload = promise.get_future().get();
|
||||
delete callbackEntry;
|
||||
delete response;
|
||||
res.set_content(responsePayload.dump(), "text/json");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#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(payload);
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// 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"
|
||||
#include "NameModule.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::Get("/name", Daybreak::Modules::NameModule::GetName);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#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}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <cstdint>
|
||||
#include <json.hpp>
|
||||
#include <payloads/NamePayload.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace Daybreak {
|
||||
void to_json(json& j, const NamePayload& p) {
|
||||
j = json
|
||||
{
|
||||
{"Id", p.Id},
|
||||
{"Name", p.Name}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#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}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#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},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// 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.
|
||||
@@ -0,0 +1,106 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x86;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,72 @@
|
||||
// See https://aka.ms/new-console-template for more information
|
||||
using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
|
||||
const string tempFile = "tempfile.zip";
|
||||
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
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Console.WriteLine("Deleting browser caches");
|
||||
try
|
||||
{
|
||||
Directory.Delete("BrowserData", true);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
Directory.Delete("Daybreak.exe.WebView2", true);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
}
|
||||
|
||||
Console.WriteLine("Deleting package");
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Failed to delete {tempFile}.\n{e}");
|
||||
}
|
||||
|
||||
Console.WriteLine("Launching application");
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executableName
|
||||
}
|
||||
};
|
||||
|
||||
if (process.Start() is false)
|
||||
{
|
||||
Console.WriteLine("Failed to launch application");
|
||||
Console.ReadKey();
|
||||
}
|
||||
@@ -1,18 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0-windows</TargetFramework>
|
||||
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Platforms>AnyCPU;x86;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.0.0-alpha0002" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
<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">
|
||||
<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">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user