diff --git a/.editorconfig b/.editorconfig
index 4d9252b..e270271 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,453 +1,466 @@
-# 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 = \n© PROJECT-AUTHOR\n
-# 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]
+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
-# 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
+# Don't use this. qualifier
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+
+# 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
-# Disable warnings for using LoggerMessage delegates
-dotnet_diagnostic.CA1848.severity = none
+# CA1725: Parameter names should match base declaration
+dotnet_diagnostic.CA1725.severity = suggestion
-##########################################
-# 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.
-##########################################
\ No newline at end of file
+# 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 = warning
+
+# 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
\ No newline at end of file
diff --git a/.gitea/workflows/server.yaml b/.gitea/workflows/server.yaml
index 95239b7..bdb37bf 100644
--- a/.gitea/workflows/server.yaml
+++ b/.gitea/workflows/server.yaml
@@ -1,13 +1,171 @@
-name: Test if Server can be built
+name: Build, Package and Push Images
run-name: ${{ gitea.actor }} is building the Server application
on: [ push ]
jobs:
- build-server:
+ preprocess:
+ runs-on: ubuntu-latest
+ outputs:
+ sanitized_branch_name: ${{ steps.sanitize.outputs.sanitized_branch_name }}
steps:
- - uses: actions/checkout@v3
- - name: Setup dotnet
- uses: https://github.com/actions/setup-dotnet@v3
- with:
- global-json-file: global.json
- - run: dotnet build Server
+ - 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@v3
+ - name: Setup dotnet
+ uses: https://github.com/actions/setup-dotnet@v3
+ with:
+ dotnet-version: 8.0
+ - name: Install dependencies
+ run: dotnet restore
+ - name: Build
+ run: |
+ dotnet build Server -c Release
+ # dotnet test Server.Tests -c Release
+
+ sonarqube:
+ needs: build
+ runs-on: ubuntu-latest
+ if: github.ref_name == 'master'
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup dotnet
+ uses: https://github.com/actions/setup-dotnet@v3
+ with:
+ dotnet-version: 8.0
+ - 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-11-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 Server -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@v3
+ - 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: Setup Dependency Track Dependencies
+ run: |
+ dotnet tool install --global CycloneDX
+ - name: Generate SBOM
+ run: |
+ dotnet CycloneDX Server/Server.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
+ needs: [ build, preprocess ]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup dotnet
+ uses: https://github.com/actions/setup-dotnet@v3
+ with:
+ dotnet-version: 8.0
+ # 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: Server/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: Server/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
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup dotnet
+ uses: https://github.com/actions/setup-dotnet@v3
+ with:
+ dotnet-version: 8.0
+ - 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: |
+ docker sbom forge.rainote.dev/${{ github.repository }}:${{ needs.preprocess.outputs.sanitized_branch_name }} --format cyclonedx-json --output 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 }}/bom.json"
+
diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj
index 3a39862..8b71371 100644
--- a/Benchmarks/Benchmarks.csproj
+++ b/Benchmarks/Benchmarks.csproj
@@ -5,11 +5,15 @@
enable
enable
preview
- net6.0;net7.0;net8.0
+ net6.0;net7.0
-
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/Benchmarks/BinaryConversionBenchmarks.cs b/Benchmarks/BinaryConversionBenchmarks.cs
index 820502d..74cef4c 100644
--- a/Benchmarks/BinaryConversionBenchmarks.cs
+++ b/Benchmarks/BinaryConversionBenchmarks.cs
@@ -14,30 +14,30 @@ using BenchmarkDotNet.Order;
[ThreadingDiagnoser]
public class BinaryConversionBenchmarks
{
- private byte[] data;
- private int offset;
+ private byte[] _data = null!;
+ private int _offset;
[GlobalSetup]
public void Setup()
{
- this.data = RandomNumberGenerator.GetBytes(4000);
- this.offset = RandomNumberGenerator.GetInt32(0, 3500);
+ this._data = RandomNumberGenerator.GetBytes(4000);
+ this._offset = RandomNumberGenerator.GetInt32(0, 3500);
}
[Benchmark]
- public short BitConverterTest() => BitConverter.ToInt16(this.data, this.offset);
+ public short BitConverterTest() => BitConverter.ToInt16(this._data, this._offset);
[Benchmark]
public short BinaryReader()
{
- using var ms = new MemoryStream(this.data);
+ using var ms = new MemoryStream(this._data);
using var reader = new BinaryReader(ms);
- reader.BaseStream.Position = this.offset;
+ reader.BaseStream.Position = this._offset;
return reader.ReadInt16();
}
[Benchmark]
public short BinaryPrimitives() =>
System.Buffers.Binary.BinaryPrimitives.ReadInt16LittleEndian(
- new ArraySegment(this.data, this.offset, sizeof(short)));
+ new ArraySegment(this._data, this._offset, sizeof(short)));
}
diff --git a/Continuity.sln b/Continuity.sln
index 87391ca..a8a1984 100644
--- a/Continuity.sln
+++ b/Continuity.sln
@@ -4,12 +4,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{7D560FA1-A61C-4B67-8300-835CA5814621}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "build", "build\build.csproj", "{046A3B46-FC08-4B08-A52A-1DC5D426120D}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C1303691-99F6-41CE-BAD3-2CA112D75DBF}"
- ProjectSection(SolutionItems) = preProject
- docker-compose.yml = docker-compose.yml
- EndProjectSection
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wonderking", "Wonderking\Wonderking.csproj", "{6B53A10B-C397-4347-BB00-A12272D0528E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -17,8 +12,6 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {046A3B46-FC08-4B08-A52A-1DC5D426120D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {046A3B46-FC08-4B08-A52A-1DC5D426120D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EDA8B31-3E03-4CA3-87D1-CFEB05C277D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EDA8B31-3E03-4CA3-87D1-CFEB05C277D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EDA8B31-3E03-4CA3-87D1-CFEB05C277D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -27,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
diff --git a/Server/.dockerignore b/Server/.dockerignore
new file mode 100644
index 0000000..a72b3bb
--- /dev/null
+++ b/Server/.dockerignore
@@ -0,0 +1,1227 @@
+### JetBrains template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### ASPNETCore template
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/
+
+### VisualStudio template
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+### Csharp template
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+### Rider template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
diff --git a/Server/AuthSession.cs b/Server/AuthSession.cs
index bdc3168..443d3ae 100644
--- a/Server/AuthSession.cs
+++ b/Server/AuthSession.cs
@@ -1,3 +1,5 @@
+using Wonderking.Packets;
+
namespace Server;
using System.Reflection;
@@ -8,28 +10,28 @@ using Packets;
public class AuthSession : TcpSession
{
- private readonly ILogger logger;
- private readonly IMediator mediator;
+ private readonly ILogger _logger;
+ private readonly IMediator _mediator;
public AuthSession(TcpServer
server, IMediator mediator, ILogger logger) : base(server)
{
- this.mediator = mediator;
- this.logger = logger;
+ this._mediator = mediator;
+ this._logger = logger;
}
public Guid AccountId { get; set; }
public override long Send(byte[] buffer)
{
- this.logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(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);
+ this._logger.LogTrace("Packet of type {Type} is being serialized", type.Name);
var packetIdAttribute = type.GetCustomAttribute();
if (packetIdAttribute == null)
{
@@ -57,40 +59,40 @@ public class AuthSession : TcpSession
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._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);
+ this._logger.LogDebug("Length: {Size} & offset: {Offset}", size, offset);
Span decryptedBuffer = new byte[size];
// xor every value after the first 8 bytes
var dataBuffer = Decrypt(new ArraySegment(buffer, 8, (int)size - 8).ToArray());
- this.logger.LogDebug("Length {Length}", BitConverter.ToUInt16(buffer, 0));
+ 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]);
+ 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("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()));
+ 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);
- _ = this.mediator.Send(rawPacket);
+ _ = this._mediator.Send(rawPacket);
- this.logger.LogInformation("Connection from: {@RemoteEndpoint}", this.Socket.RemoteEndPoint?.ToString());
+ this._logger.LogInformation("Connection from: {@RemoteEndpoint}", this.Socket.RemoteEndPoint?.ToString());
base.OnReceived(decryptedBuffer.ToArray(), offset, decryptedBuffer.Length);
}
diff --git a/Server/ChannelSession.cs b/Server/ChannelSession.cs
index ae11461..593719e 100644
--- a/Server/ChannelSession.cs
+++ b/Server/ChannelSession.cs
@@ -8,34 +8,34 @@ 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 }
+ 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[]
+ 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 _decryptor;
- private readonly ICryptoTransform encryptor;
- private readonly ILogger logger;
- private readonly IMediator mediator;
+ private readonly ICryptoTransform _encryptor;
+ private readonly ILogger _logger;
+ private readonly IMediator _mediator;
public ChannelSession(TcpServer server, IMediator mediator, ILogger logger) : base(server)
{
- this.mediator = mediator;
- this.logger = logger;
+ this._mediator = mediator;
+ this._logger = logger;
var aes = Aes.Create();
- aes.Key = Key;
- aes.IV = Iv;
+ aes.Key = _key;
+ aes.IV = _iv;
aes.Padding = PaddingMode.None;
#pragma warning disable SEC0026
aes.Mode = CipherMode.ECB;
#pragma warning restore SEC0026
- this.decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
- this.encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
+ 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)
@@ -43,12 +43,12 @@ public class ChannelSession : TcpSession
try
{
using (var ms = new MemoryStream(Decrypt(buffer)))
- using (var cs = new CryptoStream(ms, this.decryptor, CryptoStreamMode.Read))
+ using (var cs = new CryptoStream(ms, this._decryptor, CryptoStreamMode.Read))
{
var amountOfReadBytes = cs.Read(buffer);
if (amountOfReadBytes != buffer.Length)
{
- this.logger.LogError("Amount of read bytes is not equal to buffer length.");
+ this._logger.LogError("Amount of read bytes is not equal to buffer length.");
}
}
@@ -56,8 +56,8 @@ public class ChannelSession : TcpSession
}
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));
+ this._logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message);
+ this._logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer));
}
}
diff --git a/Server/Consumers/PacketConsumer.cs b/Server/Consumers/PacketConsumer.cs
index 44c80cf..9b9f7cd 100644
--- a/Server/Consumers/PacketConsumer.cs
+++ b/Server/Consumers/PacketConsumer.cs
@@ -6,13 +6,13 @@ using Services;
public class PacketConsumer : IConsumer
{
- private readonly PacketDistributorService distributorService;
+ private readonly PacketDistributorService _distributorService;
- public PacketConsumer(PacketDistributorService distributorService) => this.distributorService = distributorService;
+ public PacketConsumer(PacketDistributorService distributorService) => this._distributorService = distributorService;
public Task Consume(ConsumeContext context)
{
- this.distributorService.AddPacket(context.Message);
+ this._distributorService.AddPacket(context.Message);
return Task.CompletedTask;
}
}
diff --git a/Server/DB/WonderkingContext.cs b/Server/DB/WonderkingContext.cs
index 0b33c01..2cc9720 100644
--- a/Server/DB/WonderkingContext.cs
+++ b/Server/DB/WonderkingContext.cs
@@ -7,13 +7,13 @@ using Microsoft.Extensions.Logging;
public class WonderkingContext : DbContext
{
- private readonly IConfiguration configuration;
- private readonly ILoggerFactory loggerFactory;
+ private readonly IConfiguration _configuration;
+ private readonly ILoggerFactory _loggerFactory;
public WonderkingContext(ILoggerFactory loggerFactory, IConfiguration configuration)
{
- this.loggerFactory = loggerFactory;
- this.configuration = configuration;
+ this._loggerFactory = loggerFactory;
+ this._configuration = configuration;
}
public DbSet Accounts { get; set; }
@@ -22,8 +22,8 @@ public class WonderkingContext : DbContext
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);
+ $"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(builder =>
diff --git a/Server/Dockerfile b/Server/Dockerfile
index 5bcbaf6..709b557 100644
--- a/Server/Dockerfile
+++ b/Server/Dockerfile
@@ -1,18 +1,28 @@
-FROM mcr.microsoft.com/dotnet/runtime:7.0 AS base
+FROM mcr.microsoft.com/dotnet/runtime:8.0-bookworm-slim AS base
WORKDIR /app
-FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
+FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim AS build
+ARG TARGETARCH
+ENV TZ=Etc/UTC
+ENV DOTNET_TieredPGO=1
+ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
+
+RUN echo "Target: $TARGETARCH"
+RUN echo "Build: $BUILDPLATFORM"
WORKDIR /src
+COPY ["Wonderking/Wonderking.csproj", "Wonderking/"]
COPY ["Server/Server.csproj", "Server/"]
-RUN dotnet restore "Server/Server.csproj"
+RUN dotnet restore "Wonderking/Wonderking.csproj" -a $TARGETARCH
+RUN dotnet restore "Server/Server.csproj" -a $TARGETARCH
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
+RUN dotnet publish "Server/Server.csproj" -c Release -a $TARGETARCH --no-restore -f net8.0 -o /app
FROM base AS final
WORKDIR /app
-COPY --from=publish /app/publish .
-ENTRYPOINT ["dotnet", "Server.dll"]
+COPY --from=publish /app .
+USER $APP_UID
+ENTRYPOINT ["./Server"]
+
+
diff --git a/Server/PacketLoggerMessages.cs b/Server/LoggerMessages/PacketLoggerMessages.cs
similarity index 97%
rename from Server/PacketLoggerMessages.cs
rename to Server/LoggerMessages/PacketLoggerMessages.cs
index 25257b4..3601281 100644
--- a/Server/PacketLoggerMessages.cs
+++ b/Server/LoggerMessages/PacketLoggerMessages.cs
@@ -1,8 +1,8 @@
-namespace Server;
-
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
-using Packets;
+using Wonderking.Packets;
+
+namespace Server.LoggerMessages;
public static partial class PacketLoggerMessages
{
@@ -43,7 +43,6 @@ public static partial class PacketLoggerMessages
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);
diff --git a/Server/PacketHandlers/ChannelSelectionHandler.cs b/Server/PacketHandlers/ChannelSelectionHandler.cs
index a8091b0..12c2030 100644
--- a/Server/PacketHandlers/ChannelSelectionHandler.cs
+++ b/Server/PacketHandlers/ChannelSelectionHandler.cs
@@ -1,23 +1,25 @@
+using Microsoft.EntityFrameworkCore;
+using Wonderking.Packets.Incoming;
+
namespace Server.PacketHandlers;
using DB;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NetCoreServer;
-using Packets.Incoming;
public class ChannelSelectionHandler : IPacketHandler
{
- private readonly IConfiguration configuration;
- private readonly ILogger logger;
- private readonly WonderkingContext wonderkingContext;
+ private readonly IConfiguration _configuration;
+ private readonly ILogger _logger;
+ private readonly WonderkingContext _wonderkingContext;
public ChannelSelectionHandler(IConfiguration configuration, ILogger logger,
WonderkingContext wonderkingContext)
{
- this.configuration = configuration;
- this.logger = logger;
- this.wonderkingContext = wonderkingContext;
+ this._configuration = configuration;
+ this._logger = logger;
+ this._wonderkingContext = wonderkingContext;
}
public ChannelSelectionHandler()
@@ -27,7 +29,9 @@ public class ChannelSelectionHandler : IPacketHandler
public Task HandleAsync(ChannelSelectionPacket packet, TcpSession session)
{
var authSession = (AuthSession)session;
- var charactersOfAccount = this.wonderkingContext.Accounts.FirstOrDefault(a => a.Id == authSession.AccountId);
+ var charactersOfAccount = this._wonderkingContext.Accounts.Include(account => account.Characters)
+ .FirstOrDefault(a => a.Id == authSession.AccountId)
+ ?.Characters;
return Task.CompletedTask;
}
}
diff --git a/Server/PacketHandlers/IPacketHandler.cs b/Server/PacketHandlers/IPacketHandler.cs
index a9f1c86..40448d6 100644
--- a/Server/PacketHandlers/IPacketHandler.cs
+++ b/Server/PacketHandlers/IPacketHandler.cs
@@ -1,8 +1,9 @@
+using Wonderking.Packets;
+
namespace Server.PacketHandlers;
using JetBrains.Annotations;
using NetCoreServer;
-using Packets;
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
public interface IPacketHandler where T : IPacket
diff --git a/Server/PacketHandlers/LoginHandler.cs b/Server/PacketHandlers/LoginHandler.cs
index dbd1a65..35dd997 100644
--- a/Server/PacketHandlers/LoginHandler.cs
+++ b/Server/PacketHandlers/LoginHandler.cs
@@ -1,35 +1,36 @@
-namespace Server.PacketHandlers;
-
using System.Security.Cryptography;
using System.Text;
+using Wonderking.Packets.Incoming;
+using Wonderking.Packets.Outgoing;
+
+namespace Server.PacketHandlers;
+
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
{
- private readonly IConfiguration configuration;
- private readonly ILogger logger;
- private readonly WonderkingContext wonderkingContext;
+ private readonly IConfiguration _configuration;
+ private readonly ILogger _logger;
+ private readonly WonderkingContext _wonderkingContext;
public LoginHandler(ILogger logger, WonderkingContext wonderkingContext, IConfiguration configuration)
{
- this.logger = logger;
- this.wonderkingContext = wonderkingContext;
- this.configuration = configuration;
+ this._logger = logger;
+ this._wonderkingContext = wonderkingContext;
+ this._configuration = configuration;
}
public async Task HandleAsync(LoginInfoPacket packet, TcpSession session)
{
LoginResponseReason loginResponseReason;
- this.logger.LogInformation("Login data: Username {Username} & Password {Password}", packet.Username,
+ this._logger.LogInformation("Login data: Username {Username} & Password {Password}", packet.Username,
packet.Password);
- var account = this.wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username);
+ var account = this._wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username);
// 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."
@@ -41,22 +42,22 @@ public class LoginHandler : IPacketHandler
};
if (account == null)
{
- if (this.configuration.GetSection("Testing").GetValue("CreateAccountOnLogin"))
+ if (this._configuration.GetSection("Testing").GetValue("CreateAccountOnLogin"))
{
argon2Id.Salt = RandomNumberGenerator.GetBytes(16);
var finalAccount =
- await this.wonderkingContext.Accounts.AddAsync(new Account(packet.Username, Array.Empty(), "",
+ await this._wonderkingContext.Accounts.AddAsync(new Account(packet.Username, Array.Empty(), "",
0, argon2Id.Salt)).ConfigureAwait(true);
- await this.wonderkingContext.SaveChangesAsync().ConfigureAwait(true);
+ await this._wonderkingContext.SaveChangesAsync().ConfigureAwait(true);
argon2Id.AssociatedData = finalAccount.Entity.Id.ToByteArray();
finalAccount.Entity.Password = await argon2Id.GetBytesAsync(16).ConfigureAwait(true);
- this.wonderkingContext.Accounts.Update(finalAccount.Entity);
+ this._wonderkingContext.Accounts.Update(finalAccount.Entity);
loginResponseReason = LoginResponseReason.Ok;
- await this.wonderkingContext.SaveChangesAsync().ConfigureAwait(true);
+ await this._wonderkingContext.SaveChangesAsync().ConfigureAwait(true);
}
else
{
- this.logger.LogInformation("Requested account for user: {Username} does not exist", packet.Username);
+ this._logger.LogInformation("Requested account for user: {Username} does not exist", packet.Username);
loginResponseReason = LoginResponseReason.AccountDoesNotExit;
}
}
@@ -78,12 +79,9 @@ public class LoginHandler : IPacketHandler
IsGameMaster = true
};
var sess = session as AuthSession;
- if (account != null)
+ if (account != null && sess != null)
{
- if (sess != null)
- {
- sess.AccountId = account.Id;
- }
+ sess.AccountId = account.Id;
}
sess?.Send(loginResponsePacket);
diff --git a/Server/Packets/RawPacket.cs b/Server/Packets/RawPacket.cs
index 6f96690..11e7ca0 100644
--- a/Server/Packets/RawPacket.cs
+++ b/Server/Packets/RawPacket.cs
@@ -1,3 +1,5 @@
+using Wonderking.Packets;
+
namespace Server.Packets;
using MassTransit;
diff --git a/Server/Program.cs b/Server/Program.cs
index 76327dd..3241823 100644
--- a/Server/Program.cs
+++ b/Server/Program.cs
@@ -1,4 +1,3 @@
-#pragma warning disable AV1500
using System.Net;
using System.Reflection;
using MassTransit;
@@ -35,11 +34,10 @@ builder.Services.AddHostedService(provider => new WonderkingAuthServer(IPAddress
provider.GetService() ?? throw new InvalidOperationException()));
using var host = builder.Build();
-await using (var scope = host.Services.CreateAsyncScope())
+using (var scope = host.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService();
await db.Database.MigrateAsync().ConfigureAwait(true);
}
await host.RunAsync().ConfigureAwait(true);
-#pragma warning restore AV1500
diff --git a/Server/Server.csproj b/Server/Server.csproj
index 34e1cef..cfa8679 100644
--- a/Server/Server.csproj
+++ b/Server/Server.csproj
@@ -2,13 +2,32 @@
Exe
- net7.0
enable
warnings
Linux
Server
default
true
+ net8.0;net7.0
+ true
+ strict
+ Timothy (RaiNote) Schenk
+ Timothy (RaiNote) Schenk
+ https://forge.rainote.dev/wonderking/continuity
+ https://forge.rainote.dev/wonderking/continuity
+ git
+ False
+ True
+ LICENSE
+ latest-recommended
+
+
+
+ 7
+
+
+
+ 7
@@ -18,26 +37,35 @@
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
@@ -68,4 +96,15 @@
Always
+
+
+
+ True
+ \
+
+
+
+
+
+
diff --git a/Server/Services/PacketDistributorService.cs b/Server/Services/PacketDistributorService.cs
index 65b3b51..79f9c34 100644
--- a/Server/Services/PacketDistributorService.cs
+++ b/Server/Services/PacketDistributorService.cs
@@ -1,3 +1,6 @@
+using Server.LoggerMessages;
+using Wonderking.Packets;
+
namespace Server.Services;
using System.Collections.Concurrent;
@@ -17,35 +20,32 @@ using static DotNext.Metaprogramming.CodeGenerator;
public class PacketDistributorService : IHostedService
{
- private readonly ConcurrentQueue concurrentQueue;
+ private readonly ConcurrentQueue _concurrentQueue;
private readonly
ImmutableDictionary> deserializationMap;
+ Func> _deserializationMap;
- private readonly ILogger logger;
- private readonly ConcurrentDictionary packetHandlersInstantiation;
-
- private readonly IServiceProvider serviceProvider;
+ private readonly ILogger _logger;
+ private readonly ConcurrentDictionary _packetHandlersInstantiation;
public PacketDistributorService(ILogger logger, IServiceProvider serviceProvider)
{
- this.concurrentQueue = new ConcurrentQueue();
- this.logger = logger;
- this.serviceProvider = serviceProvider;
+ this._concurrentQueue = new ConcurrentQueue();
+ this._logger = logger;
var tempDeserializationMap =
new Dictionary>();
var executingAssembly = Assembly.GetExecutingAssembly();
var packetsTypes = this.GetPacketsWithId(executingAssembly);
var packetHandlers = this.GetAllPacketHandlersWithId(executingAssembly);
- this.packetHandlersInstantiation = new ConcurrentDictionary();
+ this._packetHandlersInstantiation = new ConcurrentDictionary();
packetHandlers.ForEach(x =>
{
var packetHandler =
- ActivatorUtilities.GetServiceOrCreateInstance(this.serviceProvider,
+ ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider,
x.Value);
- this.packetHandlersInstantiation.TryAdd(x.Key, packetHandler);
+ this._packetHandlersInstantiation.TryAdd(x.Key, packetHandler);
});
foreach (var packetsType in packetsTypes)
{
@@ -64,7 +64,7 @@ public class PacketDistributorService : IHostedService
tempDeserializationMap.Add(packetsType.Key, lambda);
}
- this.deserializationMap = tempDeserializationMap.ToImmutableDictionary();
+ this._deserializationMap = tempDeserializationMap.ToImmutableDictionary();
}
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
@@ -82,45 +82,56 @@ public class PacketDistributorService : IHostedService
if (packetsWithId is not { Count: 0 })
{
packetsWithId.AsParallel()
- .ForAll(packet => this.logger.PacketWithIdAdded(packet.Key, packet.Value.FullName));
+ .ForAll(packet => this._logger.PacketWithIdAdded(packet.Key, packet.Value.FullName));
return packetsWithId;
}
- this.logger.NoPacketsFound();
+ this._logger.NoPacketsFound();
throw new IncompleteInitialization();
}
private Dictionary 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 is { IsGenericType: true } && t.GetGenericTypeDefinition() == typeof(IPacketHandler<>))
- .GetGenericArguments().First().GetCustomAttribute().Code);
+ // ! : 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()?.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 =>
- this.logger.PacketHandlerWithIdAdded(packetHandler.Key, packetHandler.Value.FullName));
+ this._logger.PacketHandlerWithIdAdded(packetHandler.Key, packetHandler.Value.FullName));
return packetHandlersWithId;
}
- this.logger.NoPacketHandlersFound();
+ this._logger.NoPacketHandlersFound();
throw new IncompleteInitialization();
}
public void AddPacket(RawPacket rawPacket)
{
- this.concurrentQueue.Enqueue(rawPacket);
+ this._concurrentQueue.Enqueue(rawPacket);
this.DequeueRawPacket();
- this.logger.PacketReceived(rawPacket.OperationCode);
+ this._logger.PacketReceived(rawPacket.OperationCode);
}
private void DequeueRawPacket()
{
- if (this.concurrentQueue.TryDequeue(out var item))
+ if (this._concurrentQueue.TryDequeue(out var item))
{
ThreadPool.QueueUserWorkItem(this.InvokePacketHandler, item, true);
}
@@ -128,18 +139,19 @@ public class PacketDistributorService : IHostedService
private void InvokePacketHandler(RawPacket item)
{
- this.logger.PacketDequeued(item.Session.Id, item.OperationCode);
- if (!this.deserializationMap.ContainsKey(item.OperationCode))
+ this._logger.PacketDequeued(item.Session.Id, item.OperationCode);
+ if (!this._deserializationMap.TryGetValue(item.OperationCode, out var value))
{
- this.logger.PacketTypeNotFound(item.OperationCode);
+ this._logger.PacketTypeNotFound(item.OperationCode);
return;
}
- var packet = this.deserializationMap[item.OperationCode](item.MessageBody);
- this.logger.PacketData(JsonConvert.SerializeObject(packet));
- this.packetHandlersInstantiation[item.OperationCode].GetType().GetMethod(nameof(IPacketHandler.HandleAsync))
- ?.Invoke(this.packetHandlersInstantiation[item.OperationCode], new object[] { packet, item.Session });
+ var packet = value(item.MessageBody);
+ this._logger.PacketData(JsonConvert.SerializeObject(packet));
+ this._packetHandlersInstantiation[item.OperationCode].GetType()
+ .GetMethod(nameof(IPacketHandler.HandleAsync))
+ ?.Invoke(this._packetHandlersInstantiation[item.OperationCode], new object[] { packet, item.Session });
- this.logger.PacketFinished(item.Session.Id, item.OperationCode);
+ this._logger.PacketFinished(item.Session.Id, item.OperationCode);
}
}
diff --git a/Server/Services/WonderkingAuthServer.cs b/Server/Services/WonderkingAuthServer.cs
index 6cbb8e7..fd9d6e1 100644
--- a/Server/Services/WonderkingAuthServer.cs
+++ b/Server/Services/WonderkingAuthServer.cs
@@ -9,14 +9,14 @@ using NetCoreServer;
public class WonderkingAuthServer : TcpServer, IHostedService
{
- private readonly ILogger logger;
- private readonly IServiceProvider serviceProvider;
+ private readonly ILogger _logger;
+ private readonly IServiceProvider _serviceProvider;
public WonderkingAuthServer(IPAddress address, int port, ILogger logger,
IServiceProvider serviceProvider) : base(address, port)
{
- this.logger = logger;
- this.serviceProvider = serviceProvider;
+ this._logger = logger;
+ this._serviceProvider = serviceProvider;
}
public Task StartAsync(CancellationToken cancellationToken)
@@ -32,31 +32,31 @@ public class WonderkingAuthServer : TcpServer, IHostedService
}
protected override TcpSession CreateSession() =>
- ActivatorUtilities.CreateInstance(this.serviceProvider, this);
+ ActivatorUtilities.CreateInstance(this._serviceProvider, this);
protected override void OnStarting()
{
- this.logger.LogInformation("Starting");
+ this._logger.LogInformation("Starting");
base.OnStarting();
}
protected override void OnStarted()
{
- this.logger.LogInformation("Started");
+ this._logger.LogInformation("Started");
base.OnStarted();
}
protected override void OnStopping()
{
- this.logger.LogInformation("Stopping");
+ this._logger.LogInformation("Stopping");
base.OnStopping();
}
protected override void OnStopped()
{
- this.logger.LogInformation("Stopped");
+ this._logger.LogInformation("Stopped");
base.OnStopped();
}
- protected override void OnError(SocketError error) => this.logger.LogError("An error has occured {Error}", error);
+ protected override void OnError(SocketError error) => this._logger.LogError("An error has occured {Error}", error);
}
diff --git a/Server/docker-compose.yml b/Server/docker-compose.yml
index 5cbd3e9..1efa332 100644
--- a/Server/docker-compose.yml
+++ b/Server/docker-compose.yml
@@ -1,6 +1,9 @@
services:
server:
- image: continuity-server:latest
+ container_name: continuity-server
+ image: server:latest
+ depends_on:
+ - db
environment:
- ENVIRONMENT=Development
- Testing:CreateAccountOnLogin=true
@@ -14,6 +17,7 @@
- "10001:10001"
db:
+ container_name: continuity-db
image: postgres:16.0-alpine
environment:
- POSTGRES_USER=continuity
@@ -23,6 +27,11 @@
- continuity
volumes:
- db-data:/var/lib/postgresql/data
+ healthcheck:
+ test: [ "CMD-SHELL", "sh -c 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}'" ]
+ interval: 10s
+ timeout: 3s
+ retries: 3
networks:
continuity:
diff --git a/Server/Packets/IPacket.cs b/Wonderking/Packets/IPacket.cs
similarity index 86%
rename from Server/Packets/IPacket.cs
rename to Wonderking/Packets/IPacket.cs
index e5d5317..fa795eb 100644
--- a/Server/Packets/IPacket.cs
+++ b/Wonderking/Packets/IPacket.cs
@@ -1,7 +1,7 @@
-namespace Server.Packets;
-
using JetBrains.Annotations;
+namespace Wonderking.Packets;
+
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
public interface IPacket
{
diff --git a/Server/Packets/Incoming/ChannelSelectionPacket.cs b/Wonderking/Packets/Incoming/ChannelSelectionPacket.cs
similarity index 77%
rename from Server/Packets/Incoming/ChannelSelectionPacket.cs
rename to Wonderking/Packets/Incoming/ChannelSelectionPacket.cs
index ea17fb4..c74e385 100644
--- a/Server/Packets/Incoming/ChannelSelectionPacket.cs
+++ b/Wonderking/Packets/Incoming/ChannelSelectionPacket.cs
@@ -1,4 +1,4 @@
-namespace Server.Packets.Incoming;
+namespace Wonderking.Packets.Incoming;
[PacketId(OperationCode.ChannelSelection)]
public class ChannelSelectionPacket : IPacket
@@ -12,5 +12,5 @@ public class ChannelSelectionPacket : IPacket
this.ChannelId = BitConverter.ToUInt16(data, 2);
}
- public byte[] Serialize() => throw new NotImplementedException();
+ public byte[] Serialize() => throw new NotSupportedException();
}
diff --git a/Server/Packets/Incoming/LoginInfoPacket.cs b/Wonderking/Packets/Incoming/LoginInfoPacket.cs
similarity index 96%
rename from Server/Packets/Incoming/LoginInfoPacket.cs
rename to Wonderking/Packets/Incoming/LoginInfoPacket.cs
index 4351884..4758ef7 100644
--- a/Server/Packets/Incoming/LoginInfoPacket.cs
+++ b/Wonderking/Packets/Incoming/LoginInfoPacket.cs
@@ -1,7 +1,7 @@
-namespace Server.Packets.Incoming;
-
using System.Text;
+namespace Wonderking.Packets.Incoming;
+
[PacketId(OperationCode.LoginInfo)]
public class LoginInfoPacket : IPacket
{
diff --git a/Server/Packets/OperationCode.cs b/Wonderking/Packets/OperationCode.cs
similarity index 77%
rename from Server/Packets/OperationCode.cs
rename to Wonderking/Packets/OperationCode.cs
index 578c544..f8b9eea 100644
--- a/Server/Packets/OperationCode.cs
+++ b/Wonderking/Packets/OperationCode.cs
@@ -1,4 +1,4 @@
-namespace Server.Packets;
+namespace Wonderking.Packets;
public enum OperationCode : ushort
{
diff --git a/Server/Packets/Outgoing/LoginResponsePacket.cs b/Wonderking/Packets/Outgoing/LoginResponsePacket.cs
similarity index 98%
rename from Server/Packets/Outgoing/LoginResponsePacket.cs
rename to Wonderking/Packets/Outgoing/LoginResponsePacket.cs
index 63299fe..057d032 100644
--- a/Server/Packets/Outgoing/LoginResponsePacket.cs
+++ b/Wonderking/Packets/Outgoing/LoginResponsePacket.cs
@@ -1,4 +1,4 @@
-namespace Server.Packets.Outgoing;
+namespace Wonderking.Packets.Outgoing;
[PacketId(OperationCode.LoginResponse)]
public class LoginResponsePacket : IPacket
diff --git a/Server/Packets/Outgoing/LoginResponseReason.cs b/Wonderking/Packets/Outgoing/LoginResponseReason.cs
similarity index 92%
rename from Server/Packets/Outgoing/LoginResponseReason.cs
rename to Wonderking/Packets/Outgoing/LoginResponseReason.cs
index b4e8bff..adc830f 100644
--- a/Server/Packets/Outgoing/LoginResponseReason.cs
+++ b/Wonderking/Packets/Outgoing/LoginResponseReason.cs
@@ -1,4 +1,4 @@
-namespace Server.Packets.Outgoing;
+namespace Wonderking.Packets.Outgoing;
public enum LoginResponseReason : byte
{
diff --git a/Server/Packets/Outgoing/ServerChannelData.cs b/Wonderking/Packets/Outgoing/ServerChannelData.cs
similarity index 60%
rename from Server/Packets/Outgoing/ServerChannelData.cs
rename to Wonderking/Packets/Outgoing/ServerChannelData.cs
index a6eee00..b707c4a 100644
--- a/Server/Packets/Outgoing/ServerChannelData.cs
+++ b/Wonderking/Packets/Outgoing/ServerChannelData.cs
@@ -1,5 +1,8 @@
-namespace Server.Packets.Outgoing;
+using System.Runtime.InteropServices;
+namespace Wonderking.Packets.Outgoing;
+
+[StructLayout(LayoutKind.Auto)]
public struct ServerChannelData
{
public ushort ServerId { get; set; }
diff --git a/Server/Packets/PacketIdAttribute.cs b/Wonderking/Packets/PacketIdAttribute.cs
similarity index 87%
rename from Server/Packets/PacketIdAttribute.cs
rename to Wonderking/Packets/PacketIdAttribute.cs
index 6638733..e2f2b5a 100644
--- a/Server/Packets/PacketIdAttribute.cs
+++ b/Wonderking/Packets/PacketIdAttribute.cs
@@ -1,4 +1,4 @@
-namespace Server.Packets;
+namespace Wonderking.Packets;
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class PacketIdAttribute : Attribute
diff --git a/Wonderking/Wonderking.csproj b/Wonderking/Wonderking.csproj
new file mode 100644
index 0000000..e8fbd2c
--- /dev/null
+++ b/Wonderking/Wonderking.csproj
@@ -0,0 +1,34 @@
+
+
+
+ enable
+ enable
+ net8.0;net7.0
+ strict
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
diff --git a/build.cmd b/build.cmd
deleted file mode 100644
index b08cc59..0000000
--- a/build.cmd
+++ /dev/null
@@ -1,7 +0,0 @@
-:; set -eo pipefail
-:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
-:; ${SCRIPT_DIR}/build.sh "$@"
-:; exit $?
-
-@ECHO OFF
-powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*
diff --git a/build.ps1 b/build.ps1
deleted file mode 100644
index 2719418..0000000
--- a/build.ps1
+++ /dev/null
@@ -1,74 +0,0 @@
-[CmdletBinding()]
-Param(
- [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
- [string[]]$BuildArguments
-)
-
-Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
-
-Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
-$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
-
-###########################################################################
-# CONFIGURATION
-###########################################################################
-
-$BuildProjectFile = "$PSScriptRoot\build\build.csproj"
-$TempDirectory = "$PSScriptRoot\\.nuke\temp"
-
-$DotNetGlobalFile = "$PSScriptRoot\\global.json"
-$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
-$DotNetChannel = "STS"
-
-$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
-$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
-$env:DOTNET_MULTILEVEL_LOOKUP = 0
-
-###########################################################################
-# EXECUTION
-###########################################################################
-
-function ExecSafe([scriptblock] $cmd) {
- & $cmd
- if ($LASTEXITCODE) { exit $LASTEXITCODE }
-}
-
-# If dotnet CLI is installed globally and it matches requested version, use for execution
-if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
- $(dotnet --version) -and $LASTEXITCODE -eq 0) {
- $env:DOTNET_EXE = (Get-Command "dotnet").Path
-}
-else {
- # Download install script
- $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
- New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
- (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
-
- # If global.json exists, load expected version
- if (Test-Path $DotNetGlobalFile) {
- $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
- if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
- $DotNetVersion = $DotNetGlobal.sdk.version
- }
- }
-
- # Install by channel or version
- $DotNetDirectory = "$TempDirectory\dotnet-win"
- if (!(Test-Path variable:DotNetVersion)) {
- ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
- } else {
- ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
- }
- $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
-}
-
-Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)"
-
-if (Test-Path env:NUKE_ENTERPRISE_TOKEN) {
- & $env:DOTNET_EXE nuget remove source "nuke-enterprise" > $null
- & $env:DOTNET_EXE nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password $env:NUKE_ENTERPRISE_TOKEN > $null
-}
-
-ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
-ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
diff --git a/build.sh b/build.sh
deleted file mode 100644
index 25e0d46..0000000
--- a/build.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env bash
-
-bash --version 2>&1 | head -n 1
-
-set -eo pipefail
-SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
-
-###########################################################################
-# CONFIGURATION
-###########################################################################
-BUILD_PROJECT_FILE="$SCRIPT_DIR/build/build.csproj"
-TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp"
-
-DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
-DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
-DOTNET_CHANNEL="STS"
-
-export DOTNET_CLI_TELEMETRY_OPTOUT=1
-export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
-export DOTNET_MULTILEVEL_LOOKUP=0
-
-###########################################################################
-# EXECUTION
-###########################################################################
-
-function FirstJsonValue {
- perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
-}
-
-# If dotnet CLI is installed globally and it matches requested version, use for execution
-if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
- export DOTNET_EXE="$(command -v dotnet)"
-else
- # Download install script
- DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
- mkdir -p "$TEMP_DIRECTORY"
- curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
- chmod +x "$DOTNET_INSTALL_FILE"
-
- # If global.json exists, load expected version
- if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
- DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
- if [[ "$DOTNET_VERSION" == "" ]]; then
- unset DOTNET_VERSION
- fi
- fi
-
- # Install by channel or version
- DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
- if [[ -z ${DOTNET_VERSION+x} ]]; then
- "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
- else
- "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
- fi
- export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
-fi
-
-echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)"
-
-if [[ ! -z ${NUKE_ENTERPRISE_TOKEN+x} && "$NUKE_ENTERPRISE_TOKEN" != "" ]]; then
- "$DOTNET_EXE" nuget remove source "nuke-enterprise" &>/dev/null || true
- "$DOTNET_EXE" nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password "$NUKE_ENTERPRISE_TOKEN" --store-password-in-clear-text &>/dev/null || true
-fi
-
-"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
-"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
diff --git a/build/.editorconfig b/build/.editorconfig
deleted file mode 100644
index 31e43dc..0000000
--- a/build/.editorconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-[*.cs]
-dotnet_style_qualification_for_field = false:warning
-dotnet_style_qualification_for_property = false:warning
-dotnet_style_qualification_for_method = false:warning
-dotnet_style_qualification_for_event = false:warning
-dotnet_style_require_accessibility_modifiers = never:warning
-
-csharp_style_expression_bodied_methods = true:silent
-csharp_style_expression_bodied_properties = true:warning
-csharp_style_expression_bodied_indexers = true:warning
-csharp_style_expression_bodied_accessors = true:warning
diff --git a/build/Build.cs b/build/Build.cs
deleted file mode 100644
index d78a3f3..0000000
--- a/build/Build.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using Nuke.Common;
-using Nuke.Common.Git;
-using Nuke.Common.IO;
-using Nuke.Common.Tools.Docker;
-using Nuke.Common.Tools.DotNet;
-using Nuke.Common.Tools.SonarScanner;
-using Serilog;
-
-class Build : NukeBuild
-{
- /// Support plugins are available for:
- /// - JetBrains ReSharper https://nuke.build/resharper
- /// - JetBrains Rider https://nuke.build/rider
- /// - Microsoft VisualStudio https://nuke.build/visualstudio
- /// - Microsoft VSCode https://nuke.build/vscode
- public static int Main() => Execute(x => x.Information, x => x.Deploy);
-
- [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
- readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
-
- GitRepository GitRepository => GitRepository.FromLocalDirectory(RootDirectory);
-
- Target Information => _ => _
- .Before(Clean)
- .Executes(() =>
- {
- Log.Information("Branch Name: {BranchName}", GitRepository.Branch);
- Log.Information("Commit: {Commit}", GitRepository.Commit);
- });
-
- Target Clean => _ => _
- .Before(Restore)
- .Executes(() => DotNetTasks.DotNetClean());
-
- Target Restore => _ => _
- .Executes(() => DotNetTasks.DotNetRestore());
-
- Target Compile => _ => _
- .DependsOn(Clean)
- .DependsOn(Restore)
- .Executes(() =>
- {
- DockerTasks.DockerStackRm(settings => settings.SetStacks("continuity"));
- DotNetTasks.DotNetBuild(settings => settings.SetNoRestore(true));
- });
-
- Target Pack => _ => _
- .DependsOn(Compile)
- .Executes(() =>
- {
- DockerTasks.DockerBuild(settings => settings
- .SetPath(AbsolutePath.Create(RootDirectory))
- .SetFile("Server/Dockerfile")
- .SetTag("continuity-server:latest")
- .SetCompress(true)
- .SetProgress(ProgressType.auto));
- if (!IsLocalBuild)
- {
- DockerTasks.DockerPush(settings => settings.SetName("continuity-server:latest"));
- }
- });
-
- Target Deploy => _ => _.DependsOn(Pack).Executes(() =>
- {
- DockerTasks.DockerPull(settings => settings.SetName("postgres:16.0-alpine"));
- if (IsLocalBuild)
- {
- var dockerComposeFile = AbsolutePath.Create(RootDirectory / "Server" / "docker-compose.yml");
- DockerTasks.DockerStackDeploy(settings => settings
- .AddComposeFile(dockerComposeFile)
- .SetStack("continuity")
- .SetPrune(true)
- );
- return;
- }
-
- Log.Error("Deploy is only available on local builds.");
- });
-}
diff --git a/build/Configuration.cs b/build/Configuration.cs
deleted file mode 100644
index 5519911..0000000
--- a/build/Configuration.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.ComponentModel;
-using Nuke.Common.Tooling;
-
-[TypeConverter(typeof(TypeConverter))]
-public class Configuration : Enumeration
-{
- public static Configuration Debug { get; } = new() { Value = nameof(Debug) };
- public static Configuration Release { get; } = new() { Value = nameof(Release) };
-
- public static implicit operator string(Configuration configuration) => configuration.Value;
-}
diff --git a/build/Directory.Build.props b/build/Directory.Build.props
deleted file mode 100644
index e147d63..0000000
--- a/build/Directory.Build.props
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/build/Directory.Build.targets b/build/Directory.Build.targets
deleted file mode 100644
index 2532609..0000000
--- a/build/Directory.Build.targets
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/build/build.csproj b/build/build.csproj
deleted file mode 100644
index c97b50f..0000000
--- a/build/build.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- Exe
- net6.0
-
- CS0649;CS0169;CA1050;CA1822;CA2211;IDE1006
- ..
- ..
- 1
- false
-
-
-
-
-
-
-
diff --git a/build/build.csproj.DotSettings b/build/build.csproj.DotSettings
deleted file mode 100644
index eb3f4c2..0000000
--- a/build/build.csproj.DotSettings
+++ /dev/null
@@ -1,28 +0,0 @@
-
- DO_NOT_SHOW
- DO_NOT_SHOW
- DO_NOT_SHOW
- DO_NOT_SHOW
- DO_NOT_SHOW
- Implicit
- Implicit
- ExpressionBody
- 0
- NEXT_LINE
- True
- False
- 120
- IF_OWNER_IS_SINGLE_LINE
- WRAP_IF_LONG
- False
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- True
- True
- True
- True
- True
- True
- True
- True
- True
diff --git a/global.json b/global.json
index c65c9ea..ad3eb2c 100644
--- a/global.json
+++ b/global.json
@@ -1,7 +1,7 @@
{
"sdk": {
- "version": "8.0.0",
- "rollForward": "latestMinor",
+ "version": "7.0.403",
+ "rollForward": "latestMajor",
"allowPrerelease": true
}
}
\ No newline at end of file