Open snake-biscuits opened 2 months ago
really, this has 2 parts
The listed BspClasses have external files we parse
But .link
can be in base.Bsp
.from_archive
will likely be per class
started looking at this now
archives.base.Archive
has a .from_archive
@classmethod
__init__
planning to add .mount
& .unmount
methods to base.Archive
to link "external files"
these can provide some kind of file handles to keep the data present
.unmount
will be to reduce memory usage
unmounting a file that was added automatically will probably be really painful
implementing .mount
for BspClass
es will likely be more complex
since RespawnBsp
has ExternalLumpManager
to try and cache files
we might need to keep the archive
open to dynamically mount .bsp_lump
bsp.mount(archive, filename)
makes sense
but I'd also like to mount from files, streams & bytes
might be a while until I land on an implementation
.link
can be inbase.Bsp
.from_archive
will likely be per class
.from_archive
has been implemented in base.Bsp
If we have a .related_filenames()
function we can use that to automatically check for & mount files
This should probably be optional & off by default to reduce memory usage
Some RespawnBsp
(Apex Season 10 onwards) will need external .bsp_lump
to be useful though
We already have .mount_lump
methods, so I'm thinking .mount_file
should work as a name
These should do the job:
def mount_file(self, filename: str, archive=None):
if archive is None:
self.external_files[filename] = open(filename, "rb")
else:
self.external_files[filename] = io.BytesIO(archive.read(filename))
def unmount_file(self, filename: str):
self.external_files.pop(filename)
Afaik all external files would be binary
If not we can always add plaintext=False
to .mount_file
Could be useful to have some kind of .stream
method in ArchiveClass
es to reduce memory usage
Likely a lot slower and would have to be tailored to each individual ArchiveClass
Maybe keep it in mind for if we come back to optimise this system
particle manifests would be a plaintext extra file for ValveBsp
though as discussed in #156, we're going to focus on mounting lump data
(extra lighting information & external lumps)
.related_filenames
isn't going to work
.lmp
filenames include version numbers[^vdc]
we should probably use fnmatch
patterns instead
this could be used with archive.namelist()
or os.listdir()
though we'll need some path splitting solution for working out mod-relative paths
path_tuple
in archives.base
could be useful
probably handy for autodetect.naps
too
maybe we add a new filesystem
module?
[^vdc]: Valve Developer Community: Pathing levels with lump files
we could extract files we want to mount inside archives if we use temporary files we'd be reducing ram usage load time would only increase by the write time we have to get every byte of the file from the archive either way
until we work out a system for streaming assets in archives anyway
implementations of streaming would be unique to each ArchiveClass
io.BytesIO(archive.read(filename))
might work as a default
extras
seems like a good name to reference "external files"
helps keep variable names short
(mount_extras
vs. mount_external_files
)
totally didn't get the idea from the Guilty Gear soundtrack playing in another tab
ArchiveClasses & BspClasses now automatically mount extras
each specific class which uses external files now needs to access them via self.extras
they also need class-specific .extra_patterns
implementations
We need archives we can use to actually test file mounting
I currently don't have any .bsp
s inside archives w/ supplementary files
Might have to make an id_software.Pak
w/ .lit
& .vis
files
Can't use respawn.Vpk
because we don't have compression yet
Tho I guess for ArchiveClass
es I could test a sega.Gdi
inside a pkware.Zip
Could add a raw bytedata arg to .mount_file
for testing
def mount_file(self, filename: str, archive=None, raw_data: bytes = None):
if raw_data is not None:
self.extras[filename] = io.BytesIO(raw_data)
else:
... # load from file or archive as before
I'm sure this could also be useful outside of testing
From #191: We should also look at some standard method for linking related files
sega.Gdi
,respawn.RPak
,respawn.Vpk
&valve.Vpk
could all use this too since their.read()
methods can't function without grabbing data from other filesPlaces where this'd be useful
ArchiveClasses
respawn.RPak
respawn.Vpk
sega.Gdi
valve.Vpk
BspClasses
ValveBsp
RespawnBsp
(respawn.ExternalLumpManager
)Related
156