Compare commits
354 commits
migrate2ef
...
master
Author | SHA1 | Date | |
---|---|---|---|
650baf43c1 | |||
04fe2b18c1 | |||
e47385f27c | |||
0b88b6c9fe | |||
c7a2e935ec | |||
c76931afed | |||
c1854b65ae | |||
f0a688e00b | |||
727df46579 | |||
057f980c57 | |||
a5f84b84a0 | |||
6025553be8 | |||
4547036258 | |||
4d9dd9bcdf | |||
187f627cc9 | |||
1c61093e32 | |||
0d198de2fd | |||
702b682fad | |||
074c1d991b | |||
cb550af720 | |||
126ec704e5 | |||
2df122740b | |||
6dc479d5a9 | |||
73d8e140fb | |||
78ba35c66f | |||
4002e37aa5 | |||
71aed8ff2d | |||
1422df014c | |||
67ab4fd049 | |||
e127579300 | |||
f718823729 | |||
f95c9f5e39 | |||
f96405c347 | |||
328821be89 | |||
f12d070409 | |||
a307f18866 | |||
4ce9e0479e | |||
2295c9fff2 | |||
8e35773d45 | |||
e5526547eb | |||
25240b4b19 | |||
82e65f9590 | |||
93db8c6c08 | |||
77f81e3ca7 | |||
9eb092987d | |||
053b6139a1 | |||
9f2db032c3 | |||
2516279abf | |||
faf3dee5e4 | |||
bb1e433c88 | |||
17e44ea1e4 | |||
03f53faac9 | |||
d5d517e2a4 | |||
461b4a9ea5 | |||
57c4024578 | |||
6a9cacebb5 | |||
3e64d538cf | |||
6d9a72ded4 | |||
2d90059418 | |||
5ebc4ec09d | |||
1363ddf8fe | |||
769d0bf21c | |||
5b8880f392 | |||
43a5c994df | |||
8937480606 | |||
41b9da9735 | |||
18e2e80332 | |||
b28fb5b2a3 | |||
fb5097ac71 | |||
db155a87c0 | |||
ecaa3c6c10 | |||
1cdff7f0be | |||
81646f4501 | |||
dc9f96fb19 | |||
ec155ecab1 | |||
c4905b8cba | |||
e72f939319 | |||
3efe3a5aac | |||
effe9a5a1d | |||
0d14701031 | |||
3f311956c6 | |||
526660dc35 | |||
ecd86d890c | |||
aa09d0b755 | |||
0704d9f07d | |||
b2547d25a3 | |||
a547d6ebbf | |||
b3de52c6d8 | |||
9bd75cd6c4 | |||
bd25ff9f09 | |||
4bb4236eb3 | |||
ac976321f5 | |||
d15b1f8045 | |||
b3a8aee1f7 | |||
af3f772796 | |||
19fffa9efe | |||
e1b0189c41 | |||
bccbaa87d9 | |||
f09ab06066 | |||
40b2896fa3 | |||
ec797a5885 | |||
927ec4e5a1 | |||
9a6a47e8f4 | |||
6a9e1c338e | |||
157dbbc2f5 | |||
55e7e8fc4c | |||
f1bf15ded1 | |||
fb63fc8d3a | |||
aac1bbfc5f | |||
5949a7dfe5 | |||
45b13be4a7 | |||
4823c352dc | |||
8f6886a6cf | |||
c20426ee03 | |||
5dd622dc4b | |||
733db535ac | |||
85dd69d243 | |||
299a9e8b98 | |||
a351d95bdc | |||
9f3007b10e | |||
db63e581e5 | |||
8d2f969214 | |||
c630135b91 | |||
47023a3c3f | |||
6bcf90bc87 | |||
8b294dd1ca | |||
b3941d2672 | |||
6589a9f890 | |||
600f4a2f50 | |||
63309db7d9 | |||
955fe83c03 | |||
d2425d80e7 | |||
bd483ae213 | |||
efdbad09d0 | |||
17a2a49cfd | |||
42c53584f7 | |||
0077d380f3 | |||
4b7f0b6f00 | |||
1f4f3cff51 | |||
55276354db | |||
58f4448438 | |||
a247f82a8f | |||
71cf2a8dd3 | |||
16673ef3c0 | |||
87955f3ba3 | |||
3db8a918e3 | |||
04f8c5d52c | |||
bdc3b149fe | |||
6e406b4b00 | |||
ea89688d8b | |||
9900d3611b | |||
9ec8039c99 | |||
c2ba247dbe | |||
7fde237434 | |||
873ab306a5 | |||
dd4ed0a67b | |||
854ac06de6 | |||
797ea61f36 | |||
316881266b | |||
5abe7f7564 | |||
b68e058429 | |||
a11675df45 | |||
1f9acf009d | |||
6a1abfeaf9 | |||
c6552c7c5a | |||
580871ccb2 | |||
6768fbf2a9 | |||
7a98cdb89a | |||
f65961fe94 | |||
9f6d64f73d | |||
b40cfe00c1 | |||
bc5351dbf7 | |||
94cf988d93 | |||
08c8539e35 | |||
8ee8bce13a | |||
3cb1e23e23 | |||
e16bb57c88 | |||
6ebc360d1b | |||
40c9224158 | |||
a2252efd3a | |||
973bbe9803 | |||
803a19765f | |||
e1e6268e90 | |||
cdac9fdf37 | |||
dbc3ff3c62 | |||
70d173199c | |||
fe99ae1b8d | |||
0bf8fa241e | |||
b4a0681c57 | |||
2983c84bd8 | |||
01702e94f7 | |||
2d391834c4 | |||
3602d74eb4 | |||
76991338f3 | |||
46649adfd8 | |||
4781a5c12a | |||
2a098a3366 | |||
bfecf799ef | |||
7e697fca80 | |||
9d04ecd28a | |||
1cb8911f7c | |||
f740ebc49f | |||
816dd44006 | |||
a3589a7f8e | |||
ec03639c1c | |||
b2f0f836c2 | |||
db66835ca6 | |||
9b5986eac7 | |||
1d5a0e19ad | |||
1c5bef00d6 | |||
90b9ed80c1 | |||
a35dca94e8 | |||
f8df667a18 | |||
9fa848df79 | |||
826a9b71e0 | |||
83453839b0 | |||
40ccbe50e5 | |||
9ab71891cf | |||
c85f9f32cb | |||
5b7360c9a4 | |||
945877dfd9 | |||
f4d8e9787b | |||
40cc767b33 | |||
5b813d19c2 | |||
c0bfb158e0 | |||
75900a198c | |||
dc885c614d | |||
be8299d2db | |||
569b66ccd7 | |||
35fc057181 | |||
cb121b692a | |||
12bb44c7dc | |||
f09f122747 | |||
ba52f57b8a | |||
eb9045d34b | |||
1ac6d76d48 | |||
9bdafbf24d | |||
7888c16487 | |||
f0f11c5db3 | |||
1c7f14e3e7 | |||
1d271081a6 | |||
df8b3b7108 | |||
3bcfe010cf | |||
589c527694 | |||
df9090c163 | |||
ff43691cdc | |||
04ef0d0b52 | |||
0b596d9574 | |||
8ee1c06c00 | |||
c197afc750 | |||
1e92c53bad | |||
a214f6fb0b | |||
1015160dc8 | |||
8706e7677a | |||
73c137d561 | |||
b584ca55bf | |||
c239c11391 | |||
c2c94665ea | |||
0817873eb1 | |||
4c1b948df1 | |||
8d00ed2a42 | |||
109b628a4a | |||
a984fcd001 | |||
6de1c0b97f | |||
97a171e4ed | |||
818f12e771 | |||
d42ed882be | |||
5b143c1ef3 | |||
90846c04b8 | |||
6d646db902 | |||
d5a311fce7 | |||
4b0840b5b9 | |||
08437c7b3f | |||
5381d78cfc | |||
8bbd36eb89 | |||
64ba76e41a | |||
a9f382963b | |||
98aa813f65 | |||
b2373d1556 | |||
7fec462a1d | |||
293b65a856 | |||
9a827214fa | |||
72cacab0ed | |||
1a13c3fb1b | |||
9356a729b0 | |||
24a118d52a | |||
dc7daaef5c | |||
497d415fb6 | |||
e4d6f15345 | |||
1a6e1e4ccc | |||
f5cd6c380e | |||
cb087f53e9 | |||
d90dcf696d | |||
b7a33d0a3f | |||
1135605d27 | |||
f6c2f4d2b6 | |||
85aaec2371 | |||
20931b5751 | |||
555ec5c392 | |||
c0219cc0f7 | |||
2550f597a9 | |||
59ba0ece7f | |||
fa52bf66f8 | |||
1455bdd75a | |||
a6b804dfe7 | |||
659e75d2df | |||
2198d3992a | |||
2a1dec45d8 | |||
68c1cae587 | |||
c87847833d | |||
5c9439e78d | |||
829442a1f1 | |||
b4e88e398e | |||
bf0890722a | |||
ab559a84a1 | |||
b486f7023a | |||
baddf19cbc | |||
c16f077881 | |||
01246ce3d3 | |||
d4c3f52d0b | |||
2b16747e4f | |||
3944bea5cc | |||
732e6de4ca | |||
42f84c734c | |||
2045176f29 | |||
60ad9f0a48 | |||
afd076e85a | |||
7623cd60ea | |||
a402ea3e35 | |||
d95c899368 | |||
16d948efb2 | |||
e562e22170 | |||
0379a3138d | |||
3f6427a09f | |||
fae7104211 | |||
f8a6e686f8 | |||
e36445f2c0 | |||
fb1a45108b | |||
40b35542e4 | |||
e50925a949 | |||
35d6d18945 | |||
e58fa35941 | |||
4499045afe | |||
21c9d925f3 | |||
82e5cce676 | |||
8816fb2944 | |||
756031b186 | |||
d44d072823 | |||
f802dcf2a3 | |||
010f05c565 | |||
63c29f21df | |||
fd47ba2db0 | |||
710bdf8af3 | |||
c520833e29 |
156 changed files with 11860 additions and 1484 deletions
845
.editorconfig
845
.editorconfig
|
@ -1,450 +1,469 @@
|
|||
# Version: 4.1.1 (Using https://semver.org/)
|
||||
# Updated: 2022-05-23
|
||||
# See https://github.com/RehanSaeed/EditorConfig/releases for release notes.
|
||||
# See https://github.com/RehanSaeed/EditorConfig for updates to this file.
|
||||
# See http://EditorConfig.org for more information about .editorconfig files.
|
||||
; EditorConfig to support per-solution formatting.
|
||||
; Use the EditorConfig VS add-in to make this work.
|
||||
; http://editorconfig.org/
|
||||
;
|
||||
; Here are some resources for what's supported for .NET/C#
|
||||
; https://kent-boogaart.com/blog/editorconfig-reference-for-c-developers
|
||||
; https://learn.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
|
||||
;
|
||||
; Be **careful** editing this because some of the rules don't support adding a severity level
|
||||
; For instance if you change to `dotnet_sort_system_directives_first = true:warning` (adding `:warning`)
|
||||
; then the rule will be silently ignored.
|
||||
|
||||
##########################################
|
||||
# Common Settings
|
||||
##########################################
|
||||
|
||||
# This file is the top-most EditorConfig file
|
||||
; This is the default for the codeline.
|
||||
root = true
|
||||
|
||||
# All Files
|
||||
; For disabling MA0048 and MA0051 in a specific folder, e.g., Migrations
|
||||
[**/Migrations/*.cs]
|
||||
dotnet_diagnostic.MA0048.severity = none
|
||||
dotnet_diagnostic.MA0051.severity = none
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
##########################################
|
||||
# File Extension Settings
|
||||
##########################################
|
||||
|
||||
# Visual Studio Solution Files
|
||||
[*.sln]
|
||||
indent_style = tab
|
||||
|
||||
# Visual Studio XML Project Files
|
||||
[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}]
|
||||
indent_size = 2
|
||||
|
||||
# XML Configuration Files
|
||||
[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}]
|
||||
indent_size = 2
|
||||
|
||||
# JSON Files
|
||||
[*.{json,json5,webmanifest}]
|
||||
indent_size = 2
|
||||
|
||||
# YAML Files
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
# Markdown Files
|
||||
[*.{md,mdx}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# Web Files
|
||||
[*.{htm,html,js,jsm,ts,tsx,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}]
|
||||
indent_size = 2
|
||||
|
||||
# Batch Files
|
||||
[*.{cmd,bat}]
|
||||
end_of_line = crlf
|
||||
|
||||
# Bash Files
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
|
||||
# Makefiles
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
##########################################
|
||||
# Default .NET Code Style Severities
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#scope
|
||||
##########################################
|
||||
|
||||
[*.{cs,csx,cake,vb,vbx}]
|
||||
# Default Severity for all .NET Code Style rules below
|
||||
dotnet_analyzer_diagnostic.severity = warning
|
||||
|
||||
##########################################
|
||||
# Language Rules
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules
|
||||
##########################################
|
||||
|
||||
# .NET Style Rules
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#net-style-rules
|
||||
[*.{cs,csx,cake,vb,vbx}]
|
||||
# "this." and "Me." qualifiers
|
||||
dotnet_style_qualification_for_field = true:warning
|
||||
dotnet_style_qualification_for_property = true:warning
|
||||
dotnet_style_qualification_for_method = true:warning
|
||||
dotnet_style_qualification_for_event = true:warning
|
||||
# Language keywords instead of framework type names for type references
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
|
||||
dotnet_style_predefined_type_for_member_access = true:warning
|
||||
# Modifier preferences
|
||||
dotnet_style_require_accessibility_modifiers = always:warning
|
||||
csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async:warning
|
||||
visual_basic_preferred_modifier_order = Partial, Default, Private, Protected, Public, Friend, NotOverridable, Overridable, MustOverride, Overloads, Overrides, MustInherit, NotInheritable, Static, Shared, Shadows, ReadOnly, WriteOnly, Dim, Const, WithEvents, Widening, Narrowing, Custom, Async:warning
|
||||
dotnet_style_readonly_field = true:warning
|
||||
# Parentheses preferences
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning
|
||||
# Expression-level preferences
|
||||
dotnet_style_object_initializer = true:warning
|
||||
dotnet_style_collection_initializer = true:warning
|
||||
dotnet_style_explicit_tuple_names = true:warning
|
||||
dotnet_style_prefer_inferred_tuple_names = true:warning
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
|
||||
dotnet_style_prefer_auto_properties = true:warning
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion
|
||||
dotnet_diagnostic.IDE0045.severity = suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_return = false:suggestion
|
||||
dotnet_diagnostic.IDE0046.severity = suggestion
|
||||
dotnet_style_prefer_compound_assignment = true:warning
|
||||
dotnet_style_prefer_simplified_interpolation = true:warning
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true:warning
|
||||
# Null-checking preferences
|
||||
dotnet_style_coalesce_expression = true:warning
|
||||
dotnet_style_null_propagation = true:warning
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
|
||||
# File header preferences
|
||||
# file_header_template = <copyright file="{fileName}" company="PROJECT-AUTHOR">\n© PROJECT-AUTHOR\n</copyright>
|
||||
# If you use StyleCop, you'll need to disable SA1636: File header copyright text should match.
|
||||
# dotnet_diagnostic.SA1636.severity = none
|
||||
# Undocumented
|
||||
dotnet_style_operator_placement_when_wrapping = end_of_line:warning
|
||||
csharp_style_prefer_null_check_over_type_check = true:warning
|
||||
|
||||
# C# Style Rules
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules
|
||||
[*.{cs,csx,cake}]
|
||||
# 'var' preferences
|
||||
csharp_style_var_for_built_in_types = true:warning
|
||||
csharp_style_var_when_type_is_apparent = true:warning
|
||||
csharp_style_var_elsewhere = true:warning
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_methods = true:warning
|
||||
csharp_style_expression_bodied_constructors = true:warning
|
||||
csharp_style_expression_bodied_operators = true:warning
|
||||
csharp_style_expression_bodied_properties = true:warning
|
||||
csharp_style_expression_bodied_indexers = true:warning
|
||||
csharp_style_expression_bodied_accessors = true:warning
|
||||
csharp_style_expression_bodied_lambdas = true:warning
|
||||
csharp_style_expression_bodied_local_functions = true:warning
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:warning
|
||||
csharp_style_prefer_switch_expression = true:warning
|
||||
csharp_style_prefer_pattern_matching = true:warning
|
||||
csharp_style_prefer_not_pattern = true:warning
|
||||
# Expression-level preferences
|
||||
csharp_style_inlined_variable_declaration = true:warning
|
||||
csharp_prefer_simple_default_expression = true:warning
|
||||
csharp_style_pattern_local_over_anonymous_function = true:warning
|
||||
csharp_style_deconstructed_variable_declaration = true:warning
|
||||
csharp_style_prefer_index_operator = true:warning
|
||||
csharp_style_prefer_range_operator = true:warning
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
|
||||
# "Null" checking preferences
|
||||
csharp_style_throw_expression = true:warning
|
||||
csharp_style_conditional_delegate_call = true:warning
|
||||
# Code block preferences
|
||||
csharp_prefer_braces = true:warning
|
||||
csharp_prefer_simple_using_statement = true:suggestion
|
||||
dotnet_diagnostic.IDE0063.severity = suggestion
|
||||
# 'using' directive preferences
|
||||
csharp_using_directive_placement = inside_namespace:warning
|
||||
# Modifier preferences
|
||||
csharp_prefer_static_local_function = true:warning
|
||||
|
||||
##########################################
|
||||
# Unnecessary Code Rules
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/unnecessary-code-rules
|
||||
##########################################
|
||||
|
||||
# .NET Unnecessary code rules
|
||||
[*.{cs,csx,cake,vb,vbx}]
|
||||
dotnet_code_quality_unused_parameters = all:warning
|
||||
dotnet_remove_unnecessary_suppression_exclusions = none:warning
|
||||
|
||||
# C# Unnecessary code rules
|
||||
[*.{cs,csx,cake}]
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
|
||||
dotnet_diagnostic.IDE0058.severity = suggestion
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
||||
dotnet_diagnostic.IDE0059.severity = suggestion
|
||||
|
||||
##########################################
|
||||
# Formatting Rules
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules
|
||||
##########################################
|
||||
|
||||
# .NET formatting rules
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#net-formatting-rules
|
||||
[*.{cs,csx,cake,vb,vbx}]
|
||||
# Organize using directives
|
||||
[*.cs]
|
||||
dotnet_diagnostic.MA0004.severity = none
|
||||
file_header_template = Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
indent_size = 4
|
||||
dotnet_sort_system_directives_first = true
|
||||
dotnet_separate_import_directive_groups = false
|
||||
# Dotnet namespace options
|
||||
dotnet_style_namespace_match_folder = true:suggestion
|
||||
dotnet_diagnostic.IDE0130.severity = suggestion
|
||||
dotnet_diagnostic.MA0007.severity = none
|
||||
#MA0004.report = DetectContext # (default) Try to detect the current context and report only if it considers ConfigureAwait is needed
|
||||
# Don't use this. qualifier
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
|
||||
# C# formatting rules
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#c-formatting-rules
|
||||
[*.{cs,csx,cake}]
|
||||
# Newline options
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#new-line-options
|
||||
# use int x = .. over Int32
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||
|
||||
# use int.MaxValue over Int32.MaxValue
|
||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||
|
||||
# Require var all the time.
|
||||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
|
||||
# Disallow throw expressions.
|
||||
csharp_style_throw_expression = false:suggestion
|
||||
|
||||
# Newline settings
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
# Indentation options
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#indentation-options
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_switch_labels = true
|
||||
csharp_indent_labels = no_change
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents_when_block = false
|
||||
# Spacing options
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#spacing-options
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_square_brackets = false
|
||||
# Wrap options
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#wrap-options
|
||||
csharp_preserve_single_line_statements = false
|
||||
csharp_preserve_single_line_blocks = true
|
||||
# Namespace options
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#namespace-options
|
||||
csharp_style_namespace_declarations = file_scoped:warning
|
||||
|
||||
##########################################
|
||||
# .NET Naming Rules
|
||||
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/naming-rules
|
||||
##########################################
|
||||
# Namespace settings
|
||||
csharp_style_namespace_declarations = file_scoped
|
||||
|
||||
[*.{cs,csx,cake,vb,vbx}]
|
||||
# Brace settings
|
||||
csharp_prefer_braces = true # Prefer curly braces even for one line of code
|
||||
|
||||
##########################################
|
||||
# Styles
|
||||
##########################################
|
||||
|
||||
# camel_case_style - Define the camelCase style
|
||||
dotnet_naming_style.camel_case_style.capitalization = camel_case
|
||||
# pascal_case_style - Define the PascalCase style
|
||||
# name all constant fields using PascalCase
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||
# first_upper_style - The first character must start with an upper-case character
|
||||
dotnet_naming_style.first_upper_style.capitalization = first_word_upper
|
||||
# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
|
||||
dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case
|
||||
dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I
|
||||
# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T'
|
||||
dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case
|
||||
dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T
|
||||
# disallowed_style - Anything that has this style applied is marked as disallowed
|
||||
dotnet_naming_style.disallowed_style.capitalization = pascal_case
|
||||
dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____
|
||||
dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____
|
||||
# internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file
|
||||
dotnet_naming_style.internal_error_style.capitalization = pascal_case
|
||||
dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____
|
||||
dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____
|
||||
|
||||
##########################################
|
||||
# .NET Design Guideline Field Naming Rules
|
||||
# Naming rules for fields follow the .NET Framework design guidelines
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/index
|
||||
##########################################
|
||||
# internal and private fields should be _camelCase
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
|
||||
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
|
||||
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
|
||||
# All public/protected/protected_internal constant fields must be PascalCase
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
|
||||
dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal
|
||||
dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const
|
||||
dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group
|
||||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
|
||||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning
|
||||
[*.{xml,config,*proj,nuspec,props,resx,targets,yml,tasks}]
|
||||
indent_size = 2
|
||||
|
||||
# All public/protected/protected_internal static readonly fields must be PascalCase
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
|
||||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal
|
||||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly
|
||||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group
|
||||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
|
||||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning
|
||||
# Xml config files
|
||||
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
|
||||
indent_size = 2
|
||||
|
||||
# No other public/protected/protected_internal fields are allowed
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
|
||||
dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal
|
||||
dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
|
||||
##########################################
|
||||
# StyleCop Field Naming Rules
|
||||
# Naming rules for fields follow the StyleCop analyzers
|
||||
# This does not override any rules using disallowed_style above
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
|
||||
##########################################
|
||||
[*.{ps1,psm1}]
|
||||
indent_size = 4
|
||||
|
||||
# All constant fields must be PascalCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
|
||||
[*.sh]
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
|
||||
# All static readonly fields must be PascalCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
|
||||
[*.{razor,cshtml}]
|
||||
charset = utf-8-bom
|
||||
|
||||
# No non-private instance fields are allowed
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
|
||||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
|
||||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error
|
||||
[*.{cs,vb}]
|
||||
|
||||
# Private fields must be camelCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md
|
||||
dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private
|
||||
dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = camel_case_style
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning
|
||||
# SYSLIB1054: Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time
|
||||
dotnet_diagnostic.SYSLIB1054.severity = warning
|
||||
|
||||
# Local variables must be camelCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
|
||||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = silent
|
||||
# CA1018: Mark attributes with AttributeUsageAttribute
|
||||
dotnet_diagnostic.CA1018.severity = warning
|
||||
|
||||
# This rule should never fire. However, it's included for at least two purposes:
|
||||
# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers.
|
||||
# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#).
|
||||
dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field
|
||||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group
|
||||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
|
||||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
|
||||
# CA1047: Do not declare protected member in sealed type
|
||||
dotnet_diagnostic.CA1047.severity = warning
|
||||
|
||||
# CA1305: Specify IFormatProvider
|
||||
dotnet_diagnostic.CA1305.severity = warning
|
||||
|
||||
##########################################
|
||||
# Other Naming Rules
|
||||
##########################################
|
||||
# CA1507: Use nameof to express symbol names
|
||||
dotnet_diagnostic.CA1507.severity = warning
|
||||
|
||||
# All of the following must be PascalCase:
|
||||
# - Namespaces
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
|
||||
# - Classes and Enumerations
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
|
||||
# - Delegates
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types
|
||||
# - Constructors, Properties, Events, Methods
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members
|
||||
dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property
|
||||
dotnet_naming_rule.element_rule.symbols = element_group
|
||||
dotnet_naming_rule.element_rule.style = pascal_case_style
|
||||
dotnet_naming_rule.element_rule.severity = warning
|
||||
# CA1510: Use ArgumentNullException throw helper
|
||||
dotnet_diagnostic.CA1510.severity = warning
|
||||
|
||||
# Interfaces use PascalCase and are prefixed with uppercase 'I'
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
|
||||
dotnet_naming_symbols.interface_group.applicable_kinds = interface
|
||||
dotnet_naming_rule.interface_rule.symbols = interface_group
|
||||
dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style
|
||||
dotnet_naming_rule.interface_rule.severity = warning
|
||||
# CA1511: Use ArgumentException throw helper
|
||||
dotnet_diagnostic.CA1511.severity = warning
|
||||
|
||||
# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T'
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
|
||||
dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter
|
||||
dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group
|
||||
dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style
|
||||
dotnet_naming_rule.type_parameter_rule.severity = warning
|
||||
# CA1512: Use ArgumentOutOfRangeException throw helper
|
||||
dotnet_diagnostic.CA1512.severity = warning
|
||||
|
||||
# Function parameters use camelCase
|
||||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters
|
||||
dotnet_naming_symbols.parameters_group.applicable_kinds = parameter
|
||||
dotnet_naming_rule.parameters_rule.symbols = parameters_group
|
||||
dotnet_naming_rule.parameters_rule.style = camel_case_style
|
||||
dotnet_naming_rule.parameters_rule.severity = warning
|
||||
# CA1513: Use ObjectDisposedException throw helper
|
||||
dotnet_diagnostic.CA1513.severity = warning
|
||||
|
||||
##########################################
|
||||
# License
|
||||
##########################################
|
||||
# The following applies as to the .editorconfig file ONLY, and is
|
||||
# included below for reference, per the requirements of the license
|
||||
# corresponding to this .editorconfig file.
|
||||
# See: https://github.com/RehanSaeed/EditorConfig
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2017-2019 Muhammad Rehan Saeed
|
||||
# Copyright (c) 2019 Henry Gabryjelski
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any
|
||||
# person obtaining a copy of this software and associated
|
||||
# documentation files (the "Software"), to deal in the
|
||||
# Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute,
|
||||
# sublicense, and/or sell copies of the Software, and to permit
|
||||
# persons to whom the Software is furnished to do so, subject
|
||||
# to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
##########################################
|
||||
# CA1725: Parameter names should match base declaration
|
||||
dotnet_diagnostic.CA1725.severity = suggestion
|
||||
|
||||
# CA1802: Use literals where appropriate
|
||||
dotnet_diagnostic.CA1802.severity = warning
|
||||
|
||||
# CA1805: Do not initialize unnecessarily
|
||||
dotnet_diagnostic.CA1805.severity = warning
|
||||
|
||||
# CA1810: Do not initialize unnecessarily
|
||||
dotnet_diagnostic.CA1810.severity = warning
|
||||
|
||||
# CA1821: Remove empty Finalizers
|
||||
dotnet_diagnostic.CA1821.severity = warning
|
||||
|
||||
# CA1822: Make member static
|
||||
dotnet_diagnostic.CA1822.severity = warning
|
||||
dotnet_code_quality.CA1822.api_surface = private, internal
|
||||
|
||||
# CA1823: Avoid unused private fields
|
||||
dotnet_diagnostic.CA1823.severity = warning
|
||||
|
||||
# CA1825: Avoid zero-length array allocations
|
||||
dotnet_diagnostic.CA1825.severity = warning
|
||||
|
||||
# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly
|
||||
dotnet_diagnostic.CA1826.severity = warning
|
||||
|
||||
# CA1827: Do not use Count() or LongCount() when Any() can be used
|
||||
dotnet_diagnostic.CA1827.severity = warning
|
||||
|
||||
# CA1828: Do not use CountAsync() or LongCountAsync() when AnyAsync() can be used
|
||||
dotnet_diagnostic.CA1828.severity = warning
|
||||
|
||||
# CA1829: Use Length/Count property instead of Count() when available
|
||||
dotnet_diagnostic.CA1829.severity = warning
|
||||
|
||||
# CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder
|
||||
dotnet_diagnostic.CA1830.severity = warning
|
||||
|
||||
# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
|
||||
dotnet_diagnostic.CA1831.severity = warning
|
||||
|
||||
# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
|
||||
dotnet_diagnostic.CA1832.severity = warning
|
||||
|
||||
# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
|
||||
dotnet_diagnostic.CA1833.severity = warning
|
||||
|
||||
# CA1834: Consider using 'StringBuilder.Append(char)' when applicable
|
||||
dotnet_diagnostic.CA1834.severity = warning
|
||||
|
||||
# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
|
||||
dotnet_diagnostic.CA1835.severity = warning
|
||||
|
||||
# CA1836: Prefer IsEmpty over Count
|
||||
dotnet_diagnostic.CA1836.severity = warning
|
||||
|
||||
# CA1837: Use 'Environment.ProcessId'
|
||||
dotnet_diagnostic.CA1837.severity = warning
|
||||
|
||||
# CA1838: Avoid 'StringBuilder' parameters for P/Invokes
|
||||
dotnet_diagnostic.CA1838.severity = warning
|
||||
|
||||
# CA1839: Use 'Environment.ProcessPath'
|
||||
dotnet_diagnostic.CA1839.severity = warning
|
||||
|
||||
# CA1840: Use 'Environment.CurrentManagedThreadId'
|
||||
dotnet_diagnostic.CA1840.severity = warning
|
||||
|
||||
# CA1841: Prefer Dictionary.Contains methods
|
||||
dotnet_diagnostic.CA1841.severity = warning
|
||||
|
||||
# CA1842: Do not use 'WhenAll' with a single task
|
||||
dotnet_diagnostic.CA1842.severity = warning
|
||||
|
||||
# CA1843: Do not use 'WaitAll' with a single task
|
||||
dotnet_diagnostic.CA1843.severity = warning
|
||||
|
||||
# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream'
|
||||
dotnet_diagnostic.CA1844.severity = warning
|
||||
|
||||
# CA1845: Use span-based 'string.Concat'
|
||||
dotnet_diagnostic.CA1845.severity = warning
|
||||
|
||||
# CA1846: Prefer AsSpan over Substring
|
||||
dotnet_diagnostic.CA1846.severity = warning
|
||||
|
||||
# CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
|
||||
dotnet_diagnostic.CA1847.severity = warning
|
||||
|
||||
# CA1852: Seal internal types
|
||||
dotnet_diagnostic.CA1852.severity = warning
|
||||
|
||||
# CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
|
||||
dotnet_diagnostic.CA1854.severity = warning
|
||||
|
||||
# CA1855: Prefer 'Clear' over 'Fill'
|
||||
dotnet_diagnostic.CA1855.severity = warning
|
||||
|
||||
# CA1856: Incorrect usage of ConstantExpected attribute
|
||||
dotnet_diagnostic.CA1856.severity = error
|
||||
|
||||
# CA1857: A constant is expected for the parameter
|
||||
dotnet_diagnostic.CA1857.severity = warning
|
||||
|
||||
# CA1858: Use 'StartsWith' instead of 'IndexOf'
|
||||
dotnet_diagnostic.CA1858.severity = warning
|
||||
|
||||
# CA2007: Consider calling ConfigureAwait on the awaited task
|
||||
dotnet_diagnostic.CA2007.severity = none
|
||||
|
||||
# CA2008: Do not create tasks without passing a TaskScheduler
|
||||
dotnet_diagnostic.CA2008.severity = warning
|
||||
|
||||
# CA2009: Do not call ToImmutableCollection on an ImmutableCollection value
|
||||
dotnet_diagnostic.CA2009.severity = warning
|
||||
|
||||
# CA2011: Avoid infinite recursion
|
||||
dotnet_diagnostic.CA2011.severity = warning
|
||||
|
||||
# CA2012: Use ValueTask correctly
|
||||
dotnet_diagnostic.CA2012.severity = warning
|
||||
|
||||
# CA2013: Do not use ReferenceEquals with value types
|
||||
dotnet_diagnostic.CA2013.severity = warning
|
||||
|
||||
# CA2014: Do not use stackalloc in loops.
|
||||
dotnet_diagnostic.CA2014.severity = warning
|
||||
|
||||
# CA2016: Forward the 'CancellationToken' parameter to methods that take one
|
||||
dotnet_diagnostic.CA2016.severity = warning
|
||||
|
||||
# CA2200: Rethrow to preserve stack details
|
||||
dotnet_diagnostic.CA2200.severity = warning
|
||||
|
||||
# CA2201: Do not raise reserved exception types
|
||||
dotnet_diagnostic.CA2201.severity = warning
|
||||
|
||||
# CA2208: Instantiate argument exceptions correctly
|
||||
dotnet_diagnostic.CA2208.severity = warning
|
||||
|
||||
# CA2245: Do not assign a property to itself
|
||||
dotnet_diagnostic.CA2245.severity = warning
|
||||
|
||||
# CA2246: Assigning symbol and its member in the same statement
|
||||
dotnet_diagnostic.CA2246.severity = warning
|
||||
|
||||
# CA2249: Use string.Contains instead of string.IndexOf to improve readability.
|
||||
dotnet_diagnostic.CA2249.severity = warning
|
||||
|
||||
# IDE0005: Remove unnecessary usings
|
||||
dotnet_diagnostic.IDE0005.severity = warning
|
||||
|
||||
# IDE0011: Curly braces to surround blocks of code
|
||||
dotnet_diagnostic.IDE0011.severity = warning
|
||||
|
||||
# IDE0020: Use pattern matching to avoid is check followed by a cast (with variable)
|
||||
dotnet_diagnostic.IDE0020.severity = warning
|
||||
|
||||
# IDE0029: Use coalesce expression (non-nullable types)
|
||||
dotnet_diagnostic.IDE0029.severity = warning
|
||||
|
||||
# IDE0030: Use coalesce expression (nullable types)
|
||||
dotnet_diagnostic.IDE0030.severity = warning
|
||||
|
||||
# IDE0031: Use null propagation
|
||||
dotnet_diagnostic.IDE0031.severity = warning
|
||||
|
||||
# IDE0035: Remove unreachable code
|
||||
dotnet_diagnostic.IDE0035.severity = warning
|
||||
|
||||
# IDE0036: Order modifiers
|
||||
csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async:suggestion
|
||||
dotnet_diagnostic.IDE0036.severity = warning
|
||||
|
||||
# IDE0038: Use pattern matching to avoid is check followed by a cast (without variable)
|
||||
dotnet_diagnostic.IDE0038.severity = warning
|
||||
|
||||
# IDE0043: Format string contains invalid placeholder
|
||||
dotnet_diagnostic.IDE0043.severity = warning
|
||||
|
||||
# IDE0044: Make field readonly
|
||||
dotnet_diagnostic.IDE0044.severity = warning
|
||||
|
||||
# IDE0051: Remove unused private members
|
||||
dotnet_diagnostic.IDE0051.severity = warning
|
||||
|
||||
# IDE0055: All formatting rules
|
||||
dotnet_diagnostic.IDE0055.severity = suggestion
|
||||
|
||||
# IDE0059: Unnecessary assignment to a value
|
||||
dotnet_diagnostic.IDE0059.severity = warning
|
||||
|
||||
# IDE0060: Remove unused parameter
|
||||
dotnet_code_quality_unused_parameters = non_public
|
||||
dotnet_diagnostic.IDE0060.severity = warning
|
||||
|
||||
# IDE0062: Make local function static
|
||||
dotnet_diagnostic.IDE0062.severity = warning
|
||||
|
||||
# IDE0073: File header
|
||||
dotnet_diagnostic.IDE0073.severity = warning
|
||||
# Not a dotnet foundation project
|
||||
#file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
# IDE0161: Convert to file-scoped namespace
|
||||
dotnet_diagnostic.IDE0161.severity = warning
|
||||
|
||||
# IDE0200: Lambda expression can be removed
|
||||
dotnet_diagnostic.IDE0200.severity = warning
|
||||
|
||||
# IDE2000: Disallow multiple blank lines
|
||||
dotnet_style_allow_multiple_blank_lines_experimental = false
|
||||
dotnet_diagnostic.IDE2000.severity = warning
|
||||
|
||||
[{eng/tools/**.cs,**/{test,testassets,samples,Samples,perf,benchmarkapps,scripts,stress}/**.cs,src/Hosting/Server.IntegrationTesting/**.cs,src/Servers/IIS/IntegrationTesting.IIS/**.cs,src/Shared/Http2cat/**.cs,src/Testing/**.cs}]
|
||||
# CA1018: Mark attributes with AttributeUsageAttribute
|
||||
dotnet_diagnostic.CA1018.severity = suggestion
|
||||
# CA1507: Use nameof to express symbol names
|
||||
dotnet_diagnostic.CA1507.severity = suggestion
|
||||
# CA1510: Use ArgumentNullException throw helper
|
||||
dotnet_diagnostic.CA1510.severity = suggestion
|
||||
# CA1511: Use ArgumentException throw helper
|
||||
dotnet_diagnostic.CA1511.severity = suggestion
|
||||
# CA1512: Use ArgumentOutOfRangeException throw helper
|
||||
dotnet_diagnostic.CA1512.severity = suggestion
|
||||
# CA1513: Use ObjectDisposedException throw helper
|
||||
dotnet_diagnostic.CA1513.severity = suggestion
|
||||
# CA1802: Use literals where appropriate
|
||||
dotnet_diagnostic.CA1802.severity = suggestion
|
||||
# CA1805: Do not initialize unnecessarily
|
||||
dotnet_diagnostic.CA1805.severity = suggestion
|
||||
# CA1810: Do not initialize unnecessarily
|
||||
dotnet_diagnostic.CA1810.severity = suggestion
|
||||
# CA1822: Make member static
|
||||
dotnet_diagnostic.CA1822.severity = suggestion
|
||||
# CA1823: Avoid zero-length array allocations
|
||||
dotnet_diagnostic.CA1825.severity = suggestion
|
||||
# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly
|
||||
dotnet_diagnostic.CA1826.severity = suggestion
|
||||
# CA1827: Do not use Count() or LongCount() when Any() can be used
|
||||
dotnet_diagnostic.CA1827.severity = suggestion
|
||||
# CA1829: Use Length/Count property instead of Count() when available
|
||||
dotnet_diagnostic.CA1829.severity = suggestion
|
||||
# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
|
||||
dotnet_diagnostic.CA1831.severity = suggestion
|
||||
# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
|
||||
dotnet_diagnostic.CA1832.severity = suggestion
|
||||
# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
|
||||
dotnet_diagnostic.CA1833.severity = suggestion
|
||||
# CA1834: Consider using 'StringBuilder.Append(char)' when applicable
|
||||
dotnet_diagnostic.CA1834.severity = suggestion
|
||||
# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
|
||||
dotnet_diagnostic.CA1835.severity = suggestion
|
||||
# CA1837: Use 'Environment.ProcessId'
|
||||
dotnet_diagnostic.CA1837.severity = suggestion
|
||||
# CA1838: Avoid 'StringBuilder' parameters for P/Invokes
|
||||
dotnet_diagnostic.CA1838.severity = suggestion
|
||||
# CA1841: Prefer Dictionary.Contains methods
|
||||
dotnet_diagnostic.CA1841.severity = suggestion
|
||||
# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream'
|
||||
dotnet_diagnostic.CA1844.severity = suggestion
|
||||
# CA1845: Use span-based 'string.Concat'
|
||||
dotnet_diagnostic.CA1845.severity = suggestion
|
||||
# CA1846: Prefer AsSpan over Substring
|
||||
dotnet_diagnostic.CA1846.severity = suggestion
|
||||
# CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
|
||||
dotnet_diagnostic.CA1847.severity = suggestion
|
||||
# CA1852: Seal internal types
|
||||
dotnet_diagnostic.CA1852.severity = suggestion
|
||||
# CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
|
||||
dotnet_diagnostic.CA1854.severity = suggestion
|
||||
# CA1855: Prefer 'Clear' over 'Fill'
|
||||
dotnet_diagnostic.CA1855.severity = suggestion
|
||||
# CA1856: Incorrect usage of ConstantExpected attribute
|
||||
dotnet_diagnostic.CA1856.severity = suggestion
|
||||
# CA1857: A constant is expected for the parameter
|
||||
dotnet_diagnostic.CA1857.severity = suggestion
|
||||
# CA1858: Use 'StartsWith' instead of 'IndexOf'
|
||||
dotnet_diagnostic.CA1858.severity = suggestion
|
||||
# CA2007: Consider calling ConfigureAwait on the awaited task
|
||||
dotnet_diagnostic.CA2007.severity = suggestion
|
||||
# CA2008: Do not create tasks without passing a TaskScheduler
|
||||
dotnet_diagnostic.CA2008.severity = suggestion
|
||||
# CA2012: Use ValueTask correctly
|
||||
dotnet_diagnostic.CA2012.severity = suggestion
|
||||
# CA2201: Do not raise reserved exception types
|
||||
dotnet_diagnostic.CA2201.severity = suggestion
|
||||
# CA2249: Use string.Contains instead of string.IndexOf to improve readability.
|
||||
dotnet_diagnostic.CA2249.severity = suggestion
|
||||
# IDE0005: Remove unnecessary usings
|
||||
dotnet_diagnostic.IDE0005.severity = suggestion
|
||||
# IDE0020: Use pattern matching to avoid is check followed by a cast (with variable)
|
||||
dotnet_diagnostic.IDE0020.severity = suggestion
|
||||
# IDE0029: Use coalesce expression (non-nullable types)
|
||||
dotnet_diagnostic.IDE0029.severity = suggestion
|
||||
# IDE0030: Use coalesce expression (nullable types)
|
||||
dotnet_diagnostic.IDE0030.severity = suggestion
|
||||
# IDE0031: Use null propagation
|
||||
dotnet_diagnostic.IDE0031.severity = suggestion
|
||||
# IDE0038: Use pattern matching to avoid is check followed by a cast (without variable)
|
||||
dotnet_diagnostic.IDE0038.severity = suggestion
|
||||
# IDE0044: Make field readonly
|
||||
dotnet_diagnostic.IDE0044.severity = suggestion
|
||||
# IDE0051: Remove unused private members
|
||||
dotnet_diagnostic.IDE0051.severity = suggestion
|
||||
# IDE0059: Unnecessary assignment to a value
|
||||
dotnet_diagnostic.IDE0059.severity = suggestion
|
||||
# IDE0060: Remove unused parameters
|
||||
dotnet_diagnostic.IDE0060.severity = suggestion
|
||||
# IDE0062: Make local function static
|
||||
dotnet_diagnostic.IDE0062.severity = suggestion
|
||||
# IDE0200: Lambda expression can be removed
|
||||
dotnet_diagnostic.IDE0200.severity = suggestion
|
||||
|
||||
# CA2016: Forward the 'CancellationToken' parameter to methods that take one
|
||||
dotnet_diagnostic.CA2016.severity = suggestion
|
||||
|
||||
# Defaults for content in the shared src/ and shared runtime dir
|
||||
|
||||
[{**/Shared/runtime/**.{cs,vb},src/Shared/test/Shared.Tests/runtime/**.{cs,vb},**/microsoft.extensions.hostfactoryresolver.sources/**.{cs,vb}}]
|
||||
# CA1822: Make member static
|
||||
dotnet_diagnostic.CA1822.severity = silent
|
||||
# IDE0011: Use braces
|
||||
dotnet_diagnostic.IDE0011.severity = silent
|
||||
# IDE0055: Fix formatting
|
||||
dotnet_diagnostic.IDE0055.severity = silent
|
||||
# IDE0060: Remove unused parameters
|
||||
dotnet_diagnostic.IDE0060.severity = silent
|
||||
# IDE0062: Make local function static
|
||||
dotnet_diagnostic.IDE0062.severity = silent
|
||||
# IDE0161: Convert to file-scoped namespace
|
||||
dotnet_diagnostic.IDE0161.severity = silent
|
||||
|
||||
[{**/Shared/**.cs,**/microsoft.extensions.hostfactoryresolver.sources/**.{cs,vb}}]
|
||||
# IDE0005: Remove unused usings. Ignore for shared src files since imports for those depend on the projects in which they are included.
|
||||
dotnet_diagnostic.IDE0005.severity = silent
|
127
.gitea/workflows/docs.yaml
Normal file
127
.gitea/workflows/docs.yaml
Normal file
|
@ -0,0 +1,127 @@
|
|||
name: Build documentation
|
||||
run-name: ${{ gitea.actor }} is building the Wiki documentation
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- master
|
||||
paths:
|
||||
- Wiki/**
|
||||
- Wiki.Dockerfile
|
||||
|
||||
env:
|
||||
# Name of module and id separated by a slash
|
||||
INSTANCE: Wiki/wiki
|
||||
# Replace HI with the ID of the instance in capital letters
|
||||
ARTIFACT: webHelpWIKI2-all.zip
|
||||
# Writerside docker image version
|
||||
DOCKER_VERSION: 232.10165.1
|
||||
ALGOLIA_ARTIFACT: algolia-indexes-wiki.zip
|
||||
|
||||
|
||||
jobs:
|
||||
preprocess:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
sanitized_branch_name: ${{ steps.sanitize.outputs.sanitized_branch_name }}
|
||||
steps:
|
||||
- name: Sanitize branch name
|
||||
id: sanitize
|
||||
run: echo "::set-output name=sanitized_branch_name::$(echo ${{ github.ref_name }} | sed 's/\//-/g')"
|
||||
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
container: registry.jetbrains.team/p/writerside/builder/writerside-builder:${{env.DOCKER_VERSION}}
|
||||
steps:
|
||||
- name: Install basic dependencies
|
||||
run: |
|
||||
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
|
||||
echo "::add-path::$HOME/.nvm"
|
||||
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
nvm install 18
|
||||
nvm use 18
|
||||
echo "::add-path::$(dirname $(which npm))"
|
||||
nvm --version
|
||||
- name: Check Node.js version
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- name: Checkout repository
|
||||
uses: https://github.com/actions/checkout@v3
|
||||
- name: Build docs
|
||||
run: |
|
||||
set -e
|
||||
export DISPLAY=:99
|
||||
Xvfb :99 &
|
||||
/opt/builder/bin/idea.sh helpbuilderinspect -source-dir . -product ${{env.INSTANCE}} -output-dir artifacts/ || true
|
||||
echo "Test existing of ${{ env.ARTIFACT }} artifact"
|
||||
test -e artifacts/${{ env.ARTIFACT }}
|
||||
- name: rename artifact
|
||||
run: |
|
||||
mv artifacts/${{ env.ARTIFACT }} artifacts/wiki.zip
|
||||
- name: Upload documentation
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: wiki.zip
|
||||
path: artifacts/wiki.zip
|
||||
retention-days: 14
|
||||
- name: Upload algolia-indexes
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: algolia-indexes.zip
|
||||
path: artifacts/${{ env.ALGOLIA_ARTIFACT }}
|
||||
retention-days: 14
|
||||
|
||||
build-docs-container:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
needs: [docs, preprocess]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: https://github.com/actions/checkout@v3
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ github.server_url }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
- name: Retrieve docs artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: wiki.zip
|
||||
path: ${{ github.workspace }}
|
||||
- name: Unzip wiki.zip into .public
|
||||
run: |
|
||||
mkdir .public
|
||||
unzip -jo -qq ./wiki.zip/wiki.zip -d .public
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: Wiki.Dockerfile
|
||||
push: true
|
||||
tags: forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }}-wiki
|
||||
platforms: linux/amd64,linux/arm64
|
||||
- name: Build and push to latest
|
||||
if: github.ref_name == 'master'
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: Wiki.Dockerfile
|
||||
push: true
|
||||
tags: forge.rainote.dev/${{ github.repository }}:latest-wiki
|
||||
platforms: linux/amd64, linux/arm64
|
||||
|
||||
deploy-wiki:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
needs: [build-docs-container, docs, preprocess]
|
||||
steps:
|
||||
- name: Deploy Image to CapRrover
|
||||
run: |
|
||||
docker run caprover/cli-caprover:2.2.3 caprover deploy --caproverUrl ${{ secrets.CAPROVER_SERVER }} --appToken ${{ secrets.WIKI_APP_TOKEN }} --imageName forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }}-wiki -a ${{ secrets.WIKI_APP_NAME }}
|
|
@ -1,13 +1,206 @@
|
|||
name: Test if Server can be built
|
||||
name: Build, Package and Push Images
|
||||
run-name: ${{ gitea.actor }} is building the Server application
|
||||
on: [ push ]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- master
|
||||
paths-ignore:
|
||||
- Wiki/**
|
||||
- Benchmarks/**
|
||||
- .run/**
|
||||
|
||||
jobs:
|
||||
build-server:
|
||||
preprocess:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
sanitized_branch_name: ${{ steps.sanitize.outputs.sanitized_branch_name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Sanitize branch name
|
||||
id: sanitize
|
||||
run: echo "::set-output name=sanitized_branch_name::$(echo ${{ github.ref_name }} | sed 's/\//-/g')"
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
- run: dotnet build Server
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: |
|
||||
dotnet build Continuity.AuthServer -c Release
|
||||
|
||||
sonarqube:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
if: github.ref_name == 'master'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
dotnet restore
|
||||
echo "::add-path::$HOME/.dotnet/tools"
|
||||
- name: Setup Sonarqube Dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install --yes openjdk-18-jre
|
||||
dotnet tool install --global dotnet-sonarscanner
|
||||
dotnet tool install --global dotnet-coverage
|
||||
- name: Sonarqube Begin
|
||||
run: |
|
||||
dotnet sonarscanner begin /key:"${{ secrets.SONAR_PROJECT_KEY }}" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="${{ secrets.SONAR_HOST_URL }}"
|
||||
- name: Sonarqube Scan
|
||||
run: |
|
||||
dotnet build Continuity.AuthServer -c Release
|
||||
# dotnet test --collect "Code Coverage" --logger trx --results-directory "TestsResults"
|
||||
# dotnet-coverage collect 'dotnet test' -f xml -o 'coverage.xml'
|
||||
- name: Sonarqube End
|
||||
run: |
|
||||
dotnet sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
|
||||
|
||||
sbom-scan:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
dotnet restore
|
||||
echo "::add-path::$HOME/.dotnet/tools"
|
||||
- name: Setup Dependency Track Dependencies
|
||||
run: |
|
||||
dotnet tool install --global CycloneDX
|
||||
- name: Generate SBOM
|
||||
run: |
|
||||
dotnet CycloneDX Continuity.AuthServer/Continuity.AuthServer.csproj -o . -dgl
|
||||
- name: Upload SBOM
|
||||
uses: https://github.com/DependencyTrack/gh-upload-sbom@v2.0.1
|
||||
with:
|
||||
apiKey: ${{ secrets.DEPENDENCY_TRACK_API_KEY }}
|
||||
serverHostname: ${{ secrets.DEPENDENCY_TRACK_URL }}
|
||||
projectName: ${{ secrets.DEPENDENCY_TRACK_PROJECT_NAME }}
|
||||
autoCreate: true
|
||||
# set projectversion to be the branch name
|
||||
projectVersion: ${{ github.ref_name }}
|
||||
bomFilename: ${{ github.workspace }}/bom.xml
|
||||
|
||||
container-build:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
needs: [build, preprocess]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
# Add support for more platforms with QEMU (optional)
|
||||
# https://github.com/docker/setup-qemu-action
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ github.server_url }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: Continuity.AuthServer/Dockerfile
|
||||
push: true
|
||||
tags: forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
- name: Build and push to latest
|
||||
if: github.ref_name == 'master'
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: Continuity.AuthServer/Dockerfile
|
||||
push: true
|
||||
tags: forge.rainote.dev/${{ github.repository }}:latest
|
||||
platforms: linux/amd64, linux/arm64
|
||||
|
||||
container-sbom-scan:
|
||||
needs: [container-build, preprocess]
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
dotnet restore
|
||||
echo "::add-path::$HOME/.dotnet/tools"
|
||||
- name: Setup Dependency Track Dependencies
|
||||
run: |
|
||||
mkdir ~/.docker
|
||||
curl -sSfL https://raw.githubusercontent.com/docker/sbom-cli-plugin/main/install.sh | sh -s --
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ github.server_url }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
- name: Generate SBOM
|
||||
run: |
|
||||
echo forge.rainote.dev/${{ github.repository }}
|
||||
echo forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }}
|
||||
docker pull forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }}
|
||||
docker sbom -D forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }} --format cyclonedx-json --output container-bom.json
|
||||
- name: Upload SBOM
|
||||
uses: https://github.com/DependencyTrack/gh-upload-sbom@v2.0.1
|
||||
with:
|
||||
apiKey: ${{ secrets.DEPENDENCY_TRACK_API_KEY }}
|
||||
serverHostname: ${{ secrets.DEPENDENCY_TRACK_URL }}
|
||||
projectName: ${{ secrets.DEPENDENCY_TRACK_PROJECT_NAME }}-container
|
||||
autoCreate: true
|
||||
# set projectversion to be the branch name
|
||||
projectVersion: ${{ github.ref_name }}
|
||||
bomFilename: ${{ github.workspace }}/container-bom.json
|
||||
|
||||
generate-licences:
|
||||
needs: [build, preprocess]
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: |
|
||||
7.0
|
||||
8.0
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
dotnet restore
|
||||
echo "::add-path::$HOME/.dotnet/tools"
|
||||
- name: Install nuget-license
|
||||
run: dotnet tool install --global dotnet-project-licenses
|
||||
- name: Export licenses
|
||||
run: dotnet-project-licenses -i . -u --projects-filter projects_ignore_licenses.json -m -j -e -f licenses
|
||||
- name: Upload licenses
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: licenses
|
||||
path: licenses
|
||||
retention-days: 31
|
||||
|
|
170
.gitea/workflows/server_pr.yaml
Normal file
170
.gitea/workflows/server_pr.yaml
Normal file
|
@ -0,0 +1,170 @@
|
|||
name: PR Workflow
|
||||
run-name: ${{ gitea.actor }} PR related workflow
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- Wiki/**
|
||||
- Benchmarks/**
|
||||
- .run/**
|
||||
|
||||
jobs:
|
||||
preprocess:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
sanitized_branch_name: ${{ steps.sanitize.outputs.sanitized_branch_name }}
|
||||
steps:
|
||||
- name: Sanitize branch name
|
||||
id: sanitize
|
||||
run: echo "::set-output name=sanitized_branch_name::$(echo ${{ github.ref_name }} | sed 's/\//-/g')"
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: |
|
||||
dotnet build Continuity.AuthServer -c Release
|
||||
|
||||
sbom-scan:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
dotnet restore
|
||||
echo "::add-path::$HOME/.dotnet/tools"
|
||||
- name: Setup Dependency Track Dependencies
|
||||
run: |
|
||||
dotnet tool install --global CycloneDX
|
||||
- name: Generate SBOM
|
||||
run: |
|
||||
dotnet CycloneDX Continuity.AuthServer/Continuity.AuthServer.csproj -o . -dgl
|
||||
- name: Upload SBOM
|
||||
uses: https://github.com/DependencyTrack/gh-upload-sbom@v2.0.1
|
||||
with:
|
||||
apiKey: ${{ secrets.DEPENDENCY_TRACK_API_KEY }}
|
||||
serverHostname: ${{ secrets.DEPENDENCY_TRACK_URL }}
|
||||
projectName: ${{ secrets.DEPENDENCY_TRACK_PROJECT_NAME }}
|
||||
autoCreate: true
|
||||
# set projectversion to be the branch name
|
||||
projectVersion: ${{ github.ref_name }}
|
||||
bomFilename: ${{ github.workspace }}/bom.xml
|
||||
|
||||
container-build:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
needs: [ build, preprocess ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
# Add support for more platforms with QEMU (optional)
|
||||
# https://github.com/docker/setup-qemu-action
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ github.server_url }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: Continuity.AuthServer/Dockerfile
|
||||
push: true
|
||||
tags: forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
- name: Build and push to latest
|
||||
if: github.ref_name == 'master'
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: Continuity.AuthServer/Dockerfile
|
||||
push: true
|
||||
tags: forge.rainote.dev/${{ github.repository }}:latest
|
||||
platforms: linux/amd64, linux/arm64
|
||||
|
||||
container-sbom-scan:
|
||||
needs: [ container-build, preprocess ]
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
global-json-file: global.json
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
dotnet restore
|
||||
echo "::add-path::$HOME/.dotnet/tools"
|
||||
- name: Setup Dependency Track Dependencies
|
||||
run: |
|
||||
mkdir ~/.docker
|
||||
curl -sSfL https://raw.githubusercontent.com/docker/sbom-cli-plugin/main/install.sh | sh -s --
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ github.server_url }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
- name: Generate SBOM
|
||||
run: |
|
||||
echo forge.rainote.dev/${{ github.repository }}
|
||||
echo forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }}
|
||||
docker pull forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }}
|
||||
docker sbom -D forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }} --format cyclonedx-json --output container-bom.json
|
||||
- name: Upload SBOM
|
||||
uses: https://github.com/DependencyTrack/gh-upload-sbom@v2.0.1
|
||||
with:
|
||||
apiKey: ${{ secrets.DEPENDENCY_TRACK_API_KEY }}
|
||||
serverHostname: ${{ secrets.DEPENDENCY_TRACK_URL }}
|
||||
projectName: ${{ secrets.DEPENDENCY_TRACK_PROJECT_NAME }}-container
|
||||
autoCreate: true
|
||||
# set projectversion to be the branch name
|
||||
projectVersion: ${{ github.ref_name }}
|
||||
bomFilename: ${{ github.workspace }}/container-bom.json
|
||||
|
||||
generate-licences:
|
||||
needs: [ build, preprocess ]
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest@sha256:5f2ff408985b10de9da4a8ea735b7f07d4f98c61608180ebb8964deb37f7580a
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup dotnet
|
||||
uses: https://github.com/actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: |
|
||||
7.0
|
||||
8.0
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
dotnet restore
|
||||
echo "::add-path::$HOME/.dotnet/tools"
|
||||
- name: Install nuget-license
|
||||
run: dotnet tool install --global dotnet-project-licenses
|
||||
- name: Export licenses
|
||||
run: dotnet-project-licenses -i . -u --projects-filter projects_ignore_licenses.json -m -j -e -f licenses
|
||||
- name: Upload licenses
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: licenses
|
||||
path: licenses
|
||||
retention-days: 31
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -3,6 +3,8 @@
|
|||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||
|
||||
licenses
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
|
@ -480,3 +482,7 @@ $RECYCLE.BIN/
|
|||
|
||||
.idea
|
||||
.vscode
|
||||
|
||||
.nuke
|
||||
|
||||
wk-data
|
||||
|
|
118
.gitlab-ci.yml
118
.gitlab-ci.yml
|
@ -1,118 +0,0 @@
|
|||
image: mcr.microsoft.com/dotnet/sdk:latest
|
||||
|
||||
# ### Define variables
|
||||
#
|
||||
variables:
|
||||
# 1) Name of directory where restore and build objects are stored.
|
||||
OBJECTS_DIRECTORY: 'obj'
|
||||
# 2) Name of directory used for keeping restored dependencies.
|
||||
NUGET_PACKAGES_DIRECTORY: '.nuget'
|
||||
# 3) A relative path to the source code from project repository root.
|
||||
# NOTE: Please edit this path so it matches the structure of your project!
|
||||
SOURCE_CODE_PATH: '*/*/'
|
||||
|
||||
# ### Define global cache rule
|
||||
#
|
||||
# Before building the project, all dependencies (e.g. third-party NuGet packages)
|
||||
# must be restored. Jobs on GitLab.com's Shared Runners are executed on autoscaled machines.
|
||||
#
|
||||
# Each machine is used only once (for security reasons) and after that is removed.
|
||||
# This means that, before every job, a dependency restore must be performed
|
||||
# because restored dependencies are removed along with machines. Fortunately,
|
||||
# GitLab provides cache mechanism with the aim of keeping restored dependencies
|
||||
# for other jobs.
|
||||
#
|
||||
# This example shows how to configure cache to pass over restored
|
||||
# dependencies for re-use.
|
||||
#
|
||||
# With global cache rule, cached dependencies will be downloaded before every job
|
||||
# and then unpacked to the paths as specified below.
|
||||
cache:
|
||||
# Per-stage and per-branch caching.
|
||||
key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
# Specify three paths that should be cached:
|
||||
#
|
||||
# 1) Main JSON file holding information about package dependency tree, packages versions,
|
||||
# frameworks etc. It also holds information where to the dependencies were restored.
|
||||
- '$SOURCE_CODE_PATH$OBJECTS_DIRECTORY/project.assets.json'
|
||||
# 2) Other NuGet and MSBuild related files. Also needed.
|
||||
- '$SOURCE_CODE_PATH$OBJECTS_DIRECTORY/*.csproj.nuget.*'
|
||||
# 3) Path to the directory where restored dependencies are kept.
|
||||
- '$NUGET_PACKAGES_DIRECTORY'
|
||||
#
|
||||
# 'pull-push' policy means that latest cache will be downloaded (if it exists)
|
||||
# before executing the job, and a newer version will be uploaded afterwards.
|
||||
# Such a setting saves time when there are no changes in referenced third-party
|
||||
# packages.
|
||||
#
|
||||
# For example, if you run a pipeline with changes in your code,
|
||||
# but with no changes within third-party packages which your project is using,
|
||||
# then project restore will happen quickly as all required dependencies
|
||||
# will already be there — unzipped from cache.
|
||||
|
||||
# 'pull-push' policy is the default cache policy, you do not have to specify it explicitly.
|
||||
policy: pull-push
|
||||
|
||||
# ### Restore project dependencies
|
||||
#
|
||||
# NuGet packages by default are restored to '.nuget/packages' directory
|
||||
# in the user's home directory. That directory is out of scope of GitLab caching.
|
||||
#
|
||||
# To get around this, a custom path can be specified using the '--packages <PATH>' option
|
||||
# for 'dotnet restore' command. In this example, a temporary directory is created
|
||||
# in the root of project repository, so its content can be cached.
|
||||
#
|
||||
# Learn more about GitLab cache: https://docs.gitlab.com/ee/ci/caching/index.html
|
||||
before_script:
|
||||
- 'dotnet restore --packages $NUGET_PACKAGES_DIRECTORY'
|
||||
|
||||
build:
|
||||
stage: build
|
||||
# ### Build all projects discovered from solution file.
|
||||
#
|
||||
# Note: this will fail if you have any projects in your solution that are not
|
||||
# .NET Core-based projects (e.g. WCF service), which is based on .NET Framework,
|
||||
# not .NET Core. In this scenario, you will need to build every .NET Core-based
|
||||
# project by explicitly specifying a relative path to the directory
|
||||
# where it is located (e.g. 'dotnet build ./src/ConsoleApp').
|
||||
# Only one project path can be passed as a parameter to 'dotnet build' command.
|
||||
script:
|
||||
- 'dotnet build --no-restore'
|
||||
|
||||
tests:
|
||||
stage: test
|
||||
# ### Run the tests
|
||||
#
|
||||
# You can either run tests for all test projects that are defined in your solution
|
||||
# with 'dotnet test' or run tests only for specific project by specifying
|
||||
# a relative path to the directory where it is located (e.g. 'dotnet test ./test/UnitTests').
|
||||
#
|
||||
# You may want to define separate testing jobs for different types of testing
|
||||
# (e.g. integration tests, unit tests etc).
|
||||
script:
|
||||
- 'dotnet test --no-restore'
|
||||
|
||||
sonarqube-check:
|
||||
image: mcr.microsoft.com/dotnet/sdk:latest
|
||||
variables:
|
||||
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
|
||||
GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}"
|
||||
paths:
|
||||
- .sonar/cache
|
||||
script:
|
||||
- "apt-get update"
|
||||
- "apt-get install --yes openjdk-11-jre"
|
||||
- "dotnet tool install --global dotnet-sonarscanner"
|
||||
- "dotnet tool install --global dotnet-coverage"
|
||||
- "export PATH=\"$PATH:$HOME/.dotnet/tools\""
|
||||
- "dotnet sonarscanner begin /k:\"wonderking_continuity_AYeecUUTs-PH__JrTRky\" /d:sonar.token=\"$SONAR_TOKEN\" /d:\"sonar.host.url=$SONAR_HOST_URL\" "
|
||||
- "dotnet build"
|
||||
- "dotnet test --collect \"Code Coverage\" --logger trx --results-directory \"TestsResults\""
|
||||
# - "dotnet-coverage collect 'dotnet test' -f xml -o 'coverage.xml'"
|
||||
- "dotnet sonarscanner end /d:sonar.login=\"$SONAR_TOKEN\""
|
||||
allow_failure: true
|
||||
only:
|
||||
- master
|
19
.pre-commit-config.yaml
Normal file
19
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
#Use dotnet format already installed on your machine
|
||||
- id: dotnet-format
|
||||
name: dotnet-format
|
||||
language: system
|
||||
entry: dotnet format --include
|
||||
types_or: [c#, vb]
|
||||
- repo: https://github.com/Mateusz-Grzelinski/actionlint-py
|
||||
rev: v1.6.26.11
|
||||
hooks:
|
||||
- id: actionlint
|
||||
additional_dependencies: [pyflakes>=3.0.1, shellcheck-py>=0.9.0.5]
|
||||
- repo: https://github.com/hadolint/hadolint
|
||||
rev: v2.12.0
|
||||
hooks:
|
||||
- id: hadolint-docker
|
||||
args: [--ignore, SC2086]
|
16
.run/Server_Dockerfile.run.xml
Normal file
16
.run/Server_Dockerfile.run.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Server/Dockerfile" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="continuity" />
|
||||
<option name="buildCliOptions" value="--platform linux/amd64" />
|
||||
<option name="buildKitEnabled" value="true" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="contextFolderPath" value="." />
|
||||
<option name="sourceFilePath" value="Server/Dockerfile" />
|
||||
</settings>
|
||||
</deployment>
|
||||
<EXTENSION ID="com.jetbrains.rider.docker.debug" isFastModeEnabled="true" isSslEnabled="false" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
6
.run/build images.run.xml
Normal file
6
.run/build images.run.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="build images" type="PowerShellRunType" factoryName="PowerShell" scriptUrl="C:\Users\Timot\Projects\Continuity\build-image.ps1" workingDirectory="C:\Users\Timot\Projects\Continuity" executablePath="C:\Users\Timot\scoop\apps\pwsh\current\pwsh.exe">
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
19
.run/docker-compose.yml_ Compose Deployment.run.xml
Normal file
19
.run/docker-compose.yml_ Compose Deployment.run.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="docker-compose.yml: Compose Deployment" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
||||
<deployment type="docker-compose.yml">
|
||||
<settings>
|
||||
<option name="buildKitEnabledForCompose" value="true" />
|
||||
<option name="envFilePath" value="" />
|
||||
<option name="sourceFilePath" value="docker-compose.yml" />
|
||||
<option name="upDetach" value="false" />
|
||||
<option name="upRemoveOrphans" value="true" />
|
||||
</settings>
|
||||
</deployment>
|
||||
<EXTENSION ID="com.jetbrains.rider.docker.debug" isFastModeEnabled="true" isSslEnabled="false" />
|
||||
<method v="2">
|
||||
<option name="Build" default="false" projectName="Wonderking" projectPath="$PROJECT_DIR$/Wonderking/Wonderking.csproj" />
|
||||
<option name="Build" default="false" projectName="Server" projectPath="$PROJECT_DIR$/Server/Server.csproj" />
|
||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="build images" run_configuration_type="PowerShellRunType" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
128
Benchmarks/Argon2Benchmarks.cs
Normal file
128
Benchmarks/Argon2Benchmarks.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Order;
|
||||
using Isopoh.Cryptography.Argon2;
|
||||
using Konscious.Security.Cryptography;
|
||||
using Argon2 = Isopoh.Cryptography.Argon2.Argon2;
|
||||
|
||||
namespace Benchmarks;
|
||||
|
||||
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
||||
[Config(typeof(GenericConfig))]
|
||||
public class Argon2Benchmarks
|
||||
{
|
||||
[Params(2, 4)] public int _iterations;
|
||||
[Params(16, 32)] public int _memory;
|
||||
[Params(1, 2)] public int _parallelism;
|
||||
private byte[] _salt = null!;
|
||||
private byte[] _additionalData = null!;
|
||||
[Params(16)] public int _length;
|
||||
|
||||
private byte[] _password = null!;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_salt = RandomNumberGenerator.GetBytes(16);
|
||||
_additionalData = RandomNumberGenerator.GetBytes(16);
|
||||
_password = RandomNumberGenerator.GetBytes(16);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public byte[] Argon2i()
|
||||
{
|
||||
return new Argon2i(_password)
|
||||
{
|
||||
Iterations = _iterations,
|
||||
MemorySize = 1024 * _memory,
|
||||
DegreeOfParallelism = _parallelism,
|
||||
AssociatedData = _additionalData,
|
||||
Salt = _salt,
|
||||
}.GetBytes(_length);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public byte[] Argon2d()
|
||||
{
|
||||
return new Argon2d(_password)
|
||||
{
|
||||
Iterations = _iterations,
|
||||
MemorySize = 1024 * _memory,
|
||||
DegreeOfParallelism = _parallelism,
|
||||
AssociatedData = _additionalData,
|
||||
Salt = _salt,
|
||||
}.GetBytes(_length);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public byte[] Argon2id()
|
||||
{
|
||||
return new Argon2id(_password)
|
||||
{
|
||||
Iterations = _iterations,
|
||||
MemorySize = 1024 * _memory,
|
||||
DegreeOfParallelism = _parallelism,
|
||||
AssociatedData = _additionalData,
|
||||
Salt = _salt,
|
||||
}.GetBytes(_length);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public byte[] IsopohArgon2DD()
|
||||
{
|
||||
var config = new Argon2Config
|
||||
{
|
||||
Type = Argon2Type.DataDependentAddressing,
|
||||
Version = Argon2Version.Nineteen,
|
||||
MemoryCost = 1024 * _memory,
|
||||
TimeCost = _iterations,
|
||||
Lanes = _parallelism,
|
||||
HashLength = _length,
|
||||
Salt = _salt,
|
||||
AssociatedData = _additionalData,
|
||||
Password = _password,
|
||||
};
|
||||
var argon2 = new Argon2(config);
|
||||
return argon2.Hash().Buffer;
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public byte[] IsopohArgon2DI()
|
||||
{
|
||||
var config = new Argon2Config
|
||||
{
|
||||
Type = Argon2Type.DataIndependentAddressing,
|
||||
Version = Argon2Version.Nineteen,
|
||||
MemoryCost = 1024 * _memory,
|
||||
TimeCost = _iterations,
|
||||
Lanes = _parallelism,
|
||||
HashLength = _length,
|
||||
Salt = _salt,
|
||||
AssociatedData = _additionalData,
|
||||
Password = _password,
|
||||
};
|
||||
var argon2 = new Argon2(config);
|
||||
return argon2.Hash().Buffer;
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public byte[] IsopohArgon2Hybrid()
|
||||
{
|
||||
var config = new Argon2Config
|
||||
{
|
||||
Type = Argon2Type.HybridAddressing,
|
||||
Version = Argon2Version.Nineteen,
|
||||
MemoryCost = 1024 * _memory,
|
||||
TimeCost = _iterations,
|
||||
Lanes = _parallelism,
|
||||
HashLength = _length,
|
||||
Salt = _salt,
|
||||
AssociatedData = _additionalData,
|
||||
Password = _password,
|
||||
};
|
||||
var argon2 = new Argon2(config);
|
||||
return argon2.Hash().Buffer;
|
||||
}
|
||||
}
|
|
@ -4,12 +4,27 @@
|
|||
<OutputType>Exe</OutputType>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>default</LangVersion>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.7"/>
|
||||
<PackageReference Include="AsyncFixer" Version="1.6.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
|
||||
<PackageReference Include="DotNext.Unsafe" Version="0.14.0" />
|
||||
<PackageReference Include="Isopoh.Cryptography.Argon2" Version="2.0.0" />
|
||||
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.0" />
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.146">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.28">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,44 +1,70 @@
|
|||
namespace Benchmarks;
|
||||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Buffers.Binary;
|
||||
using System.Security.Cryptography;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Order;
|
||||
|
||||
[SimpleJob(RuntimeMoniker.NativeAot70)]
|
||||
[SimpleJob(RuntimeMoniker.Net70)]
|
||||
[SimpleJob(RuntimeMoniker.Net60)]
|
||||
namespace Benchmarks;
|
||||
|
||||
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
||||
[RankColumn]
|
||||
[MemoryDiagnoser]
|
||||
[ExceptionDiagnoser]
|
||||
[ThreadingDiagnoser]
|
||||
[Config(typeof(GenericConfig))]
|
||||
public class BinaryConversionBenchmarks
|
||||
{
|
||||
private byte[] data;
|
||||
private int offset;
|
||||
private byte[] _data = null!;
|
||||
private int _offset;
|
||||
private int _writeBuffer;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
this.data = RandomNumberGenerator.GetBytes(4000);
|
||||
this.offset = RandomNumberGenerator.GetInt32(0, 3500);
|
||||
_data = RandomNumberGenerator.GetBytes(4000);
|
||||
_offset = RandomNumberGenerator.GetInt32(0, 3500);
|
||||
_writeBuffer = RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public short BitConverterTest() => BitConverter.ToInt16(this.data, this.offset);
|
||||
public short BitConverterParseTest()
|
||||
{
|
||||
return BitConverter.ToInt16(_data, _offset);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public short BinaryReader()
|
||||
{
|
||||
using var ms = new MemoryStream(this.data);
|
||||
using var ms = new MemoryStream(_data);
|
||||
using var reader = new BinaryReader(ms);
|
||||
reader.BaseStream.Position = this.offset;
|
||||
reader.BaseStream.Position = _offset;
|
||||
return reader.ReadInt16();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public short BinaryPrimitives() =>
|
||||
System.Buffers.Binary.BinaryPrimitives.ReadInt16LittleEndian(
|
||||
new ArraySegment<byte>(this.data, this.offset, sizeof(short)));
|
||||
public short BinaryPrimitivesRead()
|
||||
{
|
||||
return BinaryPrimitives.ReadInt16LittleEndian(
|
||||
new ArraySegment<byte>(_data, _offset, sizeof(short)));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void BinaryPrimitivesWrite()
|
||||
{
|
||||
BinaryPrimitives.WriteInt32LittleEndian(_data.AsSpan(_offset, 4),
|
||||
_writeBuffer);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void BitConverterCopy()
|
||||
{
|
||||
BitConverter.GetBytes(_writeBuffer).CopyTo(_data, _offset);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void BitConverterAssignment()
|
||||
{
|
||||
var bytes = BitConverter.GetBytes(_writeBuffer);
|
||||
_data[_offset] = bytes[0];
|
||||
_data[_offset + 1] = bytes[1];
|
||||
_data[_offset + 2] = bytes[2];
|
||||
_data[_offset + 3] = bytes[3];
|
||||
}
|
||||
}
|
||||
|
|
86
Benchmarks/DataCacheBenchmark.cs
Normal file
86
Benchmarks/DataCacheBenchmark.cs
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Immutable;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Order;
|
||||
|
||||
namespace Benchmarks;
|
||||
|
||||
[Config(typeof(GenericConfig))]
|
||||
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
||||
public class DataCacheBenchmark
|
||||
{
|
||||
private ConcurrentDictionary<int, int> _concurrentDictionary;
|
||||
private Dictionary<int, int> _dictionary;
|
||||
private HashSet<int> _hashSet;
|
||||
private ImmutableHashSet<int> _immutableHashSet;
|
||||
[Params(1000, 100000, 1000000)] public int N;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_hashSet = new HashSet<int>();
|
||||
_dictionary = new Dictionary<int, int>();
|
||||
_concurrentDictionary = new ConcurrentDictionary<int, int>();
|
||||
_immutableHashSet = ImmutableHashSet<int>.Empty;
|
||||
|
||||
_hashSet.Clear();
|
||||
_dictionary.Clear();
|
||||
_concurrentDictionary.Clear();
|
||||
_immutableHashSet = _immutableHashSet.Clear();
|
||||
_hashSet.EnsureCapacity(N);
|
||||
_dictionary.EnsureCapacity(N);
|
||||
|
||||
for (var i = 0; i < N; i++)
|
||||
{
|
||||
_immutableHashSet = _immutableHashSet.Add(i);
|
||||
_hashSet.Add(i);
|
||||
_dictionary.Add(i, i);
|
||||
_concurrentDictionary.TryAdd(i, i);
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void HashSetAdd()
|
||||
{
|
||||
ParallelEnumerable.Range(0, N).AsParallel().ForAll(i => _hashSet.Add(i));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void DictionaryAdd()
|
||||
{
|
||||
ParallelEnumerable.Range(0, N).AsParallel().ForAll(i => _dictionary.Add(N + i, i));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ConcurrentDictionaryAddOrUpdate()
|
||||
{
|
||||
ParallelEnumerable.Range(0, N).AsParallel().ForAll(i =>
|
||||
_concurrentDictionary.AddOrUpdate(N + i, i, (key, oldValue) => oldValue + i));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ImmutableHashSetLookup()
|
||||
{
|
||||
ParallelEnumerable.Range(0, N).AsParallel().ForAll(i => _immutableHashSet.Contains(i));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void HashSetLookup()
|
||||
{
|
||||
ParallelEnumerable.Range(0, N).AsParallel().ForAll(i => _hashSet.Contains(i));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void DictionaryLookup()
|
||||
{
|
||||
ParallelEnumerable.Range(0, N).AsParallel().ForAll(i => _dictionary.ContainsKey(i));
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void ConcurrentDictionaryLookup()
|
||||
{
|
||||
ParallelEnumerable.Range(0, N).AsParallel().ForAll(i => _concurrentDictionary.ContainsKey(i));
|
||||
}
|
||||
}
|
33
Benchmarks/GenericConfig.cs
Normal file
33
Benchmarks/GenericConfig.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using BenchmarkDotNet.Analysers;
|
||||
using BenchmarkDotNet.Columns;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnosers;
|
||||
using BenchmarkDotNet.Environments;
|
||||
using BenchmarkDotNet.Exporters;
|
||||
using BenchmarkDotNet.Exporters.Csv;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
|
||||
namespace Benchmarks;
|
||||
|
||||
public class GenericConfig : ManualConfig
|
||||
{
|
||||
public GenericConfig()
|
||||
{
|
||||
AddJob(Job.Default
|
||||
.WithRuntime(CoreRuntime.Core80))
|
||||
.AddDiagnoser(ThreadingDiagnoser.Default, MemoryDiagnoser.Default,
|
||||
EventPipeProfiler.Default)
|
||||
.AddAnalyser(MinIterationTimeAnalyser.Default, OutliersAnalyser.Default,
|
||||
RuntimeErrorAnalyser.Default, EnvironmentAnalyser.Default)
|
||||
.AddColumn(RankColumn.Arabic).AddExporter(CsvExporter.Default, MarkdownExporter.Default);
|
||||
AddJob(Job.Default
|
||||
.WithRuntime(CoreRuntime.Core70))
|
||||
.AddDiagnoser(ThreadingDiagnoser.Default, MemoryDiagnoser.Default,
|
||||
EventPipeProfiler.Default)
|
||||
.AddAnalyser(MinIterationTimeAnalyser.Default, OutliersAnalyser.Default,
|
||||
RuntimeErrorAnalyser.Default, EnvironmentAnalyser.Default)
|
||||
.AddColumn(RankColumn.Arabic).AddExporter(CsvExporter.Default, MarkdownExporter.Default);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
namespace Benchmarks;
|
||||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Reflection;
|
||||
using BenchmarkDotNet.Running;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
public static void Main(string[] args) => BenchmarkRunner.Run(Assembly.GetExecutingAssembly());
|
||||
}
|
||||
BenchmarkRunner.Run(Assembly.GetExecutingAssembly());
|
||||
|
|
1227
Continuity.AuthServer/.dockerignore
Normal file
1227
Continuity.AuthServer/.dockerignore
Normal file
File diff suppressed because it is too large
Load diff
115
Continuity.AuthServer/AuthSession.cs
Normal file
115
Continuity.AuthServer/AuthSession.cs
Normal file
|
@ -0,0 +1,115 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using Continuity.AuthServer.Packets;
|
||||
using MassTransit.Mediator;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetCoreServer;
|
||||
using Wonderking.Packets;
|
||||
|
||||
namespace Continuity.AuthServer;
|
||||
|
||||
public class AuthSession : TcpSession
|
||||
{
|
||||
private readonly ILogger<AuthSession> _logger;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public AuthSession(TcpServer
|
||||
server, IMediator mediator, ILogger<AuthSession> logger) : base(server)
|
||||
{
|
||||
_mediator = mediator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Guid AccountId { get; set; }
|
||||
|
||||
public override long Send(byte[] buffer)
|
||||
{
|
||||
_logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(buffer));
|
||||
return base.Send(buffer);
|
||||
}
|
||||
|
||||
public Task SendAsync(IPacket packet)
|
||||
{
|
||||
var type = packet.GetType();
|
||||
_logger.LogInformation("Packet of type {Type} is being serialized", type.Name);
|
||||
var packetIdAttribute = type.GetCustomAttribute<PacketIdAttribute>();
|
||||
if (packetIdAttribute == null)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var opcode = packetIdAttribute.Code;
|
||||
|
||||
Span<byte> packetData = packet.Serialize();
|
||||
var length = (ushort)(packetData.Length + 8);
|
||||
|
||||
Span<byte> buffer = stackalloc byte[length];
|
||||
buffer.Clear();
|
||||
packetData.CopyTo(buffer[8..length]);
|
||||
|
||||
var bytesOfLength = BitConverter.GetBytes(length);
|
||||
var bytesOfOpcode = BitConverter.GetBytes((ushort)opcode);
|
||||
for (var i = 0; i < bytesOfLength.Length || i < 2; i++)
|
||||
{
|
||||
buffer[i] = bytesOfLength[i];
|
||||
}
|
||||
|
||||
for (var i = 0; i < bytesOfOpcode.Length || i < 2; i++)
|
||||
{
|
||||
buffer[2 + i] = bytesOfOpcode[i];
|
||||
}
|
||||
|
||||
_logger.LogInformation("Packet data being parsed is: {Data}", BitConverter.ToString(packetData.ToArray()));
|
||||
_logger.LogInformation("Packet being parsed is: {Data}", BitConverter.ToString(buffer.ToArray()));
|
||||
|
||||
SendAsync(buffer);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||
{
|
||||
_logger.LogDebug("Length: {Size} & offset: {Offset}", size, offset);
|
||||
Span<byte> decryptedBuffer = stackalloc byte[(int)size];
|
||||
|
||||
// xor every value after the first 8 bytes
|
||||
var dataBuffer = Decrypt(buffer.AsSpan(8, (int)size - 8));
|
||||
_logger.LogDebug("Length {Length}", BitConverter.ToUInt16(buffer, 0));
|
||||
|
||||
var opCode = BitConverter.ToUInt16(buffer.ToArray(), 2);
|
||||
|
||||
_logger.LogDebug("Packet Op Code: {OpCode}", opCode);
|
||||
_logger.LogDebug("Some Value: {RandomValue}", buffer[4]);
|
||||
|
||||
var clientAliveTime = BitConverter.ToUInt16(buffer.ToArray(), 5);
|
||||
|
||||
_logger.LogDebug("Client Alive time: {ClientAliveTime}", clientAliveTime);
|
||||
_logger.LogDebug("Might be a flag: {Flag}", buffer[7]);
|
||||
|
||||
_logger.LogDebug("Full buffer: {Buffer}", BitConverter.ToString(dataBuffer.ToArray()));
|
||||
|
||||
var rawPacket = new RawPacket((OperationCode)opCode, dataBuffer, clientAliveTime, buffer[7],
|
||||
buffer[4], Id, this);
|
||||
|
||||
_ = _mediator.Send(rawPacket);
|
||||
|
||||
_logger.LogInformation("Connection from: {@RemoteEndpoint}", Socket.RemoteEndPoint?.ToString());
|
||||
base.OnReceived(decryptedBuffer.ToArray(), offset, decryptedBuffer.Length);
|
||||
}
|
||||
|
||||
private static Span<byte> Decrypt(Span<byte> buffer)
|
||||
{
|
||||
for (var i = 0; i < buffer.Length; ++i)
|
||||
{
|
||||
buffer[i] = (byte)(buffer[i] ^ i ^ (3 * (0xFE - i)));
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
protected override void OnError(SocketError error)
|
||||
{
|
||||
_logger.LogWarning("An error has occured: {Error}", error);
|
||||
}
|
||||
}
|
75
Continuity.AuthServer/ChannelSession.cs
Normal file
75
Continuity.AuthServer/ChannelSession.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using MassTransit.Mediator;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetCoreServer;
|
||||
|
||||
namespace Continuity.AuthServer;
|
||||
|
||||
public class ChannelSession : TcpSession
|
||||
{
|
||||
private static readonly byte[] _key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7 }
|
||||
.Reverse().ToArray();
|
||||
|
||||
private static readonly byte[] _iv = new byte[]
|
||||
{
|
||||
0xfe, 220, 0xba, 0x98, 0x76, 0x54, 50, 0x10, 15, 30, 0x2d, 60, 0x4b, 90, 0x69, 120
|
||||
}.Reverse().ToArray();
|
||||
|
||||
private readonly ICryptoTransform _decryptor;
|
||||
|
||||
private readonly ICryptoTransform _encryptor;
|
||||
private readonly ILogger<ChannelSession> _logger;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public ChannelSession(TcpServer server, IMediator mediator, ILogger<ChannelSession> logger) : base(server)
|
||||
{
|
||||
_mediator = mediator;
|
||||
_logger = logger;
|
||||
var aes = Aes.Create();
|
||||
aes.Key = _key;
|
||||
aes.IV = _iv;
|
||||
aes.Padding = PaddingMode.None;
|
||||
#pragma warning disable SEC0026
|
||||
aes.Mode = CipherMode.ECB;
|
||||
#pragma warning restore SEC0026
|
||||
|
||||
_decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||
_encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
|
||||
}
|
||||
|
||||
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var ms = new MemoryStream(Decrypt(buffer)))
|
||||
using (var cs = new CryptoStream(ms, _decryptor, CryptoStreamMode.Read))
|
||||
{
|
||||
var amountOfReadBytes = cs.Read(buffer);
|
||||
if (amountOfReadBytes != buffer.Length)
|
||||
{
|
||||
_logger.LogError("Amount of read bytes is not equal to buffer length");
|
||||
}
|
||||
}
|
||||
|
||||
base.OnReceived(buffer, offset, size);
|
||||
}
|
||||
catch (CryptographicException ex)
|
||||
{
|
||||
_logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message);
|
||||
_logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] Decrypt(byte[] buffer)
|
||||
{
|
||||
for (var i = 0; i < buffer.Length; ++i)
|
||||
{
|
||||
buffer[i] = (byte)(buffer[i] ^ i ^ (3 * (0xFE - i)));
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
23
Continuity.AuthServer/Consumers/PacketConsumer.cs
Normal file
23
Continuity.AuthServer/Consumers/PacketConsumer.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Continuity.AuthServer.Packets;
|
||||
using Continuity.AuthServer.Services;
|
||||
using MassTransit;
|
||||
|
||||
namespace Continuity.AuthServer.Consumers;
|
||||
|
||||
public class PacketConsumer : IConsumer<RawPacket>
|
||||
{
|
||||
private readonly PacketDistributorService _distributorService;
|
||||
|
||||
public PacketConsumer(PacketDistributorService distributorService)
|
||||
{
|
||||
_distributorService = distributorService;
|
||||
}
|
||||
|
||||
public Task Consume(ConsumeContext<RawPacket> context)
|
||||
{
|
||||
_distributorService.AddPacket(context.Message);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
121
Continuity.AuthServer/Continuity.AuthServer.csproj
Normal file
121
Continuity.AuthServer/Continuity.AuthServer.csproj
Normal file
|
@ -0,0 +1,121 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>warnings</Nullable>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<LangVersion>default</LangVersion>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
<Features>strict</Features>
|
||||
<Authors>Timothy (RaiNote) Schenk</Authors>
|
||||
<Copyright>Timothy (RaiNote) Schenk</Copyright>
|
||||
<PackageProjectUrl>https://forge.rainote.dev/wonderking/continuity</PackageProjectUrl>
|
||||
<RepositoryUrl>https://forge.rainote.dev/wonderking/continuity</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
||||
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<AnalysisLevel>latest-recommended</AnalysisLevel>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0|AnyCPU'">
|
||||
<WarningLevel>7</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
|
||||
<WarningLevel>7</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\.dockerignore">
|
||||
<Link>.dockerignore</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncFixer" Version="1.6.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="DotNext" Version="5.13.0" />
|
||||
<PackageReference Include="DotNext.IO" Version="5.13.0" />
|
||||
<PackageReference Include="DotNext.Metaprogramming" Version="5.13.0" />
|
||||
<PackageReference Include="DotNext.Threading" Version="5.13.0" />
|
||||
<PackageReference Include="DotNext.Unsafe" Version="5.13.0" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0"/>
|
||||
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.0"/>
|
||||
<PackageReference Include="MassTransit" Version="8.1.3" />
|
||||
<PackageReference Include="MassTransit.Analyzers" Version="8.1.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Meziantou.Analyzer" Version="2.0.146">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0"/>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.28">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NetCoreServer" Version="8.0.7" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
|
||||
<PackageReference Include="Npgsql.OpenTelemetry" Version="8.0.2" />
|
||||
<PackageReference Include="Nullable.Extended.Analyzer" Version="1.15.6169">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="OpenTelemetry" Version="1.7.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.7.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.7.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Zipkin" Version="1.7.0" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.7.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.EntityFrameworkCore" Version="1.0.0-beta.10"/>
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.7.1" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.0.0-alpha.6" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.7.0" />
|
||||
<PackageReference Include="OpenTelemetry.PersistentStorage.FileSystem" Version="1.0.0"/>
|
||||
<PackageReference Include="OpenTelemetry.ResourceDetectors.Container" Version="1.0.0-beta.6"/>
|
||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0"/>
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="settings.Development.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\LICENSE">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Wonderking\Wonderking.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
34
Continuity.AuthServer/DB/Documents/Account.cs
Normal file
34
Continuity.AuthServer/DB/Documents/Account.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Continuity.AuthServer.DB.Documents;
|
||||
|
||||
[Index(nameof(Username), IsUnique = true)]
|
||||
[Index(nameof(Id), IsUnique = true)]
|
||||
public class Account
|
||||
{
|
||||
public Account(string username, byte[] password, string email, byte permissionLevel, byte[] salt)
|
||||
{
|
||||
Username = username;
|
||||
Password = password;
|
||||
Email = email;
|
||||
PermissionLevel = permissionLevel;
|
||||
Salt = salt;
|
||||
}
|
||||
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[MaxLength(20)] public string Username { get; set; }
|
||||
|
||||
[Column(TypeName = "bytea")] public byte[] Password { get; set; }
|
||||
|
||||
[EmailAddress] public string Email { get; set; }
|
||||
public byte PermissionLevel { get; set; }
|
||||
[Column(TypeName = "bytea")] public byte[] Salt { get; set; }
|
||||
public virtual ICollection<Character> Characters { get; set; }
|
||||
}
|
45
Continuity.AuthServer/DB/Documents/Character.cs
Normal file
45
Continuity.AuthServer/DB/Documents/Character.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Wonderking.Game.Data.Character;
|
||||
using Wonderking.Packets.Outgoing.Data;
|
||||
|
||||
namespace Continuity.AuthServer.DB.Documents;
|
||||
|
||||
[Index(nameof(Name), IsUnique = true)]
|
||||
[Index(nameof(Id), IsUnique = true)]
|
||||
public class Character
|
||||
{
|
||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
||||
[Required]
|
||||
public virtual Account Account { get; set; }
|
||||
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public ushort MapId { get; set; }
|
||||
|
||||
[MaxLength(20)] public string Name { get; set; }
|
||||
|
||||
public short LastXCoordinate { get; set; }
|
||||
public short LastYCoordinate { get; set; }
|
||||
public PvPLevel PvPLevel { get; set; }
|
||||
public Gender Gender { get; set; }
|
||||
public long Experience { get; set; }
|
||||
public byte Level { get; set; }
|
||||
|
||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
||||
public virtual ICollection<InventoryItem> InventoryItems { get; set; }
|
||||
|
||||
public BaseStats BaseStats { get; set; }
|
||||
|
||||
public JobData JobData { get; set; }
|
||||
public int Health { get; set; }
|
||||
public int Mana { get; set; }
|
||||
|
||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
||||
public virtual GuildMember GuildMember { get; set; }
|
||||
}
|
22
Continuity.AuthServer/DB/Documents/Guild.cs
Normal file
22
Continuity.AuthServer/DB/Documents/Guild.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Continuity.AuthServer.DB.Documents;
|
||||
|
||||
[Index(nameof(Name), IsUnique = true)]
|
||||
[Index(nameof(Id), IsUnique = true)]
|
||||
public class Guild
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[MaxLength(16)] public string Name { get; set; }
|
||||
public string Notice { get; set; }
|
||||
|
||||
[DeleteBehavior(DeleteBehavior.Cascade)]
|
||||
public virtual ICollection<GuildMember> GuildMembers { get; set; }
|
||||
}
|
31
Continuity.AuthServer/DB/Documents/GuildMember.cs
Normal file
31
Continuity.AuthServer/DB/Documents/GuildMember.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Continuity.AuthServer.DB.Documents;
|
||||
|
||||
[Index(nameof(Id), IsUnique = true)]
|
||||
public class GuildMember
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public virtual Guid CharacterId { get; set; }
|
||||
|
||||
[DeleteBehavior(DeleteBehavior.Restrict)]
|
||||
[ForeignKey(nameof(CharacterId))]
|
||||
[Required]
|
||||
public virtual Character Character { get; set; }
|
||||
|
||||
public virtual Guid GuildId { get; set; }
|
||||
|
||||
[DeleteBehavior(DeleteBehavior.Restrict)]
|
||||
[ForeignKey(nameof(GuildId))]
|
||||
[Required]
|
||||
public virtual Guild Guild { get; set; }
|
||||
|
||||
public GuildRank Rank { get; set; }
|
||||
}
|
13
Continuity.AuthServer/DB/Documents/GuildRank.cs
Normal file
13
Continuity.AuthServer/DB/Documents/GuildRank.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
namespace Continuity.AuthServer.DB.Documents;
|
||||
|
||||
public enum GuildRank : byte
|
||||
{
|
||||
Initiate = 0,
|
||||
Member = 1,
|
||||
Veteran = 2,
|
||||
Elite = 3,
|
||||
Officer = 4,
|
||||
Master = 5
|
||||
}
|
31
Continuity.AuthServer/DB/Documents/InventoryItem.cs
Normal file
31
Continuity.AuthServer/DB/Documents/InventoryItem.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Continuity.AuthServer.DB.Documents;
|
||||
|
||||
public class InventoryItem
|
||||
{
|
||||
[DeleteBehavior(DeleteBehavior.Restrict)]
|
||||
[Required]
|
||||
public virtual Character Character { get; set; }
|
||||
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public ushort ItemId { get; set; }
|
||||
public ushort Count { get; set; }
|
||||
public byte Slot { get; set; }
|
||||
public InventoryTab InventoryTab { get; set; }
|
||||
public byte Level { get; set; }
|
||||
public byte Rarity { get; set; }
|
||||
public byte AddOption { get; set; }
|
||||
public byte AddOption2 { get; set; }
|
||||
public byte AddOption3 { get; set; }
|
||||
public short Option { get; set; }
|
||||
public short Option2 { get; set; }
|
||||
public short Option3 { get; set; }
|
||||
}
|
14
Continuity.AuthServer/DB/Documents/InventoryTab.cs
Normal file
14
Continuity.AuthServer/DB/Documents/InventoryTab.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
namespace Continuity.AuthServer.DB.Documents;
|
||||
|
||||
public enum InventoryTab : byte
|
||||
{
|
||||
WornEquipment = 0,
|
||||
WornCashEquipment = 1,
|
||||
Equipment = 2,
|
||||
Etc = 3,
|
||||
Cash = 4,
|
||||
Warehouse = 5,
|
||||
GiftBox = 6
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
@ -25,7 +26,7 @@ namespace Server.DB.Migrations
|
|||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Server.DB.Documents.Account", b =>
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder) => migrationBuilder.CreateTable(
|
||||
name: "Accounts",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Username = table.Column<string>(type: "varchar(20)", nullable: false),
|
||||
Password = table.Column<byte[]>(type: "bytea", nullable: false),
|
||||
Email = table.Column<string>(type: "text", nullable: false),
|
||||
PermissionLevel = table.Column<byte>(type: "smallint", nullable: false),
|
||||
Salt = table.Column<byte[]>(type: "bytea", nullable: false)
|
||||
},
|
||||
constraints: table => table.PrimaryKey("PK_Accounts", x => x.Id));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder) => migrationBuilder.DropTable(
|
||||
name: "Accounts");
|
||||
}
|
116
Continuity.AuthServer/DB/Migrations/20230817230423_CharacterDataDraft.Designer.cs
generated
Normal file
116
Continuity.AuthServer/DB/Migrations/20230817230423_CharacterDataDraft.Designer.cs
generated
Normal file
|
@ -0,0 +1,116 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20230817230423_CharacterDataDraft")]
|
||||
partial class CharacterDataDraft
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "7.0.10")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("ServerId")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Account");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class CharacterDataDraft : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Username",
|
||||
table: "Accounts",
|
||||
type: "varchar(20)",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "varchar(20)");
|
||||
|
||||
migrationBuilder.AlterColumn<byte[]>(
|
||||
name: "Salt",
|
||||
table: "Accounts",
|
||||
type: "bytea",
|
||||
nullable: true,
|
||||
oldClrType: typeof(byte[]),
|
||||
oldType: "bytea");
|
||||
|
||||
migrationBuilder.AlterColumn<byte[]>(
|
||||
name: "Password",
|
||||
table: "Accounts",
|
||||
type: "bytea",
|
||||
nullable: true,
|
||||
oldClrType: typeof(byte[]),
|
||||
oldType: "bytea");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Email",
|
||||
table: "Accounts",
|
||||
type: "text",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Characters",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
ServerId = table.Column<byte>(type: "smallint", nullable: false),
|
||||
AccountId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
MapId = table.Column<int>(type: "integer", nullable: false),
|
||||
Name = table.Column<string>(type: "varchar(20)", nullable: true),
|
||||
LastXCoordinate = table.Column<short>(type: "smallint", nullable: false),
|
||||
LastYCoordinate = table.Column<short>(type: "smallint", nullable: false),
|
||||
PvPLevel = table.Column<byte>(type: "smallint", nullable: false),
|
||||
Gender = table.Column<byte>(type: "smallint", nullable: false),
|
||||
Experience = table.Column<long>(type: "bigint", nullable: false),
|
||||
Level = table.Column<byte>(type: "smallint", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Characters", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
column: x => x.AccountId,
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Characters_AccountId",
|
||||
table: "Characters",
|
||||
column: "AccountId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Characters");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Username",
|
||||
table: "Accounts",
|
||||
type: "varchar(20)",
|
||||
nullable: false,
|
||||
defaultValue: "",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "varchar(20)",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<byte[]>(
|
||||
name: "Salt",
|
||||
table: "Accounts",
|
||||
type: "bytea",
|
||||
nullable: false,
|
||||
defaultValue: Array.Empty<byte>(),
|
||||
oldClrType: typeof(byte[]),
|
||||
oldType: "bytea",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<byte[]>(
|
||||
name: "Password",
|
||||
table: "Accounts",
|
||||
type: "bytea",
|
||||
nullable: false,
|
||||
defaultValue: Array.Empty<byte>(),
|
||||
oldClrType: typeof(byte[]),
|
||||
oldType: "bytea",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Email",
|
||||
table: "Accounts",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: "",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldNullable: true);
|
||||
}
|
||||
}
|
184
Continuity.AuthServer/DB/Migrations/20231108143729_AddInventoryToCharacter.Designer.cs
generated
Normal file
184
Continuity.AuthServer/DB/Migrations/20231108143729_AddInventoryToCharacter.Designer.cs
generated
Normal file
|
@ -0,0 +1,184 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231108143729_AddInventoryToCharacter")]
|
||||
partial class AddInventoryToCharacter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "7.0.13")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("ServerId")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("ItemId")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("ItemType")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Account");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class AddInventoryToCharacter : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "InventoryItem",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
CharacterId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
ItemId = table.Column<short>(type: "smallint", nullable: false),
|
||||
Count = table.Column<int>(type: "integer", nullable: false),
|
||||
Slot = table.Column<byte>(type: "smallint", nullable: false),
|
||||
ItemType = table.Column<byte>(type: "smallint", nullable: false),
|
||||
Level = table.Column<byte>(type: "smallint", nullable: false),
|
||||
Rarity = table.Column<byte>(type: "smallint", nullable: false),
|
||||
AddOption = table.Column<byte>(type: "smallint", nullable: false),
|
||||
AddOption2 = table.Column<byte>(type: "smallint", nullable: false),
|
||||
AddOption3 = table.Column<byte>(type: "smallint", nullable: false),
|
||||
Option = table.Column<short>(type: "smallint", nullable: false),
|
||||
Option2 = table.Column<short>(type: "smallint", nullable: false),
|
||||
Option3 = table.Column<short>(type: "smallint", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_InventoryItem", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_InventoryItem_Characters_CharacterId",
|
||||
column: x => x.CharacterId,
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_InventoryItem_CharacterId",
|
||||
table: "InventoryItem",
|
||||
column: "CharacterId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "InventoryItem");
|
||||
}
|
||||
}
|
250
Continuity.AuthServer/DB/Migrations/20231113192405_AdditionalCharacterData.Designer.cs
generated
Normal file
250
Continuity.AuthServer/DB/Migrations/20231113192405_AdditionalCharacterData.Designer.cs
generated
Normal file
|
@ -0,0 +1,250 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231113192405_AdditionalCharacterData")]
|
||||
partial class AdditionalCharacterData
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "7.0.13")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("ServerId")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("ItemType")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class AdditionalCharacterData : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "ItemId",
|
||||
table: "InventoryItem",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
oldClrType: typeof(short),
|
||||
oldType: "smallint");
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "BaseStats_Dexterity",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "BaseStats_Intelligence",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "BaseStats_Luck",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "BaseStats_Strength",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "BaseStats_Vitality",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<short>(
|
||||
name: "BaseStats_Wisdom",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Health",
|
||||
table: "Characters",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<byte>(
|
||||
name: "JobData_FirstJob",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<byte>(
|
||||
name: "JobData_FourthJob",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<byte>(
|
||||
name: "JobData_SecondJob",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<byte>(
|
||||
name: "JobData_ThirdJob",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Mana",
|
||||
table: "Characters",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BaseStats_Dexterity",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BaseStats_Intelligence",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BaseStats_Luck",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BaseStats_Strength",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BaseStats_Vitality",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BaseStats_Wisdom",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Health",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "JobData_FirstJob",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "JobData_FourthJob",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "JobData_SecondJob",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "JobData_ThirdJob",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Mana",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.AlterColumn<short>(
|
||||
name: "ItemId",
|
||||
table: "InventoryItem",
|
||||
type: "smallint",
|
||||
nullable: false,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "integer");
|
||||
}
|
||||
}
|
334
Continuity.AuthServer/DB/Migrations/20231114203409_AddGuildData.Designer.cs
generated
Normal file
334
Continuity.AuthServer/DB/Migrations/20231114203409_AddGuildData.Designer.cs
generated
Normal file
|
@ -0,0 +1,334 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231114203409_AddGuildData")]
|
||||
partial class AddGuildData
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("ServerId")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("ItemType")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany()
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class AddGuildData : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "GuildId",
|
||||
table: "Characters",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Guild",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Name = table.Column<string>(type: "text", nullable: true),
|
||||
Notice = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Guild", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GuildMember",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
CharacterId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
GuildId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Rank = table.Column<byte>(type: "smallint", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GuildMember", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
column: x => x.CharacterId,
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_GuildMember_Guild_GuildId",
|
||||
column: x => x.GuildId,
|
||||
principalTable: "Guild",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Characters_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Characters_Name",
|
||||
table: "Characters",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Accounts_Username",
|
||||
table: "Accounts",
|
||||
column: "Username",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildMember_CharacterId",
|
||||
table: "GuildMember",
|
||||
column: "CharacterId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildMember_GuildId",
|
||||
table: "GuildMember",
|
||||
column: "GuildId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Guild_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId",
|
||||
principalTable: "Guild",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Guild_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GuildMember");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Guild");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Characters_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Characters_Name",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Accounts_Username",
|
||||
table: "Accounts");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GuildId",
|
||||
table: "Characters");
|
||||
}
|
||||
}
|
334
Continuity.AuthServer/DB/Migrations/20231115174714_GuildIsNotRequired.Designer.cs
generated
Normal file
334
Continuity.AuthServer/DB/Migrations/20231115174714_GuildIsNotRequired.Designer.cs
generated
Normal file
|
@ -0,0 +1,334 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231115174714_GuildIsNotRequired")]
|
||||
partial class GuildIsNotRequired
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("ServerId")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany()
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class GuildIsNotRequired : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "ItemType",
|
||||
table: "InventoryItem",
|
||||
newName: "InventoryTab");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "InventoryTab",
|
||||
table: "InventoryItem",
|
||||
newName: "ItemType");
|
||||
}
|
||||
}
|
323
Continuity.AuthServer/DB/Migrations/20231115183824_SwitchToDataAnnotations.Designer.cs
generated
Normal file
323
Continuity.AuthServer/DB/Migrations/20231115183824_SwitchToDataAnnotations.Designer.cs
generated
Normal file
|
@ -0,0 +1,323 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231115183824_SwitchToDataAnnotations")]
|
||||
partial class SwitchToDataAnnotations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId");
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId");
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany()
|
||||
.HasForeignKey("CharacterId");
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId");
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class SwitchToDataAnnotations : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Guild_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Guild_GuildId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Characters_Name",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ServerId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "GuildId",
|
||||
table: "GuildMember",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CharacterId",
|
||||
table: "GuildMember",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "Characters",
|
||||
type: "text",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "varchar(20)",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "GuildId",
|
||||
table: "Characters",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "AccountId",
|
||||
table: "Characters",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Accounts_Id",
|
||||
table: "Accounts",
|
||||
column: "Id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters",
|
||||
column: "AccountId",
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Guild_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId",
|
||||
principalTable: "Guild",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
table: "GuildMember",
|
||||
column: "CharacterId",
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Guild_GuildId",
|
||||
table: "GuildMember",
|
||||
column: "GuildId",
|
||||
principalTable: "Guild",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Guild_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Guild_GuildId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Accounts_Id",
|
||||
table: "Accounts");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "GuildId",
|
||||
table: "GuildMember",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CharacterId",
|
||||
table: "GuildMember",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "Characters",
|
||||
type: "varchar(20)",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "GuildId",
|
||||
table: "Characters",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "AccountId",
|
||||
table: "Characters",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<byte>(
|
||||
name: "ServerId",
|
||||
table: "Characters",
|
||||
type: "smallint",
|
||||
nullable: false,
|
||||
defaultValue: (byte)0);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Characters_Name",
|
||||
table: "Characters",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters",
|
||||
column: "AccountId",
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Guild_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId",
|
||||
principalTable: "Guild",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
table: "GuildMember",
|
||||
column: "CharacterId",
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Guild_GuildId",
|
||||
table: "GuildMember",
|
||||
column: "GuildId",
|
||||
principalTable: "Guild",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
334
Continuity.AuthServer/DB/Migrations/20231116110504_DBPoolingAndLazyLoadingSupport.Designer.cs
generated
Normal file
334
Continuity.AuthServer/DB/Migrations/20231116110504_DBPoolingAndLazyLoadingSupport.Designer.cs
generated
Normal file
|
@ -0,0 +1,334 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231116110504_DBPoolingAndLazyLoadingSupport")]
|
||||
partial class DBPoolingAndLazyLoadingSupport
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Proxies:ChangeTracking", false)
|
||||
.HasAnnotation("Proxies:CheckEquality", false)
|
||||
.HasAnnotation("Proxies:LazyLoading", true)
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId");
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId");
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany()
|
||||
.HasForeignKey("CharacterId");
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId");
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class DBPoolingAndLazyLoadingSupport : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "Characters",
|
||||
type: "varchar(20)",
|
||||
maxLength: 20,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Characters_Id",
|
||||
table: "Characters",
|
||||
column: "Id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Characters_Name",
|
||||
table: "Characters",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Characters_Id",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Characters_Name",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "Characters",
|
||||
type: "text",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "varchar(20)",
|
||||
oldMaxLength: 20,
|
||||
oldNullable: true);
|
||||
}
|
||||
}
|
338
Continuity.AuthServer/DB/Migrations/20231120162002_FixInventoryItemAsDbset.Designer.cs
generated
Normal file
338
Continuity.AuthServer/DB/Migrations/20231120162002_FixInventoryItemAsDbset.Designer.cs
generated
Normal file
|
@ -0,0 +1,338 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231120162002_FixInventoryItemAsDbset")]
|
||||
partial class FixInventoryItemAsDbset
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Proxies:ChangeTracking", false)
|
||||
.HasAnnotation("Proxies:CheckEquality", false)
|
||||
.HasAnnotation("Proxies:LazyLoading", true)
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Guilds");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId");
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId");
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "dexterity");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "intelligence");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "luck");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "strength");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "vitality");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "wisdom");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany()
|
||||
.HasForeignKey("CharacterId");
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId");
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId");
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class FixInventoryItemAsDbset : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Guild_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Guild_GuildId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_InventoryItem_Characters_CharacterId",
|
||||
table: "InventoryItem");
|
||||
|
||||
migrationBuilder.DropPrimaryKey(
|
||||
name: "PK_InventoryItem",
|
||||
table: "InventoryItem");
|
||||
|
||||
migrationBuilder.DropPrimaryKey(
|
||||
name: "PK_Guild",
|
||||
table: "Guild");
|
||||
|
||||
migrationBuilder.RenameTable(
|
||||
name: "InventoryItem",
|
||||
newName: "InventoryItems");
|
||||
|
||||
migrationBuilder.RenameTable(
|
||||
name: "Guild",
|
||||
newName: "Guilds");
|
||||
|
||||
migrationBuilder.RenameIndex(
|
||||
name: "IX_InventoryItem_CharacterId",
|
||||
table: "InventoryItems",
|
||||
newName: "IX_InventoryItems_CharacterId");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CharacterId",
|
||||
table: "InventoryItems",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AddPrimaryKey(
|
||||
name: "PK_InventoryItems",
|
||||
table: "InventoryItems",
|
||||
column: "Id");
|
||||
|
||||
migrationBuilder.AddPrimaryKey(
|
||||
name: "PK_Guilds",
|
||||
table: "Guilds",
|
||||
column: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Guilds_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId",
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Guilds_GuildId",
|
||||
table: "GuildMember",
|
||||
column: "GuildId",
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_InventoryItems_Characters_CharacterId",
|
||||
table: "InventoryItems",
|
||||
column: "CharacterId",
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Guilds_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Guilds_GuildId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_InventoryItems_Characters_CharacterId",
|
||||
table: "InventoryItems");
|
||||
|
||||
migrationBuilder.DropPrimaryKey(
|
||||
name: "PK_InventoryItems",
|
||||
table: "InventoryItems");
|
||||
|
||||
migrationBuilder.DropPrimaryKey(
|
||||
name: "PK_Guilds",
|
||||
table: "Guilds");
|
||||
|
||||
migrationBuilder.RenameTable(
|
||||
name: "InventoryItems",
|
||||
newName: "InventoryItem");
|
||||
|
||||
migrationBuilder.RenameTable(
|
||||
name: "Guilds",
|
||||
newName: "Guild");
|
||||
|
||||
migrationBuilder.RenameIndex(
|
||||
name: "IX_InventoryItems_CharacterId",
|
||||
table: "InventoryItem",
|
||||
newName: "IX_InventoryItem_CharacterId");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CharacterId",
|
||||
table: "InventoryItem",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddPrimaryKey(
|
||||
name: "PK_InventoryItem",
|
||||
table: "InventoryItem",
|
||||
column: "Id");
|
||||
|
||||
migrationBuilder.AddPrimaryKey(
|
||||
name: "PK_Guild",
|
||||
table: "Guild",
|
||||
column: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Guild_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId",
|
||||
principalTable: "Guild",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Guild_GuildId",
|
||||
table: "GuildMember",
|
||||
column: "GuildId",
|
||||
principalTable: "Guild",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_InventoryItem_Characters_CharacterId",
|
||||
table: "InventoryItem",
|
||||
column: "CharacterId",
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
339
Continuity.AuthServer/DB/Migrations/20231121205726_MissingCascadeDeletionOnCharacter.Designer.cs
generated
Normal file
339
Continuity.AuthServer/DB/Migrations/20231121205726_MissingCascadeDeletionOnCharacter.Designer.cs
generated
Normal file
|
@ -0,0 +1,339 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231121205726_MissingCascadeDeletionOnCharacter")]
|
||||
partial class MissingCascadeDeletionOnCharacter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Proxies:ChangeTracking", false)
|
||||
.HasAnnotation("Proxies:CheckEquality", false)
|
||||
.HasAnnotation("Proxies:LazyLoading", true)
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Guilds");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId");
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId");
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "dexterity");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "intelligence");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "luck");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "strength");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "vitality");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "wisdom");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany()
|
||||
.HasForeignKey("CharacterId");
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId");
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class MissingCascadeDeletionOnCharacter : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_InventoryItems_Characters_CharacterId",
|
||||
table: "InventoryItems");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_InventoryItems_Characters_CharacterId",
|
||||
table: "InventoryItems",
|
||||
column: "CharacterId",
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_InventoryItems_Characters_CharacterId",
|
||||
table: "InventoryItems");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_InventoryItems_Characters_CharacterId",
|
||||
table: "InventoryItems",
|
||||
column: "CharacterId",
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
}
|
353
Continuity.AuthServer/DB/Migrations/20231122064508_IndexingAndVariousOtherAnnotations.Designer.cs
generated
Normal file
353
Continuity.AuthServer/DB/Migrations/20231122064508_IndexingAndVariousOtherAnnotations.Designer.cs
generated
Normal file
|
@ -0,0 +1,353 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231122064508_IndexingAndVariousOtherAnnotations")]
|
||||
partial class IndexingAndVariousOtherAnnotations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Proxies:ChangeTracking", false)
|
||||
.HasAnnotation("Proxies:CheckEquality", false)
|
||||
.HasAnnotation("Proxies:LazyLoading", true)
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(16)
|
||||
.HasColumnType("character varying(16)");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Guilds");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "dexterity");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "intelligence");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "luck");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "strength");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "vitality");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "wisdom");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany()
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class IndexingAndVariousOtherAnnotations : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Guilds_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Guilds_GuildId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "Guilds",
|
||||
type: "character varying(16)",
|
||||
maxLength: 16,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "text",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "Characters",
|
||||
type: "character varying(20)",
|
||||
maxLength: 20,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "varchar(20)",
|
||||
oldMaxLength: 20,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Username",
|
||||
table: "Accounts",
|
||||
type: "character varying(20)",
|
||||
maxLength: 20,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "varchar(20)",
|
||||
oldMaxLength: 20,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Guilds_Id",
|
||||
table: "Guilds",
|
||||
column: "Id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Guilds_Name",
|
||||
table: "Guilds",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildMember_Id",
|
||||
table: "GuildMember",
|
||||
column: "Id",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters",
|
||||
column: "AccountId",
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Guilds_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId",
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
table: "GuildMember",
|
||||
column: "CharacterId",
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Guilds_GuildId",
|
||||
table: "GuildMember",
|
||||
column: "GuildId",
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Guilds_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GuildMember_Guilds_GuildId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Guilds_Id",
|
||||
table: "Guilds");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Guilds_Name",
|
||||
table: "Guilds");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_GuildMember_Id",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "Guilds",
|
||||
type: "text",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(16)",
|
||||
oldMaxLength: 16,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Name",
|
||||
table: "Characters",
|
||||
type: "varchar(20)",
|
||||
maxLength: 20,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(20)",
|
||||
oldMaxLength: 20,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Username",
|
||||
table: "Accounts",
|
||||
type: "varchar(20)",
|
||||
maxLength: 20,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "character varying(20)",
|
||||
oldMaxLength: 20,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters",
|
||||
column: "AccountId",
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Guilds_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId",
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Characters_CharacterId",
|
||||
table: "GuildMember",
|
||||
column: "CharacterId",
|
||||
principalTable: "Characters",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GuildMember_Guilds_GuildId",
|
||||
table: "GuildMember",
|
||||
column: "GuildId",
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
}
|
368
Continuity.AuthServer/DB/Migrations/20231122091030_VariousDeletionBehaviours.Designer.cs
generated
Normal file
368
Continuity.AuthServer/DB/Migrations/20231122091030_VariousDeletionBehaviours.Designer.cs
generated
Normal file
|
@ -0,0 +1,368 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231122091030_VariousDeletionBehaviours")]
|
||||
partial class VariousDeletionBehaviours
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Proxies:ChangeTracking", false)
|
||||
.HasAnnotation("Proxies:CheckEquality", false)
|
||||
.HasAnnotation("Proxies:LazyLoading", true)
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("GuildMemberId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GuildMemberId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(16)
|
||||
.HasColumnType("character varying(16)");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Guilds");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid?>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.GuildMember", "GuildMember")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildMemberId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "dexterity");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "intelligence");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "luck");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "strength");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "vitality");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "wisdom");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany()
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class VariousDeletionBehaviours : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "GuildMemberId",
|
||||
table: "Accounts",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Accounts_GuildMemberId",
|
||||
table: "Accounts",
|
||||
column: "GuildMemberId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Accounts_GuildMember_GuildMemberId",
|
||||
table: "Accounts",
|
||||
column: "GuildMemberId",
|
||||
principalTable: "GuildMember",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters",
|
||||
column: "AccountId",
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Accounts_GuildMember_GuildMemberId",
|
||||
table: "Accounts");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Accounts_GuildMemberId",
|
||||
table: "Accounts");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GuildMemberId",
|
||||
table: "Accounts");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Accounts_AccountId",
|
||||
table: "Characters",
|
||||
column: "AccountId",
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
}
|
348
Continuity.AuthServer/DB/Migrations/20231125112400_FixEntityRelationships.Designer.cs
generated
Normal file
348
Continuity.AuthServer/DB/Migrations/20231125112400_FixEntityRelationships.Designer.cs
generated
Normal file
|
@ -0,0 +1,348 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
[Migration("20231125112400_FixEntityRelationships")]
|
||||
partial class FixEntityRelationships
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Proxies:ChangeTracking", false)
|
||||
.HasAnnotation("Proxies:CheckEquality", false)
|
||||
.HasAnnotation("Proxies:LazyLoading", true)
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(16)
|
||||
.HasColumnType("character varying(16)");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Guilds");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "dexterity");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "intelligence");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "luck");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "strength");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "vitality");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "wisdom");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithOne("GuildMember")
|
||||
.HasForeignKey("Continuity.AuthServer.DB.Documents.GuildMember", "CharacterId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("GuildMember");
|
||||
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class FixEntityRelationships : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Accounts_GuildMember_GuildMemberId",
|
||||
table: "Accounts");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Characters_Guilds_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_GuildMember_CharacterId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Characters_GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Accounts_GuildMemberId",
|
||||
table: "Accounts");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GuildId",
|
||||
table: "Characters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GuildMemberId",
|
||||
table: "Accounts");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CharacterId",
|
||||
table: "InventoryItems",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "GuildId",
|
||||
table: "GuildMember",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CharacterId",
|
||||
table: "GuildMember",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "AccountId",
|
||||
table: "Characters",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildMember_CharacterId",
|
||||
table: "GuildMember",
|
||||
column: "CharacterId",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_GuildMember_CharacterId",
|
||||
table: "GuildMember");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CharacterId",
|
||||
table: "InventoryItems",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "GuildId",
|
||||
table: "GuildMember",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "CharacterId",
|
||||
table: "GuildMember",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "AccountId",
|
||||
table: "Characters",
|
||||
type: "uuid",
|
||||
nullable: true,
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "uuid");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "GuildId",
|
||||
table: "Characters",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "GuildMemberId",
|
||||
table: "Accounts",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildMember_CharacterId",
|
||||
table: "GuildMember",
|
||||
column: "CharacterId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Characters_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Accounts_GuildMemberId",
|
||||
table: "Accounts",
|
||||
column: "GuildMemberId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Accounts_GuildMember_GuildMemberId",
|
||||
table: "Accounts",
|
||||
column: "GuildMemberId",
|
||||
principalTable: "GuildMember",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Characters_Guilds_GuildId",
|
||||
table: "Characters",
|
||||
column: "GuildId",
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,345 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
partial class WonderkingContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("Proxies:ChangeTracking", false)
|
||||
.HasAnnotation("Proxies:CheckEquality", false)
|
||||
.HasAnnotation("Proxies:LazyLoading", true)
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long>("Experience")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<byte>("Gender")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Health")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<short>("LastXCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("LastYCoordinate")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("Mana")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MapId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<byte>("PvPLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(16)
|
||||
.HasColumnType("character varying(16)");
|
||||
|
||||
b.Property<string>("Notice")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Guilds");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("GuildId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("Rank")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("Id")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GuildMember");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<byte>("AddOption")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("AddOption3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("InventoryTab")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<byte>("Level")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option2")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<short>("Option3")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Rarity")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte>("Slot")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CharacterId");
|
||||
|
||||
b.ToTable("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Account", "Account")
|
||||
.WithMany("Characters")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.BaseStats", "BaseStats", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<short>("Dexterity")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "dexterity");
|
||||
|
||||
b1.Property<short>("Intelligence")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "intelligence");
|
||||
|
||||
b1.Property<short>("Luck")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "luck");
|
||||
|
||||
b1.Property<short>("Strength")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "strength");
|
||||
|
||||
b1.Property<short>("Vitality")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "vitality");
|
||||
|
||||
b1.Property<short>("Wisdom")
|
||||
.HasColumnType("smallint")
|
||||
.HasAnnotation("Relational:JsonPropertyName", "wisdom");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.OwnsOne("Wonderking.Packets.Outgoing.Data.JobData", "JobData", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("CharacterId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<byte>("FirstJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("FourthJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("SecondJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.Property<byte>("ThirdJob")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b1.HasKey("CharacterId");
|
||||
|
||||
b1.ToTable("Characters");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("CharacterId");
|
||||
});
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("BaseStats");
|
||||
|
||||
b.Navigation("JobData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithOne("GuildMember")
|
||||
.HasForeignKey("Continuity.AuthServer.DB.Documents.GuildMember", "CharacterId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Guild", "Guild")
|
||||
.WithMany("GuildMembers")
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.InventoryItem", b =>
|
||||
{
|
||||
b.HasOne("Continuity.AuthServer.DB.Documents.Character", "Character")
|
||||
.WithMany("InventoryItems")
|
||||
.HasForeignKey("CharacterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Character");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Navigation("Characters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Character", b =>
|
||||
{
|
||||
b.Navigation("GuildMember");
|
||||
|
||||
b.Navigation("InventoryItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Continuity.AuthServer.DB.Documents.Guild", b =>
|
||||
{
|
||||
b.Navigation("GuildMembers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
19
Continuity.AuthServer/DB/WonderkingContext.cs
Normal file
19
Continuity.AuthServer/DB/WonderkingContext.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Continuity.AuthServer.DB.Documents;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Continuity.AuthServer.DB;
|
||||
|
||||
public class WonderkingContext : DbContext
|
||||
{
|
||||
public WonderkingContext([NotNull] DbContextOptions options) : base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public DbSet<Account> Accounts { get; set; }
|
||||
public DbSet<Character> Characters { get; set; }
|
||||
public DbSet<InventoryItem> InventoryItems { get; set; }
|
||||
public DbSet<Guild> Guilds { get; set; }
|
||||
}
|
27
Continuity.AuthServer/Dockerfile
Normal file
27
Continuity.AuthServer/Dockerfile
Normal file
|
@ -0,0 +1,27 @@
|
|||
FROM mcr.microsoft.com/dotnet/runtime:8.0-alpine AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
|
||||
ARG TARGETARCH
|
||||
ENV TZ=Etc/UTC
|
||||
ENV DOTNET_TieredPGO=1
|
||||
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
|
||||
|
||||
RUN echo "Target: $TARGETARCH" && echo "Build: $BUILDPLATFORM"
|
||||
WORKDIR /src
|
||||
COPY ["Continuity.AuthServer/Continuity.AuthServer.csproj", "Continuity.AuthServer/"]
|
||||
COPY ["Wonderking/Wonderking.csproj", "Wonderking/"]
|
||||
RUN dotnet restore "Wonderking/Wonderking.csproj" -a $TARGETARCH && dotnet restore "Continuity.AuthServer/Continuity.AuthServer.csproj" -a $TARGETARCH
|
||||
COPY . .
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "Continuity.AuthServer/Continuity.AuthServer.csproj" -c Release -a $TARGETARCH --no-restore -f net8.0 -o /app
|
||||
COPY ../config /app/config
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
USER $APP_UID
|
||||
ENTRYPOINT ["./Continuity.AuthServer"]
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Continuity.AuthServer.PacketHandlers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Continuity.AuthServer.LoggerMessages;
|
||||
|
||||
internal static partial class LoginHandlerLoggerMessages
|
||||
{
|
||||
[LoggerMessage(EventId = 0, Level = LogLevel.Information,
|
||||
Message = "Login data: Username {Username} & Password {Password}")]
|
||||
public static partial void LoginData(this ILogger<LoginHandler> logger, string username, string password);
|
||||
|
||||
[LoggerMessage(EventId = 1, Level = LogLevel.Information,
|
||||
Message = "Requested account for user: {Username} does not exist")]
|
||||
public static partial void RequestedAccountDoesNotExist(this ILogger<LoginHandler> logger, string username);
|
||||
}
|
51
Continuity.AuthServer/LoggerMessages/PacketLoggerMessages.cs
Normal file
51
Continuity.AuthServer/LoggerMessages/PacketLoggerMessages.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Wonderking.Packets;
|
||||
|
||||
namespace Continuity.AuthServer.LoggerMessages;
|
||||
|
||||
internal static partial class PacketLoggerMessages
|
||||
{
|
||||
[LoggerMessage(EventId = 0, Level = LogLevel.Information,
|
||||
Message = "Packet creation function created for {PacketID}")]
|
||||
public static partial void PacketCreationFunctionCreated(this ILogger logger, OperationCode packetId);
|
||||
|
||||
[LoggerMessage(EventId = 1, Level = LogLevel.Trace,
|
||||
Message = "Packet with ID: {PacketID} has been added as {PacketName}")]
|
||||
public static partial void PacketWithIdAdded(this ILogger logger, OperationCode packetId, string packetName);
|
||||
|
||||
[LoggerMessage(EventId = 2, Level = LogLevel.Trace,
|
||||
Message = "PacketHandler with ID: {PacketID} has been added as {PacketName}")]
|
||||
public static partial void PacketHandlerWithIdAdded(this ILogger logger, OperationCode packetId,
|
||||
[CanBeNull] string packetName);
|
||||
|
||||
[LoggerMessage(EventId = 3, Level = LogLevel.Information,
|
||||
Message = "Packet with ID: {PacketID} has been received")]
|
||||
public static partial void PacketReceived(this ILogger logger, OperationCode packetId);
|
||||
|
||||
[LoggerMessage(EventId = 4, Level = LogLevel.Trace,
|
||||
Message = "[{SessionID}] Packet with ID: {PacketID} is being dequeued")]
|
||||
public static partial void PacketDequeued(this ILogger logger, Guid sessionId, OperationCode packetId);
|
||||
|
||||
[LoggerMessage(EventId = 5, Level = LogLevel.Information,
|
||||
Message = "Couldn't find Packet type for Id: {PacketID}")]
|
||||
public static partial void PacketTypeNotFound(this ILogger logger, OperationCode packetId);
|
||||
|
||||
[LoggerMessage(EventId = 6, Level = LogLevel.Trace,
|
||||
Message = "[{SessionID}] Packet with ID: {PacketID} has finished")]
|
||||
public static partial void PacketFinished(this ILogger logger, Guid sessionId, OperationCode packetId);
|
||||
|
||||
[LoggerMessage(EventId = 7, Level = LogLevel.Critical,
|
||||
Message = "No PacketHandlers have been found")]
|
||||
public static partial void NoPacketHandlersFound(this ILogger logger);
|
||||
|
||||
[LoggerMessage(EventId = 8, Level = LogLevel.Trace,
|
||||
Message = "Packet data {PacketData}")]
|
||||
public static partial void PacketData(this ILogger logger, string packetData);
|
||||
|
||||
[LoggerMessage(EventId = 9, Level = LogLevel.Critical,
|
||||
Message = "No Packets have been found")]
|
||||
public static partial void NoPacketsFound(this ILogger logger);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Continuity.AuthServer.DB.Documents;
|
||||
using Wonderking.Game.Data.Character;
|
||||
using Wonderking.Packets.Outgoing.Data;
|
||||
|
||||
namespace Continuity.AuthServer.PacketHandlers;
|
||||
|
||||
public partial class ChannelSelectionHandler
|
||||
{
|
||||
private sealed record InventoryItemProjection(ushort ItemId, byte Slot, InventoryTab InventoryTab);
|
||||
|
||||
private sealed record CharacterDataProjection(
|
||||
string Name,
|
||||
JobData JobData,
|
||||
Gender Gender,
|
||||
ushort Level,
|
||||
long Experience,
|
||||
BaseStats BaseStats,
|
||||
int Health,
|
||||
int Mana,
|
||||
IEnumerable<InventoryItemProjection> InventoryItems);
|
||||
}
|
137
Continuity.AuthServer/PacketHandlers/ChannelSelectionHandler.cs
Normal file
137
Continuity.AuthServer/PacketHandlers/ChannelSelectionHandler.cs
Normal file
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Continuity.AuthServer.DB;
|
||||
using Continuity.AuthServer.DB.Documents;
|
||||
using DotNext.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NetCoreServer;
|
||||
using Wonderking.Packets.Incoming;
|
||||
using Wonderking.Packets.Outgoing;
|
||||
using Wonderking.Packets.Outgoing.Data;
|
||||
|
||||
namespace Continuity.AuthServer.PacketHandlers;
|
||||
|
||||
public partial class ChannelSelectionHandler : IPacketHandler<ChannelSelectionPacket>
|
||||
{
|
||||
private readonly WonderkingContext _wonderkingContext;
|
||||
|
||||
public ChannelSelectionHandler(WonderkingContext wonderkingContext)
|
||||
{
|
||||
_wonderkingContext = wonderkingContext;
|
||||
}
|
||||
|
||||
public async Task HandleAsync(ChannelSelectionPacket packet, TcpSession session)
|
||||
{
|
||||
if (session is not AuthSession authSession)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ChannelSelectionResponsePacket responsePacket;
|
||||
var guildNameResponsePacket = new CharacterSelectionSetGuildNamePacket { GuildNames = Array.Empty<string>() };
|
||||
|
||||
var accountExists =
|
||||
await _wonderkingContext.Accounts.AsNoTracking().AnyAsync(a => a.Id == authSession.AccountId);
|
||||
|
||||
var amountOfCharacter = await _wonderkingContext.Characters.AsNoTracking().Include(c => c.Account)
|
||||
.Where(c => c.Account.Id == authSession.AccountId).Take(3)
|
||||
.CountAsync();
|
||||
|
||||
if (!accountExists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (amountOfCharacter > 0)
|
||||
{
|
||||
responsePacket = new ChannelSelectionResponsePacket
|
||||
{
|
||||
ChannelIsFullFlag = 0,
|
||||
Endpoint = "127.0.0.1",
|
||||
Port = 2000,
|
||||
Characters = await GetCharacterDataAsync(authSession.AccountId).ToArrayAsync()
|
||||
};
|
||||
|
||||
guildNameResponsePacket.GuildNames =
|
||||
await _wonderkingContext.Characters.AsNoTracking().Include(c => c.Account).Include(c => c.GuildMember)
|
||||
.ThenInclude(gm => gm.Guild)
|
||||
.Where(c => c.Account.Id == authSession.AccountId && c.GuildMember.Guild != null)
|
||||
.Select(c => c.GuildMember.Guild.Name).Take(3).ToArrayAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
responsePacket = new ChannelSelectionResponsePacket
|
||||
{
|
||||
ChannelIsFullFlag = 0,
|
||||
Endpoint = "127.0.0.1",
|
||||
Port = 2000,
|
||||
Characters = Array.Empty<CharacterData>()
|
||||
};
|
||||
}
|
||||
|
||||
await authSession.SendAsync(responsePacket);
|
||||
if (guildNameResponsePacket.GuildNames.Length > 0 &&
|
||||
guildNameResponsePacket.GuildNames.Select(n => n != string.Empty).Any())
|
||||
{
|
||||
await authSession.SendAsync(guildNameResponsePacket);
|
||||
}
|
||||
}
|
||||
|
||||
private static ushort[] GetItemIDsByInventoryTab(IEnumerable<InventoryItemProjection> items)
|
||||
{
|
||||
var ids = new ushort[20];
|
||||
ids.AsSpan().Clear();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item.Slot > 20)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ids[item.Slot] = item.ItemId;
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
private async IAsyncEnumerable<CharacterData> GetCharacterDataAsync(Guid accountId)
|
||||
{
|
||||
var characterDataProjections = _wonderkingContext.Characters.AsNoTracking().AsSplitQuery()
|
||||
.Include(c => c.InventoryItems).Include(c => c.Account)
|
||||
.Where(c => c.Account.Id == accountId)
|
||||
.Select(c => new CharacterDataProjection(
|
||||
c.Name,
|
||||
c.JobData,
|
||||
c.Gender,
|
||||
c.Level,
|
||||
c.Experience,
|
||||
c.BaseStats,
|
||||
c.Health,
|
||||
c.Mana,
|
||||
c.InventoryItems.Select(i =>
|
||||
new InventoryItemProjection(i.ItemId, i.Slot, i.InventoryTab))
|
||||
)).Take(3);
|
||||
|
||||
await foreach (var c in characterDataProjections)
|
||||
{
|
||||
yield return new CharacterData
|
||||
{
|
||||
Name = c.Name,
|
||||
Job = c.JobData,
|
||||
Gender = c.Gender,
|
||||
Level = c.Level,
|
||||
// TODO: Calculate instead of clamping based on max experience for level
|
||||
Experience = Math.Clamp(c.Experience, 0, 100),
|
||||
Stats = c.BaseStats,
|
||||
Health = c.Health,
|
||||
Mana = c.Mana,
|
||||
EquippedItems =
|
||||
GetItemIDsByInventoryTab(c.InventoryItems.Where(i =>
|
||||
i.InventoryTab == InventoryTab.WornEquipment)),
|
||||
EquippedCashItems = GetItemIDsByInventoryTab(c.InventoryItems.Where(i =>
|
||||
i.InventoryTab == InventoryTab.WornCashEquipment))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
176
Continuity.AuthServer/PacketHandlers/CharacterCreationHandler.cs
Normal file
176
Continuity.AuthServer/PacketHandlers/CharacterCreationHandler.cs
Normal file
|
@ -0,0 +1,176 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Continuity.AuthServer.DB;
|
||||
using Continuity.AuthServer.DB.Documents;
|
||||
using Continuity.AuthServer.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NetCoreServer;
|
||||
using Wonderking.Game.Data.Character;
|
||||
using Wonderking.Game.Mapping;
|
||||
using Wonderking.Packets.Incoming;
|
||||
using Wonderking.Packets.Outgoing;
|
||||
using Wonderking.Packets.Outgoing.Data;
|
||||
|
||||
namespace Continuity.AuthServer.PacketHandlers;
|
||||
|
||||
public class CharacterCreationHandler : IPacketHandler<CharacterCreationPacket>
|
||||
{
|
||||
private readonly CharacterStatsMappingConfiguration _characterStatsMapping;
|
||||
private readonly ItemObjectPoolService _itemObjectPoolService;
|
||||
private readonly WonderkingContext _wonderkingContext;
|
||||
|
||||
public CharacterCreationHandler(WonderkingContext wonderkingContext, ItemObjectPoolService itemObjectPoolService,
|
||||
CharacterStatsMappingConfiguration characterStatsMappingConfiguration)
|
||||
{
|
||||
_wonderkingContext = wonderkingContext;
|
||||
_itemObjectPoolService = itemObjectPoolService;
|
||||
_characterStatsMapping = characterStatsMappingConfiguration;
|
||||
}
|
||||
|
||||
public async Task HandleAsync(CharacterCreationPacket packet, TcpSession session)
|
||||
{
|
||||
if (session is not AuthSession authSession)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var account = await _wonderkingContext.Accounts.FirstOrDefaultAsync(a => a.Id == authSession.AccountId);
|
||||
|
||||
if (account is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var firstJobConfig = SelectFirstJobConfig(packet.FirstJob);
|
||||
var items = CreateDefaultItems(packet, firstJobConfig);
|
||||
|
||||
var toBeAddedCharacter = CreateDefaultCharacter(packet, account, items, firstJobConfig);
|
||||
account.Characters.Add(toBeAddedCharacter);
|
||||
await _wonderkingContext.SaveChangesAsync();
|
||||
|
||||
var character =
|
||||
new CharacterData
|
||||
{
|
||||
Name = toBeAddedCharacter.Name,
|
||||
Job = toBeAddedCharacter.JobData,
|
||||
Gender = toBeAddedCharacter.Gender,
|
||||
Level = toBeAddedCharacter.Level,
|
||||
Experience = toBeAddedCharacter.Experience,
|
||||
Stats = toBeAddedCharacter.BaseStats,
|
||||
Health = toBeAddedCharacter.Health,
|
||||
Mana = toBeAddedCharacter.Mana,
|
||||
EquippedItems =
|
||||
GetItemIDsByInventoryTab(toBeAddedCharacter.InventoryItems
|
||||
.Where(item => item.InventoryTab == InventoryTab.WornEquipment)
|
||||
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).AsEnumerable()),
|
||||
EquippedCashItems = GetItemIDsByInventoryTab(toBeAddedCharacter.InventoryItems
|
||||
.Where(item => item.InventoryTab == InventoryTab.WornCashEquipment)
|
||||
.Select(item => new Tuple<ushort, byte>(item.ItemId, item.Slot)).AsEnumerable())
|
||||
};
|
||||
|
||||
await authSession.SendAsync(new CharacterCreationResponsePacket
|
||||
{
|
||||
Character = character,
|
||||
Slot = packet.Slot,
|
||||
isDuplicate = false
|
||||
});
|
||||
}
|
||||
|
||||
private InventoryItem[] CreateDefaultItems(CharacterCreationPacket packet, JobSpecificMapping firstJobConfig)
|
||||
{
|
||||
var mappedDefaultItems = _characterStatsMapping.DefaultCharacterMapping.Items
|
||||
.Select(i => _itemObjectPoolService.GetBaseInventoryItem(i.Id, i.Quantity)).ToArray();
|
||||
|
||||
var mappedJobItems = firstJobConfig.Items
|
||||
.Select(i => _itemObjectPoolService.GetBaseInventoryItem(i.Id, i.Quantity)).ToArray();
|
||||
var defaultItems = CreateChosenItems(packet);
|
||||
InventoryItem[] items =
|
||||
[
|
||||
.. mappedDefaultItems,
|
||||
.. mappedJobItems,
|
||||
.. defaultItems
|
||||
];
|
||||
return items;
|
||||
}
|
||||
|
||||
private static Character CreateDefaultCharacter(CharacterCreationPacket packet, Account account,
|
||||
InventoryItem[] items, JobSpecificMapping firstJobConfig)
|
||||
{
|
||||
return new Character()
|
||||
{
|
||||
Account = account,
|
||||
MapId = 300,
|
||||
Name = packet.Name,
|
||||
LastXCoordinate = 113,
|
||||
LastYCoordinate = 0,
|
||||
PvPLevel = PvPLevel.None,
|
||||
Gender = packet.Gender,
|
||||
Experience = 0,
|
||||
Level = 1,
|
||||
InventoryItems = items,
|
||||
BaseStats = firstJobConfig.BaseStats,
|
||||
JobData = new JobData { FirstJob = packet.FirstJob, SecondJob = 0, ThirdJob = 0, FourthJob = 0 },
|
||||
Health = CalculateCurrentHealth(1, firstJobConfig),
|
||||
Mana = CalculateCurrentMana(1, firstJobConfig)
|
||||
};
|
||||
}
|
||||
|
||||
private JobSpecificMapping SelectFirstJobConfig(byte firstJob)
|
||||
{
|
||||
return firstJob switch
|
||||
{
|
||||
1 => _characterStatsMapping.Swordsman,
|
||||
2 => _characterStatsMapping.Mage,
|
||||
3 => _characterStatsMapping.Thief,
|
||||
4 => _characterStatsMapping.Scout,
|
||||
_ => _characterStatsMapping.Swordsman
|
||||
};
|
||||
}
|
||||
|
||||
private InventoryItem[] CreateChosenItems(CharacterCreationPacket packet)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
_itemObjectPoolService.GetBaseInventoryItem((ushort)((packet.FirstJob - 1) * 6 +
|
||||
((byte)packet.Gender - 1) * 3 +
|
||||
packet.Hair + 1)),
|
||||
_itemObjectPoolService.GetBaseInventoryItem((ushort)((packet.FirstJob - 1) * 6 +
|
||||
((byte)packet.Gender - 1) * 3 +
|
||||
packet.Eyes + 25)),
|
||||
_itemObjectPoolService.GetBaseInventoryItem((ushort)(((byte)packet.Gender - 1) * 3 +
|
||||
packet.Shirt + 49)),
|
||||
_itemObjectPoolService.GetBaseInventoryItem((ushort)(((byte)packet.Gender - 1) * 3 +
|
||||
packet.Pants + 58))
|
||||
};
|
||||
}
|
||||
|
||||
private static int CalculateCurrentHealth(ushort level, JobSpecificMapping firstJobConfig)
|
||||
{
|
||||
return (int)((level - 1) * firstJobConfig.DynamicStats.HealthPerLevel +
|
||||
firstJobConfig.BaseStats.Vitality * firstJobConfig.DynamicStats.HealthPerVitality);
|
||||
}
|
||||
|
||||
private static int CalculateCurrentMana(ushort level, JobSpecificMapping firstJobConfig)
|
||||
{
|
||||
return (int)((level - 1) * firstJobConfig.DynamicStats.ManaPerLevel +
|
||||
firstJobConfig.BaseStats.Wisdom * firstJobConfig.DynamicStats.ManaPerWisdom);
|
||||
}
|
||||
|
||||
private static ushort[] GetItemIDsByInventoryTab(IEnumerable<Tuple<ushort, byte>> items)
|
||||
{
|
||||
Span<ushort> ids = stackalloc ushort[20];
|
||||
ids.Clear();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item.Item2 > 20)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ids[item.Item2] = item.Item1;
|
||||
}
|
||||
|
||||
return ids.ToArray();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NetCoreServer;
|
||||
using Wonderking.Packets.Incoming;
|
||||
using Wonderking.Packets.Outgoing;
|
||||
|
||||
namespace Continuity.AuthServer.PacketHandlers;
|
||||
|
||||
public class CharacterDeletionHandler : IPacketHandler<CharacterDeletePacket>
|
||||
{
|
||||
private readonly WonderkingContext _wonderkingContext;
|
||||
|
||||
public CharacterDeletionHandler(WonderkingContext wonderkingContext)
|
||||
{
|
||||
_wonderkingContext = wonderkingContext;
|
||||
}
|
||||
|
||||
public async Task HandleAsync(CharacterDeletePacket packet, TcpSession session)
|
||||
{
|
||||
if (session is not AuthSession authSession)
|
||||
{
|
||||
session.Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
var character = await _wonderkingContext.Characters.FirstOrDefaultAsync(x => x.Name == packet.Name &&
|
||||
x.Account.Id == authSession.AccountId);
|
||||
|
||||
var response = new CharacterDeleteResponsePacket { HasToBeZero = 0 };
|
||||
if (character == null)
|
||||
{
|
||||
await authSession.SendAsync(response);
|
||||
return;
|
||||
}
|
||||
|
||||
_wonderkingContext.Characters.Remove(character);
|
||||
await _wonderkingContext.SaveChangesAsync();
|
||||
|
||||
await authSession.SendAsync(response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Continuity.AuthServer.PacketHandlers;
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct CharacterMappingItemEntry
|
||||
{
|
||||
public required ushort Id { get; set; }
|
||||
public required ushort Quantity { get; set; }
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using Continuity.AuthServer.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NetCoreServer;
|
||||
using Wonderking.Packets.Incoming;
|
||||
using Wonderking.Packets.Outgoing;
|
||||
|
||||
namespace Continuity.AuthServer.PacketHandlers;
|
||||
|
||||
public class CharacterNameCheckHandler : IPacketHandler<CharacterNameCheckPacket>
|
||||
{
|
||||
private readonly WonderkingContext _wonderkingContext;
|
||||
|
||||
public CharacterNameCheckHandler(WonderkingContext wonderkingContext)
|
||||
{
|
||||
_wonderkingContext = wonderkingContext;
|
||||
}
|
||||
|
||||
public async Task HandleAsync(CharacterNameCheckPacket packet, TcpSession session)
|
||||
{
|
||||
var isTaken = await _wonderkingContext.Characters.AnyAsync(c => c.Name == packet.Name);
|
||||
var responsePacket = new CharacterNameCheckPacketResponse { IsTaken = isTaken };
|
||||
if (session is AuthSession authSession)
|
||||
{
|
||||
await authSession.SendAsync(responsePacket);
|
||||
}
|
||||
}
|
||||
}
|
37
Continuity.AuthServer/PacketHandlers/IPacketHandler.cs
Normal file
37
Continuity.AuthServer/PacketHandlers/IPacketHandler.cs
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Diagnostics;
|
||||
using JetBrains.Annotations;
|
||||
using NetCoreServer;
|
||||
using Wonderking.Packets;
|
||||
|
||||
namespace Continuity.AuthServer.PacketHandlers;
|
||||
|
||||
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
|
||||
public interface IPacketHandler<in T> : IPacketHandler where T : IPacket
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public Task HandleAsync(T packet, TcpSession session);
|
||||
|
||||
async Task<bool> IPacketHandler.TryHandleAsync(IPacket packet, TcpSession session)
|
||||
{
|
||||
if (packet is not T tPacket)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using (var activity = new ActivitySource(nameof(Server)).StartActivity("HandleAsync"))
|
||||
{
|
||||
activity?.SetTag("Handler", this.ToString());
|
||||
activity?.SetTag("PacketId", packet.ToString());
|
||||
await HandleAsync(tPacket, session);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPacketHandler
|
||||
{
|
||||
Task<bool> TryHandleAsync(IPacket packet, TcpSession session);
|
||||
}
|
129
Continuity.AuthServer/PacketHandlers/LoginHandler.cs
Normal file
129
Continuity.AuthServer/PacketHandlers/LoginHandler.cs
Normal file
|
@ -0,0 +1,129 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Continuity.AuthServer.DB.Documents;
|
||||
using Continuity.AuthServer.LoggerMessages;
|
||||
using Konscious.Security.Cryptography;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetCoreServer;
|
||||
using Wonderking.Packets.Incoming;
|
||||
using Wonderking.Packets.Outgoing;
|
||||
using Wonderking.Packets.Outgoing.Data;
|
||||
|
||||
namespace Continuity.AuthServer.PacketHandlers;
|
||||
|
||||
public class LoginHandler : IPacketHandler<LoginInfoPacket>
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<LoginHandler> _logger;
|
||||
private readonly WonderkingContext _wonderkingContext;
|
||||
private static readonly ActivitySource _activitySource = new ActivitySource(nameof(Server));
|
||||
|
||||
public LoginHandler(ILogger<LoginHandler> logger, WonderkingContext wonderkingContext, IConfiguration configuration)
|
||||
{
|
||||
_logger = logger;
|
||||
_wonderkingContext = wonderkingContext;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public async Task HandleAsync(LoginInfoPacket packet, TcpSession session)
|
||||
{
|
||||
LoginResponseReason loginResponseReason;
|
||||
_logger.LoginData(packet.Username, packet.Password);
|
||||
var account = await _wonderkingContext.Accounts.FirstOrDefaultAsync(a => a.Username == packet.Username);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
if (_configuration.GetSection("Testing").GetValue<bool>("CreateAccountOnLogin"))
|
||||
{
|
||||
loginResponseReason = await CreateAccountOnLoginAsync(packet.Username, packet.Password);
|
||||
account = await _wonderkingContext.Accounts.FirstOrDefaultAsync(a => a.Username == packet.Username);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.RequestedAccountDoesNotExist(packet.Username);
|
||||
loginResponseReason = LoginResponseReason.AccountDoesNotExit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var salt = account.Salt;
|
||||
var tempPasswordBytes = await GetPasswordHashAsync(packet.Password, salt, account.Id);
|
||||
loginResponseReason = tempPasswordBytes.SequenceEqual(account.Password)
|
||||
? LoginResponseReason.Ok
|
||||
: LoginResponseReason.WrongPassword;
|
||||
}
|
||||
|
||||
var channelData = new ServerChannelData[1];
|
||||
channelData[0] = new ServerChannelData { ChannelId = 0, LoadPercentage = 0, ServerId = 0 };
|
||||
var loginResponsePacket = new LoginResponsePacket
|
||||
{
|
||||
ResponseReason = loginResponseReason,
|
||||
ChannelData = channelData.ToArray(),
|
||||
UnknownFlag = 1,
|
||||
IsGameMaster = true
|
||||
};
|
||||
|
||||
var authSession = session as AuthSession;
|
||||
if (account != null && authSession != null)
|
||||
{
|
||||
authSession.AccountId = account.Id;
|
||||
}
|
||||
|
||||
_logger.LogInformation("LoginResponsePacket: {@LoginResponsePacket}", loginResponsePacket);
|
||||
_ = authSession?.SendAsync(loginResponsePacket);
|
||||
}
|
||||
|
||||
private static async Task<byte[]> GetPasswordHashAsync(string password, byte[] salt, Guid userId)
|
||||
{
|
||||
using var activity = _activitySource.StartActivity("GetPasswordHashAsync");
|
||||
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Chea1t_Sheet.html#argon2id
|
||||
// "Use Argon2id with a minimum configuration of 19 MiB of memory, an iteration count of 2, and 1 degree of parallelism."
|
||||
var argon2Id = new Argon2id(Encoding.ASCII.GetBytes(password))
|
||||
{
|
||||
MemorySize = 1024 * 19,
|
||||
Iterations = 2,
|
||||
DegreeOfParallelism = 1,
|
||||
Salt = salt,
|
||||
AssociatedData = userId.ToByteArray()
|
||||
};
|
||||
return await argon2Id.GetBytesAsync(16);
|
||||
}
|
||||
|
||||
private async Task<LoginResponseReason> CreateAccountOnLoginAsync(string username, string password)
|
||||
{
|
||||
using var activity = _activitySource.StartActivity("CreateAccountOnLoginAsync");
|
||||
LoginResponseReason loginResponseReason;
|
||||
var transaction =
|
||||
await _wonderkingContext.Database.BeginTransactionAsync();
|
||||
await using (transaction)
|
||||
{
|
||||
try
|
||||
{
|
||||
var salt = RandomNumberGenerator.GetBytes(16);
|
||||
var finalAccount = await _wonderkingContext.Accounts.AddAsync(new Account(username,
|
||||
Array.Empty<byte>(), "", 0, salt));
|
||||
await _wonderkingContext.SaveChangesAsync();
|
||||
finalAccount.Entity.Password =
|
||||
await GetPasswordHashAsync(password, salt, finalAccount.Entity.Id);
|
||||
_wonderkingContext.Accounts.Update(finalAccount.Entity);
|
||||
loginResponseReason = LoginResponseReason.Ok;
|
||||
await _wonderkingContext.SaveChangesAsync();
|
||||
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
await transaction.RollbackAsync(); // Rollback the transaction on error
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return loginResponseReason;
|
||||
}
|
||||
}
|
|
@ -1,26 +1,29 @@
|
|||
namespace Server.Packets;
|
||||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using MassTransit;
|
||||
using Wonderking.Packets;
|
||||
|
||||
namespace Continuity.AuthServer.Packets;
|
||||
|
||||
[MessageUrn("packets")]
|
||||
public class RawPacket
|
||||
{
|
||||
public RawPacket(OperationCode operationCode, byte[] messageBody, uint aliveTime, byte unknownValue2,
|
||||
public RawPacket(OperationCode operationCode, Span<byte> messageBody, uint aliveTime, byte unknownValue2,
|
||||
byte unknownValue, Guid sessionId, AuthSession session)
|
||||
{
|
||||
this.MessageBody = messageBody;
|
||||
this.UnknownValue2 = unknownValue2;
|
||||
this.UnknownValue = unknownValue;
|
||||
this.SessionId = sessionId;
|
||||
this.Session = session;
|
||||
this.OperationCode = operationCode;
|
||||
MessageBody = messageBody.ToArray();
|
||||
UnknownValue2 = unknownValue2;
|
||||
UnknownValue = unknownValue;
|
||||
SessionId = sessionId;
|
||||
Session = session;
|
||||
OperationCode = operationCode;
|
||||
/*
|
||||
* 20s = 5
|
||||
* 15s = 4
|
||||
* 10s = 3
|
||||
* client alive time * 5s => uptime
|
||||
*/
|
||||
this.ClientAliveTime = TimeSpan.FromSeconds(5 * aliveTime);
|
||||
ClientAliveTime = TimeSpan.FromSeconds(5 * aliveTime);
|
||||
}
|
||||
|
||||
public OperationCode OperationCode { get; }
|
127
Continuity.AuthServer/Program.cs
Normal file
127
Continuity.AuthServer/Program.cs
Normal file
|
@ -0,0 +1,127 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using Continuity.AuthServer.DB;
|
||||
using Continuity.AuthServer.Services;
|
||||
using MassTransit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Npgsql;
|
||||
using OpenTelemetry.Logs;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using Wonderking.Game.Mapping;
|
||||
|
||||
var builder = Host.CreateApplicationBuilder();
|
||||
#if DEBUG
|
||||
builder.Environment.EnvironmentName = "Development";
|
||||
#endif
|
||||
|
||||
builder.Services.AddMetrics();
|
||||
|
||||
builder.Configuration.AddJsonFile("settings.json", true, true)
|
||||
.AddJsonFile($"settings.{builder.Environment.EnvironmentName}.json", true)
|
||||
.AddEnvironmentVariables().Build();
|
||||
|
||||
builder.Services.AddLogging();
|
||||
var loggerFactory = LoggerFactory.Create(loggingBuilder =>
|
||||
{
|
||||
loggingBuilder.AddFile("logs/Continuity.AuthServer-{Date}.log", LogLevel.Trace);
|
||||
loggingBuilder.AddFile("logs/Continuity.AuthServer-{Date}.json.log", LogLevel.Trace, isJson: true);
|
||||
loggingBuilder.AddConsole();
|
||||
});
|
||||
|
||||
var configuration = builder.Configuration;
|
||||
if (configuration.GetValue<bool>("Tracing:Enabled"))
|
||||
{
|
||||
Action<ResourceBuilder> resourceBuilderAction = r => r
|
||||
.AddService("Continuity", serviceInstanceId: Environment.MachineName);
|
||||
|
||||
builder.Services.AddOpenTelemetry()
|
||||
.ConfigureResource(resourceBuilderAction)
|
||||
.WithTracing(tracing =>
|
||||
{
|
||||
tracing.AddSource(nameof(Server));
|
||||
//tracing.AddSource("MassTransit");
|
||||
tracing.AddEntityFrameworkCoreInstrumentation(options => options.SetDbStatementForText = true);
|
||||
tracing.AddNpgsql();
|
||||
})
|
||||
.WithMetrics(metrics =>
|
||||
{
|
||||
metrics.AddRuntimeInstrumentation();
|
||||
metrics.AddProcessInstrumentation();
|
||||
});
|
||||
|
||||
builder.Logging.AddOpenTelemetry(logging =>
|
||||
{
|
||||
var resourceBuilder = ResourceBuilder.CreateDefault();
|
||||
resourceBuilderAction(resourceBuilder);
|
||||
logging.SetResourceBuilder(resourceBuilder);
|
||||
logging.IncludeFormattedMessage = true;
|
||||
logging.IncludeScopes = true;
|
||||
});
|
||||
builder.Services.Configure<OpenTelemetryLoggerOptions>(logging =>
|
||||
{
|
||||
logging.AddOtlpExporter(options =>
|
||||
{
|
||||
options.Endpoint = new Uri(configuration["OTLP:Logging:Endpoint"] ?? string.Empty);
|
||||
});
|
||||
});
|
||||
builder.Services.ConfigureOpenTelemetryMeterProvider(metrics =>
|
||||
{
|
||||
metrics.AddOtlpExporter(options =>
|
||||
options.Endpoint = new Uri(configuration["OTLP:Metrics:Endpoint"] ?? string.Empty));
|
||||
});
|
||||
builder.Services.ConfigureOpenTelemetryTracerProvider(tracing =>
|
||||
{
|
||||
tracing.AddZipkinExporter(options =>
|
||||
options.Endpoint = new Uri(configuration["Zipkin:Endpoint"] ?? string.Empty));
|
||||
tracing.AddOtlpExporter(options => options.Endpoint = new Uri(configuration["OTLP:Tracing:Endpoint"] ?? string.Empty));
|
||||
});
|
||||
}
|
||||
|
||||
builder.Services.AddHealthChecks()
|
||||
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
|
||||
|
||||
builder.Services.AddDbContextPool<WonderkingContext>(o =>
|
||||
{
|
||||
o.UseNpgsql(
|
||||
$"Host={configuration["DB:Host"]};Username={configuration["DB:Username"]};Password={configuration["DB:Password"]};Database={configuration["DB:Database"]};Port={configuration["DB:Port"]}")
|
||||
.EnableSensitiveDataLogging().UseLazyLoadingProxies().UseLoggerFactory(loggerFactory);
|
||||
});
|
||||
|
||||
builder.Services.AddSingleton<CharacterStatsMappingConfiguration>(
|
||||
JsonSerializer.Deserialize<CharacterStatsMappingConfiguration>(
|
||||
File.ReadAllText("config/character-stats.mapping.json")) ?? throw new InvalidOperationException());
|
||||
|
||||
builder.Services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
builder.Services.AddSingleton<PacketDistributorService>();
|
||||
builder.Services.AddSingleton<ItemObjectPoolService>();
|
||||
builder.Services.AddHostedService(provider =>
|
||||
provider.GetService<ItemObjectPoolService>() ?? throw new InvalidOperationException());
|
||||
builder.Services.AddHostedService(provider =>
|
||||
provider.GetService<PacketDistributorService>() ?? throw new InvalidOperationException());
|
||||
builder.Services.AddMassTransit(x =>
|
||||
{
|
||||
x.UsingInMemory((context, configurator) => configurator.ConfigureEndpoints(context));
|
||||
x.AddMediator(cfg => cfg.AddConsumers(Assembly.GetExecutingAssembly()));
|
||||
});
|
||||
builder.Services.AddHostedService(provider => new WonderkingAuthServer(IPAddress.Any, 10001,
|
||||
provider.GetService<ILogger<WonderkingAuthServer>>() ?? throw new InvalidOperationException(),
|
||||
provider.GetService<IServiceProvider>() ?? throw new InvalidOperationException()));
|
||||
|
||||
using var host = builder.Build();
|
||||
using (var scope = host.Services.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<WonderkingContext>();
|
||||
await db.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
await host.RunAsync();
|
98
Continuity.AuthServer/Services/ItemObjectPoolService.cs
Normal file
98
Continuity.AuthServer/Services/ItemObjectPoolService.cs
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using Continuity.AuthServer.DB.Documents;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Wonderking.Game.Data;
|
||||
using Wonderking.Game.Reader;
|
||||
|
||||
namespace Continuity.AuthServer.Services;
|
||||
|
||||
public class ItemObjectPoolService : IHostedService
|
||||
{
|
||||
private readonly ConcurrentDictionary<uint, ItemObject> _itemObjectPool;
|
||||
private readonly ItemReader _itemReader;
|
||||
private readonly ILogger<ItemObjectPoolService> _logger;
|
||||
|
||||
public ItemObjectPoolService(IConfiguration configuration, ILogger<ItemObjectPoolService> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_itemReader = new ItemReader(configuration.GetSection("Game").GetSection("Data").GetValue<string>("Path") ??
|
||||
string.Empty);
|
||||
|
||||
_itemObjectPool = new ConcurrentDictionary<uint, ItemObject>();
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var amountOfEntries = _itemReader.GetAmountOfEntries();
|
||||
Parallel.For(0, (int)amountOfEntries, i =>
|
||||
{
|
||||
var itemObject = _itemReader.GetEntry((uint)i);
|
||||
var result = _itemObjectPool.TryAdd(itemObject.ItemID, itemObject);
|
||||
if (!result)
|
||||
{
|
||||
throw new KeyNotFoundException($"Failed to add item {itemObject.ItemID} to the item object pool");
|
||||
}
|
||||
|
||||
_logger.LogTrace("Item with {ID} has been added", itemObject.ItemID);
|
||||
});
|
||||
_logger.LogInformation("A total of {AmountOfEntries} items have been added to the item object pool",
|
||||
_itemObjectPool.Count);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public ItemObject GetItem(ushort itemId)
|
||||
{
|
||||
_ = _itemObjectPool.TryGetValue(itemId, out var itemObject);
|
||||
return itemObject;
|
||||
}
|
||||
|
||||
public bool ContainsItem(ushort itemId)
|
||||
{
|
||||
return _itemObjectPool.ContainsKey(itemId);
|
||||
}
|
||||
|
||||
public IQueryable<ItemObject> QueryItems()
|
||||
{
|
||||
return _itemObjectPool.AsReadOnly().Values.AsQueryable();
|
||||
}
|
||||
|
||||
public InventoryItem GetBaseInventoryItem(ushort itemId, ushort count = 1, bool isWorn = false)
|
||||
{
|
||||
var item = GetItem(itemId);
|
||||
return new InventoryItem
|
||||
{
|
||||
ItemId = itemId,
|
||||
Count = count,
|
||||
Slot = (byte)item.SlotNo1,
|
||||
InventoryTab =
|
||||
item.ItemType switch
|
||||
{
|
||||
1 => InventoryTab.WornCashEquipment,
|
||||
2 => isWorn ? InventoryTab.WornEquipment : InventoryTab.Equipment,
|
||||
3 => InventoryTab.Etc,
|
||||
4 => isWorn ? InventoryTab.WornCashEquipment : InventoryTab.Cash,
|
||||
5 => InventoryTab.Warehouse,
|
||||
0 => InventoryTab.WornEquipment,
|
||||
_ => InventoryTab.WornEquipment
|
||||
},
|
||||
Level = item.MinimumLevelRequirement,
|
||||
Rarity = 0,
|
||||
AddOption = 0,
|
||||
AddOption2 = 0,
|
||||
AddOption3 = 0,
|
||||
Option = 0,
|
||||
Option2 = 0,
|
||||
Option3 = 0
|
||||
};
|
||||
}
|
||||
}
|
187
Continuity.AuthServer/Services/PacketDistributorService.cs
Normal file
187
Continuity.AuthServer/Services/PacketDistributorService.cs
Normal file
|
@ -0,0 +1,187 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Continuity.AuthServer.LoggerMessages;
|
||||
using Continuity.AuthServer.PacketHandlers;
|
||||
using Continuity.AuthServer.Packets;
|
||||
using DotNext.Collections.Generic;
|
||||
using DotNext.Linq.Expressions;
|
||||
using DotNext.Metaprogramming;
|
||||
using MassTransit.Internals;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using Wonderking.Packets;
|
||||
|
||||
namespace Continuity.AuthServer.Services;
|
||||
|
||||
using static CodeGenerator;
|
||||
using static ExpressionBuilder;
|
||||
|
||||
public class PacketDistributorService : IHostedService, IDisposable
|
||||
{
|
||||
private readonly ConcurrentQueue<RawPacket> _concurrentQueue;
|
||||
|
||||
private readonly ILogger<PacketDistributorService> _logger;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
private ImmutableDictionary<OperationCode,
|
||||
Func<byte[], IPacket>> _deserializationMap;
|
||||
|
||||
private ConcurrentDictionary<OperationCode, IPacketHandler> _packetHandlersInstantiation;
|
||||
private readonly ActivitySource _activitySource;
|
||||
|
||||
public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider)
|
||||
{
|
||||
_concurrentQueue = new ConcurrentQueue<RawPacket>();
|
||||
_logger = logger;
|
||||
_serviceProvider = serviceProvider;
|
||||
_activitySource = new ActivitySource(nameof(Server));
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var tempDeserializationMap =
|
||||
new Dictionary<OperationCode, Func<byte[], IPacket>>();
|
||||
|
||||
var wonderkingAssembly = Assembly.GetAssembly(typeof(IPacket));
|
||||
var packetsTypes = GetPacketsWithId(wonderkingAssembly);
|
||||
var packetHandlers = GetAllPacketHandlersWithId(Assembly.GetExecutingAssembly());
|
||||
_packetHandlersInstantiation = new ConcurrentDictionary<OperationCode, IPacketHandler>();
|
||||
packetHandlers.ForEach(x =>
|
||||
{
|
||||
var packetHandler =
|
||||
ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider,
|
||||
x.Value);
|
||||
_packetHandlersInstantiation.TryAdd(x.Key, packetHandler as IPacketHandler);
|
||||
});
|
||||
foreach (var packetsType in packetsTypes)
|
||||
{
|
||||
var lambda = Lambda<Func<byte[], IPacket>>(fun =>
|
||||
{
|
||||
var argPacketData = fun[0];
|
||||
var newPacket = packetsType.Value.New();
|
||||
|
||||
var packetVariable = DeclareVariable(packetsType.Value, "packet");
|
||||
Assign(packetVariable, newPacket);
|
||||
Call(packetVariable, nameof(IPacket.Deserialize), argPacketData);
|
||||
|
||||
Return(packetVariable);
|
||||
}).Compile();
|
||||
_logger.PacketCreationFunctionCreated(packetsType.Key);
|
||||
tempDeserializationMap.Add(packetsType.Key, lambda);
|
||||
}
|
||||
|
||||
_deserializationMap = tempDeserializationMap.ToImmutableDictionary();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Dictionary<OperationCode, Type> GetPacketsWithId(Assembly executingAssembly)
|
||||
{
|
||||
// ! : We are filtering if types that don't have an instance of the required Attribute
|
||||
var packetsWithId = executingAssembly.GetTypes().AsParallel()
|
||||
.Where(type => type.HasInterface(typeof(IPacket)) && type is { IsInterface: false, IsAbstract: false })
|
||||
.Where(type => type.Namespace?.Contains("Incoming") ?? false)
|
||||
.Select(type => new { Type = type, Attribute = type.GetCustomAttribute<PacketIdAttribute>() })
|
||||
.Where(item => item.Attribute is not null)
|
||||
.ToDictionary(item => item.Attribute!.Code, item => item.Type);
|
||||
if (packetsWithId is not { Count: 0 })
|
||||
{
|
||||
packetsWithId.AsParallel()
|
||||
.ForAll(packet => _logger.PacketWithIdAdded(packet.Key, packet.Value.FullName));
|
||||
return packetsWithId;
|
||||
}
|
||||
|
||||
_logger.NoPacketsFound();
|
||||
throw new IncompleteInitialization();
|
||||
}
|
||||
|
||||
private Dictionary<OperationCode, Type> GetAllPacketHandlersWithId(Assembly assembly)
|
||||
{
|
||||
// ! : We are filtering if types that don't have an instance of the required Attribute
|
||||
var packetHandlersWithId = assembly.GetTypes().AsParallel()
|
||||
.Where(t =>
|
||||
t is { IsClass: true, IsAbstract: false } && Array.Exists(t
|
||||
.GetInterfaces(), i =>
|
||||
i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketHandler<>)))
|
||||
.Select(type => new
|
||||
{
|
||||
Type = type,
|
||||
PacketId = type
|
||||
.GetInterfaces().First(t1 =>
|
||||
t1 is { IsGenericType: true } && t1.GetGenericTypeDefinition() == typeof(IPacketHandler<>))
|
||||
.GetGenericArguments()[0].GetCustomAttribute<PacketIdAttribute>()?.Code
|
||||
})
|
||||
.Where(x => x.PacketId is not null)
|
||||
.ToDictionary(
|
||||
x => x.PacketId!.Value, x => x.Type
|
||||
);
|
||||
|
||||
if (packetHandlersWithId is not { Count: 0 })
|
||||
{
|
||||
packetHandlersWithId.AsParallel().ForAll(packetHandler =>
|
||||
_logger.PacketHandlerWithIdAdded(packetHandler.Key, packetHandler.Value.FullName));
|
||||
return packetHandlersWithId;
|
||||
}
|
||||
|
||||
_logger.NoPacketHandlersFound();
|
||||
throw new IncompleteInitialization();
|
||||
}
|
||||
|
||||
public void AddPacket(RawPacket rawPacket)
|
||||
{
|
||||
_concurrentQueue.Enqueue(rawPacket);
|
||||
DequeueRawPacket();
|
||||
_logger.PacketReceived(rawPacket.OperationCode);
|
||||
}
|
||||
|
||||
private void DequeueRawPacket()
|
||||
{
|
||||
if (_concurrentQueue.TryDequeue(out var item))
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(InvokePacketHandler, item, preferLocal: false);
|
||||
}
|
||||
}
|
||||
|
||||
private void InvokePacketHandler(RawPacket item)
|
||||
{
|
||||
IPacket packet;
|
||||
_logger.PacketDequeued(item.Session.Id, item.OperationCode);
|
||||
if (!_deserializationMap.TryGetValue(item.OperationCode, out var value))
|
||||
{
|
||||
_logger.PacketTypeNotFound(item.OperationCode);
|
||||
return;
|
||||
}
|
||||
|
||||
using (var packetParsingActivity = _activitySource.StartActivity("PacketParsing"))
|
||||
{
|
||||
packetParsingActivity?.SetTag("PacketId", item.OperationCode);
|
||||
packet = value(item.MessageBody);
|
||||
}
|
||||
|
||||
using (var packetHandlerActivity = _activitySource.StartActivity("PacketHandler"))
|
||||
{
|
||||
packetHandlerActivity?.SetTag("PacketId", item.OperationCode);
|
||||
_ = _packetHandlersInstantiation[item.OperationCode].TryHandleAsync(packet, item.Session);
|
||||
}
|
||||
|
||||
_logger.PacketData(JsonConvert.SerializeObject(packet));
|
||||
_logger.PacketFinished(item.Session.Id, item.OperationCode);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
_activitySource.Dispose();
|
||||
}
|
||||
}
|
82
Continuity.AuthServer/Services/WonderkingAuthServer.cs
Normal file
82
Continuity.AuthServer/Services/WonderkingAuthServer.cs
Normal file
|
@ -0,0 +1,82 @@
|
|||
// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License.
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetCoreServer;
|
||||
|
||||
namespace Continuity.AuthServer.Services;
|
||||
|
||||
public class WonderkingAuthServer : TcpServer, IHostedService
|
||||
{
|
||||
private readonly ILogger<WonderkingAuthServer> _logger;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public WonderkingAuthServer(IPAddress address, int port, ILogger<WonderkingAuthServer> logger,
|
||||
IServiceProvider serviceProvider) : base(address, port)
|
||||
{
|
||||
_logger = logger;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
Start();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
DisconnectAll();
|
||||
Stop();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected override TcpSession CreateSession()
|
||||
{
|
||||
return ActivatorUtilities.CreateInstance<AuthSession>(_serviceProvider, this);
|
||||
}
|
||||
|
||||
protected override void OnStarting()
|
||||
{
|
||||
_logger.LogInformation("Starting");
|
||||
base.OnStarting();
|
||||
}
|
||||
|
||||
protected override void OnStarted()
|
||||
{
|
||||
_logger.LogInformation("Started");
|
||||
base.OnStarted();
|
||||
}
|
||||
|
||||
protected override void OnStopping()
|
||||
{
|
||||
_logger.LogInformation("Stopping");
|
||||
base.OnStopping();
|
||||
}
|
||||
|
||||
protected override void OnStopped()
|
||||
{
|
||||
_logger.LogInformation("Stopped");
|
||||
base.OnStopped();
|
||||
}
|
||||
|
||||
protected override void OnConnected(TcpSession session)
|
||||
{
|
||||
_logger.LogInformation("Client connected {Session}", session.Id);
|
||||
base.OnConnected(session);
|
||||
}
|
||||
|
||||
protected override void OnDisconnected(TcpSession session)
|
||||
{
|
||||
_logger.LogInformation("Client disconnected {Session}", session.Id);
|
||||
base.OnDisconnected(session);
|
||||
}
|
||||
|
||||
protected override void OnError(SocketError error)
|
||||
{
|
||||
_logger.LogError("An error has occured {Error}", error);
|
||||
}
|
||||
}
|
17
Continuity.AuthServer/settings.Development.json
Normal file
17
Continuity.AuthServer/settings.Development.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"DB": {
|
||||
"Username": "continuity",
|
||||
"Host": "localhost",
|
||||
"Password": "continuity",
|
||||
"Database": "continuity",
|
||||
"Port": "5432"
|
||||
},
|
||||
"Testing": {
|
||||
"CreateAccountOnLogin": true
|
||||
},
|
||||
"Game": {
|
||||
"Data": {
|
||||
"Path": "../wk-data/"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{7EDA8B31-3E03-4CA3-87D1-CFEB05C277D6}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Continuity.AuthServer", "Continuity.AuthServer\Continuity.AuthServer.csproj", "{7EDA8B31-3E03-4CA3-87D1-CFEB05C277D6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{7D560FA1-A61C-4B67-8300-835CA5814621}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wonderking", "Wonderking\Wonderking.csproj", "{6B53A10B-C397-4347-BB00-A12272D0528E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -18,5 +20,9 @@ Global
|
|||
{7D560FA1-A61C-4B67-8300-835CA5814621}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7D560FA1-A61C-4B67-8300-835CA5814621}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7D560FA1-A61C-4B67-8300-835CA5814621}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B53A10B-C397-4347-BB00-A12272D0528E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B53A10B-C397-4347-BB00-A12272D0528E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B53A10B-C397-4347-BB00-A12272D0528E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B53A10B-C397-4347-BB00-A12272D0528E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=decryptor/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -1,2 +1,6 @@
|
|||
# What is this project about?
|
||||
This is a continuation and rewrite of the original Project Infinity for Wonderking.
|
||||
|
||||
## Important notes for developers
|
||||
|
||||
* Avoid using statements with TcpSession, AuthSession or any type that inherits Session outside the session itself.
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
namespace Server;
|
||||
|
||||
using System.Reflection;
|
||||
using MassTransit.Mediator;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetCoreServer;
|
||||
using Packets;
|
||||
|
||||
public class AuthSession : TcpSession
|
||||
{
|
||||
private readonly ILogger<AuthSession> logger;
|
||||
private readonly IMediator mediator;
|
||||
|
||||
public AuthSession(TcpServer
|
||||
server, IMediator mediator, ILogger<AuthSession> logger) : base(server)
|
||||
{
|
||||
this.mediator = mediator;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public override long Send(byte[] buffer)
|
||||
{
|
||||
this.logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(buffer));
|
||||
return base.Send(buffer);
|
||||
}
|
||||
|
||||
public void Send(IPacket packet)
|
||||
{
|
||||
var type = packet.GetType();
|
||||
this.logger.LogTrace("Packet of type {Type} is being serialized", type.Name);
|
||||
var packetIdAttribute = type.GetCustomAttribute<PacketIdAttribute>();
|
||||
if (packetIdAttribute == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var opcode = packetIdAttribute.Code;
|
||||
|
||||
Span<byte> packetData = packet.Serialize();
|
||||
var length = (ushort)(packetData.Length + 8);
|
||||
|
||||
Span<byte> buffer = stackalloc byte[length];
|
||||
buffer.Clear();
|
||||
packetData.CopyTo(buffer.Slice(8, length - 8));
|
||||
|
||||
var bytesOfLength = BitConverter.GetBytes(length);
|
||||
var bytesOfOpcode = BitConverter.GetBytes((ushort)opcode);
|
||||
for (var i = 0; i < bytesOfLength.Length || i < 2; i++)
|
||||
{
|
||||
buffer[i] = bytesOfLength[i];
|
||||
}
|
||||
|
||||
for (var i = 0; i < bytesOfOpcode.Length || i < 2; i++)
|
||||
{
|
||||
buffer[2 + i] = bytesOfOpcode[i];
|
||||
}
|
||||
|
||||
this.logger.LogTrace("Packet data being parsed is: {Data}", BitConverter.ToString(packetData.ToArray()));
|
||||
this.logger.LogTrace("Packet being parsed is: {Data}", BitConverter.ToString(buffer.ToArray()));
|
||||
|
||||
this.Send(buffer);
|
||||
}
|
||||
|
||||
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||
{
|
||||
this.logger.LogDebug("Length: {Size} & offset: {Offset}", size, offset);
|
||||
Span<byte> decryptedBuffer = new byte[size];
|
||||
|
||||
// xor every value after the first 8 bytes
|
||||
var dataBuffer = Decrypt(new ArraySegment<byte>(buffer, 8, (int)size - 8).ToArray());
|
||||
|
||||
this.logger.LogDebug("Length {length}", BitConverter.ToUInt16(buffer, 0));
|
||||
var opCode = BitConverter.ToUInt16(buffer.ToArray(), 2);
|
||||
this.logger.LogDebug("Packet Op Code: {OpCode}", opCode);
|
||||
this.logger.LogDebug("Some Value: {RandomValue}", buffer[4]);
|
||||
var clientAliveTime = BitConverter.ToUInt16(buffer.ToArray(), 5);
|
||||
this.logger.LogDebug("Client Alive time: {ClientAliveTime}", clientAliveTime);
|
||||
this.logger.LogDebug("Might be a flag: {Flag}", buffer[7]);
|
||||
|
||||
this.logger.LogDebug("Full buffer: {Buffer}", BitConverter.ToString(dataBuffer.ToArray()));
|
||||
|
||||
var rawPacket = new RawPacket((OperationCode)opCode, dataBuffer, clientAliveTime, buffer[7],
|
||||
buffer[4], this.Id, this);
|
||||
Task.Run(() => this.mediator.Send(rawPacket));
|
||||
this.logger.LogInformation("Connection from: {@RemoteEndpoint}", this.Socket.RemoteEndPoint?.ToString());
|
||||
base.OnReceived(decryptedBuffer.ToArray(), offset, decryptedBuffer.Length);
|
||||
}
|
||||
|
||||
private static byte[] Decrypt(byte[] buffer)
|
||||
{
|
||||
for (var i = 0; i < buffer.Length; ++i)
|
||||
{
|
||||
buffer[i] = (byte)(buffer[i] ^ i ^ (3 * (0xFE - i)));
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
namespace Server;
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using MassTransit.Mediator;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetCoreServer;
|
||||
|
||||
public class ChannelSession : TcpSession
|
||||
{
|
||||
private static readonly byte[] Key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7 }
|
||||
.Reverse().ToArray();
|
||||
|
||||
private static readonly byte[] Iv = new byte[]
|
||||
{
|
||||
0xfe, 220, 0xba, 0x98, 0x76, 0x54, 50, 0x10, 15, 30, 0x2d, 60, 0x4b, 90, 0x69, 120
|
||||
}.Reverse().ToArray();
|
||||
|
||||
private readonly ICryptoTransform decryptor;
|
||||
|
||||
private readonly ICryptoTransform encryptor;
|
||||
private readonly ILogger<ChannelSession> logger;
|
||||
private readonly IMediator mediator;
|
||||
|
||||
public ChannelSession(TcpServer server, IMediator mediator, ILogger<ChannelSession> logger) : base(server)
|
||||
{
|
||||
this.mediator = mediator;
|
||||
this.logger = logger;
|
||||
var aes = Aes.Create();
|
||||
aes.Key = Key;
|
||||
aes.IV = Iv;
|
||||
aes.Padding = PaddingMode.None;
|
||||
aes.Mode = CipherMode.ECB;
|
||||
|
||||
this.decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||
this.encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
|
||||
}
|
||||
|
||||
protected override void OnReceived(byte[] buffer, long offset, long size)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var ms = new MemoryStream(Decrypt(buffer)))
|
||||
using (var cs = new CryptoStream(ms, this.decryptor, CryptoStreamMode.Read))
|
||||
{
|
||||
cs.Read(buffer);
|
||||
}
|
||||
|
||||
base.OnReceived(buffer, offset, size);
|
||||
}
|
||||
catch (CryptographicException ex)
|
||||
{
|
||||
this.logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message);
|
||||
this.logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] Decrypt(byte[] buffer)
|
||||
{
|
||||
for (var i = 0; i < buffer.Length; ++i)
|
||||
{
|
||||
buffer[i] = (byte)(buffer[i] ^ i ^ (3 * (0xFE - i)));
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
namespace Server.Consumers;
|
||||
|
||||
using MassTransit;
|
||||
using Packets;
|
||||
using Services;
|
||||
|
||||
public class PacketConsumer : IConsumer<RawPacket>
|
||||
{
|
||||
private readonly PacketDistributorService distributorService;
|
||||
|
||||
public PacketConsumer(PacketDistributorService distributorService) => this.distributorService = distributorService;
|
||||
|
||||
public Task Consume(ConsumeContext<RawPacket> context)
|
||||
{
|
||||
this.distributorService.AddPacket(context.Message);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
namespace Server.DB.Documents;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
public class Account
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public Account(string username, byte[] password, string email, byte permissionLevel, byte[] salt)
|
||||
{
|
||||
this.Username = username;
|
||||
this.Password = password;
|
||||
this.Email = email;
|
||||
this.PermissionLevel = permissionLevel;
|
||||
this.Salt = salt;
|
||||
}
|
||||
|
||||
public string Username { get; set; }
|
||||
public byte[] Password { get; set; }
|
||||
public string Email { get; set; }
|
||||
public byte PermissionLevel { get; set; }
|
||||
public byte[] Salt { get; set; }
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Accounts",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Username = table.Column<string>(type: "varchar(20)", nullable: false),
|
||||
Password = table.Column<byte[]>(type: "bytea", nullable: false),
|
||||
Email = table.Column<string>(type: "text", nullable: false),
|
||||
PermissionLevel = table.Column<byte>(type: "smallint", nullable: false),
|
||||
Salt = table.Column<byte[]>(type: "bytea", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Accounts", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Accounts");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using Server.DB;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Server.DB.Migrations
|
||||
{
|
||||
[DbContext(typeof(WonderkingContext))]
|
||||
partial class WonderkingContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "7.0.10")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Server.DB.Documents.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<byte[]>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<byte>("PermissionLevel")
|
||||
.HasColumnType("smallint");
|
||||
|
||||
b.Property<byte[]>("Salt")
|
||||
.IsRequired()
|
||||
.HasColumnType("bytea");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(20)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
namespace Server.DB;
|
||||
|
||||
using System.Data.Common;
|
||||
using Documents;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Npgsql;
|
||||
|
||||
public class WonderkingContext : DbContext
|
||||
{
|
||||
private readonly ILoggerFactory loggerFactory;
|
||||
private readonly IConfiguration configuration;
|
||||
|
||||
public WonderkingContext(ILoggerFactory loggerFactory, IConfiguration configuration)
|
||||
{
|
||||
this.loggerFactory = loggerFactory;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
|
||||
optionsBuilder
|
||||
.UseNpgsql(
|
||||
$"Host={this.configuration["DB:Host"]};Username={this.configuration["DB:Username"]};Password={this.configuration["DB:Password"]};Database={this.configuration["DB:Database"]};Port={this.configuration["DB:Port"]}")
|
||||
.EnableSensitiveDataLogging().UseLoggerFactory(this.loggerFactory);
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder) =>
|
||||
modelBuilder.Entity<Account>(builder =>
|
||||
{
|
||||
builder.Property(b => b.Username).HasColumnType("varchar(20)");
|
||||
builder.Property(b => b.Password).HasColumnType("bytea");
|
||||
builder.Property(b => b.Salt).HasColumnType("bytea");
|
||||
builder.HasKey(b => b.Id);
|
||||
});
|
||||
|
||||
public DbSet<Account> Accounts { get; set; }
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
FROM mcr.microsoft.com/dotnet/runtime:7.0 AS base
|
||||
WORKDIR /app
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0.400 AS build
|
||||
WORKDIR /src
|
||||
COPY ["Server/Server.csproj", "Server/"]
|
||||
RUN dotnet restore "Server/Server.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/Server"
|
||||
RUN dotnet build "Server.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "Server.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "Server.dll"]
|
|
@ -1,12 +0,0 @@
|
|||
namespace Server.PacketHandlers;
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using NetCoreServer;
|
||||
using Packets;
|
||||
|
||||
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
|
||||
public interface IPacketHandler<in T> where T : IPacket
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public Task HandleAsync(T packet, TcpSession session);
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
namespace Server.PacketHandlers;
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using DB;
|
||||
using DB.Documents;
|
||||
using Konscious.Security.Cryptography;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetCoreServer;
|
||||
using Packets.Incoming;
|
||||
using Packets.Outgoing;
|
||||
|
||||
public class LoginHandler : IPacketHandler<LoginInfoPacket>
|
||||
{
|
||||
private readonly IConfiguration configuration;
|
||||
private readonly ILogger<LoginHandler> logger;
|
||||
private readonly WonderkingContext wonderkingContext;
|
||||
|
||||
public LoginHandler(ILogger<LoginHandler> logger, WonderkingContext wonderkingContext, IConfiguration configuration)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.wonderkingContext = wonderkingContext;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public async Task HandleAsync(LoginInfoPacket packet, TcpSession session)
|
||||
{
|
||||
var loginResponseReason = LoginResponseReason.Error;
|
||||
this.logger.LogInformation("Login data: Username {Username} & Password {Password}", packet.Username,
|
||||
packet.Password);
|
||||
var account = this.wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username);
|
||||
|
||||
// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id
|
||||
// "Use Argon2id with a minimum configuration of 19 MiB of memory, an iteration count of 2, and 1 degree of parallelism."
|
||||
var argon2Id = new Argon2id(Encoding.ASCII.GetBytes(packet.Password));
|
||||
argon2Id.MemorySize = 1024 * 40;
|
||||
argon2Id.Iterations = 4;
|
||||
argon2Id.DegreeOfParallelism = 2;
|
||||
if (account == null)
|
||||
{
|
||||
if (this.configuration.GetSection("Testing").GetValue<bool>("CreateAccountOnLogin"))
|
||||
{
|
||||
argon2Id.Salt = RandomNumberGenerator.GetBytes(128);
|
||||
var finalAccount =
|
||||
await this.wonderkingContext.Accounts.AddAsync(new Account(packet.Username, Array.Empty<byte>(), "",
|
||||
0, argon2Id.Salt));
|
||||
await this.wonderkingContext.SaveChangesAsync();
|
||||
argon2Id.AssociatedData = finalAccount.Entity.Id.ToByteArray();
|
||||
finalAccount.Entity.Password = await argon2Id.GetBytesAsync(128);
|
||||
this.wonderkingContext.Accounts.Update(finalAccount.Entity);
|
||||
loginResponseReason = LoginResponseReason.Ok;
|
||||
await this.wonderkingContext.SaveChangesAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Send Message that account does not exist
|
||||
this.logger.LogInformation("Requested account for user: {Username} does not exist", packet.Username);
|
||||
loginResponseReason = LoginResponseReason.AccountDoesNotExit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
argon2Id.Salt = account.Salt;
|
||||
argon2Id.AssociatedData = account.Id.ToByteArray();
|
||||
var tempPasswordBytes = await argon2Id.GetBytesAsync(128);
|
||||
loginResponseReason = tempPasswordBytes.SequenceEqual(account.Password)
|
||||
? LoginResponseReason.Ok
|
||||
: LoginResponseReason.WrongPassword;
|
||||
}
|
||||
|
||||
var loginResponsePacket = new LoginResponsePacket
|
||||
{
|
||||
ResponseReason = loginResponseReason,
|
||||
ChannelData = new[] { new ServerChannelData { ChannelId = 0, LoadPercentage = 75, ServerId = 0 } },
|
||||
UnknownFlag = 1,
|
||||
IsGameMaster = true
|
||||
};
|
||||
var sess = session as AuthSession;
|
||||
sess.Send(loginResponsePacket);
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
namespace Server.Packets.Incoming;
|
||||
|
||||
using System.Text;
|
||||
|
||||
[PacketId(OperationCode.LoginInfo)]
|
||||
public class LoginInfoPacket : IPacket
|
||||
{
|
||||
public required string Username { get; set; }
|
||||
|
||||
public required string Password { get; set; }
|
||||
|
||||
public void Deserialize(byte[] data)
|
||||
{
|
||||
this.Username = Encoding.ASCII.GetString(data, 0, 20).TrimEnd('\0');
|
||||
this.Password = Encoding.ASCII.GetString(data, 20, 31).TrimEnd('\0');
|
||||
}
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
Span<byte> dataSpan = stackalloc byte[20 + 31];
|
||||
var usernameBytes = Encoding.ASCII.GetBytes(this.Username);
|
||||
var passwordBytes = Encoding.ASCII.GetBytes(this.Password);
|
||||
for (var i = 0; i < 20 || i < this.Username.Length; i++)
|
||||
{
|
||||
dataSpan[i] = usernameBytes[i];
|
||||
}
|
||||
|
||||
for (var i = 0; i < 31 || i < this.Password.Length; i++)
|
||||
{
|
||||
dataSpan[20 + i] = passwordBytes[i];
|
||||
}
|
||||
|
||||
return dataSpan.ToArray();
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace Server.Packets;
|
||||
|
||||
public enum OperationCode : ushort
|
||||
{
|
||||
LoginInfo = 11,
|
||||
LoginResponse = 12
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
namespace Server.Packets.Outgoing;
|
||||
|
||||
[PacketId(OperationCode.LoginResponse)]
|
||||
public class LoginResponsePacket : IPacket
|
||||
{
|
||||
public required LoginResponseReason ResponseReason { get; set; }
|
||||
public required byte UnknownFlag { get; set; } = 1;
|
||||
public required bool IsGameMaster { get; set; }
|
||||
|
||||
public required ServerChannelData[] ChannelData { get; set; }
|
||||
|
||||
public void Deserialize(byte[] data)
|
||||
{
|
||||
this.ResponseReason = (LoginResponseReason)data[0];
|
||||
this.UnknownFlag = data[1];
|
||||
this.IsGameMaster = BitConverter.ToBoolean(data, 2);
|
||||
var channelAmount = BitConverter.ToUInt16(data, 3);
|
||||
const int sizeOfServerChannelData = 5;
|
||||
this.ChannelData = Enumerable.Repeat(0, channelAmount).Select(i => new ServerChannelData
|
||||
{
|
||||
ServerId = BitConverter.ToUInt16(data, 5 + 0 + (i * sizeOfServerChannelData)),
|
||||
ChannelId = BitConverter.ToUInt16(data, 5 + 2 + (i * sizeOfServerChannelData)),
|
||||
LoadPercentage = data[5 + 4 + (i * sizeOfServerChannelData)]
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
const int sizeOfServerChannelData = 5;
|
||||
Span<byte> dataSpan = stackalloc byte[5 + (this.ChannelData.Length * sizeOfServerChannelData)];
|
||||
dataSpan.Clear();
|
||||
dataSpan[0] = (byte)this.ResponseReason;
|
||||
dataSpan[1] = this.UnknownFlag;
|
||||
dataSpan[2] = BitConverter.GetBytes(this.IsGameMaster)[0];
|
||||
var bytesOfChannelAmount = BitConverter.GetBytes((ushort)this.ChannelData.Length);
|
||||
dataSpan[3] = bytesOfChannelAmount[0];
|
||||
dataSpan[4] = bytesOfChannelAmount[1];
|
||||
|
||||
for (var i = 0; i < this.ChannelData.Length; i++)
|
||||
{
|
||||
var bytesOfServerId = BitConverter.GetBytes(this.ChannelData[i].ServerId);
|
||||
var bytesOfChannelId = BitConverter.GetBytes(this.ChannelData[i].ChannelId);
|
||||
dataSpan[5 + 0 + (i * sizeOfServerChannelData)] = bytesOfServerId[0];
|
||||
dataSpan[5 + 1 + (i * sizeOfServerChannelData)] = bytesOfServerId[1];
|
||||
dataSpan[5 + 2 + (i * sizeOfServerChannelData)] = bytesOfChannelId[0];
|
||||
dataSpan[5 + 3 + (i * sizeOfServerChannelData)] = bytesOfChannelId[1];
|
||||
dataSpan[5 + 4 + (i * sizeOfServerChannelData)] = this.ChannelData[i].LoadPercentage;
|
||||
}
|
||||
|
||||
return dataSpan.ToArray();
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Server.Packets.Outgoing;
|
||||
|
||||
public struct ServerChannelData
|
||||
{
|
||||
public ushort ServerId { get; set; }
|
||||
public ushort ChannelId { get; set; }
|
||||
public byte LoadPercentage { get; set; }
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Server.Packets;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public class PacketIdAttribute : Attribute
|
||||
{
|
||||
public PacketIdAttribute(OperationCode code) => this.Code = code;
|
||||
public OperationCode Code { get; }
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#pragma warning disable AV1500
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using MassTransit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Server.DB;
|
||||
using Server.Services;
|
||||
|
||||
var builder = Host.CreateApplicationBuilder();
|
||||
var configurationRoot = builder.Configuration.AddJsonFile("settings.json", false, true)
|
||||
.AddEnvironmentVariables().Build();
|
||||
builder.Services.AddLogging();
|
||||
builder.Logging.AddFile("Logs/Server-{Date}.log", LogLevel.Debug);
|
||||
builder.Logging.AddFile("Logs/Server-{Date}.json.log", LogLevel.Debug, isJson: true);
|
||||
builder.Services.AddEntityFrameworkNpgsql();
|
||||
builder.Services.AddDbContext<WonderkingContext>();
|
||||
builder.Services.AddSingleton<PacketDistributorService>();
|
||||
builder.Services.AddHostedService<PacketDistributorService>(provider =>
|
||||
provider.GetService<PacketDistributorService>() ?? throw new InvalidOperationException());
|
||||
builder.Services.AddMassTransit(x =>
|
||||
{
|
||||
x.UsingInMemory((context, configurator) => configurator.ConfigureEndpoints(context));
|
||||
x.AddMediator(cfg => cfg.AddConsumers(Assembly.GetExecutingAssembly()));
|
||||
});
|
||||
builder.Services.AddHostedService<WonderkingAuthServer>(provider => new WonderkingAuthServer(IPAddress.Any, 10001,
|
||||
provider.GetService<ILogger<WonderkingAuthServer>>() ?? throw new InvalidOperationException(),
|
||||
provider.GetService<IServiceProvider>() ?? throw new InvalidOperationException()));
|
||||
|
||||
using var host = builder.Build();
|
||||
await using (var scope = host.Services.CreateAsyncScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<WonderkingContext>();
|
||||
await db.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
await host.RunAsync();
|
||||
#pragma warning restore AV1500
|
|
@ -1,87 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<RootNamespace>Server</RootNamespace>
|
||||
<LangVersion>default</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\.dockerignore">
|
||||
<Link>.dockerignore</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNext" Version="4.13.1" />
|
||||
<PackageReference Include="DotNext.IO" Version="4.13.1" />
|
||||
<PackageReference Include="DotNext.Metaprogramming" Version="4.13.1" />
|
||||
<PackageReference Include="DotNext.Reflection" Version="4.9.0" />
|
||||
<PackageReference Include="DotNext.Threading" Version="4.13.1" />
|
||||
<PackageReference Include="DotNext.Unsafe" Version="4.13.1" />
|
||||
<PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2023.2.0"/>
|
||||
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.0" />
|
||||
<PackageReference Include="MassTransit" Version="8.0.16"/>
|
||||
<PackageReference Include="MassTransit.Analyzers" Version="8.0.16">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0"/>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.7.30">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NetCoreServer" Version="7.0.0"/>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
|
||||
<PackageReference Include="Nullable.Extended.Analyzer" Version="1.10.4539">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Puma.Security.Rules.2022" Version="2.4.23">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.Analyzers" Version="4.4.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.4.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.Formatting.Analyzers" Version="4.4.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="settings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,139 +0,0 @@
|
|||
namespace Server.Services;
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using MassTransit.Internals;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using PacketHandlers;
|
||||
using Packets;
|
||||
using static DotNext.Metaprogramming.CodeGenerator;
|
||||
using static DotNext.Linq.Expressions.ExpressionBuilder;
|
||||
|
||||
public class PacketDistributorService : IHostedService
|
||||
{
|
||||
private readonly ConcurrentQueue<RawPacket> concurrentQueue;
|
||||
private readonly ILogger<PacketDistributorService> logger;
|
||||
private readonly Dictionary<OperationCode, Type> packetHandlers;
|
||||
private readonly Dictionary<OperationCode, Func<byte[], IPacket>> deserializationMap;
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider)
|
||||
{
|
||||
this.concurrentQueue = new ConcurrentQueue<RawPacket>();
|
||||
this.logger = logger;
|
||||
this.serviceProvider = serviceProvider;
|
||||
this.packetHandlers = new Dictionary<OperationCode, Type>();
|
||||
this.deserializationMap = new Dictionary<OperationCode, Func<byte[], IPacket>>();
|
||||
|
||||
var executingAssembly = Assembly.GetExecutingAssembly();
|
||||
var packetsTypes = this.GetPacketsWithId(executingAssembly);
|
||||
this.packetHandlers = this.GetAllPacketHandlersWithId(executingAssembly);
|
||||
|
||||
foreach (var packetsType in packetsTypes)
|
||||
{
|
||||
var lambda = Lambda<Func<byte[], IPacket>>(fun =>
|
||||
{
|
||||
var arg = fun[0];
|
||||
var newPacket = packetsType.Value.New();
|
||||
|
||||
var packetVariable = DeclareVariable(packetsType.Value, "packet");
|
||||
Assign(packetVariable, newPacket);
|
||||
Call(packetVariable, nameof(IPacket.Deserialize), arg);
|
||||
|
||||
Return(packetVariable);
|
||||
}).Compile();
|
||||
logger.LogInformation("Packet creation function created for {Opcode}", packetsType.Key);
|
||||
this.deserializationMap.Add(packetsType.Key, lambda);
|
||||
}
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
|
||||
private Dictionary<OperationCode, Type> GetPacketsWithId(Assembly executingAssembly)
|
||||
{
|
||||
var packetsWithId = executingAssembly.GetTypes().AsParallel()
|
||||
.Where(type => type.GetCustomAttribute<PacketIdAttribute>() != null && type.HasInterface(typeof(IPacket)) &&
|
||||
!type.IsInterface)
|
||||
.ToDictionary(packet => packet.GetCustomAttribute<PacketIdAttribute>()!.Code);
|
||||
if (packetsWithId is not { Count: 0 })
|
||||
{
|
||||
packetsWithId.AsParallel().ForAll(packet =>
|
||||
{
|
||||
this.logger.LogTrace("Packet with ID: {PacketID} has been added as {PacketName}", packet.Key,
|
||||
packet.Value.FullName);
|
||||
});
|
||||
return packetsWithId;
|
||||
}
|
||||
|
||||
this.logger.LogCritical("No Packets have been found");
|
||||
throw new IncompleteInitialization();
|
||||
}
|
||||
|
||||
private Dictionary<OperationCode, Type> GetAllPacketHandlersWithId(Assembly assembly)
|
||||
{
|
||||
var packetHandlersWithId = assembly.GetTypes().AsParallel().Where(t =>
|
||||
t is { IsClass: true, IsAbstract: false } && t
|
||||
.GetInterfaces().Any(i =>
|
||||
i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketHandler<>))).ToDictionary(type =>
|
||||
type.GetInterfaces().First(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IPacketHandler<>))
|
||||
.GetGenericArguments()[0].GetCustomAttribute<PacketIdAttribute>().Code);
|
||||
|
||||
if (packetHandlersWithId is not { Count: 0 })
|
||||
{
|
||||
packetHandlersWithId.AsParallel().ForAll(packetHandler =>
|
||||
{
|
||||
this.logger.LogTrace("PacketHandler with ID: {PacketID} has been added as {PacketName}",
|
||||
packetHandler.Key,
|
||||
packetHandler.Value.FullName);
|
||||
});
|
||||
return packetHandlersWithId;
|
||||
}
|
||||
|
||||
this.logger.LogCritical("No PacketHandlers have been found");
|
||||
throw new IncompleteInitialization();
|
||||
}
|
||||
|
||||
public void AddPacket(RawPacket rawPacket)
|
||||
{
|
||||
this.concurrentQueue.Enqueue(rawPacket);
|
||||
this.DequeueRawPacket();
|
||||
this.logger.LogInformation("Packet with ID: {MessageOperationCode} has been received",
|
||||
rawPacket.OperationCode);
|
||||
}
|
||||
|
||||
private void DequeueRawPacket()
|
||||
{
|
||||
if (this.concurrentQueue.TryDequeue(out var item))
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(this.InvokePacketHandler, item, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void InvokePacketHandler(RawPacket item)
|
||||
{
|
||||
this.logger.LogTrace("[{TempId}] Packet with ID: {MessageOperationCode} is being dequeued",
|
||||
item.Session.Id, item.OperationCode);
|
||||
if (!this.deserializationMap.ContainsKey(item.OperationCode))
|
||||
{
|
||||
this.logger.LogInformation("Couldn't find Packet type for Id: {Opcode}", item.OperationCode);
|
||||
return;
|
||||
}
|
||||
|
||||
var packet = this.deserializationMap[item.OperationCode](item.MessageBody);
|
||||
var packetHandler =
|
||||
ActivatorUtilities.GetServiceOrCreateInstance(this.serviceProvider,
|
||||
this.packetHandlers[item.OperationCode]);
|
||||
packetHandler.GetType().GetMethod("HandleAsync")
|
||||
?.Invoke(packetHandler, new object[] { packet, item.Session });
|
||||
this.logger.LogDebug("Packet data {PacketData}", JsonConvert.SerializeObject(packet));
|
||||
this.logger.LogTrace("[{TempId}] Packet with ID: {MessageOperationCode} has finished",
|
||||
item.Session.Id,
|
||||
item.OperationCode);
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
namespace Server.Services;
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NetCoreServer;
|
||||
|
||||
public class WonderkingAuthServer : TcpServer, IHostedService
|
||||
{
|
||||
private readonly ILogger<WonderkingAuthServer> logger;
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
public WonderkingAuthServer(IPAddress address, int port, ILogger<WonderkingAuthServer> logger,
|
||||
IServiceProvider serviceProvider) : base(address, port)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
this.Start();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
this.Stop();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected override TcpSession CreateSession() =>
|
||||
ActivatorUtilities.CreateInstance<AuthSession>(this.serviceProvider, this);
|
||||
|
||||
protected override void OnStarting()
|
||||
{
|
||||
this.logger.LogInformation("Starting");
|
||||
base.OnStarting();
|
||||
}
|
||||
|
||||
protected override void OnStarted()
|
||||
{
|
||||
this.logger.LogInformation("Started");
|
||||
base.OnStarted();
|
||||
}
|
||||
|
||||
protected override void OnStopping()
|
||||
{
|
||||
this.logger.LogInformation("Stopping");
|
||||
base.OnStopping();
|
||||
}
|
||||
|
||||
protected override void OnStopped()
|
||||
{
|
||||
this.logger.LogInformation("Stopped");
|
||||
base.OnStopped();
|
||||
}
|
||||
|
||||
protected override void OnError(SocketError error) => this.logger.LogError("An error has occured {Error}", error);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"DB": {
|
||||
"Username": "continuitydevuser",
|
||||
"Host": "perf.rainote.dev",
|
||||
"Password": "7>CU`D2/LKw6hD/7",
|
||||
"Database": "continuity",
|
||||
"Port": "13543"
|
||||
},
|
||||
"Testing": {
|
||||
"CreateAccountOnLogin": true
|
||||
}
|
||||
}
|
2
Wiki.Dockerfile
Normal file
2
Wiki.Dockerfile
Normal file
|
@ -0,0 +1,2 @@
|
|||
FROM nginx:1.25.3-alpine3.18-slim
|
||||
COPY .public /usr/share/nginx/html
|
20
Wiki/topics/Character-Creation-Packet.md
Normal file
20
Wiki/topics/Character-Creation-Packet.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Character Creation Packet
|
||||
|
||||
## Metadata
|
||||
|
||||
**Operation Code**: 15
|
||||
|
||||
### Structure
|
||||
|
||||
| Identifier | Datatype | Size in bytes |
|
||||
|------------|----------|---------------|
|
||||
| Slot | byte | 1 |
|
||||
| Unknown | byte | 1 |
|
||||
| Id | ushort | 2 |
|
||||
| Name | string | 20 |
|
||||
| First Job | byte | 1 |
|
||||
| Gender | byte | 1 |
|
||||
| Hair | byte | 1 |
|
||||
| Eyes | byte | 1 |
|
||||
| Shirt | byte | 1 |
|
||||
| Pants | byte | 1 |
|
58
Wiki/topics/Character-Creation-Response-Packet.md
Normal file
58
Wiki/topics/Character-Creation-Response-Packet.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
# Character Creation Response Packet
|
||||
|
||||
## Metadata
|
||||
|
||||
**Operation Code**: 13
|
||||
|
||||
### Structure
|
||||
|
||||
Total size: 1 + 132
|
||||
|
||||
| Identifier | Datatype | Size in bytes |
|
||||
|----------------|---------------|---------------|
|
||||
| Is Duplicate | byte | 1 |
|
||||
| Character data | CharacterData | 132 |
|
||||
|
||||
### Subtypes
|
||||
|
||||
#### CharacterData
|
||||
|
||||
Total size: 132 bytes
|
||||
|
||||
| Identifier | Datatype | Size in bytes |
|
||||
|------------------------|------------------|---------------|
|
||||
| Character Slot | int | 4 |
|
||||
| Character Name | string | 20 |
|
||||
| Jobs | Job Data | 4 |
|
||||
| Gender | byte | 1 |
|
||||
| Level | unsigned short | 2 |
|
||||
| Exp? | byte | 1 |
|
||||
| Stats | BaseStats | 12 |
|
||||
| Health | int | 4 |
|
||||
| Mana | int | 4 |
|
||||
| Equipped Item Ids | unsigned short[] | 20 * 2 (40) |
|
||||
| Equipped Cash Item Ids | unsigned short[] | 20 * 2 (40) |
|
||||
|
||||
#### Job Data
|
||||
|
||||
Total size: 4 bytes
|
||||
|
||||
| Identifier | Datatype | Size in bytes |
|
||||
|------------|----------|---------------|
|
||||
| First Job | byte | 1 |
|
||||
| Second Job | byte | 1 |
|
||||
| Third Job | byte | 1 |
|
||||
| Fourth Job | byte | 1 |
|
||||
|
||||
#### BaseStats
|
||||
|
||||
Total size: 12 bytes
|
||||
|
||||
| Identifier | Datatype | Size in bytes |
|
||||
|--------------|----------|---------------|
|
||||
| Strength | short | 2 |
|
||||
| Dexterity | short | 2 |
|
||||
| Intelligence | short | 2 |
|
||||
| Vitality | short | 2 |
|
||||
| Luck | short | 2 |
|
||||
| Wisdom | short | 2 |
|
3
Wiki/topics/Home.md
Normal file
3
Wiki/topics/Home.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Continuity
|
||||
|
||||
This is the Wiki for Continuity and additional information regarding Wonderking's architecture
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue