Game Development Community

MS4: Odd client/server bug.

by Stefan Lundmark · in Torque Game Engine Advanced · 09/10/2006 (9:38 am) · 11 replies

This is what I get when joining a server (dedicated/listen does not matter)

Quote:*** Phase 2: Download Ghost Objects
Warning: (d:\tse\engine\gfx\bitmappng.cpp @ 108) GBitmap::readPNG: stream doesn't contain a PNG
PlatformMemory: allocating new page, total bytes allocated so far: 16262884 (total bytes in all pages=25165824)
PlatformMemory: allocating new page, total bytes allocated so far: 23862460 (total bytes in all pages=33554432)
Fatal: (d:\tse\engine\interior\interiorlmmanager.cpp @ 219)InteriorLMManager::removeInstance: invalid instance handle
Error, a DecalManager (1e6af84) isn't properly out of the bins!
Error, a VolumeLight (b486c80) isn't properly out of the bins!
Error, a VolumeLight (b486c80) isn't properly out of the bins!
Error, a VolumeLight (b486c80) isn't properly out of the bins!
Error, a VolumeLight (b486c80) isn't properly out of the bins!
Error, a WaterBlock (b48723c) isn't properly out of the bins!
Error, a TSStatic (19c5720) isn't properly out of the bins!
Error, a TSStatic (19c5a08) isn't properly out of the bins!
Error, a TSStatic (b475d60) isn't properly out of the bins!

Sometimes it just says "Invalid packet" which is not very obvious. And if I run release mode I get a crash.

Both client and server are identical and share the same assets. They work just fine in a singleplayer setup, but not when joining. This is basically the 'demo' mod but with multiplayer.

Putting a breakpoint in SimObject::registerObject() shows nothing, suprisingly. All the object ID's are "???" in the callstack.

Pretty funny huh!

#1
09/10/2006 (10:25 am)
Sounds as if a packUpdate/unpackUpdate pair may be mismatched.
#2
09/10/2006 (10:37 am)
I ran with Torque_NetDebug (whatever it is named.. dead tired atm) and couldnt spot any mismatches. :/
#3
09/10/2006 (12:16 pm)
Boy am I tired.

Anyway, I found something and would like to hear a comment from GG:

// ok, if the material list load failed...
         // if this is a local connection, we'll assume that's ok
         // and just have white textures...
         // otherwise we want to return false.
         Interior* pInterior = mInteriorRes->getDetailLevel(i);
         if(!pInterior->prepForRendering(mInteriorRes.getFilePath()) )
         {
            if(!bool(mServerObject))
            {
               Con::printf ("Bang bang, problem!" );
	[b]return false;[/b]
            }
         }
      }

Commenting out the bold return false; part from the above code finally lets me join our dedicated server. This leads me to believe materials are not sent over the network for some reason.

Thoughts?

Now back to the lighting crashes :/
#4
09/10/2006 (3:46 pm)
I think you did in fact find an issue!

Quite a while ago (MS 2 I think), it was determined that sending materials as part of mission download was extremely inefficient (could take minutes and minutes with a lot of materials), so it is explicitly assumed that all materials exist on the client (in fact, in the shared /data directory).

It appears as if the above code wasn't updated very well as part of this change in base assumptions.

And, you'll need to have your materials client side...
#5
09/10/2006 (4:20 pm)
This was an issue in MS3.5, as well, but it was tied more-so to missing physical textures versus the Materials.. As MaterialLists still look for a texture named accordingly to what was in the .map/.dif. So if that texture was missing, but you had a material named the same, it would error out.

We fixed this by searching for a material named accordingly to what was trying to be loaded, then grabbing one of the Base Texture filenames from the Material and pushing it into the MaterialList. This stopped most of the issues, except with Lightmaps trying to be generated on a non-existant Interior, since it would fail being loaded, due to Texture issues.

The return false is actually probably an attempt to fix that issue, as if the physical textures aren't existing, then it will be an invalid instance. So, you get a false if something is missing, thus keeping it from trying to do something it shouldnt.
#6
09/10/2006 (4:22 pm)
"Sometimes it just says "Invalid packet" which is not very obvious"


More than likely a texture it is looking for is missing, and I would bet it is "White", as Map2dif inserts that into .difs and such with missing textures. You can check the createTexture calls and find where the missing texture console printing is disabled and enable it.
#7
09/10/2006 (7:53 pm)
In general packet errors == missing assets and the best way to find it is to set a few breakpoints and track it down.

Better error reporting in this area would be very useful all around. :)
#8
09/11/2006 (1:27 am)
There are no missing textures in the interior Jeremiah/Ben. I exported the texture list and put printf's inside the code and all of them are defined as materials and loading properly.

Though I do see the problem you mentioned Jeremiah, with that it checks for the actual referenced texture inside the .dif instead of the material. That's really dirty, but according to Brian it is intended.

Thanks for following up on this guys.

Edit: Oh and..

Quote:
Quite a while ago (MS 2 I think), it was determined that sending materials as part of mission download was extremely inefficient (could take minutes and minutes with a lot of materials), so it is explicitly assumed that all materials exist on the client (in fact, in the shared /data directory).

I was dead tired, sorry. Of course materials are no longer sent over the network, and thanks for reminding me that I should go to sleep before 3'oclock :) I'm not sure we all agreed this is a bug or just me not understanding the architecture, but in any case I did put a note in there and it works for now.

Thanks Stephen.
#9
09/11/2006 (2:12 pm)
Yeah, I fixed another crash related to this the other day, should be up in CVS. At this point, I'm just forcing prepForRendering to return true because it's just causing headaches and confusion with textures and materials.

Now worst case, I believe is "no material" texture being rendered, or possiblly no interior geometry rendered for unmapped areas.
#10
09/13/2006 (4:15 am)
I imagine it is intended, as it makes sure the physical texture is present which is useful for some certain things.. Although I guess it could be still in place, if/when somebody decides to add back some mini-fixed function pipeline support just as fallbacks.

In any case, I modified it for our codebase so certain classes can use the new implementation we setup, and if not, then it'll still use the original method

materialList.cpp:

// If we are tagged (Interiors/DTS), then we will do it
			 // the new way and bypass the other support below - byte
			 if(useMaterial)
				success = handle.set(Material::getBaseTexture(name), &GFXDefaultStaticDiffuseProfile);


Material.cpp:

const char * Material::getBaseTexture( const char* name )
{
	// find the material
	Material *loadMat = dynamic_cast<Material*>(Sim::findObject( name ) );

	// use another variable to keep filePath from getting clobbered
	static char fullFilename[256];

	if(loadMat)
	{
		// copy full path
		dStrcpy(fullFilename, loadMat->filePath);

		// find a baseTexture!
		for( int i=0; i<MAX_STAGES; i++ )
		{
			// glow sometimes messes up the naming.. lets check
			if(loadMat->glow[i])
			{
				if( loadMat->baseTexFilename[i+1] && loadMat->baseTexFilename[i+1][0] )
				{
					dStrcat( fullFilename, loadMat->baseTexFilename[i+1] );
					break;
				}
			}
			if( loadMat->baseTexFilename[i] && loadMat->baseTexFilename[i][0] )
			{
				dStrcat( fullFilename, loadMat->baseTexFilename[i] );
				break;
			}
		}
	}
	return fullFilename;
}

It could be done better I'm sure, but so far it works like a charm and has a benefit of allowing us to sort out textures alot easier and any Interior/DTS can reference any texture with ease which our artists are happy about
#11
09/13/2006 (4:59 pm)
Thanks for sharing your workaround for this issue - I have a feeling this'll be useful for a fair number of people. :)