-
Notifications
You must be signed in to change notification settings - Fork 4
Extendible SaveFile implementation #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
* Provide Stream Saver Interfaces * Add IIOStreamProvider file implementation * Add IAsyncIOStreamProvider http implementation Currently missing some constructor parameters for HttpClient initialization. * Add IStreamSerializer and IAsyncStreamSerializer implementation for Json * Rewrite SaveFile to use interfaces. Additionally, expose a static class SaveFile with the method CreateGZipJsonFile. This returns a SaveFile using File Input/Output, Json Serialization and GZip compression. This is likely how the SaveFile will mostly be used. * parameter should be interface instead of class * Add documentation * Exhaustive overloads for SaveFile.CreateGZipJsonFile Now you can call this method with a JsonSerializerContext or JsonTypeInfo parameter. * Functionally tested HttpIO The HttpIO is ready for the field! It now exposes the necessary headers and optional Request uris, some easy-to-use constructors and properly disposes its objects. * Remove null-forgiving operators from deserialize extension methods * Remove ConfigureAwait(false) from all async calls as it introduces save issues * Fix ContentLength = 0 on Write * Add namespaces for Compression, IO, and Serialization * Fix IAsyncIOStreamProvider We need to compress the memory stream and leave it open BEFORE writing it with our IAsyncIOStreamProvider. Note that this isn't a completely correct name, since it doesn't provide a write / input stream, it accepts one. Will need to change this once a good name has been devised. * Add HttpIO documentation * Fix naming in static SaveFile Gzip should be GZip
The dependency on Godot for running tests is unnecessary, as all of the functionality in this library is based on native C#. All of the tests have been rewritten to use xunit for quicker testing. Moq has been used for testing the SaveFile class and its many possible configurations based on the given interfaces.
IIOStreamProvider -> IStreamIO IAsyncIOStreamProvider -> IAsyncStreamIO ICompressionStreamProvider -> IStreamCompressor These namechanges make it easier to form a connection between IStreamIO, IStreamCompresor, and IStreamSerializer as part of a bigger whole.
This makes the documentation more generally applicable: SaveFile could be easier implemented into standard C# applications without a need or understanding of the rest of the Chickensoft Ecosystem.
In reality, the order of saving goes io, compression, serialization. But from a user-perspective, the order of priority goes io, serialization, compression. In order to make the documentation come across a little more natural, the order of priority is applied in the documentation.
|
Important Version number still needs to be updated. I would like help to know all the places the version number occurs, to make sure I update them all. |
|
Important I have not written any tests for any implementations of io, serialization or compression. However, I have tested all my implementations against the Chickensoft GameDemo and can assure they work. Let me know if it is desirable I still write tests for my implementations or not. |
Good question! Versioning is handled by our release workflows. The version number in project files should always be left at |
|
The ci test fails because of the syntax |
In multiple places, "compressor" was written as "compresser".
So, MY understanding of the situation (which may be incorrect): We could look into fixing it, but for now I'll simply change my code a little. I suspect that, over time, ubuntu-latest will support this and everything will be fixed by itself, and since it's only 1 simple issue it's not a big deal for now. Note I also took a glance at fixing this in the pipeline through setup-dotnet, but that's only for specifying the sdk. I do not fully understand how it arrives at C# 14, and I decided this was not worth a bottleneck. |
The ci pipeline does not support C# 14 out of the box. We could look into fixing this, but it might be fixed by itself in the future. For now, these small syntax changes are much easier to rely upon.
|
Yeah, .NET updates are slow to trickle through. I am watching this with keen interest but will hold off on reviewing until I can see what the PR for the game demo that uses this looks like. That will allow me to review more from a dog-fooding perspective and do it justice. |
|
Silly me, now it builds, but it still expects Godot to run tests. I'll update the workflow file later, but today I start with work again. So I expect my response to issues may slow down a little. |
That should be the last one.
This is more true to the nature of these methods.
|
I've removed godot-testing from the workflow file and changed it to dotnet testing. I also wanted to remove - name: 🧮 Compute Next Version
uses: chickensoft-games/next-godot-csproj-version@v1
id: next-version
with:
project-version: ${{ steps.current-version.outputs.tag }}
godot-version: global.json
bump: ${{ inputs.bump }}I am unsure how this functions, so let me know how I should change this code so that any references to godot may be omitted. |
Didn't think about changing the workflow before: mistakes creep up.
|
Also... I don't know if changing the workflow from the PR actually works...? So better to just run it and see if it's using my updated workflow or not 😅 Edit: Jay! 🙌 |
|
@jolexxa I'm working on getting 100% code coverage now. Where and how should I export the results? Right now I'm not using any external tools like coverlet, I'm just using Test > Analyze Code Coverage for All Tests in visual studio, which allows me to export to I've never used code coverage before so I'm still figuring out how it all works. If I need coverlet, I would appreciate some guidelines of how to use it and generate a PS: |
|
You can borrow a coverage.sh script from one of the other chickensoft projects which has an xunit test project, like LogicBlocks. |
|
Finished generating and carefully reviewing all the test cases and I'm very satisfied! I will try to look into coverlet next once I have the time. If that results in a 100% coverage, then this PR should be ready to go! |
|
I still have some small improvements to make, like adding AOT support (should be easy), and here and there I've been working on XML support. The XmlSerializer is very poorly made however, so I'm still navigating a lot of mazes and gotchas for that. Either way, I'll add them after the release of this PR, cause it's already big enough. |
… ...) It just looks a little nicer.
Look this commit is not very structured but basically it gets the coverage up to 100% and that's pretty rad no?
Not so much fix as take the suggestion
SaveFilehas been reimplemented from the ground up to provide the user with an easy and optimized way to save and load their game data, whilst remaining completely extendible!SaveFileis now build up of 3 parts:IStreamIO / IAsyncStreamIO,IStreamCompressor, andIStreamSerializer / IAsyncStreamSerializer. These handle saving-concerns separately and, through their use of streams, optimally. ASaveFilerequires a combination of these types in one of its constructors, after which its behaviour remains consistent.The above is a very common use case, and a static method is provided to make it easier to read:
The beauty of an extendible system like this is that it allows creators to experiment with different ways of saving easily. They will be able to experiment with serialization methods or cloud providers easily, without incurring too much development overhead. Additionally, any extensions writen may be contributed back to SaveFileBuilder / the community.
Tests have been rewritten to use Xunit and do away with GodotTest. Since SaveFileBuilder can be its own standalone package, testing through GodotTest is an unnecessary step that complicates the testing process.
Mocking has been used to test
SaveFileand its many possible configurations. Note that, should an interface implementation be tested, this should be done separately from anySaveFileTests.SaveFileTestsonly test the flow / interaction between its interfaces, not their implementations.The ReadMe / documentation has been rewritten with a bigger focus on standalone applications. This makes the documentation more generally applicable: SaveFile could be easier implemented into standard C# applications without a need or understanding of the rest of the Chickensoft Ecosystem. However, a separate section in the documentation specifically details how to use it in Godot / with Chickensoft, so that this information is still readily available.