diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 054f820..d5c5549 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,9 +1,5 @@ name: '๐Ÿ“ฆ Release' on: - # Make a release whenever we push a version tag. - push: - tags: - - 'v*' # Make a release whenever the developer wants. workflow_dispatch: inputs: @@ -72,15 +68,15 @@ jobs: find: "0.0.0-devbuild" replace: ${{ steps.next-version.outputs.version }} regex: false - include: Chickensoft.GoDotCollections/Chickensoft.GoDotCollections.csproj + include: Chickensoft.Collections/Chickensoft.Collections.csproj - name: ๐Ÿ“ฆ Build - run: dotnet build Chickensoft.GoDotCollections/Chickensoft.GoDotCollections.csproj -c Release + run: dotnet build Chickensoft.Collections/Chickensoft.Collections.csproj -c Release - name: ๐Ÿ”Ž Get Package Path id: package-path run: | - package=$(find ./Chickensoft.GoDotCollections/nupkg -name "*.nupkg") + package=$(find ./Chickensoft.Collections/nupkg -name "*.nupkg") echo "package=$package" >> "$GITHUB_OUTPUT" echo "๐Ÿ“ฆ Found package: $package" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index c1b66fa..3070a98 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -31,23 +31,8 @@ jobs: - name: ๐Ÿ“ฆ Restore Dependencies run: dotnet restore - - name: ๐Ÿค– Setup Godot - uses: chickensoft-games/setup-godot@v2 - with: - version: global.json - - - name: ๐Ÿ”ฌ Verify Setup - run: | - dotnet --version - godot --version - - - name: ๐Ÿง‘โ€๐Ÿ”ฌ Generate .NET Bindings - working-directory: Chickensoft.GoDotCollections.Tests - run: godot --headless --build-solutions --quit || exit 0 - - name: ๐Ÿฆบ Build Projects run: dotnet build # --configuration Release - name: ๐Ÿงช Run Tests - working-directory: Chickensoft.GoDotCollections.Tests - run: godot --headless --run-tests --quit-on-finish + run: dotnet test diff --git a/.gitignore b/.gitignore index 60591dc..3a2d1fd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,7 @@ -Chickensoft.GoDotCollections/nupkg/ +Chickensoft.Collections/nupkg/ -Chickensoft.GoDotCollections.Tests/coverage/* -!Chickensoft.GoDotCollections.Tests/coverage/.gdignore +Chickensoft.Collections.Tests/coverage/* -.godot/ bin/ obj/ .generated/ diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index aeb1bcb..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "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. - "--headless", - "--run-tests", - "--quit-on-finish" - ], - "cwd": "${workspaceFolder}/Chickensoft.GoDotCollections.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. - "--headless", - "--run-tests=${fileBasenameNoExtension}", - "--quit-on-finish" - ], - "cwd": "${workspaceFolder}/Chickensoft.GoDotCollections.Tests", - "stopAtEntry": false, - }, - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json index e377ecc..a1122a2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -132,14 +132,13 @@ // Allow html in markdown. "MD033": false, // Allow non-unique heading names so we don't break the changelog. - "MD024": false + "MD024": false, }, - "markdownlint.ignore": [ - "**/LICENSE" + "markdownlint.lintWorkspaceGlobs": [ + "!**/LICENSE" ], "omnisharp.enableEditorConfigSupport": true, "omnisharp.enableMsBuildLoadProjectsOnDemand": false, - "omnisharp.enableRoslynAnalyzers": true, "omnisharp.maxFindSymbolsItems": 3000, "omnisharp.organizeImportsOnFormat": true, "omnisharp.useModernNet": true, @@ -163,4 +162,4 @@ } }, "dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true -} +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b0345d0..1f90a02 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -22,10 +22,10 @@ { "label": "coverage", "group": "test", - "command": "${workspaceFolder}/Chickensoft.GoDotCollections.Tests/coverage.sh", + "command": "${workspaceFolder}/Chickensoft.Collections.Tests/coverage.sh", "type": "shell", "options": { - "cwd": "${workspaceFolder}/Chickensoft.GoDotCollections.Tests" + "cwd": "${workspaceFolder}/Chickensoft.Collections.Tests" }, "presentation": { "echo": true, @@ -35,23 +35,6 @@ "showReuseMessage": false, "clear": true }, - }, - { - "label": "build-solutions", - "group": "test", - "command": "dotnet restore; ${env:GODOT} --headless --build-solutions --quit || exit 0", - "type": "shell", - "options": { - "cwd": "${workspaceFolder}/Chickensoft.GoDotCollections.Tests" - }, - "presentation": { - "echo": true, - "reveal": "silent", - "focus": false, - "panel": "shared", - "showReuseMessage": false, - "clear": false - } - }, + } ] -} +} \ No newline at end of file diff --git a/Chickensoft.Collections.Tests.sln b/Chickensoft.Collections.Tests.sln new file mode 100644 index 0000000..4b5e4dc --- /dev/null +++ b/Chickensoft.Collections.Tests.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.Collections", "Chickensoft.Collections\Chickensoft.Collections.csproj", "{4789AFE1-321A-4D01-877D-59FAE5C8E666}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chickensoft.Collections.Tests", "Chickensoft.Collections.Tests\Chickensoft.Collections.Tests.csproj", "{C6729B76-21EB-4C52-87EF-B1F8DA06673D}" +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 + {4789AFE1-321A-4D01-877D-59FAE5C8E666}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4789AFE1-321A-4D01-877D-59FAE5C8E666}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4789AFE1-321A-4D01-877D-59FAE5C8E666}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4789AFE1-321A-4D01-877D-59FAE5C8E666}.Release|Any CPU.Build.0 = Release|Any CPU + {C6729B76-21EB-4C52-87EF-B1F8DA06673D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6729B76-21EB-4C52-87EF-B1F8DA06673D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6729B76-21EB-4C52-87EF-B1F8DA06673D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6729B76-21EB-4C52-87EF-B1F8DA06673D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Chickensoft.Collections.Tests/Chickensoft.Collections.Tests.csproj b/Chickensoft.Collections.Tests/Chickensoft.Collections.Tests.csproj new file mode 100644 index 0000000..6b61756 --- /dev/null +++ b/Chickensoft.Collections.Tests/Chickensoft.Collections.Tests.csproj @@ -0,0 +1,39 @@ + + + net8.0 + disable + enable + + false + true + preview + portable + + + true + .generated + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/Chickensoft.GoDotCollections.Tests/badges/branch_coverage.svg b/Chickensoft.Collections.Tests/badges/branch_coverage.svg similarity index 100% rename from Chickensoft.GoDotCollections.Tests/badges/branch_coverage.svg rename to Chickensoft.Collections.Tests/badges/branch_coverage.svg diff --git a/Chickensoft.GoDotCollections.Tests/badges/line_coverage.svg b/Chickensoft.Collections.Tests/badges/line_coverage.svg similarity index 100% rename from Chickensoft.GoDotCollections.Tests/badges/line_coverage.svg rename to Chickensoft.Collections.Tests/badges/line_coverage.svg diff --git a/Chickensoft.Collections.Tests/coverage.sh b/Chickensoft.Collections.Tests/coverage.sh new file mode 100755 index 0000000..3819fb3 --- /dev/null +++ b/Chickensoft.Collections.Tests/coverage.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +dotnet build + +dotnet test \ + -p:CollectCoverage=true \ + -p:CoverletOutputFormat="opencover" \ + -p:CoverletOutput=./coverage/ + +reportgenerator \ + -reports:"./coverage/coverage.opencover.xml" \ + -targetdir:"./coverage/report" \ + "-assemblyfilters:-*Chickensoft.LogicBlocks.Generator*" \ + -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' + xdg-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.GoDotCollections.Tests/test/src/AutoPropTest.cs b/Chickensoft.Collections.Tests/src/AutoPropTest.cs similarity index 91% rename from Chickensoft.GoDotCollections.Tests/test/src/AutoPropTest.cs rename to Chickensoft.Collections.Tests/src/AutoPropTest.cs index f54bf1d..ab901c7 100644 --- a/Chickensoft.GoDotCollections.Tests/test/src/AutoPropTest.cs +++ b/Chickensoft.Collections.Tests/src/AutoPropTest.cs @@ -1,15 +1,12 @@ -namespace Chickensoft.GoDotCollections.Tests; +namespace Chickensoft.Collections.Tests; using System; using System.Collections.Generic; -using Godot; -using GoDotCollections; -using GoDotTest; +using Chickensoft.Collections; using Shouldly; +using Xunit; -public class NotifierTest : TestClass { - public NotifierTest(Node testScene) : base(testScene) { } - +public class NotifierTest { public static class Utils { public static void ClearWeakReference(WeakReference weakReference) { weakReference.Target = null; @@ -22,20 +19,20 @@ public static void ClearWeakReference(WeakReference weakReference) { new AutoProp(1) ); - [Test] + [Fact] public void Initializes() { var subject = new AutoProp(1); subject.Value.ShouldBe(1); } - [Test] + [Fact] public void InitializesWithComparer() { var subject = new AutoProp(1, EqualityComparer.Default); subject.Value.ShouldBe(1); subject.Comparer.ShouldBe(EqualityComparer.Default); } - [Test] + [Fact] public void SyncCallsHandlerImmediatelyAndAllowsUnsubscribe() { using var subject = new AutoProp(1); @@ -59,7 +56,7 @@ void onSync(int value) { changedCalled.ShouldBe(1); } - [Test] + [Fact] public void ClearsEventHandlers() { using var subject = new AutoProp(1); @@ -85,7 +82,7 @@ public void ClearsEventHandlers() { errorCalled.ShouldBe(0); } - [Test] + [Fact] public void CompletesAndBlocksOtherActions() { using var subject = new AutoProp(1); @@ -111,7 +108,7 @@ public void CompletesAndBlocksOtherActions() { errorCalled.ShouldBe(0); } - [Test] + [Fact] public void CallsErrorHandler() { using var subject = new AutoProp(1); @@ -133,7 +130,7 @@ void onError(Exception exception) { errorCalled.ShouldBe(1); } - [Test] + [Fact] public void DisposesCorrectly() { var subject = new AutoProp(1); @@ -160,7 +157,7 @@ public void DisposesCorrectly() { errorCalled.ShouldBe(0); } - [Test] + [Fact] public void Finalizes() { // Weak reference has to be created and cleared from a static function // or else the GC won't ever collect it :P @@ -168,7 +165,7 @@ public void Finalizes() { Utils.ClearWeakReference(subject); } - [Test] + [Fact] public void DoesNotCallHandlersIfValueHasNotChanged() { var subject = new AutoProp(1); @@ -185,7 +182,7 @@ public void DoesNotCallHandlersIfValueHasNotChanged() { syncCalled.ShouldBe(2); } - [Test] + [Fact] public void DoesNotCallHandlerWhileInsideHandler() { var subject = new AutoProp(1); @@ -196,11 +193,11 @@ public void DoesNotCallHandlerWhileInsideHandler() { changes.Add(value); subject.OnNext(3); }; - subject.Sync += (value) => syncs.Add(value); + subject.Sync += syncs.Add; subject.OnNext(2); - changes.ShouldBe(new[] { 2, 3 }); - syncs.ShouldBe(new[] { 1, 2, 3 }); + changes.ShouldBe([2, 3]); + syncs.ShouldBe([1, 2, 3]); } } diff --git a/Chickensoft.Collections.Tests/src/BlackboardTest.cs b/Chickensoft.Collections.Tests/src/BlackboardTest.cs new file mode 100644 index 0000000..869d843 --- /dev/null +++ b/Chickensoft.Collections.Tests/src/BlackboardTest.cs @@ -0,0 +1,35 @@ +namespace Chickensoft.Collections.Tests; + +using System.Collections.Generic; +using System.Data; +using Shouldly; +using Xunit; + +public class BlackboardTest { + [Fact] + public void SetsAndGetsData() { + var blackboard = new Blackboard(); + blackboard.Has().ShouldBeFalse(); + blackboard.HasObject(typeof(string)).ShouldBeFalse(); + blackboard.Set("data"); + blackboard.Has().ShouldBeTrue(); + blackboard.HasObject(typeof(string)).ShouldBeTrue(); + blackboard.Get().ShouldBe("data"); + blackboard.GetObject(typeof(string)).ShouldBe("data"); + blackboard.Overwrite("string"); + blackboard.Get().ShouldBe("string"); + blackboard.OverwriteObject(typeof(string), "overwritten"); + blackboard.GetObject(typeof(string)).ShouldBe("overwritten"); + blackboard.SetObject(typeof(int), 5); + blackboard.GetObject(typeof(int)).ShouldBe(5); + + blackboard.Types.ShouldBe([typeof(string), typeof(int)], ignoreOrder: true); + + // Can't change values once set. + Should.Throw(() => blackboard.Set("other")); + Should.Throw(() => blackboard.Get()); + Should.Throw( + () => blackboard.GetObject(typeof(string[])) + ); + } +} diff --git a/Chickensoft.GoDotCollections.Tests/test/src/MapTest.cs b/Chickensoft.Collections.Tests/src/MapTest.cs similarity index 55% rename from Chickensoft.GoDotCollections.Tests/test/src/MapTest.cs rename to Chickensoft.Collections.Tests/src/MapTest.cs index 1177f65..8649c1d 100644 --- a/Chickensoft.GoDotCollections.Tests/test/src/MapTest.cs +++ b/Chickensoft.Collections.Tests/src/MapTest.cs @@ -1,55 +1,53 @@ -namespace Chickensoft.GoDotCollections.Tests; +namespace Chickensoft.Collections.Tests; using System.Collections; using System.Collections.Generic; -using Godot; -using GoDotCollections; -using GoDotTest; using Shouldly; +using Xunit; -public class MapTest : TestClass { - public MapTest(Node testScene) : base(testScene) { } - - [Test] +public class MapTest { + [Fact] public void Initializes() => new Map().ShouldBeOfType>(); - [Test] + [Fact] public void GetsAndSetsKeys() { - var map = new Map(); - map["a"] = 1; + var map = new Map { + ["a"] = 1 + }; map["a"].ShouldBe(1); } - [Test] + [Fact] public void GetsAndSetsKeysByIndex() { - var map = new Map(); - map["a"] = 1; + var map = new Map { + ["a"] = 1 + }; map[0].ShouldBe(1); map[0] = 2; map["a"].ShouldBe(2); map[0].ShouldBe(2); } - [Test] + [Fact] public void GetsKeys() { var map = new Map(); map.Keys.ShouldBeAssignableTo>(); } - [Test] + [Fact] public void GetsValues() { var map = new Map(); map.Values.ShouldBeAssignableTo>(); } - [Test] + [Fact] public void IsReadOnly() { var map = new Map(); map.IsReadOnly.ShouldBe(false); } - [Test] + [Fact] public void Count() { var map = new Map(); map.Count.ShouldBe(0); @@ -59,79 +57,99 @@ public void Count() { map.Count.ShouldBe(0); } - [Test] + [Fact] public void Enumerator() { - var map = new Map(); - map["a"] = 1; - map["b"] = 2; - var dictionaryEnumerator = map.GetEnumerator(); + var map = new Map { + ["a"] = 1, + ["b"] = 2 + }; + var dictionaryEnumerator = (map as IEnumerable).GetEnumerator(); dictionaryEnumerator.MoveNext().ShouldBeTrue(); dictionaryEnumerator.MoveNext().ShouldBeTrue(); dictionaryEnumerator.MoveNext().ShouldBeFalse(); } - [Test] + [Fact] public void Insert() { - var map = new Map(); - map["a"] = 1; - map["b"] = 2; + var map = new Map { + ["a"] = 1, + ["b"] = 2 + }; map.Insert(1, "X", 100); map[1].ShouldBe(100); - map.Values.ShouldBe(new List { 1, 100, 2 }); + map.Values.ShouldBe([1, 100, 2]); } - [Test] + [Fact] public void RemoveAt() { - var map = new Map(); - map["a"] = 1; - map["b"] = 2; + var map = new Map { + ["a"] = 1, + ["b"] = 2 + }; map.RemoveAt(1); - map.Values.ShouldBe(new List { 1 }); + map.Values.ShouldBe([1]); } - [Test] + [Fact] public void Contains() { - var map = new Map(); - map["a"] = 1; + var map = new Map { + ["a"] = 1 + }; map.Contains("a").ShouldBeTrue(); map.Contains("b").ShouldBeFalse(); } - [Test] + [Fact] public void Add() { - var map = new Map(); - map.Add("a", 1); - map.Add("b", 2); - map.Keys.ShouldBe(new List { "a", "b" }); - map.Values.ShouldBe(new List { 1, 2 }); + var map = new Map { + { "a", 1 }, + { "b", 2 } + }; + map.Keys.ShouldBe(["a", "b"]); + map.Values.ShouldBe([1, 2]); } - [Test] + [Fact] public void Clear() { - var map = new Map(); - map["a"] = 1; - map["b"] = 2; + var map = new Map { + ["a"] = 1, + ["b"] = 2 + }; map.Clear(); map.Count.ShouldBe(0); } - [Test] + [Fact] public void Remove() { - var map = new Map(); - map["a"] = 1; - map["b"] = 2; + var map = new Map { + ["a"] = 1, + ["b"] = 2 + }; map.Remove("a"); - map.Keys.ShouldBe(new List { "b" }); + map.Keys.ShouldBe(["b"]); } - [Test] + [Fact] public void CopyTo() { - var map = new Map(); - map["a"] = 1; - map["b"] = 2; + var map = new Map { + ["a"] = 1, + ["b"] = 2 + }; var array = new DictionaryEntry[2]; map.CopyTo(array, 0); array[0].ShouldBeOfType(); array[1].ShouldBeOfType(); } + + [Fact] + public void KeysAreOrdered() { + var map = new Map() { + ["b"] = 2, + ["a"] = 1, + }; + + map["b"] = 3; + + map.Keys.ShouldBe(["b", "a"]); + } } diff --git a/Chickensoft.GoDotCollections/Chickensoft.GoDotCollections.csproj b/Chickensoft.Collections/Chickensoft.Collections.csproj similarity index 75% rename from Chickensoft.GoDotCollections/Chickensoft.GoDotCollections.csproj rename to Chickensoft.Collections/Chickensoft.Collections.csproj index e6c83d4..c201f9d 100644 --- a/Chickensoft.GoDotCollections/Chickensoft.GoDotCollections.csproj +++ b/Chickensoft.Collections/Chickensoft.Collections.csproj @@ -1,26 +1,26 @@ - netstandard2.0 + netstandard2.1 true preview true true enable true - Chickensoft.GoDotCollections + Chickensoft.Collections true ./nupkg portable - Chickensoft.GoDotCollections + Chickensoft.Collections 0.0.0-devbuild - Chickensoft's collections collection. - ยฉ 2023 Chickensoft + Lightweight collections, utilities, and general interface types to help make maintainable code. + ยฉ 2024 Chickensoft Chickensoft Chickensoft - Chickensoft.GoDotCollections - Chickensoft.GoDotCollections release. + Chickensoft.Collections + Chickensoft.Collections release. icon.png README.md diff --git a/Chickensoft.Collections/icon.png b/Chickensoft.Collections/icon.png new file mode 100644 index 0000000..cb73386 --- /dev/null +++ b/Chickensoft.Collections/icon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20227094ae35147ed39b7db89e7f2521b7f21bd98b0a8025fb4bec653d551f7f +size 73529 diff --git a/Chickensoft.Collections/src/Assembly.cs b/Chickensoft.Collections/src/Assembly.cs new file mode 100644 index 0000000..1262d41 --- /dev/null +++ b/Chickensoft.Collections/src/Assembly.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Chickensoft.Collections.Tests")] diff --git a/Chickensoft.GoDotCollections/src/AutoProp.cs b/Chickensoft.Collections/src/collections/AutoProp.cs similarity index 99% rename from Chickensoft.GoDotCollections/src/AutoProp.cs rename to Chickensoft.Collections/src/collections/AutoProp.cs index 257d98e..6db7a26 100644 --- a/Chickensoft.GoDotCollections/src/AutoProp.cs +++ b/Chickensoft.Collections/src/collections/AutoProp.cs @@ -1,4 +1,4 @@ -namespace Chickensoft.GoDotCollections; +namespace Chickensoft.Collections; using System; using System.Collections.Generic; diff --git a/Chickensoft.GoDotCollections/src/Map.cs b/Chickensoft.Collections/src/collections/Map.cs similarity index 92% rename from Chickensoft.GoDotCollections/src/Map.cs rename to Chickensoft.Collections/src/collections/Map.cs index 19e5cec..1d3b5eb 100644 --- a/Chickensoft.GoDotCollections/src/Map.cs +++ b/Chickensoft.Collections/src/collections/Map.cs @@ -1,4 +1,5 @@ -namespace Chickensoft.GoDotCollections; +namespace Chickensoft.Collections; + using System; using System.Collections; using System.Collections.Generic; @@ -12,8 +13,8 @@ namespace Chickensoft.GoDotCollections; /// /// Key type. /// Value type. -public class Map where TKey : notnull { - private readonly OrderedDictionary _collection = new(); +public class Map : IEnumerable where TKey : notnull { + private readonly OrderedDictionary _collection = []; /// Retrieve a map value by key. /// Map key. @@ -28,37 +29,49 @@ public TValue? this[int index] { get => (TValue?)_collection[index]; set => _collection[index] = value; } + /// Map keys. public IEnumerable Keys => _collection.Keys.Cast(); + /// Map values. public IEnumerable Values => _collection.Values.Cast(); + /// Whether or not the map is read-only. public bool IsReadOnly => _collection.IsReadOnly; + /// Number of key/value pairs in the map. public int Count => _collection.Count; + /// Map enumerator. public IDictionaryEnumerator GetEnumerator() => _collection.GetEnumerator(); + /// Insert a key and value at the specified index. /// Index to insert to. /// Key. /// Value. public void Insert(int index, TKey key, TValue value) => _collection.Insert(index, key, value); + /// Remove a key/value pair at the specified index. /// Index to remove from. public void RemoveAt(int index) => _collection.RemoveAt(index); + /// True if the given key is in the map. /// Key. public bool Contains(TKey key) => _collection.Contains(key); + /// Adds or updates a key/value pair to the map. /// Key. /// Value. public void Add(TKey key, TValue value) => _collection.Add(key, value); + /// Removes all entries from the map. public void Clear() => _collection.Clear(); + /// Remove a key/value pair from the map. /// Key. public void Remove(TKey key) => _collection.Remove(key); + /// /// Copy the map to an array, beginning at the given index. /// @@ -66,4 +79,6 @@ public void Insert(int index, TKey key, TValue value) /// Start index. public void CopyTo(Array array, int index) => _collection.CopyTo(array, index); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } diff --git a/Chickensoft.Collections/src/collections/blackboard/Blackboard.cs b/Chickensoft.Collections/src/collections/blackboard/Blackboard.cs new file mode 100644 index 0000000..6e560f9 --- /dev/null +++ b/Chickensoft.Collections/src/collections/blackboard/Blackboard.cs @@ -0,0 +1,81 @@ +namespace Chickensoft.Collections; + +using System; +using System.Collections.Generic; +using System.Data; +using System.Runtime.CompilerServices; + +/// +public class Blackboard : IReadOnlyBlackboard { + /// Blackboard data storage. + protected readonly Dictionary _blackboard = []; + + /// + /// Creates a new blackboard. + /// + public Blackboard() { } + + #region IReadOnlyBlackboard + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TData Get() where TData : class { + var type = typeof(TData); + return (TData)GetBlackboardData(type); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public object GetObject(Type type) => GetBlackboardData(type); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Has() where TData : class => HasObject(typeof(TData)); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool HasObject(Type type) => _blackboard.ContainsKey(type); + #endregion IReadOnlyBlackboard + + /// + #region Blackboard + public IEnumerable Types => _blackboard.Keys; + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Set(TData data) where TData : class { + var type = typeof(TData); + SetBlackboardData(type, data); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetObject(Type type, object data) => + SetBlackboardData(type, data); + + /// + public void Overwrite(TData data) where TData : class => + _blackboard[typeof(TData)] = data; + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void OverwriteObject(Type type, object data) => + _blackboard[type] = data; + #endregion Blackboard + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private object GetBlackboardData(Type type) => + _blackboard.TryGetValue(type, out var data) + ? data + : throw new KeyNotFoundException( + $"Data of type {type} not found in the blackboard." + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetBlackboardData(Type type, object data) { + if (!_blackboard.TryAdd(type, data)) { + throw new DuplicateNameException( + $"Data of type {type} already exists in the blackboard." + ); + } + } +} diff --git a/Chickensoft.Collections/src/collections/blackboard/IBlackboard.cs b/Chickensoft.Collections/src/collections/blackboard/IBlackboard.cs new file mode 100644 index 0000000..f938311 --- /dev/null +++ b/Chickensoft.Collections/src/collections/blackboard/IBlackboard.cs @@ -0,0 +1,53 @@ +namespace Chickensoft.Collections; + +using System; +using System.Collections.Generic; +using System.Data; + +/// +/// A blackboard is a table of data. Data is accessed by its type and shared +/// between logic block states. +/// +public interface IBlackboard : IReadOnlyBlackboard { + /// + /// Adds data to the blackboard so that it can be looked up by its + /// compile-time type. + ///
+ /// Data is retrieved by its type, so do not add more than one piece of data + /// with the same type. + ///
+ /// Data to write to the blackboard. + /// Type of the data to add. + /// + void Set(TData data) where TData : class; + /// + /// Adds data to the blackboard and associates it with a specific type. + ///
+ /// Data is retrieved by its type, so do not add more than one piece of data + /// with the same type. + ///
+ /// Type of the data. + /// Data to write to the blackboard. + /// + void SetObject(Type type, object data); + /// + /// Adds new data or overwrites existing data in the blackboard, based on + /// its compile-time type. + ///
+ /// Data is retrieved by its type, so this will overwrite any existing data + /// of the given type, unlike . + ///
+ /// Data to write to the blackboard. + /// Type of the data to add or overwrite. + void Overwrite(TData data) where TData : class; + /// + /// Adds new data or overwrites existing data in the blackboard and associates + /// it with a specific type. + ///
+ /// Data is retrieved by its type, so this will overwrite any existing data + /// of the given type, unlike . + ///
+ /// Type of the data. + /// Data to write to the blackboard. + void OverwriteObject(Type type, object data); +} diff --git a/Chickensoft.Collections/src/collections/blackboard/IReadOnlyBlackboard.cs b/Chickensoft.Collections/src/collections/blackboard/IReadOnlyBlackboard.cs new file mode 100644 index 0000000..5de7fe7 --- /dev/null +++ b/Chickensoft.Collections/src/collections/blackboard/IReadOnlyBlackboard.cs @@ -0,0 +1,44 @@ +namespace Chickensoft.Collections; + +using System; +using System.Collections.Generic; + +/// +/// A read-only blackboard. A blackboard is a table of data. Data is accessed by +/// its type and shared between logic block states. +/// +public interface IReadOnlyBlackboard { + /// All types present in the blackboard. + /// Enumerable types present in the blackboard. + IEnumerable Types { get; } + + /// + /// Gets data from the blackboard by its compile-time type. + /// + /// The type of data to retrieve. + /// + TData Get() where TData : class; + + /// + /// Gets data from the blackboard by its runtime type. + /// + /// Type of the data to retrieve. + /// + object GetObject(Type type); + + /// + /// Determines if the logic block has data of the given type. + /// + /// The type of data to look for. + /// True if the blackboard contains data for that type, false + /// otherwise. + bool Has() where TData : class; + + /// + /// Determines if the logic block has data of the given type. + /// + /// The type of data to look for. + /// True if the blackboard contains data for that type, false + /// otherwise. + bool HasObject(Type type); +} diff --git a/Chickensoft.Collections/src/collections/set/IReadOnlySet.cs b/Chickensoft.Collections/src/collections/set/IReadOnlySet.cs new file mode 100644 index 0000000..13f14ad --- /dev/null +++ b/Chickensoft.Collections/src/collections/set/IReadOnlySet.cs @@ -0,0 +1,95 @@ +namespace Chickensoft.Collections; + +using System.Collections.Generic; + +/// +/// Provides a readonly abstraction of a set. +/// +/// The type of elements in the set. +public interface IReadOnlySet : IReadOnlyCollection { + /// + /// Determines whether a set is a subset of a specified collection. + /// + /// The collection to compare to the current set. + /// True if the current set is a subset of other; otherwise, false. + /// + /// If other contains the same elements as the current set, the + /// current set is still considered a subset of other. This method always + /// returns false if the current set has elements that are not in other. + /// + bool IsSubsetOf(IEnumerable other); + + /// + /// Determines whether the current set is a superset of a specified + /// collection. + /// + /// The collection to compare to the current set. + /// True if the current set is a subset of other; otherwise, false. + /// + /// + /// If other contains the same elements as the current set, the current set + /// is still considered a subset of other. This method always returns false + /// if the current set has elements that are not in other. + /// + bool IsSupersetOf(IEnumerable other); + + /// + /// Determines whether the current set is a proper (strict) superset of a + /// specified collection. + /// + /// The collection to compare to the current set. + /// True if the current set is a proper superset of other; + /// otherwise, false. + /// + /// If the current set is a proper superset of other, the current set must + /// have at least one element that other does not have. + ///
+ /// An empty set is a proper superset of any other collection. Therefore, this + /// method returns true if the collection represented by the other parameter + /// is empty, unless the current set is also empty. + ///
+ /// This method always returns false if the number of elements in the current + /// set is less than or equal to the number of elements in other. + ///
+ bool IsProperSupersetOf(IEnumerable other); + + /// + /// Determines whether the current set is a proper (strict) subset of a + /// specified collection. + /// + /// The collection to compare to the current set. + /// True if the current set is a proper subset of other; otherwise, + /// false. + /// + /// If the current set is a proper subset of other, other must have at least + /// one element that the current set does not have. + ///
+ /// An empty set is a proper subset of any other collection. Therefore, this method returns true if the current set is empty, unless the other parameter is also an empty set. + ///
+ /// This method always returns false if the current set has more or the same + /// number of elements than other. + ///
+ bool IsProperSubsetOf(IEnumerable other); + + /// + /// Determines whether the current set overlaps with the specified collection. + /// + /// The collection to compare to the current set. + /// True if the current set and other share at least one common + /// element; otherwise, false. + /// Any duplicate elements in other are ignored. + bool Overlaps(IEnumerable other); + + /// + /// Determines whether the current set and the specified collection contain + /// the same elements. + /// + /// The collection to compare to the current set. + /// True if the current set is equal to other; otherwise, false. + /// + /// + /// This method ignores the order of elements and any duplicate elements in + /// other. + /// + bool SetEquals(IEnumerable other); +} diff --git a/Chickensoft.Collections/src/collections/set/Set.cs b/Chickensoft.Collections/src/collections/set/Set.cs new file mode 100644 index 0000000..9052566 --- /dev/null +++ b/Chickensoft.Collections/src/collections/set/Set.cs @@ -0,0 +1,10 @@ +namespace Chickensoft.Collections; + +using System.Collections.Generic; + +/// +/// Set implementation that simply extends conforms to the +/// interface. +/// +/// The type of elements in the set. +public class Set : HashSet, IReadOnlySet; diff --git a/Chickensoft.GoDotCollections.Tests/Chickensoft.GoDotCollections.Tests.csproj b/Chickensoft.GoDotCollections.Tests/Chickensoft.GoDotCollections.Tests.csproj deleted file mode 100644 index 2f272ad..0000000 --- a/Chickensoft.GoDotCollections.Tests/Chickensoft.GoDotCollections.Tests.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - net6.0 - true - 10.0 - enable - Chickensoft.GoDotCollections.Tests - - - true - - - full - true - - - - - - - - - - - - - - diff --git a/Chickensoft.GoDotCollections.Tests/Chickensoft.GoDotCollections.Tests.sln b/Chickensoft.GoDotCollections.Tests/Chickensoft.GoDotCollections.Tests.sln deleted file mode 100644 index 62b2174..0000000 --- a/Chickensoft.GoDotCollections.Tests/Chickensoft.GoDotCollections.Tests.sln +++ /dev/null @@ -1,19 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chickensoft.GoDotCollections.Tests", "Chickensoft.GoDotCollections.Tests.csproj", "{15B15115-5F4F-4D74-A0AA-6AC2CE564E17}" -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 - {15B15115-5F4F-4D74-A0AA-6AC2CE564E17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {15B15115-5F4F-4D74-A0AA-6AC2CE564E17}.Debug|Any CPU.Build.0 = Debug|Any CPU - {15B15115-5F4F-4D74-A0AA-6AC2CE564E17}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU - {15B15115-5F4F-4D74-A0AA-6AC2CE564E17}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU - {15B15115-5F4F-4D74-A0AA-6AC2CE564E17}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU - {15B15115-5F4F-4D74-A0AA-6AC2CE564E17}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU - EndGlobalSection -EndGlobal diff --git a/Chickensoft.GoDotCollections.Tests/badges/.gdignore b/Chickensoft.GoDotCollections.Tests/badges/.gdignore deleted file mode 100644 index e69de29..0000000 diff --git a/Chickensoft.GoDotCollections.Tests/coverage.sh b/Chickensoft.GoDotCollections.Tests/coverage.sh deleted file mode 100755 index 40892ea..0000000 --- a/Chickensoft.GoDotCollections.Tests/coverage.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/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 "--headless --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" - -# 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="" - -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' - ;; - - CYGWIN*|MINGW32*|MSYS*|MINGW*) - echo 'MS Windows' - start coverage/report/index.htm - ;; - - *) - echo 'Other OS' - ;; -esac diff --git a/Chickensoft.GoDotCollections.Tests/coverage/.gdignore b/Chickensoft.GoDotCollections.Tests/coverage/.gdignore deleted file mode 100644 index e69de29..0000000 diff --git a/Chickensoft.GoDotCollections.Tests/icon.svg b/Chickensoft.GoDotCollections.Tests/icon.svg deleted file mode 100644 index adc26df..0000000 --- a/Chickensoft.GoDotCollections.Tests/icon.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Chickensoft.GoDotCollections.Tests/icon.svg.import b/Chickensoft.GoDotCollections.Tests/icon.svg.import deleted file mode 100644 index 7cc0431..0000000 --- a/Chickensoft.GoDotCollections.Tests/icon.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[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/lossy_quality=0.7 -compress/hdr_compression=1 -compress/bptc_ldr=0 -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.GoDotCollections.Tests/nuget.config b/Chickensoft.GoDotCollections.Tests/nuget.config deleted file mode 100644 index 27ed8a9..0000000 --- a/Chickensoft.GoDotCollections.Tests/nuget.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Chickensoft.GoDotCollections.Tests/project.godot b/Chickensoft.GoDotCollections.Tests/project.godot deleted file mode 100644 index db4bf3b..0000000 --- a/Chickensoft.GoDotCollections.Tests/project.godot +++ /dev/null @@ -1,24 +0,0 @@ -; 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.GoDotCollections.Tests" -run/main_scene="res://test/Tests.tscn" -config/features=PackedStringArray("4.0", "C#", "Mobile") -config/icon="res://icon.svg" - -[dotnet] - -project/assembly_name="Chickensoft.GoDotCollections.Tests" - -[rendering] - -renderer/rendering_method="mobile" diff --git a/Chickensoft.GoDotCollections.Tests/test/Tests.cs b/Chickensoft.GoDotCollections.Tests/test/Tests.cs deleted file mode 100644 index ea13b77..0000000 --- a/Chickensoft.GoDotCollections.Tests/test/Tests.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Chickensoft.GoDotCollections.Tests; - -using System.Reflection; -using Godot; -using GoDotTest; - -public partial class Tests : Node2D { - /// - /// Called when the node enters the scene tree for the first time. - /// - public override void _Ready() - => GoTest.RunTests(Assembly.GetExecutingAssembly(), this); -} diff --git a/Chickensoft.GoDotCollections.Tests/test/Tests.tscn b/Chickensoft.GoDotCollections.Tests/test/Tests.tscn deleted file mode 100644 index 14ebf60..0000000 --- a/Chickensoft.GoDotCollections.Tests/test/Tests.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[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.GoDotCollections.sln b/Chickensoft.GoDotCollections.sln deleted file mode 100644 index f395d3a..0000000 --- a/Chickensoft.GoDotCollections.sln +++ /dev/null @@ -1,28 +0,0 @@ -๏ปฟ -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.GoDotCollections", "Chickensoft.GoDotCollections\Chickensoft.GoDotCollections.csproj", "{903B3813-A7D9-4BBE-9DA9-9CE259C5CF6F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chickensoft.GoDotCollections.Tests", "Chickensoft.GoDotCollections.Tests\Chickensoft.GoDotCollections.Tests.csproj", "{3C391030-B330-4507-8CC8-804DA4EF83EF}" -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 - {903B3813-A7D9-4BBE-9DA9-9CE259C5CF6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {903B3813-A7D9-4BBE-9DA9-9CE259C5CF6F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {903B3813-A7D9-4BBE-9DA9-9CE259C5CF6F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {903B3813-A7D9-4BBE-9DA9-9CE259C5CF6F}.Release|Any CPU.Build.0 = Release|Any CPU - {3C391030-B330-4507-8CC8-804DA4EF83EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C391030-B330-4507-8CC8-804DA4EF83EF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C391030-B330-4507-8CC8-804DA4EF83EF}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {3C391030-B330-4507-8CC8-804DA4EF83EF}.Release|Any CPU.Build.0 = Debug|Any CPU - EndGlobalSection -EndGlobal diff --git a/Chickensoft.GoDotCollections/icon.png b/Chickensoft.GoDotCollections/icon.png deleted file mode 100644 index ff06ecc..0000000 --- a/Chickensoft.GoDotCollections/icon.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c2df21969f892631b68883b69090ffc9e8e3318d130e16f1c8406be128fe0882 -size 25603 diff --git a/Chickensoft.GoDotCollections/src/Assembly.cs b/Chickensoft.GoDotCollections/src/Assembly.cs deleted file mode 100644 index e4b6a96..0000000 --- a/Chickensoft.GoDotCollections/src/Assembly.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Chickensoft.GoDotCollections.Tests")] diff --git a/README.md b/README.md index 17acf4b..7d1bfc1 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,46 @@ -# GoDotCollections +# Chickensoft Collections [![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] -Chickensoft's collections collection. +Lightweight collections, utilities, and general interface types to help make maintainable code. ---

-Cardboard Box with Chickensoft Logo +Cardboard Box with Chickensoft Logo

-Sometimes you need a collection abstraction that just isn't present in dotnet. Well, here you are. - ## Install -Currently, there are no Godot-specific dependencies. This is just a netstandard2.0 package โ€” use with any Godot version! +```sh +dotnet add package Chickensoft.Collections +``` ## Map -A typed facade over `OrderedDictionary`. Provides a basic mechanism to store strongly typed keys and values (preserving key insertion order). +A typed facade over `OrderedDictionary`. Provides a basic mechanism to store strongly typed keys and values while preserving key insertion order. + +```csharp + var map = new Map() { + ["b"] = 2, + ["a"] = 1, + }; + + map.Keys.ShouldBe(["b", "a"]); +``` + +## Set and IReadOnlySet + +For whatever reason, netstandard does not include `IReadOnlySet`. To workaround this, we've provided our own version of `IReadOnlySet` and a `Set` implementation that simply extends `HashSet` and adds the interface to it. ## AutoProp -GoDotCollections includes a small reactive helper object that allows you to make observable properties in the style of `IObservable`, but is implemented over plain C# events and modifies the API to be more ergonomic *a la Chickensoft*. +AutoProp allows you to make observable properties in the style of `IObservable`, but is implemented over plain C# events and modifies the API to be more ergonomic, *a la Chickensoft style*. -AutoProps are basically a simplified version of a `BehaviorSubject` that only updates when the new value is not equal to the previous value, as determined by the equality comparer (or the default one if you don't provide one). +AutoProps are basically a simplified version of a `BehaviorSubject` that only updates when the new value is not equal to the previous value, as determined by the equality comparer (or the default one if you don't provide one). They operate synchronously and make guarantees about the order of changes in a very simple, easy to reason about manner. ```csharp -using Chickensoft.GoDotCollections; +using Chickensoft.Collections; public class MyObject : IDisposable { // Read-only version exposed as interface. @@ -105,9 +118,17 @@ public class MyObject : IDisposable { - โœ… Doesn't update if the value hasn't changed. +## Blackboard + +A blackboard datatype is provided that allows reference values to be stored by type. It implements two interfaces, `IBlackboard` and `IReadOnlyBlackboard`. + +```csharp + +``` + --- -๐Ÿฃ Package generated from a ๐Ÿค Chickensoft Template โ€” +๐Ÿฃ Created with love by Chickensoft ๐Ÿค โ€” [chickensoft-badge]: https://raw.githubusercontent.com/chickensoft-games/chickensoft_site/main/static/img/badges/chickensoft_badge.svg [chickensoft-website]: https://chickensoft.games @@ -115,5 +136,5 @@ public class MyObject : IDisposable { [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/docsickensoft%20Discord-%237289DA.svg?style=flat&logo=discord&logoColor=white -[line-coverage]: Chickensoft.GoDotCollections.Tests/badges/line_coverage.svg -[branch-coverage]: Chickensoft.GoDotCollections.Tests/badges/branch_coverage.svg +[line-coverage]: Chickensoft.Collections.Tests/badges/line_coverage.svg +[branch-coverage]: Chickensoft.Collections.Tests/badges/branch_coverage.svg diff --git a/cspell.json b/cspell.json index 8e868cb..8da4ec6 100644 --- a/cspell.json +++ b/cspell.json @@ -5,9 +5,8 @@ "ignorePaths": [ "**/*.tscn", "**/*.import", - "Chickensoft.GoDotCollections.Tests/badges/**/*.*", - "Chickensoft.GoDotCollections.Tests/coverage/**/*.*", - "Chickensoft.GoDotCollections.Tests/.godot/**/*.*" + "Chickensoft.Collections.Tests/badges/**/*.*", + "Chickensoft.Collections.Tests/coverage/**/*.*" ], "words": [ "assemblyfilters", @@ -26,8 +25,6 @@ "Finalizer", "Finalizers", "globaltool", - "godotengine", - "godotpackage", "issuecomment", "justalemon", "lcov", @@ -64,4 +61,4 @@ "Unparented", "Xunit" ] -} +} \ No newline at end of file