- Joined
- Jun 13, 2016
- Messages
- 586
As reported by @TriggerHappy, the "Allow Local Files" requirement has been lifted from the and now anyone can (apparently) read files, with or without this setting.
This is a huge deal breaker, and as the maintainer of Wurst's (rather high-level) Persistence API, this has made me reconsider some of the choices I made in the library. In particular, I'd like to investigate, and propose, some alternative methods of reading data from Preload files.
Note: All of this is heavily inspired by @TriggerHappy's past work on FileIO, so huge credit goes to him for coming up with all of this.
Note2: If you didn't know, Wurst has a very high-level and relatively easy-to-use Persistence API which handles all the grunt work behind the scenes, starting from reading the data from disc, to synchronizing it between players, and deserializing it into a nice comfy class for you to use, while handling various edge and error cases. Oh, and did you also know that it can handle arbitrarily large files as well?
With that said, let me revise some of the methods that have already been discovered by others, and some of the more obscure ones I came up with:
1. SetPlayerName / GetPlayerName
The classic. The preloader file contains consecutive calls to `SetPlayerName(Player(x), "payload")`, which are then read by the map's script, and the names reset. This has a very severe limitation of only allowing MAX_PLAYERS * 1024 (2048 if you really wanna push it) bytes per file. While definitely more than most people would ever need, there are certain scenarios in maps where you might need to save more than that. This is the method that Wurst currently uses, and it splits the total payload into multiple files in the case that more than 1 is needed.
2. SetUnitName / GetUnitName
This is a very weird one I came up with not so long ago... The idea is that the preloader file contains consecutive calls to `SetUnitName(CreateUnit(...), "payload")`. The gotcha that prevents desyncs here is that all other players must create the required amount of units at the same time as the loader runs the file. I didn't go anywhere with this, but in my tests, it worked, without desyncing.
3. BlzSetAbilityTooltip
This is one pioneered by @TriggerHappy in his latest FileIO library, however he only uses 1 ability with 1 level, which limits the payload to around 2048 chars, since (AFAIK) that's the length limit of strings in WC3 before they go bad. 1-2KB is more than most people would ever need, but we are here to push limits! So...
4. BlzSetAbilityTooltip on multiple ability levels
This one requires a custom dummy ability with a certain number of levels. I came up with this shortly after looking at TriggerHappy's new lib, and has the nice benefit of being VERY expandable, having minimal side effects, and able to have files of up to 128MB in payload. The file consists of consecutive calls to `BlzSetAbilityTooltip(DUMMY_ID, "payload", i)`, and in my tests, one JASS thread can handle around 100-200 thousand of these calls, making this method arguably the best one, although I'm still yet to test it thoroughly.
And that's about it, as far as my own knowledge on this goes. This is, of course, entirely orthogonal to the problem of actually synchcronizing the data, which I covered in my tutorial here.
There's 3 reasons why I'm posting about this here:
1. To spread the knowledge about File IO in WC3.
2. To see if anyone else has dabbled in this and knows any other alternative methods that may be superior to the ones I outlined here.
3. To see what you guys think about it.
Thanks for reading!
This is a huge deal breaker, and as the maintainer of Wurst's (rather high-level) Persistence API, this has made me reconsider some of the choices I made in the library. In particular, I'd like to investigate, and propose, some alternative methods of reading data from Preload files.
Note: All of this is heavily inspired by @TriggerHappy's past work on FileIO, so huge credit goes to him for coming up with all of this.
Note2: If you didn't know, Wurst has a very high-level and relatively easy-to-use Persistence API which handles all the grunt work behind the scenes, starting from reading the data from disc, to synchronizing it between players, and deserializing it into a nice comfy class for you to use, while handling various edge and error cases. Oh, and did you also know that it can handle arbitrarily large files as well?
With that said, let me revise some of the methods that have already been discovered by others, and some of the more obscure ones I came up with:
1. SetPlayerName / GetPlayerName
The classic. The preloader file contains consecutive calls to `SetPlayerName(Player(x), "payload")`, which are then read by the map's script, and the names reset. This has a very severe limitation of only allowing MAX_PLAYERS * 1024 (2048 if you really wanna push it) bytes per file. While definitely more than most people would ever need, there are certain scenarios in maps where you might need to save more than that. This is the method that Wurst currently uses, and it splits the total payload into multiple files in the case that more than 1 is needed.
2. SetUnitName / GetUnitName
This is a very weird one I came up with not so long ago... The idea is that the preloader file contains consecutive calls to `SetUnitName(CreateUnit(...), "payload")`. The gotcha that prevents desyncs here is that all other players must create the required amount of units at the same time as the loader runs the file. I didn't go anywhere with this, but in my tests, it worked, without desyncing.
3. BlzSetAbilityTooltip
This is one pioneered by @TriggerHappy in his latest FileIO library, however he only uses 1 ability with 1 level, which limits the payload to around 2048 chars, since (AFAIK) that's the length limit of strings in WC3 before they go bad. 1-2KB is more than most people would ever need, but we are here to push limits! So...
4. BlzSetAbilityTooltip on multiple ability levels
This one requires a custom dummy ability with a certain number of levels. I came up with this shortly after looking at TriggerHappy's new lib, and has the nice benefit of being VERY expandable, having minimal side effects, and able to have files of up to 128MB in payload. The file consists of consecutive calls to `BlzSetAbilityTooltip(DUMMY_ID, "payload", i)`, and in my tests, one JASS thread can handle around 100-200 thousand of these calls, making this method arguably the best one, although I'm still yet to test it thoroughly.
And that's about it, as far as my own knowledge on this goes. This is, of course, entirely orthogonal to the problem of actually synchcronizing the data, which I covered in my tutorial here.
There's 3 reasons why I'm posting about this here:
1. To spread the knowledge about File IO in WC3.
2. To see if anyone else has dabbled in this and knows any other alternative methods that may be superior to the ones I outlined here.
3. To see what you guys think about it.
Thanks for reading!