Arcana, if you're still reading this thread, I saw something that reminded me of an earlier discussion.
In another thread there was discussion was about re-engineering things and how closely you had to get to the original implementation versus designing something that works completely differently and making it protocol-compatible. I grumbled something about the protocols in COH using a lot of implementation details in them that makes it difficult to do the latter. SG bases turn out to be a good example of this.
Bit of necessary backstory: The COH world graph consists of two things: Groupdefs - or defs for short, and Refs. Defs at the lowest level represent a single mesh, but more often reference other defs in a hierarchical manner, building up a complex object from smaller pieces, which is where the 'group' part of the name comes from. Defs are defined both in map files as well as the object library - a shared repository that contains every static 3D object in game. The defs from map files are typically more complex and might be things like a big group that instances many buildings from other defs that come from the object library.
But defs only define what groups look like, they don't actually place them anywhere. Map files also contain a list of Refs - references to specific defs with instructions on where to place them. In zone maps there are only a handful of top-level refs that point at the defs defined in that same file. One common thing to see is a ref to "grp_Geometry", the customary name of the Groupdef that all of the zone geometry is under.
When I say things like "the server just sends a map filename for the client to load", that's actually a gross simplification to keep conversations manageable. What actually happens is that the server first sends a list of files to load defs from - first all of the various object library files it depends on*, then the map itself. Then it sends the list of top-level refs that point to some of the defs just loaded.
And that's just to get a normal map loaded, that's not even the point to my story.
As I mentioned, bases work quite differently. They use a similar mechanism, but instead of the final filename in the list being the zone map, it's an empty filename followed by a compressed base structure. The client uses that structure and builds a number of defs in memory, parented by "grpbase_0" -- the 0 is presumably to identify the base so that multiple bases can be loaded during a base raid. It also adds a grpbase_0 ref to the global list of refs in memory. In theory, that means all you have to do is send a compressed base (in binary format) and the client will do all of the work of generating the geometry for it, just like when playing back a demorecord.
When I first started working on bases in Paragon Chat, I wasted a good day's worth of time on a real headscratcher of a problem. The base was being sent correctly, I verified that it was being received and the geometry was being generated in client memory, but when I actually zoned in it was an empty map. I tried all sorts of different things to try to make it work, or even do something different like crash just to see if I was on the right track.
Finally, I managed to piece together what was happening. After sending the file names (or base), it still expects a list of refs. When an empty list didn't work, I had previously tried changing that to send simply "Base" (the name I was using internally in Paragon Chat to represent the base) with no success. Only once I started watching the ref list memory area did I realize that when I was sending a "Base" ref, or no ref at all, the client was checking it against the list it already had. It then deleted the "grpbase_0" ref it had created earlier because it wasn't on the list of refs sent by the 'server'. In the end I had to modify Paragon Chat to nearly perfectly duplicate how the client was generating groupdefs from the base data in order to make it successfully load.
In hindsight I should have realized that sooner, since the normal map load procedure involves sending all of the refs as well. However, in the early days I was just duplicating the packet captures I was going by and since the map file already had the list in it, I never thought to try something different. Had I done so I would have realized just how tightly coupled the protocol is to the implementation behind it.
That's just one example, but I've run into the same thing numerous times. Even sending costumes correctly requires building up a single-instance list of costume parts in a particular order and then transmitting numeric indices into that list.