Well, you have 16 float parms. It's possible to pack 23 or 24 bits (I think) of integer values per parm if you use bitwise operations, or the full 32 bits if you use LordHavoc's incredibly evil 1000+ line code from hell. You could fit the relative player origin in the parms, but you'll never get nearby entities to fit in there, let alone a hub system.
There have been hacks. One old Quake mod I believe devoted one bit to the alive/dead state of each monster in all of the several maps it used. You probably had to assign a unique 'bit number' to each monster entity in the level editor, and could only fit so many monsters, and it wouldn't remember their position or health.
As long as you're using a custom engine, it's customary to use FRIK_FILE for hub systems. I did this for an old dead mod of mine (Fniggium), and was considering linking you to the code for reference. But it's pretty much indecipherable and mostly covers other things. But anyway, you can still if you want. I think it worked, but I don't remember for sure.
What I do is similar to what I think Quake2 does. Saves are created in folders, with each map getting its own save file in the folder. The current game state is held in the '_current' save folder. When you load a save game, it copies all the files of that save folder to the _current folder, and vice versa for saving. In addition to the map save files, you have a global 'game state' file, which probably contains the current map, and the player information. (Note that this idea of a _current save will probably bork up completely if you run two copies of the game at once, which worked fine in Quake 1).
The entities are written to the files in your own formatting, and read back using tokenize() (courtesy of KRIMZON_SV_PARSECLIENTCOMMAND) to parse it.