IEffectPainter *CEffectCreator::CreatePainterFromStreamAndCreator (SLoadCtx &Ctx, CEffectCreator *pCreator) // CreatePainterFromStreamAndCreator // // Load a painter from a stream given a creator { // Older versions did not save UNID or class if there was no creator if (Ctx.dwVersion < 43 && pCreator == NULL) return NULL; // The UNID is ignored (because it is the UNID of the creator) IEffectPainter::ReadUNID(Ctx); // Validate the class if (IEffectPainter::ValidateClass(Ctx, pCreator ? pCreator->GetTag() : NULL_STR) != NOERROR) return NULL; // Load it if (pCreator == NULL) return NULL; IEffectPainter *pPainter = pCreator->CreatePainter(); pPainter->ReadFromStream(Ctx); // Done return pPainter; }
ALERROR IEffectPainter::ValidateClass (SLoadCtx &Ctx, const CString &sOriginalClass) // ValidateClass // // Reads the class string. If the class does not match the current painter, // we read the old data and return ERR_FAIL. { if (Ctx.dwVersion >= 40) { CString sClass; sClass.ReadFromStream(Ctx.pStream); // If the original class doesn't match the current one, then it means // that the design changed. In that case, we load the painter using the // old class. if (!strEquals(sClass, sOriginalClass)) { // If sClass is blank, then it means that the original did not have // an effect painter (but the current design does) if (!sClass.IsBlank()) { // Get the original creator CEffectCreator *pOriginalCreator; if (CEffectCreator::CreateFromTag(sClass, &pOriginalCreator) != NOERROR) { kernelDebugLogMessage("Unable to find original effect creator: %s", sClass.GetASCIIZPointer()); return ERR_FAIL; } // Load the original painter IEffectPainter *pOriginalPainter = pOriginalCreator->CreatePainter(); pOriginalPainter->ReadFromStream(Ctx); // Discard pOriginalPainter->Delete(); delete pOriginalCreator; } // Done return ERR_FAIL; } } return NOERROR; }
IEffectPainter *CEffectCreator::CreatePainterFromStream (SLoadCtx &Ctx, bool bNullCreator) // CreatePainterFromStream // // Load a painter from a stream { CEffectCreator *pCreator; // For previous versions, we only stored UNID if we had a creator if (Ctx.dwVersion < 43 && bNullCreator) return NULL; // At version 15 we started saving versions as string UNIDs. We need to do this // because sometimes the effect creator is inside a weapon fire desc // structure (also identified by string UNIDs). if (Ctx.dwVersion >= 15) { CString sUNID; sUNID.ReadFromStream(Ctx.pStream); pCreator = (sUNID.IsBlank() ? NULL : CEffectCreator::FindEffectCreator(sUNID)); // Load the creator class that saved the painter if (IEffectPainter::ValidateClass(Ctx, (pCreator ? pCreator->GetTag() : NULL_STR)) != NOERROR) return NULL; // Error if (pCreator == NULL) { if (!sUNID.IsBlank()) kernelDebugLogMessage("Invalid painter creator: %s", sUNID.GetASCIIZPointer()); return NULL; } } // Old style uses DWORD UNIDs else { // The first DWORD is the UNID of the creator DWORD dwUNID; Ctx.pStream->Read((char *)&dwUNID, sizeof(DWORD)); if (dwUNID == 0) return NULL; pCreator = g_pUniverse->FindEffectType(dwUNID); // Error if (pCreator == NULL) { kernelDebugLogMessage("Invalid painter creator: %x", dwUNID); return NULL; } } // Let the creator create the object IEffectPainter *pPainter = pCreator->CreatePainter(); // Load it pPainter->ReadFromStream(Ctx); // Done return pPainter; }