void C4Effect::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers) { // read name pComp->Separator(StdCompiler::SEP_START); // '(' // read priority pComp->Value(iPriority); pComp->Separator(); // read time and intervall pComp->Value(iTime); pComp->Separator(); pComp->Value(iInterval); pComp->Separator(); // read object number pComp->Value(CommandTarget); pComp->Separator(); // read ID pComp->Value(idCommandTarget); pComp->Separator(); // proplist C4PropListNumbered::CompileFunc(pComp, numbers); pComp->Separator(StdCompiler::SEP_END); // ')' // is there a next effect? bool fNext = !! pNext; if (pComp->hasNaming()) { if (fNext || pComp->isCompiler()) fNext = pComp->Separator(); } else pComp->Value(fNext); if (!fNext) return; // read next pComp->Value(mkParAdapt(mkPtrAdaptNoNull(pNext), numbers)); // denumeration and callback assignment will be done later }
void C4TeamList::CompileFunc(StdCompiler *pComp) { // if (pComp->isCompiler()) Clear(); - do not clear, because this would corrupt the fCustom-flag pComp->Value(mkNamingAdapt(fActive, "Active", true)); pComp->Value(mkNamingAdapt(fCustom, "Custom", true)); pComp->Value(mkNamingAdapt(fAllowHostilityChange, "AllowHostilityChange", false)); pComp->Value(mkNamingAdapt(fAllowTeamSwitch, "AllowTeamSwitch", false)); pComp->Value(mkNamingAdapt(fAutoGenerateTeams, "AutoGenerateTeams", false)); pComp->Value(mkNamingAdapt(iLastTeamID, "LastTeamID", 0)); StdEnumEntry<TeamDist> TeamDistEntries[] = { { "Free", TEAMDIST_Free }, { "Host", TEAMDIST_Host }, { "None", TEAMDIST_None }, { "Random", TEAMDIST_Random }, { "RandomInv", TEAMDIST_RandomInv }, }; pComp->Value(mkNamingAdapt(mkEnumAdaptT<uint8_t>(eTeamDist, TeamDistEntries), "TeamDistribution", TEAMDIST_Free)); pComp->Value(mkNamingAdapt(fTeamColors, "TeamColors", false)); pComp->Value(mkNamingAdapt(iMaxScriptPlayers, "MaxScriptPlayers", 0)); pComp->Value(mkNamingAdapt(mkParAdapt(sScriptPlayerNames, StdCompiler::RCT_All), "ScriptPlayerNames", StdStrBuf())); int32_t iOldTeamCount = iTeamCount; pComp->Value(mkNamingCountAdapt(iTeamCount, "Team")); if (pComp->isCompiler()) { while (iOldTeamCount--) delete ppList[iOldTeamCount]; delete [] ppList; if ((iTeamCapacity = iTeamCount)) { ppList = new C4Team *[iTeamCapacity]; memset(ppList, 0, sizeof(C4Team *)*iTeamCapacity); } else ppList = NULL; } if (iTeamCount) { // Force compiler to spezialize mkPtrAdaptNoNull(*ppList); // Save team list, using map-function. pComp->Value(mkNamingAdapt( mkArrayAdaptMap(ppList, iTeamCount, mkPtrAdaptNoNull<C4Team>), "Team")); } if (pComp->isCompiler()) { // adjust last team ID, which may not be set properly for player-generated team files iLastTeamID = std::max(GetLargestTeamID(), iLastTeamID); // force automatic generation of teams if none are defined if (!iTeamCount) fAutoGenerateTeams = true; } }
void C4Effect::CompileFunc(StdCompiler *pComp, C4PropList * Owner, C4ValueNumbers * numbers) { if (pComp->isCompiler()) Target = Owner; // read name pComp->Separator(StdCompiler::SEP_START); // '(' // read priority pComp->Value(iPriority); pComp->Separator(); // read time and intervall pComp->Value(iTime); pComp->Separator(); pComp->Value(iInterval); pComp->Separator(); // read object number // FIXME: replace with this when savegame compat breaks for other reasons // pComp->Value(mkParAdapt(CommandTarget, numbers)); int32_t nptr = 0; if (!pComp->isCompiler() && CommandTarget.getPropList() && CommandTarget._getPropList()->GetPropListNumbered()) nptr = CommandTarget._getPropList()->GetPropListNumbered()->Number; pComp->Value(nptr); if (pComp->isCompiler()) CommandTarget.SetObjectEnum(nptr); pComp->Separator(); // read ID if (pComp->isDecompiler()) { const C4PropListStatic * p = CommandTarget.getPropList() ? CommandTarget._getPropList()->IsStatic() : NULL; if (p) p->RefCompileFunc(pComp, numbers); else pComp->String(const_cast<char*>("None"), 5, StdCompiler::RCT_ID); } else { StdStrBuf s; pComp->Value(mkParAdapt(s, StdCompiler::RCT_ID)); // An Object trumps a definition as command target if (!nptr) if (!::ScriptEngine.GetGlobalConstant(s.getData(), &CommandTarget)) CommandTarget.Set0(); } pComp->Separator(); // proplist C4PropListNumbered::CompileFunc(pComp, numbers); pComp->Separator(StdCompiler::SEP_END); // ')' // is there a next effect? bool fNext = !! pNext; if (pComp->hasNaming()) { if (fNext || pComp->isCompiler()) fNext = pComp->Separator(); } else pComp->Value(fNext); if (!fNext) return; // read next pComp->Value(mkParAdapt(mkPtrAdaptNoNull(pNext), Owner, numbers)); // denumeration and callback assignment will be done later }
void C4RecordChunk::CompileFunc(StdCompiler *pComp) { pComp->Value(mkNamingAdapt(Frame, "Frame")); pComp->Value(mkNamingAdapt(mkIntAdapt(Type), "Type")); switch (Type) { case RCT_Ctrl: pComp->Value(mkPtrAdaptNoNull(pCtrl)); break; case RCT_CtrlPkt: pComp->Value(mkPtrAdaptNoNull(pPkt)); break; case RCT_End: break; case RCT_Frame: break; case RCT_File: pComp->Value(Filename); pComp->Value(mkPtrAdaptNoNull(pFileData)); break; default: pComp->Value(mkPtrAdaptNoNull(pDbg)); break; } }
void C4ObjectList::CompileFunc(StdCompiler *pComp, bool fSkipPlayerObjects, C4ValueNumbers * numbers) { // "Object" section count int32_t iObjCnt = ObjectCount(); pComp->Value(mkNamingCountAdapt(iObjCnt, "Object")); if (pComp->isDecompiler()) { // skipping player objects would screw object counting in non-naming compilers assert(!fSkipPlayerObjects || pComp->hasNaming()); // Decompile all objects in reverse order for (C4ObjectLink *pPos = Last; pPos; pPos = pPos->Prev) if (pPos->Obj->Status) if (!fSkipPlayerObjects || !pPos->Obj->IsUserPlayerObject()) pComp->Value(mkNamingAdapt(mkParAdapt(*pPos->Obj, numbers), "Object")); } else { // FIXME: Check that no PlayerObjects are loaded when fSkipPlayerObjects is true // i.e. that loading and saving was done with the same flag. // Remove previous data Clear(); // Load objects, add them to the list. for (int i = 0; i < iObjCnt; i++) { C4Object *pObj = NULL; try { pComp->Value(mkNamingAdapt(mkParAdapt(mkPtrAdaptNoNull(pObj), numbers), "Object")); Add(pObj, stReverse); } catch (StdCompiler::Exception *pExc) { // Failsafe object loading: If an error occurs during object loading, just skip that object and load the next one if (!pExc->Pos.getLength()) LogF("ERROR: Object loading: %s", pExc->Msg.getData()); else LogF("ERROR: Object loading(%s): %s", pExc->Pos.getData(), pExc->Msg.getData()); delete pExc; } } } }
BOOL C4Playback::ReadBinary(const StdBuf &Buf) { // sequential reading: Take over rest from last buffer const StdBuf *pUseBuf; uint32_t iFrame = 0; if (fLoadSequential) { sequentialBuffer.Append(Buf); pUseBuf = &sequentialBuffer; iFrame = iLastSequentialFrame; } else pUseBuf = &Buf; // get buffer data size_t iPos = 0; bool fFinished = false; do { // unpack header if (pUseBuf->getSize() - iPos < sizeof(C4RecordChunkHead)) break; const C4RecordChunkHead *pHead = getBufPtr<C4RecordChunkHead>(*pUseBuf, iPos); // get chunk iPos += sizeof(C4RecordChunkHead); StdBuf Chunk = pUseBuf->getPart(iPos, pUseBuf->getSize() - iPos); // Create entry C4RecordChunk c; c.Frame = (iFrame += pHead->iFrm); c.Type = pHead->Type; // Unpack data try { // Initialize compiler StdCompilerBinRead Compiler; Compiler.setInput(Chunk.getRef()); Compiler.Begin(); // Read chunk switch (pHead->Type) { case RCT_Ctrl: Compiler.Value(mkPtrAdaptNoNull(c.pCtrl)); break; case RCT_CtrlPkt: Compiler.Value(mkPtrAdaptNoNull(c.pPkt)); break; case RCT_End: fFinished = true; break; case RCT_File: Compiler.Value(c.Filename); Compiler.Value(mkPtrAdaptNoNull(c.pFileData)); break; default: // debugrec if (pHead->Type >= 0x80) Compiler.Value(mkPtrAdaptNoNull(c.pDbg)); } // Advance over data Compiler.End(); iPos += Compiler.getPosition(); } catch (StdCompiler::EOFException *pEx) { // This is to be expected for sequential reading if (fLoadSequential) { iPos -= sizeof(C4RecordChunkHead); iFrame -= pHead->iFrm; delete pEx; break; } LogF("Record: Binary unpack error: %s", pEx->Msg.getData()); c.Delete(); delete pEx; return FALSE; } catch (StdCompiler::Exception *pEx) { LogF("Record: Binary unpack error: %s", pEx->Msg.getData()); c.Delete(); delete pEx; return FALSE; } // Add to list chunks.push_back(c); c.pPkt = NULL; } while (!fFinished); // erase everything but the trailing part from sequential buffer if (fLoadSequential) { if (iPos >= sequentialBuffer.getSize()) sequentialBuffer.Clear(); else if (iPos) { sequentialBuffer.Move(iPos, sequentialBuffer.getSize() - iPos); sequentialBuffer.Shrink(iPos); } iLastSequentialFrame = iFrame; } return TRUE; }