I’m delighted to see the zip developed. Since I started to invest my time in CGE one thing is constantly on my table - virtual file system. it’s not a surprise that games are using it, however I was wandering how to make it work with your engine.
The TCastleZip introduces nice methods and properties. Registering own protocol is very useful indeed. And by introducing it you have already made my life easier.
As zip are a special case of a virtual file system, is it possible to make some basic functionalities from TCastleZip being part of a parent class from which zip class would inherit - a class that could open a door for a systematic access to other packed systems? At the moment TCastleZip is a class on its own, I could use it as an ancestor to a more general class or simply copy/paste parts of it as a template, no problem here, but I think having one class to rule them all would be easier in the future of CGE as you may want to add some other file formats.
In particular (first thing that came to my mind), binary glTF stored in *.glb is a “packed” file system and it could be possible to read it once - like zip - instead of having multiple copies of the same resources. Also x3dv with embedded resources (created by default in Castle Model Viewer when exporting glb->x3dv). I don’t personally intend to use *.glb in production but I think it’s a good example of a virtual file system.
Oh, I think we already have something you ask for, though it’s not a class
Namely, you can use global routine RegisterUrlProtocol to register your own URL protocol, with custom callbacks for reading and writing. This way all the engine reading/writing routines will recognize the new URL protocol.
In effect, a virtual filesystem is defined by the callbacks (and you can naturally implement them all by a single class, which is what TCastleZip does). There are 3 callbacks provided to RegisterUrlProtocol now, all optional:
asynchronous reader
synchronous reader (just return readable TStream for the resource)
writer (just return writeable TStream for the resource)
I want to keep extending this API, add additional callbacks to
enumerate directory contents (so that you can search arbitrary filesystems with FindFiles ). This is also on TODO, though not immediate.
Possibly, at some point RegisterUrlProtocol will take a record/class with these callbacks, to avoid having a procedure with zillion optional parameters
The callbacks are something I hoped for. Now I see we can easily implement our own data or game-save systems to integrate with CGE, without the need of overwriting the engine sources. That’s perfect.
Ps. I’ve seen the large game of yours, nice idea. Secretly thinking if you’ll polish and publish the Castle game too.
Two of the things mentioned above have happened, namely:
RegisterUrlProtocol exposes now a class that allows to configure URL behavior. (So we can extend the functionality offered by custom URLs, aka virtual file systems, without adding more and more parameters to RegisterUrlProtocol.)
One can register an ExistsEvent handler for custom URLs, to configure how UriExists behaves for them.
Many built-in URLs, including ZIP handling, and including internal castle-data enumeration by castle-data:/auto_generated/CastleDataInformation.xml, define the ExistsEvent.
So on the web, queries like UriExists('castle-data:/my_texture.png') are useful now.