diff --git a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.dll b/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.dll
deleted file mode 100644
index ed40419a54dee5fc4c37a568448e3fb303adf430..0000000000000000000000000000000000000000
--- a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.dll
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:64f5675190dab38200ad7d1adf112e18356070817d4e668c8d0bcf0f4d295330
-size 341504
diff --git a/Assets/Packages/morelinq.3.4.2/morelinq.3.4.2.nupkg b/Assets/Packages/morelinq.3.4.2/morelinq.3.4.2.nupkg
deleted file mode 100644
index cc2cc11e029a1da4c3211ca94ba034b65ad243e5..0000000000000000000000000000000000000000
Binary files a/Assets/Packages/morelinq.3.4.2/morelinq.3.4.2.nupkg and /dev/null differ
diff --git a/Assets/Packages/morelinq.3.4.2.meta b/Assets/Packages/morelinq.4.1.0.meta
similarity index 77%
rename from Assets/Packages/morelinq.3.4.2.meta
rename to Assets/Packages/morelinq.4.1.0.meta
index 7863f9630f6b7d18d109fe834e3e95af764e19e1..b7af24565d816c48e2f6e8d448bb3e916fbd507e 100644
--- a/Assets/Packages/morelinq.3.4.2.meta
+++ b/Assets/Packages/morelinq.4.1.0.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 8ac5a9fb8f513cb45ac53b8b8108f5bc
+guid: 88a2bf6590e8fe74b90eace7f4f9b096
 folderAsset: yes
 DefaultImporter:
   externalObjects: {}
diff --git a/Assets/Packages/morelinq.3.4.2/.signature.p7s b/Assets/Packages/morelinq.4.1.0/.signature.p7s
similarity index 72%
rename from Assets/Packages/morelinq.3.4.2/.signature.p7s
rename to Assets/Packages/morelinq.4.1.0/.signature.p7s
index 03f3747c54baff21c9deb88e38beb77a8ba2ca9b..8b3ae022954c9f7983a2e9da4e6cb23432dfcfb2 100644
Binary files a/Assets/Packages/morelinq.3.4.2/.signature.p7s and b/Assets/Packages/morelinq.4.1.0/.signature.p7s differ
diff --git a/Assets/Packages/morelinq.3.4.2/COPYING.txt b/Assets/Packages/morelinq.4.1.0/COPYING.txt
similarity index 100%
rename from Assets/Packages/morelinq.3.4.2/COPYING.txt
rename to Assets/Packages/morelinq.4.1.0/COPYING.txt
diff --git a/Assets/Packages/morelinq.3.4.2/COPYING.txt.meta b/Assets/Packages/morelinq.4.1.0/COPYING.txt.meta
similarity index 75%
rename from Assets/Packages/morelinq.3.4.2/COPYING.txt.meta
rename to Assets/Packages/morelinq.4.1.0/COPYING.txt.meta
index 6612bd9e9f02f97721716ad1df8265e675a66655..33b8845c2a33dbd27f7c5e511881e65bb29d152f 100644
--- a/Assets/Packages/morelinq.3.4.2/COPYING.txt.meta
+++ b/Assets/Packages/morelinq.4.1.0/COPYING.txt.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 301b7f85f7db42f43ba1de1eb9171df3
+guid: fa565e8d2134a894c83e03bb2e6b990b
 TextScriptImporter:
   externalObjects: {}
   userData: 
diff --git a/Assets/Packages/morelinq.3.4.2/README.md b/Assets/Packages/morelinq.4.1.0/README.md
similarity index 94%
rename from Assets/Packages/morelinq.3.4.2/README.md
rename to Assets/Packages/morelinq.4.1.0/README.md
index ece3287fc5066b4bf048aea1b39ae403e5dcbc61..2a897f2113b04713c26a308175be2c50679f964f 100644
--- a/Assets/Packages/morelinq.3.4.2/README.md
+++ b/Assets/Packages/morelinq.4.1.0/README.md
@@ -34,10 +34,11 @@ using static MoreLinq.Extensions.LeadExtension;
 In the example above, only the [`Lag`][lag] and [`Lead`][lead] extension
 methods will be available in scope.
 
-Apart from extension methods, MoreLINQ also offers regular static method
-that *generate* (instead of operating on) sequences, like `Unfold`,
-`Random`, `Sequence` and others. If you want to use these while statically
-importing other individual extension methods, you can do so via aliasing:
+Apart from extension methods, MoreLINQ also offers regular static method that
+*generate* (instead of operating on) sequences, like [`Unfold`][unfold],
+[`Random`][random], [`Sequence`][sequence] and others. If you want to use these
+while statically importing other individual extension methods, you can do so via
+aliasing:
 
 ```c#
 using static MoreLinq.Extensions.LagExtension;
@@ -167,8 +168,11 @@ first sequence has fewer, the same or more elements than the second sequence.
 
 Returns a sequence consisting of the head element and the given tail elements.
 
-This method is obsolete and will be removed in a future version. Use `Append`
-instead.
+This extension was rendered obsolete in version 3.0 and eventually removed in
+version 4.0. Use [`Append`][linq-append] from .NET instead that's been available
+since .NET Standard 1.6+, .NET Core 1.0+ and .NET Framework 4.7.1+.
+
+[linq-append]: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.append
 
 ### Consume
 
@@ -202,6 +206,12 @@ projected type.
 
 This method has 2 overloads.
 
+### Duplicates
+
+Returns all duplicate elements of the given source.
+
+This method has 2 overloads.
+
 ### EndsWith
 
 Determines whether the end of the first sequence is equivalent to the second
@@ -357,14 +367,32 @@ Performs a left outer join between two sequences.
 
 This method has 4 overloads.
 
-### MaxBy
+### ~~MaxBy~~
+
+:warning: **This method is obsolete. Use [`Maxima`](#maxima) instead.**
 
 Returns the maxima (maximal elements) of the given sequence, based on the
 given projection.
 
 This method has 2 overloads.
 
-### MinBy
+### Maxima
+
+Returns the maxima (maximal elements) of the given sequence, based on the
+given projection.
+
+This method has 2 overloads.
+
+### ~~MinBy~~
+
+:warning: **This method is obsolete. Use [`Minima`](#minima) instead.**
+
+Returns the minima (minimal elements) of the given sequence, based on the
+given projection.
+
+This method has 2 overloads.
+
+### Minima
 
 Returns the minima (minimal elements) of the given sequence, based on the
 given projection.
@@ -689,8 +717,7 @@ subset of the original
 Processes a sequence into a series of subsequences representing a windowed
 subset of the original
 
-This method is obsolete and will be removed in a future version. Use `Window`
-instead.
+This method was removed and has been superseded by [`Window`](#window) instead.
 
 ### WindowLeft
 
diff --git a/Assets/Packages/morelinq.3.4.2/README.md.meta b/Assets/Packages/morelinq.4.1.0/README.md.meta
similarity index 75%
rename from Assets/Packages/morelinq.3.4.2/README.md.meta
rename to Assets/Packages/morelinq.4.1.0/README.md.meta
index 155e826df16cc4e5bb38bb092a16e50241464c65..0c2e3b52eb30c7079b8b306508f30c99bc2b1aaa 100644
--- a/Assets/Packages/morelinq.3.4.2/README.md.meta
+++ b/Assets/Packages/morelinq.4.1.0/README.md.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 2c02eae7182b7b9439d234e0c3c468ce
+guid: 63128cb297f01cf4ab31e482c4cfe2fc
 TextScriptImporter:
   externalObjects: {}
   userData: 
diff --git a/Assets/Packages/morelinq.3.4.2/lib.meta b/Assets/Packages/morelinq.4.1.0/lib.meta
similarity index 77%
rename from Assets/Packages/morelinq.3.4.2/lib.meta
rename to Assets/Packages/morelinq.4.1.0/lib.meta
index 8b0a0d80be0a724296d67c2dbdf20c36a86fd7f4..81e5ae54d1f30deb4aedae8ce9731d11d9b098ed 100644
--- a/Assets/Packages/morelinq.3.4.2/lib.meta
+++ b/Assets/Packages/morelinq.4.1.0/lib.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 99aaade9aebe6fa4a89590d585727759
+guid: 6ed39c01f8508d04596c455cf576bd63
 folderAsset: yes
 DefaultImporter:
   externalObjects: {}
diff --git a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1.meta b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1.meta
similarity index 77%
rename from Assets/Packages/morelinq.3.4.2/lib/netstandard2.1.meta
rename to Assets/Packages/morelinq.4.1.0/lib/netstandard2.1.meta
index 04de02c202b265756d049fee9783fc4f5c258633..61e7bd39756fc914fee14ddafe7b41c2dd99ea7b 100644
--- a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1.meta
+++ b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 2a95cde6af78e274d8ad315bd4735054
+guid: 8828b04e155f03846a3d91822fe830d0
 folderAsset: yes
 DefaultImporter:
   externalObjects: {}
diff --git a/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.dll b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.dll
new file mode 100644
index 0000000000000000000000000000000000000000..51647d341394f6f30a0ac7b22ad69d70c7253604
--- /dev/null
+++ b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.dll
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:666a3ea539793fccdc50ac2d639828221e16e8b6d55ba12d178efdd1be2042a6
+size 335872
diff --git a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.dll.meta b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.dll.meta
similarity index 91%
rename from Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.dll.meta
rename to Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.dll.meta
index 8d7c65391b226809adb61a218c8cd00b601b50e6..2a5ade255624add56fd7322867bb54571718b15d 100644
--- a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.dll.meta
+++ b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.dll.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: bb6220cc6a89fbd4da9723d767b62041
+guid: a236491e6a7e06c43910d647e752c100
 labels:
 - NuGetForUnity
 PluginImporter:
diff --git a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.xml b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.xml
similarity index 97%
rename from Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.xml
rename to Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.xml
index dafea4c2d53ee0d8a15009b3288118e9978970bb..527bfc95ff50c11fff67c7cdb5a6f5bb59b58de7 100644
--- a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.xml
+++ b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.xml
@@ -325,16 +325,6 @@
             <returns>A sequence consisting of the head elements and the given tail element.</returns>
             <remarks>This operator uses deferred execution and streams its results.</remarks>
         </member>
-        <member name="M:MoreLinq.MoreEnumerable.Concat``1(System.Collections.Generic.IEnumerable{``0},``0)">
-            <summary>
-            Returns a sequence consisting of the head elements and the given tail element.
-            </summary>
-            <typeparam name="T">Type of sequence</typeparam>
-            <param name="head">All elements of the head. Must not be null.</param>
-            <param name="tail">Tail element of the new sequence.</param>
-            <returns>A sequence consisting of the head elements and the given tail element.</returns>
-            <remarks>This operator uses deferred execution and streams its results.</remarks>
-        </member>
         <member name="M:MoreLinq.MoreEnumerable.Assert``1(System.Collections.Generic.IEnumerable{``0},System.Func{``0,System.Boolean})">
             <summary>
             Asserts that all elements of a sequence meet a given condition
@@ -469,7 +459,7 @@
             </para>
             </remarks>
         </member>
-        <member name="M:MoreLinq.MoreEnumerable.Batch``2(System.Collections.Generic.IEnumerable{``0},System.Int32,System.Func{System.Collections.Generic.IEnumerable{``0},``1})">
+        <member name="M:MoreLinq.MoreEnumerable.Batch``2(System.Collections.Generic.IEnumerable{``0},System.Int32,System.Func{``0[],``1})">
             <summary>
             Batches the source sequence into sized buckets and applies a projection to each bucket.
             </summary>
@@ -990,6 +980,31 @@
             <returns>A sequence consisting of distinct elements from the source sequence,
             comparing them by the specified key projection.</returns>
         </member>
+        <member name="M:MoreLinq.MoreEnumerable.Duplicates``1(System.Collections.Generic.IEnumerable{``0})">
+            <summary>
+            Returns all duplicate elements of the given source.
+            </summary>
+            <param name="source">The source sequence.</param>
+            <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
+            <returns>All elements that are duplicated.</returns>
+            <remarks>This operator uses deferred execution and streams its results.</remarks>
+        </member>
+        <member name="M:MoreLinq.MoreEnumerable.Duplicates``1(System.Collections.Generic.IEnumerable{``0},System.Collections.Generic.IEqualityComparer{``0})">
+            <summary>
+            Returns all duplicate elements of the given source, using the specified equality
+            comparer.
+            </summary>
+            <param name="source">The source sequence.</param>
+            <param name="comparer">
+            The equality comparer to use to determine whether one <typeparamref name="TSource"/>
+            equals another. If <see langword="null"/>, the default equality comparer for
+            <typeparamref name="TSource"/> is used.</param>
+            <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
+            <returns>All elements that are duplicated.</returns>
+            <remarks>This operator uses deferred execution and streams its results.</remarks>
+        </member>
         <member name="M:MoreLinq.MoreEnumerable.EndsWith``1(System.Collections.Generic.IEnumerable{``0},System.Collections.Generic.IEnumerable{``0})">
             <summary>
             Determines whether the end of the first sequence is equivalent to
@@ -2674,6 +2689,41 @@
             <returns>A sequence containing results projected from a left
             outer join of the two input sequences.</returns>
         </member>
+        <member name="M:MoreLinq.MoreEnumerable.MaxBy``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})">
+            <summary>
+            Returns the maximal elements of the given sequence, based on
+            the given projection.
+            </summary>
+            <remarks>
+            This overload uses the default comparer  for the projected type.
+            This operator uses deferred execution. The results are evaluated
+            and cached on first use to returned sequence.
+            </remarks>
+            <typeparam name="TSource">Type of the source sequence</typeparam>
+            <typeparam name="TKey">Type of the projected element</typeparam>
+            <param name="source">Source sequence</param>
+            <param name="selector">Selector to use to pick the results to compare</param>
+            <returns>The sequence of maximal elements, according to the projection.</returns>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null</exception>
+        </member>
+        <member name="M:MoreLinq.MoreEnumerable.MaxBy``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IComparer{``1})">
+            <summary>
+            Returns the maximal elements of the given sequence, based on
+            the given projection and the specified comparer for projected values.
+            </summary>
+            <remarks>
+            This operator uses deferred execution. The results are evaluated
+            and cached on first use to returned sequence.
+            </remarks>
+            <typeparam name="TSource">Type of the source sequence</typeparam>
+            <typeparam name="TKey">Type of the projected element</typeparam>
+            <param name="source">Source sequence</param>
+            <param name="selector">Selector to use to pick the results to compare</param>
+            <param name="comparer">Comparer to use to compare projected values</param>
+            <returns>The sequence of maximal elements, according to the projection.</returns>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/>, <paramref name="selector"/>
+            or <paramref name="comparer"/> is null</exception>
+        </member>
         <member name="M:MoreLinq.MoreEnumerable.First``1(MoreLinq.IExtremaEnumerable{``0})">
             <summary>
             Returns the first element of a sequence.
@@ -2754,7 +2804,7 @@
             <typeparamref name="T"/> if the sequence contains no elements.
             </returns>
         </member>
-        <member name="M:MoreLinq.MoreEnumerable.MaxBy``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})">
+        <member name="M:MoreLinq.MoreEnumerable.Maxima``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})">
             <summary>
             Returns the maximal elements of the given sequence, based on
             the given projection.
@@ -2771,7 +2821,7 @@
             <returns>The sequence of maximal elements, according to the projection.</returns>
             <exception cref="T:System.ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null</exception>
         </member>
-        <member name="M:MoreLinq.MoreEnumerable.MaxBy``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IComparer{``1})">
+        <member name="M:MoreLinq.MoreEnumerable.Maxima``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IComparer{``1})">
             <summary>
             Returns the maximal elements of the given sequence, based on
             the given projection and the specified comparer for projected values.
@@ -2824,6 +2874,41 @@
             <exception cref="T:System.ArgumentNullException"><paramref name="source"/>, <paramref name="selector"/>
             or <paramref name="comparer"/> is null</exception>
         </member>
+        <member name="M:MoreLinq.MoreEnumerable.Minima``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})">
+            <summary>
+            Returns the minimal elements of the given sequence, based on
+            the given projection.
+            </summary>
+            <remarks>
+            This overload uses the default comparer for the projected type.
+            This operator uses deferred execution. The results are evaluated
+            and cached on first use to returned sequence.
+            </remarks>
+            <typeparam name="TSource">Type of the source sequence</typeparam>
+            <typeparam name="TKey">Type of the projected element</typeparam>
+            <param name="source">Source sequence</param>
+            <param name="selector">Selector to use to pick the results to compare</param>
+            <returns>The sequence of minimal elements, according to the projection.</returns>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null</exception>
+        </member>
+        <member name="M:MoreLinq.MoreEnumerable.Minima``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IComparer{``1})">
+            <summary>
+            Returns the minimal elements of the given sequence, based on
+            the given projection and the specified comparer for projected values.
+            </summary>
+            <remarks>
+            This operator uses deferred execution. The results are evaluated
+            and cached on first use to returned sequence.
+            </remarks>
+            <typeparam name="TSource">Type of the source sequence</typeparam>
+            <typeparam name="TKey">Type of the projected element</typeparam>
+            <param name="source">Source sequence</param>
+            <param name="selector">Selector to use to pick the results to compare</param>
+            <param name="comparer">Comparer to use to compare projected values</param>
+            <returns>The sequence of minimal elements, according to the projection.</returns>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/>, <paramref name="selector"/>
+            or <paramref name="comparer"/> is null</exception>
+        </member>
         <member name="M:MoreLinq.MoreEnumerable.Move``1(System.Collections.Generic.IEnumerable{``0},System.Int32,System.Int32,System.Int32)">
             <summary>
             Returns a sequence with a range of elements in the source sequence
@@ -2850,15 +2935,6 @@
             The <c>result</c> variable will contain <c>{ 3, 4, 0, 1, 2, 5 }</c>.
             </example>
         </member>
-        <member name="M:MoreLinq.MoreEnumerable.NestedLoops(System.Action,System.Collections.Generic.IEnumerable{System.UInt64})">
-            <summary>
-            Produces a sequence from an action based on the dynamic generation of N nested loops
-            whose iteration counts are defined by a sequence of loop counts.
-            </summary>
-            <param name="action">Action delegate for which to produce a nested loop sequence</param>
-            <param name="loopCounts">A sequence of loop repetition counts</param>
-            <returns>A sequence of Action representing the expansion of a set of nested loops</returns>
-        </member>
         <member name="M:MoreLinq.MoreEnumerable.OrderBy``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},MoreLinq.OrderByDirection)">
             <summary>
             Sorts the elements of a sequence in a particular direction (ascending, descending) according to a key
@@ -3667,32 +3743,6 @@
             <see langword="null"/>.
             </exception>
         </member>
-        <member name="T:MoreLinq.MoreEnumerable.PermutationEnumerator`1">
-            <summary>
-            The private implementation class that produces permutations of a sequence.
-            </summary>
-        </member>
-        <member name="M:MoreLinq.MoreEnumerable.PermutationEnumerator`1.NextPermutation">
-            <summary>
-            Transposes elements in the cached permutation array to produce the next permutation
-            </summary>
-        </member>
-        <member name="M:MoreLinq.MoreEnumerable.PermutationEnumerator`1.PermuteValueSet">
-            <summary>
-            Creates a new list containing the values from the original
-            set in their new permuted order.
-            </summary>
-            <remarks>
-            The reason we return a new permuted value set, rather than reuse
-            an existing collection, is that we have no control over what the
-            consumer will do with the results produced. They could very easily
-            generate and store a set of permutations and only then begin to
-            process them. If we reused the same collection, the caller would
-            be surprised to discover that all of the permutations looked the
-            same.
-            </remarks>
-            <returns>List of permuted source sequence values</returns>
-        </member>
         <member name="M:MoreLinq.MoreEnumerable.Permutations``1(System.Collections.Generic.IEnumerable{``0})">
             <summary>
             Generates a sequence of lists that represent the permutations of the original sequence.
@@ -4559,6 +4609,12 @@
             are disposed - either when Excluded or when the DisposableGroup is disposed.
             </summary>
         </member>
+        <member name="M:MoreLinq.MoreEnumerable.DisposableGroup`1.#ctor(System.Collections.Generic.IEnumerable{System.Collections.Generic.IEnumerator{`0}})">
+            <summary>
+            Class used to assist in ensuring that groups of disposable iterators
+            are disposed - either when Excluded or when the DisposableGroup is disposed.
+            </summary>
+        </member>
         <member name="M:MoreLinq.MoreEnumerable.Split``1(System.Collections.Generic.IEnumerable{``0},``0)">
             <summary>
             Splits the source sequence by a separator.
@@ -4815,25 +4871,15 @@
             Thrown if <paramref name="subsetSize"/> is less than zero.
             </exception>
         </member>
-        <member name="T:MoreLinq.MoreEnumerable.SubsetGenerator`1">
-            <summary>
-            This class is responsible for producing the lexographically ordered k-subsets
-            </summary>
-        </member>
-        <member name="T:MoreLinq.MoreEnumerable.SubsetGenerator`1.SubsetEnumerator">
+        <member name="M:MoreLinq.MoreEnumerable.Subsets``1(System.Collections.Generic.List{``0},System.Int32)">
             <summary>
-            SubsetEnumerator uses a snapshot of the original sequence, and an
-            iterative, reductive swap algorithm to produce all subsets of a
-            predetermined size less than or equal to the original set size.
+            Produces lexographically ordered k-subsets.
             </summary>
-        </member>
-        <member name="M:MoreLinq.MoreEnumerable.SubsetGenerator`1.GetEnumerator">
-            <summary>
-            Returns an enumerator that produces all of the k-sized
-            subsets of the initial value set. The enumerator returns
-            and <see cref="T:System.Collections.Generic.IList`1"/> for each subset.
-            </summary>
-            <returns>an <see cref="T:System.Collections.IEnumerator"/> that enumerates all k-sized subsets</returns>
+            <remarks>
+            It uses a snapshot of the original sequence, and an iterative,
+            reductive swap algorithm to produce all subsets of a predetermined
+            size less than or equal to the original set size.
+            </remarks>
         </member>
         <member name="M:MoreLinq.MoreEnumerable.TagFirstLast``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,System.Boolean,System.Boolean,``1})">
             <summary>
@@ -5777,23 +5823,6 @@
             Returned sub-sequences are buffered, but the overall operation is streamed.</para>
             </remarks>
         </member>
-        <member name="M:MoreLinq.MoreEnumerable.Windowed``1(System.Collections.Generic.IEnumerable{``0},System.Int32)">
-            <summary>
-            Processes a sequence into a series of sub-sequences representing a windowed subset of the original.
-            </summary>
-            <typeparam name="TSource">The type of the elements of the source sequence.</typeparam>
-            <param name="source">The sequence to evaluate a sliding window over.</param>
-            <param name="size">The size (number of elements) in each window.</param>
-            <returns>
-            A series of sequences representing each sliding window subsequence.</returns>
-            <remarks>
-            <para>
-            The number of sequences returned is: <c>Max(0, sequence.Count() - windowSize) +
-            1</c></para>
-            <para>
-            Returned sub-sequences are buffered, but the overall operation is streamed.</para>
-            </remarks>
-        </member>
         <member name="M:MoreLinq.MoreEnumerable.WindowLeft``1(System.Collections.Generic.IEnumerable{``0},System.Int32)">
              <summary>
              Creates a left-aligned sliding window of a given size over the
@@ -7537,7 +7566,7 @@
             </para>
             </remarks>
         </member>
-        <member name="M:MoreLinq.Extensions.BatchExtension.Batch``2(System.Collections.Generic.IEnumerable{``0},System.Int32,System.Func{System.Collections.Generic.IEnumerable{``0},``1})">
+        <member name="M:MoreLinq.Extensions.BatchExtension.Batch``2(System.Collections.Generic.IEnumerable{``0},System.Int32,System.Func{``0[],``1})">
             <summary>
             Batches the source sequence into sized buckets and applies a projection to each bucket.
             </summary>
@@ -8020,6 +8049,34 @@
             <returns>A sequence consisting of distinct elements from the source sequence,
             comparing them by the specified key projection.</returns>
         </member>
+        <member name="T:MoreLinq.Extensions.DuplicatesExtension">
+            <summary><c>Duplicates</c> extension.</summary>
+        </member>
+        <member name="M:MoreLinq.Extensions.DuplicatesExtension.Duplicates``1(System.Collections.Generic.IEnumerable{``0})">
+            <summary>
+            Returns all duplicate elements of the given source.
+            </summary>
+            <param name="source">The source sequence.</param>
+            <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
+            <returns>All elements that are duplicated.</returns>
+            <remarks>This operator uses deferred execution and streams its results.</remarks>
+        </member>
+        <member name="M:MoreLinq.Extensions.DuplicatesExtension.Duplicates``1(System.Collections.Generic.IEnumerable{``0},System.Collections.Generic.IEqualityComparer{``0})">
+            <summary>
+            Returns all duplicate elements of the given source, using the specified equality
+            comparer.
+            </summary>
+            <param name="source">The source sequence.</param>
+            <param name="comparer">
+            The equality comparer to use to determine whether one <typeparamref name="TSource"/>
+            equals another. If <see langword="null"/>, the default equality comparer for
+            <typeparamref name="TSource"/> is used.</param>
+            <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
+            <returns>All elements that are duplicated.</returns>
+            <remarks>This operator uses deferred execution and streams its results.</remarks>
+        </member>
         <member name="T:MoreLinq.Extensions.EndsWithExtension">
             <summary><c>EndsWith</c> extension.</summary>
         </member>
@@ -9787,6 +9844,44 @@
             <exception cref="T:System.ArgumentNullException"><paramref name="source"/>, <paramref name="selector"/>
             or <paramref name="comparer"/> is null</exception>
         </member>
+        <member name="T:MoreLinq.Extensions.MaximaExtension">
+            <summary><c>Maxima</c> extension.</summary>
+        </member>
+        <member name="M:MoreLinq.Extensions.MaximaExtension.Maxima``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})">
+            <summary>
+            Returns the maximal elements of the given sequence, based on
+            the given projection.
+            </summary>
+            <remarks>
+            This overload uses the default comparer  for the projected type.
+            This operator uses deferred execution. The results are evaluated
+            and cached on first use to returned sequence.
+            </remarks>
+            <typeparam name="TSource">Type of the source sequence</typeparam>
+            <typeparam name="TKey">Type of the projected element</typeparam>
+            <param name="source">Source sequence</param>
+            <param name="selector">Selector to use to pick the results to compare</param>
+            <returns>The sequence of maximal elements, according to the projection.</returns>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null</exception>
+        </member>
+        <member name="M:MoreLinq.Extensions.MaximaExtension.Maxima``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IComparer{``1})">
+            <summary>
+            Returns the maximal elements of the given sequence, based on
+            the given projection and the specified comparer for projected values.
+            </summary>
+            <remarks>
+            This operator uses deferred execution. The results are evaluated
+            and cached on first use to returned sequence.
+            </remarks>
+            <typeparam name="TSource">Type of the source sequence</typeparam>
+            <typeparam name="TKey">Type of the projected element</typeparam>
+            <param name="source">Source sequence</param>
+            <param name="selector">Selector to use to pick the results to compare</param>
+            <param name="comparer">Comparer to use to compare projected values</param>
+            <returns>The sequence of maximal elements, according to the projection.</returns>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/>, <paramref name="selector"/>
+            or <paramref name="comparer"/> is null</exception>
+        </member>
         <member name="T:MoreLinq.Extensions.MinByExtension">
             <summary><c>MinBy</c> extension.</summary>
         </member>
@@ -9825,6 +9920,44 @@
             <exception cref="T:System.ArgumentNullException"><paramref name="source"/>, <paramref name="selector"/>
             or <paramref name="comparer"/> is null</exception>
         </member>
+        <member name="T:MoreLinq.Extensions.MinimaExtension">
+            <summary><c>Minima</c> extension.</summary>
+        </member>
+        <member name="M:MoreLinq.Extensions.MinimaExtension.Minima``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1})">
+            <summary>
+            Returns the minimal elements of the given sequence, based on
+            the given projection.
+            </summary>
+            <remarks>
+            This overload uses the default comparer for the projected type.
+            This operator uses deferred execution. The results are evaluated
+            and cached on first use to returned sequence.
+            </remarks>
+            <typeparam name="TSource">Type of the source sequence</typeparam>
+            <typeparam name="TKey">Type of the projected element</typeparam>
+            <param name="source">Source sequence</param>
+            <param name="selector">Selector to use to pick the results to compare</param>
+            <returns>The sequence of minimal elements, according to the projection.</returns>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null</exception>
+        </member>
+        <member name="M:MoreLinq.Extensions.MinimaExtension.Minima``2(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Collections.Generic.IComparer{``1})">
+            <summary>
+            Returns the minimal elements of the given sequence, based on
+            the given projection and the specified comparer for projected values.
+            </summary>
+            <remarks>
+            This operator uses deferred execution. The results are evaluated
+            and cached on first use to returned sequence.
+            </remarks>
+            <typeparam name="TSource">Type of the source sequence</typeparam>
+            <typeparam name="TKey">Type of the projected element</typeparam>
+            <param name="source">Source sequence</param>
+            <param name="selector">Selector to use to pick the results to compare</param>
+            <param name="comparer">Comparer to use to compare projected values</param>
+            <returns>The sequence of minimal elements, according to the projection.</returns>
+            <exception cref="T:System.ArgumentNullException"><paramref name="source"/>, <paramref name="selector"/>
+            or <paramref name="comparer"/> is null</exception>
+        </member>
         <member name="T:MoreLinq.Extensions.MoveExtension">
             <summary><c>Move</c> extension.</summary>
         </member>
@@ -13090,126 +13223,6 @@
             Gets field or property member names.
             </summary>
         </member>
-        <member name="T:System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute">
-            <summary>
-            Specifies that the method or property will ensure that the listed field and property
-            members have not-null values when returning with the specified return value condition.
-            </summary>
-        </member>
-        <member name="M:System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute.#ctor(System.Boolean,System.String)">
-            <summary>
-            Initializes the attribute with the specified return value condition and a field or property member.
-            </summary>
-            <param name="returnValue">The return value condition. If the method returns this value, the associated parameter will not be null.</param>
-            <param name="member">The field or property member that is promised to be not-null.</param>
-        </member>
-        <member name="M:System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute.#ctor(System.Boolean,System.String[])">
-            <summary>
-            Initializes the attribute with the specified return value condition and list of field and property members.
-            </summary>
-            <param name="returnValue">The return value condition. If the method returns this value, the associated parameter will not be null.</param>
-            <param name="members">The list of field and property members that are promised to be not-null.</param>
-        </member>
-        <member name="P:System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute.ReturnValue">
-            <summary>
-            Gets the return value condition.
-            </summary>
-        </member>
-        <member name="P:System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute.Members">
-            <summary>
-            Gets field or property member names.
-            </summary>
-        </member>
-        <member name="T:System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute">
-            <summary>
-            Specifies that this constructor sets all required members for the current type,
-            and callers do not need to set any required members themselves.
-            </summary>
-        </member>
-        <member name="T:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute">
-            <summary>
-            Specifies the syntax used in a string.
-            </summary>
-        </member>
-        <member name="M:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.#ctor(System.String)">
-            <summary>
-            Initializes the <see cref="T:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute"/> with the identifier of the syntax used.
-            </summary>
-            <param name="syntax">The syntax identifier.</param>
-        </member>
-        <member name="M:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.#ctor(System.String,System.Object[])">
-            <summary>Initializes the <see cref="T:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
-            <param name="syntax">The syntax identifier.</param>
-            <param name="arguments">Optional arguments associated with the specific syntax employed.</param>
-        </member>
-        <member name="P:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Syntax">
-            <summary>Gets the identifier of the syntax used.</summary>
-        </member>
-        <member name="P:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Arguments">
-            <summary>Optional arguments associated with the specific syntax employed.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.CompositeFormat">
-            <summary>The syntax identifier for strings containing composite formats for string formatting.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateOnlyFormat">
-            <summary>The syntax identifier for strings containing date format specifiers.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.DateTimeFormat">
-            <summary>The syntax identifier for strings containing date and time format specifiers.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.EnumFormat">
-            <summary>The syntax identifier for strings containing <see cref="T:System.Enum"/> format specifiers.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.GuidFormat">
-            <summary>The syntax identifier for strings containing <see cref="T:System.Guid"/> format specifiers.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json">
-            <summary>The syntax identifier for strings containing JavaScript Object Notation (JSON).</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat">
-            <summary>The syntax identifier for strings containing numeric format specifiers.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Regex">
-            <summary>The syntax identifier for strings containing regular expressions.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.TimeOnlyFormat">
-            <summary>The syntax identifier for strings containing time format specifiers.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.TimeSpanFormat">
-            <summary>The syntax identifier for strings containing <see cref="T:System.TimeSpan"/> format specifiers.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Uri">
-            <summary>The syntax identifier for strings containing URIs.</summary>
-        </member>
-        <member name="F:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Xml">
-            <summary>The syntax identifier for strings containing XML.</summary>
-        </member>
-        <member name="T:System.Diagnostics.CodeAnalysis.UnscopedRefAttribute">
-            <summary>
-            Used to indicate a byref escapes and is not scoped.
-            </summary>
-            <remarks>
-            <para>
-            There are several cases where the C# compiler treats a <see langword="ref"/> as implicitly
-            <see langword="scoped"/> - where the compiler does not allow the <see langword="ref"/> to escape the method.
-            </para>
-            <para>
-            For example:
-            <list type="number">
-                <item><see langword="this"/> for <see langword="struct"/> instance methods.</item>
-                <item><see langword="ref"/> parameters that refer to <see langword="ref"/> <see langword="struct"/> types.</item>
-                <item><see langword="out"/> parameters.</item>
-            </list>
-            </para>
-            <para>
-            This attribute is used in those instances where the <see langword="ref"/> should be allowed to escape.
-            </para>
-            <para>
-            Applying this attribute, in any form, has impact on consumers of the applicable API. It is necessary for
-            API authors to understand the lifetime implications of applying this attribute and how it may impact their users.
-            </para>
-            </remarks>
-        </member>
         <member name="T:System.Runtime.CompilerServices.CallerArgumentExpressionAttribute">
             <summary>
             An attribute that allows parameters to receive the expression of other parameters.
@@ -13226,125 +13239,5 @@
             Gets the parameter name the expression is retrieved from.
             </summary>
         </member>
-        <member name="T:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute">
-            <summary>
-            Indicates that compiler support for a particular feature is required for the location where this attribute is applied.
-            </summary>
-        </member>
-        <member name="M:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.#ctor(System.String)">
-            <summary>
-            Creates a new instance of the <see cref="T:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute"/> type.
-            </summary>
-            <param name="featureName">The name of the feature to indicate.</param>
-        </member>
-        <member name="P:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.FeatureName">
-            <summary>
-            The name of the compiler feature.
-            </summary>
-        </member>
-        <member name="P:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.IsOptional">
-            <summary>
-            If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand <see cref="P:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.FeatureName"/>.
-            </summary>
-        </member>
-        <member name="F:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.RefStructs">
-            <summary>
-            The <see cref="P:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.FeatureName"/> used for the ref structs C# feature.
-            </summary>
-        </member>
-        <member name="F:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.RequiredMembers">
-            <summary>
-            The <see cref="P:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.FeatureName"/> used for the required members C# feature.
-            </summary>
-        </member>
-        <member name="T:System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute">
-            <summary>
-            Indicates which arguments to a method involving an interpolated string handler should be passed to that handler.
-            </summary>
-        </member>
-        <member name="M:System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute.#ctor(System.String)">
-            <summary>
-            Initializes a new instance of the <see cref="T:System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute"/> class.
-            </summary>
-            <param name="argument">The name of the argument that should be passed to the handler.</param>
-            <remarks><see langword="null"/> may be used as the name of the receiver in an instance method.</remarks>
-        </member>
-        <member name="M:System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute.#ctor(System.String[])">
-            <summary>
-            Initializes a new instance of the <see cref="T:System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute"/> class.
-            </summary>
-            <param name="arguments">The names of the arguments that should be passed to the handler.</param>
-            <remarks><see langword="null"/> may be used as the name of the receiver in an instance method.</remarks>
-        </member>
-        <member name="P:System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute.Arguments">
-            <summary>
-            Gets the names of the arguments that should be passed to the handler.
-            </summary>
-            <remarks><see langword="null"/> may be used as the name of the receiver in an instance method.</remarks>
-        </member>
-        <member name="T:System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute">
-            <summary>
-            Indicates the attributed type is to be used as an interpolated string handler.
-            </summary>
-        </member>
-        <member name="T:System.Runtime.CompilerServices.IsExternalInit">
-            <summary>
-            Reserved to be used by the compiler for tracking metadata.
-            This class should not be used by developers in source code.
-            </summary>
-        </member>
-        <member name="T:System.Runtime.CompilerServices.ModuleInitializerAttribute">
-             <summary>
-             Used to indicate to the compiler that a method should be called
-             in its containing module's initializer.
-             </summary>
-             <remarks>
-             When one or more valid methods
-             with this attribute are found in a compilation, the compiler will
-             emit a module initializer which calls each of the attributed methods.
-            
-             Certain requirements are imposed on any method targeted with this attribute:
-             - The method must be `static`.
-             - The method must be an ordinary member method, as opposed to a property accessor, constructor, local function, etc.
-             - The method must be parameterless.
-             - The method must return `void`.
-             - The method must not be generic or be contained in a generic type.
-             - The method's effective accessibility must be `internal` or `public`.
-            
-             The specification for module initializers in the .NET runtime can be found here:
-             https://github.com/dotnet/runtime/blob/main/docs/design/specs/Ecma-335-Augments.md#module-initializer
-             </remarks>
-        </member>
-        <member name="T:System.Runtime.CompilerServices.RequiredMemberAttribute">
-            <summary>
-            Specifies that a type has required members or that a member is required.
-            </summary>
-        </member>
-        <member name="T:System.Runtime.CompilerServices.SkipLocalsInitAttribute">
-            <summary>
-            Used to indicate to the compiler that the <c>.locals init</c> flag should not be set in method headers.
-            </summary>
-        </member>
-        <member name="M:System.Runtime.Versioning.RequiresPreviewFeaturesAttribute.#ctor">
-            <summary>
-            Initializes a new instance of the <see cref="T:System.Runtime.Versioning.RequiresPreviewFeaturesAttribute"/> class.
-            </summary>
-        </member>
-        <member name="M:System.Runtime.Versioning.RequiresPreviewFeaturesAttribute.#ctor(System.String)">
-            <summary>
-            Initializes a new instance of the <see cref="T:System.Runtime.Versioning.RequiresPreviewFeaturesAttribute"/> class with the specified message.
-            </summary>
-            <param name="message">An optional message associated with this attribute instance.</param>
-        </member>
-        <member name="P:System.Runtime.Versioning.RequiresPreviewFeaturesAttribute.Message">
-            <summary>
-            Returns the optional message associated with this attribute instance.
-            </summary>
-        </member>
-        <member name="P:System.Runtime.Versioning.RequiresPreviewFeaturesAttribute.Url">
-            <summary>
-            Returns the optional URL associated with this attribute instance.
-            </summary>
-        </member>
     </members>
 </doc>
diff --git a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.xml.meta b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.xml.meta
similarity index 75%
rename from Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.xml.meta
rename to Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.xml.meta
index aad815d9d1ffcdaaeb939fb9381627a4c9000062..1827d81306f6264f9b5eb68767a72624c32eee0e 100644
--- a/Assets/Packages/morelinq.3.4.2/lib/netstandard2.1/MoreLinq.xml.meta
+++ b/Assets/Packages/morelinq.4.1.0/lib/netstandard2.1/MoreLinq.xml.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 254d1481ea9fe27418aa0f92557d346e
+guid: b06c7e1601d31ec48a8bd90a5db97891
 TextScriptImporter:
   externalObjects: {}
   userData: 
diff --git a/Assets/Packages/morelinq.4.1.0/morelinq.4.1.0.nupkg b/Assets/Packages/morelinq.4.1.0/morelinq.4.1.0.nupkg
new file mode 100644
index 0000000000000000000000000000000000000000..a015136cbc83bb30319e607b7f2e893bb90ccf54
Binary files /dev/null and b/Assets/Packages/morelinq.4.1.0/morelinq.4.1.0.nupkg differ
diff --git a/Assets/Packages/morelinq.3.4.2/morelinq.3.4.2.nupkg.meta b/Assets/Packages/morelinq.4.1.0/morelinq.4.1.0.nupkg.meta
similarity index 74%
rename from Assets/Packages/morelinq.3.4.2/morelinq.3.4.2.nupkg.meta
rename to Assets/Packages/morelinq.4.1.0/morelinq.4.1.0.nupkg.meta
index 566f2097f8fac87b52e21cea834a43a418c33651..1bd0574066644608dca270fe9c26083afbf80356 100644
--- a/Assets/Packages/morelinq.3.4.2/morelinq.3.4.2.nupkg.meta
+++ b/Assets/Packages/morelinq.4.1.0/morelinq.4.1.0.nupkg.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 76bb6f26c5b24c347b9698ab410378cb
+guid: 9edf3f0028edbeb45bee3812e4baa7a0
 DefaultImporter:
   externalObjects: {}
   userData: 
diff --git a/Assets/Scripts/GlobalBehaviour.cs b/Assets/Scripts/GlobalBehaviour.cs
index 13be7e09be532b0ed926d8742c6a69b4a5b6147e..8d5b102e4387df03655163f799d0f1fd99f591fb 100644
--- a/Assets/Scripts/GlobalBehaviour.cs
+++ b/Assets/Scripts/GlobalBehaviour.cs
@@ -211,10 +211,8 @@ IEnumerator _GetContextfromServer()
                  || fact.GetDefines() == null) // Scala rule?
                     continue;
 
-                List<Fact> new_list = new();
-
                 System.DateTime parse_time = System.DateTime.Now;
-                yield return ParsingDictionary.parseFactDictionary[fact.getType()](new_list, fact);
+                List<Fact> new_list = Fact.MMTFactory(fact); // old but IEnumerator: yield return ParsingDictionary.parseFactDictionary[fact.getType()](new_list, fact);
                 justParseTime += System.DateTime.Now - parse_time;
 
                 if (new_list.Count == 0)
diff --git a/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs b/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
index 15828e908e772e13cdb11ba34c31bc49d191daaf..6799e7c73b0a376d0bf7f9d01319238f0f4025b3 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
@@ -567,15 +567,24 @@ static string _SendAdd(string path, string body)//, Action<string> uriCallback)
         }
     }
 
+    /// <summary> Used by <see cref="MakeFact(List{Fact}, object, SOMDoc, bool, SOMDoc)"/> to create unique pseudo-URIs / <see cref="Id"/>s. </summary>
     private static uint bypasscc = 0;
-    public static void MakeFact(List<Fact> ret, object payload, SOMDoc ServerDefinition, bool BypassServer)
+    /// <summary>
+    /// Tries to parse <paramref name="payload"/> into <see cref="Fact"/>(s)
+    /// </summary>
+    /// <param name="ret">to add results to</param>
+    /// <param name="payload">to be parsed</param>
+    /// <param name="ServerDefinition">what the Server could use. Only relevant for certain types of <paramref name="payload"/>.</param>
+    /// <param name="BypassServer">iff <c>true</c> avoids Server-side initialization</param>
+    /// <param name="BypassURI">iff <c><paramref name="BypassServer"/>==true</c> used as Server reference; iff set <c>null</c> a unique pseudo reference will be generated</param>
+    /// <exception cref="NotImplementedException">iff <paramref name="payload"/> is of unhandled type</exception>
+    public static void MakeFact(List<Fact> ret, object payload, SOMDoc ServerDefinition, bool BypassServer, SOMDoc BypassURI = null)
     {
         Type type = payload.GetType();
 
-        if (BypassServer) bypasscc++;
-        SOMDoc BypassURI = BypassServer
-            ? new OMLIT<uint>(bypasscc)
-            : null;
+        if (BypassServer
+         && BypassURI == null)
+            BypassURI = new OMLIT<uint>(++bypasscc);
 
         if (payload is Fact fact)
             ret.Add(fact);
@@ -606,14 +615,66 @@ public static void MakeFact(List<Fact> ret, object payload, SOMDoc ServerDefinit
                 ? DynamicListFact.MMTFactory((List<dynamic>)payload, ServerDefinition, SOMDoc.SOMDocType(type), BypassURI)
                 : DynamicListFact.MMTFactory((List<dynamic>)payload, ServerDefinition, SOMDoc.SOMDocType(type)));
         else
-        if (type.IsAnonymousType())
+        if (type.IsAnonymousType()) // TODO? generic Fact
             return;
         else
             throw new NotImplementedException($"For Type {type}.");
         return;
     }
+
+    /// <summary>
+    /// Compiles/Executes <paramref name="ingredient"/> and parses result into @Fact s
+    /// </summary>
+    /// <param name="ingredient">MMT package to be interpreted</param>
+    /// <returns>containing all @Fact s succesfully parsed, or empty when failed.</returns>
+    public static List<Fact> MMTFactory(MMTFact ingredient)
+    {
+        List<Fact> ret = new();
+
+        // First try static approach
+        ParsingDictionary.parseFactDictionary[ingredient.getType()]
+            .Invoke(ret, ingredient)
+            .FastForward();
+
+        if (ret.Count != 0)
+            return ret;
+
+        SOMDoc indirect_payload = ingredient.GetDefines();
+
+        //if (indirect_payload == null)
+        //    return new();
+
+        object CompiledValue;
+        try
+        {
+            Func<object[], object[]> builder =
+                indirect_payload.PartialInvokeCastingLambdaExpression(out _, out Type[] signature);
+
+            if (signature.Length != 1)
+                return new();
+
+            CompiledValue = builder(new object[0])[0];
+        }
+        catch (Exception ex)
+        {
+            Debug.Log($"{nameof(ingredient)} could not be built/executed:");
+            Debug.LogException(ex);
+            return new();
+        }
+
+        //try // simplify
+        //{
+        //    indirect_payload = SOMDoc.SOMDocObject(CompiledValue);
+        //}
+        //catch (NotSupportedException) { }
+
+        MakeFact(ret, CompiledValue, indirect_payload, true, ingredient.@ref);
+
+        return ret;
+    }
 }
 
+
 public interface IUnpackable
 {
     public abstract IEnumerator UnpackMe(List<Fact> ret, bool BypassServer);
diff --git a/Assets/Scripts/InteractionEngine/FactHandling/Facts/FunctionFact.cs b/Assets/Scripts/InteractionEngine/FactHandling/Facts/FunctionFact.cs
index 226f3b8e631ad68461b7e5af6bfcadd63d34d90e..e6865dc5c0439974b66501c617b69ca3e23bea89 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/Facts/FunctionFact.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/Facts/FunctionFact.cs
@@ -7,11 +7,18 @@
 using System.Linq.Expressions;
 using UnityEngine;
 
+/// <summary>
+/// Binds a domain mapper (<see cref="FunctionFact"/>) opperating on time t in seconds to a <see cref="FunctionFact"/>.
+/// Uses <see cref="FunctionFact"/> Function_args to map from a linear scale to the domain of <see cref="FunctionFact"/> Function to execute it.
+/// </summary>
 public class FunctionCallFact : FactWrappedCRTP<FunctionCallFact>
 {
     protected override object GetCompiledValue()
         => Tuple.Create(Domain, Function_args.CompiledValue, Function.CompiledValue);
 
+    /// <summary>
+    /// <see cref="Fact.Id"/> of <see cref="Function"/>
+    /// </summary>
     public string func_id
     {
         get => Function?.Id ?? _func_id;
@@ -24,6 +31,9 @@ private set
     }
     private string _func_id;
 
+    /// <summary>
+    /// <see cref="Fact.Id"/> of <see cref="Function_args"/>
+    /// </summary>
     public string arg_func_id
     {
         get => Function_args?.Id ?? _arg_func_id;
@@ -36,12 +46,21 @@ private set
     }
     private string _arg_func_id;
 
+    /// <summary>
+    /// Linear domain on R this Fact is valid on;
+    /// Intervall is defined as [t_0, t_n]
+    /// </summary>
     public (float t_0, float t_n) Domain;
 
-
+    /// <summary>
+    /// The function to be called with <see cref="Call(float)"/>
+    /// </summary>
     [JsonIgnore]
     public FunctionFact Function;
 
+    /// <summary>
+    /// Mapps from linear <see cref="Domain"/> to arguments from <see cref="Function"/>. (may be multidimensional)
+    /// </summary>
     [JsonIgnore]
     public FunctionFact Function_args;
 
@@ -51,6 +70,12 @@ public FunctionCallFact(string func_id, string arg_func_id, (float t_0, float t_
         this.func_id = func_id;
         this.arg_func_id = arg_func_id;
         this.Domain = Domain;
+
+        if (Function_args.Signature[0] != typeof(float)
+         || Function_args.Signature[1..] != Function.Signature[..^0])
+            throw new ArgumentException(
+                $"Signatures must match: Func<float, D> {nameof(arg_func_id)} and Func<D,R> {nameof(func_id)}!\n" +
+                $"But where {Function_args.Signature} and {Function.Signature}.");
     }
 
     public FunctionCallFact(FunctionFact Function, FunctionFact Function_args, (float t_0, float t_n) Domain) : base()
@@ -58,8 +83,19 @@ public FunctionCallFact(FunctionFact Function, FunctionFact Function_args, (floa
         this.Function = Function;
         this.Function_args = Function_args;
         this.Domain = Domain;
+
+        if (Function_args.Signature[0] != typeof(float)
+         || Function_args.Signature[1..] != Function.Signature[..^0])
+            throw new ArgumentException(
+                $"Signatures must match: Func<float, D> {nameof(arg_func_id)} and Func<D,R> {nameof(func_id)}!\n" +
+                $"But where {Function_args.Signature} and {Function.Signature}.");
     }
 
+    /// <summary>
+    /// Mapps <paramref name="t"/> with <see cref="Function_args"/> to domain of <see cref="Function"/> and calls it.
+    /// </summary>
+    /// <param name="t">to be used as argument for <see cref="Function_args"/>. Semantical use is time in seconds.</param>
+    /// <returns><see cref="Function"/>(<see cref="Function_args"/>(<paramref name="t"/>)) iff <paramref name="t"/> is within <see cref="Domain"/></returns>
     public object[] Call(float t)
     {
         if (t < Domain.t_0 || t > Domain.t_n)
@@ -148,16 +184,28 @@ protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new)
         => new FunctionCallFact(old_to_new[this.func_id], old_to_new[this.arg_func_id], this.Domain);
 }
 
+/// <summary>
+/// A function <c>Func<object[], object[]></c> as Fact.
+/// </summary>
 public class FunctionFact : FactWrappedCRTP<FunctionFact>
 {
     protected override object GetCompiledValue()
         => Expression.Lambda(CompileBase).Compile().DynamicInvoke();
 
+    /// <summary>
+    /// MMT AST representing the function
+    /// </summary>
     public SOMDoc Function_SOMDoc;
 
+    /// <summary>
+    /// The signature of this function.
+    /// </summary>
     [JsonIgnore]
     public Type[] Signature;
 
+    /// <summary>
+    /// Encapsulated function.
+    /// </summary>
     [JsonIgnore]
     public Func<object[], object[]> Function;
 
diff --git a/Assets/Scripts/InteractionEngine/FactHandling/Facts/MMTTypes.cs b/Assets/Scripts/InteractionEngine/FactHandling/Facts/MMTTypes.cs
index c3a6053e59a6e8114af826feed7160078df9540e..c53d2f7e7ad8b91b00e8c110aeabeb00ea39314c 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/Facts/MMTTypes.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/Facts/MMTTypes.cs
@@ -269,7 +269,7 @@ public override SOMDoc Defines()
 
         ret.AddRange(orig);
         foreach (Fact Fact in orig)
-            if (Fact is DynamicListFact pack)
+            if (Fact is IUnpackable pack)
                 yield return pack.UnpackMe(ret, true); //TODO: set to false, once Server can index
     }
 
@@ -440,14 +440,15 @@ public static List<Fact> MMTFactory(object payload, SOMDoc indirect_payload, SOM
         Type[] Signature = payload.GetType().GetGenericArguments();
         List<Fact> ret = new();
 
-        // Isomorphismen
+        // ###### Isomorphismen ######
+        // RxRxR <=> Vector3
         if (payload is Tuple<float, float, float> point)
         {
             Vector3 vec = new(point.Item1, point.Item2, point.Item3);
             ret.Add(new PointFact(vec, vec));
             return ret;
         }
-        //if(payload is Tuple<Tuple<float, float>, Func<float, TIn>, Func<TIn?[..],TOut>> func)
+        //if(payload is Tuple<Tuple<float, float>, Func<float, TIn>, Func<TIn?[..],TOut>> func) <=> FunctionCallFact
         if (Signature.Length == 3
          && Signature[0].Equals(typeof(Tuple<float, float>))
          && FuncExtensions.IsFuncType(Signature[1], out int callerCount)
diff --git a/Assets/Scripts/InventoryStuff/ScrollDetails.cs b/Assets/Scripts/InventoryStuff/ScrollDetails.cs
index 81755de95fd4be271120ce8db8fecd927bbc5806..c9656d80f0bc6588265571ce39ada059021c7e59 100644
--- a/Assets/Scripts/InventoryStuff/ScrollDetails.cs
+++ b/Assets/Scripts/InventoryStuff/ScrollDetails.cs
@@ -282,15 +282,13 @@ IEnumerator _MagicButton()
         IEnumerator __GeneratePushoutFacts(List<MMTFact> pushoutFacts)
         {
             List<Fact> new_facts = new();
-            Dictionary<string, string> oldt_to_new = new();
+            Dictionary<string, string> old_to_new = new();
             System.DateTime parseTime = System.DateTime.UtcNow;
 
             bool samestep = false;
             for (int i = 0; i < pushoutFacts.Count; i++)
             {
-                List<Fact> new_list = new();
-                yield return ParsingDictionary.parseFactDictionary[pushoutFacts[i].getType()]
-                                        (new_list, pushoutFacts[i].MapURIs(oldt_to_new));
+                List<Fact> new_list = Fact.MMTFactory(pushoutFacts[i].MapURIs(old_to_new));
 
                 if (new_list.Count == 0)
                 {
@@ -310,7 +308,7 @@ IEnumerator __GeneratePushoutFacts(List<MMTFact> pushoutFacts)
                     else
                     {
                         // AnimateExistingFactEvent.Invoke(_new, FactWrapper.FactMaterials.Hint); // Automaticly done in FactRecorder
-                        oldt_to_new.Add(new_fact.Id, added.Id);
+                        old_to_new.Add(new_fact.Id, added.Id);
                     }
 
                     yield return null;
@@ -465,10 +463,7 @@ void _processRenderedScroll(Scroll rendered, List<string> hintUris)
                 //If ScrollFact is assigned -> No Hint
                 if (!RenderedScrollFact.IsSet)
                 {
-                    List<Fact> HintFactList = new();
-                    ParsingDictionary.parseFactDictionary[rendered.requiredFacts[i].getType()]
-                        .Invoke(HintFactList, rendered.requiredFacts[i])
-                        .FastForward();
+                    List<Fact> HintFactList = Fact.MMTFactory(rendered.requiredFacts[i]);
 
                     foreach (Fact HintFact in HintFactList)
                     {
diff --git a/Assets/Scripts/MMTServer/CommunicationProtocoll/MMTConstants.cs b/Assets/Scripts/MMTServer/CommunicationProtocoll/MMTConstants.cs
index de04d96ab0e1a956dd52eb505df2d7345a68b6f3..3661ee345ad31788eda1e35467cf9cba8f221a50 100644
--- a/Assets/Scripts/MMTServer/CommunicationProtocoll/MMTConstants.cs
+++ b/Assets/Scripts/MMTServer/CommunicationProtocoll/MMTConstants.cs
@@ -4,6 +4,9 @@
 
 namespace REST_JSON_API
 {
+    /// <summary>
+    /// Collection of MMT URIs and mappings to C\# types (if applicable)
+    /// </summary>
     public static class MMTConstants
     {
         public static readonly string Point = "http://mathhub.info/MitM/core/geometry?3DGeometry?point";
diff --git a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
index 7cd2a72440402f1baae31d757bec4a8d0faf329d..192673b53e736d0b32456e39780c26bf1dc0d397 100644
--- a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
+++ b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
@@ -11,6 +11,16 @@ namespace REST_JSON_API
 {
     abstract public partial class SOMDoc
     {
+        /// <summary>
+        /// translates this SOMDoc AST into a C\# AST, changes/casts the signature to Func<object[], object[]>, and compiles it.
+        /// Function arguments can be inserted at any position as to partially invoke the function. 
+        /// </summary>
+        /// <param name="compile_base">Cached Expression Tree</param>
+        /// <param name="signature">the original signature</param>
+        /// <param name="callArgs">arguments to be inserted. The position carries over. Set <c>null</c> to skipp all.</param>
+        /// <param name="useArgs">set a position to <c>false</c> iff the corresponding entree in <paramref name="callArgs"/> shall be ignored / the original parameter be used. 
+        /// Missing values will be interpreted as <c>true</c>. Set <c>null</c> to use all.</param>
+        /// <returns>the compiled function, with a new signature and partially inserted arguments.</returns>
         public Func<object[], object[]> PartialInvokeCastingLambdaExpression(out Expression compile_base, out Type[] signature, object[] callArgs = null, bool[] useArgs = null)
         {
             List<Type> signature_list;
@@ -73,11 +83,21 @@ public Func<object[], object[]> PartialInvokeCastingLambdaExpression(out Express
             return final_expression.Compile() as Func<object[], object[]>;
         }
 
+        /// <summary>
+        /// Libary and configuartions to translate a SOMDoc AST into an Expression-Tree
+        /// </summary>
         protected static class SOMDocToLambdaExpression
         {
             // TODO: Populate Dictionaries
             #region ExpressionDictionaries
 
+            /// <summary>
+            /// Builds a <see cref="LambdaExpression"/> within <see cref="MakeLambdaExpression"/>
+            /// </summary>
+            /// <param name="lambda_applicant">arguments to be used; usually comes from <see cref="OMA.arguments"/></param>
+            /// <param name="lambda_arguments">currently unused. space for a second set of parameters</param>
+            /// <param name="bound_params">to be bound as parameters in <see cref="Expression.Lambda(Expression, ParameterExpression[])"/></param>
+            /// <returns>encoding the current Abstract-Syntax-Tree</returns>
             public delegate LambdaExpression CustomFunction(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params);
             private static readonly Dictionary<string, CustomFunction> MMTtoLambdaMaker = new()
         {
@@ -274,6 +294,16 @@ protected static class SOMDocToLambdaExpression
             #endregion ExpressionDictionaries
 
             //TODO: case ((f->x)->y) instead of  assumed (f->(x->y))
+            /// <summary>
+            /// Maps <paramref name="URI"/> to an operation and uses the other parameters as operants to build an Expression-Tree.
+            /// </summary>
+            /// <param name="URI"><see cref="MMTConstants"/> to be mapped to an operation</param>
+            /// <param name="lambda_applicant">arguments to be used; usually comes from <see cref="OMA.arguments"/></param>
+            /// <param name="lambda_arguments">currently unused. space for a second set of parameters</param>
+            /// <param name="bound_params">to be bound as parameters in <see cref="Expression.Lambda(Expression, ParameterExpression[])"/></param>
+            /// <returns>encoding the current Abstract-Syntax-Tree</returns>
+            /// <exception cref="ArgumentException">iff <paramref name="lambda_applicant"/> could not be used in <paramref name="URI"/></exception>
+            /// <exception cref="NotImplementedException">iff <paramref name="URI"/> could not be mapped</exception>
             public static LambdaExpression MakeLambdaExpression(string URI, LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
             {
                 void ThrowArgumentException(ExpressionType expression_cast, int expected)
@@ -354,6 +384,14 @@ void ThrowArgumentException(ExpressionType expression_cast, int expected)
             public static LambdaExpression PartialInvoke(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
                 => _PartialInvoke(lambda_applicant[0].Body, lambda_arguments, bound_params);
 
+            /// <summary>
+            /// May invoke a function with an incomplete parameter set.
+            /// </summary>
+            /// <param name="func">function to be invoked</param>
+            /// <param name="lambda_arguments">arguments to invoke with</param>
+            /// <param name="bound_params">to be bound as parameters in <see cref="Expression.Lambda(Expression, ParameterExpression[])"/></param>
+            /// <returns>new function with up to <paramref name="lambda_arguments"/>.Count less arguments</returns>
+            /// <exception cref="ArgumentException">iff <paramref name="func"/> is not a function</exception>
             public static LambdaExpression _PartialInvoke(Expression func, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
             {
                 if (!FuncExtensions.IsFuncType(func.Type, out int signature_count))
@@ -389,6 +427,11 @@ public static LambdaExpression _PartialInvoke(Expression func, LambdaExpression[
                 );
             }
 
+            /// <summary>
+            /// Chains multiple <see cref="CustomFunction"/>s into a single one. The resalt of one will be used as lambda_applicant for the next one.
+            /// </summary>
+            /// <param name="makes">to be chained</param>
+            /// <returns>wich combines all <paramref name="makes"/>. When executed it will return the return value of the last <see cref="CustomFunction"/> in <paramref name="makes"/>.</returns>
             public static CustomFunction ChainMakes(CustomFunction[] makes)
                 => (LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params) =>
                 {
@@ -398,8 +441,8 @@ public static CustomFunction ChainMakes(CustomFunction[] makes)
                     return lambda_applicant[0];
                 };
 
-            public static LambdaExpression ExpresionFuncToLambda(LambdaExpression func, string name, LambdaExpression[] args_lamda, ParameterExpression[] bound_params, uint nTargs_fallback)
-                => Expression.Lambda(Expression.Invoke(func, args_lamda.Select(l => l.Body)), name, bound_params);
+            public static LambdaExpression ExpresionFuncToLambda(LambdaExpression func, string name_me, LambdaExpression[] args_lamda, ParameterExpression[] bound_params)
+                => Expression.Lambda(Expression.Invoke(func, args_lamda.Select(l => l.Body)), name_me, bound_params);
 
             public static LambdaExpression ParseFuncUUToExpression<U>(Func<U, U> func)
                 => (Expression<Func<U, U>>)((U x) => func(x));
@@ -418,7 +461,7 @@ public static LambdaExpression MakeSin(LambdaExpression[] lambda_applicant, Lamb
                         : lambda_applicant[0].ReturnType == typeof(double) ? ParseFuncUUToExpression<double>(Math.Sin)
                         : throw new NotImplementedException("Sinus for " + lambda_applicant[0].ReturnType),
 
-                        "Sin", lambda_arguments.Length > 0 ? lambda_arguments : lambda_applicant, bound_params, 1
+                        "Sin", lambda_arguments.Length > 0 ? lambda_arguments : lambda_applicant, bound_params
                     );
 
             public static LambdaExpression MakeCos(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
@@ -427,7 +470,7 @@ public static LambdaExpression MakeCos(LambdaExpression[] lambda_applicant, Lamb
                         : lambda_applicant[0].ReturnType == typeof(double) ? ParseFuncUUToExpression<double>(Math.Cos)
                         : throw new NotImplementedException("Cosinus for " + lambda_applicant[0].ReturnType),
 
-                        "Cos", lambda_arguments.Length > 0 ? lambda_arguments : lambda_applicant, bound_params, 1
+                        "Cos", lambda_arguments.Length > 0 ? lambda_arguments : lambda_applicant, bound_params
                     );
 
             public static LambdaExpression MakeRoot(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
@@ -436,7 +479,7 @@ public static LambdaExpression MakeRoot(LambdaExpression[] lambda_applicant, Lam
                         : lambda_applicant[0].ReturnType == typeof(double) ? ParseFuncUUToExpression<double>(Math.Sqrt)
                         : throw new NotImplementedException("Sqrt for " + lambda_applicant[0].ReturnType),
 
-                        "Sqrt", lambda_arguments.Length > 0 ? lambda_arguments : lambda_applicant, bound_params, 1
+                        "Sqrt", lambda_arguments.Length > 0 ? lambda_arguments : lambda_applicant, bound_params
                     );
 
             public static LambdaExpression ProjLVecTupel(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
@@ -498,7 +541,7 @@ public static LambdaExpression MakeTupel(LambdaExpression[] lambda_applicant, La
 
                     return ExpresionFuncToLambda(
                                 (Expression<Func<float, float, float, Vector3>>)((x, y, z) => new Vector3(x, y, z)),
-                                "UnityEngineVector3", lambda_applicant, bound_params, 3
+                                "UnityEngineVector3", lambda_applicant, bound_params
                     );
 
                 Type[] genericTypes = new Type[lambda_applicant.Length];
@@ -614,16 +657,29 @@ public static LambdaExpression FeedForwardUntil(LambdaExpression[] lambda_applic
                        CallAnyFunction(false, "ToList", typeof(Enumerable))}
                 )(lambda_applicant[1..], lambda_arguments, bound_params);  // lambda_applicant[0] is ReturnType
 
+            /// <summary>
+            /// Find (any) generic methods and call it, given the arguments.
+            /// This method tries to match the arguments to a method called <paramref name="method_name"/> in <paramref name="type"/>.
+            /// If unsuccessfull, an Exception will be thrown.
+            /// If the results are undecisive, the first one will be used and a log-entree created.
+            /// </summary>
+            /// <remarks>Although non-generic methods can be used this way, it is advised against this usage for performance reasons!</remarks>
+            /// <param name="self">if <c>true</c> the method will be called on the first argument itselfe; otherwise on <paramref name="type"/></param>
+            /// <param name="method_name">the name of the function to be called</param>
+            /// <param name="type">the <c>Type</c> the function is a member of, or <c>null</c> iff the type of the first argument is to be used</param>
+            /// <param name="lambda_manual">can be used to manually insert any number of constant arguments at any position (0-indexed)</param>
+            /// <returns>that dynamically builds a method call</returns>
+            /// <exception cref="Exception">Iff no matching method could be found</exception>
             public static CustomFunction CallAnyFunction(bool self, string method_name, Type type = null, (uint, LambdaExpression)[] lambda_manual = null)
                 => (LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params) =>
                 {
-                    type ??= lambda_applicant[0].ReturnType;
-
                     LambdaExpression[] lambda_args_new = lambda_applicant
-                        .Skip(self ? 1 : 0)
                         .AppendRangeAt(lambda_manual)
+                        .Skip(self ? 1 : 0)
                         .ToArray();
 
+                    type ??= lambda_args_new[0].ReturnType;
+
                     Expression[] call_args = lambda_args_new
                         .Select(l => l.Body)
                         .ToArray();
@@ -883,6 +939,10 @@ public static CustomFunction GetPropertyOrField(string property_name)
                         bound_params
                     );
 
+            /// <summary>
+            /// Casts lambda_arguments into <c>int</c>s and uses them to (multidimensional) index lambda_applicant.<paramref name="property_name"/>
+            /// </summary>
+            /// <param name="property_name">name of property to index</param>
             public static CustomFunction IntCastedIndexer(string property_name)
                 => (LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
                 => Expression.Lambda(
diff --git a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocs.cs b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocs.cs
index 18201bded4c5e5f0f683549f4c9029d0339fe4ab..6c6eb188270afe078f89cf55c102da32fc91c894 100644
--- a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocs.cs
+++ b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocs.cs
@@ -11,6 +11,9 @@
 
 namespace REST_JSON_API
 {
+    /// <summary>
+    /// Used to check for approximate equality on number values, e.g. within <see cref="SOMDoc.Equivalent(SOMDoc)"/>
+    /// </summary>
     public class ApproximationComparer : EqualityComparer<object>
     {
         public static readonly ApproximationComparer Instance = new();
@@ -114,7 +117,15 @@ public static SOMDoc SOMDocType(Type type)
             throw new NotImplementedException($"For Type {type}");
         }
 
-        public static SOMDoc SOMDocObject(object obj)
+        /// <summary>
+        /// Attempts to build a @SOMDoc from any object.
+        /// </summary>
+        /// <param name="obj">object to parse</param>
+        /// <param name="force">uses case for Anonymous classes as failsafe</param>
+        /// <returns></returns>
+        /// <exception cref="NotSupportedException">iff <c>typeof(<paramref name="obj"/>) == Func</c></exception>
+        /// <exception cref="NotImplementedException">iff unknown type and <c><paramref name="force"/> == false</c></exception>
+        public static SOMDoc SOMDocObject(object obj, bool force = false)
         {
             Type type = obj.GetType();
 
@@ -145,19 +156,6 @@ public static SOMDoc SOMDocObject(object obj)
                 return MakeShallowList(payload.ToArray());
             }
 
-            if (type.IsAnonymousType())
-                return new OMA(
-                    new OMS(MMTConstants.MakeType),
-                    type.GetFields()
-                        .Select(mem =>
-                            new OML_Member(
-                                mem.Name,
-                                null, //SOMDocType(mem.FieldType), 
-                                SOMDocObject(mem.GetValue(obj))
-                            )
-                        ).ToArray()
-                );
-
             if (MMTConstants.TYPE_TO_OMS.TryGetValue(type, out string uri))
                 switch (obj)
                 {
@@ -173,6 +171,21 @@ public static SOMDoc SOMDocObject(object obj)
 
             if (FuncExtensions.IsFuncType(type, out _))
                 throw new NotSupportedException("Cannot reconstruct SOMDoc from Func<>!");
+
+            if (force
+             || type.IsAnonymousType())
+                return new OMA(
+                    new OMS(MMTConstants.MakeType),
+                    type.GetFields()
+                        .Select(mem =>
+                            new OML_Member(
+                                mem.Name,
+                                null, //SOMDocType(mem.FieldType), 
+                                SOMDocObject(mem.GetValue(obj))
+                            )
+                        ).ToArray()
+                );
+
             Error:
             throw new NotImplementedException($"For Type {type}");
         }
diff --git a/Assets/Scripts/MMTServer/CommunicationProtocoll/TupleFactory.cs b/Assets/Scripts/MMTServer/CommunicationProtocoll/TupleFactory.cs
index 4f925e03144e81fe63c27d3609d072e07c5bebb1..6c8b8a32fbfeefc3dfd8f079866301f38534c611 100644
--- a/Assets/Scripts/MMTServer/CommunicationProtocoll/TupleFactory.cs
+++ b/Assets/Scripts/MMTServer/CommunicationProtocoll/TupleFactory.cs
@@ -18,7 +18,7 @@ public interface ITupleFactory
     }
 
     /// <summary>
-    /// Creates types that are much like anonymous types.
+    /// Creates types that are much like anonymous types, via string-Type-pairs.
     /// </summary>
     public static class TupleFactory
     {
diff --git a/Assets/Scripts/StageStatic.cs b/Assets/Scripts/StageStatic.cs
index de00bccdfb9727a9dedf71624b0066e988781221..761e8afe1dbf6a72e3494c79aa560e47a0c7e97d 100644
--- a/Assets/Scripts/StageStatic.cs
+++ b/Assets/Scripts/StageStatic.cs
@@ -346,7 +346,8 @@ public static void ShallowLoadStages(bool force = false)
                 }
                 catch (Exception ex)
                 {
-                    Debug.LogError("Could not load StageFile: " + file.FullName);
+                    Debug.LogError("Could not load StageFile: " + file.FullName + "\n" +
+                        "See Log below!");
                     Debug.LogException(ex);
                 }
             }
diff --git a/Assets/Stages.zip b/Assets/Stages.zip
new file mode 100644
index 0000000000000000000000000000000000000000..86094d0739fdc77bb325e57cee1fbb2f4d81b4b2
--- /dev/null
+++ b/Assets/Stages.zip
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:58ed76b255063e314cf77dff6bf3ab21fb0f688ecbb5a3686d6e2a17e1b97b68
+size 74359
diff --git a/Assets/Stages.zip.meta b/Assets/Stages.zip.meta
new file mode 100644
index 0000000000000000000000000000000000000000..6ea37ae4c0f3cb65b6b7863ed7ae251c1cb39bb1
--- /dev/null
+++ b/Assets/Stages.zip.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 060328157f55f1c4f82d84591a6bf777
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/packages.config b/Assets/packages.config
index 3180a16983082221c4f2ae5be53feb24fb9f574b..e7e8bc417497503202e3bbfeadad79843d9e16c4 100644
--- a/Assets/packages.config
+++ b/Assets/packages.config
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="morelinq" version="3.4.2" manuallyInstalled="true" />
+  <package id="morelinq" version="4.1.0" manuallyInstalled="true" />
 </packages>
\ No newline at end of file
diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset
index f34e4bc384be08e0b31a2ec0e04ada25c9bc3db8..e9cebd7f0cbcab3eb57171e489208a216347f823 100644
--- a/ProjectSettings/QualitySettings.asset
+++ b/ProjectSettings/QualitySettings.asset
@@ -224,5 +224,6 @@ QualitySettings:
     excludedTargetPlatforms: []
   m_PerPlatformDefaultQuality:
     Android: 0
+    Server: 0
     Standalone: 5
     Windows Store Apps: 0