-
Notifications
You must be signed in to change notification settings - Fork 18
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
New filesystem #76
base: master
Are you sure you want to change the base?
New filesystem #76
Conversation
…consistent with original filesystem
@Chomenor Can you run Another point on style; all engine code uses C++ true/false instead of qtrue/qfalse. |
@Chomenor great job on the file system, I've been giving it a test drive for a little bit. I'm going to follow full review shortly. |
@@ -608,7 +608,16 @@ bool CL_CloseAVI( void ) | |||
// Write index | |||
|
|||
// Open the temp index file | |||
#ifdef NEW_FILESYSTEM | |||
indexSize = 0; | |||
{ char path[FS_MAX_PATH]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regrettably, It's not documented anywhere and some files (such as this one) have not yet been updated, but please try to follow a general style of
indexSize = 0;
{
char path[FS_MAX_PATH];
if(fs_generate_path_writedir(FS_GetCurrentGameDir(), idxFileName, 0, FS_ALLOW_SLASH, path, sizeof(path)))
afd.idxF = fs_direct_read_handle_open(0, path, (unsigned int *)&indexSize);
}
Notably
- Curly braces on a separate line (exceptions for small one line conditionals and functions)
- 4 space indent (no tabs)
FS_FCloseFile( args[1] ); | ||
return 0; | ||
case CG_FS_SEEK: | ||
#ifdef NEW_FILESYSTEM | ||
if(fs_handle_get_owner(args[1]) != FS_HANDLEOWNER_CGAME) return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to fix the indenting throughout here
clc.cURLDisconnected = false; | ||
if (!clc.activeCURLNotGameRelated) CL_Reconnect_f(); | ||
return; | ||
} | ||
} | ||
|
||
#ifndef NEW_FILESYSTEM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure we need to ifndef the one line comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use a script to verify the ifdefs (no new filesystem changes outside them) so that's why I always use them. I expect you will probably remove the ifdefs altogether at some point if you end up using the filesystem.
@@ -1991,6 +2023,82 @@ A download completed or failed | |||
*/ | |||
void CL_NextDownload(void) | |||
{ | |||
#ifdef NEW_FILESYSTEM | |||
// Attempts to initiate a download, or calls CL_DownloadsComplete if no more downloads are available | |||
*clc.downloadTempName = *clc.downloadName = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/0/'\0'/
@@ -4727,7 +4860,13 @@ static void CL_InitRef(void) | |||
ri.FS_WriteFile = FS_WriteFile; | |||
ri.FS_FreeFileList = FS_FreeFileList; | |||
ri.FS_ListFiles = FS_ListFiles; | |||
#ifdef NEW_FILESYSTEM | |||
// This function is not implemented in the new filesystem, and it does | |||
// not appear to actually be used in the renderer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to cleanup the renderer api and remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I just delete the field it would cause a crash with mixed renderer versions, so I'm not sure I want to do that right away
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no use case for client/renderer version mismatch. I expect this scenario to not work in general.
return qtrue; | ||
} | ||
|
||
int fs_get_source_dir_id(const fsc_file_t *file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider making these member functions of fsc_file_t
src/filesystem/fs_misc.cpp
Outdated
static qboolean inactive_mod_file_disabled(const fsc_file_t *file, int level) | ||
{ | ||
// Check if a file is disabled by inactive mod settings | ||
if (level < 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invert checks like this; if ( level >= 2 ) return false;
keep the indentation of the rest of your code close to one level deep as possible.
// Hash Table | ||
/* ******************************************************************************** */ | ||
|
||
void fs_hashtable_initialize(fs_hashtable_t *hashtable, int bucket_count) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More of this I would want to be considered for replacement with a std::map
vs a custom hash table.
{ | ||
// Valid for an uninitialized hash table | ||
hashtable->bucket_count = bucket_count; | ||
hashtable->buckets = (fs_hashtable_entry_t **)Z_Malloc(sizeof(fs_hashtable_entry_t *) * bucket_count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Z_Malloc and friends are garbage and I'd rather you use malloc
. If nothing else, because my debug builds all use address sanitizer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To elaborate on this; Z_Malloc
prevents memory security devices (such as heap cookies), but also prevent tools like address sanitizer and valgrind.
} query_result_t; | ||
|
||
/* ******************************************************************************** */ | ||
// Resource construction - Converts file or shader to lookup resource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you elaborate, perhaps in some documentation what a "lookup resource" is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a temporary structure that can represent either an image or shader, and contains all the values needed to sort the resource against other resources.
Regarding the code formatting and C++ integrations, it would be helpful to me to delay some of these changes until some other steps are accomplished. The main steps I would like to see are as follows:
Delaying more extraneous features and code changes until these major steps are addressed would help me with sharing certain work between this project and my ioq3 project, and also helps limit how much time I invest in this port before a decision has been made on whether you will actually end up using it. |
Hello, Merry Christmas, Happy New Year, and in general Happy Holidays @Chomenor ! I hope all is well. I apologize for this reply being so so so late (been busy with a lot of irl stuff, but now I have more time to work a lot more on this project again). I finally got around to fixing up that precedence order on this repo's wiki ( https://github.com/GrangerHub/tremulous/wiki/File-System-Load-Precedences ), and made some other misc edits to that wiki. If you are still interested and have some time, I would greatly appreciate it if you update your work for trem based on the requested layout, and include your latest updates to your ioq3 implementation (I just reviewed the latest version of your file system readme in your ioq3 repo, and I really like all of the features you have listed there). After your file system is completed and it is tested well with tremulous clients and tremulous servers. I would really like to include your file system in an upcoming client release. If you can't work on this, I understand, and I would have time to try to finish your file system for trem starting about 2 months from now (before then I'm mainly focusing on getting the new game play, game mode system, and bot system done for 1.3 in the next 2 months). But if you would work on finishing your file system for our Tremulous project, that would be very awesome! If you have any questions, feel free to ask! |
Some relatively new features/enhancements we've made that has some relation to the file system: |
Sure, I'm willing to help finish the filesystem. I think it was fairly close to being completed before, at least to the extent that Tremulous could run and connect to servers. I probably don't have time to develop every filesystem-related feature by myself, but if you can handle testing and most work that needs to be done outside the filesystem code, I should be able to handle most of whatever is needed within the filesystem. Did you ever make progress on splitting the vm (game module) compilation off from the engine repository? If I remember right that was one of the last things we had been discussing. |
Awesome! Thanks @Chomenor , this is much appreciated :) ! I'll help where I can. I think I'm familiar enough with the engine code to figure out how to implement required stuff outside of the file system (although I can certainly become more familiar). I did compile a version with your file system awhile ago, and it did have the vast majority of the features working very well then. I personally only develop on Linux at the moment, but with whatever is left, most likely it should work on the supported Windows, and Mac platforms, and we can find players to test on those platforms. @wtfbbqhax (aka blowFish) I think that did remove the vm compilation from this engine repo, I'm not 100% sure though. This engine repo still compiles the dynamic libraries for its included older game logic though. The game logic repo does still build the cgame and ui qvm, although we disabled the game qvm support there, since it wasn't important for the purposes of that repo, and was a pain to keep functional with the game logic development. This engine repo and the game logic repo are not compatible with each other yet, the game logic repo has its own fork of the engine that has been modified for the server development, but after I finish the new game play, game mode system, and bot system, I'll be working on making the two repos compatible, and then strip the engine parts from the game logic repo, and strip the game logic parts from this engine repo, then probably make use of a submodule of the game logic repo in this engine repo. With that said, the file system can probably be completed on this repo before/alongside any of those other planned updates without issue, and we may not even have to worry about porting this file system to the game logic repo, since ultimately the game logic in the game logic repo will be coming to this engine repo one way or another. |
Based on a quick test the makefile in this engine repo does appear to generate qvm files. What I envision is creating some "stock" qvm pk3s that are packaged with the engine, which would be used for the purposes of the main menu ui, connecting to unpure unmodded servers, and running a local game. I would suggest treating these pk3s more as assets than code, so they would potentially go in an asset repo and get copied into engine distributions from there, rather than built directly. That way the pk3 hashes remain stable for both the filesystem and potentially pure servers to reference. So the repo layout would be as follows:
|
@Chomenor , sounds like a generally good approach. There are a few things that I would like to add/suggest/ask.
So for connecting to a 1.3 server: the precedence order of searching and loading the hardcoded "default content" would be as follows:
For connecting to a gpp server: the precedence order of searching and loading the hardcoded "default content" would be as follows:
For connecting to a 1.1 server: the precedence order of searching and loading the hardcoded "default content" would be as follows:
For connecting to a 1.4 server in the future: the precedence order of searching and loading the hardcoded "default content" would be as follows:
For connecting to a 1.5 server in the future: the precedence order of searching and loading the hardcoded "default content" would be as follows:
and so on...
|
Also, as a placeholder, I cold make a second temporary repo that would be a copy of this engine repo, but focused on just packaging the assests, and download the built game logic from the other mentioned temporary repo. so that the repo arrangement of this current engine repo, and two temporary placeholder repos (that would be copies of this repo), would behave similar to what you have described, @Chomenor . |
Is it really necessary to use native code for the stock game modules? Using qvms only would simplify things a lot. I would assume qvms are generally better anyway (less chance of cross-platform issues, more commonality with mods used on actual servers). You can always load dlls manually if needed for debugging purposes. Hashes would generally change between builds, hence the reason to store the game module pk3s as assets and only update them when necessary. It doesn't matter what method or repo you use to create the stock module pk3s, as long as the actual saving of the pk3s is done manually. The important thing is the pk3 hashes are known in advance (before the engine is built) and don't change unless updated intentionally. |
QVMs have some advantages, in particular, as you've mentioned, a convenient way to distribute cross platform, and a relatively safe way to execute unknown code. However, we've found that they have a lot of disadvantages, they can break easily as we develop, especially when it comes to memory. I recently had to move all of the string literals used in the weapon/upgrade/buildable/class/team attributes structs to config files (although I was planning on doing that for the new game mode system anyways), because the QVM couldn't handle the stack memory used by those strings and would just crash. They are also significantly slower than dynamic libraries. There are other ways that they break that we had to work around as well. Additionally, the actual level of security from loading unknown QVMs, is questionable. For the game logic in the 1.3 game logic repo, we just completely dropped the server side support for the game.qvm. The only reason we are keeping the QVM support for now is for backwards compatibility of old clients on the new servers (in regards to them loading the cgame.qvm and the ui.qvm), and for the new 1.3 clients to be able to play on old 1.1 and gpp servers. With the new config file based game mode system I'm working on, the vast majority of modding should be doable via the game mode config files without having to change the game logic, so mods would just have to distribute those config files in the vast majority of cases. Ultimately for what comes after 1.3, we are planning on dropping the use of QVMs, and have modding done entirely through the configs, and at some point we'll expand the Lua support, and even more modding could be done through Lua scripts. With that said, I suppose that verification of the dynamic libraries as default content would not be necessary, since downloading of dynamic libraries from game servers is not allowed. perhaps as long as the dynamic libraries are in the correct version base folder for the given currently specified engine version, we could have them override the default content QVMs (that is while you are at the main menu, or download menu, or starting a local game that isn't set to use a non-base fs_game, or when connecting to a semi-pure or unpure server if following the overall precedence order would reuslt in them being loaded). In other words, in the case that the 1.3 engine version is being used, in a situation where the dynamic libraries are allowed, and the active mod is the default base_1.3, first the dynamic libraries would be searched for and loaded in the base_1.3 folder, if they aren't found, then the hardcoded default content pk3 files with the default 1.3 QVMs would be searched for and loaded. In the case that the gpp engine version is being used, and the active mod is the default gpp, first the dynamic libraries would be searched for and loaded in the gpp folder, if they aren't found, then the hardcoded default content pk3 files with the default gpp QVMs would be searched for and loaded. Connecting to a 1.1 server that uses as its fs_game base, would work in the same way, but with respect to the base folder. So it is just a matter of giving the dynamic libraries (if present in the proper version based folder) precedence over the corresponding QVM(s) located in the hardcoded default content pk3(s), without having to do any hash check on the dynamic libraries. There is another potential issue I would like to bring up with the currently proposed design, that I'm hoping we can address. This design with hardcoded default content is perfect for standard client use, it ensures there is no funny business with attempts to override the main menu and download menu, and it comes with other advantages. But what about in the case where we are working on developing the default 1.3 game logic on a local setup, and we are testing using the 1.3 client and loading a local server through the client, and in addition connecting one or more other clients on the same local network for testing. Can that be done in a relatively straightforward automated way, with similar (or better) ease to how that can be done now with the old file system currently in use? |
Is the requirement to use native dlls specific to the game module? Could we use qvms for the cgame and ui? |
Well, somewhat, for now. But I think we can handle the consideration of all dynamic libraries for when default content is loaded in a straightforward way entirely through the precedence search/load order without having to worry about checking the specific dynamic library is the correct one, other than checking that it is located in the right place. Here is what I'm thinking for this case:
If connecting to a semipure or unpure server that is determined to be a 1.3 engine version, the default content search starts at search/load 1) listed above. If connecting to a semipure or unpure server that is determined to be a gpp engine version, the default content search starts at search/load 3) listed above. If connecting to a semipure or unpure server that is determined to be a 1.1 engine version, the default content search starts at search/load 5) listed above. For now, if connecting to a pure server, skip the dynamic library search/load for the cgame and ui modules, but still include the dynamic library search/load for the game module in the case of starting a local game server through the client. The engine version of the server you are connecting to can be determined by finding the highest engine version that includes in its hardcoded default content at least one pk3 file that the given connected server lists. |
@Chomenor , sure, I'll put something together sometime tomorrow (or later today rather, it's 1:21 am here at the moment). I think I'll copy the setup we have for the GrangerPub server, since that uses the tremded from this repo. |
@Chomenor , this is pretty much the same setup we have for the GrangerPub server, I tested this .zip on my local Linux computer, and it works: https://www.dropbox.com/s/9pitcb2ahtxf0rb/GPub_Setup.zip?dl=0 You are going to have to change the tremded repo in the |
Looks good, thanks. I'll start working on it. Since I'm planning to use a new system for specifying versioned pk3s, is it okay if I drop support for fs_pk3PrefixPairs? That reduces complexity but it does mean that existing server configs will need to be updated to use the new system. |
Sure, as long as the new system works for providing the multiprotocol support at least just as well now, I'm all for that. It probably wouldn't require too much alteration of the bash scripts, let me know if/when you need any assistance with adjusting any of the scripts. |
@dGr8LookinSparky I've added basic multi-version pk3 support now. I haven't tested it much, but it does seem to work with the server config you gave me to the extent that different client versions could successfully connect. I added a wiki page documenting the new system here. The example at the bottom shows the lines that need to be added to one of the server config files. |
Very awesome work @Chomenor :) ! I'll find some time in a few days to test it out, and perhaps setup a new test server. |
Howdy @Chomenor , I found a bug where if after you build a release locally, if you delete the ui.so in the |
Sorry about the merge problem. I seem to be having some line ending related problems using Git on Windows since the .gitattributes was recently changed. Git's line ending behavior is really confusing to me. I wish it would just leave the line endings alone instead of changing them back and forth randomly... I'm going to try to switch to git on Linux for interacting with this repository and hopefully that will stop the problems. |
yeah, we had to change the git attributes because it was corrupting new audio files at least when added from linux. Maybe it can be fixed up more to work for windows again (but without messing around with things like audio files)? This is one of those obscure aspects of git. |
It seems like it is possible to tag certain extensions as binary, like
etc. I'm not sure that's related to my particular problem, but it could be useful. |
@Chomenor you may need to clone again so that your line endings are now consistent. I agree that audio files should be marked binary, but to switch safely between Linux/Mac and Windows devs, we still have to use the auto switch. So the
|
As far as I can tell the UI error traces to this line: Line 1942 in 38cbdc8
|
Thanks @Chomenor :) , I'll have some time later today to look into it more deeply. But from initially browsing that part of the code, maybe with how QVMs work I have to explicitly check |
I don't know, it would depend on how that code is supposed to work. Personally I don't know what that code even does... Also, I encountered another unrelated issue while debugging that one: the line tremulous/src/sdl/sdl_glimp.cpp Line 199 in 38cbdc8
A potential fix is to change the line
to
|
I'll look into that too. Regarding the bucket stuff, that's a new thing I implemented that is used to semi-randomly select from multiple music files, which music to play in the main menu on startup. It ensures that all of the music files in a particular directory are played exactly once for each startup of the client, before resetting and starting again. It is meant to introduce some variety in the music in the main menu. The specific music files we are using currently are placeholders from previous trem mods, that we'll replace at some point when new theme music is made. The general bucket system can be used for other things potentially, like for map rotations, and anything else that we might want to have selected in that kind of way. |
Do you know if the |
Oh jeeze, I think I found the problem, in |
It looks like that fixed it, I'll get the repos updated accordingly :) |
Sounds good! |
Ah yes, it looks like it. When you get a chance, @Buom01 could you test and make sure that issue has been fixed? |
@dGr8LookinSparky Working fine now ! @Chomenor Nice works, that sound promising ! |
This is my effort to port my ioquake3 filesystem project to Tremulous. It's not actually complete/ready to merge yet, but @wtfbbqhax suggested I open a pull request so it can be covered by the CI system.
My current progress is that the game is in a roughly working state, and it should be able to run and connect to most servers. However more advanced features like special pk3 precedence rules and support for hosting multi-protocol servers have not been implemented yet.