* Good start
* Misc
* Make ApiAuthenticationMiddleware use new json
* Remove first newtonsoft dependency
* Pull latest ASFB json enhancements
* Start reimplementing newtonsoft!
* One thing at a time
* Keep doing all kind of breaking changes which need to be tested later
* Add back ShouldSerialize() support
* Misc
* Eradicate remaining parts of newtonsoft
* WIP
* Workaround STJ stupidity in regards to derived types
STJ can't serialize derived type properties by default, so we'll use another approach in our serializable file function
* Make CI happy
* Bunch of further fixes
* Fix AddFreeLicense() after rewrite
* Add full support for JsonDisallowNullAttribute
* Optimize our json utilities even further
* Misc
* Add support for fields in disallow null
* Misc optimization
* Fix deserialization of GlobalCache in STD
* Fix non-public [JsonExtensionData]
* Fix IM missing method exception, correct db storage helpers
* Fix saving into generic databases
Thanks STJ
* Make Save() function abstract to force inheritors to implement it properly
* Correct ShouldSerializeAdditionalProperties to be a method
* Misc cleanup
* Code review
* Allow JSON comments in configs, among other
* Allow trailing commas in configs
Users very often add them accidentally, no reason to throw on them
* Fix confirmation ID
Probably needs further fixes, will need to check later
* Correct confirmations deserialization
* Use JsonNumberHandling
* Misc
* Misc
* [JsonDisallowNull] corrections
* Forbid [JsonDisallowNull] on non-nullable structs
* Not really but okay
* Add and use ToJson() helpers
* Misc
* Misc
This addresses two things:
- It allows for better load-balancing, as STD refresh can be postponed for a short while after bot logs in - it has more important matters to handle right away, and STD is optional/supportive plugin.
- It helps @xPaw sleep better at night working around fools with their ASFs crashing thirty times per second due to third-party plugins.
* Initial .NET 8
* Make it compile in release mode ignoring warnings for now
* First round of improvements
* Second round of improvements
* Third round of improvements
* Use new throws
* Fix .NET Framework, YAY, thanks madness!
Madness devs are awesome
* Misc
* Misc
* AF_NETLINK might be required for some http calls
No clue why
* Fix service files
Doesn't do what it should
* Update CardsFarmer.cs
* New improvements
* Address feedback
* Misc
* Misc
* Misc refactor
* Misc
- Make use of new UnixFileMode, always one native method we need to maintain less
- Add madness support for it, because new feature of course
- Add optional netstandard target and required compatibility for it, so I can test netf-oriented changes easier
* Start work on extracting remote communication
* ok
* Dockerfile fixes
* More fixes
* Prepare /Api/Announce and /Api/HeartBeat
* Decrease publish race conditions
* OK
* Misc
* Misc
* Misc
* Move Steam group part back to ASF core
* Finally implement match actively v2 core
* Update RemoteCommunication.cs
* Use single round exclusively, report inventories more often
* Use randomization when asking others for assetIDs
* Add support for license and crowdin
* Kill dead code
* Fix return type of inventories
* Fix responses for good
* Unify old backend with new
* Report whole inventory, always
Helps with optimization on the backend side in terms of inventory fetching
* Update RemoteCommunication.cs
* Determine index of each asset and tell server about it
* Update AnnouncementRequest.cs
* Fix ASF screwing up with the order
* Fix warnings
* Misc rename
* Final logging touches
For unknown to me reason, this breaks for many people with Steam reporting invalid data and ASF caching it until new change number, which may never arrive. Add our own 7-days validity on top, to ensure that user never needs to delete ASF.db manually.
It's getting more and more complicated... We have places where we accept errors but still want relevant JSON body (most of the Steam error-places), and now we also have a place where we expected error to not carry one. Moreover, we still want to account for invalid JSON body on 2xx and retry on them.
So let's make the code even more complicated than it already is by adding yet another endpoint that does exactly the same what the other endpoint does BUT allows us us to optionally accept null/invalid body on success/errors/both, lol. I hate myself.
Maybe we can obsolete the first endpoint eventually and stick with just the second?
Okay, I wish we had uncovered it earlier as part of V5.2 but it has bitten us in the back just now, so I'm addressing it as part of monthly cycle instead.
Previously used void methods did not allow async operations in plugins in a "nice way". If plugin didn't require synchronization with the ASF and just minded its own business, it wasn't half bad as it could use async void signature. However, if plugin by any chance had to do something BEFORE ASF continued with the rest of the logic, it had to explicitly leave non-async void signature and call its async-capable stuff in synchronous manner (usually with Wait() or .Result), which is vastly suboptimal.
This was visible even in our STD plugin, which previously had (and still has) GlobalCache initialization in OnASFInit(). If that cache initialization took a bit longer time, STD would hit InvalidOperationException() in OnLicenseList() callback as global cache didn't load yet while we were already long past OnASFInit().
Therefore, I've decided to make a breaking change for a very good reason - all previous methods were converted to tasks, which allows from plugin to do one of three things:
- If plugin is async and requires synchronization (like STD), it can declare itself as async await, and do its awaits as-needed, and ASF will wait for those.
- If plugin is truly synchronous (and not just a synchronous signature with awful Wait() or .Result, see above), it can simply return Task.CompletedTask and has exactly the same logic.
- Finally, if plugin calls some async stuff but doesn't need ASF synchronization, it can "offload" itself from it by calling e.g. ASF's Utilities.InBackground() with whole logic, while returning Task.CompletedTask from the main method. This will allow it to effectively do what async void previously did, by just hooking into the process without intention of slowing it down.
All in all I'm confident this approach, while a bit counter-intuitive at first, will result in better compatibility between ASF and the plugins, as if I wanted to fix my STD issue right now without that breaking change, I'd have to actually call .Result on my async global cache loader function, which is utterly stupid if we can fix ASF to do the right thing instead.
This "approach" can be commonly found in some other libs with similar to ASF's event-hook behaviour, e.g. Discord.Net.
You'll sadly need to do some method signature changes in all of your plugins, as the core OnLoaded() was also changed. See the ones I did in SteamTokenDumperPlugin.cs if you need a practical example, and see ExamplePlugin.cs if you need further explanation.
This is important as we don't want to miss a depot, by moving it below we ensure that all depot tasks succeeded before we mark appIDs as "finished with"