From f2d38139f8b5c6fe61cb7d0dfc12577b2ab9ccbb Mon Sep 17 00:00:00 2001 From: Joanna May Date: Sun, 9 Jun 2024 22:15:31 -0500 Subject: [PATCH] feat: initial commit --- .editorconfig | 470 ++++++++++++++++++ .gitattributes | 46 ++ .github/workflows/release.yaml | 99 ++++ .github/workflows/spellcheck.yaml | 26 + .github/workflows/tests.yaml | 68 +++ .gitignore | 11 + .vscode/extensions.json | 10 + .vscode/launch.json | 37 ++ .vscode/settings.json | 169 +++++++ .vscode/tasks.json | 40 ++ CONTRIBUTING.md | 38 ++ .../.editorconfig | 8 + .../Chickensoft.SaveFileBuilder.Tests.csproj | 36 ++ .../Chickensoft.SaveFileBuilder.Tests.sln | 19 + .../badges/.gdignore | 0 .../badges/branch_coverage.svg | 3 + .../badges/line_coverage.svg | 3 + Chickensoft.SaveFileBuilder.Tests/coverage.sh | 81 +++ .../coverage/.gdignore | 0 Chickensoft.SaveFileBuilder.Tests/icon.svg | 3 + .../icon.svg.import | 37 ++ .../nuget.config | 8 + .../project.godot | 24 + .../test/Tests.cs | 12 + .../test/Tests.tscn | 6 + .../test/src/SaveChunkTest.cs | 57 +++ .../test/src/SaveFileTest.cs | 47 ++ Chickensoft.SaveFileBuilder.sln | 28 ++ .../Chickensoft.SaveFileBuilder.csproj | 52 ++ Chickensoft.SaveFileBuilder/icon.png | 3 + Chickensoft.SaveFileBuilder/src/SaveChunk.cs | 91 ++++ Chickensoft.SaveFileBuilder/src/SaveFile.cs | 70 +++ LICENSE | 21 + README.md | 143 ++++++ cspell.json | 72 +++ docs/renovatebot_pr.png | 3 + docs/spelling_fix.png | 3 + global.json | 9 + renovate.json | 38 ++ 39 files changed, 1891 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/spellcheck.yaml create mode 100644 .github/workflows/tests.yaml create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 CONTRIBUTING.md create mode 100644 Chickensoft.SaveFileBuilder.Tests/.editorconfig create mode 100644 Chickensoft.SaveFileBuilder.Tests/Chickensoft.SaveFileBuilder.Tests.csproj create mode 100644 Chickensoft.SaveFileBuilder.Tests/Chickensoft.SaveFileBuilder.Tests.sln create mode 100644 Chickensoft.SaveFileBuilder.Tests/badges/.gdignore create mode 100644 Chickensoft.SaveFileBuilder.Tests/badges/branch_coverage.svg create mode 100644 Chickensoft.SaveFileBuilder.Tests/badges/line_coverage.svg create mode 100755 Chickensoft.SaveFileBuilder.Tests/coverage.sh create mode 100644 Chickensoft.SaveFileBuilder.Tests/coverage/.gdignore create mode 100644 Chickensoft.SaveFileBuilder.Tests/icon.svg create mode 100644 Chickensoft.SaveFileBuilder.Tests/icon.svg.import create mode 100644 Chickensoft.SaveFileBuilder.Tests/nuget.config create mode 100644 Chickensoft.SaveFileBuilder.Tests/project.godot create mode 100644 Chickensoft.SaveFileBuilder.Tests/test/Tests.cs create mode 100644 Chickensoft.SaveFileBuilder.Tests/test/Tests.tscn create mode 100644 Chickensoft.SaveFileBuilder.Tests/test/src/SaveChunkTest.cs create mode 100644 Chickensoft.SaveFileBuilder.Tests/test/src/SaveFileTest.cs create mode 100644 Chickensoft.SaveFileBuilder.sln create mode 100644 Chickensoft.SaveFileBuilder/Chickensoft.SaveFileBuilder.csproj create mode 100644 Chickensoft.SaveFileBuilder/icon.png create mode 100644 Chickensoft.SaveFileBuilder/src/SaveChunk.cs create mode 100644 Chickensoft.SaveFileBuilder/src/SaveFile.cs create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cspell.json create mode 100644 docs/renovatebot_pr.png create mode 100644 docs/spelling_fix.png create mode 100644 global.json create mode 100644 renovate.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a9e0a78 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,470 @@ +# --------------------------------------------------------------------------- # +# Chickensoft C# Style — .editorconfig # +# --------------------------------------------------------------------------- # +# Godot-friendly, K&R coding style with a bit of Dart-style flair thrown in. # +# --------------------------------------------------------------------------- # +# # +# # +# ╓╗_▄╗_╓▄_ # +# ▄▄╟▓▓▓▓▓▓▓▓ # +# ╙▓▓▓▀▀╠╠╦╦╓,_ # +# ,φ╠╠╠╠╠╠╠╠╠╠▒╥ # +# φ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╦ # +# @╠╠╫▌╠╟▌╠╠╠╠╠╠╠╠╠ # +# ╠╠╠▄▄▄▒╠╠╠╠╠╠╠╠╠╠b # +# ╠╠╨███▌╠╠╠╠╠╠╠▒╠╠▒_ ç╓ # +# ╠╠╠╠▒▒╠╠╠╠╠╠╠╠▒Å▄╠╬▒φ╩ε # +# ╚╠╠╠╠╠╠╠╠╠╠╠▒█▒╫█Å╠╠╩ # +# ╠╠╠╠╠╠╠╠╠╠╠╠╠╟╫▒╠╠╩ # +# ╙╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╜ # +# ╙╚╠╠╠╠╠╠╠╠╩╙ # +# ╒ µ # +# ▌ ▓ # +# ^▀▀ "▀ª # +# # +# # +# --------------------------------------------------------------------------- # +# +# Based on: +# - https://github.com/RehanSaeed/EditorConfig/blob/main/.editorconfig +# - https://gist.github.com/FaronBracy/155d8d7ad98b4ceeb526b9f47543db1b +# - various other gists floating around :) +# +# Have a problem? Encounter an issue? +# Come visit our Discord and let us know! https://discord.gg/MjA6HUzzAE +# +# Based on https://github.com/RehanSaeed/EditorConfig/blob/main/.editorconfig +# and https://gist.github.com/FaronBracy/155d8d7ad98b4ceeb526b9f47543db1b + +# This file is the top-most EditorConfig file +root = true + +# All Files +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = 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 + +[*_Generated.cs, *.g.cs, *.generated.cs] +# Ignore a lack of documentation for generated code. Doesn't apply to builds, +# just to viewing generation output. +dotnet_diagnostic.CS1591.severity = none + +########################################## +# Default .NET Code Style Severities +########################################## + +[*.{cs,csx,cake,vb,vbx}] +# Default Severity for all .NET Code Style rules below +dotnet_analyzer_diagnostic.severity = warning + +########################################## +# Language Rules +########################################## + +# .NET Style Rules +[*.{cs,csx,cake,vb,vbx}] + +# "this." and "Me." qualifiers +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_property = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_event = false + +# 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 = true:suggestion +dotnet_diagnostic.IDE0045.severity = suggestion +dotnet_style_prefer_conditional_expression_over_return = true: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 +# Keep operators at end of line when wrapping. +dotnet_style_operator_placement_when_wrapping = end_of_line:warning +csharp_style_prefer_null_check_over_type_check = true:warning + +# Code block preferences +csharp_prefer_braces = true:warning +csharp_prefer_simple_using_statement = true:suggestion +dotnet_diagnostic.IDE0063.severity = suggestion + +# 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 = false: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 +# Don't suggest making public methods static. Very annoying. +csharp_prefer_static_local_function = false +# Only suggest making private methods static (if they don't use instance data). +dotnet_code_quality.CA1822.api_surface = private + +########################################## +# Unnecessary Code Rules +########################################## + +# .NET Unnecessary code rules +[*.{cs,csx,cake,vb,vbx}] + +dotnet_code_quality_unused_parameters = non_public:suggestion +dotnet_remove_unnecessary_suppression_exclusions = none +dotnet_diagnostic.IDE0079.severity = warning + +# C# Unnecessary code rules +[*.{cs,csx,cake}] + +# Chickensoft Unused Code Additions +# +# Unfortunately for VSCode users, disabling these rules prevents you from +# detecting unused code. Enabling them will trigger the roslyn analyzers' +# automatic code fixes to remove unused code, which is very annoying when +# you're actively coding or using reflection. +# +# I have not found a way to disable automatic fixes while keeping +# warnings/suggestions/etc in the editor. If you find a way, please file an +# issue or open a PR. + +# Don't remove method parameters that are unused. +dotnet_diagnostic.IDE0060.severity = none +dotnet_diagnostic.RCS1163.severity = none + +# Don't remove methods that are unused. +dotnet_diagnostic.IDE0051.severity = none +dotnet_diagnostic.RCS1213.severity = none + +# Use discard variable for unused expression values. +csharp_style_unused_value_expression_statement_preference = discard_variable + +# .NET formatting rules +[*.{cs,csx,cake,vb,vbx}] + +# Organize using directives +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false + +# Dotnet namespace options +# +# We don't care about namespaces matching folder structure. Games and apps +# are complicated and you are free to organize them however you like. Change +# this if you want to enforce it. +dotnet_style_namespace_match_folder = false +dotnet_diagnostic.IDE0130.severity = none + +# C# formatting rules +[*.{cs,csx,cake}] + +# Newline options +csharp_new_line_before_open_brace = none +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 +csharp_indent_switch_labels = true +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = no_change +csharp_indent_block_contents = true +csharp_indent_braces = false + +# 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 +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +# Namespace options +csharp_style_namespace_declarations = file_scoped:warning + +########################################## +# .NET Naming Rules +########################################## +[*.{cs,csx,cake,vb,vbx}] + +########################################## +# Chickensoft Naming Conventions & Styles +# These deviate heavily from Microsoft's Offical Naming Conventions. +########################################## + +# Allow underscores in names. +dotnet_diagnostic.CA1707.severity = none + +# Styles +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +dotnet_naming_style.upper_case_style.capitalization = all_upper +dotnet_naming_style.upper_case_style.word_separator = _ + +dotnet_naming_style.camel_case_style.capitalization = camel_case + +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# Use uppercase for all constant fields. +dotnet_naming_rule.constants_uppercase.severity = suggestion +dotnet_naming_rule.constants_uppercase.symbols = constant_fields +dotnet_naming_rule.constants_uppercase.style = upper_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.applicable_accessibilities = * +dotnet_naming_symbols.constant_fields.required_modifiers = const + +# Non-public fields should be _camelCase +dotnet_naming_rule.non_public_fields_under_camel.severity = suggestion +dotnet_naming_rule.non_public_fields_under_camel.symbols = non_public_fields +dotnet_naming_rule.non_public_fields_under_camel.style = camel_case_underscore_style +dotnet_naming_symbols.non_public_fields.applicable_kinds = field +dotnet_naming_symbols.non_public_fields.required_modifiers = +dotnet_naming_symbols.non_public_fields.applicable_accessibilities = private,private_protected,protected,internal,protected,protected_internal + +# Public fields should be PascalCase +dotnet_naming_rule.public_fields_pascal.severity = suggestion +dotnet_naming_rule.public_fields_pascal.symbols = public_fields +dotnet_naming_rule.public_fields_pascal.style = pascal_case_style +dotnet_naming_symbols.public_fields.applicable_kinds = field +dotnet_naming_symbols.public_fields.required_modifiers = +dotnet_naming_symbols.public_fields.applicable_accessibilities = public + +# Async methods should have "Async" suffix. +# Disabled because it makes tests too verbose. +# dotnet_naming_style.end_in_async.required_suffix = Async +# dotnet_naming_style.end_in_async.capitalization = pascal_case +# dotnet_naming_rule.methods_end_in_async.symbols = methods_async +# dotnet_naming_rule.methods_end_in_async.style = end_in_async +# dotnet_naming_rule.methods_end_in_async.severity = warning +# dotnet_naming_symbols.methods_async.applicable_kinds = method +# dotnet_naming_symbols.methods_async.required_modifiers = async +# dotnet_naming_symbols.methods_async.applicable_accessibilities = * + +########################################## +# Other Naming Rules +########################################## + +# All of the following must be PascalCase: +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 + +# 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_style.prefix_interface_with_i_style.capitalization = pascal_case +dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I +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 + +# 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_style.prefix_type_parameters_with_t_style.capitalization = pascal_case +dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T +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 + +# 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 + +# Anything not specified uses camel case. +dotnet_naming_rule.unspecified_naming.severity = warning +dotnet_naming_rule.unspecified_naming.symbols = unspecified +dotnet_naming_rule.unspecified_naming.style = camel_case_style +dotnet_naming_symbols.unspecified.applicable_kinds = * +dotnet_naming_symbols.unspecified.applicable_accessibilities = * + +########################################## +# Chickensoft Rule Overrides +########################################## + +# Allow using keywords as names +# dotnet_diagnostic.CA1716.severity = none +# Don't require culture info for ToString() +dotnet_diagnostic.CA1304.severity = none +# Don't require a string comparison for comparing strings. +dotnet_diagnostic.CA1310.severity = none +# Don't require a string format specifier. +dotnet_diagnostic.CA1305.severity = none +# Allow protected fields. +dotnet_diagnostic.CA1051.severity = none +# Don't warn about checking values that are supposedly never null. Sometimes +# they are actually null. +dotnet_diagnostic.CS8073.severity = none +# Don't remove seemingly "unnecessary" assignments, as they often have +# intended side-effects. +dotnet_diagnostic.IDE0059.severity = none +# Switch/case should always have a default clause. Tell that to Roslynator. +dotnet_diagnostic.RCS1070.severity = none +# Tell roslynator not to eat unused parameters. +dotnet_diagnostic.RCS1163.severity = none +# Tell dotnet not to remove unused parameters. +dotnet_diagnostic.IDE0060.severity = none +# Tell roslynator not to remove `partial` modifiers. +dotnet_diagnostic.RCS1043.severity = none +# Tell roslynator not to make classes static so aggressively. +dotnet_diagnostic.RCS1102.severity = none +# Roslynator wants to make properties readonly all the time, so stop it. +# The developer knows best when it comes to contract definitions with Godot. +dotnet_diagnostic.RCS1170.severity = none +# Allow expression values to go unused, even without discard variable. +# Otherwise, using Moq would be way too verbose. +dotnet_diagnostic.IDE0058.severity = none +# Don't let roslynator turn every local variable into a const. +# If we did, we'd have to specify the types of local variables far more often, +# and this style prefers type inference. +dotnet_diagnostic.RCS1118.severity = none +# Enums don't need to declare explicit values. Everyone knows they start at 0. +dotnet_diagnostic.RCS1161.severity = none +# Allow unconstrained type parameter to be checked for null. +dotnet_diagnostic.RCS1165.severity = none +# Allow keyword-based names so that parameter names like `@event` can be used. +dotnet_diagnostic.CA1716.severity = none +# Let me put comments where I like +dotnet_diagnostic.RCS1181.severity = none +# Allow me to use the word Collection if I want. +dotnet_diagnostic.CA1711.severity = none +# No primary constructors — not supported well by tooling. +dotnet_diagnostic.IDE0290.severity = none +# Let me write dumb if statements for readability. +dotnet_diagnostic.IDE0046.severity = none +# Don't make me use expression bodies for methods +dotnet_diagnostic.IDE0022.severity = none +# Don't make me populate a switch expression redundantly +dotnet_diagnostic.IDE0072.severity = none diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3b7ca90 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,46 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf + +# Image formats +*.bmp filter=lfs diff=lfs merge=lfs -text +*.dds filter=lfs diff=lfs merge=lfs -text +*.exr filter=lfs diff=lfs merge=lfs -text +*.hdr filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text +*.jpeg filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.tga filter=lfs diff=lfs merge=lfs -text +*.svg filter=lfs diff=lfs merge=lfs -text +*.webp filter=lfs diff=lfs merge=lfs -text + +# Audio and Video formats +*.mp3 filter=lfs diff=lfs merge=lfs -text +*.wav filter=lfs diff=lfs merge=lfs -text +*.ogg filter=lfs diff=lfs merge=lfs -text +*.ogx filter=lfs diff=lfs merge=lfs -text +*.ogv filter=lfs diff=lfs merge=lfs -text + +# 3D formats +*.gltf filter=lfs diff=lfs merge=lfs -text +*.blend filter=lfs diff=lfs merge=lfs -text +*.blend1 filter=lfs diff=lfs merge=lfs -text +*.glb filter=lfs diff=lfs merge=lfs -text +*.dae filter=lfs diff=lfs merge=lfs -text +*.obj filter=lfs diff=lfs merge=lfs -text +*.fbx filter=lfs diff=lfs merge=lfs -text + +# Build +*.dll filter=lfs diff=lfs merge=lfs -text +*.exe filter=lfs diff=lfs merge=lfs -text +*.pdb filter=lfs diff=lfs merge=lfs -text +*.so filter=lfs diff=lfs merge=lfs -text +*.dylib filter=lfs diff=lfs merge=lfs -text + +# Packaging +*.zip filter=lfs diff=lfs merge=lfs -text +*.7z filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.file filter=lfs diff=lfs merge=lfs -text +*.dylib filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..fa81b5a --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,99 @@ +name: '📦 Release' +on: + # Make a release whenever the developer wants. + workflow_dispatch: + inputs: + bump: + type: string + description: "major, minor, or patch" + required: true + default: "patch" + # Make a release whenever we're told to by another workflow. + workflow_call: + secrets: + NUGET_API_KEY: + description: "API key for Nuget" + required: true + GH_BASIC: + description: "Personal access token (PAT) for GitHub" + required: true + # Input unifies with the workflow dispatch since it's identical. + inputs: + bump: + type: string + description: "major, minor, or patch" + required: true + default: "patch" +jobs: + release: + name: '📦 Release' + runs-on: ubuntu-latest + env: + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_NOLOGO: true + steps: + - name: 🧾 Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.GH_BASIC }} + lfs: true + submodules: 'recursive' + fetch-depth: 0 # So we can get all tags. + + - name: 🔎 Read Current Project Version + id: current-version + uses: WyriHaximus/github-action-get-previous-tag@v1 + with: + fallback: "0.0.0-devbuild" + + - name: 🖨 Print Current Version + run: | + echo "Current Version: ${{ steps.current-version.outputs.tag }}" + + - name: 🧮 Compute Next Version + uses: chickensoft-games/next-godot-csproj-version@v1 + id: next-version + with: + project-version: ${{ steps.current-version.outputs.tag }} + godot-version: global.json + bump: ${{ inputs.bump }} + + - uses: actions/setup-dotnet@v4 + name: 💽 Setup .NET SDK + with: + # Use the .NET SDK from global.json in the root of the repository. + global-json-file: global.json + + # Write version to file so .NET will build correct version. + - name: 📝 Write Version to File + uses: jacobtomlinson/gha-find-replace@v3 + with: + find: "0.0.0-devbuild" + replace: ${{ steps.next-version.outputs.version }} + regex: false + include: Chickensoft.SaveFileBuilder/Chickensoft.SaveFileBuilder.csproj + + - name: 📦 Build + run: dotnet build \ + Chickensoft.SaveFileBuilder/Chickensoft.SaveFileBuilder.csproj -c Release + + - name: 🔎 Get Package Path + id: package-path + run: | + package=$(find ./Chickensoft.SaveFileBuilder/nupkg -name "*.nupkg") + echo "package=$package" >> "$GITHUB_OUTPUT" + echo "📦 Found package: $package" + + - name: ✨ Create Release + env: + GITHUB_TOKEN: ${{ secrets.GH_BASIC }} + run: | + version="${{ steps.next-version.outputs.version }}" + gh release create --title "v$version" --generate-notes "$version" \ + "${{ steps.package-path.outputs.package }}" + + - name: 🛜 Publish to Nuget + run: | + dotnet nuget push "${{ steps.package-path.outputs.package }}" \ + --api-key "${{ secrets.NUGET_API_KEY }}" \ + --source "https://api.nuget.org/v3/index.json" --skip-duplicate diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml new file mode 100644 index 0000000..c7ca58f --- /dev/null +++ b/.github/workflows/spellcheck.yaml @@ -0,0 +1,26 @@ +name: '🧑‍🏫 Spellcheck' +on: + push: + pull_request: + +jobs: + spellcheck: + name: '🧑‍🏫 Spellcheck' + # Only run the workflow if it's not a PR or if it's a PR from a fork. + # This prevents duplicate workflows from running on PR's that originate + # from the repository itself. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: ubuntu-latest + defaults: + run: + working-directory: '.' + steps: + - uses: actions/checkout@v4 + name: 🧾 Checkout + + - uses: streetsidesoftware/cspell-action@v6 + name: 📝 Check Spelling + with: + config: './cspell.json' + incremental_files_only: false + root: '.' diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000..da7bc76 --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,68 @@ +name: 🚥 Tests +on: + push: + pull_request: + +jobs: + tests: + name: 🧪 Evaluate Tests on ${{ matrix.os }} + # Only run the workflow if it's not a PR or if it's a PR from a fork. + # This prevents duplicate workflows from running on PR's that originate + # from the repository itself. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: ${{ matrix.os }} + strategy: + # Don't cancel other OS runners if one fails. + fail-fast: false + matrix: + # Put the operating systems you want to run on here. + # + # You can change windows-2019 to windows-latest, but windows-2019 + # was running in half the time. Try it out and see what works best. + os: [ubuntu-latest, macos-latest, windows-2019] + env: + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_NOLOGO: true + defaults: + run: + # Use bash shells on all platforms. + shell: bash + steps: + - name: 🧾 Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.GH_BASIC }} + lfs: true + submodules: 'recursive' + + - name: 💽 Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + # Use the .NET SDK from global.json in the root of the repository. + global-json-file: global.json + + - name: 📦 Restore Dependencies + run: dotnet restore + + - name: 🤖 Setup Godot + uses: chickensoft-games/setup-godot@v2 + with: + # Version must include major, minor, and patch, and be >= 4.0.0 + # Pre-release label is optional. + # + # In this case, we are using the version from global.json. + # + # This allows checks on renovatebot PR's to succeed whenever + # renovatebot updates the Godot SDK version. + version: global.json + + - name: 🧑‍🔬 Generate .NET Bindings + working-directory: Chickensoft.SaveFileBuilder.Tests + run: godot --headless --build-solutions --quit || exit 0 + + - name: 🦺 Build Projects + run: dotnet build + + - name: 🧪 Run Tests + working-directory: Chickensoft.SaveFileBuilder.Tests + run: godot --headless --run-tests --quit-on-finish diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..377ed34 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +**/coverage/* +!**/coverage/.gdignore +nupkg/ +.godot/ +bin/ +obj/ +.generated/ +.vs/ +.DS_Store +*.DotSettings.user +*.binlog diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..ac45447 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "ms-dotnettools.csharp", + "selcukermaya.se-csproj-extensions", + "josefpihrt-vscode.roslynator", + "streetsidesoftware.code-spell-checker", + "VisualStudioExptTeam.vscodeintellicode", + "DavidAnson.vscode-markdownlint" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..1d76302 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,37 @@ +{ + "version": "0.2.0", + "configurations": [ + // For these launch configurations to work, you need to setup a GODOT + // environment variable. On mac or linux, this can be done by adding + // the following to your .zshrc, .bashrc, or .bash_profile file: + // export GODOT="/Applications/Godot.app/Contents/MacOS/Godot" + { + "name": "🧪 Debug Tests", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${env:GODOT}", + "args": [ + // These command line flags are used by GoDotTest to run tests. + "--run-tests", + "--quit-on-finish" + ], + "cwd": "${workspaceFolder}/Chickensoft.SaveFileBuilder.Tests", + "stopAtEntry": false, + }, + { + "name": "🔬 Debug Current Test", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${env:GODOT}", + "args": [ + // These command line flags are used by GoDotTest to run tests. + "--run-tests=${fileBasenameNoExtension}", + "--quit-on-finish" + ], + "cwd": "${workspaceFolder}/Chickensoft.SaveFileBuilder.Tests", + "stopAtEntry": false, + }, + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b68bb4c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,169 @@ +{ + "[csharp]": { + "editor.codeActionsOnSave": { + "source.addMissingImports": "explicit", + "source.fixAll": "explicit", + "source.organizeImports": "explicit" + }, + "editor.formatOnPaste": true, + "editor.formatOnSave": true, + "editor.formatOnType": false + }, + "csharp.semanticHighlighting.enabled": true, + "dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true, + // Required to keep the C# language server from getting confused about which + // solution to open. + "dotnet.defaultSolution": "Chickensoft.SaveFileBuilder.sln", + "dotnet.server.useOmnisharp": false, + "editor.semanticHighlighting.enabled": true, + // C# doc comment colorization gets lost with semantic highlighting, but we + // need semantic highlighting for proper syntax highlighting with record + // shorthand. + // + // Here's a workaround for doc comment highlighting from + // https://github.com/OmniSharp/omnisharp-vscode/issues/3816 + "editor.tokenColorCustomizations": { + "[*]": { + // Themes that don't include the word "Dark" or "Light" in them. + // These are some bold colors that show up well against most dark and + // light themes. + // + // Change them to something that goes well with your preferred theme :) + "textMateRules": [ + { + "scope": "comment.documentation", + "settings": { + "foreground": "#0091ff" + } + }, + { + "scope": "comment.documentation.attribute", + "settings": { + "foreground": "#8480ff" + } + }, + { + "scope": "comment.documentation.cdata", + "settings": { + "foreground": "#0091ff" + } + }, + { + "scope": "comment.documentation.delimiter", + "settings": { + "foreground": "#aa00ff" + } + }, + { + "scope": "comment.documentation.name", + "settings": { + "foreground": "#ef0074" + } + } + ] + }, + "[*Dark*]": { + // Themes that include the word "Dark" in them. + "textMateRules": [ + { + "scope": "comment.documentation", + "settings": { + "foreground": "#608B4E" + } + }, + { + "scope": "comment.documentation.attribute", + "settings": { + "foreground": "#C8C8C8" + } + }, + { + "scope": "comment.documentation.cdata", + "settings": { + "foreground": "#E9D585" + } + }, + { + "scope": "comment.documentation.delimiter", + "settings": { + "foreground": "#808080" + } + }, + { + "scope": "comment.documentation.name", + "settings": { + "foreground": "#569CD6" + } + } + ] + }, + "[*Light*]": { + // Themes that include the word "Light" in them. + "textMateRules": [ + { + "scope": "comment.documentation", + "settings": { + "foreground": "#008000" + } + }, + { + "scope": "comment.documentation.attribute", + "settings": { + "foreground": "#282828" + } + }, + { + "scope": "comment.documentation.cdata", + "settings": { + "foreground": "#808080" + } + }, + { + "scope": "comment.documentation.delimiter", + "settings": { + "foreground": "#808080" + } + }, + { + "scope": "comment.documentation.name", + "settings": { + "foreground": "#808080" + } + } + ] + } + }, + "markdownlint.config": { + // Allow non-unique heading names so we don't break the changelog. + "MD024": false, + // Allow html in markdown. + "MD033": false + }, + "markdownlint.lintWorkspaceGlobs": [ + "!**/LICENSE" + ], + "omnisharp.enableEditorConfigSupport": true, + "omnisharp.enableMsBuildLoadProjectsOnDemand": false, + "omnisharp.maxFindSymbolsItems": 3000, + "omnisharp.organizeImportsOnFormat": true, + "omnisharp.useModernNet": true, + // Remove these if you're happy with your terminal profiles. + "terminal.integrated.defaultProfile.windows": "Git Bash", + "terminal.integrated.profiles.windows": { + "Command Prompt": { + "icon": "terminal-cmd", + "path": [ + "${env:windir}\\Sysnative\\cmd.exe", + "${env:windir}\\System32\\cmd.exe" + ] + }, + "Git Bash": { + "icon": "terminal", + "source": "Git Bash" + }, + "PowerShell": { + "icon": "terminal-powershell", + "source": "PowerShell" + } + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..48ff94b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,40 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "--no-restore" + ], + "problemMatcher": "$msCompile", + "presentation": { + "echo": true, + "reveal": "silent", + "focus": false, + "panel": "shared", + "showReuseMessage": false, + "clear": false + } + }, + { + "label": "coverage", + "group": "test", + "command": "${workspaceFolder}/Chickensoft.SaveFileBuilder.Tests/coverage.sh", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}/Chickensoft.SaveFileBuilder.Tests" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": false, + "clear": true + }, + }, + ] +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..931c1e0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,38 @@ +# Contributing + +Thank you for taking the time to read this contributing guide and for showing interest in helping this project! + +## Getting Started + +Need a helping hand to get started? Check out these resources! + +- [Discord Server][discord] +- [Chickensoft Website][chickensoft] + +Please read our [code of conduct](#code-of-conduct). We do our best to treat others fairly and foster a welcoming environment. + +## Project Setup + +This is a C# nuget package, for use with the .NET SDK 6 or 7. As such, the `dotnet` tool will allow you to restore packages and build projects. + +The `Chickensoft.SaveFileBuilder.Tests` project must be built with the Godot editor at least once before `dotnet build` will succeed. Godot has to generate the .NET bindings for the project, since tests run in an actual game environment. + +## Coding Guidelines + +Your IDE should automatically adhere to the style guidelines in the provided `.editorconfig` file. Please try to keep lines under 80 characters long whenever possible. + +We try to write tests for our projects to ensure a certain level of quality. We are willing to give you support and guidance if you need help! + +## Code of Conduct + +We follow the [Contributor Covenant][covenant]. + +In short: + +> We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + + + +[discord]: https://discord.gg/gSjaPgMmYW +[chickensoft]: https://chickensoft.games +[covenant]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/ diff --git a/Chickensoft.SaveFileBuilder.Tests/.editorconfig b/Chickensoft.SaveFileBuilder.Tests/.editorconfig new file mode 100644 index 0000000..9ea24c1 --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/.editorconfig @@ -0,0 +1,8 @@ +# EditorConfig for the test project. + +root = false + +[*.{cs,csx,cake}] + +# Not disposing of objects in a test is normal within Godot +dotnet_diagnostic.CA1001.severity = none diff --git a/Chickensoft.SaveFileBuilder.Tests/Chickensoft.SaveFileBuilder.Tests.csproj b/Chickensoft.SaveFileBuilder.Tests/Chickensoft.SaveFileBuilder.Tests.csproj new file mode 100644 index 0000000..f5230fa --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/Chickensoft.SaveFileBuilder.Tests.csproj @@ -0,0 +1,36 @@ + + + net7.0 + disable + enable + true + preview + Chickensoft.SaveFileBuilder.Tests + full + true + + + + true + + + true + .generated + + + + + + + + + + + + + + + + + + diff --git a/Chickensoft.SaveFileBuilder.Tests/Chickensoft.SaveFileBuilder.Tests.sln b/Chickensoft.SaveFileBuilder.Tests/Chickensoft.SaveFileBuilder.Tests.sln new file mode 100644 index 0000000..6783804 --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/Chickensoft.SaveFileBuilder.Tests.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chickensoft.SaveFileBuilder.Tests", "Chickensoft.SaveFileBuilder.Tests.csproj", "{834B83D0-DC42-47BC-8792-D8D03D8C254F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + ExportDebug|Any CPU = ExportDebug|Any CPU + ExportRelease|Any CPU = ExportRelease|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {834B83D0-DC42-47BC-8792-D8D03D8C254F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {834B83D0-DC42-47BC-8792-D8D03D8C254F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {834B83D0-DC42-47BC-8792-D8D03D8C254F}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {834B83D0-DC42-47BC-8792-D8D03D8C254F}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {834B83D0-DC42-47BC-8792-D8D03D8C254F}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {834B83D0-DC42-47BC-8792-D8D03D8C254F}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + EndGlobalSection +EndGlobal diff --git a/Chickensoft.SaveFileBuilder.Tests/badges/.gdignore b/Chickensoft.SaveFileBuilder.Tests/badges/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/Chickensoft.SaveFileBuilder.Tests/badges/branch_coverage.svg b/Chickensoft.SaveFileBuilder.Tests/badges/branch_coverage.svg new file mode 100644 index 0000000..cc017fc --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/badges/branch_coverage.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ce7844d3ba8c9572c3b69e692577880eef0a933dd29df2cee61acc8b0c8f8c3 +size 7388 diff --git a/Chickensoft.SaveFileBuilder.Tests/badges/line_coverage.svg b/Chickensoft.SaveFileBuilder.Tests/badges/line_coverage.svg new file mode 100644 index 0000000..c2cc7ce --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/badges/line_coverage.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5770c82fa07a9f273c9e27a171fa96075709de25820e6b636918206b5cb465c +size 5161 diff --git a/Chickensoft.SaveFileBuilder.Tests/coverage.sh b/Chickensoft.SaveFileBuilder.Tests/coverage.sh new file mode 100755 index 0000000..e7eeb1d --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/coverage.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# To collect code coverage, you will need the following environment setup: +# +# - A "GODOT" environment variable pointing to the Godot executable +# - ReportGenerator installed +# +# dotnet tool install -g dotnet-reportgenerator-globaltool +# +# - A version of coverlet > 3.2.0. +# +# As of Jan 2023, this is not yet released. +# +# The included `nuget.config` file will allow you to install a nightly +# version of coverlet from the coverlet nightly nuget feed. +# +# dotnet tool install --global coverlet.console --prerelease. +# +# You can build coverlet yourself, but you will need to edit the path to +# coverlet below to point to your local build of the coverlet dll. +# +# If you need help with coverage, feel free to join the Chickensoft Discord. +# https://chickensoft.games + +dotnet build --no-restore + +coverlet \ + "./.godot/mono/temp/bin/Debug" --verbosity detailed \ + --target $GODOT \ + --targetargs "--run-tests --coverage --quit-on-finish" \ + --format "opencover" \ + --output "./coverage/coverage.xml" \ + --exclude-by-file "**/test/**/*.cs" \ + --exclude-by-file "**/*Microsoft.NET.Test.Sdk.Program.cs" \ + --exclude-by-file "**/Godot.SourceGenerators/**/*.cs" \ + --exclude-assemblies-without-sources "missingall" \ + --skipautoprops + +# Projects included via will be collected in code coverage. +# If you want to exclude them, replace the string below with the names of +# the assemblies to ignore. e.g., +# ASSEMBLIES_TO_REMOVE="-AssemblyToRemove1;-AssemblyToRemove2" +ASSEMBLIES_TO_REMOVE="-Chickensoft.SaveFileBuilder.Tests" + +reportgenerator \ + -reports:"./coverage/coverage.xml" \ + -targetdir:"./coverage/report" \ + "-assemblyfilters:$ASSEMBLIES_TO_REMOVE" \ + "-classfilters:-GodotPlugins.Game.Main" \ + -reporttypes:"Html;Badges" + +# Copy badges into their own folder. The badges folder should be included in +# source control so that the README.md in the root can reference the badges. + +mkdir -p ./badges +mv ./coverage/report/badge_branchcoverage.svg ./badges/branch_coverage.svg +mv ./coverage/report/badge_linecoverage.svg ./badges/line_coverage.svg + +# Determine OS, open coverage accordingly. + +case "$(uname -s)" in + + Darwin) + echo 'Mac OS X' + open coverage/report/index.htm + ;; + + Linux) + echo 'Linux' + open coverage/report/index.htm + ;; + + CYGWIN*|MINGW32*|MSYS*|MINGW*) + echo 'MS Windows' + start coverage/report/index.htm + ;; + + *) + echo 'Other OS' + ;; +esac diff --git a/Chickensoft.SaveFileBuilder.Tests/coverage/.gdignore b/Chickensoft.SaveFileBuilder.Tests/coverage/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/Chickensoft.SaveFileBuilder.Tests/icon.svg b/Chickensoft.SaveFileBuilder.Tests/icon.svg new file mode 100644 index 0000000..c316a5a --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/icon.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da97ab7aac233047029a9fd47e915059fda75d8dd43fc15b0e71d300f4f20f0f +size 4174 diff --git a/Chickensoft.SaveFileBuilder.Tests/icon.svg.import b/Chickensoft.SaveFileBuilder.Tests/icon.svg.import new file mode 100644 index 0000000..e8dbc89 --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://da2tcc2mhkfgi" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Chickensoft.SaveFileBuilder.Tests/nuget.config b/Chickensoft.SaveFileBuilder.Tests/nuget.config new file mode 100644 index 0000000..f498747 --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/nuget.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Chickensoft.SaveFileBuilder.Tests/project.godot b/Chickensoft.SaveFileBuilder.Tests/project.godot new file mode 100644 index 0000000..82ce87f --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/project.godot @@ -0,0 +1,24 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Chickensoft.SaveFileBuilder.Tests" +run/main_scene="res://test/Tests.tscn" +config/features=PackedStringArray("4.2", "C#", "Mobile") +config/icon="res://icon.svg" + +[dotnet] + +project/assembly_name="Chickensoft.SaveFileBuilder.Tests" + +[rendering] + +renderer/rendering_method="mobile" diff --git a/Chickensoft.SaveFileBuilder.Tests/test/Tests.cs b/Chickensoft.SaveFileBuilder.Tests/test/Tests.cs new file mode 100644 index 0000000..4372f25 --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/test/Tests.cs @@ -0,0 +1,12 @@ +namespace Chickensoft.SaveFileBuilder.Tests; + +using System.Reflection; +using Godot; +using Chickensoft.GoDotTest; + +public partial class Tests : Node2D { + public override void _Ready() => CallDeferred(MethodName.RunTests); + + public void RunTests() => + GoTest.RunTests(Assembly.GetExecutingAssembly(), this); +} diff --git a/Chickensoft.SaveFileBuilder.Tests/test/Tests.tscn b/Chickensoft.SaveFileBuilder.Tests/test/Tests.tscn new file mode 100644 index 0000000..14ebf60 --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/test/Tests.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bv5dxd8hrc5g4"] + +[ext_resource type="Script" path="res://test/Tests.cs" id="1_310o6"] + +[node name="Node2D" type="Node2D"] +script = ExtResource("1_310o6") diff --git a/Chickensoft.SaveFileBuilder.Tests/test/src/SaveChunkTest.cs b/Chickensoft.SaveFileBuilder.Tests/test/src/SaveChunkTest.cs new file mode 100644 index 0000000..9344e3e --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/test/src/SaveChunkTest.cs @@ -0,0 +1,57 @@ +namespace Chickensoft.SaveFileBuilder.Tests; + +using System.Threading.Tasks; +using Chickensoft.GoDotTest; +using Godot; +using Shouldly; + +public class SaveChunkTest(Node testScene) : TestClass(testScene) { + private sealed record SaveData { } + + [Test] + public void SavesAndLoads() { + var onSave = Task.CompletedTask; + var data = new SaveData(); + + var loaded = false; + + var saveChunk = new SaveChunk( + onSave: (chunk) => data, + onLoad: (chunk, data) => loaded = true + ); + + saveChunk.ShouldNotBeNull(); + + saveChunk.GetSaveData().ShouldBeSameAs(data); + saveChunk.LoadSaveData(data); + loaded.ShouldBeTrue(); + } + + [Test] + public void AddsAndGetsChunk() { + var onSave = Task.CompletedTask; + var data = new SaveData(); + + var saveChunk = new SaveChunk( + onSave: (chunk) => data, + onLoad: (chunk, data) => { } + ); + + var childLoaded = false; + var childData = new SaveData(); + var child = new SaveChunk( + onSave: (chunk) => childData, + onLoad: (chunk, data) => childLoaded = true + ); + + saveChunk.AddChunk(child); + + var childChunk = saveChunk.GetChunk(); + + childChunk.ShouldBeSameAs(child); + + saveChunk.GetChunkSaveData().ShouldBeSameAs(childData); + saveChunk.LoadChunkSaveData(childData); + childLoaded.ShouldBeTrue(); + } +} diff --git a/Chickensoft.SaveFileBuilder.Tests/test/src/SaveFileTest.cs b/Chickensoft.SaveFileBuilder.Tests/test/src/SaveFileTest.cs new file mode 100644 index 0000000..450d563 --- /dev/null +++ b/Chickensoft.SaveFileBuilder.Tests/test/src/SaveFileTest.cs @@ -0,0 +1,47 @@ +namespace Chickensoft.SaveFileBuilder.Tests; + +using System.Threading.Tasks; +using Chickensoft.GoDotTest; +using Godot; +using Shouldly; + +public class SaveFileTest(Node testScene) : TestClass(testScene) { + private sealed record SaveData { } + + [Test] + public async Task SavesAndLoads() { + var onSave = Task.CompletedTask; + var data = new SaveData(); + + var saveFile = new SaveFile( + root: new SaveChunk( + onSave: (chunk) => new SaveData(), + onLoad: (chunk, data) => { } + ), + onSave: _ => onSave, + onLoad: () => Task.FromResult(data) + ); + + await Should.NotThrowAsync(async () => { + await saveFile.Load(); + await saveFile.Save(); + }); + } + + [Test] + public async Task DoesNotLoadIfNull() { + var onSave = Task.CompletedTask; + var data = new SaveData(); + + var saveFile = new SaveFile( + root: new SaveChunk( + onSave: (chunk) => new SaveData(), + onLoad: (chunk, data) => { } + ), + onSave: _ => onSave, + onLoad: () => Task.FromResult(null) + ); + + await Should.NotThrowAsync(saveFile.Load); + } +} diff --git a/Chickensoft.SaveFileBuilder.sln b/Chickensoft.SaveFileBuilder.sln new file mode 100644 index 0000000..2594f2f --- /dev/null +++ b/Chickensoft.SaveFileBuilder.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chickensoft.SaveFileBuilder", "Chickensoft.SaveFileBuilder\Chickensoft.SaveFileBuilder.csproj", "{B1A8B525-F357-4408-8DEC-DCE510C4C4CA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chickensoft.SaveFileBuilder.Tests", "Chickensoft.SaveFileBuilder.Tests\Chickensoft.SaveFileBuilder.Tests.csproj", "{1C650F6D-5BA9-49FD-9C22-A7756F4A09D4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B1A8B525-F357-4408-8DEC-DCE510C4C4CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1A8B525-F357-4408-8DEC-DCE510C4C4CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1A8B525-F357-4408-8DEC-DCE510C4C4CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1A8B525-F357-4408-8DEC-DCE510C4C4CA}.Release|Any CPU.Build.0 = Release|Any CPU + {1C650F6D-5BA9-49FD-9C22-A7756F4A09D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C650F6D-5BA9-49FD-9C22-A7756F4A09D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C650F6D-5BA9-49FD-9C22-A7756F4A09D4}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {1C650F6D-5BA9-49FD-9C22-A7756F4A09D4}.Release|Any CPU.Build.0 = Debug|Any CPU + EndGlobalSection +EndGlobal diff --git a/Chickensoft.SaveFileBuilder/Chickensoft.SaveFileBuilder.csproj b/Chickensoft.SaveFileBuilder/Chickensoft.SaveFileBuilder.csproj new file mode 100644 index 0000000..cd0c294 --- /dev/null +++ b/Chickensoft.SaveFileBuilder/Chickensoft.SaveFileBuilder.csproj @@ -0,0 +1,52 @@ + + + net7.0 + true + preview + true + true + enable + true + Chickensoft.SaveFileBuilder + true + ./nupkg + portable + + SaveFileBuilder + 0.0.0-devbuild + Chickensoft.SaveFileBuilder description. + © 2024 Chickensoft + Chickensoft + Chickensoft + + Chickensoft.SaveFileBuilder + SaveFileBuilder release. + icon.png + + README.md + LICENSE + + + git + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + diff --git a/Chickensoft.SaveFileBuilder/icon.png b/Chickensoft.SaveFileBuilder/icon.png new file mode 100644 index 0000000..0b3d204 --- /dev/null +++ b/Chickensoft.SaveFileBuilder/icon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a085aead2eab99f05dfc90095275658abc8a2964046751525096afeadc9795c +size 99354 diff --git a/Chickensoft.SaveFileBuilder/src/SaveChunk.cs b/Chickensoft.SaveFileBuilder/src/SaveChunk.cs new file mode 100644 index 0000000..a7940d2 --- /dev/null +++ b/Chickensoft.SaveFileBuilder/src/SaveChunk.cs @@ -0,0 +1,91 @@ +namespace Chickensoft.SaveFileBuilder; + +using System; +using Chickensoft.Collections; + +/// +/// Represents a section of a save file. A chunk can contain other chunks. +/// Save chunks form a tree composing the save file contents. +/// +/// Type of data associated with this save chunk. +/// +public interface ISaveChunk where TData : class { + /// + /// Gets the data associated with this save chunk. + /// + /// Save chunk data. + TData GetSaveData(); + + /// + /// Loads the data associated with this save chunk. + /// + /// + void LoadSaveData(TData data); + + /// + /// Adds a child save chunk to this chunk. + /// + /// Type of data associated with the child save + /// chunk. + void AddChunk(ISaveChunk child) where TDataType : class; + + /// + /// Gets a child save chunk. + /// + /// Type of data associated with the child save + /// chunk. + ISaveChunk GetChunk() where TDataType : class; + + /// + /// Gets the data associated with a child save chunk. + /// + /// Type of data associated with the child save + /// chunk. + TDataType GetChunkSaveData() where TDataType : class; +} + +/// +public sealed class SaveChunk : ISaveChunk where TData : class { + private readonly Func, TData> _onSave; + private readonly Action, TData> _onLoad; + private readonly Blackboard _children = new(); + + /// + /// Creates a new save chunk. + /// + /// Function to get the save data associated + /// with this chunk. Should receive the current chunk as a parameter and + /// return save data. + /// Function to load the save data associated + /// with this chunk. Should receive the current chunk and the data as + /// parameters. + public SaveChunk( + Func, TData> onSave, + Action, TData> onLoad + ) { + _onSave = onSave; + _onLoad = onLoad; + } + + /// + public TData GetSaveData() => _onSave(this); + + /// + public void LoadSaveData(TData data) => _onLoad(this, data); + + /// + public void AddChunk(ISaveChunk child) + where TDataType : class => _children.Set(child); + + /// + public ISaveChunk GetChunk() where TDataType : class => + _children.Get>(); + + /// + public TDataType GetChunkSaveData() where TDataType : class => + GetChunk().GetSaveData(); + + /// + public void LoadChunkSaveData(TDataType data) + where TDataType : class => GetChunk().LoadSaveData(data); +} diff --git a/Chickensoft.SaveFileBuilder/src/SaveFile.cs b/Chickensoft.SaveFileBuilder/src/SaveFile.cs new file mode 100644 index 0000000..7cd1e5f --- /dev/null +++ b/Chickensoft.SaveFileBuilder/src/SaveFile.cs @@ -0,0 +1,70 @@ +namespace Chickensoft.SaveFileBuilder; + +using System; +using System.Threading.Tasks; + +/// +/// Represents a save file composed of one or more save chunks. +/// +/// Type of data represented by the save file. +/// +public interface ISaveFile where TData : class { + /// + /// Root save chunk from which the save file contents are composed. + /// + ISaveChunk Root { get; } + + /// + /// Collects save data from the save file chunk tree and saves it. + /// + /// Asynchronous task. + Task Save(); + + /// + /// Loads save data and restores the save file chunk tree. + /// + /// Asynchronous task. + Task Load(); +} + +/// +public class SaveFile : ISaveFile where TData : class { + /// + public ISaveChunk Root { get; } + + private readonly Func _onSave; + private readonly Func> _onLoad; + + /// + /// + /// + /// + /// Function that saves the data. + /// Function that loads the data. + public SaveFile( + SaveChunk root, + Func onSave, + Func> onLoad + ) { + Root = root; + _onSave = onSave; + _onLoad = onLoad; + } + + /// + public Task Save() => _onSave(Root.GetSaveData()); + + /// + public async Task Load() { + // Loading save data is asynchronous since it's usually coming from + // the disk or network. + var data = await _onLoad(); + + if (data is null) { + return; + } + + // Actually restoring the loaded data is synchronous. + Root.LoadSaveData(data); + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..089e924 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2023 Chickensoft + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..20e550b --- /dev/null +++ b/README.md @@ -0,0 +1,143 @@ +# 👽 SaveFileBuilder + +[![Chickensoft Badge][chickensoft-badge]][chickensoft-website] [![Discord][discord-badge]][discord] [![Read the docs][read-the-docs-badge]][docs] ![line coverage][line-coverage] ![branch coverage][branch-coverage] + +Compose chunks of save data into a single data type by creating loosely coupled save chunks at various points in the scene tree. + +--- + +

+Chickensoft.SaveFileBuilder +

+ +## 🥚 Getting Started + +Find the latest version of [`Chickensoft.SaveFileBuilder`][nuget] on nuget. + +```sh +dotnet add package Chickensoft.SaveFileBuilder +``` + +## 📄 SaveFile and Root SaveChunk + +Find the highest node in your scene tree that needs to be concerned with save data to use as the root of your save file. Use [AutoInject] to provide the root save chunk to all its descendant nodes. + +> [!TIP] +> Check out the Chickensoft [Game Demo] for a complete, working example of using SaveFileBuilder to save composed states of everything that needs to be persisted in a game. + +```csharp +using Chickensoft.Introspection; +using Chickensoft.AutoInject; +using Chickensoft.SaveFileBuilder; +using Godot; + +[Meta(typeof(IAutoNode))] +public partial class Game : Node3D { + public SaveFile SaveFile { get; set; } = default!; + + // Provide the root save chunk to all descendant nodes. + ISaveChunk IProvide>.Value() => SaveFile.Root; + + public void Setup() { + SaveFile = new SaveFile( + root: new SaveChunk( + onSave: (chunk) => { + // Use root chunk to get child chunks that were added to us + // lower in the scene tree. + var gameData = new GameData() { + MapData = chunk.GetChunkSaveData(), + PlayerData = chunk.GetChunkSaveData(), + PlayerCameraData = chunk.GetChunkSaveData() + }; + + return gameData; + }, + onLoad: (chunk, data) => { + // Break up the game data and send it to the child chunks so that + // they can load the data into the nodes they belong to. + chunk.LoadChunkSaveData(data.MapData); + chunk.LoadChunkSaveData(data.PlayerData); + chunk.LoadChunkSaveData(data.PlayerCameraData); + } + ), + onSave: async (GameData data) => { + // Save the game data to disk. + var json = JsonSerializer.Serialize(data, JsonOptions); + await FileSystem.File.WriteAllTextAsync(SaveFilePath, json); + }, + onLoad: async () => { + // Load the game data from disk. + if (!FileSystem.File.Exists(SaveFilePath)) { + GD.Print("No save file to load :'("); + return null; + } + + var json = await FileSystem.File.ReadAllTextAsync(SaveFilePath); + return JsonSerializer.Deserialize(json, JsonOptions); + } + ); + + ... + } +} +``` + +## 🍪 Defining Save Chunks + +SaveChunks are smaller pieces of save data that are composed together into the overall save file's data. Simply add a chunk to a descendant node of the scene with the root SaveChunk and register it with the root save chunk once you've resolved dependencies with AutoInject. + +```csharp +[Meta(typeof(IAutoNode))] +public partial class Player : CharacterBody3D { + [Dependency] + public ISaveChunk GameChunk => this.DependOn>(); + public ISaveChunk PlayerChunk { get; set; } = default!; + + public void Setup() { + ... + + PlayerChunk = new SaveChunk( + onSave: (chunk) => new PlayerData() { + GlobalTransform = GlobalTransform, + StateMachine = (PlayerLogic)PlayerLogic, + Velocity = Velocity + }, + onLoad: (chunk, data) => { + GlobalTransform = data.GlobalTransform; + Velocity = data.Velocity; + PlayerLogic.RestoreFrom(data.StateMachine); + PlayerLogic.Start(); + } + ); + + ... + } + + public void OnResolved() { + // Add a child to our parent save chunk (the game chunk) so that it can + // look up the player chunk when loading and saving the game. + GameChunk.AddChunk(PlayerChunk); + + ... + } +} +``` + +Once a save chunk has been added to a parent save chunk, the parent save chunk can access it from the callbacks specified by `onSave` and `onLoad`, querying its data or forcing it load data into its node. + +--- + +🐣 Package generated from a 🐤 Chickensoft Template — + +[chickensoft-badge]: https://raw.githubusercontent.com/chickensoft-games/chickensoft_site/main/static/img/badges/chickensoft_badge.svg +[chickensoft-website]: https://chickensoft.games +[discord-badge]: https://raw.githubusercontent.com/chickensoft-games/chickensoft_site/main/static/img/badges/discord_badge.svg +[discord]: https://discord.gg/gSjaPgMmYW +[read-the-docs-badge]: https://raw.githubusercontent.com/chickensoft-games/chickensoft_site/main/static/img/badges/read_the_docs_badge.svg +[docs]: https://chickensoft.games/docs +[line-coverage]: Chickensoft.SaveFileBuilder.Tests/badges/line_coverage.svg +[branch-coverage]: Chickensoft.SaveFileBuilder.Tests/badges/branch_coverage.svg + +[AutoInject]: https://github.com/chickensoft-games/AutoInject +[Game Demo]: https://github.com/chickensoft-games/GameDemo +[nuget]: https://www.nuget.org/packages/Chickensoft.SaveFileBuilder diff --git a/cspell.json b/cspell.json new file mode 100644 index 0000000..f4a78df --- /dev/null +++ b/cspell.json @@ -0,0 +1,72 @@ +{ + "files": [ + "**/*.*" + ], + "ignorePaths": [ + "**/*.tscn", + "**/*.import", + "**/badges/**/*.*", + "**/coverage/**/*.*", + "**/.godot/**/*.*", + "**/obj/**/*.*", + "**/bin/**/*.*", + "**/nupkg/**/*.*" + ], + "words": [ + "assemblyfilters", + "devbuild", + "skipautoprops", + "automerge", + "branchcoverage", + "brandedoutcast", + "buildtransitive", + "camelcase", + "chickenpackage", + "Chickensoft", + "classfilters", + "contentfiles", + "CYGWIN", + "devbuild", + "endregion", + "Finalizer", + "Finalizers", + "globaltool", + "godotengine", + "godotpackage", + "issuecomment", + "justalemon", + "lcov", + "lihop", + "linecoverage", + "methodcoverage", + "missingall", + "msbuild", + "MSYS", + "nameof", + "Nerdbank", + "netstandard", + "NOLOGO", + "nupkg", + "Omnisharp", + "opencover", + "OPTOUT", + "paramref", + "pascalcase", + "Postinitialize", + "Predelete", + "renovatebot", + "reportgenerator", + "reporttypes", + "Shouldly", + "subfolders", + "targetargs", + "targetdir", + "tscn", + "typeof", + "typeparam", + "typeparamref", + "ulong", + "Unparented", + "Xunit" + ] +} diff --git a/docs/renovatebot_pr.png b/docs/renovatebot_pr.png new file mode 100644 index 0000000..44568a0 --- /dev/null +++ b/docs/renovatebot_pr.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b63d75d932457b93f79f54e5c4192d201a29aefb4e437a3732c63099ec8f78a1 +size 148110 diff --git a/docs/spelling_fix.png b/docs/spelling_fix.png new file mode 100644 index 0000000..a306f61 --- /dev/null +++ b/docs/spelling_fix.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:870bad263d4bbf803f2278af6e4346cf1e9c07c48c51d85c40ad9b5b63f761b2 +size 71136 diff --git a/global.json b/global.json new file mode 100644 index 0000000..78068fd --- /dev/null +++ b/global.json @@ -0,0 +1,9 @@ +{ + "sdk": { + "rollForward": "major", + "version": "7.0.404" + }, + "msbuild-sdks": { + "Godot.NET.Sdk": "4.2.2" + } +} diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..6e2564c --- /dev/null +++ b/renovate.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base", + ":semanticCommits" + ], + "prHourlyLimit": 2, + "versioning": "loose", + "packageRules": [ + { + "matchPackagePatterns": [ + "*" + ], + "groupName": "all dependencies", + "groupSlug": "all-deps", + "automerge": true + }, + { + "matchPackagePrefixes": [ + "dotnet-sdk" + ], + "allowedVersions": "!/preview/" + }, + { + "matchPackagePrefixes": [ + "GodotSharp", + "Godot.NET.Sdk" + ], + "allowedVersions": "/^(\\d+\\.\\d+\\.\\d+)(-(beta|rc)\\.(\\d+)(\\.\\d+)*)?$/" + }, + { + "matchPackagePrefixes": [ + "Chickensoft" + ], + "allowedVersions": "/^(\\d+\\.\\d+\\.\\d+)(-godot(\\d+\\.)+\\d+(-.*)?)?$/" + } + ] +} \ No newline at end of file