Code Search for Developers
 
 
  

ModFiles.cpp from Scorched 3D at Krugle


Show ModFiles.cpp syntax highlighted

////////////////////////////////////////////////////////////////////////////////
//    Scorched3D (c) 2000-2003
//
//    This file is part of Scorched3D.
//
//    Scorched3D is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    Scorched3D is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with Scorched3D; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

#include <engine/ModFiles.h>
#include <common/Defines.h>
#include <common/Logger.h>
#include <common/FileList.h>
#include <stdio.h>

ModFiles::ModFiles()
{
}

ModFiles::~ModFiles()
{
	std::map<std::string, ModFileEntry *>::iterator itor;
	for (itor = files_.begin();
		itor != files_.end();
		itor++)
	{
		delete (*itor).second;
	}
	files_.clear();
}

bool ModFiles::fileEnding(const char *file, const char *ext)
{
	int fileLen = strlen(file);
	int extLen = strlen(ext);
	if (fileLen < extLen) return false;

	for (int i=0; i<extLen; i++)
	{
		if (file[fileLen - i - 1] != ext[extLen - i - 1])
		{
			return false;
		}
	}
	return true;
}

bool ModFiles::excludeFile(const char *file)
{
	if (strstr(file, "Thumbs.db")) return true;
	if (strstr(file, "CVS")) return true;
	if (strstr(file, "..")) return true;

	if (!fileEnding(file, ".xml") &&
		!fileEnding(file, ".bmp") &&
		!fileEnding(file, ".txt") &&
		!fileEnding(file, ".png") &&
		!fileEnding(file, ".jpg") &&
		!fileEnding(file, ".ico") &&
		!fileEnding(file, ".ase") &&
		!fileEnding(file, ".wav") &&
		!fileEnding(file, ".ogg"))
	{
		Logger::log(formatString("Excluding mod file \"%s\"", file));
		return true;
	}

	return false;
}

bool ModFiles::loadModFiles(const char *mod, bool createDir, ProgressCounter *counter)
{
	{
		// Get and check the user mod directory exists
		std::string modDir = getModFile(mod);
		if (s3d_dirExists(modDir.c_str()))
		{
			if (counter) counter->setNewOp("Loading user mods");
			if (!loadModDir(modDir.c_str(), mod, counter)) return false;
		}
		else
		{
			if (createDir) s3d_dirMake(modDir.c_str());
		}
	}

	{
		// Get and check global mod directory
		std::string modDir = getGlobalModFile(mod);
		if (s3d_dirExists(modDir.c_str()))
		{
			if (counter) counter->setNewOp("Loading global mods");
			if (!loadModDir(modDir.c_str(), mod, counter)) return false;
		}
	}

	// For the default "none" mod load some files that can
	// be downloaded
	if (0 == strcmp("none", mod))
	{
		loadLocalModFile("data/accessories.xml", mod);
		loadLocalModFile("data/modinfo.xml", mod);
		loadLocalModFile("data/landscapes.xml", mod);

		const char *landscapesBase = "data/landscapes";
		std::string dir = getDataFile(landscapesBase);
		FileList fList(dir.c_str(), "*.xml", true);
		std::list<std::string> &files = fList.getFiles();
		std::list<std::string>::iterator itor;
		for (itor = files.begin();
			itor != files.end();
			itor++)
		{
			char *file = (char *) (*itor).c_str();
			file += dir.size() - strlen(landscapesBase);
			loadLocalModFile(file, mod);
		}
	}
	
	{
		unsigned int totalCompSize = 0, totalSize = 0;
		std::map<std::string, ModFileEntry *>::iterator itor;
		for (itor = files_.begin();
			itor != files_.end();
			itor++)
		{
			ModFileEntry *entry = (*itor).second;
			totalCompSize += entry->getCompressedSize();
			totalSize += entry->getUncompressedSize();
		}

		Logger::log(formatString("Loaded mod \"%s\", %u files, space required %u (%u) bytes", 
			mod, files_.size(), totalCompSize, totalSize));

		if (!createDir && files_.empty())
		{
			dialogMessage("Mod", formatString(
				"Failed to find \"%s\" mod files in directories \"%s\" \"%s\"",
				mod,
				getModFile(mod),
				getGlobalModFile(mod)));
			return false;
		}
	}

	return true;
}

bool ModFiles::loadLocalModFile(const char *local, const char *mod)
{
	const char *dataFile = getDataFile(local);
	std::string modDirStr(dataFile);
	char *modDir = (char *) modDirStr.c_str();
	modDir[strlen(dataFile) - strlen(local)] = '\0';

	return loadModFile(dataFile, modDir, mod);
}

bool ModFiles::loadModDir(const char *modDir, const char *mod, ProgressCounter *counter)
{
	// Load all files contained in this directory
	FileList allfiles(modDir, "*", true, true);
	FileList::ListType &files = allfiles.getFiles();
	FileList::ListType::iterator itor;

	int i = 0;
	for (itor = files.begin();
		itor != files.end();
		itor++, i++)
	{
		if (counter) counter->setNewPercentage(float(i) 
			/ float(files.size()) * 100.0f);

		// Load the file
		std::string &fileName = (*itor);
		if (!loadModFile(fileName.c_str(), modDir, mod))
		{
			return false;
		}
	}

	return true;
}

bool ModFiles::loadModFile(const char *fullFileName,
	const char *modDir, const char *mod)
{
	std::string shortFileNameStr(fullFileName);
	const char *shortFileName = shortFileNameStr.c_str();

	// Check to see if we ignore this file
	if (excludeFile(fullFileName)) return true;

	// Turn it into a unix style path and remove the 
	// name of the directory that contains it
	int modDirLen = strlen(modDir);
	shortFileName += modDirLen;
	s3d_fileDos2Unix((char *) shortFileName);
	while (shortFileName[0] == '/') shortFileName++;

	// Check that all files are lower case
	std::string oldFileName = shortFileName;
	_strlwr((char *) shortFileName);
	if (strcmp(oldFileName.c_str(), shortFileName) != 0)
	{
		dialogMessage("Mod", formatString(
			"ERROR: All mod files must have lower case filenames.\n"
			"File \"%s,%s\" has upper case charaters in it",
			oldFileName.c_str(),
			shortFileName));
		return false;
	}

	// Check we don't have this file already
	if (files_.find(shortFileName) != files_.end()) return true;

	// Create the new mod file and load the file
	ModFileEntry *file = new ModFileEntry();
	if (!file->loadModFile(fullFileName))
	{
		dialogMessage("Mod", formatString(
			"Error: Failed to load file \"%s\" mod directory \"%s\" in the \"%s\" mod",
			fullFileName,
			modDir,
			mod));
		return false;
	}

	// Store for future
	file->setFileName(shortFileName);
	files_[shortFileName] = file;
	return true;
}

bool ModFiles::writeModFiles(const char *mod)
{
	std::string modDir = getModFile(mod);
	if (!s3d_dirExists(modDir.c_str()))
	{
		s3d_dirMake(modDir.c_str());
	}

	std::map<std::string, ModFileEntry *>::iterator itor;
	for (itor = files_.begin();
		itor != files_.end();
		itor++)
	{
		ModFileEntry *entry = (*itor).second;
		if (!entry->writeModFile(entry->getFileName(), mod)) return false;
	}
	return true;
}

void ModFiles::clearData()
{
	 std::map<std::string, ModFileEntry *>::iterator itor;
	 for (itor = files_.begin();
	 	itor != files_.end();
		itor++)
	{
		 ModFileEntry *entry = (*itor).second;
		 entry->getCompressedBuffer().clear();
	}
}

bool ModFiles::exportModFiles(const char *mod, const char *fileName)
{
	FILE *out = fopen(fileName, "wb");
	if (!out) return false;

	// Mod Name
	NetBuffer tmpBuffer;
	tmpBuffer.reset();
	tmpBuffer.addToBuffer(ScorchedProtocolVersion);
	tmpBuffer.addToBuffer(mod);
	fwrite(tmpBuffer.getBuffer(),
		sizeof(unsigned char),
		tmpBuffer.getBufferUsed(), 
		out);	

	// Mod Files
	std::map<std::string, ModFileEntry *>::iterator itor;
	for (itor = files_.begin();
		itor != files_.end();
		itor++)
	{
		ModFileEntry *entry = (*itor).second;
	
		tmpBuffer.reset();
		tmpBuffer.addToBuffer(entry->getFileName());
		tmpBuffer.addToBuffer(entry->getUncompressedSize());
		tmpBuffer.addToBuffer(entry->getCompressedBuffer().getBufferUsed());
		tmpBuffer.addToBuffer(entry->getCompressedCrc());
		tmpBuffer.addDataToBuffer(entry->getCompressedBuffer().getBuffer(),
			entry->getCompressedBuffer().getBufferUsed());

		fwrite(tmpBuffer.getBuffer(),
			sizeof(unsigned char),
			tmpBuffer.getBufferUsed(), 
			out);
	}

	// End of Mod Files
	tmpBuffer.reset();
	tmpBuffer.addToBuffer("*");
	fwrite(tmpBuffer.getBuffer(),
		sizeof(unsigned char),
		tmpBuffer.getBufferUsed(), 
		out);

	fclose(out);
	return true;
}

bool ModFiles::importModFiles(const char **mod, const char *fileName)
{
	FILE *in = fopen(fileName, "rb");
	if (!in) return false;

	// Read Buffer
	NetBuffer tmpBuffer;
	unsigned char readBuf[512];
	while (unsigned int size = fread(readBuf, sizeof(unsigned char), 512, in))
	{
		tmpBuffer.addDataToBuffer(readBuf, size);
	}
	fclose(in);
	return importModFiles(mod, tmpBuffer);
}

bool ModFiles::importModFiles(const char **mod, NetBuffer &tmpBuffer)
{
	// Mod Name
	static std::string modName;
	std::string version;
	NetBufferReader tmpReader(tmpBuffer);
	if (!tmpReader.getFromBuffer(version)) return false;
	if (!tmpReader.getFromBuffer(modName)) return false;
	*mod = modName.c_str();

	if (0 != strcmp(version.c_str(), ScorchedProtocolVersion))
	{
		dialogMessage("Scorched3D", formatString(
			"Failed to import mod, scorched version differs.\n"
			"Please obtain a newer version of this mod.\n"
			"Import version = %s\n"
			"Current version = %s\n",
			version.c_str(),
			ScorchedProtocolVersion));
		return false;
	}

	for (;;)
	{
		// File Name
		std::string name;
		if (!tmpReader.getFromBuffer(name)) return false;
		if (0 == strcmp(name.c_str(), "*")) break;

		// File Header
		unsigned int unCompressedSize;
		unsigned int compressedSize;
		unsigned int compressedCrc;
		tmpReader.getFromBuffer(unCompressedSize);
		tmpReader.getFromBuffer(compressedSize);
		tmpReader.getFromBuffer(compressedCrc);

		// File
		ModFileEntry *entry = new ModFileEntry;
		entry->setFileName(name.c_str());
		entry->setCompressedCrc(compressedCrc);
		entry->setUncompressedSize(unCompressedSize);
		entry->getCompressedBuffer().allocate(compressedSize);
		entry->getCompressedBuffer().setBufferUsed(compressedSize);
		tmpReader.getDataFromBuffer(
			entry->getCompressedBuffer().getBuffer(), 
			compressedSize);
		files_[name] = entry;
	}

	return true;
}




See more files for this project here

Scorched 3D

Scorched3D is a 3D remake of the popular 2D artillery game Scorched Earth.\r\nScorched3D can be played against the computer, other players and remotely across the internet or LAN.

Project homepage: http://sourceforge.net/projects/scorched3d
Programming language(s): C,C++,XML
License: gpl2

  Action.cpp
  Action.h
  ActionController.cpp
  ActionController.h
  ActionReferenced.cpp
  ActionReferenced.h
  EventContainer.cpp
  EventContainer.h
  GameState.cpp
  GameState.h
  GameStateI.cpp
  GameStateI.h
  GameStateStimulusI.cpp
  GameStateStimulusI.h
  MainLoop.cpp
  MainLoop.h
  MainLoopI.cpp
  MainLoopI.h
  MetaClass.cpp
  MetaClass.h
  ModDirs.cpp
  ModDirs.h
  ModFileEntry.cpp
  ModFileEntry.h
  ModFiles.cpp
  ModFiles.h
  ModInfo.cpp
  ModInfo.h
  PhysicsParticle.cpp
  PhysicsParticle.h
  PhysicsParticleObject.cpp
  PhysicsParticleObject.h
  PlayShots.cpp
  PlayShots.h
  ScorchedCollisionIds.cpp
  ScorchedCollisionIds.h
  ScorchedContext.cpp
  ScorchedContext.h
  ShotState.cpp
  ShotState.h
  SyncCheck.cpp
  SyncCheck.h
  ViewPoints.cpp
  ViewPoints.h