Пример #1
0
bool C4PlayerInfoCore::Load(C4Group &hGroup)
{
	// New version
	StdStrBuf Source;
	if (hGroup.LoadEntryString(C4CFN_PlayerInfoCore,&Source))
	{
		// Compile
		StdStrBuf GrpName = hGroup.GetFullName(); GrpName.Append(DirSep C4CFN_PlayerInfoCore);
		if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(*this, Source, GrpName.getData()))
			return false;
		// Pref for AutoContextMenus is still undecided: default by player's control style
		if (OldPrefAutoContextMenu == -1)
			OldPrefAutoContextMenu = OldPrefControlStyle;
		// Determine true color from indexed pref color
		if (!PrefColorDw)
			PrefColorDw = GetPrefColorValue(PrefColor);
		// Validate colors
		PrefColorDw &= 0xffffff;
		PrefColor2Dw &= 0xffffff;
		// Validate name
		C4Markup::StripMarkup(PrefName);
		// Success
		return true;
	}

	// Old version no longer supported - sorry
	return false;
}
Пример #2
0
bool C4ParticleDef::Load(C4Group &group)
{
	// store file
	Filename.Copy(group.GetFullName());
	// load
	char *particle_source;
	if (group.LoadEntry(C4CFN_ParticleCore,&particle_source,NULL,1))
	{
		if (!Compile(particle_source, Filename.getData()))
		{
			DebugLogF("invalid particle def at '%s'", group.GetFullName().getData());
			delete [] particle_source; return false;
		}
		delete [] particle_source;
		// load graphics
		if (!Gfx.Load(group, C4CFN_DefGraphics, C4FCT_Full, C4FCT_Full, false, C4SF_MipMap))
		{
			DebugLogF("particle %s has no valid graphics defined", Name.getData());
			return false;
		}
		// set facet, if assigned - otherwise, assume full surface
		if (GfxFace.Wdt) Gfx.Set(Gfx.Surface, GfxFace.x, GfxFace.y, GfxFace.Wdt, GfxFace.Hgt);
		// set phase num
		int32_t Q; Gfx.GetPhaseNum(PhasesX, Q);
		Length = PhasesX * Q;
		if (!Length)
		{
			DebugLogF("invalid facet for particle '%s'", Name.getData());
			return false;
		}
				// calc aspect
		Aspect=(float) Gfx.Hgt/Gfx.Wdt;
		
		// particle overloading
		C4ParticleDef *def_overload;
		if ((def_overload = Particles.definitions.GetDef(Name.getData(), this)))
		{
			if (Config.Graphics.VerboseObjectLoading >= 1)
				{ char ostr[250]; sprintf(ostr,LoadResStr("IDS_PRC_DEFOVERLOAD"),def_overload->Name.getData(),"<particle>"); Log(ostr); }
			delete def_overload;
		}
		// success
		return true;
	}
	return false;
}
Пример #3
0
BOOL C4PlayerInfoCore::Save(C4Group &hGroup)
  {
	StdStrBuf Source, Name = hGroup.GetFullName(); Name.Append(DirSep C4CFN_PlayerInfoCore);
	if(!DecompileToBuf_Log<StdCompilerINIWrite>(*this, &Source, Name.getData()))
		return FALSE;
	if (!hGroup.Add(C4CFN_PlayerInfoCore,Source,FALSE,TRUE))
		return FALSE;
	hGroup.Delete("C4Player.c4b");
	return TRUE;
	}
Пример #4
0
bool C4PlayerInfoCore::Save(C4Group &hGroup)
{
	StdStrBuf Source, Name = hGroup.GetFullName(); Name.Append(DirSep C4CFN_PlayerInfoCore);
	if (!DecompileToBuf_Log<StdCompilerINIWrite>(*this, &Source, Name.getData()))
		return false;
	if (!hGroup.Add(C4CFN_PlayerInfoCore,Source,false,true))
		return false;
	hGroup.Delete("C4Player.ocb");
	return true;
}
Пример #5
0
bool C4VectorFont::Init(C4Group &hGrp, const char *szFilename, C4Config &rCfg)
	{
	// name by file
	Name.Copy(GetFilenameOnly(szFilename));
#if defined(_WIN32) && !defined(HAVE_FREETYPE)
	// check whether group is directory or packed
	if (!hGrp.IsPacked())
		{
		// it's open: use the file directly
		SCopy(hGrp.GetFullName().getData(), FileName, _MAX_PATH);
		AppendBackslash(FileName);
		SAppend(szFilename, FileName);
		if (!FileExists(FileName)) { *FileName=0; return false; }
		fIsTempFile = false;
		}
	else
		{
		// it's packed: extract to temp path
		SCopy(rCfg.AtTempPath(szFilename), FileName, _MAX_PATH);
		// make sure the filename is not in use, in case multiple instances of the engine are run
		if (FileExists(FileName))
			{
			RemoveExtension(FileName);
			StdStrBuf sNewFilename;
			for (int i=0; i<1000; ++i)
				{
				sNewFilename.Format("%s%x", FileName, (int)rand());
				if (*GetExtension(szFilename))
					{
					sNewFilename.AppendChar('.');
					sNewFilename.Append(GetExtension(szFilename));
					}
				if (!FileExists(sNewFilename.getData())) break;
				}
			SCopy(sNewFilename.getData(), FileName, _MAX_PATH);
			}
		if (!hGrp.ExtractEntry(szFilename, FileName)) { *FileName=0; return false; }
		fIsTempFile = true;
		}
	// add the font resource
	//if (!AddFontResourceEx(FileName, FR_PRIVATE, NULL)) requires win2k
	if (!AddFontResource(FileName))
		{
		if (fIsTempFile) EraseFile(FileName);
		*FileName='\0';
		return false;
		}
#else
	if (!hGrp.LoadEntry(szFilename, Data)) return false;
#endif
	// success
	return true;
	}
Пример #6
0
bool C4Language::CloseGroup(const char *strPath)
{
	// Check all open language packs
	C4Group *pPack;
	for (int iPack = 0; (pPack = Packs.GetGroup(iPack)); iPack++)
		if (ItemIdentical(strPath, pPack->GetFullName().getData()))
		{
			Packs.UnregisterGroup(iPack);
			return true;
		}
	// No pack of that path
	return false;
}
Пример #7
0
BOOL C4ComponentHost::LoadEx(const char *szName, C4Group &hGroup,
                             const char *szFilename, const char *szLanguage) {
  // Load from a group set containing the provided group and
  // alternative groups for cross-loading from a language pack
  C4GroupSet hGroups;
  hGroups.RegisterGroup(
      hGroup, false, 1000,
      C4GSCnt_Component);  // Provided group gets highest priority
  hGroups.RegisterGroups(Languages.GetPackGroups(pConfig->AtExeRelativePath(
                             hGroup.GetFullName().getData())),
                         C4GSCnt_Language);
  // Load from group set
  return Load(szName, hGroups, szFilename, szLanguage);
}
Пример #8
0
bool C4Shader::LoadSlices(C4GroupSet *pGroups, const char *szFile)
{
	// Search for our shaders
	C4Group *pGroup = pGroups->FindEntry(szFile);
	if(!pGroup) return false;
	// Load it, save the path for later reloading
	StdStrBuf Shader;
	if(!pGroup->LoadEntryString(szFile, &Shader))
		return false;
	// If it physically exists, save back creation time so we
	// can automatically reload it if it changes
	StdStrBuf Source = FormatString("%s" DirSep "%s", pGroup->GetFullName().getData(), szFile);
	int iSourceTime = 0;
	if(FileExists(Source.getData()))
		iSourceTime = FileTime(Source.getData());
	// Load
	StdStrBuf What = FormatString("file %s", Config.AtRelativePath(Source.getData()));
	AddFragmentSlices(What.getData(), Shader.getData(), Source.getData(), iSourceTime);
	return true;
}
Пример #9
0
bool C4MusicSystem::InitForScenario(C4Group & hGroup)
{
	// check if the scenario contains music
	bool fLocalMusic = false;
	StdStrBuf MusicDir;
	if (GrpContainsMusic(hGroup))
	{
		// clear global songs
		ClearSongs();
		fLocalMusic = true;
		// add songs
		MusicDir.Take(Game.ScenarioFile.GetFullName());
		LoadDir(MusicDir.getData());
		// log
		LogF(LoadResStr("IDS_PRC_LOCALMUSIC"), MusicDir.getData());
	}
	// check for music folders in group set
	C4Group *pMusicFolder = NULL;
	while ((pMusicFolder = Game.GroupSet.FindGroup(C4GSCnt_Music, pMusicFolder)))
	{
		if (!fLocalMusic)
		{
			// clear global songs
			ClearSongs();
			fLocalMusic = true;
		}
		// add songs
		MusicDir.Take(pMusicFolder->GetFullName());
		MusicDir.AppendChar(DirectorySeparator);
		MusicDir.Append(C4CFN_Music);
		LoadDir(MusicDir.getData());
		// log
		LogF(LoadResStr("IDS_PRC_LOCALMUSIC"), MusicDir.getData());
	}
	// no music?
	if (!SongCount) return false;
	// set play list
	SetPlayList(0);
	// ok
	return true;
}
Пример #10
0
bool C4Def::LoadDefCore(C4Group &hGroup)
{
	StdStrBuf Source;
	if (hGroup.LoadEntryString(C4CFN_DefCore,&Source))
	{
		StdStrBuf Name = hGroup.GetFullName() + (const StdStrBuf &)FormatString("%cDefCore.txt", DirectorySeparator);
		if (!Compile(Source.getData(), Name.getData()))
			return false;
		Source.Clear();

		// Check mass
		if (Mass < 0)
		{
			DebugLogF("WARNING: Def %s (%s) at %s has invalid mass!", GetName(), id.ToString(), hGroup.GetFullName().getData());
			Mass = 0;
		}

		return true;
	}
	return false;
}
Пример #11
0
bool C4Def::LoadSolidMask(C4Group &hGroup)
{
	if (hGroup.FindEntry(C4CFN_SolidMask))
	{
		pSolidMask = C4SolidMask::LoadMaskFromFile(hGroup, C4CFN_SolidMask);
		if (!pSolidMask)
		{
			DebugLogF("  Error loading SolidMask of %s (%s)", hGroup.GetFullName().getData(), id.ToString());
			return false;
		}
		// check SolidMask size
		if (SolidMask.x<0 || SolidMask.y<0 || SolidMask.x + SolidMask.Wdt>pSolidMask->Wdt || SolidMask.y + SolidMask.Hgt>pSolidMask->Hgt) SolidMask.Default();
	}
	else if (SolidMask.Wdt)
	{
		// Warning in case someone wants to define SolidMasks the old way (in the main graphics file)
		DebugLogF("WARNING: Definition %s (%s) defines SolidMask in DefCore but has no SolidMask file!", hGroup.GetFullName().getData(), id.ToString());
		SolidMask.Default();
	}

	return true;
}
Пример #12
0
bool C4MaterialCore::Load(C4Group &hGroup,
                          const char *szEntryName)
{
	StdStrBuf Source;
	if (!hGroup.LoadEntryString(szEntryName,&Source))
		return false;
	StdStrBuf Name = hGroup.GetFullName() + DirSep + szEntryName;
	if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(*this, Source, Name.getData()))
		return false;
	// adjust placement, if not specified
	if (!Placement)
	{
		if (DensitySolid(Density))
		{
			Placement=30;
			if (!DigFree) Placement+=20;
			if (!BlastFree) Placement+=10;
		}
		else if (DensityLiquid(Density))
			Placement=10;
		else Placement=5;
	}
	return true;
}
Пример #13
0
bool C4DefGraphics::LoadBitmap(C4Group &hGroup, const char *szFilename, const char *szOverlay, const char *szNormal, bool fColorByOwner)
{
	if (!szFilename) return false;
	Type = TYPE_Bitmap; // will be reset to TYPE_None in Clear() if loading fails
	Bmp.Bitmap = new C4Surface();
	if (!Bmp.Bitmap->Load(hGroup, szFilename, false, true, C4SF_MipMap))
	{
		Clear();
		return false;
	}

	// Create owner color bitmaps
	if (fColorByOwner)
	{
		// Create additionmal bitmap
		Bmp.BitmapClr=new C4Surface();
		// if overlay-surface is present, load from that
		if (szOverlay && Bmp.BitmapClr->Load(hGroup, szOverlay, false, false, C4SF_MipMap))
		{
			// set as Clr-surface, also checking size
			if (!Bmp.BitmapClr->SetAsClrByOwnerOf(Bmp.Bitmap))
			{
				DebugLogF("    Gfx loading error in %s: %s (%d x %d) doesn't match overlay %s (%d x %d) - invalid file or size mismatch",
				          hGroup.GetFullName().getData(), szFilename, Bmp.Bitmap ? Bmp.Bitmap->Wdt : -1, Bmp.Bitmap ? Bmp.Bitmap->Hgt : -1,
				          szOverlay, Bmp.BitmapClr->Wdt, Bmp.BitmapClr->Hgt);
				Clear();
				return false;
			}
		}
		else
		{
			// otherwise, create by all blue shades
			if (!Bmp.BitmapClr->CreateColorByOwner(Bmp.Bitmap))
			{
				Clear();
				return false;
			}
		}
		fColorBitmapAutoCreated = true;
	}

	if (szNormal)
	{
		Bmp.BitmapNormal = new C4Surface();
		if (Bmp.BitmapNormal->Load(hGroup, szNormal, false, true, C4SF_MipMap))
		{
			// Normal map loaded. Sanity check and link.
			if(Bmp.BitmapNormal->Wdt != Bmp.Bitmap->Wdt ||
			   Bmp.BitmapNormal->Hgt != Bmp.Bitmap->Hgt)
			{
				DebugLogF("    Gfx loading error in %s: %s (%d x %d) doesn't match normal %s (%d x %d) - invalid file or size mismatch",
				          hGroup.GetFullName().getData(), szFilename, Bmp.Bitmap ? Bmp.Bitmap->Wdt : -1, Bmp.Bitmap ? Bmp.Bitmap->Hgt : -1,
				          szNormal, Bmp.BitmapNormal->Wdt, Bmp.BitmapNormal->Hgt);
				Clear();
				return false;
			}

			Bmp.Bitmap->pNormalSfc = Bmp.BitmapNormal;
			if(Bmp.BitmapClr) Bmp.BitmapClr->pNormalSfc = Bmp.BitmapNormal;
		}
		else
		{
			// No normal map
			delete Bmp.BitmapNormal;
			Bmp.BitmapNormal = NULL;
		}
	}

	Type = TYPE_Bitmap;
	// success
	return true;
}
Пример #14
0
C4GroupSet C4Language::GetPackGroups(C4Group & hGroup)
{
	// Build a group set containing the provided group and
	// alternative groups for cross-loading from a language pack
	char strRelativePath[_MAX_PATH + 1];
	char strTargetLocation[_MAX_PATH + 1];
	char strPackPath[_MAX_PATH + 1];
	char strPackGroupLocation[_MAX_PATH + 1];
	char strAdvance[_MAX_PATH + 1];

	// Store wanted target location
	SCopy(Config.AtRelativePath(hGroup.GetFullName().getData()), strRelativePath, _MAX_PATH);
	SCopy(strRelativePath, strTargetLocation, _MAX_PATH);

	// Adjust location by scenario origin
	if (Game.C4S.Head.Origin.getLength() && SEqualNoCase(GetExtension(Game.C4S.Head.Origin.getData()), "ocs"))
	{
		const char *szScenarioRelativePath = GetRelativePathS(strRelativePath, Config.AtRelativePath(Game.ScenarioFilename));
		if (szScenarioRelativePath != strRelativePath)
		{
			// this is a path within the scenario! Change to origin.
			size_t iRestPathLen = SLen(szScenarioRelativePath);
			if (Game.C4S.Head.Origin.getLength() + 1 + iRestPathLen <= _MAX_PATH)
			{
				SCopy(Game.C4S.Head.Origin.getData(), strTargetLocation);
				if (iRestPathLen)
				{
					SAppendChar(DirectorySeparator, strTargetLocation);
					SAppend(szScenarioRelativePath, strTargetLocation);
				}
			}
		}
	}

	// Process all language packs (and their respective pack groups)
	C4Group *pPack, *pPackGroup;
	for (int iPack = 0; (pPack = Packs.GetGroup(iPack)) && (pPackGroup = PackGroups.GetGroup(iPack)); iPack++)
	{
		// Get current pack group position within pack
		SCopy(pPack->GetFullName().getData(), strPackPath, _MAX_PATH);
		GetRelativePath(pPackGroup->GetFullName().getData(), strPackPath, strPackGroupLocation);

		// Pack group is at correct position within pack: continue with next pack
		if (SEqualNoCase(strPackGroupLocation, strTargetLocation))
			continue;

		// Try to backtrack until we can reach the target location as a relative child
		while ( strPackGroupLocation[0]
		        && !GetRelativePath(strTargetLocation, strPackGroupLocation, strAdvance)
		        && pPackGroup->OpenMother() )
		{
			// Update pack group location
			GetRelativePath(pPackGroup->GetFullName().getData(), strPackPath, strPackGroupLocation);
		}

		// We can reach the target location as a relative child
		if (strPackGroupLocation[0] && GetRelativePath(strTargetLocation, strPackGroupLocation, strAdvance))
		{
			// Advance pack group to relative child
			pPackGroup->OpenChild(strAdvance);
		}

		// Cannot reach by advancing: need to close and reopen (rewinding group file)
		else
		{
			// Close pack group (if it is open at all)
			pPackGroup->Close();
			// Reopen pack group to relative position in language pack if possible
			pPackGroup->OpenAsChild(pPack, strTargetLocation);
		}

	}

	// Store new target location
	SCopy(strTargetLocation, PackGroupLocation, _MAX_FNAME);

	C4GroupSet r;
	// Provided group gets highest priority
	r.RegisterGroup(hGroup, false, 1000, C4GSCnt_Component);
	// register currently open pack groups
	r.RegisterGroups(PackGroups, C4GSCnt_Language);
	return r;
}
Пример #15
0
bool C4ObjectInfo::Save(C4Group &hGroup, bool fStoreTiny, C4DefList *pDefs)
{
	// Set group file name; rename if necessary
	char szTempGroup[_MAX_PATH+1];
	SCopy(Name, szTempGroup, _MAX_PATH);
	MakeFilenameFromTitle(szTempGroup);
	SAppend(".oci",szTempGroup, _MAX_PATH);
	if (!SEqualNoCase(Filename, szTempGroup))
	{
		if (!Filename[0])
		{
			// first time creation of file - make sure it's not a duplicate
			SCopy(szTempGroup, Filename, _MAX_PATH);
			while (hGroup.FindEntry(Filename))
			{
				// if a crew info of that name exists already, rename!
				RemoveExtension(Filename);
				int32_t iFinNum = GetTrailingNumber(Filename), iLen = SLen(Filename);
				while (iLen && Inside(Filename[iLen-1], '0', '9')) --iLen;
				if (iLen>_MAX_PATH-22) { LogF("Error generating unique filename for %s(%s): Path overflow", Name, hGroup.GetFullName().getData()); break; }
				snprintf(Filename+iLen, 22, "%d", iFinNum+1);
				EnforceExtension(Filename, "oci");
			}
		}
		else
		{
			// Crew was renamed; file rename necessary, if the name is not blocked by another crew info
			if (!hGroup.FindEntry(szTempGroup))
			{
				if (hGroup.Rename(Filename, szTempGroup))
					SCopy(szTempGroup, Filename, _MAX_PATH);
				else
				{
					// could not rename. Not fatal; just use old file
					LogF("Error adjusting crew info for %s into %s: Rename error from %s to %s!", Name, hGroup.GetFullName().getData(), Filename, szTempGroup);
				}
			}
		}
	}
	// Open group
	C4Group hTemp;
	if (!hTemp.OpenAsChild(&hGroup, Filename, false, true))
		return false;
	// custom rank image present?
	if (pDefs && !fStoreTiny)
	{
		C4Def *pDef = pDefs->ID2Def(id);
		if (pDef)
		{
			if (pDef->pRankSymbols)
			{
				C4FacetSurface fctRankSymbol;
				if (C4RankSystem::DrawRankSymbol(&fctRankSymbol, Rank, pDef->pRankSymbols, pDef->iNumRankSymbols, true))
				{
					fctRankSymbol.GetFace().SavePNG(hTemp, C4CFN_ClonkRank);
				}
			}
			else
			{
				// definition does not have custom rank symbols: Remove any rank image from Clonk
				hTemp.Delete(C4CFN_ClonkRank);
			}
		}
	}

	// Save info to temp group
	if (!C4ObjectInfoCore::Save(hTemp, pDefs))
		{ hTemp.Close(); return false; }
	// Close temp group
	hTemp.Close();
	// Success
	return true;
}
Пример #16
0
bool C4Def::Load(C4Group &hGroup,
	StdMeshSkeletonLoader &loader,
	DWORD dwLoadWhat,
	const char *szLanguage,
	C4SoundSystem *pSoundSystem,
	C4DefGraphicsPtrBackup *gfx_backup
	)
{
	bool AddFileMonitoring = false;
	if (Game.pFileMonitor && !SEqual(hGroup.GetFullName().getData(),Filename) && !hGroup.IsPacked())
		AddFileMonitoring = true;

	// Store filename
	SCopy(hGroup.GetFullName().getData(),Filename);

	// Verbose log filename
	if (Config.Graphics.VerboseObjectLoading>=3)
		Log(hGroup.GetFullName().getData());

	if (AddFileMonitoring) Game.pFileMonitor->AddDirectory(Filename);

	// Pre-read all images and shader stuff because they ar eaccessed in unpredictable order during loading
	hGroup.PreCacheEntries(C4CFN_ShaderFiles);
	hGroup.PreCacheEntries(C4CFN_ImageFiles);

	LoadMeshMaterials(hGroup, gfx_backup);
	bool fSuccess = LoadParticleDef(hGroup);

	// Read DefCore
	if (fSuccess) fSuccess = LoadDefCore(hGroup);

	// Skip def: don't even read sounds!
	if (fSuccess && Game.C4S.Definitions.SkipDefs.GetIDCount(id, 1)) return false;

	// Read sounds, even if not a valid def (for pure ocd sound folders)
	if (dwLoadWhat & C4D_Load_Sounds) LoadSounds(hGroup, pSoundSystem);

	// cancel if not a valid definition
	if (!fSuccess) return false;

	// Read and parse SolidMask bitmap
	if (!LoadSolidMask(hGroup)) return false;

	// Read surface bitmap, meshes, skeletons
	if ((dwLoadWhat & C4D_Load_Bitmap) && !LoadGraphics(hGroup, loader)) return false;

	// Read string table
	C4Language::LoadComponentHost(&StringTable, hGroup, C4CFN_ScriptStringTbl, szLanguage);

	// Register ID with script engine
	::ScriptEngine.RegisterGlobalConstant(id.ToString(), C4VPropList(this));
	ParentKeyName = ::Strings.RegString(id.ToString());

	// Read script
	if (dwLoadWhat & C4D_Load_Script) LoadScript(hGroup, szLanguage);

	// Read clonknames
	if (dwLoadWhat & C4D_Load_ClonkNames) LoadClonkNames(hGroup, pClonkNames, szLanguage);

	// Read clonkranks
	if (dwLoadWhat & C4D_Load_RankNames) LoadRankNames(hGroup, szLanguage);

	// Read rankfaces
	if (dwLoadWhat & C4D_Load_RankFaces) LoadRankFaces(hGroup);

	// Temporary flag
	if (dwLoadWhat & C4D_Load_Temporary) Temporary=true;

	return true;
}
Пример #17
0
// Construct full path
void C4ComponentHost::CopyFilePathFromGroup(const C4Group &hGroup) {
  SCopy(pConfig->AtExeRelativePath(hGroup.GetFullName().getData()), FilePath,
        _MAX_PATH - 1);
  SAppendChar(DirectorySeparator, FilePath);
  SAppend(Filename, FilePath, _MAX_PATH);
}
Пример #18
0
BOOL C4Playback::Open(C4Group &rGrp) {
  // clean up
  Clear();
  fLoadSequential = false;
  iLastSequentialFrame = 0;
  bool fStrip = false;
  // get text record file
  StdStrBuf TextBuf;
  if (rGrp.LoadEntryString(C4CFN_CtrlRecText, TextBuf)) {
    if (!ReadText(TextBuf)) return FALSE;
  } else {
    // open group? Then do some sequential reading for large files
    // Can't do this when a dump is forced, because the dump needs all data
    // Also can't do this when stripping is desired
    if (!rGrp.IsPacked())
      if (!Game.RecordDumpFile.getLength())
        if (!fStrip) fLoadSequential = true;
    // get record file
    if (fLoadSequential) {
      if (!rGrp.FindEntry(C4CFN_CtrlRec)) return FALSE;
      if (!playbackFile.Open(
              FormatString("%s%c%s", rGrp.GetFullName().getData(),
                           (char)DirectorySeparator,
                           (const char *)C4CFN_CtrlRec).getData()))
        return FALSE;
      // forcing first chunk to be read; will call ReadBinary
      currChunk = chunks.end();
      if (!NextSequentialChunk()) {
        // empty replay??!
        LogFatal("Record: Binary read error.");
        return FALSE;
      }
    } else {
      // non-sequential reading: Just read as a whole
      StdBuf BinaryBuf;
      if (rGrp.LoadEntry(C4CFN_CtrlRec, BinaryBuf)) {
        if (!ReadBinary(BinaryBuf)) return FALSE;
      } else {
        // file too large? Try sequential loading and parsing
        /*				size_t iSize;
                                        if (rGrp.AccessEntry(C4CFN_CtrlRec,
           &iSize))
                                                {
                                                CStdFile fOut;
           fOut.Create(Game.RecordDumpFile.getData());
                                                fLoadSequential = true;
                                                const size_t iChunkSize =
           1024*1024*16; // 16M
                                                while (iSize)
                                                        {
                                                        size_t iLoadSize =
           Min<size_t>(iChunkSize, iSize);
                                                        BinaryBuf.SetSize(iLoadSize);
                                                        if
           (!rGrp.Read(BinaryBuf.getMData(), iLoadSize))
                                                                {
                                                                LogFatal("Record:
           Binary load error!");
                                                                return FALSE;
                                                                }
                                                        iSize -= iLoadSize;
                                                        if
           (!ReadBinary(BinaryBuf)) return FALSE;
                                                        LogF("%d binary
           remaining", iSize);
                                                        currChunk =
           chunks.begin();
                                                        if (fStrip) Strip();
                                                        StdStrBuf
           s(ReWriteText());
                                                        fOut.WriteString(s.getData());
                                                        LogF("Wrote %d text
           bytes (%d binary remaining)", s.getLength(), iSize);
                                                        chunks.clear();
                                                        }
                                                fOut.Close();
                                                fLoadSequential = false;
                                                }
                                        else*/
        {
          // no control data?
          LogFatal("Record: No control data found!");
          return FALSE;
        }
      }
    }
  }
  // rewrite record
  if (fStrip) Strip();
  if (Game.RecordDumpFile.getLength()) {
    if (SEqualNoCase(GetExtension(Game.RecordDumpFile.getData()), "txt"))
      ReWriteText().SaveToFile(Game.RecordDumpFile.getData());
    else
      ReWriteBinary().SaveToFile(Game.RecordDumpFile.getData());
  }
  // reset status
  currChunk = chunks.begin();
  Finished = false;
// external debugrec file
#if defined(DEBUGREC_EXTFILE) && defined(DEBUGREC)
#ifdef DEBUGREC_EXTFILE_WRITE
  if (!DbgRecFile.Create(DEBUGREC_EXTFILE)) {
    LogFatal("DbgRec: Creation of external file \"" DEBUGREC_EXTFILE
             "\" failed!");
    return FALSE;
  } else
    Log("DbgRec: Writing to \"" DEBUGREC_EXTFILE "\"...");
#else
  if (!DbgRecFile.Open(DEBUGREC_EXTFILE)) {
    LogFatal("DbgRec: Opening of external file \"" DEBUGREC_EXTFILE
             "\" failed!");
    return FALSE;
  } else
    Log("DbgRec: Checking against \"" DEBUGREC_EXTFILE "\"...");
#endif
#endif
  // ok
  return TRUE;
}
Пример #19
0
int C4GameObjects::Load(C4Group &hGroup, bool fKeepInactive) {
  Clear(!fKeepInactive);

  // Load data component
  StdStrBuf Source;
  if (!hGroup.LoadEntryString(C4CFN_ScenarioObjects, Source)) return 0;

  // Compile
  StdStrBuf Name = hGroup.GetFullName() + DirSep C4CFN_ScenarioObjects;
  if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkParAdapt(*this, false),
                                                  Source, Name.getData()))
    return 0;

  // Process objects
  C4ObjectLink *cLnk = nullptr;
  C4Object *pObj = nullptr;
  bool fObjectNumberCollision = false;
  int32_t iMaxObjectNumber = 0;
  for (cLnk = Last; cLnk; cLnk = cLnk->Prev) {
    C4Object *pObj = cLnk->Obj;
    // check object number collision with inactive list
    if (fKeepInactive) {
      for (C4ObjectLink *clnk = InactiveObjects.First; clnk; clnk = clnk->Next)
        if (clnk->Obj->Number == pObj->Number) fObjectNumberCollision = true;
    }
    // keep track of numbers
    iMaxObjectNumber = Max<long>(iMaxObjectNumber, pObj->Number);
    // add to list of backobjects
    if (pObj->Category & C4D_Background)
      Game.BackObjects.Add(pObj, C4ObjectList::stMain, this);
    // add to list of foreobjects
    if (pObj->Category & C4D_Foreground)
      Game.ForeObjects.Add(pObj, C4ObjectList::stMain, this);
    // Unterminate end
  }

  // Denumerate pointers
  // if object numbers collideded, numbers will be adjusted afterwards
  // so fake inactive object list empty meanwhile
  C4ObjectLink *pInFirst = nullptr;
  if (fObjectNumberCollision) {
    pInFirst = InactiveObjects.First;
    InactiveObjects.First = NULL;
  }
  // denumerate pointers
  Denumerate();
  // update object enumeration index now, because calls like UpdateTransferZone
  // might create objects
  Game.ObjectEnumerationIndex =
      Max(Game.ObjectEnumerationIndex, iMaxObjectNumber);
  // end faking and adjust object numbers
  if (fObjectNumberCollision) {
    InactiveObjects.First = pInFirst;
    // simply renumber all inactive objects
    for (cLnk = InactiveObjects.First; cLnk; cLnk = cLnk->Next)
      if ((pObj = cLnk->Obj)->Status)
        pObj->Number = ++Game.ObjectEnumerationIndex;
  }

  // special checks:
  // -contained/contents-consistency
  // -StaticBack-objects zero speed
  for (cLnk = First; cLnk; cLnk = cLnk->Next)
    if ((pObj = cLnk->Obj)->Status) {
      // staticback must not have speed
      if (pObj->Category & C4D_StaticBack) {
        pObj->xdir = pObj->ydir = 0;
      }
      // contained must be in contents list
      if (pObj->Contained)
        if (!pObj->Contained->Contents.GetLink(pObj)) {
          DebugLogF(
              "Error in Objects.txt: Container of #%d is #%d, but not found in "
              "contents list!",
              pObj->Number, pObj->Contained->Number);
          pObj->Contained->Contents.Add(pObj, C4ObjectList::stContents);
        }
      // all contents must have contained set; otherwise, remove them!
      C4Object *pObj2;
      for (C4ObjectLink *cLnkCont = pObj->Contents.First; cLnkCont;
           cLnkCont = cLnkCont->Next) {
        // check double links
        if (pObj->Contents.GetLink(cLnkCont->Obj) != cLnkCont) {
          DebugLogF("Error in Objects.txt: Double containment of #%d by #%d!",
                    cLnkCont->Obj->Number, pObj->Number);
          // this remove-call will only remove the previous (dobuled) link, so
          // cLnkCont should be save
          pObj->Contents.Remove(cLnkCont->Obj);
          // contents checked already
          continue;
        }
        // check contents/contained-relation
        if ((pObj2 = cLnkCont->Obj)->Status)
          if (pObj2->Contained != pObj) {
            DebugLogF(
                "Error in Objects.txt: Object #%d not in container #%d as "
                "referenced!",
                pObj2->Number, pObj->Number);
            pObj2->Contained = pObj;
          }
      }
    }
  // sort out inactive objects
  C4ObjectLink *cLnkNext;
  for (cLnk = First; cLnk; cLnk = cLnkNext) {
    cLnkNext = cLnk->Next;
    if (cLnk->Obj->Status == C4OS_INACTIVE) {
      if (cLnk->Prev)
        cLnk->Prev->Next = cLnkNext;
      else
        First = cLnkNext;
      if (cLnkNext)
        cLnkNext->Prev = cLnk->Prev;
      else
        Last = cLnk->Prev;
      if (cLnk->Prev = InactiveObjects.Last)
        InactiveObjects.Last->Next = cLnk;
      else
        InactiveObjects.First = cLnk;
      InactiveObjects.Last = cLnk;
      cLnk->Next = NULL;
      Mass -= pObj->Mass;
    }
  }

  {
    C4DebugRecOff DBGRECOFF;  // - script callbacks that would kill
                              // DebugRec-sync for runtime start
    // update graphics
    UpdateGraphics(false);
    // Update faces
    UpdateFaces(false);
    // Update ocf
    SetOCF();
  }

  // make sure list is sorted by category - after sorting out inactives, because
  // inactives aren't sorted into the main list
  FixObjectOrder();

  // Sectors.Dump();

  // misc updates
  for (cLnk = First; cLnk; cLnk = cLnk->Next)
    if ((pObj = cLnk->Obj)->Status) {
      // add to plrview
      pObj->PlrFoWActualize();
      // update flipdir (for old objects.txt with no flipdir defined)
      // assigns Action.DrawDir as well
      pObj->UpdateFlipDir();
    }
  // Done
  return ObjectCount();
}